@shijiu/jsview-vue 0.9.359-alpha.0 → 0.9.422

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 (47) hide show
  1. package/dom/bin/jsview-browser-debug-dom.min.js +1 -1
  2. package/dom/bin/jsview-dom.min.js +1 -1
  3. package/dom/target_core_revision.js +3 -3
  4. package/loader/jsview.config.default.js +1 -1
  5. package/loader/jsview.default.config.js +1 -1
  6. package/loader/loader.js +2 -1
  7. package/package.json +1 -1
  8. package/patches/node_modules/@vue/compiler-sfc/dist/jsview-style-format.js +1 -1
  9. package/patches/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +20 -7
  10. package/samples/Basic/App.vue +37 -29
  11. package/samples/Basic/components/ContentBlock.vue +1 -1
  12. package/samples/Basic/components/FontStyle.css +6 -0
  13. package/samples/Basic/components/div/DivBackground.vue +1 -1
  14. package/samples/Basic/components/div/DivCssScoped.vue +6 -13
  15. package/samples/Basic/components/div/DivCssVar.vue +3 -7
  16. package/samples/Basic/components/div/DivGroup2.vue +7 -2
  17. package/samples/Basic/components/div/DivLayout.vue +3 -3
  18. package/samples/Basic/components/div/DivTransform.vue +27 -0
  19. package/samples/Basic/components/img/ImageGroup.vue +31 -0
  20. package/samples/Basic/components/img/ImgLayout.vue +41 -0
  21. package/samples/Basic/components/panel/Panel1.vue +53 -0
  22. package/samples/Basic/components/panel/Panel2.vue +35 -0
  23. package/samples/Basic/components/panel/TitleBar.vue +29 -0
  24. package/samples/Basic/components/text/TextEmoji.vue +30 -0
  25. package/samples/Basic/components/text/{TextGroup.vue → TextGroup1.vue} +0 -0
  26. package/samples/Basic/components/text/TextGroup2.vue +31 -0
  27. package/utils/JsViewEngineWidget/JsvFocusBlock.vue +13 -0
  28. package/utils/JsViewEngineWidget/MetroWidget/ContentView.vue +63 -0
  29. package/utils/JsViewEngineWidget/MetroWidget/Dispatcher.js +19 -0
  30. package/utils/JsViewEngineWidget/MetroWidget/DivWrapper.vue +51 -0
  31. package/utils/JsViewEngineWidget/MetroWidget/ItemView.vue +220 -0
  32. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +1860 -0
  33. package/utils/JsViewEngineWidget/MetroWidget/RootView.vue +153 -0
  34. package/utils/JsViewEngineWidget/SimpleWidget/SimpleWidget.vue +137 -118
  35. package/utils/JsViewEngineWidget/TemplateParser.js +212 -158
  36. package/utils/JsViewEngineWidget/index.js +3 -2
  37. package/utils/JsViewPlugin/BrowserPluginLoader.js +14 -0
  38. package/utils/JsViewPlugin/JsvPlayer/JsvMedia.js +502 -108
  39. package/utils/JsViewPlugin/JsvPlayer/JsvMediaBrowserInterface.js +101 -0
  40. package/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue +262 -92
  41. package/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser.vue +40 -0
  42. package/utils/JsViewPlugin/JsvPlayer/index.js +27 -0
  43. package/utils/JsViewVueWidget/BrowserDebugWidget/BrowserTextureAnim.vue +1 -2
  44. package/utils/JsViewVueWidget/JsvMarquee.vue +18 -10
  45. package/utils/JsViewVueWidget/JsvMaskClipDiv.vue +3 -3
  46. package/utils/JsViewVueWidget/JsvNinePatch.vue +28 -10
  47. package/samples/Basic/components/TitleBar.vue +0 -27
@@ -1,39 +1,92 @@
1
1
  /* eslint-disable no-prototype-builtins */
2
2
 
3
3
  let MediaPluginInfo={
4
- //downloadUrl:"http://192.168.0.34:8080/plugin/JsvPlayer-3.0.zip", //插件下载地址
4
+ //downloadUrl:"http://192.168.0.37:8080/plugin/JsvPlayer-6.0.zip", //插件下载地址
5
5
  packageName:"com.qcode.jsvplayer",
6
6
  name:"播放器插件",
7
- version:"1.1.2", //插件需要的最低版本号
8
- versionCodeMin:112,
9
- versionCodeMax:112,
7
+ version:"1.3.5", //插件需要的最低版本号
8
+ versionCodeMin:135,
9
+ versionCodeMax:135,
10
10
  bridgeName:"jsvPlayerBridge", //插件bridge注册到jsview的名称
11
11
  className:"com.qcode.jsvplayer.JsvPlayer", //插件初始化类名称
12
12
  initMethod:"createInstance", //插件初始化方法
13
13
  listener:"top.JsvPlayerPluginLoadResult", //插件加载结果回调
14
- //md5:"bf6ee4f3726527755b7d9b08d4975adb"
15
- // debug: true,
14
+ listener2: "top.JsvPlayerPluginStatus",
15
+ // debug:true,
16
+ // md5:"9fca9d2dc29468d332961b0be3e8081e"
16
17
  };
