chuijs 3.6.2 → 3.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1203 -162
  3. package/framework/appLayout/default/chui_app_layout.js +747 -747
  4. package/framework/appLayout/default/global_style.css +592 -568
  5. package/framework/appLayout/default/main_theme_style.css +118 -101
  6. package/framework/components/chui_accordion/accordion.js +63 -63
  7. package/framework/components/chui_accordion/styles.css +79 -75
  8. package/framework/components/chui_badge/badge.js +55 -55
  9. package/framework/components/chui_badge/styles.css +29 -29
  10. package/framework/components/chui_button/button.js +48 -48
  11. package/framework/components/chui_button/styles.css +75 -70
  12. package/framework/components/chui_calendar/calendar.js +97 -97
  13. package/framework/components/chui_card/card.js +87 -0
  14. package/framework/components/chui_card/styles.css +72 -0
  15. package/framework/components/chui_code/code.js +18 -18
  16. package/framework/components/chui_code/styles.css +9 -9
  17. package/framework/components/chui_console/console.js +27 -27
  18. package/framework/components/chui_console/styles.css +31 -31
  19. package/framework/components/chui_content_block/content_block.js +51 -51
  20. package/framework/components/chui_content_block/styles.css +2 -2
  21. package/framework/components/chui_context_menu/context_menu.js +230 -0
  22. package/framework/components/chui_context_menu/styles.css +136 -0
  23. package/framework/components/chui_custom_element/custom_element.js +24 -24
  24. package/framework/components/chui_details/details.js +85 -85
  25. package/framework/components/chui_details/styles.css +70 -66
  26. package/framework/components/chui_fieldset/fieldset.js +40 -40
  27. package/framework/components/chui_fieldset/styles.css +24 -24
  28. package/framework/components/chui_form/form.js +40 -40
  29. package/framework/components/chui_form/styles.css +21 -21
  30. package/framework/components/chui_graphs/graphs.js +234 -190
  31. package/framework/components/chui_graphs/styles.css +37 -32
  32. package/framework/components/chui_hero/hero.js +98 -0
  33. package/framework/components/chui_hero/styles.css +91 -0
  34. package/framework/components/chui_html_block/html_block.js +16 -16
  35. package/framework/components/chui_html_block/styles.css +5 -5
  36. package/framework/components/chui_hx/hx.js +15 -15
  37. package/framework/components/chui_hx/styles.css +38 -38
  38. package/framework/components/chui_icons/icons.js +2144 -2144
  39. package/framework/components/chui_icons/styles.css +13 -13
  40. package/framework/components/chui_inputs/chui_check_box/check_box.js +32 -32
  41. package/framework/components/chui_inputs/chui_check_box/styles.css +91 -86
  42. package/framework/components/chui_inputs/chui_combo_box/combo_box.js +166 -150
  43. package/framework/components/chui_inputs/chui_combo_box/styles.css +113 -107
  44. package/framework/components/chui_inputs/chui_date/date.js +177 -174
  45. package/framework/components/chui_inputs/chui_date/styles.css +163 -128
  46. package/framework/components/chui_inputs/chui_email/email.js +61 -61
  47. package/framework/components/chui_inputs/chui_email/styles.css +69 -71
  48. package/framework/components/chui_inputs/chui_file/file.js +76 -76
  49. package/framework/components/chui_inputs/chui_file/styles.css +99 -99
  50. package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +295 -295
  51. package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +212 -235
  52. package/framework/components/chui_inputs/chui_number/number.js +108 -108
  53. package/framework/components/chui_inputs/chui_number/styles.css +84 -84
  54. package/framework/components/chui_inputs/chui_password/password.js +99 -99
  55. package/framework/components/chui_inputs/chui_password/styles.css +97 -97
  56. package/framework/components/chui_inputs/chui_radio_button/radio_button.js +45 -45
  57. package/framework/components/chui_inputs/chui_radio_button/styles.css +76 -73
  58. package/framework/components/chui_inputs/chui_select_box/select_box.js +187 -170
  59. package/framework/components/chui_inputs/chui_select_box/styles.css +123 -117
  60. package/framework/components/chui_inputs/chui_text/styles.css +83 -84
  61. package/framework/components/chui_inputs/chui_text/text.js +91 -91
  62. package/framework/components/chui_inputs/chui_text_area/styles.css +57 -57
  63. package/framework/components/chui_inputs/chui_text_area/text_area.js +61 -61
  64. package/framework/components/chui_inputs/chui_toggle/styles.css +66 -61
  65. package/framework/components/chui_inputs/chui_toggle/toggle.js +36 -36
  66. package/framework/components/chui_label/label.js +54 -54
  67. package/framework/components/chui_label/styles.css +11 -11
  68. package/framework/components/chui_media/audio.js +908 -908
  69. package/framework/components/chui_media/audio_styles.css +458 -458
  70. package/framework/components/chui_media/image.js +105 -105
  71. package/framework/components/chui_media/image_styles.css +61 -61
  72. package/framework/components/chui_media/video.js +248 -248
  73. package/framework/components/chui_media/video_styles.css +160 -160
  74. package/framework/components/chui_menu_bar/menu_bar.js +66 -74
  75. package/framework/components/chui_menu_bar/styles.css +114 -76
  76. package/framework/components/chui_modal/modal.js +142 -135
  77. package/framework/components/chui_modal/styles.css +36 -36
  78. package/framework/components/chui_notification/notification.js +72 -72
  79. package/framework/components/chui_notification/notification_download.js +78 -78
  80. package/framework/components/chui_notification/notification_download_progress.css +119 -123
  81. package/framework/components/chui_notification/notification_download_progress.js +105 -105
  82. package/framework/components/chui_notification/notification_update.js +54 -54
  83. package/framework/components/chui_notification/styles.css +91 -91
  84. package/framework/components/chui_notification/styles_download.css +85 -85
  85. package/framework/components/chui_notification/styles_update.css +73 -73
  86. package/framework/components/chui_paragraph/paragraph.js +14 -14
  87. package/framework/components/chui_paragraph/styles.css +6 -6
  88. package/framework/components/chui_popups/popups.js +250 -250
  89. package/framework/components/chui_popups/styles.css +129 -115
  90. package/framework/components/chui_progress_bar/progress_bar.js +28 -28
  91. package/framework/components/chui_progress_bar/styles.css +28 -28
  92. package/framework/components/chui_radio_group/radio_group.js +57 -57
  93. package/framework/components/chui_radio_group/styles.css +3 -3
  94. package/framework/components/chui_slideshow/slideshow.js +75 -75
  95. package/framework/components/chui_slideshow/styles.css +94 -85
  96. package/framework/components/chui_spinner/spinner.js +45 -45
  97. package/framework/components/chui_spinner/styles.css +23 -23
  98. package/framework/components/chui_table/styles.css +42 -42
  99. package/framework/components/chui_table/table.js +234 -234
  100. package/framework/components/chui_tabs/chui_tabs.js +77 -77
  101. package/framework/components/chui_tabs/styles.css +54 -48
  102. package/framework/components/chui_text_editor/styles.css +217 -217
  103. package/framework/components/chui_text_editor/text_editor.js +144 -144
  104. package/framework/components/chui_text_editor/text_editor_panel.js +568 -568
  105. package/framework/components/chui_tree_view/styles.css +81 -75
  106. package/framework/components/chui_tree_view/tree_view.js +90 -90
  107. package/framework/components/chui_webview/styles.css +27 -27
  108. package/framework/components/chui_webview/webview.js +103 -103
  109. package/framework/components/telegram_bot/chui_telegram_bot.js +183 -183
  110. package/framework/modules/chui_animations/animations.js +121 -121
  111. package/framework/modules/chui_animations/styles.css +79 -79
  112. package/framework/modules/chui_fonts.js +7129 -6974
  113. package/framework/modules/chui_functions.js +106 -78
  114. package/framework/modules/chui_logger/chui_logger.js +53 -53
  115. package/framework/modules/chui_page/page.js +86 -86
  116. package/framework/modules/chui_page/styles.css +9 -9
  117. package/framework/tray_bar/chui_menu_items.js +48 -48
  118. package/index.js +570 -555
  119. package/package.json +51 -46
