nuvio-tizen 1.8.12 → 1.8.13
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.
Potentially problematic release.
This version of nuvio-tizen might be problematic. Click here for more details.
- package/config.xml +1 -1
- package/index.html +9 -9
- package/js/player.js +43 -5
- package/package.json +1 -1
package/config.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets"
|
|
3
|
-
id="http://nuvio.tizen/NuvioTizen" version="1.8.
|
|
3
|
+
id="http://nuvio.tizen/NuvioTizen" version="1.8.13" viewmodes="maximized">
|
|
4
4
|
<tizen:application id="Nuvio00001.Nuvio" package="Nuvio00001" required_version="2.4"/>
|
|
5
5
|
<content src="index.html"/>
|
|
6
6
|
<feature name="http://tizen.org/feature/screen.size.all"/>
|
package/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=1920, height=1080, user-scalable=no">
|
|
6
6
|
<title>Nuvio</title>
|
|
7
|
-
<link rel="stylesheet" href="css/style.css?v=1.8.
|
|
7
|
+
<link rel="stylesheet" href="css/style.css?v=1.8.13">
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<!-- CSS-applied sentinel (kept off-screen); app.js waits for its width before rendering -->
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
|
|
48
48
|
<!-- Load order matters: polyfills -> util -> data -> input -> player -> views -> app -->
|
|
49
49
|
<!-- ?v= busts the TV webview cache on every release (keep in sync with package.json) -->
|
|
50
|
-
<script src="js/polyfills.js?v=1.8.
|
|
51
|
-
<script src="js/util.js?v=1.8.
|
|
52
|
-
<script src="js/stremio.js?v=1.8.
|
|
53
|
-
<script src="js/keys.js?v=1.8.
|
|
54
|
-
<script src="js/focus.js?v=1.8.
|
|
55
|
-
<script src="js/player.js?v=1.8.
|
|
56
|
-
<script src="js/views.js?v=1.8.
|
|
57
|
-
<script src="js/app.js?v=1.8.
|
|
50
|
+
<script src="js/polyfills.js?v=1.8.13"></script>
|
|
51
|
+
<script src="js/util.js?v=1.8.13"></script>
|
|
52
|
+
<script src="js/stremio.js?v=1.8.13"></script>
|
|
53
|
+
<script src="js/keys.js?v=1.8.13"></script>
|
|
54
|
+
<script src="js/focus.js?v=1.8.13"></script>
|
|
55
|
+
<script src="js/player.js?v=1.8.13"></script>
|
|
56
|
+
<script src="js/views.js?v=1.8.13"></script>
|
|
57
|
+
<script src="js/app.js?v=1.8.13"></script>
|
|
58
58
|
</body>
|
|
59
59
|
</html>
|
package/js/player.js
CHANGED
|
@@ -54,6 +54,12 @@ var Player = (function () {
|
|
|
54
54
|
var _barOpen = false;
|
|
55
55
|
var _barIdx = 0;
|
|
56
56
|
|
|
57
|
+
// seek robustness (AVPlay can error if you seek mid-buffer)
|
|
58
|
+
var _buffering = false;
|
|
59
|
+
var _pendingSeek = null;
|
|
60
|
+
var _lastSeekAt = 0;
|
|
61
|
+
var _seekRecovering = false;
|
|
62
|
+
|
|
57
63
|
var _active = false;
|
|
58
64
|
var _onExit = null;
|
|
59
65
|
var _ctx = null; // { id, type, name, poster, resumeSec }
|
|
@@ -161,6 +167,7 @@ var Player = (function () {
|
|
|
161
167
|
_audioIdx = null;
|
|
162
168
|
_menuOpen = false; _barOpen = false;
|
|
163
169
|
_segments = null; _creditsSec = null; _creditsHandled = false; _segShown = {};
|
|
170
|
+
_buffering = false; _pendingSeek = null; _lastSeekAt = 0; _seekRecovering = false;
|
|
164
171
|
hideSkip();
|
|
165
172
|
subsEl.className = 'hidden'; U.clear(subsEl);
|
|
166
173
|
subMenuEl.className = 'hidden';
|
|
@@ -222,11 +229,26 @@ var Player = (function () {
|
|
|
222
229
|
try {
|
|
223
230
|
avplay.open(url);
|
|
224
231
|
avplay.setListener({
|
|
225
|
-
onbufferingstart: function () { U.spinner(true); },
|
|
226
|
-
onbufferingcomplete: function () {
|
|
232
|
+
onbufferingstart: function () { _buffering = true; U.spinner(true); },
|
|
233
|
+
onbufferingcomplete: function () {
|
|
234
|
+
_buffering = false; U.spinner(false);
|
|
235
|
+
if (_pendingSeek != null) { var pt = _pendingSeek; _pendingSeek = null; doAVSeek(pt, 0); }
|
|
236
|
+
},
|
|
227
237
|
onstreamcompleted: function () { _cur = _dur; onEnded(); },
|
|
228
238
|
oncurrentplaytime: function (ms) { _cur = ms / 1000; onProgress(); },
|
|
229
|
-
onerror: function (err) {
|
|
239
|
+
onerror: function (err) {
|
|
240
|
+
U.spinner(false);
|
|
241
|
+
// A seek can throw a transient error on some HLS streams. If we just
|
|
242
|
+
// sought, try to recover (resume) instead of ending playback.
|
|
243
|
+
if (Date.now() - _lastSeekAt < 6000 && !_seekRecovering) {
|
|
244
|
+
_seekRecovering = true;
|
|
245
|
+
try { avplay.play(); } catch (e) {}
|
|
246
|
+
setTimeout(function () { _seekRecovering = false; }, 4000);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
U.toast('Playback error: ' + err);
|
|
250
|
+
setTimeout(exit, 1500);
|
|
251
|
+
}
|
|
230
252
|
});
|
|
231
253
|
try { avplay.setStreamingProperty('ADAPTIVE_INFO', 'BITRATES=1'); } catch (e0) {}
|
|
232
254
|
avplay.prepareAsync(function () {
|
|
@@ -395,17 +417,33 @@ var Player = (function () {
|
|
|
395
417
|
|
|
396
418
|
function seekTo(sec) {
|
|
397
419
|
if (_isLive) { showOSD(false); U.toast('Live — seeking unavailable', 1500); return; }
|
|
398
|
-
|
|
420
|
+
// keep a small margin from the very end (seeking to EOF can error)
|
|
421
|
+
var maxT = _dur ? Math.max(0, _dur - 2) : 1e9;
|
|
422
|
+
var target = Math.max(0, Math.min(maxT, sec));
|
|
399
423
|
_cur = target;
|
|
400
424
|
renderOSD();
|
|
401
425
|
showOSD(false);
|
|
402
426
|
if (useAV) {
|
|
403
|
-
|
|
427
|
+
// Don't seek while buffering — queue it until buffering completes.
|
|
428
|
+
if (_buffering) { _pendingSeek = target; U.spinner(true); return; }
|
|
429
|
+
doAVSeek(target, 0);
|
|
404
430
|
} else {
|
|
405
431
|
try { videoEl.currentTime = target; } catch (e2) {}
|
|
406
432
|
}
|
|
407
433
|
}
|
|
408
434
|
|
|
435
|
+
// Seek only when AVPlay is in a seekable state; retry briefly otherwise.
|
|
436
|
+
function doAVSeek(targetSec, attempt) {
|
|
437
|
+
_lastSeekAt = Date.now();
|
|
438
|
+
var st = '';
|
|
439
|
+
try { st = avplay.getState(); } catch (e) {}
|
|
440
|
+
if (st === 'PLAYING' || st === 'PAUSED' || st === 'READY') {
|
|
441
|
+
try { avplay.seekTo(Math.floor(targetSec * 1000)); } catch (e2) { /* non-fatal */ }
|
|
442
|
+
} else if (attempt < 4 && _active) {
|
|
443
|
+
setTimeout(function () { if (_active) { doAVSeek(targetSec, attempt + 1); } }, 350);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
409
447
|
function seekBy(delta) { seekTo(_cur + delta); }
|
|
410
448
|
|
|
411
449
|
// ---------- subtitles ----------
|