Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move manual events into tech controller #1415

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/js/media/flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ vjs.Flash.prototype.src = function(src){
vjs.Flash.prototype['setCurrentTime'] = function(time){
this.lastSeekTarget_ = time;
this.el_.vjs_setProperty('currentTime', time);
vjs.MediaTechController.prototype.setCurrentTime.call(this);
};

vjs.Flash.prototype['currentTime'] = function(time){
Expand Down
113 changes: 113 additions & 0 deletions src/js/media/media.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ vjs.MediaTechController = vjs.Component.extend({
options.reportTouchActivity = false;
vjs.Component.call(this, player, options, ready);

// Manually track progress in cases where the browser/flash player doesn't report it.
if (!this.features['progressEvents']) {
this.manualProgressOn();
}

// Manually track timeudpates in cases where the browser/flash player doesn't report it.
if (!this.features['timeupdateEvents']) {
this.manualTimeUpdatesOn();
}

this.initControlsListeners();
}
});
Expand Down Expand Up @@ -153,6 +163,109 @@ vjs.MediaTechController.prototype.onTap = function(){
this.player().userActive(!this.player().userActive());
};

/* Fallbacks for unsupported event types
================================================================================ */
// Manually trigger progress events based on changes to the buffered amount
// Many flash players and older HTML5 browsers don't send progress or progress-like events
vjs.MediaTechController.prototype.manualProgressOn = function(){
this.manualProgress = true;

// Trigger progress watching when a source begins loading
this.trackProgress();

// Watch for a native progress event call on the tech element
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless you think otherwise, let's kill this native event listener. It was needed when certain browsers didn't support these events, e.g. firefox 3.5 or Safari 3. As far as I know even devices are consistent with these events now.

If we do that we also need to set those features to true on the html5 video tech, so that these are never turned on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And delete all the wonderful tests you wrote around that feature. :(

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will shed a tear for my beautiful tests but I agree it's better to get rid of that outdated browser support if it's feasible. I'll double check on the worst Android phone I can find just to be sure.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these events are still being relied on by the Flash tech to display the buffer state in the progress bar. We could move these into the Flash tech but I think that might be better handled in a separate patch. Your thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we talking about the same thing? I mean remove the this.one('progress', function(){ that listens for the real events incase they do exist, not removing the manual events all together. Flash should never have the real events.

// In HTML5, some older versions don't support the progress event
// So we're assuming they don't, and turning off manual progress if they do.
// As opposed to doing user agent detection
this.one('progress', function(){

// Update known progress support for this playback technology
this.features['progressEvents'] = true;

// Turn off manual progress tracking
this.manualProgressOff();
});
};

vjs.MediaTechController.prototype.manualProgressOff = function(){
this.manualProgress = false;
this.stopTrackingProgress();
};

vjs.MediaTechController.prototype.trackProgress = function(){

this.progressInterval = setInterval(vjs.bind(this, function(){
// Don't trigger unless buffered amount is greater than last time

var bufferedPercent = this.player().bufferedPercent();

if (this.bufferedPercent_ != bufferedPercent) {
this.player().trigger('progress');
}

this.bufferedPercent_ = bufferedPercent;

if (bufferedPercent === 1) {
this.stopTrackingProgress();
}
}), 500);
};
vjs.MediaTechController.prototype.stopTrackingProgress = function(){ clearInterval(this.progressInterval); };

/*! Time Tracking -------------------------------------------------------------- */
vjs.MediaTechController.prototype.manualTimeUpdatesOn = function(){
this.manualTimeUpdates = true;

this.player().on('play', vjs.bind(this, this.trackCurrentTime));
this.player().on('pause', vjs.bind(this, this.stopTrackingCurrentTime));
// timeupdate is also called by .currentTime whenever current time is set

// Watch for native timeupdate event
this.one('timeupdate', function(){
// Update known progress support for this playback technology
this.features['timeupdateEvents'] = true;
// Turn off manual progress tracking
this.manualTimeUpdatesOff();
});
};

vjs.MediaTechController.prototype.manualTimeUpdatesOff = function(){
this.manualTimeUpdates = false;
this.stopTrackingCurrentTime();
this.off('play', this.trackCurrentTime);
this.off('pause', this.stopTrackingCurrentTime);
};

vjs.MediaTechController.prototype.trackCurrentTime = function(){
if (this.currentTimeInterval) { this.stopTrackingCurrentTime(); }
this.currentTimeInterval = setInterval(vjs.bind(this, function(){
this.player().trigger('timeupdate');
}), 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
};

// Turn off play progress tracking (when paused or dragging)
vjs.MediaTechController.prototype.stopTrackingCurrentTime = function(){
clearInterval(this.currentTimeInterval);

// #1002 - if the video ends right before the next timeupdate would happen,
// the progress bar won't make it all the way to the end
this.player().trigger('timeupdate');
};

vjs.MediaTechController.prototype.dispose = function() {
// Turn off any manual progress or timeupdate tracking
if (this.manualProgress) { this.manualProgressOff(); }

if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); }

vjs.Component.prototype.dispose.call(this);
};

vjs.MediaTechController.prototype.setCurrentTime = function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we added a listener to the seeking event instead of having this in the setCurrentTime function? That would avoid needing this include in the sub-techs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good thinking.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not seeing seeking or seeked events coming from the Flash player so this won't work. Defer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeking should be in there.
2f5c9b6f1d919220201f0c1f0bc113a2271a/src/com/videojs/providers/HTTPVideoProvider.as#L522

But I believe we're currently trigger it directly on the player in the case of flash, in case you were listening for it on the tech or the object itself.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice, doesn't seem to be working. Filed videojs/video-js-swf#114 to track it.

// improve the accuracy of manual timeupdates
if (this.manualTimeUpdates) { this.player().trigger('timeupdate'); }
};

