@shijiu/jsview-vue 2.1.6-alpha.0 → 2.1.25

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 (31) hide show
  1. package/package.json +1 -1
  2. package/utils/JsViewEngineWidget/JsvFocusBlock.vue +22 -1
  3. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +6 -0
  4. package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +24 -15
  5. package/utils/JsViewPlugin/JsvAudio/JsvAudio.vue +3 -3
  6. package/utils/JsViewPlugin/JsvPlayer/GetVersion.js +20 -0
  7. package/utils/JsViewPlugin/JsvPlayer/JsvMedia.js +1847 -0
  8. package/utils/JsViewPlugin/JsvPlayer/JsvMediaBrowserInterface.js +101 -0
  9. package/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue +369 -0
  10. package/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser-0.9.vue +53 -0
  11. package/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser.vue +505 -0
  12. package/utils/JsViewPlugin/JsvPlayer/index-0.9.js +60 -0
  13. package/utils/JsViewPlugin/JsvPlayer/index.js +59 -0
  14. package/utils/JsViewPlugin/JsvPlayer/version.mjs +18 -0
  15. package/utils/JsViewPlugin/index.js +1 -0
  16. package/utils/JsViewVueTools/JsvRuntimeBridge.js +5 -4
  17. package/utils/JsViewVueWidget/JsvFreeMoveActor/ActorControl.js +112 -0
  18. package/utils/JsViewVueWidget/JsvFreeMoveActor/CallbackManager.js +68 -0
  19. package/utils/JsViewVueWidget/JsvFreeMoveActor/CommonTools.js +18 -0
  20. package/utils/JsViewVueWidget/JsvFreeMoveActor/FreeMoveActor.vue +46 -0
  21. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetAction.js +216 -0
  22. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetCondition.js +66 -0
  23. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetState.js +38 -0
  24. package/utils/JsViewVueWidget/JsvFreeMoveActor/TypeDefine.js +12 -0
  25. package/utils/JsViewVueWidget/JsvFreeMoveActor/index.js +3 -0
  26. package/utils/JsViewVueWidget/JsvPosterImage.vue +16 -10
  27. package/utils/JsViewVueWidget/JsvRipple/Constant.js +4 -0
  28. package/utils/JsViewVueWidget/JsvRipple/JsvRipple.vue +134 -0
  29. package/utils/JsViewVueWidget/JsvRipple/index.js +7 -0
  30. package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue +55 -68
  31. package/utils/JsViewVueWidget/index.js +2 -0