17
18
 
18
- var mediaArray = []
19
+ function reconfigMediaPluginInfo(){
20
+ if(typeof window.jJsvRuntimeBridge!=='undefined' && window.jJsvRuntimeBridge && typeof window.jJsvRuntimeBridge.getPluginBaseUrl !== "undefined"){
21
+ let plugin_base_url = window.jJsvRuntimeBridge.getPluginBaseUrl();
22
+ if(plugin_base_url){
23
+ MediaPluginInfo.downloadUrl = (plugin_base_url[plugin_base_url.length-1]==="/"?plugin_base_url:(plugin_base_url+"/"))+MediaPluginInfo.packageName+"/JsvPlayer-135.zip?md5=1056e2e32f8a91e2dfef86d86200da53";
24
+ }
25
+ }
26
+ }
27
+
28
+ var mediaArray = [];
29
+
30
+ var pluginLoadListener = [];
19
31
 
20
- var pluginLoading = false;
32
+ /**
33
+ * 0:未加载;
34
+ * 1:开始加载;
35
+ * 2:加载旧插件;
36
+ * 3:加载新插件;
37
+ * 4:加载成功;
38
+ * 5:加载失败。
39
+ */
40
+ var pluginLoadState = 0;
41
+
42
+ window.top.JsvPlayerPluginStatus = function(status){
43
+ console.log("JsvPlayerPluginStatus: "+status);
44
+ let ret = JSON.parse(status);
45
+
46
+ let plugin_status = 2;
47
+ if(ret && ret.first_load){
48
+ pluginLoadState = 3;
49
+ plugin_status = 3;
50
+ }else{
51
+ pluginLoadState = 2;
52
+ }
53
+
54
+ for(let i=0; i<pluginLoadListener.length; i++){
55
+ pluginLoadListener[i](plugin_status);
56
+ }
57
+ }
21
58
 