/**
* Provide a default setPoster method for techs
*
Expand Down
113 changes: 0 additions & 113 deletions src/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,6 @@ vjs.Player.prototype.dispose = function(){
if (this.tag && this.tag['player']) { this.tag['player'] = null; }
if (this.el_ && this.el_['player']) { this.el_['player'] = null; }

// Ensure that tracking progress and time progress will stop and plater deleted
this.stopTrackingProgress();
this.stopTrackingCurrentTime();

if (this.tech) { this.tech.dispose(); }

// Component dispose
Expand Down Expand Up @@ -311,16 +307,6 @@ vjs.Player.prototype.loadTech = function(techName, source){

var techReady = function(){
this.player_.triggerReady();

// Manually track progress in cases where the browser/flash player doesn't report it.
if (!this.features['progressEvents']) {
this.player_.manualProgressOn();
}

// Manually track timeudpates in cases where the browser/flash player doesn't report it.
if (!this.features['timeupdateEvents']) {
this.player_.manualTimeUpdatesOn();
}
};

// Grab tech-specific options from player options and add source and parent element to use.
Expand All @@ -344,11 +330,6 @@ vjs.Player.prototype.loadTech = function(techName, source){
vjs.Player.prototype.unloadTech = function(){
this.isReady_ = false;

// Turn off any manual progress or timeupdate tracking
if (this.manualProgress) { this.manualProgressOff(); }

if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); }

this.tech.dispose();

this.tech = false;
Expand All @@ -368,98 +349,7 @@ vjs.Player.prototype.unloadTech = function(){
// vjs.log('loadedTech')
// },

/* Fallbacks for unsupported event types
================================================================================ */
// Manually trigger progress events based on changes to the buffered amount
// Many flash players and older HTML5 browsers don't send progress or progress-like events
vjs.Player.prototype.manualProgressOn = function(){
this.manualProgress = true;

// Trigger progress watching when a source begins loading
this.trackProgress();

// Watch for a native progress event call on the tech element
// In HTML5, some older versions don't support the progress event
// So we're assuming they don't, and turning off manual progress if they do.
// As opposed to doing user agent detection
if (this.tech) {
this.tech.one('progress', function(){

// Update known progress support for this playback technology
this.features['progressEvents'] = true;

// Turn off manual progress tracking
this.player_.manualProgressOff();
});
}
};

vjs.Player.prototype.manualProgressOff = function(){
this.manualProgress = false;
this.stopTrackingProgress();
};

