1
0
mirror of https://github.com/videojs/video.js.git synced 2024-12-25 02:42:10 +02:00

@dmlap use seekable on source handlers when defined. closes #2376

This commit is contained in:
David LaPalomento 2015-07-21 17:12:24 -04:00
parent 52bbd468d5
commit d3d5d032fc
5 changed files with 82 additions and 9 deletions

View File

@ -70,6 +70,7 @@ CHANGELOG
* @dmlap switched events to not bubble by default ([view](https://github.com/videojs/video.js/pull/2351))
* @dmlap export videojs.createTimeRange ([view](https://github.com/videojs/video.js/pull/2361))
* @dmlap export a basic played() on techs ([view](https://github.com/videojs/video.js/pull/2384))
* @dmlap use seekable on source handlers when defined ([view](https://github.com/videojs/video.js/pull/2376))
--------------------

View File

@ -164,9 +164,16 @@ class Flash extends Tech {
* @method setCurrentTime
*/
setCurrentTime(time) {
this.lastSeekTarget_ = time;
this.el_.vjs_setProperty('currentTime', time);
super.setCurrentTime();
let seekable = this.seekable();
if (seekable.length) {
// clamp to the current seekable range
time = time > seekable.start(0) ? time : seekable.start(0);
time = time < seekable.end(seekable.length - 1) ? time : seekable.end(seekable.length - 1);
this.lastSeekTarget_ = time;
this.el_.vjs_setProperty('currentTime', time);
super.setCurrentTime();
}
}
/**

View File

@ -565,6 +565,16 @@ Tech.withSourceHandlers = function(_Tech){
this.sourceHandler_ = sh.handleSource(source, this);
this.on('dispose', this.disposeSourceHandler);
this.originalSeekable_ = this.seekable;
// when a source handler is registered, prefer its implementation of
// seekable when present.
this.seekable = function() {
if (this.sourceHandler_ && this.sourceHandler_.seekable) {
return this.sourceHandler_.seekable();
}
return this.originalSeekable_.call(this);
};
return this;
};
@ -574,6 +584,7 @@ Tech.withSourceHandlers = function(_Tech){
_Tech.prototype.disposeSourceHandler = function(){
if (this.sourceHandler_ && this.sourceHandler_.dispose) {
this.sourceHandler_.dispose();
this.seekable = this.originalSeekable_;
}
};

View File

@ -1,4 +1,5 @@
import Flash from '../../../src/js/tech/flash.js';
import { createTimeRange } from '../../../src/js/utils/time-ranges.js';
import document from 'global/document';
q.module('Flash');
@ -30,14 +31,17 @@ test('currentTime', function() {
// Mock out a Flash instance to avoid creating the swf object
let mockFlash = {
el_: {
vjs_setProperty: function(prop, val){
vjs_setProperty(prop, val){
setPropVal = val;
},
vjs_getProperty: function(){
vjs_getProperty(){
return getPropVal;
}
},
seeking: function(){
seekable(){
return createTimeRange(5, 1000);
},
seeking(){
return seeking;
}
};
@ -57,6 +61,15 @@ test('currentTime', function() {
result = getCurrentTime.call(mockFlash);
equal(result, 20, 'currentTime is retrieved from the lastSeekTarget while seeking');
notEqual(result, getPropVal, 'currentTime is not retrieved from the element while seeking');
// clamp seeks to seekable
setCurrentTime.call(mockFlash, 1001);
result = getCurrentTime.call(mockFlash);
equal(result, mockFlash.seekable().end(0), 'clamped to the seekable end');
setCurrentTime.call(mockFlash, 1);
result = getCurrentTime.call(mockFlash);
equal(result, mockFlash.seekable().start(0), 'clamped to the seekable start');
});
test('dispose removes the object element even before ready fires', function() {
@ -141,3 +154,10 @@ test('seekable', function() {
result = seekable.call(mockFlash);
equal(result.length, mockFlash.duration_, 'seekable is empty with a zero duration');
});
// fake out the <object> interaction but leave all the other logic intact
class MockFlash extends Flash {
constructor() {
super({});
}
}

View File

@ -1,6 +1,7 @@
var noop = function() {}, clock, oldTextTracks;
import Tech from '../../../src/js/tech/tech.js';
import { createTimeRange } from '../../../src/js/utils/time-ranges.js';
q.module('Media Tech', {
'setup': function() {
@ -97,7 +98,7 @@ test('dispose() should stop time tracking', function() {
ok(true, 'no exception was thrown');
});
test('should add the source hanlder interface to a tech', function(){
test('should add the source handler interface to a tech', function(){
var sourceA = { src: 'foo.mp4', type: 'video/mp4' };
var sourceB = { src: 'no-support', type: 'no-support' };
@ -176,7 +177,7 @@ test('should add the source hanlder interface to a tech', function(){
ok(disposeCalled, 'the handler dispose method was called when the tech was disposed');
});
test('should handle unsupported sources with the source hanlder API', function(){
test('should handle unsupported sources with the source handler API', function(){
// Define a new tech class
var MyTech = Tech.extend();
// Extend Tech with source handlers
@ -197,7 +198,40 @@ test('should track whether a video has played', function() {
let tech = new Tech();
equal(tech.played().length, 0, 'starts with zero length');
tech.trigger('playing');
equal(tech.played().length, 1, 'has length after playing');
});
test('delegates seekable to the source handler', function(){
let MyTech = Tech.extend({
seekable: function() {
throw new Error('You should not be calling me!');
}
});
Tech.withSourceHandlers(MyTech);
let seekableCount = 0;
let handler = {
seekable: function() {
seekableCount++;
return createTimeRange(0, 0);
}
};
MyTech.registerSourceHandler({
canHandleSource: function() {
return true;
},
handleSource: function(source, tech) {
return handler;
}
});
let tech = new MyTech();
tech.setSource({
src: 'example.mp4',
type: 'video/mp4'
});
tech.seekable();
equal(seekableCount, 1, 'called the source handler');
});