ovenplayer 0.10.2 → 0.10.3-3.alpha-2
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/LICENSE +1 -1
- package/README.md +39 -46
- package/dist/ovenplayer.js +1 -1
- package/dist/ovenplayer.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/fonts/seek-icons.svg +13 -13
- package/src/js/api/Api.js +231 -140
- package/src/js/api/Configurator.js +6 -3
- package/src/js/api/SupportChecker.js +9 -3
- package/src/js/api/constants.js +203 -15
- package/src/js/api/media/Manager.js +15 -106
- package/src/js/api/provider/Controller.js +5 -6
- package/src/js/api/provider/html5/Provider.js +107 -86
- package/src/js/api/provider/html5/providers/Dash.js +39 -110
- package/src/js/api/provider/html5/providers/Hls.js +139 -99
- package/src/js/api/provider/html5/providers/Html5.js +3 -1
- package/src/js/api/provider/html5/providers/WebRTC.js +207 -37
- package/src/js/api/provider/html5/providers/WebRTCLoader.js +247 -116
- package/src/js/ovenplayer.js +5 -9
- package/src/js/ovenplayer.sdk.js +5 -6
- package/src/js/utils/browser.js +6 -1
- package/src/js/utils/getTouchSection.js +23 -0
- package/src/js/utils/likeA$.js +4 -3
- package/src/js/utils/resize-sensor.js +168 -1
- package/src/js/utils/underscore.js +5 -5
- package/src/js/view/components/controls/fullScreenButton.js +22 -15
- package/src/js/view/components/controls/main.js +33 -20
- package/src/js/view/components/controls/playlistPanel.js +1 -1
- package/src/js/view/components/controls/progressBar.js +151 -76
- package/src/js/view/components/controls/settingButton.js +65 -48
- package/src/js/view/components/controls/settingPanel/audioTrackPanel.js +57 -0
- package/src/js/view/components/controls/settingPanel/captionPanel.js +1 -1
- package/src/js/view/components/controls/settingPanel/main.js +110 -80
- package/src/js/view/components/controls/settingPanel/qualityPanel.js +2 -2
- package/src/js/view/components/controls/settingPanel/sourcePanel.js +1 -1
- package/src/js/view/components/controls/settingPanel/speedPanel.js +1 -1
- package/src/js/view/components/controls/settingPanel/timeDisplayPanel.js +1 -1
- package/src/js/view/components/controls/timeDisplay.js +95 -23
- package/src/js/view/components/controls/timeDisplayTemplate.js +1 -1
- package/src/js/view/components/controls/volumeButton.js +2 -3
- package/src/js/view/components/helpers/captionViewer.js +1 -1
- package/src/js/view/components/helpers/contextPanel.js +1 -1
- package/src/js/view/components/helpers/contextPanelTemplate.js +1 -1
- package/src/js/view/components/helpers/main.js +21 -0
- package/src/js/view/components/helpers/thumbnailTemplate.js +0 -1
- package/src/js/view/engine/Templates.js +2 -0
- package/src/js/view/view.js +53 -14
- package/src/js/view/viewTemplate.js +8 -8
- package/src/stylesheet/ovenplayer.less +565 -308
|
@@ -7,7 +7,7 @@ import LA$ from 'utils/likeA$';
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
const CaptionPanel = function($container, api, data){
|
|
10
|
-
const $root = LA$(
|
|
10
|
+
const $root = LA$(api.getContainerElement());
|
|
11
11
|
let panelManager = PanelManager();
|
|
12
12
|
|
|
13
13
|
data.setFront = function(isFront){
|
|
@@ -9,117 +9,133 @@ import sizeHumanizer from "utils/sizeHumanizer";
|
|
|
9
9
|
import SpeedPanel from "view/components/controls/settingPanel/speedPanel";
|
|
10
10
|
import SourcePanel from "view/components/controls/settingPanel/sourcePanel";
|
|
11
11
|
import QualityPanel from "view/components/controls/settingPanel/qualityPanel";
|
|
12
|
+
import AudioTrackPanel from "view/components/controls/settingPanel/audioTrackPanel";
|
|
12
13
|
import CaptionPanel from "view/components/controls/settingPanel/captionPanel";
|
|
13
14
|
import TimeDisplayPanel from "view/components/controls/settingPanel/timeDisplayPanel";
|
|
14
15
|
import {
|
|
15
16
|
CONTENT_LEVEL_CHANGED, PROVIDER_RTMP
|
|
16
17
|
} from "api/constants";
|
|
18
|
+
import {AUDIO_TRACK_CHANGED} from "../../../../api/constants";
|
|
17
19
|
|
|
18
20
|
let PANEL_TITLE = {
|
|
19
|
-
"speed"
|
|
20
|
-
"speedUnit"
|
|
21
|
-
"source"
|
|
22
|
-
"quality"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
21
|
+
"speed": "Speed",
|
|
22
|
+
"speedUnit": "x",
|
|
23
|
+
"source": "Source",
|
|
24
|
+
"quality": "Quality",
|
|
25
|
+
"audioTrack": "Audio",
|
|
26
|
+
"caption": "Caption",
|
|
27
|
+
"display": "Display"
|
|
25
28
|
};
|
|
26
29
|
|
|
27
|
-
const Panels = function($container, api, data){
|
|
30
|
+
const Panels = function ($container, api, data) {
|
|
28
31
|
|
|
29
|
-
const $root = LA$(
|
|
32
|
+
const $root = LA$(api.getContainerElement());
|
|
30
33
|
let panelManager = PanelManager();
|
|
31
34
|
|
|
32
35
|
let playerConfig = api.getConfig();
|
|
33
36
|
|
|
34
|
-
if(playerConfig && playerConfig.systemText){
|
|
37
|
+
if (playerConfig && playerConfig.systemText) {
|
|
35
38
|
Object.keys(PANEL_TITLE).forEach(title => {
|
|
36
39
|
PANEL_TITLE[title] = playerConfig.systemText.ui.setting[title];
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
function extractSubPanelData(api, panelType){
|
|
43
|
+
function extractSubPanelData(api, panelType) {
|
|
41
44
|
let panel = {
|
|
42
|
-
id
|
|
43
|
-
title
|
|
44
|
-
body
|
|
45
|
-
useCheck
|
|
46
|
-
panelType
|
|
47
|
-
height
|
|
45
|
+
id: "panel-" + new Date().getTime(),
|
|
46
|
+
title: "",
|
|
47
|
+
body: [],
|
|
48
|
+
useCheck: true,
|
|
49
|
+
panelType: panelType,
|
|
50
|
+
height: $root.height() - $root.find(".op-bottom-panel").height()
|
|
48
51
|
};
|
|
49
52
|
panel.title = PANEL_TITLE[panelType];
|
|
50
|
-
if(panelType === "speed"){
|
|
53
|
+
if (panelType === "speed") {
|
|
51
54
|
let playBackRates = api.getConfig().playbackRates;
|
|
52
55
|
let currentPlaybackRate = api.getPlaybackRate();
|
|
53
|
-
for (let i = 0; i < playBackRates.length; i
|
|
56
|
+
for (let i = 0; i < playBackRates.length; i++) {
|
|
54
57
|
let body = {
|
|
55
|
-
title
|
|
56
|
-
isCheck
|
|
57
|
-
value
|
|
58
|
-
description
|
|
59
|
-
panelType
|
|
58
|
+
title: playBackRates[i] + PANEL_TITLE.speedUnit, //(playBackRates[i] === 1? "Normal" : playBackRates[i]),
|
|
59
|
+
isCheck: currentPlaybackRate === playBackRates[i],
|
|
60
|
+
value: playBackRates[i],
|
|
61
|
+
description: playBackRates[i],
|
|
62
|
+
panelType: panelType
|
|
60
63
|
};
|
|
61
64
|
panel.body.push(body);
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
}else if(panelType === "source"){
|
|
67
|
+
} else if (panelType === "source") {
|
|
65
68
|
let sources = api.getSources();
|
|
66
|
-
for (let i = 0; i < sources.length; i
|
|
69
|
+
for (let i = 0; i < sources.length; i++) {
|
|
67
70
|
let body = {
|
|
68
|
-
title
|
|
69
|
-
isCheck
|
|
70
|
-
value
|
|
71
|
-
panelType
|
|
71
|
+
title: sources[i].label,
|
|
72
|
+
isCheck: api.getCurrentSource() === i,
|
|
73
|
+
value: i,
|
|
74
|
+
panelType: panelType
|
|
72
75
|
};
|
|
73
76
|
panel.body.push(body);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
}else if(panelType === "quality"){
|
|
79
|
+
} else if (panelType === "quality") {
|
|
77
80
|
let qualityLevels = api.getQualityLevels();
|
|
78
81
|
panel.body.push({
|
|
79
|
-
title
|
|
80
|
-
isCheck
|
|
81
|
-
value
|
|
82
|
-
panelType
|
|
82
|
+
title: "AUTO",
|
|
83
|
+
isCheck: api.isAutoQuality(),
|
|
84
|
+
value: "AUTO",
|
|
85
|
+
panelType: panelType
|
|
83
86
|
});
|
|
84
|
-
for (let i = 0; i < qualityLevels.length; i
|
|
87
|
+
for (let i = 0; i < qualityLevels.length; i++) {
|
|
85
88
|
let body = {
|
|
86
|
-
title
|
|
87
|
-
isCheck
|
|
88
|
-
value
|
|
89
|
-
panelType
|
|
89
|
+
title: qualityLevels[i].label,
|
|
90
|
+
isCheck: api.getCurrentQuality() === i,
|
|
91
|
+
value: i,
|
|
92
|
+
panelType: panelType
|
|
90
93
|
};
|
|
91
94
|
panel.body.push(body);
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
}else if(panelType === "
|
|
97
|
+
} else if (panelType === "audioTrack") {
|
|
98
|
+
let audioTracks = api.getAudioTracks();
|
|
99
|
+
|
|
100
|
+
for (let i = 0; i < audioTracks.length; i++) {
|
|
101
|
+
let body = {
|
|
102
|
+
title: audioTracks[i].label,
|
|
103
|
+
isCheck: audioTracks[i].index === api.getCurrentAudioTrack(),
|
|
104
|
+
value: audioTracks[i].index,
|
|
105
|
+
panelType: panelType
|
|
106
|
+
};
|
|
107
|
+
panel.body.push(body);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
} else if (panelType === "caption") {
|
|
95
111
|
let captions = api.getCaptionList();
|
|
96
112
|
panel.body.push({
|
|
97
|
-
title
|
|
98
|
-
isCheck
|
|
99
|
-
value
|
|
100
|
-
panelType
|
|
113
|
+
title: "OFF",
|
|
114
|
+
isCheck: api.getCurrentCaption() === -1,
|
|
115
|
+
value: -1,
|
|
116
|
+
panelType: panelType
|
|
101
117
|
});
|
|
102
|
-
for (let i = 0; i < captions.length; i
|
|
118
|
+
for (let i = 0; i < captions.length; i++) {
|
|
103
119
|
let body = {
|
|
104
|
-
title
|
|
105
|
-
isCheck
|
|
106
|
-
value
|
|
107
|
-
panelType
|
|
120
|
+
title: captions[i].label,
|
|
121
|
+
isCheck: api.getCurrentCaption() === i,
|
|
122
|
+
value: i,
|
|
123
|
+
panelType: panelType
|
|
108
124
|
};
|
|
109
125
|
panel.body.push(body);
|
|
110
126
|
}
|
|
111
127
|
|
|
112
|
-
}else if(panelType === "display"){
|
|
128
|
+
} else if (panelType === "display") {
|
|
113
129
|
let displayModes = [
|
|
114
130
|
"Play time",
|
|
115
131
|
"Framecode"
|
|
116
132
|
];
|
|
117
|
-
for (let i = 0; i < displayModes.length; i
|
|
133
|
+
for (let i = 0; i < displayModes.length; i++) {
|
|
118
134
|
let body = {
|
|
119
|
-
title
|
|
120
|
-
isCheck
|
|
121
|
-
value
|
|
122
|
-
panelType
|
|
135
|
+
title: displayModes[i],
|
|
136
|
+
isCheck: api.isTimecodeMode() ? (displayModes[i] === "Play time") : (displayModes[i] === "Framecode"),
|
|
137
|
+
value: displayModes[i],
|
|
138
|
+
panelType: panelType
|
|
123
139
|
};
|
|
124
140
|
panel.body.push(body);
|
|
125
141
|
}
|
|
@@ -128,74 +144,88 @@ const Panels = function($container, api, data){
|
|
|
128
144
|
return panel;
|
|
129
145
|
};
|
|
130
146
|
|
|
131
|
-
data.setFront = function(isFront){
|
|
132
|
-
if(isFront){
|
|
133
|
-
$root.find("#"+data.id).removeClass("background");
|
|
134
|
-
}else{
|
|
135
|
-
$root.find("#"+data.id).addClass("background");
|
|
147
|
+
data.setFront = function (isFront) {
|
|
148
|
+
if (isFront) {
|
|
149
|
+
$root.find("#" + data.id).removeClass("background");
|
|
150
|
+
} else {
|
|
151
|
+
$root.find("#" + data.id).addClass("background");
|
|
136
152
|
}
|
|
137
153
|
};
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
154
|
+
|
|
155
|
+
function setPanelMaxHeight() {
|
|
156
|
+
if ($root.find(".op-setting-panel")) {
|
|
157
|
+
$root.find(".op-setting-panel").css("max-height", $root.height() - $root.find(".op-bottom-panel").height() + "px");
|
|
141
158
|
}
|
|
142
159
|
};
|
|
143
|
-
const onRendered = function($current, template){
|
|
160
|
+
const onRendered = function ($current, template) {
|
|
144
161
|
setPanelMaxHeight();
|
|
145
162
|
|
|
146
|
-
api.on(CONTENT_LEVEL_CHANGED, function(data){
|
|
163
|
+
api.on(CONTENT_LEVEL_CHANGED, function (data) {
|
|
147
164
|
let newQuality = data.currentQuality;
|
|
148
|
-
if(data.type === "render" && $root.find("#"+template.data.id).find(".op-setting-item")){
|
|
149
|
-
_.forEach(
|
|
165
|
+
if (data.type === "render" && $root.find("#" + template.data.id).find(".op-setting-item")) {
|
|
166
|
+
_.forEach($root.find("#" + template.data.id).find(".op-setting-item").get() || [], function (panel) {
|
|
150
167
|
let $panel = LA$(panel);
|
|
151
168
|
|
|
152
|
-
if($panel.attr("op-panel-type") === "quality"){
|
|
169
|
+
if ($panel.attr("op-panel-type") === "quality") {
|
|
153
170
|
let qualityList = api.getQualityLevels();
|
|
154
171
|
let newQualityObject = qualityList[newQuality];
|
|
155
|
-
$panel.find(".op-setting-item-value").text(newQualityObject.width+"x"+newQualityObject.height+", "+ sizeHumanizer(newQualityObject.bitrate, true, "bps"));
|
|
172
|
+
$panel.find(".op-setting-item-value").text(newQualityObject.width + "x" + newQualityObject.height + ", " + sizeHumanizer(newQualityObject.bitrate, true, "bps"));
|
|
156
173
|
}
|
|
157
174
|
|
|
158
175
|
});
|
|
159
176
|
}
|
|
160
177
|
|
|
161
178
|
}, template);
|
|
179
|
+
|
|
180
|
+
api.on(AUDIO_TRACK_CHANGED, function (data) {
|
|
181
|
+
_.forEach($root.find("#" + template.data.id).find(".op-setting-item").get() || [], function (panel) {
|
|
182
|
+
|
|
183
|
+
let $panel = LA$(panel);
|
|
184
|
+
|
|
185
|
+
if($panel.attr("op-panel-type") === "audioTrack"){
|
|
186
|
+
$panel.find(".op-setting-item-value").text(api.getAudioTracks()[data.currentAudioTrack].label);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}, template);
|
|
162
190
|
};
|
|
163
|
-
const onDestroyed = function(template){
|
|
191
|
+
const onDestroyed = function (template) {
|
|
164
192
|
api.off(CONTENT_LEVEL_CHANGED, null, template);
|
|
193
|
+
api.off(AUDIO_TRACK_CHANGED, null, template);
|
|
165
194
|
};
|
|
166
195
|
const events = {
|
|
167
196
|
"click .op-setting-item": function (event, $current, template) {
|
|
168
197
|
event.preventDefault();
|
|
169
198
|
//if this panel is background it disabled click.
|
|
170
|
-
if($root.find("#"+data.id).hasClass("background")){
|
|
199
|
+
if ($root.find("#" + data.id).hasClass("background")) {
|
|
171
200
|
return false;
|
|
172
201
|
}
|
|
173
202
|
let panelType = LA$(event.currentTarget).attr("op-panel-type");
|
|
174
203
|
let panel = null;
|
|
175
|
-
if(panelType === "speed"){
|
|
204
|
+
if (panelType === "speed") {
|
|
176
205
|
panel = SpeedPanel($container, api, extractSubPanelData(api, panelType));
|
|
177
|
-
}else if(panelType === "source"){
|
|
206
|
+
} else if (panelType === "source") {
|
|
178
207
|
panel = SourcePanel($container, api, extractSubPanelData(api, panelType));
|
|
179
|
-
}else if(panelType === "quality"){
|
|
208
|
+
} else if (panelType === "quality") {
|
|
180
209
|
panel = QualityPanel($container, api, extractSubPanelData(api, panelType));
|
|
181
|
-
}else if(panelType === "
|
|
210
|
+
} else if (panelType === "audioTrack") {
|
|
211
|
+
panel = AudioTrackPanel($container, api, extractSubPanelData(api, panelType));
|
|
212
|
+
} else if (panelType === "caption") {
|
|
182
213
|
panel = CaptionPanel($container, api, extractSubPanelData(api, panelType));
|
|
183
|
-
}else if(panelType === "display"){
|
|
214
|
+
} else if (panelType === "display") {
|
|
184
215
|
panel = TimeDisplayPanel($container, api, extractSubPanelData(api, panelType));
|
|
185
216
|
}
|
|
186
217
|
|
|
187
218
|
panelManager.add(panel);
|
|
188
219
|
},
|
|
189
|
-
"click .op-setting-title"
|
|
220
|
+
"click .op-setting-title": function (event, $current, template) {
|
|
190
221
|
event.preventDefault();
|
|
191
|
-
if($root.find("#"+data.id).hasClass("background")){
|
|
222
|
+
if ($root.find("#" + data.id).hasClass("background")) {
|
|
192
223
|
return false;
|
|
193
224
|
}
|
|
194
225
|
panelManager.removeLastItem();
|
|
195
226
|
}
|
|
196
227
|
};
|
|
197
|
-
|
|
198
|
-
return OvenTemplate($container, "Panels", api.getConfig(), data, events, onRendered, onDestroyed );
|
|
228
|
+
return OvenTemplate($container, "Panels", api.getConfig(), data, events, onRendered, onDestroyed);
|
|
199
229
|
|
|
200
230
|
};
|
|
201
231
|
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "api/constants";
|
|
11
11
|
|
|
12
12
|
const QualityPanel = function($container, api, data){
|
|
13
|
-
const $root = LA$(
|
|
13
|
+
const $root = LA$(api.getContainerElement());
|
|
14
14
|
let panelManager = PanelManager();
|
|
15
15
|
|
|
16
16
|
data.setFront = function(isFront){
|
|
@@ -49,7 +49,7 @@ const QualityPanel = function($container, api, data){
|
|
|
49
49
|
event.preventDefault();
|
|
50
50
|
let value = LA$(event.currentTarget).attr("op-data-value");
|
|
51
51
|
if(value === "AUTO"){
|
|
52
|
-
api.setAutoQuality(
|
|
52
|
+
api.setAutoQuality(!api.isAutoQuality());
|
|
53
53
|
}else{
|
|
54
54
|
api.setCurrentQuality(parseInt(value));
|
|
55
55
|
}
|
|
@@ -7,7 +7,7 @@ import LA$ from 'utils/likeA$';
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
const SourcePanel = function($container, api, data){
|
|
10
|
-
const $root = LA$(
|
|
10
|
+
const $root = LA$(api.getContainerElement());
|
|
11
11
|
let panelManager = PanelManager();
|
|
12
12
|
|
|
13
13
|
data.setFront = function(isFront){
|
|
@@ -7,7 +7,7 @@ import LA$ from 'utils/likeA$';
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
const SpeedPanel = function($container, api, data){
|
|
10
|
-
const $root = LA$(
|
|
10
|
+
const $root = LA$(api.getContainerElement());
|
|
11
11
|
let panelManager = PanelManager();
|
|
12
12
|
|
|
13
13
|
data.setFront = function(isFront){
|
|
@@ -7,7 +7,7 @@ import LA$ from 'utils/likeA$';
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
const TimeDisplayPanel = function($container, api, data){
|
|
10
|
-
const $root = LA$(
|
|
10
|
+
const $root = LA$(api.getContainerElement());
|
|
11
11
|
let panelManager = PanelManager();
|
|
12
12
|
|
|
13
13
|
data.setFront = function(isFront){
|
|
@@ -2,61 +2,133 @@
|
|
|
2
2
|
* Created by hoho on 2018. 7. 25..
|
|
3
3
|
*/
|
|
4
4
|
import OvenTemplate from "view/engine/OvenTemplate";
|
|
5
|
-
import {naturalHms} from "utils/strings";
|
|
5
|
+
import { naturalHms } from "utils/strings";
|
|
6
6
|
import {
|
|
7
7
|
CONTENT_TIME,
|
|
8
|
-
CONTENT_TIME_MODE_CHANGED
|
|
8
|
+
CONTENT_TIME_MODE_CHANGED,
|
|
9
|
+
PROVIDER_HLS,
|
|
10
|
+
PROVIDER_HTML5
|
|
9
11
|
} from "api/constants";
|
|
10
12
|
|
|
11
|
-
const TimeDisplay = function($container, api, data){
|
|
13
|
+
const TimeDisplay = function ($container, api, data) {
|
|
12
14
|
|
|
13
|
-
let $position = "", $duration = "";
|
|
15
|
+
let $position = "", $duration = "", $liveBadge = "", $liveText = "";
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
const mediaElement = api.getMediaElement();
|
|
18
|
+
|
|
19
|
+
let hlsLive = false;
|
|
20
|
+
let nativeHlsLive = false;
|
|
21
|
+
|
|
22
|
+
function convertHumanizeTime(time) {
|
|
16
23
|
return naturalHms(time);
|
|
17
|
-
}
|
|
24
|
+
}
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
|
|
27
|
+
function getNativeHlsDvrWindow() {
|
|
28
|
+
return mediaElement.seekable.end(mediaElement.seekable.length - 1) - mediaElement.seekable.start(0);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const onRendered = function ($current, template) {
|
|
20
32
|
let isTimecode = api.isTimecodeMode();
|
|
21
33
|
$position = $current.find(".op-time-current");
|
|
22
34
|
$duration = $current.find(".op-time-duration");
|
|
35
|
+
$liveBadge = $current.find(".op-live-badge");
|
|
36
|
+
$liveText = $current.find(".op-live-text");
|
|
37
|
+
|
|
38
|
+
if (data && data.type === PROVIDER_HLS && data.duration === Infinity) {
|
|
39
|
+
hlsLive = true;
|
|
23
40
|
|
|
24
|
-
|
|
41
|
+
if (api.getProviderName() === PROVIDER_HTML5) {
|
|
42
|
+
nativeHlsLive = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (data.duration !== Infinity) {
|
|
25
47
|
|
|
26
|
-
if(isTimecode){
|
|
48
|
+
if (isTimecode) {
|
|
27
49
|
$duration.text(convertHumanizeTime(data.duration));
|
|
28
|
-
}else{
|
|
29
|
-
$duration.text(
|
|
50
|
+
} else {
|
|
51
|
+
$duration.text(Math.round(data.duration * api.getFramerate()) + " (" + api.getFramerate() + "fps)");
|
|
30
52
|
}
|
|
31
53
|
|
|
32
|
-
api.on(CONTENT_TIME_MODE_CHANGED, function(isTimecodeMode){
|
|
54
|
+
api.on(CONTENT_TIME_MODE_CHANGED, function (isTimecodeMode) {
|
|
33
55
|
isTimecode = isTimecodeMode;
|
|
34
|
-
if(isTimecode){
|
|
56
|
+
if (isTimecode) {
|
|
35
57
|
$duration.text(convertHumanizeTime(data.duration));
|
|
36
|
-
}else{
|
|
37
|
-
$duration.text(
|
|
58
|
+
} else {
|
|
59
|
+
$duration.text(Math.round(data.duration * api.getFramerate()) + " (" + api.getFramerate() + "fps)");
|
|
38
60
|
}
|
|
39
|
-
},template);
|
|
61
|
+
}, template);
|
|
40
62
|
|
|
41
|
-
api.on(CONTENT_TIME, function(data) {
|
|
42
|
-
if(isTimecode){
|
|
63
|
+
api.on(CONTENT_TIME, function (data) {
|
|
64
|
+
if (isTimecode) {
|
|
43
65
|
$position.text(convertHumanizeTime(data.position));
|
|
44
|
-
}else{
|
|
45
|
-
$position.text(
|
|
66
|
+
} else {
|
|
67
|
+
$position.text(Math.round(data.position * api.getFramerate()));
|
|
46
68
|
}
|
|
47
|
-
},template);
|
|
69
|
+
}, template);
|
|
70
|
+
} else {
|
|
71
|
+
if (hlsLive && !nativeHlsLive) {
|
|
72
|
+
api.on(CONTENT_TIME, function (data) {
|
|
73
|
+
|
|
74
|
+
if (data.duration - data.position > 3) {
|
|
75
|
+
$liveBadge.addClass('op-live-badge-delayed');
|
|
76
|
+
} else {
|
|
77
|
+
$liveBadge.removeClass('op-live-badge-delayed');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}, template);
|
|
81
|
+
} else if (hlsLive && nativeHlsLive) {
|
|
82
|
+
|
|
83
|
+
api.on(CONTENT_TIME, function (data) {
|
|
84
|
+
const dvrWindow = getNativeHlsDvrWindow();
|
|
85
|
+
if (dvrWindow - data.position > 3) {
|
|
86
|
+
$liveBadge.addClass('op-live-badge-delayed');
|
|
87
|
+
} else {
|
|
88
|
+
$liveBadge.removeClass('op-live-badge-delayed');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
}, template);
|
|
92
|
+
}
|
|
48
93
|
}
|
|
49
94
|
|
|
50
95
|
};
|
|
51
|
-
|
|
96
|
+
|
|
97
|
+
const onDestroyed = function (template) {
|
|
52
98
|
api.off(CONTENT_TIME_MODE_CHANGED, null, template);
|
|
53
99
|
api.off(CONTENT_TIME, null, template);
|
|
54
100
|
};
|
|
55
101
|
const events = {
|
|
102
|
+
"click .op-live-text": function (event, $current, template) {
|
|
103
|
+
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
|
|
106
|
+
api.seek(Number.MAX_SAFE_INTEGER);
|
|
107
|
+
|
|
108
|
+
//When playback get back to the latest, turn the latency control back on.
|
|
109
|
+
const config = api.getConfig();
|
|
110
|
+
if (config.hlsConfig) {
|
|
56
111
|
|
|
112
|
+
const hlsConfig = config.hlsConfig;
|
|
113
|
+
if (typeof hlsConfig.liveSyncDuration === 'number') {
|
|
114
|
+
api.getMseInstance().config.liveSyncDuration
|
|
115
|
+
= hlsConfig.liveSyncDuration;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (typeof hlsConfig.liveMaxLatencyDuration === 'number') {
|
|
119
|
+
api.getMseInstance().config.liveMaxLatencyDuration
|
|
120
|
+
= hlsConfig.liveMaxLatencyDuration;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (typeof hlsConfig.maxLiveSyncPlaybackRate === 'number') {
|
|
124
|
+
api.getMseInstance().config.maxLiveSyncPlaybackRate =
|
|
125
|
+
hlsConfig.maxLiveSyncPlaybackRate;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
57
129
|
};
|
|
58
130
|
|
|
59
|
-
return OvenTemplate($container, "TimeDisplay", api.getConfig(), data, events, onRendered, onDestroyed
|
|
131
|
+
return OvenTemplate($container, "TimeDisplay", api.getConfig(), data, events, onRendered, onDestroyed);
|
|
60
132
|
};
|
|
61
133
|
|
|
62
134
|
|
|
@@ -10,7 +10,7 @@ export default (uiText, data) => {
|
|
|
10
10
|
`<span class="op-live-badge-lowlatency">${uiText.controls.low_latency_p2p}</span>` : `<span class="op-live-badge-lowlatency">${uiText.controls.low_latency_live}</span>`
|
|
11
11
|
)
|
|
12
12
|
:
|
|
13
|
-
`<span>${uiText.controls.live}</span>`) +
|
|
13
|
+
`<span class="op-live-text" title="Skip ahead to live.">${uiText.controls.live}</span>`) +
|
|
14
14
|
`</span>`
|
|
15
15
|
)
|
|
16
16
|
:(`<span class="op-time-current">00:00</span><span class="op-time-separator"> / </span><span class="op-time-duration">00:00</span>`)
|
|
@@ -93,12 +93,11 @@ const VolumeButton = function($container, api){
|
|
|
93
93
|
|
|
94
94
|
$sliderHandle.css("left", maxRange+ "px");
|
|
95
95
|
|
|
96
|
+
setVolumeUI(api.getVolume());
|
|
97
|
+
|
|
96
98
|
api.on(READY, function() {
|
|
97
99
|
setVolumeUI(api.getVolume());
|
|
98
100
|
}, template);
|
|
99
|
-
api.on(PLAYER_PLAY, function (data) {
|
|
100
|
-
setVolumeUI(data.volume);
|
|
101
|
-
}, template);
|
|
102
101
|
api.on(CONTENT_VOLUME, function(data) {
|
|
103
102
|
|
|
104
103
|
setVolumeUI(data.volume);
|
|
@@ -14,7 +14,7 @@ import LA$ from 'utils/likeA$';
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
const CaptionViewer = function($container, api, playerState){
|
|
17
|
-
const $root = LA$(
|
|
17
|
+
const $root = LA$(api.getContainerElement());
|
|
18
18
|
|
|
19
19
|
const onRendered = function($container, $current, template){
|
|
20
20
|
let isDisable = false;
|
|
@@ -5,7 +5,7 @@ import OvenTemplate from 'view/engine/OvenTemplate';
|
|
|
5
5
|
import LA$ from 'utils/likeA$';
|
|
6
6
|
|
|
7
7
|
const ContextPanel = function($container, api, position){
|
|
8
|
-
const $root = LA$(
|
|
8
|
+
const $root = LA$(api.getContainerElement());
|
|
9
9
|
|
|
10
10
|
const onRendered = function($current, template){
|
|
11
11
|
const panelWidth = $current.width();
|
|
@@ -3,7 +3,7 @@ export default (uiText) => {
|
|
|
3
3
|
return (
|
|
4
4
|
`<div class="op-context-panel animated fadeIn">` +
|
|
5
5
|
`<div class="op-context-item" tabindex="1">` +
|
|
6
|
-
`<span class="op-context-item-text">${uiText.context}</span>` +
|
|
6
|
+
`<span class="op-context-item-text">${uiText.context} ${version}</span>` +
|
|
7
7
|
`</div>`+
|
|
8
8
|
`</div>`
|
|
9
9
|
);
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
PLAYER_STATE,
|
|
30
30
|
ALL_PLAYLIST_ENDED,
|
|
31
31
|
CONTENT_LEVEL_CHANGED,
|
|
32
|
+
CONTENT_SOURCE_CHANGED,
|
|
32
33
|
NETWORK_UNSTABLED,
|
|
33
34
|
UI_ICONS
|
|
34
35
|
} from "api/constants";
|
|
@@ -76,9 +77,22 @@ const Helpers = function($container, api){
|
|
|
76
77
|
messageBox = MessageBox($current, api, message, description, withTimer, iconClass, clickCallback, dontClose);
|
|
77
78
|
}
|
|
78
79
|
function createThumbnail(){
|
|
80
|
+
|
|
81
|
+
const mediaElement = api.getMediaElement();
|
|
82
|
+
|
|
83
|
+
if (mediaElement) {
|
|
84
|
+
mediaElement.poster = ''
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (api.getConfig().image) {
|
|
88
|
+
mediaElement.poster = api.getConfig().image;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
79
92
|
if(thumbnail){
|
|
80
93
|
thumbnail.destroy();
|
|
81
94
|
}
|
|
95
|
+
|
|
82
96
|
thumbnail = Thumbnail($current, api, api.getConfig());
|
|
83
97
|
}
|
|
84
98
|
function createWaterMark() {
|
|
@@ -188,6 +202,13 @@ const Helpers = function($container, api){
|
|
|
188
202
|
}
|
|
189
203
|
}, template);
|
|
190
204
|
|
|
205
|
+
api.on(CONTENT_SOURCE_CHANGED, function () {
|
|
206
|
+
|
|
207
|
+
if(hasThumbnail){
|
|
208
|
+
createThumbnail(); //shows when playlist changed.
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
191
212
|
//show spinner cuz dashjs spends long time for level change.
|
|
192
213
|
api.on(CONTENT_LEVEL_CHANGED, function(data){
|
|
193
214
|
if(data.currentQuality < 0 ){
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export default (uiText, data) => {
|
|
2
2
|
return (`<div class="op-thumbnail-container"><div class="op-thumbnail-wrapper">`+
|
|
3
|
-
`${data.image ? `<img src="${data.image}">`:``}` +
|
|
4
3
|
`${data.title ? `<div class="op-thumbnail-header">${data.title}</div>`:``}` +
|
|
5
4
|
`</div></div>`);
|
|
6
5
|
};
|
|
@@ -25,6 +25,7 @@ import PanelsTemplate from 'view/components/controls/settingPanel/mainTemplate';
|
|
|
25
25
|
import SpeedPanelTemplate from 'view/components/controls/settingPanel/mainTemplate';
|
|
26
26
|
import SourcePanelTemplate from 'view/components/controls/settingPanel/mainTemplate';
|
|
27
27
|
import QualityPanelTemplate from 'view/components/controls/settingPanel/mainTemplate';
|
|
28
|
+
import AudioTrackPanelTemplate from 'view/components/controls/settingPanel/mainTemplate';
|
|
28
29
|
import CaptionPanelTemplate from 'view/components/controls/settingPanel/mainTemplate';
|
|
29
30
|
import TimeDisplayPanelTemplate from 'view/components/controls/settingPanel/mainTemplate';
|
|
30
31
|
import PlaylistPanelTemplate from 'view/components/controls/playlistPanelTemplate';
|
|
@@ -53,6 +54,7 @@ const Templates = {
|
|
|
53
54
|
SpeedPanelTemplate,
|
|
54
55
|
SourcePanelTemplate,
|
|
55
56
|
QualityPanelTemplate,
|
|
57
|
+
AudioTrackPanelTemplate,
|
|
56
58
|
CaptionPanelTemplate,
|
|
57
59
|
TimeDisplayPanelTemplate,
|
|
58
60
|
PlaylistPanelTemplate
|