vjs.Player.prototype.trackProgress = function(){

this.progressInterval = setInterval(vjs.bind(this, function(){
// Don't trigger unless buffered amount is greater than last time

var bufferedPercent = this.bufferedPercent();

if (this.cache_.bufferedPercent != bufferedPercent) {
this.trigger('progress');
}

this.cache_.bufferedPercent = bufferedPercent;

if (bufferedPercent == 1) {
this.stopTrackingProgress();
}
}), 500);
};
vjs.Player.prototype.stopTrackingProgress = function(){ clearInterval(this.progressInterval); };

/*! Time Tracking -------------------------------------------------------------- */
vjs.Player.prototype.manualTimeUpdatesOn = function(){
this.manualTimeUpdates = true;

this.on('play', this.trackCurrentTime);
this.on('pause', this.stopTrackingCurrentTime);
// timeupdate is also called by .currentTime whenever current time is set

// Watch for native timeupdate event
if (this.tech) {
this.tech.one('timeupdate', function(){
// Update known progress support for this playback technology
this.features['timeupdateEvents'] = true;
// Turn off manual progress tracking
this.player_.manualTimeUpdatesOff();
});
}
};

vjs.Player.prototype.manualTimeUpdatesOff = function(){
this.manualTimeUpdates = false;
this.stopTrackingCurrentTime();
this.off('play', this.trackCurrentTime);
this.off('pause', this.stopTrackingCurrentTime);
};

vjs.Player.prototype.trackCurrentTime = function(){
if (this.currentTimeInterval) { this.stopTrackingCurrentTime(); }
this.currentTimeInterval = setInterval(vjs.bind(this, function(){
this.trigger('timeupdate');
}), 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
};

// Turn off play progress tracking (when paused or dragging)
vjs.Player.prototype.stopTrackingCurrentTime = function(){
clearInterval(this.currentTimeInterval);

// #1002 - if the video ends right before the next timeupdate would happen,
// the progress bar won't make it all the way to the end
this.trigger('timeupdate');
};
// /* Player event handlers (how the player reacts to certain events)
// ================================================================================ */

Expand Down Expand Up @@ -782,9 +672,6 @@ vjs.Player.prototype.currentTime = function(seconds){

this.techCall('setCurrentTime', seconds);

// improve the accuracy of manual timeupdates
if (this.manualTimeUpdates) { this.trigger('timeupdate'); }

return this;
}

Expand Down
1 change: 1 addition & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
'test/unit/mediafaker.js',
'test/unit/player.js',
'test/unit/core.js',
'test/unit/media.js',
'test/unit/media.html5.js',
'test/unit/controls.js',
'test/unit/poster.js',
Expand Down
2 changes: 2 additions & 0 deletions test/sinon-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ function sinon(){}
sinon.stub = function(){};
sinon.spy = function(){};
sinon.mock = function(){};
sinon.useFakeTimers = function(){};
sinon.clock.tick = function(){};

Function.prototype.alwaysCalledOn = function(){};
Function.prototype.alwaysCalledWith = function(){};
Expand Down
3 changes: 3 additions & 0 deletions test/unit/flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ test('currentTime is the seek target during seeking', function() {
parentEl = document.createElement('div'),
tech = new vjs.Flash({
id: noop,
bufferedPercent: noop,
on: noop,
trigger: noop,
options_: {}
}, {
'parentEl': parentEl
Expand Down Expand Up @@ -103,6 +105,7 @@ test('dispose removes the object element even before ready fires', function() {
tech = new vjs.Flash({
id: noop,
on: noop,
trigger: noop,
options_: {}
}, {
'parentEl': parentEl
Expand Down
4 changes: 3 additions & 1 deletion test/unit/media.html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ module('HTML5', {
el: function(){ return el; },
options_: {},
options: function(){ return {}; },
bufferedPercent: function() { return 0; },
controls: function(){ return false; },
usingNativeControls: function(){ return false; },
on: function(){ return this; },
off: function() { return this; },
ready: function(){}
ready: function(){},
trigger: function(){}
};
tech = new vjs.Html5(player, {});
},
Expand Down
Loading