diff --git a/src/js/player.js b/src/js/player.js index 4bde35f1e8..40f6d26ed4 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -2208,7 +2208,7 @@ class Player extends Component { this.currentType_ = src.type; - middleware.setSource(Fn.bind(this, this.setTimeout), src, (src_, mws) => { + middleware.setSource(this, src, (src_, mws) => { this.middleware_ = mws; const err = this.src_(src_); diff --git a/src/js/tech/middleware.js b/src/js/tech/middleware.js index a1f9c73d38..8cf901b424 100644 --- a/src/js/tech/middleware.js +++ b/src/js/tech/middleware.js @@ -15,8 +15,8 @@ export function getMiddleware(type) { return middlewares; } -export function setSource(setTimeout, src, next) { - setTimeout(() => setSourceHelper(src, middlewares[src.type], next), 1); +export function setSource(player, src, next) { + player.setTimeout(() => setSourceHelper(src, middlewares[src.type], next, player), 1); } export function setTech(middleware, tech) { @@ -32,8 +32,11 @@ export function set(middleware, tech, method, arg) { } export const allowedGetters = { + buffered: 1, currentTime: 1, - duration: 1 + duration: 1, + seekable: 1, + played: 1 }; export const allowedSetters = { @@ -50,21 +53,24 @@ function middlewareIterator(method) { }; } -function setSourceHelper(src = {}, middleware = [], next, acc = []) { - const [mw, ...mwrest] = middleware; +function setSourceHelper(src = {}, middleware = [], next, player, acc = [], lastRun = false) { + const [mwFactory, ...mwrest] = middleware; - // if mw is a string, then we're at a fork in the road - if (typeof mw === 'string') { - setSourceHelper(src, middlewares[mw], next, acc); + // if mwFactory is a string, then we're at a fork in the road + if (typeof mwFactory === 'string') { + setSourceHelper(src, middlewares[mwFactory], next, player, acc, lastRun); + + // if we have an mwFactory, call it with the player to get the mw, + // then call the mw's setSource method + } else if (mwFactory) { + const mw = mwFactory(player); - // if we have an mw, call its setSource method - } else if (mw) { mw.setSource(assign({}, src), function(err, _src) { // something happened, try the next middleware on the current level // make sure to use the old src if (err) { - return setSourceHelper(src, mwrest, next, acc); + return setSourceHelper(src, mwrest, next, player, acc, lastRun); } // we've succeeded, now we need to go deeper @@ -75,11 +81,15 @@ function setSourceHelper(src = {}, middleware = [], next, acc = []) { setSourceHelper(_src, src.type === _src.type ? mwrest : middlewares[_src.type], next, - acc); + player, + acc, + lastRun); }); } else if (mwrest.length) { - setSourceHelper(src, mwrest, next, acc); - } else { + setSourceHelper(src, mwrest, next, player, acc, lastRun); + } else if (lastRun) { next(src, acc); + } else { + setSourceHelper(src, middlewares['*'], next, player, acc, true); } } diff --git a/src/js/tech/tech.js b/src/js/tech/tech.js index 1384b0a2ad..aef6dc9cf8 100644 --- a/src/js/tech/tech.js +++ b/src/js/tech/tech.js @@ -11,7 +11,6 @@ import { bufferedPercent } from '../utils/buffer.js'; import MediaError from '../media-error.js'; import window from 'global/window'; import document from 'global/document'; -import * as middleware from './middleware.js'; import {isPlain} from '../utils/obj'; import * as TRACK_TYPES from '../tracks/track-types'; @@ -799,8 +798,6 @@ class Tech extends Component { throw new Error('Techs must have a static canPlaySource method on them'); } - middleware.use('*', {name, tech}); - Tech.techs_[name] = tech; return tech; } diff --git a/test/unit/player.test.js b/test/unit/player.test.js index 4b21e5181d..b00f0555b6 100644 --- a/test/unit/player.test.js +++ b/test/unit/player.test.js @@ -1411,7 +1411,7 @@ QUnit.test('techGet runs through middleware if allowedGetter', function(assert) let durs = 0; let ps = 0; - videojs.use('video/foo', { + videojs.use('video/foo', () => ({ currentTime() { cts++; }, @@ -1421,14 +1421,14 @@ QUnit.test('techGet runs through middleware if allowedGetter', function(assert) paused() { ps++; } - }); + })); const tag = TestHelpers.makeTag(); const player = videojs(tag, { techOrder: ['techFaker'] }); - player.middleware_ = middleware.getMiddleware('video/foo'); + player.middleware_ = [middleware.getMiddleware('video/foo')[0](player)]; player.techGet_('currentTime'); player.techGet_('duration'); @@ -1446,7 +1446,7 @@ QUnit.test('techCall runs through middleware if allowedSetter', function(assert) let cts = 0; let vols = 0; - videojs.use('video/foo', { + videojs.use('video/foo', () => ({ setCurrentTime(ct) { cts++; return ct; @@ -1454,14 +1454,14 @@ QUnit.test('techCall runs through middleware if allowedSetter', function(assert) setVolume() { vols++; } - }); + })); const tag = TestHelpers.makeTag(); const player = videojs(tag, { techOrder: ['techFaker'] }); - player.middleware_ = middleware.getMiddleware('video/foo'); + player.middleware_ = [middleware.getMiddleware('video/foo')[0](player)]; this.clock.tick(1); @@ -1492,23 +1492,23 @@ QUnit.test('src selects tech based on middleware', function(assert) { videojs.registerTech('FooTech', FooTech); videojs.registerTech('BarTech', BarTech); - videojs.use('video/foo', { + videojs.use('video/foo', () => ({ setSource(src, next) { next(null, { src: 'http://example.com/video.mp4', type: 'video/mp4' }); } - }); + })); - videojs.use('video/bar', { + videojs.use('video/bar', () => ({ setSource(src, next) { next(null, { src: 'http://example.com/video.flv', type: 'video/flv' }); } - }); + })); const tag = TestHelpers.makeTag(); const player = videojs(tag, { diff --git a/test/unit/tech/middleware.test.js b/test/unit/tech/middleware.test.js index 47c0c0a37f..71faf4f550 100644 --- a/test/unit/tech/middleware.test.js +++ b/test/unit/tech/middleware.test.js @@ -14,10 +14,11 @@ QUnit.module('Middleware', { QUnit.test('middleware can be added with the use method', function(assert) { const myMw = {}; + const mwFactory = () => myMw; - middleware.use('foo', myMw); + middleware.use('foo', mwFactory); - assert.equal(middleware.getMiddleware('foo').pop(), myMw, 'we are able to add middleware'); + assert.equal(middleware.getMiddleware('foo').pop(), mwFactory, 'we are able to add middleware'); }); QUnit.test('middleware get iterates through the middleware array the right order', function(assert) { @@ -147,7 +148,9 @@ QUnit.test('setSource is run asynchronously', function(assert) { let src; let acc; - middleware.setSource(window.setTimeout, { src: 'foo', type: 'video/foo' }, function(_src, _acc) { + middleware.setSource({ + setTimeout: window.setTimeout + }, { src: 'foo', type: 'video/foo' }, function(_src, _acc) { src = _src; acc = _acc; }); @@ -172,10 +175,13 @@ QUnit.test('setSource selects a source based on the middleware given', function( }); } }; + const fooFactory = () => mw; - middleware.use('video/foo', mw); + middleware.use('video/foo', fooFactory); - middleware.setSource(window.setTimeout, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { + middleware.setSource({ + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { src = _src; acc = _acc; }); @@ -209,11 +215,15 @@ QUnit.test('setSource can select multiple middleware from multiple types', funct }); } }; + const fooFactory = () => foomw; + const barFactory = () => barmw; - middleware.use('video/foo', foomw); - middleware.use('video/bar', barmw); + middleware.use('video/foo', fooFactory); + middleware.use('video/bar', barFactory); - middleware.setSource(window.setTimeout, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { + middleware.setSource({ + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { src = _src; acc = _acc; }); @@ -257,12 +267,17 @@ QUnit.test('setSource will select all middleware of a given type, until src chan }); } }; + const fooFactory1 = () => foomw1; + const fooFactory2 = () => foomw2; + const fooFactory3 = () => foomw3; - middleware.use('video/foo', foomw1); - middleware.use('video/foo', foomw2); - middleware.use('video/foo', foomw3); + middleware.use('video/foo', fooFactory1); + middleware.use('video/foo', fooFactory2); + middleware.use('video/foo', fooFactory3); - middleware.setSource(window.setTimeout, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { + middleware.setSource({ + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { src = _src; acc = _acc; });