@@ -0,0 +1,1847 @@
1
+ /* eslint-disable no-prototype-builtins */
2
+ import {getPluginInfo} from './GetVersion'
3
+
4
+ let EVENT_STATUS_NONE = 0;
5
+ let EVENT_STATUS_LOADSTART = 1;
6
+ let EVENT_STATUS_LOAD = 2;
7
+ let EVENT_STATUS_SEEK = 3;
8
+ let EVENT_STATUS_SEEKED = 4;
9
+ let EVENT_STATUS_STALLED = 5;
10
+ let EVENT_STATUS_RESUME = 6;
11
+ let EVENT_STATUS_DISPLAY = 7;
12
+ let EVENT_STATUS_TIMESHIFT = 8;
13
+ let EVENT_STATUS_TIMESHIFTED = 9;
14
+ let EVENT_STATUS_BACKLIVE = 10;
15
+ let EVENT_STATUS_BACKLIVED = 11;
16
+ let EVENT_STATUS_END = 12;
17
+
18
+
19
+ let MediaPluginInfo = getPluginInfo();
20
+
21
+ var mediaArray = [];
22
+
23
+ var pluginLoadListener = [];
24
+ var PluginEventKey = "JsvPlayer";
25
+ var chipType = "";
26
+
27
+ let LOG_LEVEL_FATAL = 5;
28
+ let LOG_LEVEL_ERROR = 4;
29
+ let LOG_LEVEL_WARNING = 3;
30
+ let LOG_LEVEL_DEBUG = 2;
31
+ let LOG_LEVEL_TRACE = 1;
32
+ let LogLevel = LOG_LEVEL_TRACE;
33
+ function logPrint(level, message){
34
+ if(level >= LogLevel){
35
+ console.log(message);
36
+ }
37
+ }
38
+
39
+ function logFatal(message){
40
+ logPrint(LOG_LEVEL_FATAL, message);
41
+ }
42
+
43
+ function logError(message){
44
+ logPrint(LOG_LEVEL_ERROR, message);
45
+ }
46
+
47
+ function logWarning(message){
48
+ logPrint(LOG_LEVEL_WARNING, message);
49
+ }
50
+
51
+ function logDebug(message){
52
+ logPrint(LOG_LEVEL_DEBUG, message);
53
+ }
54
+
55
+ function logTrace(message){
56
+ logPrint(LOG_LEVEL_TRACE, message);
57
+ }
58
+
59
+ function setLogLevel(level){
60
+ LogLevel = level;
61
+ }
62
+
63
+ var PLUGIN_EVENT_STATUS_START_LOAD = 1;
64
+ var PLUGIN_EVENT_STATUS_DOWNLOAD = 2;
65
+ var PLUGIN_EVENT_STATUS_UNZIPED = 3;
66
+ var PLUGIN_EVENT_STATUS_DEXLOADED = 4;
67
+ var PLUGIN_EVENT_STATUS_COMPLETE = 5;
68
+
69
+ /**
70
+ * 0:未加载;
71
+ * 1:开始加载;
72
+ * 2:加载旧插件;
73
+ * 3:加载新插件;
74
+ * 4:加载成功;
75
+ * 5:加载失败。
76
+ */
77
+ var pluginLoadState = 0;
78
+
79
+ function JsvPlayerPluginStatus(status){
80
+ logDebug("JsvPlayerPluginStatus: "+status);
81
+ let ret = JSON.parse(status);
82
+
83
+ let notify_obj = {};
84
+ notify_obj.status = 1;
85
+ if(ret && ret.first_load){
86
+ pluginLoadState = 3;
87
+ notify_obj.code = 1;
88
+ }else{
89
+ pluginLoadState = 2;
90
+ notify_obj.code = 2;
91
+ }
92
+
93
+ for(let i=0; i<pluginLoadListener.length; i++){
94
+ pluginLoadListener[i](notify_obj);
95
+ }
96
+ }
97
+
98
+ window.top.JsvPlayerPluginStatus = function(status){
99
+ JsvPlayerPluginStatus(status);
100
+ }
101
+
102
+ function JsvPlayerPluginLoadResult(result){
103
+ logDebug("JsvPlayerPluginLoadResult: "+result);
104
+ var ret_obj = JSON.parse(result)
105
+ let notify_obj = {};
106
+ if(ret_obj && (ret_obj.status === 5 || ret_obj.status === 1)){
107
+ pluginLoadState = 4;
108
+ notify_obj.status = 3;
109
+ notify_obj.code = 0;
110
+ }else if(ret_obj && ret_obj.status === -12){
111
+ pluginLoadState = 5;
112
+ notify_obj.status = 4;
113
+ notify_obj.code = ret_obj.status;
114
+ }else{
115
+ pluginLoadState = 5;
116
+ notify_obj.status = 4;
117
+ if(ret_obj){
118
+ notify_obj.code = ret_obj.status;
119
+ }else{
120
+ notify_obj.code = -1;
121
+ }
122
+ }
123
+
124
+ if(pluginLoadState === 5){
125
+ logFatal("*************************JsvPlayer plugin load failed, error code is "+ret_obj.status+"*************************");
126
+ }
127
+
128
+ UnregisterJsvPlayerPluginEvent();
129
+
130
+ if(pluginLoadState === 4){
131
+ let capabilitySet = getJsvPlayerCapabilitySet();
132
+ if(capabilitySet !== null && capabilitySet !== ""){
133
+ let capabilitySetObj = JSON.parse(capabilitySet);
134
+ if(capabilitySetObj !== null && capabilitySetObj.hasOwnProperty("chipType")){
135
+ chipType = capabilitySetObj.chipType;
136
+ }
137
+ }
138
+ }
139
+
140
+ for(let i=0; i<mediaArray.length; i++){
141
+ mediaArray[i].buildPlatformInstance();
142
+ }
143
+
144
+ for(let i=0; i<pluginLoadListener.length; i++){
145
+ pluginLoadListener[i](notify_obj);
146
+ }
147
+ }
148
+
149
+ window.top.JsvPlayerPluginLoadResult = function (result) {
150
+ JsvPlayerPluginLoadResult(result);
151
+ }
152
+
153
+ window.top.CreatePlayerResult = function (result) {
154
+ logDebug("CreatePlayerResult: "+result);
155
+ let result_obj = JSON.parse(result);
156
+ if(result_obj.code == 0){
157
+ for(var i=0; i<mediaArray.length; i++){
158
+ if(mediaArray[i].key === result_obj.key){
159
+ mediaArray[i].initPlayer();
160
+ break;
161
+ }
162
+ }
163
+ }else{
164
+ logError("Create player failed, key="+result_obj.key);
165
+ }
166
+ }.bind(this);
167
+
168
+ function JsvPlayerPluginEvent(data){
169
+ console.log("LoadPlugin2 result: "+data);
170
+ let obj = JSON.parse(data);
171
+ let event_obj = JSON.parse(obj.param);
172
+ if(event_obj.hasOwnProperty("status")){
173
+ let status = event_obj.status;
174
+ let notify_obj = {};
175
+ switch(status){
176
+ case PLUGIN_EVENT_STATUS_START_LOAD:
177
+ {
178
+ let code = 1;
179
+ if(event_obj.hasOwnProperty("code")){
180
+ code = event_obj.code;
181
+ }
182
+ notify_obj.status = 1;
183
+ notify_obj.code = code;
184
+ if(code === 1){
185
+ pluginLoadState = 3;
186
+ }else{
187
+ pluginLoadState = 2;
188
+ }
189
+ }
190
+ break;
191
+ case PLUGIN_EVENT_STATUS_DOWNLOAD:
192
+ notify_obj.status = 2;
193
+ notify_obj.code = 1;
194
+ notify_obj.progress = 100;
195
+ break;
196
+ case PLUGIN_EVENT_STATUS_UNZIPED:
197
+ notify_obj.status = 2;
198
+ notify_obj.code = 2;
199
+ break;
200
+ case PLUGIN_EVENT_STATUS_DEXLOADED:
201
+ notify_obj.status = 2;
202
+ notify_obj.code = 3;
203
+ break;
204
+ case PLUGIN_EVENT_STATUS_COMPLETE:
205
+ {
206
+ let code = 0;
207
+ if(event_obj.hasOwnProperty("code")){
208
+ code = event_obj.code;
209
+ }
210
+ if(code === 0){
211
+ notify_obj.status = 3;
212
+ notify_obj.code = 0;
213
+ pluginLoadState = 4;
214
+ }else{
215
+ notify_obj.status = 4;
216
+ notify_obj.code = code;
217
+ pluginLoadState = 5;
218
+ }
219
+ UnregisterJsvPlayerPluginEvent();
220
+ }
221
+ break;
222
+ default:
223
+ logWarning("Load plugin status, invalid status: "+status)
224
+ return;
225
+ }
226
+ for(let i=0; i<pluginLoadListener.length; i++){
227
+ pluginLoadListener[i](notify_obj);
228
+ }
229
+ if(pluginLoadState === 4){
230
+ let capabilitySet = getJsvPlayerCapabilitySet();
231
+ if(capabilitySet !== null && capabilitySet !== ""){
232
+ let capabilitySetObj = JSON.parse(capabilitySet);
233
+ if(capabilitySetObj !== null && capabilitySetObj.hasOwnProperty("chipType")){
234
+ chipType = capabilitySetObj.chipType;
235
+ }
236
+ }
237
+ for(let i=0; i<mediaArray.length; i++){
238
+ mediaArray[i].buildPlatformInstance();
239
+ }
240
+ }
241
+ }else{
242
+ let type = event_obj.type;
243
+ let param = event_obj.param;
244
+ if(type === 1){
245
+ JsvPlayerPluginStatus(param)
246
+ }else if(type === 2){
247
+ JsvPlayerPluginLoadResult(param);
248
+ }else{
249
+ logError("Invalid type: "+type);
250
+ }
251
+ }
252
+ }
253
+
254
+ function RegisterJsvPlayerPluginEvent(){
255
+ window.JMD.subscribe(PluginEventKey, JsvPlayerPluginEvent);
256
+ }
257
+
258
+ function UnregisterJsvPlayerPluginEvent(){
259
+ window.JMD.unsubscribe(PluginEventKey, JsvPlayerPluginEvent);
260
+ }
261
+
262
+ /**
263
+ * listener回调处理中参数信息的说明:
264
+ * 插件加载状态回调。
265
+ * 回调函数的参数定义如下:
266
+ * object结构,包含status和code两个变量:
267
+ * 1)开始加载插件:
268
+ * obj.status=1;
269
+ * obj.code表示是否是首次加载:1:首次加载,此时插件需要经历下载、解压等过程,用时较长,可以考虑给用户相关提示;
270
+ * 2:非首次加载,此时插件加载过程很短,可以不用出现用户提示界面。
271
+ * 2)插件加载中,加载新插件时上报此状态完整状态,加载旧插件时,只上报dexload完成状态(code=3):
272
+ * obj.status=2;
273
+ * obj.code表示加载过程中的状态:1:插件下载进度,目前只上报下载结束;2:插件解压完成;3:插件dexload完成。
274
+ * obj.progress:当code=1时(下载进度),progress为实际下载进度,百分制,目前只有100(100%,完成状态)。
275
+ * 3)插件加载成功
276
+ * obj.status=3;
277
+ * obj.code无效。
278
+ * 4)插件加载失败
279
+ * obj.status=4;
280
+ * obj.code表示插件加载失败原因:1:插件管理模块不存在(未真正开始加载插件),下面的负值为插件管理模块返回的错误;
281
+ * -1:请求插件加载的参数不正确,需要确认构造的PluginInfo内容;
282
+ * -2:未找到插件更新链接;
283
+ * -3:插件HTTP请求失败;
284
+ * -4:插件下载失败;
285
+ * -5:插件MD5校验失败;
286
+ * -6:解压失败;
287
+ * -7:文件大小为0;
288
+ * -8:未找到dex文件;
289
+ * -9:dex文件load失败;
290
+ * -10:插件初始化失败;
291
+ * -11:取消插件下载;
292
+ * -12:版本检查失败,比如已经加载了其他版本,此版本不能再加载。
293
+ *
294
+ * 备注:不管插件加载处于什么状态,都可以正常使用播放器组件,播放器对象在插件未加载完成的情况下,会把相关状态保存,等完成加载后再自动下发。
295
+ */
296
+ function globalLoadJsvPlayerPlugin(listener){
297
+ logDebug("globalLoadJsvPlayerPlugin");
298
+ let notify_obj = {};
299
+ if(typeof window.jPluginManagerBridge==='undefined' || !window.jPluginManagerBridge){
300
+ notify_obj.status = 4;
301
+ notify_obj.code = 1;
302
+ }else if(pluginLoadState === 2){
303
+ notify_obj.status = 1;
304
+ notify_obj.code = 2;
305
+ }else if(pluginLoadState === 3){
306
+ notify_obj.status = 1;
307
+ notify_obj.code = 1;
308
+ }else if(pluginLoadState === 4){
309
+ notify_obj.status = 3;
310
+ notify_obj.code = 0;
311
+ }
312
+
313
+ if(notify_obj.hasOwnProperty("status")){
314
+ if(typeof listener !== "undefined" && listener){
315
+ setTimeout(()=>{listener(notify_obj)}, 0);
316
+ }
317
+ }
318
+
319
+ if(pluginLoadState === 4 || typeof window.jPluginManagerBridge==='undefined' || !window.jPluginManagerBridge){
320
+ return;
321
+ }else if(pluginLoadState === 5){
322
+ pluginLoadState = 0;
323
+ }
324
+
325
+ if(typeof listener !== "undefined" && listener){
326
+ pluginLoadListener.push(listener);
327
+ }
328
+
329
+ if(pluginLoadState > 0){
330
+ return;
331
+ }
332
+ pluginLoadState = 1;
333
+
334
+ RegisterJsvPlayerPluginEvent();
335
+
336
+ if(typeof window.jPluginManagerBridge.LoadPlugin2 !== "undefined"){
337
+ window.jPluginManagerBridge.LoadPlugin2(PluginEventKey, JSON.stringify(MediaPluginInfo));
338
+ }else{
339
+ window.jPluginManagerBridge.LoadPlugin(JSON.stringify(MediaPluginInfo));
340
+ }
341
+ }
342
+
343
+ var preLoadingJsvPlayerPlugin = 0;
344
+ var prePluginLoadListener = [];
345
+ var PreLoadPluginEventKey = "PreJsvPlayer";
346
+
347
+ function JsvPlayerPrePluginEvent(data){
348
+ console.log("PreLoadPlugin result: "+data);
349
+ let obj = JSON.parse(data);
350
+ let event_obj = JSON.parse(obj.param);
351
+ if(event_obj.hasOwnProperty("status")){
352
+ let status = event_obj.status;
353
+ let notify_obj = {};
354
+ switch(status){
355
+ case PLUGIN_EVENT_STATUS_START_LOAD:
356
+ {
357
+ notify_obj.status = 1;
358
+ notify_obj.code = 0
359
+ }
360
+ break;
361
+ case PLUGIN_EVENT_STATUS_DOWNLOAD:
362
+ notify_obj.status = 2;
363
+ notify_obj.code = 1;
364
+ notify_obj.progress = 100;
365
+ break;
366
+ case PLUGIN_EVENT_STATUS_UNZIPED:
367
+ notify_obj.status = 2;
368
+ notify_obj.code = 2;
369
+ break;
370
+ case PLUGIN_EVENT_STATUS_COMPLETE:
371
+ {
372
+ let code = 0;
373
+ if(event_obj.hasOwnProperty("code")){
374
+ code = event_obj.code;
375
+ }
376
+ if(code === 0){
377
+ notify_obj.status = 3;
378
+ notify_obj.code = 0;
379
+ }else{
380
+ notify_obj.status = 4;
381
+ notify_obj.code = code;
382
+ }
383
+ UnregisterPreLoadJsvPlayerPluginEvent();
384
+ }
385
+ break;
386
+ default:
387
+ logWarning("Load plugin status, invalid status: "+status)
388
+ return;
389
+ }
390
+ for(let i=0; i<prePluginLoadListener.length; i++){
391
+ prePluginLoadListener[i](notify_obj);
392
+ }
393
+ }
394
+ }
395
+
396
+ function RegisterPreLoadJsvPlayerPluginEvent(){
397
+ window.JMD.subscribe(PreLoadPluginEventKey, JsvPlayerPrePluginEvent);
398
+ }
399
+
400
+ function UnregisterPreLoadJsvPlayerPluginEvent(){
401
+ window.JMD.unsubscribe(PreLoadPluginEventKey, JsvPlayerPrePluginEvent);
402
+ }
403
+
404
+ /**
405
+ * listener回调处理中参数信息的说明:
406
+ * 插件加载状态回调。
407
+ * 回调函数的参数定义如下:
408
+ * object结构,包含status和code两个变量:
409
+ * 1)开始预加载插件:
410
+ * obj.status=1;
411
+ * obj.code=0,未使用。
412
+ * 2)插件预下载中:
413
+ * obj.status=2;
414
+ * obj.code表示加载过程中的状态:1:插件下载进度,目前只上报下载结束;2:插件解压完成。
415
+ * obj.progress:当code=1时(下载进度),progress为实际下载进度,百分制,目前只有100(100%,完成状态)。
416
+ * 3)插件预下载成功
417
+ * obj.status=3;
418
+ * obj.code表示是否新下载插件:1:新预下载插件。
419
+ * 2:插件已下载成功,本次完成解压动作。
420
+ * 3:插件已存在。
421
+ * 4)插件预加载失败
422
+ * obj.status=4;
423
+ * obj.code表示插件加载失败原因:1:插件管理模块不存在(未真正开始预加载插件),下面的负值为插件管理模块返回的错误;
424
+ * 2:已经预加载了一个插件,不允许预加载第二次,即使版本不相同;
425
+ * 3:本地已经存在了此版本的插件;
426
+ * -1:请求插件加载的参数不正确;
427
+ * -2:未找到插件更新链接;
428
+ * -3:插件HTTP请求失败;
429
+ * -4:插件下载失败;
430
+ * -5:插件MD5校验失败;
431
+ * -6:解压失败;
432
+ * -7:文件大小为0;
433
+ * -8:未找到dex文件;
434
+ *
435
+ * @param {Number} versionCode 插件版本号
436
+ * @param {String} url 插件下载链接,为空时自动构造下载链接
437
+ * @param {String} md5 插件文件的md5值
438
+ * @param {listener} 状态监听函数
439
+ * @returns
440
+ */
441
+ function globalPreLoadJsvPlayerPlugin(versionCode, url, md5, listener){
442
+ logDebug("globaPrelLoadJsvPlayerPlugin");
443
+ let notify_obj = {};
444
+ if(preLoadingJsvPlayerPlugin !== 0){
445
+ /**已经预加载了同一个插件,不允许第二次预加载 */
446
+ notify_obj.status = 4;
447
+ notify_obj.code = 2;
448
+ }else if(typeof versionCode !== "number" || versionCode <= 0){
449
+ notify_obj.status = 4;
450
+ notify_obj.code = -1;
451
+ }else if(typeof window.jPluginManagerBridge==='undefined' || !window.jPluginManagerBridge || typeof window.jPluginManagerBridge.PreLoadPlugin !== "function"){
452
+ notify_obj.status = 4;
453
+ notify_obj.code = 1;
454
+ }
455
+
456
+ if(notify_obj.hasOwnProperty("status")){
457
+ if(typeof listener !== "undefined" && listener){
458
+ setTimeout(()=>{listener(notify_obj)}, 0);
459
+ }
460
+ return;
461
+ }
462
+
463
+ let plugin_info = {};
464
+ plugin_info.name = "播放器插件";
465
+ plugin_info.packageName = MediaPluginInfo.packageName;
466
+ plugin_info.versionCode = versionCode;
467
+ if(typeof url === "string" && url !== ""){
468
+ plugin_info.downloadUrl = url;
469
+ }
470
+
471
+ if(typeof md5 === "string" && md5 !== ""){
472
+ plugin_info.md5 = md5;
473
+ }
474
+
475
+ let ret = window.jPluginManagerBridge.PreLoadPlugin(PreLoadPluginEventKey, JSON.stringify(plugin_info));
476
+ if(ret === -1){
477
+ /**参数错误,无法加载插件 */
478
+ notify_obj.status = 4;
479
+ notify_obj.code = -1;
480
+ }else if(ret === -2){
481
+ /**加载了一个不同版本的插件,无法加载此插件 */
482
+ notify_obj.status = 4;
483
+ notify_obj.code = 2;
484
+ }else if(ret === 1){
485
+ /**加载了一个相同版本的插件,不再通知到此处 */
486
+ notify_obj.status = 4;
487
+ notify_obj.code = 2;
488
+ }else if(ret === 2){
489
+ /**已经存在了此版本的插件 */
490
+ notify_obj.status = 4;
491
+ notify_obj.code = 3;
492
+ }
493
+
494
+ if(notify_obj.hasOwnProperty("status")){
495
+ if(typeof listener !== "undefined" && listener){
496
+ setTimeout(()=>{listener(notify_obj)}, 0);
497
+ }
498
+ }else{
499
+ if(typeof listener !== "undefined" && listener){
500
+ prePluginLoadListener.push(listener);
501
+ }
502
+ preLoadingJsvPlayerPlugin = 1;
503
+ RegisterPreLoadJsvPlayerPluginEvent();
504
+ }
505
+ }
506
+
507
+ /**
508
+ * 根据key查询是否已经有Media对象了,如果已经有了,就不需要再创建,而是调用setRef接口将当前的对象索引+1。
509
+ * @param {string} key Player索引。
510
+ * @returns {object} Media对象。
511
+ */
512
+ function findMediaObjectByKey(key){
513
+ for(var i=0; i<mediaArray.length; i++){
514
+ if(mediaArray[i].key === key){
515
+ return mediaArray[i];
516
+ }
517
+ }
518
+
519
+ return null;
520
+ }
521
+
522
+ class JsvBaseMedia {
523
+ constructor(type, window_mode, hole_id, player_type, key, background, design_map_width, decode_type) {
524
+ logTrace("Create JsvBaseMedia, type="+type+", hole_id="+hole_id+", player_type="+player_type+", key="+key+", background="+background+", design_map_width="+design_map_width+", decode_type="+decode_type);
525
+
526
+ this.state = {
527
+ muted: false,
528
+ paused: true,
529
+ repeat: false,
530
+ enablePlayer: false,
531
+ autoplay: false,
532
+ startTime: 0.0,
533
+ currentTime: 0.0,
534
+ aspectRatio: "origin",
535
+ keepLastFrame: true,
536
+ timeUpdateLess: false,
537
+ rate: 1.0,
538
+ volume: 1.0,
539
+ chromaKey: null,
540
+ audioTrack: -1,
541
+ };
542
+
543
+ this.local = {
544
+ currentTime: 0.0,
545
+ playableDuration: 0.0,
546
+ duration: 0.0,
547
+ isRenderable: false,
548
+ paused: true,
549
+ };
550
+
551
+ this.type = type;
552
+ this.playerCreate = false;
553
+ this.key = key;
554
+ this.windowMode = window_mode;
555
+ this.background = background;
556
+ this.holeId = hole_id;
557
+ this.holeIdModify = hole_id;
558
+ this.playerType = player_type;
559
+ this.designMapWidth = design_map_width;
560
+ this.decodeType = decode_type;
561
+ this.channelID = -1;
562
+ this.ref = 1;
563
+ this.appVisible = window.JsView&&window.JsView.getVisibility?(window.JsView.getVisibility()==="show"):true;
564
+ this.eventReport = true;
565
+ this.currentEventStatus = EVENT_STATUS_NONE;
566
+ this.frameRateLimit = false;
567
+ this._onEvent = this.onEvent.bind(this);
568
+ this._onVisibilityChangeCallBack = this.onVisibilityChangeCallBack.bind(this);
569
+
570
+ let found = false;
571
+ for(let i=0; i<mediaArray.length; i++){
572
+ if(mediaArray[i].key === this.key){
573
+ found = true;
574
+ break;
575
+ }
576
+ }
577
+
578
+ if(!found){
579
+ mediaArray.push(this)
580
+ }
581
+
582
+ if(typeof window.jsvPlayerBridge=='undefined' || !window.jsvPlayerBridge){
583
+ globalLoadJsvPlayerPlugin();
584
+ }else{
585
+ this.buildPlatformInstance();
586
+ }
587
+ }
588
+
589
+ /**
590
+ * 私有接口,外部不需要调用此接口。
591
+ */
592
+ buildPlatformInstance() {
593
+ logTrace("buildPlatformInstance, key="+this.key);
594
+
595
+ if(typeof window.jsvPlayerBridge=='undefined' || !window.jsvPlayerBridge){
596
+ logError("no jsvPlayerBridge");
597
+ return;
598
+ }
599
+
600
+ let share_view = true;
601
+
602
+ window.jsvPlayerBridge.CreatePlayer2(this.key, this.windowMode, this.holeId, this.background, this.designMapWidth, share_view, this.playerType, this.decodeType).then(
603
+ result=>{
604
+ logDebug("CreatePlayerResult: "+result);
605
+ let result_obj = JSON.parse(result);
606
+ if(result_obj.code == 0){
607
+ //当播放器释放后,不需要进一步进行初始化,所以这里做了查找过程,没有直接调用initPlayer接口。
608
+ for(var i=0; i<mediaArray.length; i++){
609
+ if(mediaArray[i].key === result_obj.key){
610
+ mediaArray[i].initPlayer();
611
+ break;
612
+ }
613
+ }
614
+ }else{
615
+ logError("Create player failed, key="+result_obj.key);
616
+ }
617
+ }, data=>{
618
+ logError("Create player failed, reject("+data+")");
619
+ }
620
+ );
621
+ }
622
+
623
+ /**
624
+ * 私有接口,外部不需要调用此接口。
625
+ */
626
+ initPlayer(){
627
+ if(this.playerCreate)
628
+ return;
629
+
630
+ logDebug("InitPlayer:1, key="+this.key);
631
+
632
+ this.playerCreate = true;
633
+
634
+ window.JMD.subscribe(this.key, this._onEvent);
635
+ if (window.JsView && window.JsView.onVisibilityChange) {
636
+ logDebug("playerKey: "+this.key+", onVisibilityChange register");
637
+ window.JsView.onVisibilityChange(this._onVisibilityChangeCallBack);
638
+ }
639
+
640
+ if(this.holeIdModify !== this.holeId){
641
+ window.jsvPlayerBridge.setHoleID(this.key, this.holeIdModify);
642
+ this.holeId = this.holeIdModify;
643
+ }
644
+
645
+ this.appVisible = window.JsView&&window.JsView.getVisibility?(window.JsView.getVisibility()==="show"):true;
646
+
647
+ if(this.appVisible){
648
+ this.initParams();
649
+ }
650
+ }
651
+
652
+ initParams(){
653
+ logDebug("InitPlayer:2, key="+this.key);
654
+
655
+ if(this.channelID >= 0){
656
+ this.joinChannelPrivate(this.channelID);
657
+ }else if(this.state["src"]){
658
+ this.setState("src", this.state["src"], "string");
659
+ if(this.state["currentTime"]){
660
+ this.setState("currentTime", this.state["currentTime"], "number");
661
+ }else if(this.state["startTime"]){
662
+ this.setState("startTime", this.state["startTime"], "number");
663
+ }
664
+ }
665
+
666
+ if(this.state["paused"] == false){
667
+ this.setState("paused", this.state["paused"], "boolean");
668
+ }
669
+
670
+ if(this.state["autoplay"]){
671
+ this.setState("autoplay", this.state["autoplay"], "boolean");
672
+ }
673
+
674
+ if(this.state["repeat"]){
675
+ this.setState("repeat", this.state["repeat"], "boolean");
676
+ }
677
+
678
+ if(this.state["muted"]){
679
+ this.setState("muted", this.state["muted"], "boolean");
680
+ }
681
+
682
+ if(this.state["timeUpdateLess"]){
683
+ this.setState("timeUpdateLess", this.state["timeUpdateLess"], "boolean");
684
+ }
685
+
686
+ if(this.state["keepLastFrame"] == false){
687
+ this.setState("keepLastFrame", this.state["keepLastFrame"], "boolean");
688
+ }
689
+
690
+ if(this.state["aspectRatio"] !== "origin"){
691
+ this.setState("aspectRatio", this.state["aspectRatio"], "string");
692
+ }
693
+
694
+ if(this.state["chromaKey"]){
695
+ this.setState("chromaKey", this.state["chromaKey"], "string");
696
+ }
697
+
698
+ if(this.state["audioTrack"] !== -1){
699
+ this.setState("audioTrack", this.state["audioTrack"], "number");
700
+ }
701
+ }
702
+
703
+ onVisibilityChangeCallBack(){
704
+ let visible = window.JsView&&window.JsView.getVisibility?(window.JsView.getVisibility()==="show"):true;
705
+
706
+ this.setVisibility(visible);
707
+ }
708
+
709
+ /**
710
+ * 设置可见状态,在可见状态发生变化时,释放或者启动流。
711
+ * @param {boolean} visible true:可见,false,不可见。
712
+ */
713
+ setVisibility(visible){
714
+ logDebug("playerKey:"+this.key+", 小程序可见状态: "+visible);
715
+
716
+ if(typeof visible !== "boolean"){
717
+ logError("playerKey:"+this.key+", setVisibility, param type is invalid");
718
+ return;
719
+ }
720
+
721
+ if(visible === this.appVisible){
722
+ logDebug("playerKey:"+this.key+", 小程序可见状态未发生变化,不执行动作");
723
+ return;
724
+ }
725
+
726
+ if(visible){
727
+ this.appVisible = visible;
728
+ this.state.paused = this.local.paused;
729
+ this.state.currentTime = this.local.currentTime;
730
+ logDebug("currentTime: "+this.state.currentTime);
731
+ this.initParams();
732
+ }else{
733
+ logDebug("playerKey:"+this.key+", playerCreate: "+this.playerCreate+", channelID: "+this.channelID+", src: "+this.state["src"]);
734
+ if(this.playerCreate){
735
+ this.eventReport = false;
736
+ if(this.channelID > 0){
737
+ logDebug("leaveChannel");
738
+ window.jsvPlayerBridge.leaveChannel(this.key);
739
+ }else if(this.state["src"]){
740
+ logDebug("unload");
741
+ this.local.currentTime = this.currentTime;
742
+ this.local.paused = this.paused;
743
+ logDebug("currentTime: "+this.local.currentTime);
744
+ this.unloadPrivate();
745
+ }
746
+ }
747
+ this.appVisible = visible;
748
+ }
749
+ }
750
+
751
+ /**
752
+ * 当使用一个已有的Media对象时,需要通过这个接口追加一个ref,在调用releasePlayer接口释放时,会ref--,当ref==0才真正释放播放器实例。
753
+ */
754
+ setRef(){
755
+ this.ref++;
756
+ }
757
+
758
+ /**
759
+ * 释放播放器,一般不需要应用逻辑调用,在JsvPlayer高阶组件unmounted处理时调用此接口释放。
760
+ */
761
+ releasePlayer(){
762
+ logTrace("releasePlayer, key="+this.key+", ref="+this.ref);
763
+ this.ref--;
764
+ if(this.ref === 0){
765
+ if(typeof window.jsvPlayerBridge != "undefined" && window.jsvPlayerBridge){
766
+ this.changeFrameRate(false);
767
+ window.JMD.unsubscribe(this.key, this._onEvent);
768
+ window.jsvPlayerBridge.ReleasePlayer(this.key);
769
+ if (window.JsView && window.JsView.removeEventCallback) {
770
+ logDebug("playerKey: "+this.key+", onVisibilityChange unregister");
771
+ window.JsView.removeEventCallback(this._onVisibilityChangeCallBack);
772
+ }
773
+ }
774
+
775
+ for(let i=0; i<mediaArray.length; i++){
776
+ if(mediaArray[i].key === this.key){
777
+ mediaArray.splice(i, 1);
778
+ break;
779
+ }
780
+ }
781
+ }
782
+ }
783
+
784
+ setHoleID(hole_id){
785
+ logTrace("setHoleID, key="+this.key+", hole_id="+hole_id);
786
+ if(this.playerCreate){
787
+ this.holeId = hole_id;
788
+ this.holeIdModify = hole_id;
789
+ window.jsvPlayerBridge.setHoleID(this.key, hole_id);
790
+ }else{
791
+ this.holeIdModify = hole_id;
792
+ }
793
+ }
794
+
795
+ /**
796
+ * 当full模式且播放器模式是2(jsvplayer),如果是H2芯片,需要修改动画帧率到30帧,否则会导致播放器音画不同步。
797
+ * @param {boolean} enable 开关,视频起播时打开;视频停止,或者播放器释放时,关闭。
798
+ */
799
+ changeFrameRate(enable){
800
+ if(this.windowMode === "full" && this.playerType === 2 && chipType === "allwinnerh2"){
801
+ if(this.frameRateLimit != enable){
802
+ logDebug("changeFrameRate, key="+this.key+", enable="+enable);
803
+ this.frameRateLimit = enable;
804
+ if(enable){
805
+ window.JsView?.reduceFps?.(30);
806
+ }else{
807
+ window.JsView?.reduceFps?.(0);
808
+ }
809
+ }
810
+ }
811
+ }
812
+
813
+ needReportEvent(event){
814
+ let ret = true;
815
+ if(!this.eventReport){
816
+ ret = false;
817
+ switch(this.currentEventStatus){
818
+ case EVENT_STATUS_NONE:
819
+ this.eventReport = true;
820
+ ret = true;
821
+ break;
822
+ case EVENT_STATUS_LOADSTART:
823
+ if(event == EVENT_STATUS_LOADSTART || event == EVENT_STATUS_LOAD || event == EVENT_STATUS_DISPLAY || event == EVENT_STATUS_BACKLIVED || event == EVENT_STATUS_TIMESHIFTED){
824
+ this.eventReport = true;
825
+ }
826
+ if(event == EVENT_STATUS_LOADSTART){
827
+ ret = false;
828
+ }else{
829
+ ret = true;
830
+ }
831
+ break;
832
+ case EVENT_STATUS_LOAD:
833
+ if(event == EVENT_STATUS_LOAD || event == EVENT_STATUS_DISPLAY || event == EVENT_STATUS_BACKLIVED || event == EVENT_STATUS_TIMESHIFTED){
834
+ this.eventReport = true;
835
+ }
836
+ if(event == EVENT_STATUS_LOADSTART || event == EVENT_STATUS_LOAD){
837
+ ret = false;
838
+ }else{
839
+ ret = true;
840
+ }
841
+ break;
842
+ case EVENT_STATUS_DISPLAY:
843
+ if(event == EVENT_STATUS_DISPLAY || event == EVENT_STATUS_BACKLIVED || event == EVENT_STATUS_TIMESHIFTED){
844
+ this.eventReport = true;
845
+ }
846
+ if(event != EVENT_STATUS_END){
847
+ ret = false;
848
+ }else{
849
+ ret = true;
850
+ }
851
+ break;
852
+ case EVENT_STATUS_TIMESHIFT:
853
+ if(event == EVENT_STATUS_TIMESHIFT || event == EVENT_STATUS_TIMESHIFTED || event == EVENT_STATUS_BACKLIVE || event == EVENT_STATUS_BACKLIVED || event == EVENT_STATUS_DISPLAY){
854
+ this.eventReport = true;
855
+ }
856
+ if(event == EVENT_STATUS_TIMESHIFT){
857
+ ret = false;
858
+ }else{
859
+ ret = true;
860
+ }
861
+ break;
862
+ case EVENT_STATUS_TIMESHIFTED:
863
+ if(event == EVENT_STATUS_TIMESHIFTED || event == EVENT_STATUS_BACKLIVE || event == EVENT_STATUS_BACKLIVED || event == EVENT_STATUS_DISPLAY){
864
+ this.eventReport = true;
865
+ }
866
+ if(event == EVENT_STATUS_TIMESHIFT || event == EVENT_STATUS_TIMESHIFTED){
867
+ ret = false;
868
+ }else{
869
+ ret = true;
870
+ }
871
+ break;
872
+ case EVENT_STATUS_BACKLIVE:
873
+ if(event == EVENT_STATUS_TIMESHIFT || event == EVENT_STATUS_TIMESHIFTED || event == EVENT_STATUS_BACKLIVE || event == EVENT_STATUS_BACKLIVED || event == EVENT_STATUS_DISPLAY){
874
+ this.eventReport = true;
875
+ }
876
+ if(event == EVENT_STATUS_BACKLIVE){
877
+ ret = false;
878
+ }else{
879
+ ret = true;
880
+ }
881
+ break;
882
+ case EVENT_STATUS_BACKLIVED:
883
+ if(event == EVENT_STATUS_TIMESHIFTED || event == EVENT_STATUS_TIMESHIFT || event == EVENT_STATUS_BACKLIVED || event == EVENT_STATUS_DISPLAY){
884
+ this.eventReport = true;
885
+ }
886
+ if(event == EVENT_STATUS_BACKLIVE || event == EVENT_STATUS_BACKLIVED){
887
+ ret = false;
888
+ }else{
889
+ ret = true;
890
+ }
891
+ break;
892
+ case EVENT_STATUS_END:
893
+ this.eventReport = true;
894
+ ret = true;
895
+ break;
896
+ default:
897
+ logWarning("current event status is "+this.currentEventStatus);
898
+ this.eventReport = true;
899
+ ret = true;
900
+ break;
901
+ }
902
+
903
+ logTrace("eventReport:"+this.eventReport+", ret="+ret);
904
+ }
905
+
906
+ return ret;
907
+ }
908
+
909
+ /**
910
+ * 私有接口,外部不需要调用此接口。
911
+ */
912
+ onEvent(event_str){
913
+ logTrace("player event: "+event_str);
914
+ let obj = JSON.parse(event_str);
915
+ let event_obj = JSON.parse(obj.param);
916
+ let event = event_obj.event;
917
+ let data = event_obj.data;
918
+ switch(event){
919
+ case "onProgress":
920
+ {
921
+ // logDebug("onProgress:"+data);
922
+ if (this.local.isRenderable == false) {
923
+ return;
924
+ }
925
+
926
+ let time_update = this.local.currentTime != data.currentTime;
927
+ this.local.currentTime = data.currentTime;
928
+ if (time_update && this.hasOwnProperty("ontimeupdate")) {
929
+ this["ontimeupdate"](data.currentTime);
930
+ }
931
+
932
+ let progress_update = this.local.playableDuration != data.playableDuration;
933
+ this.local.playableDuration = data.playableDuration;
934
+ if (progress_update && this.hasOwnProperty("onprogress")) {
935
+ this["onprogress"]();
936
+ }
937
+
938
+ let canplay_through = this.local.playableDuration == this.local.duration;
939
+ if (canplay_through && progress_update && this.hasOwnProperty("oncanplaythrough")) {
940
+ this["oncanplaythrough"](); // only called one time
941
+ }
942
+ }
943
+ break;
944
+ case "onEnd":
945
+ if(this.needReportEvent(EVENT_STATUS_END)){
946
+ this.local.isRenderable = false;
947
+ this.setState("paused", true, "boolean");
948
+ if(this.hasOwnProperty("onend")){
949
+ this["onend"]();
950
+ }
951
+ this.currentEventStatus = EVENT_STATUS_END;
952
+ }
953
+ break;
954
+ case "onLoadStart":
955
+ logDebug("onLoadStart:"+data);
956
+ if(this.needReportEvent(EVENT_STATUS_LOADSTART)){
957
+ if(this.hasOwnProperty("onloadstart")){
958
+ this["onloadstart"]();
959
+ }
960
+ this.currentEventStatus = EVENT_STATUS_LOADSTART;
961
+ }
962
+ break;
963
+ case "onLoad":
964
+ logDebug("onLoad:"+data);
965
+ if(this.needReportEvent(EVENT_STATUS_LOAD)){
966
+ this.local.currentTime = data.currentTime;
967
+ this.local.duration = data.duration;
968
+
969
+ if (this.hasOwnProperty("onloadedmetadata")) {
970
+ this["onloadedmetadata"]();
971
+ }
972
+
973
+ if (this.hasOwnProperty("onload")) {
974
+ this["onload"]();
975
+ }
976
+
977
+ if (this.hasOwnProperty("ondurationchange")) {
978
+ this["ondurationchange"]();
979
+ }
980
+ this.currentEventStatus = EVENT_STATUS_LOAD;
981
+ }
982
+ break;
983
+ case "onError":
984
+ logDebug("onError:"+data);
985
+ this.local.isRenderable = false;
986
+ if(this.hasOwnProperty("onerror")){
987
+ const Error = {
988
+ MEDIA_ERR_ABORTED: 1,
989
+ MEDIA_ERR_NETWORK: 2,
990
+ MEDIA_ERR_DECODE: 3,
991
+ MEDIA_ERR_SRC_NOT_SUPPORTED: 4,
992
+ MEDIA_ERR_ONLY_ONE_4K: 5,
993
+ MEDIA_ERR_NO_DECODE_RESOURCE: 6,
994
+ };
995
+ const platform_error = data.error.what;
996
+ let e = Error.MEDIA_ERR_ABORTED;
997
+ switch (platform_error) {
998
+ case -1004 : // MediaPlayer.MEDIA_ERROR_IO
999
+ e = Error.MEDIA_ERR_NETWORK;
1000
+ break;
1001
+ case -1007 : // MediaPlayer.MEDIA_ERROR_MALFORMED
1002
+ e = Error.MEDIA_ERR_DECODE;
1003
+ break;
1004
+ case -1010 : // MediaPlayer.MEDIA_ERROR_UNSUPPORTED
1005
+ e = Error.MEDIA_ERR_SRC_NOT_SUPPORTED;
1006
+ break;
1007
+ case -50001:
1008
+ e = Error.MEDIA_ERR_ONLY_ONE_4K;
1009
+ break;
1010
+ case -50002:
1011
+ e = Error.MEDIA_ERR_NO_DECODE_RESOURCE;
1012
+ break;
1013
+ default:
1014
+ break;
1015
+ }
1016
+ this["onerror"](e);
1017
+ }
1018
+ break;
1019
+ case "onSeek":
1020
+ logDebug("onSeek:"+data);
1021
+ if(this.needReportEvent(EVENT_STATUS_SEEK)){
1022
+ this.local.isRenderable = false;
1023
+ if(this.hasOwnProperty("onseeking")){
1024
+ this["onseeking"]();
1025
+ }
1026
+ }
1027
+ break;
1028
+ case "onEventExt":
1029
+ logDebug("onEventExt:"+data);
1030
+ switch (data.eventExt) {
1031
+ case "videoMetadataUpdate" :
1032
+ if (this.hasOwnProperty("onloadedmetadata")) {
1033
+ this["onloadedmetadata"]();
1034
+ }
1035
+ break;
1036
+ case "videoSeekComplete" :
1037
+ if(this.needReportEvent(EVENT_STATUS_SEEKED)){
1038
+ //this.local.isRenderable = true; // waiting until BUFFERING END
1039
+ if (this.hasOwnProperty("onseeked")) {
1040
+ this["onseeked"]();
1041
+ }
1042
+ }
1043
+ break;
1044
+ default:
1045
+ logWarning("unimplentation event ext type = " + data.eventExt);
1046
+ break;
1047
+ }
1048
+ break;
1049
+ case "onAudioFocusGain":
1050
+ logDebug("onAudioFocusGain:"+data);
1051
+ if(this.hasOwnProperty("onaudiofocusgain")){
1052
+ this["onaudiofocusgain"](data);
1053
+ }
1054
+ break;
1055
+ case "onAudioFocusLoss":
1056
+ logDebug("onAudioFocusLoss:"+data);
1057
+ if(this.hasOwnProperty("onaudiofocusloss")){
1058
+ this["onaudiofocusloss"](data);
1059
+ }
1060
+ break;
1061
+ case "onPlaybackStalled":
1062
+ if(this.needReportEvent(EVENT_STATUS_STALLED)){
1063
+ this.local.isRenderable = false;
1064
+ if(this.hasOwnProperty("onstalled")){
1065
+ this["onstalled"]();
1066
+ }
1067
+ }
1068
+ break;
1069
+ case "onPlaybackResume":
1070
+ if(this.needReportEvent(EVENT_STATUS_RESUME)){
1071
+ this.local.isRenderable = true;
1072
+ if(this.hasOwnProperty("onplaying")){
1073
+ this["onplaying"]();
1074
+ }
1075
+ }
1076
+ break;
1077
+ case "onReadyForDisplay":
1078
+ this.changeFrameRate(true);
1079
+ if(this.needReportEvent(EVENT_STATUS_DISPLAY)){
1080
+ this.local.isRenderable = true;
1081
+ if(this.hasOwnProperty("oncanplay")){
1082
+ this["oncanplay"]();
1083
+ }
1084
+ this.currentEventStatus = EVENT_STATUS_DISPLAY;
1085
+ }
1086
+ break;
1087
+ case "onTimeShift":
1088
+ logDebug("onTimeShift");
1089
+ if(this.needReportEvent(EVENT_STATUS_TIMESHIFT)){
1090
+ if(this.hasOwnProperty("ontimeshift")){
1091
+ this["ontimeshift"](data.seekTime);
1092
+ }
1093
+ this.currentEventStatus = EVENT_STATUS_TIMESHIFT;
1094
+ }
1095
+ break;
1096
+ case "onTimeShifted":
1097
+ logDebug("onTimeShifted");
1098
+ if(this.needReportEvent(EVENT_STATUS_TIMESHIFTED)){
1099
+ if(this.hasOwnProperty("ontimeshifted")){
1100
+ this["ontimeshifted"]();
1101
+ }
1102
+ this.currentEventStatus = EVENT_STATUS_TIMESHIFTED;
1103
+ }
1104
+ break;
1105
+ case "onBackLive":
1106
+ logDebug("onBackLive");
1107
+ if(this.needReportEvent(EVENT_STATUS_BACKLIVE)){
1108
+ if(this.hasOwnProperty("onbacklive")){
1109
+ this["onbacklive"]();
1110
+ }
1111
+ this.currentEventStatus = EVENT_STATUS_BACKLIVE;
1112
+ }
1113
+ break;
1114
+ case "onBackLived":
1115
+ logDebug("onBackLived");
1116
+ if(this.needReportEvent(EVENT_STATUS_BACKLIVED)){
1117
+ if(this.hasOwnProperty("onbacklived")){
1118
+ this["onbacklived"]();
1119
+ }
1120
+ this.currentEventStatus = EVENT_STATUS_BACKLIVED;
1121
+ }
1122
+ break;
1123
+ default:
1124
+ break;
1125
+ }
1126
+ }
1127
+
1128
+ /**
1129
+ * 属性,boolean类型,不支持读取,true表示自动播放。
1130
+ */
1131
+ set autoplay(value) {
1132
+ this.setState("autoplay", value, "boolean");
1133
+ }
1134
+
1135
+ /**
1136
+ * 属性,double类型,当前时间,单位秒,set用于seek操作(起播后)或者设置起播时间(起播前),get用于读取当前时间。
1137
+ */
1138
+ get currentTime() {
1139
+ if(!this.appVisible){
1140
+ return this.local.currentTime;
1141
+ }
1142
+
1143
+ let result = this.getProperty("currentTime");
1144
+ if(result != null){
1145
+ this.local.currentTime = result;
1146
+ return result;
1147
+ }
1148
+ return 0;
1149
+ }
1150
+
1151
+ set currentTime(value) {
1152
+ this.local.isRenderable = false;
1153
+ this.local.currentTime = value;
1154
+ this.setState("currentTime", value, "number");
1155
+ }
1156
+
1157
+ /**
1158
+ * 属性,double类型,总时长,单位秒,只支持读取。
1159
+ */
1160
+ get duration() {
1161
+ if(!this.appVisible){
1162
+ return this.local.duration;
1163
+ }
1164
+
1165
+ let result = this.getProperty("duration");
1166
+ if(result != null)
1167
+ return result;
1168
+
1169
+ return 0;
1170
+ }
1171
+
1172
+ /**
1173
+ * 属性,boolean类型,不支持读取,true表示循环播放。
1174
+ */
1175
+ set loop(value) {
1176
+ if(typeof value == "boolean") {
1177
+ this.setState("repeat", value, "boolean");
1178
+ } else if(typeof value == "undefined") {
1179
+ this.setState("repeat", false, "boolean");
1180
+ } else {
1181
+ this.setState("repeat", true, "boolean"); // html5标准用法, 任何value不为boolean|undefined都会转变为true
1182
+ }
1183
+ }
1184
+
1185
+ /**
1186
+ * 属性,boolean类型,设置和获取静音状态。
1187
+ */
1188
+ get muted() {
1189
+ return this.getState("muted");
1190
+ }
1191
+
1192
+ set muted(value) {
1193
+ this.setState("muted", value, "boolean");
1194
+ }
1195
+
1196
+ /**
1197
+ * 属性,boolean类型,当前pause状态,只支持读取。
1198
+ */
1199
+ get paused() {
1200
+ return this.getState("paused");
1201
+ }
1202
+
1203
+ /**
1204
+ * 属性,float类型,设置或者读取倍速播放,通常的值是0.5、0.75、1.0、1.25、1.5、2.0、3.0。
1205
+ */
1206
+ get playbackRate() {
1207
+ return this.getState("rate");
1208
+ }
1209
+
1210
+ set playbackRate(value) {
1211
+ logDebug("playbackRate")
1212
+ this.setState("rate", value, "number");
1213
+ }
1214
+
1215
+ /**
1216
+ * 已废弃。
1217
+ */
1218
+ get preload() {
1219
+ return (this.enablePlayer ? 'auto' : 'none');
1220
+ }
1221
+
1222
+ set preload(value) {
1223
+ if (value !== 'none') { // preload = 'none' is default
1224
+ this.load();
1225
+ }
1226
+ }
1227
+
1228
+
1229
+ /**
1230
+ * 属性,string类型,播放地址,不支持读取。
1231
+ */
1232
+ set src(value) {
1233
+ this.setSrc(value, null, null, 1)
1234
+ }
1235
+
1236
+ /**
1237
+ * 属性,float类型,播放器音量,0-1.0,只影响当前播放器实例。
1238
+ */
1239
+ get volume() {
1240
+ return this.getState("volume");
1241
+ }
1242
+
1243
+ set volume(value) {
1244
+ this.setState("volume", value, "number");
1245
+ }
1246
+
1247
+ /**
1248
+ * 属性,double类型,起播时间,单位秒,可使用currentTime代替。
1249
+ */
1250
+ get startTime() {
1251
+ return this.getState("startTime");
1252
+ }
1253
+
1254
+ set startTime(value) {
1255
+ this.setState("startTime", value, "number");
1256
+ }
1257
+
1258
+ /**
1259
+ * 属性,double类型,可播放时长,本地缓存的视频时长,只支持读取。
1260
+ */
1261
+ get playableDuration() {
1262
+ return this.local.playableDuration;
1263
+ }
1264
+
1265
+ /**
1266
+ * 属性,boolean类型,true表示关闭timeupdate事件上报。
1267
+ */
1268
+ set timeupdateless(value) {
1269
+ this.setState("timeUpdateLess", !!value, "boolean");
1270
+ }
1271
+
1272
+ /**
1273
+ * 属性,boolean类型,true表示保留最后一帧,false表示不保留。
1274
+ */
1275
+ set keepLastFrame(value) {
1276
+ this.setState("keepLastFrame", !!value, "boolean");
1277
+ }
1278
+
1279
+ /**
1280
+ * 设置播放地址。
1281
+ * @param {string} url 播放地址。
1282
+ * @param {String} windowMode 播放器窗口模式。
1283
+ * null:使用this.windowMode作为窗口模式。
1284
+ * full:观影模式,全屏方式,不建议修改w/h/l/t,视频清晰度/流畅度最佳;
1285
+ * resizable:可变窗口模式,可以随意修改w/h/l/t,支持动画效果,视频清晰度/流畅度表现可能不如full模式;
1286
+ * pip:画中画模式,只在支持多路硬解的情况下使用,用户画中画的小窗播放,对清晰度/流畅度要求较差,可能会有反交错问题。
1287
+ * @param {string} head 网络请求的head信息,可以为NULL。
1288
+ * @param {int} type 类型,1表示点播,2表示直播,3表示时移,4表示回看,默认1。
1289
+ * @param {double} timeShift 时移时间,只有在type=3时才有效,表示从当前时间时移多长时间,单位秒。
1290
+ * @param {int} 分辨率类型 0:unknown或其它;1:标清;2:高清;3:超清(720P);4:蓝光(1080P);5:2K;6:4K;7:8K。
1291
+ * @param {int} 用户频道号,只在直播回看状态下需要设置
1292
+ */
1293
+ setSrc(url, windowMode, head, type, timeShift, resolution, mixNo){
1294
+ let src = {};
1295
+ src.url = url;
1296
+ if(head){
1297
+ src.head = head;
1298
+ }
1299
+ if(windowMode){
1300
+ src.windowMode = windowMode;
1301
+ }
1302
+ if(type){
1303
+ src.type = type;
1304
+ }else{
1305
+ src.type = 1;
1306
+ }
1307
+ if(type === 3 && timeShift){
1308
+ src.timeShift = timeShift;
1309
+ }
1310
+
1311
+ if(resolution && typeof resolution === "number"){
1312
+ src.resolution = resolution;
1313
+ }
1314
+
1315
+ if(mixNo && typeof mixNo == "number"){
1316
+ src.channelID = mixNo;
1317
+ }
1318
+
1319
+ this.currentEventStatus = EVENT_STATUS_NONE;
1320
+ this.setState("src", JSON.stringify(src), "string");
1321
+ this.eventReport = true;
1322
+ }
1323
+
1324
+ /**
1325
+ * 添加监听事件。
1326
+ * @param {string} type 事件类型。
1327
+ * @param {callback} listener 事件处理函数。
1328
+ */
1329
+ addEventListener(type, listener) {
1330
+ this['on' + type] = listener;
1331
+ }
1332
+
1333
+ /**
1334
+ * 重新加载视频流,初始化播放器。
1335
+ */
1336
+ load() {
1337
+ this.setState("enablePlayer", true, "boolean");
1338
+ }
1339
+
1340
+ /**
1341
+ * 暂停
1342
+ */
1343
+ pause() {
1344
+ this.local.paused = true;
1345
+ this.setState("paused", true, "boolean");
1346
+ if (this.hasOwnProperty("onpause")) {
1347
+ this["onpause"]();
1348
+ }
1349
+ }
1350
+
1351
+ /**
1352
+ * 播放
1353
+ */
1354
+ play() {
1355
+ this.local.paused = false;
1356
+ this.setState("paused", false, "boolean");
1357
+ if (this.hasOwnProperty("onplay")) {
1358
+ this["onplay"]();
1359
+ }
1360
+ }
1361
+
1362
+ /**
1363
+ * 获取AudioTrack个数
1364
+ * @returns total number of audio track.
1365
+ */
1366
+ getAudioTrackCount(){
1367
+ let count = this.getProperty("audioTrackCount");
1368
+ if(count === null){
1369
+ return 1;
1370
+ }
1371
+
1372
+ return count;
1373
+ }
1374
+
1375
+ /**
1376
+ * 获取当前使用的audio track
1377
+ * @returns the current playing track,-1 is invalid
1378
+ */
1379
+ getSelectedAudioTrack(){
1380
+ return this.getState("audioTrack");
1381
+ }
1382
+
1383
+ /**
1384
+ * 选择audio track
1385
+ * @param {*} track audio track index
1386
+ */
1387
+ selectAudioTrack(track){
1388
+ this.setState("audioTrack", track, "number");
1389
+ }
1390
+
1391
+ /**
1392
+ * 停止视频流。
1393
+ */
1394
+ unload() {
1395
+ this.unloadPrivate();
1396
+ this.currentEventStatus = EVENT_STATUS_NONE;
1397
+ this.eventReport = true;
1398
+ }
1399
+
1400
+ unloadPrivate(){
1401
+ this.setState("paused", true, "boolean");
1402
+ this.local.isRenderable = false;
1403
+ this.setState("enablePlayer", false, "boolean");
1404
+ this.changeFrameRate(false);
1405
+ }
1406
+
1407
+ /**
1408
+ * 要求终端访问指定的频道,并立即返回。对由本地设置为跳过的频道,也返回-1。
1409
+ * 频道地址为通过 CTCSetConfig 设置的频道列表中的地址:
1410
+ * 如频道地址为 igmp://的组播地址,则加入组播频道,播放器开始播放组播频道,并处理相应的时移等功能;
1411
+ * 如频道地址为 rtsp://的单播地址,则连接单播频道,播放器开始播放;
1412
+ * 如频道地址为 http://的地址,则浏览器直接发起请求,访问该页面。
1413
+ * @param {int} mixNo 用户频道号。
1414
+ * @returns {int} 0,表示成功;-1:表示频道号无效。
1415
+ */
1416
+ joinChannel(mixNo){
1417
+ logTrace("joinChannel, key="+this.key+", mixNo="+mixNo);
1418
+ if(this.type === "audio"){
1419
+ logWarning("Audio player do not support joinChannel.");
1420
+ return 0;
1421
+ }
1422
+
1423
+ let ret = this.joinChannelPrivate(mixNo);
1424
+ if(ret >= 0){
1425
+ this.currentEventStatus = EVENT_STATUS_NONE;
1426
+ this.eventReport = true;
1427
+ }
1428
+ return ret;
1429
+ }
1430
+
1431
+ joinChannelPrivate(mixNo){
1432
+ if(this.type === "audio"){
1433
+ logWarning("Audio player do not support joinChannelPrivate.");
1434
+ return 0;
1435
+ }
1436
+
1437
+ if(mixNo <= 0){
1438
+ return -1;
1439
+ }
1440
+
1441
+ let ret = 0;
1442
+ if(this.playerCreate && this.appVisible){
1443
+ ret = window.jsvPlayerBridge.JoinChannel(this.key, mixNo);
1444
+ }
1445
+
1446
+ if(ret >= 0){
1447
+ this.channelID = mixNo;
1448
+ this.local.paused = false;
1449
+
1450
+ this.setState("paused", false, "boolean");
1451
+ }
1452
+
1453
+ return ret;
1454
+ }
1455
+
1456
+ /**
1457
+ * 要求终端离开指定的频道,并立即返回。
1458
+ * 如原频道地址为 igmp://的组播地址,则立即离开组播频道,播放器停止播放组播频道,并断开相应的时移连接;
1459
+ * 如频道地址为 rtsp://的单播地址,则断开单播频道,播放器停止播放;
1460
+ * 如频道地址为 http://的地址,则浏览器不作操作。
1461
+ * 【注】:本方法只用于离开通过 joinChannel 方法加入的频道。
1462
+ * @returns {int} 0,表示成功;-1:表示频道号无效。
1463
+ */
1464
+ leaveChannel(){
1465
+ logTrace("leaveChannel, key="+this.key+", channelID="+this.channelID);
1466
+ if(this.type === "audio"){
1467
+ logWarning("Audio player do not support leaveChannel.");
1468
+ return 0;
1469
+ }
1470
+
1471
+ let ret = this.leaveChannelPrivate();
1472
+
1473
+ this.currentEventStatus = EVENT_STATUS_NONE;
1474
+ this.eventReport = true;
1475
+ return ret;
1476
+ }
1477
+
1478
+ leaveChannelPrivate(){
1479
+ let ret = 0;
1480
+ if(this.type === "audio"){
1481
+ logWarning("Audio player do not support leaveChannelPrivate.");
1482
+ return ret;
1483
+ }
1484
+
1485
+ if(this.playerCreate && this.appVisible){
1486
+ ret = window.jsvPlayerBridge.leaveChannel(this.key);
1487
+ }
1488
+
1489
+ this.channelID = -1;
1490
+ return ret;
1491
+ }
1492
+
1493
+ // /**
1494
+ // * 快进。
1495
+ // * @param {float} speed 2至32
1496
+ // */
1497
+ // fastForward(value) {
1498
+ // this.setState("fastForward", value, "number");
1499
+ // }
1500
+
1501
+ // /**
1502
+ // * 快退。
1503
+ // * @param {float} speed -2至-32
1504
+ // */
1505
+ // fastRewind(value) {
1506
+ // this.setState("fastForward", value, "number");
1507
+ // }
1508
+
1509
+ /**
1510
+ * 当流停止后,不需要显示最后一帧,调用此接口清除。
1511
+ */
1512
+ clearLastFrame(){
1513
+ logTrace("clearLastFrame, key="+this.key);
1514
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1515
+ window.jsvPlayerBridge.clearLastFrame(this.key);
1516
+ }
1517
+
1518
+ return;
1519
+ }
1520
+ /**
1521
+ * @return {int} 当前音量,0-100。
1522
+ * */
1523
+ getGlobalVolume(){
1524
+ logTrace("getGlobalVolume, key="+this.key);
1525
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1526
+ return window.jsvPlayerBridge.getGlobalVolume(100);
1527
+ }
1528
+
1529
+ return 0;
1530
+ }
1531
+
1532
+ /**
1533
+ * 设置系统音量。
1534
+ * @param {int} volume 0-100,音量值。
1535
+ * @param {int} flags 1表示显示音量调节UI;4表示使用提示音;5表示同时显示音量调节UI和使用提示音。
1536
+ * */
1537
+ setGlobalVolume(volume, flags){
1538
+ logTrace("setGlobalVolume, key="+this.key+", volume="+volume+", flags="+flags);
1539
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1540
+ return window.jsvPlayerBridge.setGlobalVolume(volume, typeof flags!="undefined"?flags:0, 100);
1541
+ }
1542
+ }
1543
+
1544
+ /**
1545
+ * 调整系统音量,一次设置一个步长。
1546
+ * @param {int} direction 1增大音量;-1减小音量。
1547
+ * @param {int} flags FLAG_SHOW_UI(1)表示显示音量调节UI;FLAG_PLAY_SOUND(4)表示使用提示音。两个值可以是或的关系。
1548
+ * */
1549
+ adjustGlobalVolume(direction, flags){
1550
+ logTrace("adjustGlobalVolume, key="+this.key+", direction="+direction+", flags="+flags);
1551
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1552
+ return window.jsvPlayerBridge.adjustGlobalVolume(direction, typeof flags!="undefined"?flags:0);
1553
+ }
1554
+ }
1555
+
1556
+ /**
1557
+ * 设置系统静音状态。
1558
+ * @param {boolean} status true表示静音,false表示取消静音。
1559
+ * @param {int} flags FLAG_SHOW_UI(1)表示显示音量调节UI;FLAG_PLAY_SOUND(4)表示使用提示音。两个值可以是或的关系。android 6.0(包含)以上有效。
1560
+ * */
1561
+ setGlobalMuted(status, flags){
1562
+ logTrace("setGlobalMuted, key="+this.key+", status="+status+", flags="+flags);
1563
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1564
+ logDebug("setMuted:"+status);
1565
+ window.jsvPlayerBridge.setGlobalMuted(status, typeof flags!="undefined"?flags:0);
1566
+ }
1567
+ }
1568
+
1569
+ /**
1570
+ * 获取系统静音状态。
1571
+ * @return {boolean} true表示静音,false表示非静音。
1572
+ * */
1573
+ getGlobalMutedStatus(){
1574
+ logTrace("getGlobalMutedStatus, key="+this.key);
1575
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1576
+ return window.jsvPlayerBridge.getGlobalMutedStatus();
1577
+ }
1578
+ }
1579
+
1580
+ /**
1581
+ * 回到视频的开头。
1582
+ */
1583
+ gotoStart(){
1584
+ logTrace("gotoStart, key="+this.key);
1585
+ if(this.playerCreate && this.appVisible){
1586
+ window.jsvPlayerBridge.gotoStart(this.key);
1587
+ }else{
1588
+ this.state["currentTime"] = 0;
1589
+ }
1590
+ }
1591
+
1592
+ /**
1593
+ * 到达视频的末尾。
1594
+ */
1595
+ gotoEnd(){
1596
+ logTrace("gotoEnd, key="+this.key);
1597
+ if(this.playerCreate && this.appVisible){
1598
+ window.jsvPlayerBridge.gotoEnd(this.key);
1599
+ }
1600
+ }
1601
+
1602
+ /**
1603
+ * 获取timeShift状态,包含是否支持时移以及最大时移时间。
1604
+ * @returns {JsonObject} 包含两个字段:1、timeShift,boolean类型,true表示支持时移;2、timeShiftLength,int类型,最大时移时长。
1605
+ */
1606
+ getTimeShiftInfo(){
1607
+ logTrace("getTimeShiftInfo, key="+this.key);
1608
+ let result = this.getProperty("timeShift");
1609
+ if(result != null && result != "")
1610
+ return JSON.parse(result);
1611
+
1612
+ return null;
1613
+ }
1614
+
1615
+ /**
1616
+ * 设置时移时间。
1617
+ * @param {double} time,值为从当前时间计算向前移动了多长时间,单位秒。
1618
+ */
1619
+ setTimeShift(time){
1620
+ logTrace("setTimeShift, key="+this.key+", time="+time);
1621
+ if(this.type === "audio"){
1622
+ logWarning("Audio player do not support setTimeShift.");
1623
+ return;
1624
+ }
1625
+ if(this.playerCreate && this.appVisible){
1626
+ window.jsvPlayerBridge.setTimeShift(this.key, time);
1627
+ }
1628
+ }
1629
+
1630
+ /**
1631
+ * 设置色度抠像参数,只支持扣绿。
1632
+ * 参考格式:{color: 0x30FF30, colorDistance: 0.15, edgeDistance: 0.4, greenOffset: 0.05}
1633
+ * @param {JSON object} chromaKey,抠像参数,JSON Object包含的参数如下:
1634
+ * color,色值,int类型,为抠图色值范围的中心点,格式为0xRRGGBB。
1635
+ * colorDistance,float类型,色域范围,范围0-1.0。
1636
+ * edgeDistance,float类型,alpha透明度距离,范围colorDistance-1.0,从colorDistance到edgeDistance的alpha值从1.0-0线性递减。
1637
+ * greenOffset,float类型,红蓝差值,范围0-1.0。
1638
+ */
1639
+ setChromaKey(chromaKey){
1640
+ logTrace("setChromaKey, key="+this.key+", chroma key="+JSON.stringify(chromaKey));
1641
+ if(this.type === "audio"){
1642
+ logWarning("Audio player do not support setChromaKey.");
1643
+ return;
1644
+ }
1645
+ this.setState("chromaKey", JSON.stringify(chromaKey), "string");
1646
+ }
1647
+
1648
+ setDebugMode(mode){
1649
+ logTrace("setDebugMode, key="+this.key+", mode="+mode);
1650
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1651
+ return window.jsvPlayerBridge.setDebugMode(this.key, mode);
1652
+ }
1653
+ }
1654
+
1655
+ /**
1656
+ * 获取是否支持倍速设置,在onCanPlay事件发送以后,通过此接口查询。
1657
+ * @returns {boolean} true:支持播放倍速设置;false:不支持播放倍速设置。
1658
+ * */
1659
+ supportPlaybackRateSet(){
1660
+ logTrace("supportPlaybackRateSet, key="+this.key);
1661
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1662
+ return window.jsvPlayerBridge.supportRateSet(this.key);
1663
+ }
1664
+
1665
+ return false;
1666
+ }
1667
+
1668
+ /**
1669
+ * 私有接口,外部不需要调用此接口。
1670
+ */
1671
+ setState(key, value, type) {
1672
+ if (typeof(value) !== type) {
1673
+ logWarning("invalid paramter type to set " + key + ". value is not " + type);
1674
+ return;
1675
+ }
1676
+
1677
+ this.state[key] = value;
1678
+ logDebug("set " + key + " = " + value);
1679
+
1680
+ let param = {};
1681
+ param[key] = value;
1682
+
1683
+ if(this.playerCreate && this.appVisible){
1684
+ window.jsvPlayerBridge.SetProperty(this.key, JSON.stringify(param));
1685
+ }
1686
+ }
1687
+
1688
+ /**
1689
+ * 私有接口,外部不需要调用此接口。
1690
+ */
1691
+ getState(key) {
1692
+ let value = this.state[key];
1693
+ logDebug("get " + key + " = " + value);
1694
+ if (typeof value == "undefined" && this.playerCreate && this.appVisible) {
1695
+ value = window.jsvPlayerBridge.GetProperty(this.key, key);
1696
+ this.state[key] = value;
1697
+ }
1698
+
1699
+ return value;
1700
+ }
1701
+
1702
+ /**
1703
+ * 私有接口,外部不需要调用此接口。
1704
+ */
1705
+ getProperty(key){
1706
+ if (this.playerCreate && typeof window.jsvPlayerBridge != "undefined" && this.appVisible) {
1707
+ let result_str = window.jsvPlayerBridge.GetProperty(this.key, key);
1708
+ if(result_str == null || result_str == "")
1709
+ return null;
1710
+
1711
+ let result = JSON.parse(result_str);
1712
+ if(result.hasOwnProperty(key))
1713
+ return result[key];
1714
+
1715
+ return null;
1716
+ }
1717
+
1718
+ return null;
1719
+ }
1720
+ }
1721
+
1722
+ class JsvMedia extends JsvBaseMedia {
1723
+ constructor(type, window_mode, hole_id, player_type, key, background, design_map_width, decode_type) {
1724
+ super(type, window_mode, hole_id, player_type, key, background, design_map_width, decode_type);
1725
+ //super.buildPlatformInstance(type);
1726
+ }
1727
+ }
1728
+
1729
+ class JsvMediaAudio extends JsvMedia {
1730
+ constructor(key, design_map_width) {
1731
+ super("audio", "resizable", 0, 3, key, true, design_map_width, 0);
1732
+ }
1733
+ }
1734
+
1735
+ class JsvMediaVideo extends JsvMedia {
1736
+ constructor(hole_id, window_mode, player_type, key, background, design_map_width, decode_type) {
1737
+ super("video", window_mode, hole_id, player_type, key, background, design_map_width, decode_type);
1738
+
1739
+ this.state.aspectRatio = 'origin'; // 'origin', 'full', '16:9', '4:3',
1740
+ }
1741
+
1742
+ /**
1743
+ * 属性,string类型,设置海报地址,未实现。
1744
+ */
1745
+ set poster(value) {
1746
+ logWarning("Video.poster() TODO");
1747
+ }
1748
+
1749
+ /**
1750
+ * 属性,string类型,设置和读取显示模式。
1751
+ * full(fill模式)表示拉升至充满显示区域;origin(contain模式)表示原始比例缩放至宽或高和显示区域相等(不超过显示区域);x:y表示按照指定比例显示。
1752
+ */
1753
+ get videoAspectRatio() {
1754
+ return this.getState("aspectRatio");
1755
+ }
1756
+
1757
+ set videoAspectRatio(value) {
1758
+ this.setState("aspectRatio", value, "string");
1759
+ }
1760
+
1761
+ /**
1762
+ * 属性,int类型,只读,获取视频的宽。
1763
+ */
1764
+ get videoHeight() {
1765
+ return this.getState("videoHeight");
1766
+ }
1767
+
1768
+ /**
1769
+ * 属性,int类型,只读,获取视频的宽。
1770
+ */
1771
+ get videoWidth() {
1772
+ return this.getState("videoWidth");
1773
+ }
1774
+ }
1775
+
1776
+ /**
1777
+ * 获取播放器能力集,当前主要是对4K多播放器的支持以及H265解码能力的支持。
1778
+ * @return {string} json string,能力集JSON数据格式。
1779
+ */
1780
+ function getJsvPlayerCapabilitySet(){
1781
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1782
+ return window.jsvPlayerBridge.getCapabilitySet();
1783
+ }
1784
+ return null;
1785
+ }
1786
+
1787
+ /**
1788
+ * 设置指定视频类型的同时使用播放器个数,会check硬件是否支持系统设置的播放器个数,最好在小程序初始化的时候,使用播放器资源之前调用。
1789
+ * @param {string} videoType,对于H264,是video/avc,对于H265,是video/hevc,其他可以参考相关定义。
1790
+ * @param {int} num,需要使用的播放器个数。
1791
+ * @return {String} json string,对设置的播放器个数的支持状态,返回的总数不会大于设置的个数(实际硬件能力可能大于设置的个数)。
1792
+ * 支持三个属性:1、total:总的播放器个数;2、hardware:硬解播放器个数;3、软解播放器个数,如果硬解播放器个数不满足需求,会根据cpu能力确定是否提供软解播放器。
1793
+ * */
1794
+ function setJsvPlayerNumber(videoType, num){
1795
+ logTrace("setPlayerNumber, videoType="+videoType+", num="+num);
1796
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1797
+ return window.jsvPlayerBridge.setPlayerNumber(videoType, num);
1798
+ }else{
1799
+ return null;
1800
+ }
1801
+ }
1802
+
1803
+ function setJsvPlayerDebugMode(mode){
1804
+ logTrace("setJsvPlayerDebugMode, mode="+mode);
1805
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1806
+ window.jsvPlayerBridge.setDebugMode(null, mode);
1807
+ }
1808
+ }
1809
+
1810
+ function getJsvPlayerRunningNum(){
1811
+ logTrace("getJsvPlayerRunningNum");
1812
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1813
+ return window.jsvPlayerBridge.getRunningPlayerNum();
1814
+ }
1815
+ return -1;
1816
+ }
1817
+
1818
+ function setOperator(operator){
1819
+ logTrace("setOperator");
1820
+ if(typeof window.jsvPlayerBridge !== "undefined"){
1821
+ return window.jsvPlayerBridge.setOperator(operator);
1822
+ }
1823
+ }
1824
+
1825
+ function globalLoadSetOperator(operator){
1826
+ setOperator(operator)
1827
+ }
1828
+
1829
+ export {
1830
+ JsvMediaVideo,
1831
+ JsvMediaAudio,
1832
+ globalLoadJsvPlayerPlugin,
1833
+ globalPreLoadJsvPlayerPlugin,
1834
+ globalLoadSetOperator,
1835
+ findMediaObjectByKey,
1836
+ getJsvPlayerCapabilitySet,
1837
+ setJsvPlayerNumber,
1838
+ setLogLevel,
1839
+ logFatal,
1840
+ logError,
1841
+ logWarning,
1842
+ logDebug,
1843
+ logTrace,
1844
+ setJsvPlayerDebugMode,
1845
+ getJsvPlayerRunningNum,
1846
+ setOperator,
1847
+ }