@quicktvui/web-renderer 1.0.0
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.
- package/package.json +24 -0
- package/src/adapters/es3-video-player.js +828 -0
- package/src/components/Modal.js +119 -0
- package/src/components/QtAnimationView.js +678 -0
- package/src/components/QtBaseComponent.js +165 -0
- package/src/components/QtFastListView.js +1920 -0
- package/src/components/QtFlexView.js +799 -0
- package/src/components/QtImage.js +203 -0
- package/src/components/QtItemFrame.js +239 -0
- package/src/components/QtItemStoreView.js +93 -0
- package/src/components/QtItemView.js +125 -0
- package/src/components/QtListView.js +331 -0
- package/src/components/QtLoadingView.js +55 -0
- package/src/components/QtPageRootView.js +19 -0
- package/src/components/QtPlayMark.js +168 -0
- package/src/components/QtProgressBar.js +199 -0
- package/src/components/QtQRCode.js +78 -0
- package/src/components/QtReplaceChild.js +149 -0
- package/src/components/QtRippleView.js +166 -0
- package/src/components/QtSeekBar.js +409 -0
- package/src/components/QtText.js +679 -0
- package/src/components/QtTransitionImage.js +170 -0
- package/src/components/QtView.js +706 -0
- package/src/components/QtWebView.js +613 -0
- package/src/components/TabsView.js +420 -0
- package/src/components/ViewPager.js +206 -0
- package/src/components/index.js +24 -0
- package/src/components/plugins/TextV2Component.js +70 -0
- package/src/components/plugins/index.js +7 -0
- package/src/core/SceneBuilder.js +58 -0
- package/src/core/TVFocusManager.js +2014 -0
- package/src/core/asyncLocalStorage.js +175 -0
- package/src/core/autoProxy.js +165 -0
- package/src/core/componentRegistry.js +84 -0
- package/src/core/constants.js +6 -0
- package/src/core/index.js +8 -0
- package/src/core/moduleUtils.js +36 -0
- package/src/core/patches.js +958 -0
- package/src/core/templateBinding.js +666 -0
- package/src/index.js +246 -0
- package/src/modules/AndroidDevelopModule.js +101 -0
- package/src/modules/AndroidDeviceModule.js +341 -0
- package/src/modules/AndroidNetworkModule.js +178 -0
- package/src/modules/AndroidSharedPreferencesModule.js +100 -0
- package/src/modules/ESDeviceInfoModule.js +450 -0
- package/src/modules/ESGroupDataModule.js +195 -0
- package/src/modules/ESIJKAudioPlayerModule.js +477 -0
- package/src/modules/ESLocalStorageModule.js +100 -0
- package/src/modules/ESLogModule.js +65 -0
- package/src/modules/ESModule.js +106 -0
- package/src/modules/ESNetworkSpeedModule.js +117 -0
- package/src/modules/ESToastModule.js +172 -0
- package/src/modules/EsNativeModule.js +117 -0
- package/src/modules/FastListModule.js +101 -0
- package/src/modules/FocusModule.js +145 -0
- package/src/modules/RuntimeDeviceModule.js +176 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
// ESIJKAudioPlayerModule - Web adapter for ES IJK Audio Player
|
|
2
|
+
// Uses HTML5 Audio API to implement audio playback
|
|
3
|
+
|
|
4
|
+
import { resolveAddon, createModuleInit } from '../core/moduleUtils'
|
|
5
|
+
|
|
6
|
+
// Player states (matching native ESPlayerState)
|
|
7
|
+
const ESPlayerState = {
|
|
8
|
+
ES_PLAYER_STATE_IDLE: 0,
|
|
9
|
+
ES_PLAYER_STATE_PREPARING: 1,
|
|
10
|
+
ES_PLAYER_STATE_PREPARED: 2,
|
|
11
|
+
ES_PLAYER_STATE_BUFFER_START: 3,
|
|
12
|
+
ES_PLAYER_STATE_BUFFER_END: 4,
|
|
13
|
+
ES_PLAYER_STATE_PLAYING: 5,
|
|
14
|
+
ES_PLAYER_STATE_SEEK_START: 6,
|
|
15
|
+
ES_PLAYER_STATE_SEEK_COMPLETED: 7,
|
|
16
|
+
ES_PLAYER_STATE_PAUSED: 8,
|
|
17
|
+
ES_PLAYER_STATE_RESUMED: 9,
|
|
18
|
+
ES_PLAYER_STATE_BEFORE_STOP: 10,
|
|
19
|
+
ES_PLAYER_STATE_STOP: 11,
|
|
20
|
+
ES_PLAYER_STATE_PLAYBACK_COMPLETED: 12,
|
|
21
|
+
ES_PLAYER_STATE_ERROR: 13,
|
|
22
|
+
ES_PLAYER_STATE_VIDEO_SIZE_CHANGED: 14,
|
|
23
|
+
ES_PLAYER_STATE_PLAYER_VIEW_CHANGED: 15,
|
|
24
|
+
ES_PLAYER_STATE_AD_START: 16,
|
|
25
|
+
ES_PLAYER_STATE_AD_END: 17,
|
|
26
|
+
ES_PLAYER_STATE_AD_SKIP: 18,
|
|
27
|
+
ES_PLAYER_STATE_AD_PAUSED: 19,
|
|
28
|
+
ES_PLAYER_STATE_AUTHORIZED: 20,
|
|
29
|
+
ES_PLAYER_STATE_SET_PLAY_RATE_SUCCESS: 21,
|
|
30
|
+
ES_PLAYER_STATE_SET_PLAY_RATE_ERROR: 22,
|
|
31
|
+
ES_PLAYER_STATE_AD_RESUMED: 23,
|
|
32
|
+
ES_PLAYER_STATE_AD_LOADED: 24,
|
|
33
|
+
ES_PLAYER_STATE_AD_TIME: 25,
|
|
34
|
+
ES_PLAYER_STATE_PLAYER_INITIALIZED: 26,
|
|
35
|
+
ES_PLAYER_STATE_TIMED_TEXT_CHANGED: 27,
|
|
36
|
+
ES_PLAYER_STATE_PLAYER_CLICKABLE: 28,
|
|
37
|
+
ES_PLAYER_STATE_INITIALIZE_SUCCESS: 29,
|
|
38
|
+
ES_PLAYER_STATE_INITIALIZE_ERROR: 30,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Get EventBus lazily
|
|
42
|
+
let _eventBus = null
|
|
43
|
+
function getEventBus() {
|
|
44
|
+
if (!_eventBus) {
|
|
45
|
+
try {
|
|
46
|
+
const esVue = require('@extscreen/es3-vue')
|
|
47
|
+
if (esVue && esVue.EventBus) {
|
|
48
|
+
_eventBus = esVue.EventBus
|
|
49
|
+
}
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.warn('[ESIJKAudioPlayerModule] EventBus not available:', e.message)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return _eventBus
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Dispatch event to EventBus
|
|
58
|
+
function dispatchEvent(eventName, data) {
|
|
59
|
+
const eventBus = getEventBus()
|
|
60
|
+
if (eventBus && eventBus.$emit) {
|
|
61
|
+
eventBus.$emit(eventName, data)
|
|
62
|
+
}
|
|
63
|
+
// Also dispatch custom event for global listeners
|
|
64
|
+
if (typeof window !== 'undefined') {
|
|
65
|
+
window.dispatchEvent(new CustomEvent(eventName, { detail: data }))
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Audio instance manager
|
|
70
|
+
class AudioPlayerManager {
|
|
71
|
+
constructor() {
|
|
72
|
+
this.instances = new Map()
|
|
73
|
+
this.defaultPlayRate = 1.0
|
|
74
|
+
this.defaultVolume = 1.0
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Get or create audio instance with event binding
|
|
78
|
+
getInstance(id) {
|
|
79
|
+
if (!this.instances.has(id)) {
|
|
80
|
+
const audio = new Audio()
|
|
81
|
+
audio.defaultPlaybackRate = this.defaultPlayRate
|
|
82
|
+
audio.volume = this.defaultVolume
|
|
83
|
+
this._bindAudioEvents(audio, id)
|
|
84
|
+
this.instances.set(id, audio)
|
|
85
|
+
}
|
|
86
|
+
return this.instances.get(id)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
_bindAudioEvents(audio, id) {
|
|
90
|
+
// Track if we've sent PREPARED for current source
|
|
91
|
+
let hasPrepared = false
|
|
92
|
+
let currentState = ESPlayerState.ES_PLAYER_STATE_IDLE
|
|
93
|
+
|
|
94
|
+
// Play event
|
|
95
|
+
audio.addEventListener('play', () => {
|
|
96
|
+
if (currentState !== ESPlayerState.ES_PLAYER_STATE_PLAYING) {
|
|
97
|
+
currentState = ESPlayerState.ES_PLAYER_STATE_PLAYING
|
|
98
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
99
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYING,
|
|
100
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PLAYING,
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// Playing event (after buffering) - don't send PREPARED again!
|
|
106
|
+
audio.addEventListener('playing', () => {
|
|
107
|
+
if (currentState !== ESPlayerState.ES_PLAYER_STATE_PLAYING) {
|
|
108
|
+
currentState = ESPlayerState.ES_PLAYER_STATE_PLAYING
|
|
109
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
110
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYING,
|
|
111
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PLAYING,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
// Pause event
|
|
117
|
+
audio.addEventListener('pause', () => {
|
|
118
|
+
currentState = ESPlayerState.ES_PLAYER_STATE_PAUSED
|
|
119
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
120
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PAUSED,
|
|
121
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PAUSED,
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
// Ended event
|
|
126
|
+
audio.addEventListener('ended', () => {
|
|
127
|
+
currentState = ESPlayerState.ES_PLAYER_STATE_PLAYBACK_COMPLETED
|
|
128
|
+
hasPrepared = true // Prevent canplay from sending PREPARED again
|
|
129
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
130
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYBACK_COMPLETED,
|
|
131
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PLAYBACK_COMPLETED,
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
// Error event
|
|
136
|
+
audio.addEventListener('error', (e) => {
|
|
137
|
+
currentState = ESPlayerState.ES_PLAYER_STATE_ERROR
|
|
138
|
+
dispatchEvent('onESAudioPlayerError', {
|
|
139
|
+
errorCode: e.target.error?.code || -1,
|
|
140
|
+
errorMessage: e.target.error?.message || 'Audio error',
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// Load start (preparing)
|
|
145
|
+
audio.addEventListener('loadstart', () => {
|
|
146
|
+
hasPrepared = false
|
|
147
|
+
currentState = ESPlayerState.ES_PLAYER_STATE_PREPARING
|
|
148
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
149
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PREPARING,
|
|
150
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PREPARING,
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// Can play (prepared) - only send once per source
|
|
155
|
+
audio.addEventListener('canplay', () => {
|
|
156
|
+
if (!hasPrepared) {
|
|
157
|
+
hasPrepared = true
|
|
158
|
+
currentState = ESPlayerState.ES_PLAYER_STATE_PREPARED
|
|
159
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
160
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PREPARED,
|
|
161
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PREPARED,
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// Waiting (buffering)
|
|
167
|
+
audio.addEventListener('waiting', () => {
|
|
168
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
169
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_BUFFER_START,
|
|
170
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_BUFFER_START,
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
// Can play through (buffer end)
|
|
175
|
+
audio.addEventListener('canplaythrough', () => {
|
|
176
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
177
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_BUFFER_END,
|
|
178
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_BUFFER_END,
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
// Duration change
|
|
183
|
+
audio.addEventListener('durationchange', () => {
|
|
184
|
+
if (audio.duration && !isNaN(audio.duration)) {
|
|
185
|
+
dispatchEvent('onESAudioPlayerInfo', {
|
|
186
|
+
what: 1, // MEDIA_INFO_DURATION
|
|
187
|
+
extra: Math.floor(audio.duration * 1000),
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
// Rate change
|
|
193
|
+
audio.addEventListener('ratechange', () => {
|
|
194
|
+
dispatchEvent('onESAudioPlayRateChanged', {
|
|
195
|
+
playRate: audio.playbackRate,
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// Seeking
|
|
200
|
+
audio.addEventListener('seeking', () => {
|
|
201
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
202
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_SEEK_START,
|
|
203
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_SEEK_START,
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
// Seeked
|
|
208
|
+
audio.addEventListener('seeked', () => {
|
|
209
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
210
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_SEEK_COMPLETED,
|
|
211
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_SEEK_COMPLETED,
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
// Volume change
|
|
216
|
+
audio.addEventListener('volumechange', () => {
|
|
217
|
+
dispatchEvent('onESAudioPlayerInfo', {
|
|
218
|
+
what: 2, // MEDIA_INFO_VOLUME_CHANGED
|
|
219
|
+
extra: Math.floor(audio.volume * 100),
|
|
220
|
+
})
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Remove audio instance
|
|
225
|
+
removeInstance(id) {
|
|
226
|
+
const audio = this.instances.get(id)
|
|
227
|
+
if (audio) {
|
|
228
|
+
audio.pause()
|
|
229
|
+
audio.src = ''
|
|
230
|
+
this.instances.delete(id)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Clear all instances
|
|
235
|
+
clearAll() {
|
|
236
|
+
this.instances.forEach((audio, id) => {
|
|
237
|
+
audio.pause()
|
|
238
|
+
audio.src = ''
|
|
239
|
+
})
|
|
240
|
+
this.instances.clear()
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const audioManager = new AudioPlayerManager()
|
|
245
|
+
|
|
246
|
+
export class ESIJKAudioPlayerModule {
|
|
247
|
+
constructor(context) {
|
|
248
|
+
this.context = context
|
|
249
|
+
this.name = ''
|
|
250
|
+
this.mode = 'normal'
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async init(...args) {
|
|
254
|
+
// Send initialized event
|
|
255
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
256
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
|
|
257
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
|
|
258
|
+
})
|
|
259
|
+
// Send init success
|
|
260
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
261
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
|
|
262
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
|
|
263
|
+
})
|
|
264
|
+
return createModuleInit(args)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
initMediaPlayer(...args) {
|
|
268
|
+
// Send initialized event
|
|
269
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
270
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
|
|
271
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
|
|
272
|
+
})
|
|
273
|
+
// Send init success
|
|
274
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
275
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
|
|
276
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
|
|
277
|
+
})
|
|
278
|
+
return resolveAddon(args, null)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
play(id, ...params) {
|
|
282
|
+
console.log('[ESIJKAudioPlayerModule] play called with id:', id, 'params:', params)
|
|
283
|
+
const audio = audioManager.getInstance(id)
|
|
284
|
+
const args = params || []
|
|
285
|
+
|
|
286
|
+
// Parse play parameters
|
|
287
|
+
// Can be:
|
|
288
|
+
// 1. URL string: play(-1, 'https://...')
|
|
289
|
+
// 2. URL in array: play(-1, ['https://...'])
|
|
290
|
+
// 3. Object: play(-1, { url: '...', uri: '...' })
|
|
291
|
+
let url = ''
|
|
292
|
+
let autoplay = true
|
|
293
|
+
|
|
294
|
+
if (args.length > 0) {
|
|
295
|
+
const firstArg = args[0]
|
|
296
|
+
|
|
297
|
+
// Check if it's a string (direct URL)
|
|
298
|
+
if (typeof firstArg === 'string') {
|
|
299
|
+
url = firstArg
|
|
300
|
+
}
|
|
301
|
+
// Check if it's an array with URL string
|
|
302
|
+
else if (Array.isArray(firstArg) && typeof firstArg[0] === 'string') {
|
|
303
|
+
url = firstArg[0]
|
|
304
|
+
}
|
|
305
|
+
// Check if it's an object with url/src/uri
|
|
306
|
+
else if (typeof firstArg === 'object' && firstArg !== null && !Array.isArray(firstArg)) {
|
|
307
|
+
url = firstArg.url || firstArg.src || firstArg.uri || ''
|
|
308
|
+
autoplay = firstArg.autoplay !== false
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
console.log('[ESIJKAudioPlayerModule] parsed url:', url, 'autoplay:', autoplay)
|
|
313
|
+
|
|
314
|
+
if (url) {
|
|
315
|
+
audio.src = url
|
|
316
|
+
audio.load()
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (autoplay && audio.src) {
|
|
320
|
+
audio.play().catch((e) => {
|
|
321
|
+
console.warn('[ESIJKAudioPlayerModule] play error:', e)
|
|
322
|
+
dispatchEvent('onESAudioPlayerError', {
|
|
323
|
+
errorCode: -1,
|
|
324
|
+
errorMessage: e.message || 'Play error',
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
return resolveAddon(args, null)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
start(id, ...args) {
|
|
332
|
+
const audio = audioManager.getInstance(id)
|
|
333
|
+
if (audio.src) {
|
|
334
|
+
audio.play().catch((e) => {
|
|
335
|
+
console.warn('[ESIJKAudioPlayerModule] start error:', e)
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
return resolveAddon(args, null)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
pause(id, ...args) {
|
|
342
|
+
const audio = audioManager.getInstance(id)
|
|
343
|
+
audio.pause()
|
|
344
|
+
return resolveAddon(args, null)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
resume(id, ...args) {
|
|
348
|
+
const audio = audioManager.getInstance(id)
|
|
349
|
+
audio.play().catch((e) => {
|
|
350
|
+
console.warn('[ESIJKAudioPlayerModule] resume error:', e)
|
|
351
|
+
})
|
|
352
|
+
// Send resumed event
|
|
353
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
354
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_RESUMED,
|
|
355
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_RESUMED,
|
|
356
|
+
})
|
|
357
|
+
return resolveAddon(args, null)
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
seekTo(id, progress, ...args) {
|
|
361
|
+
const audio = audioManager.getInstance(id)
|
|
362
|
+
if (audio.duration && progress >= 0) {
|
|
363
|
+
audio.currentTime = Math.min(progress / 1000, audio.duration) // progress is in ms
|
|
364
|
+
}
|
|
365
|
+
return resolveAddon(args, null)
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
stop(id, ...args) {
|
|
369
|
+
const audio = audioManager.getInstance(id)
|
|
370
|
+
// Send before stop event
|
|
371
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
372
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_BEFORE_STOP,
|
|
373
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_BEFORE_STOP,
|
|
374
|
+
})
|
|
375
|
+
audio.pause()
|
|
376
|
+
audio.currentTime = 0
|
|
377
|
+
// Send stopped event
|
|
378
|
+
dispatchEvent('onESAudioPlayerStatusChanged', {
|
|
379
|
+
playerStatus: ESPlayerState.ES_PLAYER_STATE_STOP,
|
|
380
|
+
playerState: ESPlayerState.ES_PLAYER_STATE_STOP,
|
|
381
|
+
})
|
|
382
|
+
return resolveAddon(args, null)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
setPlayRate(id, speed, ...args) {
|
|
386
|
+
const audio = audioManager.getInstance(id)
|
|
387
|
+
audio.playbackRate = Number(speed) || 1.0
|
|
388
|
+
dispatchEvent('onESAudioPlayRateChanged', {
|
|
389
|
+
playRate: audio.playbackRate,
|
|
390
|
+
})
|
|
391
|
+
return resolveAddon(args, null)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
setVolume(id, volume, ...args) {
|
|
395
|
+
const audio = audioManager.getInstance(id)
|
|
396
|
+
audio.volume = Math.max(0, Math.min(1, Number(volume) || 0))
|
|
397
|
+
return resolveAddon(args, null)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
setLeftRightVolume(id, leftVolume, rightVolume, ...args) {
|
|
401
|
+
const audio = audioManager.getInstance(id)
|
|
402
|
+
// HTML5 Audio doesn't support stereo balance, use average
|
|
403
|
+
const avgVolume = (Number(leftVolume) + Number(rightVolume)) / 2
|
|
404
|
+
audio.volume = Math.max(0, Math.min(1, avgVolume || 0))
|
|
405
|
+
return resolveAddon(args, null)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
reset(id, ...args) {
|
|
409
|
+
const audio = audioManager.getInstance(id)
|
|
410
|
+
audio.pause()
|
|
411
|
+
audio.currentTime = 0
|
|
412
|
+
audio.src = ''
|
|
413
|
+
return resolveAddon(args, null)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
release(id, ...args) {
|
|
417
|
+
audioManager.removeInstance(id)
|
|
418
|
+
return resolveAddon(args, null)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
async isPlaying(id, ...args) {
|
|
422
|
+
const audio = audioManager.getInstance(id)
|
|
423
|
+
const result = !audio.paused && audio.currentTime > 0
|
|
424
|
+
return resolveAddon(args, result)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
async isPaused(id, ...args) {
|
|
428
|
+
const audio = audioManager.getInstance(id)
|
|
429
|
+
const result = audio.paused
|
|
430
|
+
return resolveAddon(args, result)
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
async getDuration(id, ...args) {
|
|
434
|
+
const audio = audioManager.getInstance(id)
|
|
435
|
+
// Return duration in milliseconds
|
|
436
|
+
const duration = audio.duration && !isNaN(audio.duration) ? audio.duration * 1000 : -1
|
|
437
|
+
return resolveAddon(args, duration)
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async getCurrentPosition(id, ...args) {
|
|
441
|
+
const audio = audioManager.getInstance(id)
|
|
442
|
+
// Return position in milliseconds
|
|
443
|
+
const position = audio.currentTime && !isNaN(audio.currentTime) ? audio.currentTime * 1000 : 0
|
|
444
|
+
return resolveAddon(args, position)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
async getBufferPercentage(id, ...args) {
|
|
448
|
+
const audio = audioManager.getInstance(id)
|
|
449
|
+
if (audio.buffered.length > 0 && audio.duration > 0) {
|
|
450
|
+
const bufferedEnd = audio.buffered.end(audio.buffered.length - 1)
|
|
451
|
+
const percentage = Math.round((bufferedEnd / audio.duration) * 100)
|
|
452
|
+
return resolveAddon(args, percentage)
|
|
453
|
+
}
|
|
454
|
+
return resolveAddon(args, 0)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
async getCurrentPlayRate(id, ...args) {
|
|
458
|
+
const audio = audioManager.getInstance(id)
|
|
459
|
+
return resolveAddon(args, audio.playbackRate || 1.0)
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
async getLeftVolume(id, ...args) {
|
|
463
|
+
const audio = audioManager.getInstance(id)
|
|
464
|
+
// HTML5 Audio doesn't support stereo, return same as volume
|
|
465
|
+
return resolveAddon(args, audio.volume)
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async getRightVolume(id, ...args) {
|
|
469
|
+
const audio = audioManager.getInstance(id)
|
|
470
|
+
// HTML5 Audio doesn't support stereo, return same as volume
|
|
471
|
+
return resolveAddon(args, audio.volume)
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
destroy() {
|
|
475
|
+
audioManager.clearAll()
|
|
476
|
+
}
|
|
477
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { resolveAddon, createModuleInit } from '../core/moduleUtils'
|
|
2
|
+
|
|
3
|
+
function getRawStorage() {
|
|
4
|
+
const g = globalThis
|
|
5
|
+
return (g && g.__localStorage) || (g && g.localStorage) || null
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async function readStorage(key) {
|
|
9
|
+
const s = getRawStorage()
|
|
10
|
+
if (!s || !s.getItem) return null
|
|
11
|
+
const v = s.getItem(key)
|
|
12
|
+
return v && typeof v.then === 'function' ? await v : v
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function writeStorage(key, value) {
|
|
16
|
+
const s = getRawStorage()
|
|
17
|
+
if (!s || !s.setItem) return false
|
|
18
|
+
const r = s.setItem(key, value)
|
|
19
|
+
if (r && typeof r.then === 'function') await r
|
|
20
|
+
return true
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class ESLocalStorageModule {
|
|
24
|
+
constructor(context) {
|
|
25
|
+
this.context = context
|
|
26
|
+
this.name = ''
|
|
27
|
+
this.mode = 'normal'
|
|
28
|
+
this._name = ''
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_key(key) {
|
|
32
|
+
if (!this._name) return key
|
|
33
|
+
return `${this._name}:${key}`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async initSharedPreferences(name, ...args) {
|
|
37
|
+
this._name = String(name ?? '')
|
|
38
|
+
return resolveAddon(args, true)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async initESSharedPreferences(name, ...args) {
|
|
42
|
+
this._name = String(name ?? '')
|
|
43
|
+
return resolveAddon(args, true)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async getBoolean(key, defValue, ...args) {
|
|
47
|
+
const v = await readStorage(this._key(String(key)))
|
|
48
|
+
if (v === null || v === undefined) return resolveAddon(args, !!defValue)
|
|
49
|
+
if (v === 'true') return resolveAddon(args, true)
|
|
50
|
+
if (v === 'false') return resolveAddon(args, false)
|
|
51
|
+
if (v === '1') return resolveAddon(args, true)
|
|
52
|
+
if (v === '0') return resolveAddon(args, false)
|
|
53
|
+
return resolveAddon(args, !!defValue)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async putBoolean(key, value, ...args) {
|
|
57
|
+
const ok = await writeStorage(this._key(String(key)), value ? 'true' : 'false')
|
|
58
|
+
return resolveAddon(args, ok)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getInt(key, defValue, ...args) {
|
|
62
|
+
const v = await readStorage(this._key(String(key)))
|
|
63
|
+
if (v === null || v === undefined || v === '') return resolveAddon(args, Number(defValue) || 0)
|
|
64
|
+
const n = Number.parseInt(String(v), 10)
|
|
65
|
+
return resolveAddon(args, Number.isFinite(n) ? n : Number(defValue) || 0)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async putInt(key, value, ...args) {
|
|
69
|
+
const ok = await writeStorage(this._key(String(key)), String(Number(value) | 0))
|
|
70
|
+
return resolveAddon(args, ok)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async getLong(key, defValue, ...args) {
|
|
74
|
+
const v = await readStorage(this._key(String(key)))
|
|
75
|
+
if (v === null || v === undefined || v === '') return resolveAddon(args, Number(defValue) || 0)
|
|
76
|
+
const n = Number.parseInt(String(v), 10)
|
|
77
|
+
return resolveAddon(args, Number.isFinite(n) ? n : Number(defValue) || 0)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async putLong(key, value, ...args) {
|
|
81
|
+
const ok = await writeStorage(this._key(String(key)), String(Math.trunc(Number(value))))
|
|
82
|
+
return resolveAddon(args, ok)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getString(key, defValue, ...args) {
|
|
86
|
+
const v = await readStorage(this._key(String(key)))
|
|
87
|
+
return resolveAddon(args, v === null || v === undefined ? String(defValue ?? '') : String(v))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async putString(key, value, ...args) {
|
|
91
|
+
const ok = await writeStorage(this._key(String(key)), String(value ?? ''))
|
|
92
|
+
return resolveAddon(args, ok)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async init(...args) {
|
|
96
|
+
return createModuleInit(args)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
destroy() {}
|
|
100
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// ESLogModule - Web adapter for ES Log Module
|
|
2
|
+
// Uses console API for logging
|
|
3
|
+
|
|
4
|
+
import { resolveAddon, createModuleInit } from '../core/moduleUtils'
|
|
5
|
+
|
|
6
|
+
export class ESLogModule {
|
|
7
|
+
constructor(context) {
|
|
8
|
+
this.context = context
|
|
9
|
+
this.name = ''
|
|
10
|
+
this.mode = 'normal'
|
|
11
|
+
this.enabled = true
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async init(...args) {
|
|
15
|
+
return createModuleInit(args)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
destroy() {}
|
|
19
|
+
|
|
20
|
+
v(tag, ...args) {
|
|
21
|
+
if (!this.enabled) return
|
|
22
|
+
console.log(`[V][${tag}]`, ...args)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
d(tag, ...args) {
|
|
26
|
+
if (!this.enabled) return
|
|
27
|
+
console.debug(`[D][${tag}]`, ...args)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
i(tag, ...args) {
|
|
31
|
+
if (!this.enabled) return
|
|
32
|
+
console.info(`[I][${tag}]`, ...args)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
w(tag, ...args) {
|
|
36
|
+
if (!this.enabled) return
|
|
37
|
+
console.warn(`[W][${tag}]`, ...args)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
e(tag, ...args) {
|
|
41
|
+
if (!this.enabled) return
|
|
42
|
+
console.error(`[E][${tag}]`, ...args)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
f(tag, ...args) {
|
|
46
|
+
if (!this.enabled) return
|
|
47
|
+
console.error(`[F][${tag}]`, ...args)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async getEsInfo(...args) {
|
|
51
|
+
const info = {
|
|
52
|
+
version: 'web',
|
|
53
|
+
platform: 'web',
|
|
54
|
+
}
|
|
55
|
+
return resolveAddon(args, info)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setEnabled(enabled) {
|
|
59
|
+
this.enabled = enabled
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
isEnabled() {
|
|
63
|
+
return this.enabled
|
|
64
|
+
}
|
|
65
|
+
}
|