summaryrefslogtreecommitdiff
path: root/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js')
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js222
1 files changed, 222 insertions, 0 deletions
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js
new file mode 100644
index 00000000..791459f3
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js
@@ -0,0 +1,222 @@
+( function( mw, $ ) { "use strict";
+
+var support = mw.OgvJsSupport;
+
+mw.EmbedPlayerOgvJs = {
+
+ // Instance name:
+ instanceOf: 'OgvJs',
+
+ // Supported feature set of the OGVPlayer widget:
+ supports: {
+ 'playHead' : true,
+ 'pause' : true,
+ 'stop' : true,
+ 'fullscreen' : true,
+ 'sourceSwitch': true,
+ 'timeDisplay' : true,
+ 'volumeControl' : false,
+ 'overlays': true,
+ 'timedText': true
+ },
+
+ /**
+ * Perform setup in response to a play start command.
+ * This means loading the code asynchronously if needed,
+ * and enabling web audio for iOS Safari inside the event
+ * handler.
+ *
+ * @return jQuery.Deferred
+ */
+ _ogvJsPreInit: function() {
+ if( mw.isIOS() ) {
+ this._initializeAudioForiOS();
+ }
+ return support.loadOgvJs();
+ },
+
+ /**
+ * Actually initialize the player.
+ *
+ * @return OGVPlayer
+ */
+ _ogvJsInit: function() {
+ var options = {};
+ if ( this._iOSAudioContext ) {
+ // Reuse the audio context we opened earlier
+ options.audioContext = this._iOSAudioContext;
+ }
+ return new OGVPlayer( options );
+ },
+
+ _iOSAudioContext: undefined,
+
+ _initializeAudioForiOS: function() {
+ // iOS Safari Web Audio API must be initialized from an input event handler
+ if ( this._iOSAudioContext ) {
+ return;
+ }
+ this._iOSAudioContext = support.initAudioContext();
+ },
+
+ /**
+ * Output the the embed html
+ */
+ embedPlayerHTML: function (optionalCallback) {
+
+ $( this )
+ .empty()
+ .append( $.createSpinner( {
+ size: 'large',
+ type: 'block'
+ } ) );
+
+ var _this = this;
+ if( mw.isIOS() ) {
+ _this._initializeAudioForiOS();
+ }
+ support.loadOgvJs().done( function() {
+
+ var player = _this._ogvJsInit();
+ player.id = _this.pid;
+ player.style.width = '100%';
+ player.style.height = '100%';
+ player.src = _this.getSrc();
+ if ( _this.getDuration() ) {
+ player.durationHint = parseFloat( _this.getDuration() );
+ }
+ player.addEventListener('ended', function() {
+ _this.onClipDone();
+ });
+
+ // simulate timeupdate events, needed for subtitles
+ // @todo switch this to native timeupdate event when available upstream
+ var lastTime = 0,
+ timeupdateInterval = 0.25;
+ player.addEventListener( 'framecallback', function( event ) {
+ var player = _this.getPlayerElement(),
+ now = player ? player.currentTime : lastTime;
+ // Don't spam time updates on every frame
+ if ( Math.abs( now - lastTime ) >= timeupdateInterval ) {
+ lastTime = now;
+ $( _this ).trigger( 'timeupdate', [event, _this.id] );
+ }
+ });
+
+ $( _this ).empty().append( player );
+ player.play();
+
+ // Start the monitor:
+ _this.monitor();
+
+ if ( optionalCallback ) {
+ optionalCallback();
+ }
+ });
+ },
+
+ /**
+ * Get the embed player time
+ */
+ getPlayerElementTime: function() {
+ this.getPlayerElement();
+ var currentTime = 0;
+ if ( this.playerElement ) {
+ currentTime = this.playerElement.currentTime;
+ } else {
+ mw.log( "EmbedPlayerOgvJs:: Could not find playerElement" );
+ }
+ return currentTime;
+ },
+
+ /**
+ * Update the playerElement instance with a pointer to the embed object
+ */
+ getPlayerElement: function() {
+ // this.pid is in the form 'pid_mwe_player_<number>'; inherited from mw.EmbedPlayer.js
+ var $el = $( '#' + this.pid );
+ if( !$el.length ) {
+ return false;
+ }
+ this.playerElement = $el.get( 0 );
+ return this.playerElement;
+ },
+
+ /**
+ * Issue the doPlay request to the playerElement
+ * calls parent_play to update interface
+ */
+ play: function() {
+ this.getPlayerElement();
+ this.parent_play();
+ if ( this.playerElement ) {
+ this.playerElement.play();
+ // Restart the monitor if on second playthrough
+ this.monitor();
+ }
+ },
+
+ /**
+ * Pause playback
+ * calls parent_pause to update interface
+ */
+ pause: function() {
+ this.getPlayerElement();
+ // Update the interface
+ this.parent_pause();
+ // Call the pause function if it exists:
+ if ( this.playerElement ) {
+ this.playerElement.pause();
+ }
+ },
+
+ /**
+ * Switch the source!
+ * For simplicity we just replace the player here.
+ */
+ playerSwitchSource: function( source, switchCallback, doneCallback ){
+ var _this = this;
+ var src = source.getSrc();
+ var vid = this.getPlayerElement();
+ if ( typeof vid.stop !== 'undefined' ) {
+ vid.stop();
+ }
+
+ switchCallback();
+
+ // Currently have to tear down the player and make a new one
+ this.embedPlayerHTML( doneCallback );
+ },
+
+ /**
+ * Seek in the ogg stream
+ * @param {Float} percentage Percentage to seek into the stream
+ */
+ seek: function( percentage ) {
+ this.setCurrentTime( percentage * parseFloat( this.getDuration() ) );
+ },
+
+ setCurrentTime: function( time, callback ) {
+ this.getPlayerElement();
+
+ if ( this.playerElement ) {
+ this.playerElement.currentTime = time;
+ }
+
+ this.currentTime = time;
+ this.previousTime = time; // prevent weird double-seek. MwEmbedPlyer is weird!
+
+ // Run the onSeeking interface update
+ this.controlBuilder.onSeek();
+ // @todo add proper events upstream
+ if( this.seeking ){
+ this.seeking = false;
+ $( this ).trigger( 'seeked' );
+ }
+ if ( $.isFunction( callback ) ) {
+ callback();
+ }
+ }
+};
+
+} )( mediaWiki, jQuery );