22
59
  window.top.JsvPlayerPluginLoadResult = function (result) {
23
- console.log(result);
24
- for(var i=0; i<mediaArray.length; i++){
60
+ console.log("JsvPlayerPluginLoadResult: "+result);
61
+ var ret_obj = JSON.parse(result)
62
+ let plugin_status = 1;
63
+ if(ret_obj && (ret_obj.status === 4 || ret_obj.status === 1)){
64
+ pluginLoadState = 4;
65
+ plugin_status = 4;
66
+ }else if(ret_obj && ret_obj.status === -12){
67
+ pluginLoadState = 5;
68
+ plugin_status = 5;
69
+ }else{
70
+ pluginLoadState = 5;
71
+ }
72
+
73
+ for(let i=0; i<mediaArray.length; i++){
25
74
  mediaArray[i].buildPlatformInstance();
26
75
  }
76
+
77
+ for(let i=0; i<pluginLoadListener.length; i++){
78
+ pluginLoadListener[i](plugin_status);
79
+ }
27
80
  }
28
81
 
29
82
  window.top.CreatePlayerResult = function (result) {
30
- console.log(result);
83
+ console.log("CreatePlayerResult: "+result);
31
84
  let result_obj = JSON.parse(result);
32
85
  if(result_obj.code == 0){
33
86
  for(var i=0; i<mediaArray.length; i++){
34
87
  if(mediaArray[i].key === result_obj.key){
35
88
  mediaArray[i].initPlayer();
36
- break;
89
+ break;
37
90
  }
38
91
  }
39
92
  }else{
@@ -41,6 +94,69 @@ window.top.CreatePlayerResult = function (result) {
41
94
  }
42
95
  }.bind(this);
43
96
 
97
+ /**
98
+ * listener回调处理中参数信息的说明:
99
+ * 插件加载状态回调。
100
+ * 回调函数的参数定义如下:
101
+ * 1:无法正常加载插件。
102
+ * 2:正在加载旧插件,此时插件加载过程很短,可以不用出现用户提示界面。
103
+ * 3:正在加载新插件,此时插件需要经历下载、解压等过程,用时较长,可以考虑给用户相关提示。
104
+ * 4:插件加载完成。
105
+ * 5:已加载不同版本的插件,此版本无法加载。
106
+ *
107
+ * 备注:不管插件加载处于什么状态,都可以正常使用播放器组件,播放器对象在插件未加载完成的情况下,会把相关状态保存,等完成加载后再自动下发。
108
+ */
109
+ function globalLoadJsvPlayerPlugin(listener){
110
+ console.log("globalLoadJsvPlayerPlugin");
111
+ let plugin_status = 0;
112
+ if(typeof window.jPluginManagerBridge==='undefined' || !window.jPluginManagerBridge){
113
+ plugin_status = 1;
114
+ }else if(pluginLoadState === 2){
115
+ plugin_status = 2;
116
+ }else if(pluginLoadState === 3){
117
+ plugin_status = 3;
118
+ }else if(pluginLoadState === 4){
119
+ plugin_status = 4;
120
+ }else if(pluginLoadState === 5){
121
+ plugin_status = 1;
122
+ }
123
+
124
+ if(plugin_status !== 0){
125
+ if(typeof listener !== "undefined" && listener){
126
+ setTimeout(()=>{listener(plugin_status)}, 0);
127
+ }
128
+ return;
129
+ }
130
+
131
+ if(typeof listener !== "undefined" && listener){
132
+ pluginLoadListener.push(listener);
133
+ }
134
+
135
+ if(pluginLoadState > 0){
136
+ return;
137
+ }
138
+ pluginLoadState = 1;
139
+
140
+ reconfigMediaPluginInfo();
141
+
142
+ window.jPluginManagerBridge.LoadPlugin(JSON.stringify(MediaPluginInfo));
143
+ }
144
+
145
+ /**
146
+ * 根据key查询是否已经有Media对象了,如果已经有了,就不需要再创建,而是调用setRef接口将当前的对象索引+1。
147
+ * @param {string} key Player索引。
148
+ * @returns {object} Media对象。
149
+ */
150
+ function findMediaObjectByKey(key){
151
+ for(var i=0; i<mediaArray.length; i++){
152
+ if(mediaArray[i].key === key){
153
+ return mediaArray[i];
154
+ }
155
+ }
156
+
157
+ return null;
158
+ }
159
+
44
160
  class JsvBaseMedia {
45
161
  constructor(type, hole_id, player_type, key, background, design_map_width) {
46
162
  this.state = {
@@ -48,31 +164,35 @@ class JsvBaseMedia {
48
164
  paused: true,
49
165
  repeat: false,
50
166
  enablePlayer: false,
51
- autoPlay: false,
167
+ autoplay: false,
52
168
  startTime: 0.0,
169
+ currentTime: 0.0,
53
170
  aspectRatio: "origin",
171
+ keepLastFrame: false,
54
172
  };
55
173
 
56
174
  this.local = {
57
175
  currentTime: 0.0,
58
176
  playableDuration: 0.0,
59
177
  duration: 0.0,
60
-
61
178
  isRenderable: false,
62
179
  };
63
180
 
64
181
  this.type = type;
65
- this._AutoPlay = false;
66
182
  this.playerCreate = false;
67
183
  this.key = key;
68
184
  this.background = background;
69
185
  this.holeId = hole_id;
186
+ this.holeIdModify = hole_id;
70
187
  this.playerType = player_type;
71
188
  this.designMapWidth = design_map_width;
189
+ this.channelID = -1;
190
+ this.ref = 1;
191
+ this._onEvent = this.onEvent.bind(this);
72
192
 
73
193
  let found = false;
74
194
  for(let i=0; i<mediaArray.length; i++){
75
- if(mediaArray[i].key === key){
195
+ if(mediaArray[i].key === this.key){
76
196
  found = true;
77
197
  break;
78
198
  }
@@ -83,83 +203,126 @@ class JsvBaseMedia {
83
203
  }
84
204
 
85
205
  if(typeof window.jsvPlayerBridge=='undefined' || !window.jsvPlayerBridge){
86
- this.loadJsvPlayerPlugin();
206
+ globalLoadJsvPlayerPlugin();
87
207
  }else{
88
208
  this.buildPlatformInstance();
89
209
  }
90
210
  }
91
211
 
92
- loadJsvPlayerPlugin(){
93
- if(typeof window.jPluginManagerBridge=='undefined' || !window.jPluginManagerBridge){
94
- return;
95
- }
96
-
97
- if(pluginLoading){
98
- return;
99
- }
100
-
101
- pluginLoading = true;
102
- window.jPluginManagerBridge.LoadPlugin(JSON.stringify(MediaPluginInfo));
103
- }
104
-
212
+ /**
213
+ * 私有接口,外部不需要调用此接口。
214
+ */
105
215
  buildPlatformInstance() {
106
216
  if(typeof window.jsvPlayerBridge=='undefined' || !window.jsvPlayerBridge){
107
217
  console.log("no jsvPlayerBridge");
108
218
  return;
109
219
  }
110
220
 
111
- let view_type = 0;
221
+ let share_view = true;
112
222
 
113
- let result = window.jsvPlayerBridge.CreatePlayer(this.key, this.holeId, this.background, this.designMapWidth, view_type, this.playerType, "top.CreatePlayerResult");
223
+ let result = window.jsvPlayerBridge.CreatePlayer(this.key, this.holeId, this.background, this.designMapWidth, share_view, this.playerType, "top.CreatePlayerResult");
114
224
  if(result > 0){
115
225
  this.initPlayer();
116
226
  }
117
227
  }
118
228
 
229
+ /**
230
+ * 私有接口,外部不需要调用此接口。
231
+ */
119
232
  initPlayer(){
233
+ if(this.playerCreate)
234
+ return;
235
+
120
236
  this.playerCreate = true;
121
237
 
122
- window.JMD.subscribe(this.key, function (event) {
123
- console.log("event data:" + event);
124
- let obj = JSON.parse(event);
125
- let event_obj = JSON.parse(obj.param);
126
- this.onEvent(event_obj.event, event_obj.data);
127
- }.bind(this));
238
+ window.JMD.subscribe(this.key, this._onEvent);
128
239
 
129
240
  console.log("InitPlayer:1");
241
+ if(this.holeIdModify !== this.holeId){
242
+ window.jsvPlayerBridge.setHoleID(this.key, this.holeIdModify);
243
+ this.holeId = this.holeIdModify;
244
+ }
245
+
130
246
  if(this.state["src"])
131
247
  this.setState("src", this.state["src"], "string");
132
-
133
- // console.log("InitPlayer:2");
134
- // this.setState("style", JSON.stringify(this.style), "string");
248
+ else if(this.channelID >= 0){
249
+ this.joinChannel(this.channelID);
250
+ }
135
251
 
136
252
  console.log("InitPlayer:3");
137
- if(this.state["currentTime"])
253
+ if(this.state["currentTime"]){
138
254
  this.setState("currentTime", this.state["currentTime"], "number");
255
+ }else if(this.state["startTime"]){
256
+ this.setState("startTime", this.state["startTime"], "number");
257
+ }
139
258
 
140
259
  if(this.state["paused"] == false){
141
260
  this.setState("paused", this.state["paused"], "boolean");
142
261
  }
262
+
263
+ if(this.state["autoplay"]){
264
+ this.setState("autoplay", this.state["autoplay"], "boolean");
265
+ }
266
+
267
+ if(this.state["repeat"]){
268
+ this.setState("repeat", this.state["repeat"], "boolean");
269
+ }
270
+
271
+ if(this.state["muted"]){
272
+ this.setState("muted", this.state["muted"], "boolean");
273
+ }
274
+ }
275
+
276
+ /**
277
+ * 当使用一个已有的Media对象时,需要通过这个接口追加一个ref,在调用releasePlayer接口释放时,会ref--,当ref==0才真正释放播放器实例。
278
+ */
279
+ setRef(){
280
+ this.ref++;
143
281
  }
144
282
 
283
+ /**
284
+ * 释放播放器,一般不需要应用逻辑调用,在JsvPlayer高阶组件unmounted处理时调用此接口释放。
285
+ */
145
286
  releasePlayer(){
146
- if(typeof window.jsvPlayerBridge != "undefined" && window.jsvPlayerBridge){
147
- window.jsvPlayerBridge.ReleasePlayer(this.key, this.holeId, this.background);
148
- }
287
+ this.ref--;
288
+ if(this.ref === 0){
289
+ window.JMD.unsubscribe(this.key, this._onEvent)
290
+ if(typeof window.jsvPlayerBridge != "undefined" && window.jsvPlayerBridge){
291
+ window.jsvPlayerBridge.ReleasePlayer(this.key);
292
+ }
149
293
 
150
- for(let i=0; i<mediaArray.length; i++){
151
- if(mediaArray[i].key === this.key){
152
- mediaArray.splice(i, 1);
153
- break;
294
+ for(let i=0; i<mediaArray.length; i++){
295
+ if(mediaArray[i].key === this.key){
296
+ mediaArray.splice(i, 1);
297
+ break;
298
+ }
154
299
  }
155
300
  }
156
301
  }
157
302
 
158
- onEvent(event, data){
159
- switch(event){
303
+ setHoleID(hole_id){
304
+
305
+ if(this.playerCreate){
306
+ this.holeId = hole_id;
307
+ this.holeIdModify = hole_id;
308
+ window.jsvPlayerBridge.setHoleID(this.key, hole_id);
309
+ }else{
310
+ this.holeIdModify = hole_id;
311
+ }
312
+ }
313
+
314
+ /**
315
+ * 私有接口,外部不需要调用此接口。
316
+ */
317
+ onEvent(event_str){
318
+ let obj = JSON.parse(event_str);
319
+ let event_obj = JSON.parse(obj.param);
320
+ let event = event_obj.event;
321
+ let data = event_obj.data;
322
+ switch(event){
160
323
  case "onProgress":
161
324
  {
162
- console.log("onProgress:"+data);
325
+ //console.log("onProgress:"+data);
163
326
  if (this.local.isRenderable == false) {
164
327
  return;
165
328
  }
@@ -167,7 +330,7 @@ class JsvBaseMedia {
167
330
  let time_update = this.local.currentTime != data.currentTime;
168
331
  this.local.currentTime = data.currentTime;
169
332
  if (time_update && this.hasOwnProperty("ontimeupdate")) {
170
- this["ontimeupdate"]();
333
+ this["ontimeupdate"](data.currentTime);
171
334
  }
172
335
 
173
336
  let progress_update = this.local.playableDuration != data.playableDuration;
@@ -221,8 +384,9 @@ class JsvBaseMedia {
221
384
  MEDIA_ERR_NETWORK: 2,
222
385
  MEDIA_ERR_DECODE: 3,
223
386
  MEDIA_ERR_SRC_NOT_SUPPORTED: 4,
387
+ MEDIA_ERR_ONLY_ONE_4K: 5,
224
388
  };
225
- const platform_error = data.error.extra;
389
+ const platform_error = data.error.what;
226
390
  let e = Error.MEDIA_ERR_ABORTED;
227
391
  switch (platform_error) {
228
392
  case -1004 : // MediaPlayer.MEDIA_ERROR_IO
@@ -234,6 +398,8 @@ class JsvBaseMedia {
234
398
  case -1010 : // MediaPlayer.MEDIA_ERROR_UNSUPPORTED
235
399
  e = Error.MEDIA_ERR_SRC_NOT_SUPPORTED;
236
400
  break;
401
+ case -10001:
402
+ e = Error.MEDIA_ERR_ONLY_ONE_4K;
237
403
  }
238
404
  this["onerror"](e);
239
405
  }
@@ -242,7 +408,7 @@ class JsvBaseMedia {
242
408
  console.log("onSeek:"+data);
243
409
  this.local.isRenderable = false;
244
410
  if(this.hasOwnProperty("onseeking")){
245
- this["onseeking"](data);
411
+ this["onseeking"]();
246
412
  }
247
413
  break;
248
414
  case "onEventExt":
@@ -299,10 +465,16 @@ class JsvBaseMedia {
299
465
  }
300
466
  }
301
467
 
468
+ /**
469
+ * 属性,boolean类型,不支持读取,true表示自动播放。
470
+ */
302
471
  set autoplay(value) {
303
472
  this.setState("autoplay", value, "boolean");
304
473
  }
305
474
 
475
+ /**
476
+ * 属性,double类型,当前时间,单位秒,set用于seek操作(起播后)或者设置起播时间(起播前),get用于读取当前时间。
477
+ */
306
478
  get currentTime() {
307
479
  let result = this.getProperty("currentTime");
308
480
  if(result != null)
@@ -316,6 +488,9 @@ class JsvBaseMedia {
316
488
  this.setState("seek", value, "number");
317
489
  }
318
490
 
491
+ /**
492
+ * 属性,double类型,总时长,单位秒,只支持读取。
493
+ */
319
494
  get duration() {
320
495
  let result = this.getProperty("duration");
321
496
  if(result != null)
@@ -324,6 +499,9 @@ class JsvBaseMedia {
324
499
  return 0;
325
500
  }
326
501
 
502
+ /**
503
+ * 属性,boolean类型,不支持读取,true表示循环播放。
504
+ */
327
505
  set loop(value) {
328
506
  if(typeof value == "boolean") {
329
507
  this.setState("repeat", value, "boolean");
@@ -334,6 +512,9 @@ class JsvBaseMedia {
334
512
  }
335
513
  }
336
514
 
515
+ /**
516
+ * 属性,boolean类型,设置和获取静音状态。
517
+ */
337
518
  get muted() {
338
519
  return this.getState("muted");
339
520
  }
@@ -342,6 +523,9 @@ class JsvBaseMedia {
342
523
  this.setState("muted", value, "boolean");
343
524
  }
344
525
 
526
+ /**
527
+ * 属性,boolean类型,当前pause状态,只支持读取。
528
+ */
345
529
  get paused() {
346
530
  let result = this.getProperty("paused");
347
531
  if(result != null)
@@ -350,14 +534,21 @@ class JsvBaseMedia {
350
534
  return true;
351
535
  }
352
536
 
537
+ /**
538
+ * 属性,float类型,设置或者读取倍速播放,通常的值是0.5、0.75、1.0、1.25、1.5、2.0、3.0。
539
+ */
353
540
  get playbackRate() {
354
541
  return this.getState("rate");
355
542
  }
356
543
 
357
544
  set playbackRate(value) {
545
+ console.log("playbackRate")
358
546
  this.setState("rate", value, "number");
359
547
  }
360
548
 
549
+ /**
550
+ * 已废弃。
551
+ */
361
552
  get preload() {
362
553
  return (this.enablePlayer ? 'auto' : 'none');
363
554
  }
@@ -368,10 +559,17 @@ class JsvBaseMedia {
368
559
  }
369
560
  }
370
561
 
562
+
563
+ /**
564
+ * 属性,string类型,播放地址,不支持读取。
565
+ */
371
566
  set src(value) {
372
- this.setState("src", value, "string");
567
+ this.setSrc(value, null, 1)
373
568
  }
374
569
 
570
+ /**
571
+ * 属性,float类型,播放器音量,0-1.0,只影响当前播放器实例。
572
+ */
375
573
  get volume() {
376
574
  let result = this.getProperty("volume");
377
575
  if(result != null)
@@ -384,7 +582,9 @@ class JsvBaseMedia {
384
582
  this.setState("volume", value, "number");
385
583
  }
386
584
 
387
- // Extension beyond HTML5
585
+ /**
586
+ * 属性,double类型,起播时间,单位秒,可使用currentTime代替。
587
+ */
388
588
  get startTime() {
389
589
  return this.getState("startTime");
390
590
  }
@@ -393,22 +593,70 @@ class JsvBaseMedia {
393
593
  this.setState("startTime", value, "number");
394
594
  }
395
595
 
596
+ /**
597
+ * 属性,double类型,可播放时长,总时长-已播放时长,只支持读取。
598
+ */
396
599
  get playableDuration() {
397
600
  return this.local.playableDuration;
398
601
  }
399
602
 
603
+ /**
604
+ * 属性,boolean类型,true表示关闭timeupdate事件上报。
605
+ */
400
606
  set timeupdateless(value) {
401
607
  this.setState("timeUpdateLess", !!value, "boolean");
402
608
  }
403
609
 
610
+ /**
611
+ * 属性,boolean类型,true表示保留最后一帧,false表示不保留。
612
+ */
613
+ set keepLastFrame(value) {
614
+ this.setState("keepLastFrame", !!value, "boolean");
615
+ }
616
+
617
+ /**
618
+ * 设置播放地址。
619
+ * @param {string} url 播放地址。
620
+ * @param {string} head 网络请求的head信息,可以为NULL。
621
+ * @param {int} type 类型,1表示点播,2表示直播,3表示时移,默认1。
622
+ * @param {double} timeShift 时移时间,只有在type=3时才有效,表示从当前时间时移多长时间,单位秒。
623
+ */
624
+ setSrc(url, head, type, timeShift){
625
+ let src = {};
626
+ src.url = url;
627
+ if(head){
628
+ src.head = head;
629
+ }
630
+ if(type){
631
+ src.type = type;
632
+ }else{
633
+ src.type = 1;
634
+ }
635
+ if(type === 3 && timeShift){
636
+ src.timeShift = timeShift;
637
+ }
638
+ this.setState("src", JSON.stringify(src), "string");
639
+ }
640
+
641
+ /**
642
+ * 添加监听事件。
643
+ * @param {string} type 事件类型。
644
+ * @param {callback} listener 事件处理函数。
645
+ */
404
646
  addEventListener(type, listener) {
405
647
  this['on' + type] = listener;
406
648
  }
407
649
 
650
+ /**
651
+ * 重新加载视频流,初始化播放器。
652
+ */
408
653
  load() {
409
654
  this.setState("enablePlayer", true, "boolean");
410
655
  }
411
656
 
657
+ /**
658
+ * 暂停
659
+ */
412
660
  pause() {
413
661
  this.setState("paused", true, "boolean");
414
662
  if (this.hasOwnProperty("onpause")) {
@@ -416,6 +664,9 @@ class JsvBaseMedia {
416
664
  }
417
665
  }
418
666
 
667
+ /**
668
+ * 播放
669
+ */
419
670
  play() {
420
671
  this.setState("paused", false, "boolean");
421
672
  if (this.hasOwnProperty("onplay")) {
@@ -423,12 +674,174 @@ class JsvBaseMedia {
423
674
  }
424
675
  }
425
676
 
677
+ /**
678
+ * 停止视频流。
679
+ */
426
680
  unload() {
427
681
  this.setState("paused", true, "boolean");
428
682
  this.local.isRenderable = false;
429
683
  this.setState("enablePlayer", false, "boolean");
430
684
  }
431
685
 
686
+ /**
687
+ * 要求终端访问指定的频道,并立即返回。对由本地设置为跳过的频道,也返回-1。
688
+ * 频道地址为通过 CTCSetConfig 设置的频道列表中的地址:
689
+ * 如频道地址为 igmp://的组播地址,则加入组播频道,播放器开始播放组播频道,并处理相应的时移等功能;
690
+ * 如频道地址为 rtsp://的单播地址,则连接单播频道,播放器开始播放;
691
+ * 如频道地址为 http://的地址,则浏览器直接发起请求,访问该页面。
692
+ * 【注】:在加入一个频道之前已经加入另外一个频道,需先调用 leaveChannel 方法离开前一个频道。
693
+ * @param {int} mixNo 用户频道号。
694
+ * @returns {int} 0,表示成功;-1:表示频道号无效。
695
+ */
696
+ joinChannel(mixNo){
697
+ if(mixNo <= 0){
698
+ return -1;
699
+ }
700
+
701
+ if(this.playerCreate){
702
+ return window.jsvPlayerBridge.JoinChannel(this.key, mixNo);
703
+ }else{
704
+ this.channelID = mixNo;
705
+ }
706
+
707
+ this.setState("paused", false, "boolean");
708
+ return 0;
709
+ }
710
+
711
+ /**
712
+ * 要求终端离开指定的频道,并立即返回。
713
+ * 如原频道地址为 igmp://的组播地址,则立即离开组播频道,播放器停止播放组播频道,并断开相应的时移连接;
714
+ * 如频道地址为 rtsp://的单播地址,则断开单播频道,播放器停止播放;
715
+ * 如频道地址为 http://的地址,则浏览器不作操作。
716
+ * 【注】:本方法只用于离开通过 joinChannel 方法加入的频道。
717
+ * @returns {int} 0,表示成功;-1:表示频道号无效。
718
+ */
719
+ leaveChannel(){
720
+ let ret = 0;
721
+ if(this.playerCreate){
722
+ ret = window.jsvPlayerBridge.leaveChannel(this.key);
723
+ }
724
+
725
+ this.channelID = -1;
726
+ return ret;
727
+ }
728
+
729
+ // /**
730
+ // * 快进。
731
+ // * @param {float} speed 2至32
732
+ // */
733
+ // fastForward(value) {
734
+ // this.setState("fastForward", value, "number");
735
+ // }
736
+
737
+ // /**
738
+ // * 快退。
739
+ // * @param {float} speed -2至-32
740
+ // */
741
+ // fastRewind(value) {
742
+ // this.setState("fastForward", value, "number");
743
+ // }
744
+
745
+ /**
746
+ * @return {int} 当前音量,0-100。
747
+ * */
748
+ getGlobalVolume(){
749
+ if(typeof window.jsvPlayerBridge !== "undefined"){
750
+ return window.jsvPlayerBridge.getGlobalVolume(100);
751
+ }
752
+
753
+ return 0;
754
+ }
755
+
756
+ /**
757
+ * 设置系统音量。
758
+ * @param {int} volume 0-100,音量值。
759
+ * @param {int} flags 1表示显示音量调节UI;4表示使用提示音;5表示同时显示音量调节UI和使用提示音。
760
+ * */
761
+ setGlobalVolume(volume, flags){
762
+ if(typeof window.jsvPlayerBridge !== "undefined"){
763
+ return window.jsvPlayerBridge.setGlobalVolume(volume, typeof flags!="undefined"?flags:0, 100);
764
+ }
765
+ }
766
+
767
+ /**
768
+ * 调整系统音量,一次设置一个步长。
769
+ * @param {int} direction 1增大音量;-1减小音量。
770
+ * @param {int} flags FLAG_SHOW_UI(1)表示显示音量调节UI;FLAG_PLAY_SOUND(4)表示使用提示音。两个值可以是或的关系。
771
+ * */
772
+ adjustGlobalVolume(direction, flags){
773
+ if(typeof window.jsvPlayerBridge !== "undefined"){
774
+ return window.jsvPlayerBridge.adjustGlobalVolume(direction, typeof flags!="undefined"?flags:0);
775
+ }
776
+ }
777
+
778
+ /**
779
+ * 设置系统静音状态。
780
+ * @param {boolean} status true表示静音,false表示取消静音。
781
+ * @param {int} flags FLAG_SHOW_UI(1)表示显示音量调节UI;FLAG_PLAY_SOUND(4)表示使用提示音。两个值可以是或的关系。android 6.0(包含)以上有效。
782
+ * */
783
+ setGlobalMuted(status, flags){
784
+ if(typeof window.jsvPlayerBridge !== "undefined"){
785
+ console.log("setMuted:"+status);
786
+ window.jsvPlayerBridge.setGlobalMuted(status, typeof flags!="undefined"?flags:0);
787
+ }
788
+ }
789
+
790
+ /**
791
+ * 获取系统静音状态。
792
+ * @return {boolean} true表示静音,false表示非静音。
793
+ * */
794
+ getGlobalMutedStatus(){
795
+ if(typeof window.jsvPlayerBridge !== "undefined"){
796
+ return window.jsvPlayerBridge.getGlobalMutedStatus();
797
+ }
798
+ }
799
+
800
+ /**
801
+ * 回到视频的开头。
802
+ */
803
+ gotoStart(){
804
+ if(this.playerCreate){
805
+ window.jsvPlayerBridge.gotoStart(this.key);
806
+ }else{
807
+ this.state["currentTime"] = 0;
808
+ }
809
+ }
810
+
811
+ /**
812
+ * 到达视频的末尾。
813
+ */
814
+ gotoEnd(){
815
+ if(this.playerCreate){
816
+ window.jsvPlayerBridge.gotoEnd(this.key);
817
+ }
818
+ }
819
+
820
+ /**
821
+ * 获取timeShift状态,包含是否支持时移以及最大时移时间。
822
+ * @returns {JsonObject} 包含两个字段:1、timeShift,boolean类型,true表示支持时移;2、timeShiftLength,int类型,最大时移时长。
823
+ */
824
+ getTimeShiftInfo(){
825
+ let result = this.getProperty("timeShift");
826
+ if(result != null && result != "")
827
+ return JSON.parse(result);
828
+
829
+ return null;
830
+ }
831
+
832
+ /**
833
+ * 设置时移时间。
834
+ * @param {double} time,值为从当前时间计算向前移动了多长时间,单位秒。
835
+ */
836
+ setTimeShift(time){
837
+ if(this.playerCreate){
838
+ window.jsvPlayerBridge.setTimeShift(this.key, time);
839
+ }
840
+ }
841
+
842
+ /**
843
+ * 私有接口,外部不需要调用此接口。
844
+ */
432
845
  setState(key, value, type) {
433
846
  if (typeof(value) !== type) {
434
847
  console.warn("invalid paramter type to set " + key + ". value is not " + type);
@@ -446,6 +859,9 @@ class JsvBaseMedia {
446
859
  }
447
860
  }
448
861
 
862
+ /**
863
+ * 私有接口,外部不需要调用此接口。
864
+ */
449
865
  getState(key) {
450
866
  let value = this.state[key];
451
867
  console.log("get " + key + " = " + value);
@@ -457,6 +873,9 @@ class JsvBaseMedia {
457
873
  return value;
458
874
  }
459
875
 
876
+ /**
877
+ * 私有接口,外部不需要调用此接口。
878
+ */
460
879
  getProperty(key){
461
880
  if (this.playerCreate && typeof window.jsvPlayerBridge != "undefined") {
462
881
  let result_str = window.jsvPlayerBridge.GetProperty(this.key, key);
@@ -472,17 +891,6 @@ class JsvBaseMedia {
472
891
 
473
892
  return null;
474
893
  }
475
-
476
- // setStyle(){
477
- // if(this.styleHandler != null){
478
- // clearTimeout(this.styleHandler);
479
- // this.styleHandler = null;
480
- // }
481
-
482
- // this.styleHandler = setTimeout(()=>{
483
- // this.setState("style", JSON.stringify(this.style), "string");
484
- // }, 0);
485
- // }
486
894
  }
487
895
 
488
896
  class JsvMedia extends JsvBaseMedia {
@@ -505,14 +913,17 @@ class JsvMediaVideo extends JsvMedia {
505
913
  this.state.aspectRatio = 'origin'; // 'origin', 'full', '16:9', '4:3',
506
914
  }
507
915
 
508
- // get poster() {
509
- // console.log("Video.poster() TODO");
510
- // }
511
-
916
+ /**
917
+ * 属性,string类型,设置海报地址,未实现。
918
+ */
512
919
  set poster(value) {
513
920
  console.log("Video.poster() TODO");
514
921
  }
515
922
 
923
+ /**
924
+ * 属性,string类型,设置和读取显示模式。
925
+ * full(fill模式)表示拉升至充满显示区域;origin(contain模式)表示原始比例缩放至宽或高和显示区域相等(不超过显示区域);x:y表示按照按照指定比例显示。
926
+ */
516
927
  get videoAspectRatio() {
517
928
  return this.getState("aspectRatio");
518
929
  }
@@ -521,52 +932,35 @@ class JsvMediaVideo extends JsvMedia {
521
932
  this.setState("aspectRatio", value, "string");
522
933
  }
523
934
 
935
+ /**
936
+ * 属性,int类型,只读,获取视频的宽。
937
+ */
524
938
  get videoHeight() {
525
939
  return this.getState("videoHeight");
526
940
  }
527
941
 
942
+ /**
943
+ * 属性,int类型,只读,获取视频的宽。
944
+ */
528
945
  get videoWidth() {
529
946
  return this.getState("videoWidth");
530
947
  }
948
+ }
531
949
 
532
- // get left() {
533
- // return this.style.left;
534
- // }
535
-
536
- // set left(value) {
537
- // this.style.left = value;
538
- // this.setStyle();
539
- // }
540
-
541
- // get top() {
542
- // return this.style.top;
543
- // }
544
-
545
- // set top(value) {
546
- // this.style.top = value;
547
- // this.setStyle();
548
- // }
549
-
550
- // get width() {
551
- // return this.style.width;
552
- // }
553
-
554
- // set width(value) {
555
- // this.style.width = value;
556
- // this.setStyle();
557
- // }
558
-
559
- // get height() {
560
- // return this.style.height;
561
- // }
562
-
563
- // set height(value) {
564
- // this.style.height = value;
565
- // this.setStyle();
566
- // }
950
+ /**
951
+ * 获取播放器能力集,当前主要是对4K多播放器的支持以及H265解码能力的支持。
952
+ * @return {string} 能力集数组。
953
+ */
954
+ function getJsvPlayerCapabilitySet(){
955
+ if(typeof window.jsvPlayerBridge !== "undefined"){
956
+ return window.jsvPlayerBridge.getCapabilitySet();
957
+ }
567
958
  }
568
959
 
569
960
  export {
570
961
  JsvMediaVideo,
571
- JsvMediaAudio
962
+ JsvMediaAudio,
963
+ globalLoadJsvPlayerPlugin,
964
+ findMediaObjectByKey,
965
+ getJsvPlayerCapabilitySet
572
966
  }