@@ -1,909 +1,909 @@
1
- const fs = require("fs");
2
- const dataurl = require("dataurl");
3
- const { Icon, Icons } = require("../chui_icons/icons");
4
- const {Label} = require('../chui_label/label');
5
- const {Select} = require("../chui_inputs/chui_select_box/select_box");
6
- const {Dialog} = require("../chui_modal/modal");
7
- const Store = require('electron-store');
8
- const {shell} = require("electron");
9
- const {Toggle} = require("../chui_inputs/chui_toggle/toggle");
10
- const store = new Store();
11
-
12
- let play_list = []
13
-
14
- class Audio {
15
- #current_audio = 0
16
- #chui_ap_main = document.createElement(`chui_ap_main`);
17
- #chui_ap_block = document.createElement(`chui_ap_block`);
18
- #chui_at = document.createElement(`audio`);
19
- #chui_source_tag = document.createElement(`source`);
20
- // Блок информация
21
- #chui_ap_info = document.createElement(`chui_ap_info`);
22
- #chui_ap_time1 = undefined;
23
- #chui_ap_time2 = undefined;
24
- #chui_ap_seek_block = document.createElement("chui_ap_seek_block")
25
- #chui_ap_seek = document.createElement(`input`);
26
- #chui_ap_seek_buf = document.createElement(`chui_ap_seek_buf`);
27
- #chui_ap_track_title = document.createElement(`chui_ap_track_title`);
28
- // Блок управления
29
- #chui_ap_controls = document.createElement(`chui_ap_controls`);
30
- #chui_ap_play_pause = document.createElement(`chui_ap_play_pause`);
31
- #chui_ap_next = document.createElement(`chui_ap_next`);
32
- #chui_ap_prev = document.createElement(`chui_ap_prev`);
33
- // Блок управления громкостью
34
- #chui_ap_volume_block = document.createElement("chui_ap_volume_block");
35
- #chui_ap_volume_icon = document.createElement(`chui_ap_volume_icon`);
36
- #chui_ap_volume = document.createElement(`input`);
37
- //
38
- #chui_ap_fx_icon = document.createElement(`chui_ap_fx_icon`);
39
- // Размеры иконок
40
- #icons_sizes = {
41
- play_pause: "30px",
42
- next_prev: "24px",
43
- volume: "24px"
44
- }
45
- #chui_playlist = new Playlist()
46
- #chui_audio_fx = new AudioFX(this.#chui_at)
47
- constructor(options = { autoplay: Boolean(), pin: String(), playlist: Boolean(), width: String(), height: String() }) {
48
- require('../../modules/chui_functions').setStyles(__dirname + "/audio_styles.css", 'chUiJS_Audio');
49
- this.#chui_at.setAttribute("name", "media")
50
- this.#chui_at.controls = false;
51
- this.#chui_at.preload = "metadata"
52
- this.#chui_at.crossOrigin = "anonymous"
53
- this.#chui_at.style.borderRadius = "var(--border_radius)"
54
- // Настройки
55
- if (options.autoplay) {
56
- this.#chui_at.autoplay = options.autoplay;
57
- setTimeout(async () => await this.#start(play_list[this.#current_audio]), 1)
58
- }
59
- // ИНФОРМАЦИЯ
60
- this.#chui_ap_time1 = new Label({text: `0:00`})
61
- this.#chui_ap_time2 = new Label({text: `0:00`})
62
- this.#chui_ap_seek.type = "range"
63
- this.#chui_ap_seek.id = "chui_ap_seek"
64
- this.#chui_ap_seek.max = "0"
65
- this.#chui_ap_seek.value = "0"
66
- this.#chui_ap_seek.step = "any"
67
- // КНОПКИ
68
- this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PLAY_ARROW, this.#icons_sizes.play_pause).getHTML()
69
- this.#chui_ap_next.innerHTML = new Icon(Icons.AUDIO_VIDEO.SKIP_NEXT, this.#icons_sizes.next_prev).getHTML()
70
- this.#chui_ap_prev.innerHTML = new Icon(Icons.AUDIO_VIDEO.SKIP_PREVIOUS, this.#icons_sizes.next_prev).getHTML()
71
- // Заполнение элемента
72
- // УПРАВЛЕНИЕ ГРОМКОСТЬЮ
73
- this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_UP, this.#icons_sizes.volume).getHTML()
74
- this.#chui_ap_volume.type = "range"
75
- this.#chui_ap_volume.id = "chui_ap_volume"
76
- this.#chui_ap_volume.max = "100"
77
- this.#chui_ap_volume.value = "100"
78
- this.#chui_ap_volume.step = "1"
79
- this.#chui_at.volume = this.#chui_ap_volume.value / 100;
80
- this.#chui_ap_volume_block.appendChild(this.#chui_ap_volume_icon)
81
- this.#chui_ap_volume_block.appendChild(this.#chui_ap_volume)
82
- this.#chui_ap_fx_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.EQUALIZER, this.#icons_sizes.volume).getHTML()
83
- this.#chui_ap_volume_block.appendChild(this.#chui_ap_fx_icon)
84
- // ИНФОРМАЦИЯ
85
- this.#chui_ap_info.appendChild(this.#chui_ap_time1.set())
86
- this.#chui_ap_seek_block.appendChild(this.#chui_ap_seek)
87
- this.#chui_ap_seek_block.appendChild(this.#chui_ap_seek_buf)
88
- this.#chui_ap_info.appendChild(this.#chui_ap_seek_block)
89
- this.#chui_ap_info.appendChild(this.#chui_ap_time2.set())
90
- // КНОПКИ
91
- this.#chui_ap_controls.appendChild(this.#chui_ap_prev)
92
- this.#chui_ap_controls.appendChild(this.#chui_ap_play_pause)
93
- this.#chui_ap_controls.appendChild(this.#chui_ap_next)
94
- this.#chui_ap_controls.appendChild(this.#chui_ap_track_title)
95
- //
96
- this.#chui_ap_controls.appendChild(this.#chui_ap_volume_block)
97
- //
98
- this.#chui_ap_main.appendChild(this.#chui_at)
99
- this.#chui_at.appendChild(this.#chui_source_tag)
100
- this.#chui_ap_block.appendChild(this.#chui_ap_controls)
101
- this.#chui_ap_block.appendChild(this.#chui_ap_info)
102
- //
103
- this.#chui_ap_main.appendChild(this.#chui_ap_block)
104
- // СОБЫТИЯ
105
- this.#chui_ap_play_pause.addEventListener("click", async () => this.#playAudioPause())
106
- navigator.mediaSession.setActionHandler('play', async () => this.#playAudioPause());
107
- navigator.mediaSession.setActionHandler('pause', async () => this.#playAudioPause());
108
- this.#chui_ap_next.addEventListener("click", async () => this.#playAudioNext())
109
- this.#chui_ap_prev.addEventListener("click", async () => this.#playAudioPrev())
110
- navigator.mediaSession.setActionHandler('nexttrack', async () => this.#playAudioNext());
111
- navigator.mediaSession.setActionHandler('previoustrack', async () => this.#playAudioPrev());
112
- this.#chui_at.addEventListener("timeupdate", async () => {
113
- this.#displayBufferedAmount()
114
- this.#renderProgress(this.#chui_at.currentTime)
115
- if (this.#chui_at.currentTime === this.#chui_at.duration) await this.#playAudioNext()
116
- });
117
- this.#chui_ap_seek.addEventListener('input', () => {
118
- this.#chui_at.currentTime = Number(Number(this.#chui_ap_seek.value).toFixed(6));
119
- });
120
- this.#chui_ap_volume.addEventListener('input', () => {
121
- this.#chui_at.volume = this.#chui_ap_volume.value / 100;
122
- this.#renderVolume()
123
- if (Number(this.#chui_ap_volume.value) === 0) {
124
- this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_MUTE, this.#icons_sizes.volume).getHTML()
125
- } else {
126
- this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_UP, this.#icons_sizes.volume).getHTML()
127
- }
128
- });
129
- this.#chui_ap_volume_icon.addEventListener('click', () => {
130
- if (!this.#chui_at.muted) {
131
- this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_OFF, this.#icons_sizes.volume).getHTML()
132
- this.#chui_at.muted = true
133
- this.#chui_ap_volume.disabled = true
134
- } else {
135
- this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_UP, this.#icons_sizes.volume).getHTML()
136
- this.#chui_at.muted = false
137
- this.#chui_ap_volume.disabled = false
138
- }
139
- })
140
- this.#renderVolume()
141
- if (options.pin !== undefined) this.#chui_ap_main.classList.add(options.pin);
142
- if (options.width !== undefined) this.#chui_ap_main.style.width = options.width;
143
- if (options.height !== undefined) this.#chui_ap_main.style.height = options.height;
144
- if (options.playlist !== undefined) this.#chui_ap_main.appendChild(this.#chui_playlist.getMain())
145
- let dialog = new Dialog({ closeOutSideClick: true })
146
- dialog.addToBody(this.#chui_audio_fx)
147
- this.#chui_ap_main.appendChild(dialog.set())
148
- this.#chui_ap_fx_icon.addEventListener("click", () => dialog.open())
149
- }
150
- play() {
151
- this.#chui_ap_play_pause.click()
152
- }
153
- next() {
154
- this.#chui_ap_next.click()
155
- }
156
- prev() {
157
- this.#chui_ap_prev.click()
158
- }
159
- openFolder(path) {
160
- this.#chui_playlist.getOpenFolderButton().addEventListener("click", async () => await shell.openPath(path))
161
- }
162
- set() {
163
- return this.#chui_ap_main;
164
- }
165
- restoreFX() {
166
- this.#chui_audio_fx.restore();
167
- }
168
- async #convertSong(filePath, type) {
169
- return await new Promise((resolve, reject) => {
170
- fs.readFile(filePath, (err, data) => {
171
- if (err) reject(err)
172
- resolve(dataurl.convert({data, mimetype: type}));
173
- });
174
- });
175
- };
176
- async #start(track) {
177
- this.#renderProgress("0")
178
- this.#chui_ap_track_title.innerText = `${track.artist} - ${track.title}`
179
- this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PAUSE, this.#icons_sizes.play_pause).getHTML()
180
- if (track.path.includes("http")) {
181
- this.#chui_source_tag.src = track.path
182
- } else {
183
- this.#chui_source_tag.src = String(await this.#convertSong(track.path, track.mimetype))
184
- }
185
- this.#chui_at.load()
186
- await this.#chui_at.play().then(() => {
187
- this.#setSliderMax()
188
- this.#displayBufferedAmount()
189
- })
190
- Audio.#setMediaData(track)
191
- }
192
- async #playAudioNext() {
193
- this.#current_audio = this.#current_audio + 1
194
- if (this.#current_audio < play_list.length) {
195
- await this.#start(play_list[this.#current_audio])
196
- } else if (this.#current_audio === play_list.length) {
197
- this.#current_audio = 0
198
- await this.#start(play_list[this.#current_audio])
199
- }
200
- this.setActive(this.#current_audio)
201
- }
202
- async #playAudioPrev() {
203
- this.#current_audio = this.#current_audio - 1
204
- if (this.#current_audio < 0) {
205
- this.#current_audio = play_list.length - 1
206
- await this.#start(play_list[this.#current_audio])
207
- } else {
208
- await this.#start(play_list[this.#current_audio])
209
- }
210
- this.setActive(this.#current_audio)
211
- }
212
- async #playAudioPause() {
213
- if (this.#chui_at.currentTime === 0) {
214
- this.setActive(this.#current_audio)
215
- await this.#start(play_list[this.#current_audio])
216
- } else if (this.#chui_at.currentTime > 0 && !this.#chui_at.paused) {
217
- this.#chui_at.pause()
218
- this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PLAY_ARROW, this.#icons_sizes.play_pause).getHTML()
219
- } else if (this.#chui_at.currentTime > 0 && this.#chui_at.paused) {
220
- await this.#chui_at.play()
221
- this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PAUSE, this.#icons_sizes.play_pause).getHTML()
222
- }
223
- }
224
- #displayBufferedAmount = () => {
225
- try {
226
- const end = this.#chui_at.buffered.end(0) / this.#chui_ap_seek.max * 100
227
- if (end > 100) {
228
- this.#chui_ap_seek_buf.style.width = `100%`;
229
- } else {
230
- this.#chui_ap_seek_buf.style.width = `${end}%`;
231
- }
232
- } catch (e) {}
233
- }
234
- #renderVolume = () => {
235
- let test = this.#chui_ap_volume.value / this.#chui_ap_volume.max * 100
236
- this.#chui_ap_main.style.setProperty('--volume-before-width', `${test}%`);
237
- }
238
- #renderProgress = (value) => {
239
- try {
240
- if (value > 0 && this.#chui_at.duration > 0) {
241
- this.#chui_ap_time1.setText(this.#calculateTime(value));
242
- this.#chui_ap_time2.setText(this.#calculateTime(this.#chui_at.duration));
243
- this.#chui_ap_seek.value = value;
244
- const width = this.#chui_ap_seek.value / this.#chui_ap_seek.max * 100
245
- this.#chui_ap_main.style.setProperty('--seek-before-width', `${width}%`);
246
- } else {
247
- this.#chui_ap_seek.value = value;
248
- this.#chui_ap_main.style.setProperty('--seek-before-width', `0%`);
249
- }
250
- } catch (e) {
251
- this.#chui_ap_time1.setText(`0:00`);
252
- this.#chui_ap_time2.setText(`0:00`);
253
- }
254
- }
255
- #calculateTime = (secs) => {
256
- const minutes = Math.floor(secs / 60);
257
- const seconds = Math.floor(secs % 60);
258
- const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
259
- return `${minutes}:${returnedSeconds}`;
260
- }
261
- #setSliderMax = () => {
262
- this.#chui_ap_seek.max = String(this.#chui_at.duration);
263
- }
264
- //
265
- setPlayList(list = [{ title: String(), artist: String(), album: String(), mimetype: String(), artwork: [] }]) {
266
- this.#chui_playlist.getPlaylist().innerHTML = '';
267
- play_list = list;
268
- for (let track of play_list) this.#chui_playlist.getPlaylist().appendChild(this.#setTrack(track, play_list.indexOf(track)));
269
- }
270
- #setTrack(track = {}, index = Number()) {
271
- let chui_track = document.createElement("chui_track");
272
- let chui_track_name = document.createElement("chui_track_name");
273
- //
274
- chui_track.id = `${index}`
275
- chui_track_name.innerText = `${track.artist} - ${track.title}`
276
- //
277
- chui_track.addEventListener("dblclick", async (ev) => {
278
- let target_row = ev.target
279
- if (target_row.tagName === "CHUI_TRACK_NAME" || target_row.tagName === "CHUI_TRACK_DURATION") {
280
- this.setActive(ev.target.parentNode.id)
281
- } else {
282
- this.setActive(ev.target.id)
283
- }
284
- await this.#start(track)
285
- this.#current_audio = index;
286
- })
287
- chui_track.appendChild(chui_track_name)
288
- return chui_track;
289
- }
290
- setActive(index = Number()) {
291
- document.getElementById(this.#chui_playlist.getId()).childNodes.forEach(child => {
292
- child.classList.remove("chui_track_active");
293
- })
294
- let element = document.getElementById(`${index}`)
295
- element.classList.add("chui_track_active")
296
- }
297
- static PIN = {
298
- TOP: "pin_top",
299
- BOTTOM: "pin_bottom"
300
- }
301
- static #setMediaData(media) {
302
- if ("mediaSession" in navigator) {
303
- navigator.mediaSession.metadata = new MediaMetadata({
304
- title: media.title,
305
- artist: media.artist,
306
- album: media.album,
307
- artwork: media.artwork
308
- });
309
- }
310
- }
311
- static MIMETYPES = {
312
- AU_SND: 'audio/basic',
313
- LINEAR_PCM: 'auido/L24',
314
- MID_RMI: 'audio/mid',
315
- MP3: 'audio/mpeg',
316
- MP4: 'audio/mp4',
317
- AIF_AIFC_AIFF: 'audio/x-aiff',
318
- M3U: 'audio/x-mpegurl',
319
- RA_RAM: 'audio/vnd.rn-realaudio',
320
- OGG: 'audio/ogg',
321
- VORBIS: 'audio/vorbis',
322
- WAV: 'audio/vnd.wav'
323
- }
324
- }
325
-
326
- class AudioFX {
327
- #chui_ap_equalizer_main = document.createElement('chui_ap_equalizer_main')
328
- #chui_ap_equalizer_controls = document.createElement('chui_ap_equalizer_controls')
329
- #chui_ap_equalizer_block = document.createElement('chui_ap_equalizer_block')
330
- #chui_ap_equalizer_preamp_block = document.createElement("chui_ap_equalizer_preamp_block")
331
- #chui_ap_equalizer_band_block = document.createElement("chui_ap_equalizer_band_block")
332
- #toggle_on_off = new Toggle();
333
- #eqBands = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000]
334
- #select = new Select({width: "41%"})
335
- #media = undefined;
336
- #filters = undefined;
337
- #fx_status = "chuijs.framework.settings.fx_status"
338
- #fx_preset = "chuijs.framework.settings.fx_preset"
339
- #audioContext = new AudioContext();
340
- constructor(audio) {
341
- this.#media = this.#audioContext.createMediaElementSource(audio);
342
- this.#filters = this.#eqBands.map((band, i) => {
343
- let filter = this.#audioContext.createBiquadFilter()
344
- if (i === 0) {
345
- filter.type = "lowshelf";
346
- } else if (i === this.#eqBands.length - 1) {
347
- filter.type = "highshelf";
348
- } else {
349
- filter.type = "peaking";
350
- }
351
- filter.gain.value = 0
352
- filter.Q.value = 1
353
- filter.frequency.value = band
354
- return filter
355
- })
356
- this.#filters.reduce((prev, curr) => {
357
- prev.connect(curr)
358
- return curr
359
- })
360
- this.#media.connect(this.#filters[0]);
361
- this.#filters[this.#filters.length - 1].connect(this.#audioContext.destination);
362
- //
363
- this.#chui_ap_equalizer_preamp_block.appendChild(this.#setSliderPreamp(this.#filters))
364
- this.#filters.forEach((filter) => this.#chui_ap_equalizer_band_block.appendChild(this.#setSliderBand(filter)))
365
- //
366
- this.#select.setDropdownHeight("230px")
367
- AudioFX.PRESETS.forEach(preset => this.#select.addOptions({title: preset.title, value: preset.name}))
368
- //
369
- this.#select.addValueChangeListener((e) => this.#filters.forEach((filter) => this.#setPreset(filter, e.detail.value, true)))
370
- //
371
- this.#chui_ap_equalizer_controls.appendChild(this.#select.set())
372
- this.#chui_ap_equalizer_controls.appendChild(this.#toggle_on_off.set())
373
- //
374
- this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_preamp_block)
375
- this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_band_block)
376
- //
377
- this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_controls)
378
- this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_block)
379
- //
380
- this.#toggle_on_off.addChangeListener((e) => {
381
- if (e.target.checked) {
382
- this.#fx_ON(this.#audioContext)
383
- } else {
384
- this.#fx_OFF(this.#audioContext)
385
- }
386
- })
387
- }
388
- #fx_ON(audioContext) {
389
- try {
390
- this.#media.disconnect(audioContext.destination);
391
- this.#media.connect(this.#filters[0]);
392
- this.#filters[this.#filters.length - 1].connect(audioContext.destination);
393
- } catch (e) {
394
- this.#media.connect(this.#filters[0]);
395
- this.#filters[this.#filters.length - 1].connect(audioContext.destination);
396
- }
397
- store.delete(this.#fx_status)
398
- store.set(this.#fx_status, true)
399
- this.#setStatusBlock(true)
400
- }
401
- #fx_OFF(audioContext) {
402
- this.#filters[this.#filters.length - 1].disconnect(audioContext.destination);
403
- this.#media.disconnect(this.#filters[0]);
404
- this.#media.connect(audioContext.destination);
405
- store.delete(this.#fx_status)
406
- store.set(this.#fx_status, false)
407
- this.#setStatusBlock(false)
408
- }
409
- #setPreset(filter, name) {
410
- store.delete(this.#fx_preset)
411
- store.set(this.#fx_preset, name)
412
- let filter_test = this.#getPreset(name)
413
- AudioFX.#renderPreampSlider(undefined, filter_test, filter)
414
- let input = filter_test.inputs.filter(input => input.id === String(filter.frequency.value))[0]
415
- AudioFX.#renderSlider(input, filter, filter_test.preamp)
416
- }
417
- #setStatusBlock(status) {
418
- //
419
- this.#select.setDisabled(!status)
420
- //
421
- for (let band of this.#eqBands) {
422
- let sliderBand = document.getElementById(String(band));
423
- sliderBand.disabled = !status;
424
- if (status) {
425
- sliderBand.style.cursor = "pointer"
426
- this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled")
427
- this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled")
428
- } else {
429
- sliderBand.style.cursor = "not-allowed"
430
- this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled")
431
- this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled")
432
- }
433
- }
434
- //
435
- let sliderPreamp = document.getElementById("preamp");
436
- sliderPreamp.disabled = !status;
437
- if (status) {
438
- sliderPreamp.style.cursor = "pointer"
439
- this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled")
440
- this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled")
441
- } else {
442
- sliderPreamp.style.cursor = "not-allowed"
443
- this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled")
444
- this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled")
445
- }
446
- }
447
- #getPreset(name) {
448
- return AudioFX.PRESETS.filter(preset => preset.name === name)[0];
449
- }
450
- #setSliderPreamp(filters) {
451
- let sliderMain = document.createElement("chui_eq_slider_main")
452
- let val = document.createElement("slider_label")
453
- let slider = document.createElement('input')
454
- let label = document.createElement("slider_label")
455
- sliderMain.id = "preamp_main"
456
- slider.id = "preamp"
457
- slider.type = 'range'
458
- slider.className = 'eq_slider_test'
459
- slider.step = "1"
460
- slider.min = "-10"
461
- slider.max = "10"
462
- slider.value = "0"
463
- slider.style.setProperty('--fx-before-width', `50%`);
464
- slider.oninput = (e) => AudioFX.#renderPreampSlider(e.target, this.#getPreset(store.get(this.#fx_preset)), filters)
465
- val.id = "val_preamp"
466
- val.innerText = String(slider.value)
467
- label.innerText = "AMP"
468
- sliderMain.appendChild(val)
469
- sliderMain.appendChild(slider)
470
- sliderMain.appendChild(label)
471
- return sliderMain
472
- }
473
- #setSliderBand(filter) {
474
- let freq_value = String(filter.frequency.value);
475
- let sliderMain = document.createElement("chui_eq_slider_main")
476
- let val = document.createElement("slider_label")
477
- let slider = document.createElement('input')
478
- let label = document.createElement("slider_label")
479
- slider.id = freq_value
480
- slider.type = 'range'
481
- slider.className = 'eq_slider_test'
482
- slider.step = "0.1"
483
- slider.min = "-10"
484
- slider.max = "10"
485
- slider.value = String(filter.gain.value)
486
- slider.style.setProperty('--fx-before-width', `50%`);
487
- slider.oninput = (e) => AudioFX.#renderSlider(e.target, filter, Number(document.getElementById("preamp").value))
488
- val.id = "val_" + freq_value
489
- val.innerText = String(slider.value)
490
- label.innerText = freq_value.replace("000", "K")
491
- sliderMain.appendChild(val)
492
- sliderMain.appendChild(slider)
493
- sliderMain.appendChild(label)
494
- return sliderMain
495
- }
496
- restore() {
497
- setTimeout(() => {
498
- let status = store.get(this.#fx_status)
499
- let preset = store.get(this.#fx_preset)
500
- if (status) {
501
- this.#fx_ON(this.#audioContext)
502
- this.#toggle_on_off.setValue(status)
503
- this.#select.setDefaultOption(store.get(this.#fx_preset))
504
- this.#setStatusBlock(status)
505
- } else {
506
- this.#fx_OFF(this.#audioContext)
507
- this.#toggle_on_off.setValue(status)
508
- if (status === undefined || preset === undefined) {
509
- this.#select.setDefaultOption("Default")
510
- } else {
511
- this.#select.setDefaultOption(store.get(this.#fx_preset))
512
- }
513
- this.#setStatusBlock(status)
514
- }
515
- }, 250)
516
- }
517
- set() {
518
- return this.#chui_ap_equalizer_main
519
- }
520
- static #renderPreampSlider(input, preset, filters = []) {
521
- let p_slider = document.getElementById("preamp");
522
- let p_val = document.getElementById("val_preamp");
523
- if (input === undefined) {
524
- p_slider.value = preset.preamp
525
- } else {
526
- p_slider.value = input.value
527
- preset.inputs.forEach(inp => {
528
- let slid = document.getElementById(inp.id)
529
- filters.forEach(filter => {
530
- if (String(inp.id) === String(filter.frequency.value)) {
531
- filter.gain.value = Number(slid.value) + Number(input.value)
532
- }
533
- })
534
- })
535
- }
536
- p_val.innerText = String(p_slider.value)
537
- let p_test = 50 + (p_slider.value * 5)
538
- p_slider.style.setProperty('--fx-before-width', `${p_test.toFixed(1)}%`);
539
- }
540
- static #renderSlider(input, filter, preamp) {
541
- let slider = document.getElementById(input.id);
542
- let val = document.getElementById("val_" + input.id);
543
- slider.value = input.value
544
- filter.gain.value = Number(Number(slider.value) + preamp)
545
- val.innerText = String(slider.value)
546
- let test = 50 + (slider.value * 5)
547
- slider.style.setProperty('--fx-before-width', `${test.toFixed(1)}%`);
548
- }
549
- // ya.music.Audio.fx
550
- static PRESETS = [
551
- {
552
- name: "Default",
553
- title: "По умолчанию",
554
- preamp: 0,
555
- inputs: [
556
- { id: "60", value: 0 },
557
- { id: "170", value: 0 },
558
- { id: "310", value: 0 },
559
- { id: "600", value: 0 },
560
- { id: "1000", value: 0 },
561
- { id: "3000", value: 0 },
562
- { id: "6000", value: 0 },
563
- { id: "12000", value: 0 },
564
- { id: "14000", value: 0 },
565
- { id: "16000", value: 0 },
566
- ]
567
- },
568
- {
569
- name: "Classical",
570
- title: "Классическая музыка",
571
- preamp: -1,
572
- inputs: [
573
- { id: "60", value: -0.5 },
574
- { id: "170", value: -0.5 },
575
- { id: "310", value: -0.5 },
576
- { id: "600", value: -0.5 },
577
- { id: "1000", value: -0.5 },
578
- { id: "3000", value: -0.5 },
579
- { id: "6000", value: -3.5 },
580
- { id: "12000", value: -3.5 },
581
- { id: "14000", value: -3.5 },
582
- { id: "16000", value: -4.5 },
583
- ]
584
- },
585
- {
586
- name: "Club",
587
- title: "Клубная музыка",
588
- preamp: -4,
589
- inputs: [
590
- { id: "60", value: -0.5 },
591
- { id: "170", value: -0.5 },
592
- { id: "310", value: 4 },
593
- { id: "600", value: 2.5 },
594
- { id: "1000", value: 2.5 },
595
- { id: "3000", value: 2.5 },
596
- { id: "6000", value: 1.5 },
597
- { id: "12000", value: -0.5 },
598
- { id: "14000", value: -0.5 },
599
- { id: "16000", value: -0.5 },
600
- ]
601
- },
602
- {
603
- name: "Dance",
604
- title: "Танцевальная музыка",
605
- preamp: -2,
606
- inputs: [
607
- { id: "60", value: 4.5 },
608
- { id: "170", value: 3.5 },
609
- { id: "310", value: 1 },
610
- { id: "600", value: -0.5 },
611
- { id: "1000", value: -0.5 },
612
- { id: "3000", value: -2.5 },
613
- { id: "6000", value: -3.5 },
614
- { id: "12000", value: -3.5 },
615
- { id: "14000", value: -0.5 },
616
- { id: "16000", value: -0.5 },
617
- ]
618
- },
619
- {
620
- name: "Full Bass",
621
- title: "Усиление НЧ",
622
- preamp: -4,
623
- inputs: [
624
- { id: "60", value: 4 },
625
- { id: "170", value: 4.5 },
626
- { id: "310", value: 4.5 },
627
- { id: "600", value: 2.5 },
628
- { id: "1000", value: 0.5 },
629
- { id: "3000", value: -2 },
630
- { id: "6000", value: -4 },
631
- { id: "12000", value: -5 },
632
- { id: "14000", value: -5.5 },
633
- { id: "16000", value: -5.5 },
634
- ]
635
- },
636
- {
637
- name: "Full Treble",
638
- title: "Усиление ВЧ",
639
- preamp: -6,
640
- inputs: [
641
- { id: "60", value: -4.5 },
642
- { id: "170", value: -4.5 },
643
- { id: "310", value: -4.5 },
644
- { id: "600", value: -2 },
645
- { id: "1000", value: 1 },
646
- { id: "3000", value: 5.5 },
647
- { id: "6000", value: 8 },
648
- { id: "12000", value: 8 },
649
- { id: "14000", value: 8 },
650
- { id: "16000", value: 8 },
651
- ]
652
- },
653
- {
654
- name: "Full Bass & Treble",
655
- title: "Усиление НЧ и ВЧ",
656
- preamp: -5,
657
- inputs: [
658
- { id: "60", value: 3.5 },
659
- { id: "170", value: 2.5 },
660
- { id: "310", value: -0.5 },
661
- { id: "600", value: -3.5 },
662
- { id: "1000", value: -2 },
663
- { id: "3000", value: 0.5 },
664
- { id: "6000", value: 4 },
665
- { id: "12000", value: 5.5 },
666
- { id: "14000", value: 6 },
667
- { id: "16000", value: 6 },
668
- ]
669
- },
670
- {
671
- name: "Laptop Speakers / Headphone",
672
- title: "Колонки ноутбука",
673
- preamp: -4,
674
- inputs: [
675
- { id: "60", value: 2 },
676
- { id: "170", value: 5.5 },
677
- { id: "310", value: 2.5 },
678
- { id: "600", value: -1.5 },
679
- { id: "1000", value: -1 },
680
- { id: "3000", value: 0.5 },
681
- { id: "6000", value: 2 },
682
- { id: "12000", value: 4.5 },
683
- { id: "14000", value: 6 },
684
- { id: "16000", value: 7 },
685
- ]
686
- },
687
- {
688
- name: "Large Hall",
689
- title: "Большой зал",
690
- preamp: -4,
691
- inputs: [
692
- { id: "60", value: 5 },
693
- { id: "170", value: 5 },
694
- { id: "310", value: 2.5 },
695
- { id: "600", value: 2.5 },
696
- { id: "1000", value: -0.5 },
697
- { id: "3000", value: -2 },
698
- { id: "6000", value: -2 },
699
- { id: "12000", value: -2 },
700
- { id: "14000", value: -0.5 },
701
- { id: "16000", value: -0.5 },
702
- ]
703
- },
704
- {
705
- name: "Live",
706
- title: "Концерт",
707
- preamp: -3,
708
- inputs: [
709
- { id: "60", value: -2 },
710
- { id: "170", value: -0.5 },
711
- { id: "310", value: 2 },
712
- { id: "600", value: 2.5 },
713
- { id: "1000", value: 2.5 },
714
- { id: "3000", value: 2.5 },
715
- { id: "6000", value: 2 },
716
- { id: "12000", value: 1 },
717
- { id: "14000", value: 1 },
718
- { id: "16000", value: 1 },
719
- ]
720
- },
721
- {
722
- name: "Party",
723
- title: "Вечеринка",
724
- preamp: -3,
725
- inputs: [
726
- { id: "60", value: 3.5 },
727
- { id: "170", value: 3.5 },
728
- { id: "310", value: -0.5 },
729
- { id: "600", value: -0.5 },
730
- { id: "1000", value: -0.5 },
731
- { id: "3000", value: -0.5 },
732
- { id: "6000", value: -0.5 },
733
- { id: "12000", value: -0.5 },
734
- { id: "14000", value: 3.5 },
735
- { id: "16000", value: 3.5 },
736
- ]
737
- },
738
- {
739
- name: "Pop",
740
- title: "Поп",
741
- preamp: -3,
742
- inputs: [
743
- { id: "60", value: -0.5 },
744
- { id: "170", value: 2 },
745
- { id: "310", value: 3.5 },
746
- { id: "600", value: 4 },
747
- { id: "1000", value: 2.5 },
748
- { id: "3000", value: -0.5 },
749
- { id: "6000", value: -1 },
750
- { id: "12000", value: -1 },
751
- { id: "14000", value: -0.5 },
752
- { id: "16000", value: -0.5 },
753
- ]
754
- },
755
- {
756
- name: "Reggae",
757
- title: "Регги",
758
- preamp: -4,
759
- inputs: [
760
- { id: "60", value: -0.5 },
761
- { id: "170", value: -0.5 },
762
- { id: "310", value: -0.5 },
763
- { id: "600", value: -2.5 },
764
- { id: "1000", value: -0.5 },
765
- { id: "3000", value: 3 },
766
- { id: "6000", value: 3 },
767
- { id: "12000", value: -0.5 },
768
- { id: "14000", value: -0.5 },
769
- { id: "16000", value: -0.5 },
770
- ]
771
- },
772
- {
773
- name: "Ska",
774
- title: "Ска",
775
- preamp: -6,
776
- inputs: [
777
- { id: "60", value: -1 },
778
- { id: "170", value: -2 },
779
- { id: "310", value: -2 },
780
- { id: "600", value: -0.5 },
781
- { id: "1000", value: 2 },
782
- { id: "3000", value: 2.5 },
783
- { id: "6000", value: 4 },
784
- { id: "12000", value: 4.5 },
785
- { id: "14000", value: 5.5 },
786
- { id: "16000", value: 4.5 },
787
- ]
788
- },
789
- {
790
- name: "Soft",
791
- title: "Мягкое звучание",
792
- preamp: -5,
793
- inputs: [
794
- { id: "60", value: 2 },
795
- { id: "170", value: 0.5 },
796
- { id: "310", value: -0.5 },
797
- { id: "600", value: -1 },
798
- { id: "1000", value: -0.5 },
799
- { id: "3000", value: 2 },
800
- { id: "6000", value: 4 },
801
- { id: "12000", value: 4.5 },
802
- { id: "14000", value: 5.5 },
803
- { id: "16000", value: 6 },
804
- ]
805
- },
806
- {
807
- name: "Rock",
808
- title: "Рок",
809
- preamp: -5,
810
- inputs: [
811
- { id: "60", value: 4 },
812
- { id: "170", value: 2 },
813
- { id: "310", value: -2.5 },
814
- { id: "600", value: -4 },
815
- { id: "1000", value: -1.5 },
816
- { id: "3000", value: 2 },
817
- { id: "6000", value: 4 },
818
- { id: "12000", value: 5.5 },
819
- { id: "14000", value: 5.5 },
820
- { id: "16000", value: 5.5 },
821
- ]
822
- },
823
- {
824
- name: "Soft Rock",
825
- title: "Софт-рок",
826
- preamp: -3,
827
- inputs: [
828
- { id: "60", value: 2 },
829
- { id: "170", value: 2 },
830
- { id: "310", value: 1 },
831
- { id: "600", value: -0.5 },
832
- { id: "1000", value: -2 },
833
- { id: "3000", value: -2.5 },
834
- { id: "6000", value: -1.5 },
835
- { id: "12000", value: -0.5 },
836
- { id: "14000", value: 1 },
837
- { id: "16000", value: 4 },
838
- ]
839
- },
840
- {
841
- name: "Techno",
842
- title: "Техно",
843
- preamp: -4,
844
- inputs: [
845
- { id: "60", value: 4 },
846
- { id: "170", value: 2.5 },
847
- { id: "310", value: -0.5 },
848
- { id: "600", value: -2.5 },
849
- { id: "1000", value: -2 },
850
- { id: "3000", value: -0.5 },
851
- { id: "6000", value: 4 },
852
- { id: "12000", value: 4.5 },
853
- { id: "14000", value: 4.5 },
854
- { id: "16000", value: 4 },
855
- ]
856
- }]
857
- }
858
-
859
- class Playlist {
860
- #id_contents = require("randomstring").generate();
861
- #chui_playlist_main = document.createElement("chui_playlist_main")
862
- #chui_playlist_search = document.createElement("chui_playlist_search")
863
- #chui_playlist_search_input = document.createElement("input")
864
- #chui_playlist_list = document.createElement("chui_playlist_list")
865
- #chui_playlist_open_folder = document.createElement("chui_playlist_open_folder")
866
- constructor() {
867
- this.#chui_playlist_main.appendChild(this.#chui_playlist_search)
868
- this.#chui_playlist_search_input.classList.add("chui_playlist_search_input")
869
- this.#chui_playlist_search_input.placeholder = "Поиск..."
870
- this.#chui_playlist_search.appendChild(this.#chui_playlist_search_input)
871
- //
872
- this.#chui_playlist_open_folder.innerHTML = new Icon(Icons.FILE.FOLDER, "12pt").getHTML()
873
- this.#chui_playlist_search.appendChild(this.#chui_playlist_open_folder)
874
- this.#chui_playlist_main.appendChild(this.#chui_playlist_list)
875
- this.#chui_playlist_search_input.addEventListener("input", (evt) => {
876
- for (let item of this.#chui_playlist_list.children) {
877
- let text1 = item.textContent.toLowerCase();
878
- let text2 = evt.target.value.toLowerCase();
879
- if (!text1.includes(text2)) {
880
- item.style.display = "none"
881
- } else {
882
- item.removeAttribute("style")
883
- }
884
- }
885
- })
886
- this.#chui_playlist_list.id = this.#id_contents
887
-
888
- this.#chui_playlist_list.addEventListener("mouseover", () => {
889
- this.#chui_playlist_list.style.overflow = "hidden overlay"
890
- })
891
- this.#chui_playlist_list.addEventListener("mouseleave", () => {
892
- this.#chui_playlist_list.style.overflow = "hidden hidden"
893
- })
894
- }
895
- getId() {
896
- return this.#id_contents
897
- }
898
- getOpenFolderButton() {
899
- return this.#chui_playlist_open_folder
900
- }
901
- getMain() {
902
- return this.#chui_playlist_main
903
- }
904
- getPlaylist() {
905
- return this.#chui_playlist_list
906
- }
907
- }
908
-
1
+ const fs = require("fs");
2
+ const dataurl = require("dataurl");
3
+ const { Icon, Icons } = require("../chui_icons/icons");
4
+ const {Label} = require('../chui_label/label');
5
+ const {Select} = require("../chui_inputs/chui_select_box/select_box");
6
+ const {Dialog} = require("../chui_modal/modal");
7
+ const Store = require('electron-store');
8
+ const {shell} = require("electron");
9
+ const {Toggle} = require("../chui_inputs/chui_toggle/toggle");
10
+ const store = new Store();
11
+
12
+ let play_list = []
13
+
14
+ class Audio {
15
+ #current_audio = 0
16
+ #chui_ap_main = document.createElement(`chui_ap_main`);
17
+ #chui_ap_block = document.createElement(`chui_ap_block`);
18
+ #chui_at = document.createElement(`audio`);
19
+ #chui_source_tag = document.createElement(`source`);
20
+ // Блок информация
21
+ #chui_ap_info = document.createElement(`chui_ap_info`);
22
+ #chui_ap_time1 = undefined;
23
+ #chui_ap_time2 = undefined;
24
+ #chui_ap_seek_block = document.createElement("chui_ap_seek_block")
25
+ #chui_ap_seek = document.createElement(`input`);
26
+ #chui_ap_seek_buf = document.createElement(`chui_ap_seek_buf`);
27
+ #chui_ap_track_title = document.createElement(`chui_ap_track_title`);
28
+ // Блок управления
29
+ #chui_ap_controls = document.createElement(`chui_ap_controls`);
30
+ #chui_ap_play_pause = document.createElement(`chui_ap_play_pause`);
31
+ #chui_ap_next = document.createElement(`chui_ap_next`);
32
+ #chui_ap_prev = document.createElement(`chui_ap_prev`);
33
+ // Блок управления громкостью
34
+ #chui_ap_volume_block = document.createElement("chui_ap_volume_block");
35
+ #chui_ap_volume_icon = document.createElement(`chui_ap_volume_icon`);
36
+ #chui_ap_volume = document.createElement(`input`);
37
+ //
38
+ #chui_ap_fx_icon = document.createElement(`chui_ap_fx_icon`);
39
+ // Размеры иконок
40
+ #icons_sizes = {
41
+ play_pause: "30px",
42
+ next_prev: "24px",
43
+ volume: "24px"
44
+ }
45
+ #chui_playlist = new Playlist()
46
+ #chui_audio_fx = new AudioFX(this.#chui_at)
47
+ constructor(options = { autoplay: Boolean(), pin: String(), playlist: Boolean(), width: String(), height: String() }) {
48
+ require('../../modules/chui_functions').setStyles(__dirname + "/audio_styles.css", 'chUiJS_Audio');
49
+ this.#chui_at.setAttribute("name", "media")
50
+ this.#chui_at.controls = false;
51
+ this.#chui_at.preload = "metadata"
52
+ this.#chui_at.crossOrigin = "anonymous"
53
+ this.#chui_at.style.borderRadius = "var(--border_radius)"
54
+ // Настройки
55
+ if (options.autoplay) {
56
+ this.#chui_at.autoplay = options.autoplay;
57
+ setTimeout(async () => await this.#start(play_list[this.#current_audio]), 1)
58
+ }
59
+ // ИНФОРМАЦИЯ
60
+ this.#chui_ap_time1 = new Label({text: `0:00`})
61
+ this.#chui_ap_time2 = new Label({text: `0:00`})
62
+ this.#chui_ap_seek.type = "range"
63
+ this.#chui_ap_seek.id = "chui_ap_seek"
64
+ this.#chui_ap_seek.max = "0"
65
+ this.#chui_ap_seek.value = "0"
66
+ this.#chui_ap_seek.step = "any"
67
+ // КНОПКИ
68
+ this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PLAY_ARROW, this.#icons_sizes.play_pause).getHTML()
69
+ this.#chui_ap_next.innerHTML = new Icon(Icons.AUDIO_VIDEO.SKIP_NEXT, this.#icons_sizes.next_prev).getHTML()
70
+ this.#chui_ap_prev.innerHTML = new Icon(Icons.AUDIO_VIDEO.SKIP_PREVIOUS, this.#icons_sizes.next_prev).getHTML()
71
+ // Заполнение элемента
72
+ // УПРАВЛЕНИЕ ГРОМКОСТЬЮ
73
+ this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_UP, this.#icons_sizes.volume).getHTML()
74
+ this.#chui_ap_volume.type = "range"
75
+ this.#chui_ap_volume.id = "chui_ap_volume"
76
+ this.#chui_ap_volume.max = "100"
77
+ this.#chui_ap_volume.value = "100"
78
+ this.#chui_ap_volume.step = "1"
79
+ this.#chui_at.volume = this.#chui_ap_volume.value / 100;
80
+ this.#chui_ap_volume_block.appendChild(this.#chui_ap_volume_icon)
81
+ this.#chui_ap_volume_block.appendChild(this.#chui_ap_volume)
82
+ this.#chui_ap_fx_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.EQUALIZER, this.#icons_sizes.volume).getHTML()
83
+ this.#chui_ap_volume_block.appendChild(this.#chui_ap_fx_icon)
84
+ // ИНФОРМАЦИЯ
85
+ this.#chui_ap_info.appendChild(this.#chui_ap_time1.set())
86
+ this.#chui_ap_seek_block.appendChild(this.#chui_ap_seek)
87
+ this.#chui_ap_seek_block.appendChild(this.#chui_ap_seek_buf)
88
+ this.#chui_ap_info.appendChild(this.#chui_ap_seek_block)
89
+ this.#chui_ap_info.appendChild(this.#chui_ap_time2.set())
90
+ // КНОПКИ
91
+ this.#chui_ap_controls.appendChild(this.#chui_ap_prev)
92
+ this.#chui_ap_controls.appendChild(this.#chui_ap_play_pause)
93
+ this.#chui_ap_controls.appendChild(this.#chui_ap_next)
94
+ this.#chui_ap_controls.appendChild(this.#chui_ap_track_title)
95
+ //
96
+ this.#chui_ap_controls.appendChild(this.#chui_ap_volume_block)
97
+ //
98
+ this.#chui_ap_main.appendChild(this.#chui_at)
99
+ this.#chui_at.appendChild(this.#chui_source_tag)
100
+ this.#chui_ap_block.appendChild(this.#chui_ap_controls)
101
+ this.#chui_ap_block.appendChild(this.#chui_ap_info)
102
+ //
103
+ this.#chui_ap_main.appendChild(this.#chui_ap_block)
104
+ // СОБЫТИЯ
105
+ this.#chui_ap_play_pause.addEventListener("click", async () => this.#playAudioPause())
106
+ navigator.mediaSession.setActionHandler('play', async () => this.#playAudioPause());
107
+ navigator.mediaSession.setActionHandler('pause', async () => this.#playAudioPause());
108
+ this.#chui_ap_next.addEventListener("click", async () => this.#playAudioNext())
109
+ this.#chui_ap_prev.addEventListener("click", async () => this.#playAudioPrev())
110
+ navigator.mediaSession.setActionHandler('nexttrack', async () => this.#playAudioNext());
111
+ navigator.mediaSession.setActionHandler('previoustrack', async () => this.#playAudioPrev());
112
+ this.#chui_at.addEventListener("timeupdate", async () => {
113
+ this.#displayBufferedAmount()
114
+ this.#renderProgress(this.#chui_at.currentTime)
115
+ if (this.#chui_at.currentTime === this.#chui_at.duration) await this.#playAudioNext()
116
+ });
117
+ this.#chui_ap_seek.addEventListener('input', () => {
118
+ this.#chui_at.currentTime = Number(Number(this.#chui_ap_seek.value).toFixed(6));
119
+ });
120
+ this.#chui_ap_volume.addEventListener('input', () => {
121
+ this.#chui_at.volume = this.#chui_ap_volume.value / 100;
122
+ this.#renderVolume()
123
+ if (Number(this.#chui_ap_volume.value) === 0) {
124
+ this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_MUTE, this.#icons_sizes.volume).getHTML()
125
+ } else {
126
+ this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_UP, this.#icons_sizes.volume).getHTML()
127
+ }
128
+ });
129
+ this.#chui_ap_volume_icon.addEventListener('click', () => {
130
+ if (!this.#chui_at.muted) {
131
+ this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_OFF, this.#icons_sizes.volume).getHTML()
132
+ this.#chui_at.muted = true
133
+ this.#chui_ap_volume.disabled = true
134
+ } else {
135
+ this.#chui_ap_volume_icon.innerHTML = new Icon(Icons.AUDIO_VIDEO.VOLUME_UP, this.#icons_sizes.volume).getHTML()
136
+ this.#chui_at.muted = false
137
+ this.#chui_ap_volume.disabled = false
138
+ }
139
+ })
140
+ this.#renderVolume()
141
+ if (options.pin !== undefined) this.#chui_ap_main.classList.add(options.pin);
142
+ if (options.width !== undefined) this.#chui_ap_main.style.width = options.width;
143
+ if (options.height !== undefined) this.#chui_ap_main.style.height = options.height;
144
+ if (options.playlist !== undefined) this.#chui_ap_main.appendChild(this.#chui_playlist.getMain())
145
+ let dialog = new Dialog({ closeOutSideClick: true })
146
+ dialog.addToBody(this.#chui_audio_fx)
147
+ this.#chui_ap_main.appendChild(dialog.set())
148
+ this.#chui_ap_fx_icon.addEventListener("click", () => dialog.open())
149
+ }
150
+ play() {
151
+ this.#chui_ap_play_pause.click()
152
+ }
153
+ next() {
154
+ this.#chui_ap_next.click()
155
+ }
156
+ prev() {
157
+ this.#chui_ap_prev.click()
158
+ }
159
+ openFolder(path) {
160
+ this.#chui_playlist.getOpenFolderButton().addEventListener("click", async () => await shell.openPath(path))
161
+ }
162
+ set() {
163
+ return this.#chui_ap_main;
164
+ }
165
+ restoreFX() {
166
+ this.#chui_audio_fx.restore();
167
+ }
168
+ async #convertSong(filePath, type) {
169
+ return await new Promise((resolve, reject) => {
170
+ fs.readFile(filePath, (err, data) => {
171
+ if (err) reject(err)
172
+ resolve(dataurl.convert({data, mimetype: type}));
173
+ });
174
+ });
175
+ };
176
+ async #start(track) {
177
+ this.#renderProgress("0")
178
+ this.#chui_ap_track_title.innerText = `${track.artist} - ${track.title}`
179
+ this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PAUSE, this.#icons_sizes.play_pause).getHTML()
180
+ if (track.path.includes("http")) {
181
+ this.#chui_source_tag.src = track.path
182
+ } else {
183
+ this.#chui_source_tag.src = String(await this.#convertSong(track.path, track.mimetype))
184
+ }
185
+ this.#chui_at.load()
186
+ await this.#chui_at.play().then(() => {
187
+ this.#setSliderMax()
188
+ this.#displayBufferedAmount()
189
+ })
190
+ Audio.#setMediaData(track)
191
+ }
192
+ async #playAudioNext() {
193
+ this.#current_audio = this.#current_audio + 1
194
+ if (this.#current_audio < play_list.length) {
195
+ await this.#start(play_list[this.#current_audio])
196
+ } else if (this.#current_audio === play_list.length) {
197
+ this.#current_audio = 0
198
+ await this.#start(play_list[this.#current_audio])
199
+ }
200
+ this.setActive(this.#current_audio)
201
+ }
202
+ async #playAudioPrev() {
203
+ this.#current_audio = this.#current_audio - 1
204
+ if (this.#current_audio < 0) {
205
+ this.#current_audio = play_list.length - 1
206
+ await this.#start(play_list[this.#current_audio])
207
+ } else {
208
+ await this.#start(play_list[this.#current_audio])
209
+ }
210
+ this.setActive(this.#current_audio)
211
+ }
212
+ async #playAudioPause() {
213
+ if (this.#chui_at.currentTime === 0) {
214
+ this.setActive(this.#current_audio)
215
+ await this.#start(play_list[this.#current_audio])
216
+ } else if (this.#chui_at.currentTime > 0 && !this.#chui_at.paused) {
217
+ this.#chui_at.pause()
218
+ this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PLAY_ARROW, this.#icons_sizes.play_pause).getHTML()
219
+ } else if (this.#chui_at.currentTime > 0 && this.#chui_at.paused) {
220
+ await this.#chui_at.play()
221
+ this.#chui_ap_play_pause.innerHTML = new Icon(Icons.AUDIO_VIDEO.PAUSE, this.#icons_sizes.play_pause).getHTML()
222
+ }
223
+ }
224
+ #displayBufferedAmount = () => {
225
+ try {
226
+ const end = this.#chui_at.buffered.end(0) / this.#chui_ap_seek.max * 100
227
+ if (end > 100) {
228
+ this.#chui_ap_seek_buf.style.width = `100%`;
229
+ } else {
230
+ this.#chui_ap_seek_buf.style.width = `${end}%`;
231
+ }
232
+ } catch (e) {}
233
+ }
234
+ #renderVolume = () => {
235
+ let test = this.#chui_ap_volume.value / this.#chui_ap_volume.max * 100
236
+ this.#chui_ap_main.style.setProperty('--volume-before-width', `${test}%`);
237
+ }
238
+ #renderProgress = (value) => {
239
+ try {
240
+ if (value > 0 && this.#chui_at.duration > 0) {
241
+ this.#chui_ap_time1.setText(this.#calculateTime(value));
242
+ this.#chui_ap_time2.setText(this.#calculateTime(this.#chui_at.duration));
243
+ this.#chui_ap_seek.value = value;
244
+ const width = this.#chui_ap_seek.value / this.#chui_ap_seek.max * 100
245
+ this.#chui_ap_main.style.setProperty('--seek-before-width', `${width}%`);
246
+ } else {
247
+ this.#chui_ap_seek.value = value;
248
+ this.#chui_ap_main.style.setProperty('--seek-before-width', `0%`);
249
+ }
250
+ } catch (e) {
251
+ this.#chui_ap_time1.setText(`0:00`);
252
+ this.#chui_ap_time2.setText(`0:00`);
253
+ }
254
+ }
255
+ #calculateTime = (secs) => {
256
+ const minutes = Math.floor(secs / 60);
257
+ const seconds = Math.floor(secs % 60);
258
+ const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
259
+ return `${minutes}:${returnedSeconds}`;
260
+ }
261
+ #setSliderMax = () => {
262
+ this.#chui_ap_seek.max = String(this.#chui_at.duration);
263
+ }
264
+ //
265
+ setPlayList(list = [{ title: String(), artist: String(), album: String(), mimetype: String(), artwork: [] }]) {
266
+ this.#chui_playlist.getPlaylist().innerHTML = '';
267
+ play_list = list;
268
+ for (let track of play_list) this.#chui_playlist.getPlaylist().appendChild(this.#setTrack(track, play_list.indexOf(track)));
269
+ }
270
+ #setTrack(track = {}, index = Number()) {
271
+ let chui_track = document.createElement("chui_track");
272
+ let chui_track_name = document.createElement("chui_track_name");
273
+ //
274
+ chui_track.id = `${index}`
275
+ chui_track_name.innerText = `${track.artist} - ${track.title}`
276
+ //
277
+ chui_track.addEventListener("dblclick", async (ev) => {
278
+ let target_row = ev.target
279
+ if (target_row.tagName === "CHUI_TRACK_NAME" || target_row.tagName === "CHUI_TRACK_DURATION") {
280
+ this.setActive(ev.target.parentNode.id)
281
+ } else {
282
+ this.setActive(ev.target.id)
283
+ }
284
+ await this.#start(track)
285
+ this.#current_audio = index;
286
+ })
287
+ chui_track.appendChild(chui_track_name)
288
+ return chui_track;
289
+ }
290
+ setActive(index = Number()) {
291
+ document.getElementById(this.#chui_playlist.getId()).childNodes.forEach(child => {
292
+ child.classList.remove("chui_track_active");
293
+ })
294
+ let element = document.getElementById(`${index}`)
295
+ element.classList.add("chui_track_active")
296
+ }
297
+ static PIN = {
298
+ TOP: "pin_top",
299
+ BOTTOM: "pin_bottom"
300
+ }
301
+ static #setMediaData(media) {
302
+ if ("mediaSession" in navigator) {
303
+ navigator.mediaSession.metadata = new MediaMetadata({
304
+ title: media.title,
305
+ artist: media.artist,
306
+ album: media.album,
307
+ artwork: media.artwork
308
+ });
309
+ }
310
+ }
311
+ static MIMETYPES = {
312
+ AU_SND: 'audio/basic',
313
+ LINEAR_PCM: 'auido/L24',
314
+ MID_RMI: 'audio/mid',
315
+ MP3: 'audio/mpeg',
316
+ MP4: 'audio/mp4',
317
+ AIF_AIFC_AIFF: 'audio/x-aiff',
318
+ M3U: 'audio/x-mpegurl',
319
+ RA_RAM: 'audio/vnd.rn-realaudio',
320
+ OGG: 'audio/ogg',
321
+ VORBIS: 'audio/vorbis',
322
+ WAV: 'audio/vnd.wav'
323
+ }
324
+ }
325
+
326
+ class AudioFX {
327
+ #chui_ap_equalizer_main = document.createElement('chui_ap_equalizer_main')
328
+ #chui_ap_equalizer_controls = document.createElement('chui_ap_equalizer_controls')
329
+ #chui_ap_equalizer_block = document.createElement('chui_ap_equalizer_block')
330
+ #chui_ap_equalizer_preamp_block = document.createElement("chui_ap_equalizer_preamp_block")
331
+ #chui_ap_equalizer_band_block = document.createElement("chui_ap_equalizer_band_block")
332
+ #toggle_on_off = new Toggle();
333
+ #eqBands = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000]
334
+ #select = new Select({width: "41%"})
335
+ #media = undefined;
336
+ #filters = undefined;
337
+ #fx_status = "chuijs.framework.settings.fx_status"
338
+ #fx_preset = "chuijs.framework.settings.fx_preset"
339
+ #audioContext = new AudioContext();
340
+ constructor(audio) {
341
+ this.#media = this.#audioContext.createMediaElementSource(audio);
342
+ this.#filters = this.#eqBands.map((band, i) => {
343
+ let filter = this.#audioContext.createBiquadFilter()
344
+ if (i === 0) {
345
+ filter.type = "lowshelf";
346
+ } else if (i === this.#eqBands.length - 1) {
347
+ filter.type = "highshelf";
348
+ } else {
349
+ filter.type = "peaking";
350
+ }
351
+ filter.gain.value = 0
352
+ filter.Q.value = 1
353
+ filter.frequency.value = band
354
+ return filter
355
+ })
356
+ this.#filters.reduce((prev, curr) => {
357
+ prev.connect(curr)
358
+ return curr
359
+ })
360
+ this.#media.connect(this.#filters[0]);
361
+ this.#filters[this.#filters.length - 1].connect(this.#audioContext.destination);
362
+ //
363
+ this.#chui_ap_equalizer_preamp_block.appendChild(this.#setSliderPreamp(this.#filters))
364
+ this.#filters.forEach((filter) => this.#chui_ap_equalizer_band_block.appendChild(this.#setSliderBand(filter)))
365
+ //
366
+ this.#select.setDropdownHeight("230px")
367
+ AudioFX.PRESETS.forEach(preset => this.#select.addOptions({title: preset.title, value: preset.name}))
368
+ //
369
+ this.#select.addValueChangeListener((e) => this.#filters.forEach((filter) => this.#setPreset(filter, e.detail.value, true)))
370
+ //
371
+ this.#chui_ap_equalizer_controls.appendChild(this.#select.set())
372
+ this.#chui_ap_equalizer_controls.appendChild(this.#toggle_on_off.set())
373
+ //
374
+ this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_preamp_block)
375
+ this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_band_block)
376
+ //
377
+ this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_controls)
378
+ this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_block)
379
+ //
380
+ this.#toggle_on_off.addChangeListener((e) => {
381
+ if (e.target.checked) {
382
+ this.#fx_ON(this.#audioContext)
383
+ } else {
384
+ this.#fx_OFF(this.#audioContext)
385
+ }
386
+ })
387
+ }
388
+ #fx_ON(audioContext) {
389
+ try {
390
+ this.#media.disconnect(audioContext.destination);
391
+ this.#media.connect(this.#filters[0]);
392
+ this.#filters[this.#filters.length - 1].connect(audioContext.destination);
393
+ } catch (e) {
394
+ this.#media.connect(this.#filters[0]);
395
+ this.#filters[this.#filters.length - 1].connect(audioContext.destination);
396
+ }
397
+ store.delete(this.#fx_status)
398
+ store.set(this.#fx_status, true)
399
+ this.#setStatusBlock(true)
400
+ }
401
+ #fx_OFF(audioContext) {
402
+ this.#filters[this.#filters.length - 1].disconnect(audioContext.destination);
403
+ this.#media.disconnect(this.#filters[0]);
404
+ this.#media.connect(audioContext.destination);
405
+ store.delete(this.#fx_status)
406
+ store.set(this.#fx_status, false)
407
+ this.#setStatusBlock(false)
408
+ }
409
+ #setPreset(filter, name) {
410
+ store.delete(this.#fx_preset)
411
+ store.set(this.#fx_preset, name)
412
+ let filter_test = this.#getPreset(name)
413
+ AudioFX.#renderPreampSlider(undefined, filter_test, filter)
414
+ let input = filter_test.inputs.filter(input => input.id === String(filter.frequency.value))[0]
415
+ AudioFX.#renderSlider(input, filter, filter_test.preamp)
416
+ }
417
+ #setStatusBlock(status) {
418
+ //
419
+ this.#select.setDisabled(!status)
420
+ //
421
+ for (let band of this.#eqBands) {
422
+ let sliderBand = document.getElementById(String(band));
423
+ sliderBand.disabled = !status;
424
+ if (status) {
425
+ sliderBand.style.cursor = "pointer"
426
+ this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled")
427
+ this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled")
428
+ } else {
429
+ sliderBand.style.cursor = "not-allowed"
430
+ this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled")
431
+ this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled")
432
+ }
433
+ }
434
+ //
435
+ let sliderPreamp = document.getElementById("preamp");
436
+ sliderPreamp.disabled = !status;
437
+ if (status) {
438
+ sliderPreamp.style.cursor = "pointer"
439
+ this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled")
440
+ this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled")
441
+ } else {
442
+ sliderPreamp.style.cursor = "not-allowed"
443
+ this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled")
444
+ this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled")
445
+ }
446
+ }
447
+ #getPreset(name) {
448
+ return AudioFX.PRESETS.filter(preset => preset.name === name)[0];
449
+ }
450
+ #setSliderPreamp(filters) {
451
+ let sliderMain = document.createElement("chui_eq_slider_main")
452
+ let val = document.createElement("slider_label")
453
+ let slider = document.createElement('input')
454
+ let label = document.createElement("slider_label")
455
+ sliderMain.id = "preamp_main"
456
+ slider.id = "preamp"
457
+ slider.type = 'range'
458
+ slider.className = 'eq_slider_test'
459
+ slider.step = "1"
460
+ slider.min = "-10"
461
+ slider.max = "10"
462
+ slider.value = "0"
463
+ slider.style.setProperty('--fx-before-width', `50%`);
464
+ slider.oninput = (e) => AudioFX.#renderPreampSlider(e.target, this.#getPreset(store.get(this.#fx_preset)), filters)
465
+ val.id = "val_preamp"
466
+ val.innerText = String(slider.value)
467
+ label.innerText = "AMP"
468
+ sliderMain.appendChild(val)
469
+ sliderMain.appendChild(slider)
470
+ sliderMain.appendChild(label)
471
+ return sliderMain
472
+ }
473
+ #setSliderBand(filter) {
474
+ let freq_value = String(filter.frequency.value);
475
+ let sliderMain = document.createElement("chui_eq_slider_main")
476
+ let val = document.createElement("slider_label")
477
+ let slider = document.createElement('input')
478
+ let label = document.createElement("slider_label")
479
+ slider.id = freq_value
480
+ slider.type = 'range'
481
+ slider.className = 'eq_slider_test'
482
+ slider.step = "0.1"
483
+ slider.min = "-10"
484
+ slider.max = "10"
485
+ slider.value = String(filter.gain.value)
486
+ slider.style.setProperty('--fx-before-width', `50%`);
487
+ slider.oninput = (e) => AudioFX.#renderSlider(e.target, filter, Number(document.getElementById("preamp").value))
488
+ val.id = "val_" + freq_value
489
+ val.innerText = String(slider.value)
490
+ label.innerText = freq_value.replace("000", "K")
491
+ sliderMain.appendChild(val)
492
+ sliderMain.appendChild(slider)
493
+ sliderMain.appendChild(label)
494
+ return sliderMain
495
+ }
496
+ restore() {
497
+ setTimeout(() => {
498
+ let status = store.get(this.#fx_status)
499
+ let preset = store.get(this.#fx_preset)
500
+ if (status) {
501
+ this.#fx_ON(this.#audioContext)
502
+ this.#toggle_on_off.setValue(status)
503
+ this.#select.setDefaultOption(store.get(this.#fx_preset))
504
+ this.#setStatusBlock(status)
505
+ } else {
506
+ this.#fx_OFF(this.#audioContext)
507
+ this.#toggle_on_off.setValue(status)
508
+ if (status === undefined || preset === undefined) {
509
+ this.#select.setDefaultOption("Default")
510
+ } else {
511
+ this.#select.setDefaultOption(store.get(this.#fx_preset))
512
+ }
513
+ this.#setStatusBlock(status)
514
+ }
515
+ }, 250)
516
+ }
517
+ set() {
518
+ return this.#chui_ap_equalizer_main
519
+ }
520
+ static #renderPreampSlider(input, preset, filters = []) {
521
+ let p_slider = document.getElementById("preamp");
522
+ let p_val = document.getElementById("val_preamp");
523
+ if (input === undefined) {
524
+ p_slider.value = preset.preamp
525
+ } else {
526
+ p_slider.value = input.value
527
+ preset.inputs.forEach(inp => {
528
+ let slid = document.getElementById(inp.id)
529
+ filters.forEach(filter => {
530
+ if (String(inp.id) === String(filter.frequency.value)) {
531
+ filter.gain.value = Number(slid.value) + Number(input.value)
532
+ }
533
+ })
534
+ })
535
+ }
536
+ p_val.innerText = String(p_slider.value)
537
+ let p_test = 50 + (p_slider.value * 5)
538
+ p_slider.style.setProperty('--fx-before-width', `${p_test.toFixed(1)}%`);
539
+ }
540
+ static #renderSlider(input, filter, preamp) {
541
+ let slider = document.getElementById(input.id);
542
+ let val = document.getElementById("val_" + input.id);
543
+ slider.value = input.value
544
+ filter.gain.value = Number(Number(slider.value) + preamp)
545
+ val.innerText = String(slider.value)
546
+ let test = 50 + (slider.value * 5)
547
+ slider.style.setProperty('--fx-before-width', `${test.toFixed(1)}%`);
548
+ }
549
+ // ya.music.Audio.fx
550
+ static PRESETS = [
551
+ {
552
+ name: "Default",
553
+ title: "По умолчанию",
554
+ preamp: 0,
555
+ inputs: [
556
+ { id: "60", value: 0 },
557
+ { id: "170", value: 0 },
558
+ { id: "310", value: 0 },
559
+ { id: "600", value: 0 },
560
+ { id: "1000", value: 0 },
561
+ { id: "3000", value: 0 },
562
+ { id: "6000", value: 0 },
563
+ { id: "12000", value: 0 },
564
+ { id: "14000", value: 0 },
565
+ { id: "16000", value: 0 },
566
+ ]
567
+ },
568
+ {
569
+ name: "Classical",
570
+ title: "Классическая музыка",
571
+ preamp: -1,
572
+ inputs: [
573
+ { id: "60", value: -0.5 },
574
+ { id: "170", value: -0.5 },
575
+ { id: "310", value: -0.5 },
576
+ { id: "600", value: -0.5 },
577
+ { id: "1000", value: -0.5 },
578
+ { id: "3000", value: -0.5 },
579
+ { id: "6000", value: -3.5 },
580
+ { id: "12000", value: -3.5 },
581
+ { id: "14000", value: -3.5 },
582
+ { id: "16000", value: -4.5 },
583
+ ]
584
+ },
585
+ {
586
+ name: "Club",
587
+ title: "Клубная музыка",
588
+ preamp: -4,
589
+ inputs: [
590
+ { id: "60", value: -0.5 },
591
+ { id: "170", value: -0.5 },
592
+ { id: "310", value: 4 },
593
+ { id: "600", value: 2.5 },
594
+ { id: "1000", value: 2.5 },
595
+ { id: "3000", value: 2.5 },
596
+ { id: "6000", value: 1.5 },
597
+ { id: "12000", value: -0.5 },
598
+ { id: "14000", value: -0.5 },
599
+ { id: "16000", value: -0.5 },
600
+ ]
601
+ },
602
+ {
603
+ name: "Dance",
604
+ title: "Танцевальная музыка",
605
+ preamp: -2,
606
+ inputs: [
607
+ { id: "60", value: 4.5 },
608
+ { id: "170", value: 3.5 },
609
+ { id: "310", value: 1 },
610
+ { id: "600", value: -0.5 },
611
+ { id: "1000", value: -0.5 },
612
+ { id: "3000", value: -2.5 },
613
+ { id: "6000", value: -3.5 },
614
+ { id: "12000", value: -3.5 },
615
+ { id: "14000", value: -0.5 },
616
+ { id: "16000", value: -0.5 },
617
+ ]
618
+ },
619
+ {
620
+ name: "Full Bass",
621
+ title: "Усиление НЧ",
622
+ preamp: -4,
623
+ inputs: [
624
+ { id: "60", value: 4 },
625
+ { id: "170", value: 4.5 },
626
+ { id: "310", value: 4.5 },
627
+ { id: "600", value: 2.5 },
628
+ { id: "1000", value: 0.5 },
629
+ { id: "3000", value: -2 },
630
+ { id: "6000", value: -4 },
631
+ { id: "12000", value: -5 },
632
+ { id: "14000", value: -5.5 },
633
+ { id: "16000", value: -5.5 },
634
+ ]
635
+ },
636
+ {
637
+ name: "Full Treble",
638
+ title: "Усиление ВЧ",
639
+ preamp: -6,
640
+ inputs: [
641
+ { id: "60", value: -4.5 },
642
+ { id: "170", value: -4.5 },
643
+ { id: "310", value: -4.5 },
644
+ { id: "600", value: -2 },
645
+ { id: "1000", value: 1 },
646
+ { id: "3000", value: 5.5 },
647
+ { id: "6000", value: 8 },
648
+ { id: "12000", value: 8 },
649
+ { id: "14000", value: 8 },
650
+ { id: "16000", value: 8 },
651
+ ]
652
+ },
653
+ {
654
+ name: "Full Bass & Treble",
655
+ title: "Усиление НЧ и ВЧ",
656
+ preamp: -5,
657
+ inputs: [
658
+ { id: "60", value: 3.5 },
659
+ { id: "170", value: 2.5 },
660
+ { id: "310", value: -0.5 },
661
+ { id: "600", value: -3.5 },
662
+ { id: "1000", value: -2 },
663
+ { id: "3000", value: 0.5 },
664
+ { id: "6000", value: 4 },
665
+ { id: "12000", value: 5.5 },
666
+ { id: "14000", value: 6 },
667
+ { id: "16000", value: 6 },
668
+ ]
669
+ },
670
+ {
671
+ name: "Laptop Speakers / Headphone",
672
+ title: "Колонки ноутбука",
673
+ preamp: -4,
674
+ inputs: [
675
+ { id: "60", value: 2 },
676
+ { id: "170", value: 5.5 },
677
+ { id: "310", value: 2.5 },
678
+ { id: "600", value: -1.5 },
679
+ { id: "1000", value: -1 },
680
+ { id: "3000", value: 0.5 },
681
+ { id: "6000", value: 2 },
682
+ { id: "12000", value: 4.5 },
683
+ { id: "14000", value: 6 },
684
+ { id: "16000", value: 7 },
685
+ ]
686
+ },
687
+ {
688
+ name: "Large Hall",
689
+ title: "Большой зал",
690
+ preamp: -4,
691
+ inputs: [
692
+ { id: "60", value: 5 },
693
+ { id: "170", value: 5 },
694
+ { id: "310", value: 2.5 },
695
+ { id: "600", value: 2.5 },
696
+ { id: "1000", value: -0.5 },
697
+ { id: "3000", value: -2 },
698
+ { id: "6000", value: -2 },
699
+ { id: "12000", value: -2 },
700
+ { id: "14000", value: -0.5 },
701
+ { id: "16000", value: -0.5 },
702
+ ]
703
+ },
704
+ {
705
+ name: "Live",
706
+ title: "Концерт",
707
+ preamp: -3,
708
+ inputs: [
709
+ { id: "60", value: -2 },
710
+ { id: "170", value: -0.5 },
711
+ { id: "310", value: 2 },
712
+ { id: "600", value: 2.5 },
713
+ { id: "1000", value: 2.5 },
714
+ { id: "3000", value: 2.5 },
715
+ { id: "6000", value: 2 },
716
+ { id: "12000", value: 1 },
717
+ { id: "14000", value: 1 },
718
+ { id: "16000", value: 1 },
719
+ ]
720
+ },
721
+ {
722
+ name: "Party",
723
+ title: "Вечеринка",
724
+ preamp: -3,
725
+ inputs: [
726
+ { id: "60", value: 3.5 },
727
+ { id: "170", value: 3.5 },
728
+ { id: "310", value: -0.5 },
729
+ { id: "600", value: -0.5 },
730
+ { id: "1000", value: -0.5 },
731
+ { id: "3000", value: -0.5 },
732
+ { id: "6000", value: -0.5 },
733
+ { id: "12000", value: -0.5 },
734
+ { id: "14000", value: 3.5 },
735
+ { id: "16000", value: 3.5 },
736
+ ]
737
+ },
738
+ {
739
+ name: "Pop",
740
+ title: "Поп",
741
+ preamp: -3,
742
+ inputs: [
743
+ { id: "60", value: -0.5 },
744
+ { id: "170", value: 2 },
745
+ { id: "310", value: 3.5 },
746
+ { id: "600", value: 4 },
747
+ { id: "1000", value: 2.5 },
748
+ { id: "3000", value: -0.5 },
749
+ { id: "6000", value: -1 },
750
+ { id: "12000", value: -1 },
751
+ { id: "14000", value: -0.5 },
752
+ { id: "16000", value: -0.5 },
753
+ ]
754
+ },
755
+ {
756
+ name: "Reggae",
757
+ title: "Регги",
758
+ preamp: -4,
759
+ inputs: [
760
+ { id: "60", value: -0.5 },
761
+ { id: "170", value: -0.5 },
762
+ { id: "310", value: -0.5 },
763
+ { id: "600", value: -2.5 },
764
+ { id: "1000", value: -0.5 },
765
+ { id: "3000", value: 3 },
766
+ { id: "6000", value: 3 },
767
+ { id: "12000", value: -0.5 },
768
+ { id: "14000", value: -0.5 },
769
+ { id: "16000", value: -0.5 },
770
+ ]
771
+ },
772
+ {
773
+ name: "Ska",
774
+ title: "Ска",
775
+ preamp: -6,
776
+ inputs: [
777
+ { id: "60", value: -1 },
778
+ { id: "170", value: -2 },
779
+ { id: "310", value: -2 },
780
+ { id: "600", value: -0.5 },
781
+ { id: "1000", value: 2 },
782
+ { id: "3000", value: 2.5 },
783
+ { id: "6000", value: 4 },
784
+ { id: "12000", value: 4.5 },
785
+ { id: "14000", value: 5.5 },
786
+ { id: "16000", value: 4.5 },
787
+ ]
788
+ },
789
+ {
790
+ name: "Soft",
791
+ title: "Мягкое звучание",
792
+ preamp: -5,
793
+ inputs: [
794
+ { id: "60", value: 2 },
795
+ { id: "170", value: 0.5 },
796
+ { id: "310", value: -0.5 },
797
+ { id: "600", value: -1 },
798
+ { id: "1000", value: -0.5 },
799
+ { id: "3000", value: 2 },
800
+ { id: "6000", value: 4 },
801
+ { id: "12000", value: 4.5 },
802
+ { id: "14000", value: 5.5 },
803
+ { id: "16000", value: 6 },
804
+ ]
805
+ },
806
+ {
807
+ name: "Rock",
808
+ title: "Рок",
809
+ preamp: -5,
810
+ inputs: [
811
+ { id: "60", value: 4 },
812
+ { id: "170", value: 2 },
813
+ { id: "310", value: -2.5 },
814
+ { id: "600", value: -4 },
815
+ { id: "1000", value: -1.5 },
816
+ { id: "3000", value: 2 },
817
+ { id: "6000", value: 4 },
818
+ { id: "12000", value: 5.5 },
819
+ { id: "14000", value: 5.5 },
820
+ { id: "16000", value: 5.5 },
821
+ ]
822
+ },
823
+ {
824
+ name: "Soft Rock",
825
+ title: "Софт-рок",
826
+ preamp: -3,
827
+ inputs: [
828
+ { id: "60", value: 2 },
829
+ { id: "170", value: 2 },
830
+ { id: "310", value: 1 },
831
+ { id: "600", value: -0.5 },
832
+ { id: "1000", value: -2 },
833
+ { id: "3000", value: -2.5 },
834
+ { id: "6000", value: -1.5 },
835
+ { id: "12000", value: -0.5 },
836
+ { id: "14000", value: 1 },
837
+ { id: "16000", value: 4 },
838
+ ]
839
+ },
840
+ {
841
+ name: "Techno",
842
+ title: "Техно",
843
+ preamp: -4,
844
+ inputs: [
845
+ { id: "60", value: 4 },
846
+ { id: "170", value: 2.5 },
847
+ { id: "310", value: -0.5 },
848
+ { id: "600", value: -2.5 },
849
+ { id: "1000", value: -2 },
850
+ { id: "3000", value: -0.5 },
851
+ { id: "6000", value: 4 },
852
+ { id: "12000", value: 4.5 },
853
+ { id: "14000", value: 4.5 },
854
+ { id: "16000", value: 4 },
855
+ ]
856
+ }]
857
+ }
858
+
859
+ class Playlist {
860
+ #id_contents = require("randomstring").generate();
861
+ #chui_playlist_main = document.createElement("chui_playlist_main")
862
+ #chui_playlist_search = document.createElement("chui_playlist_search")
863
+ #chui_playlist_search_input = document.createElement("input")
864
+ #chui_playlist_list = document.createElement("chui_playlist_list")
865
+ #chui_playlist_open_folder = document.createElement("chui_playlist_open_folder")
866
+ constructor() {
867
+ this.#chui_playlist_main.appendChild(this.#chui_playlist_search)
868
+ this.#chui_playlist_search_input.classList.add("chui_playlist_search_input")
869
+ this.#chui_playlist_search_input.placeholder = "Поиск..."
870
+ this.#chui_playlist_search.appendChild(this.#chui_playlist_search_input)
871
+ //
872
+ this.#chui_playlist_open_folder.innerHTML = new Icon(Icons.FILE.FOLDER, "12pt").getHTML()
873
+ this.#chui_playlist_search.appendChild(this.#chui_playlist_open_folder)
874
+ this.#chui_playlist_main.appendChild(this.#chui_playlist_list)
875
+ this.#chui_playlist_search_input.addEventListener("input", (evt) => {
876
+ for (let item of this.#chui_playlist_list.children) {
877
+ let text1 = item.textContent.toLowerCase();
878
+ let text2 = evt.target.value.toLowerCase();
879
+ if (!text1.includes(text2)) {
880
+ item.style.display = "none"
881
+ } else {
882
+ item.removeAttribute("style")
883
+ }
884
+ }
885
+ })
886
+ this.#chui_playlist_list.id = this.#id_contents
887
+
888
+ this.#chui_playlist_list.addEventListener("mouseover", () => {
889
+ this.#chui_playlist_list.style.overflow = "hidden overlay"
890
+ })
891
+ this.#chui_playlist_list.addEventListener("mouseleave", () => {
892
+ this.#chui_playlist_list.style.overflow = "hidden hidden"
893
+ })
894
+ }
895
+ getId() {
896
+ return this.#id_contents
897
+ }
898
+ getOpenFolderButton() {
899
+ return this.#chui_playlist_open_folder
900
+ }
901
+ getMain() {
902
+ return this.#chui_playlist_main
903
+ }
904
+ getPlaylist() {
905
+ return this.#chui_playlist_list
906
+ }
907
+ }
908
+
909
909
  exports.Audio = Audio