summaryrefslogtreecommitdiff
path: root/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js')
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js490
1 files changed, 490 insertions, 0 deletions
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js
new file mode 100644
index 00000000..9449a5d4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js
@@ -0,0 +1,490 @@
+/**
+ * mediaSource class represents a source for a media element.
+ *
+ * @param {Element}
+ * element: MIME type of the source.
+ * @constructor
+ */
+
+/**
+ * The base source attribute checks also see:
+ * http://dev.w3.org/html5/spec/Overview.html#the-source-element
+ */
+
+( function( mw, $ ) { "use strict";
+
+mw.mergeConfig( 'EmbedPlayer.SourceAttributes', [
+ // source id
+ 'id',
+
+ // media url
+ 'src',
+
+ // Title string for the source asset
+ 'title',
+
+ // boolean if we support temporal url requests on the source media
+ 'URLTimeEncoding',
+
+ // Store the node name for type identification
+ 'nodeName',
+
+ /**
+ * data- attributes ( not yet standards )
+ */
+
+ // Media has a startOffset ( used for plugins that
+ // display ogg page time rather than presentation time
+ 'data-startoffset',
+
+ // A hint to the duration of the media file so that duration
+ // can be displayed in the player without loading the media file
+ 'data-durationhint',
+
+ // Source stream qualities
+ // NOTE data- is striped from the attribute as we build out the "mediaSource" object
+ 'data-shorttitle', // short title for stream ( useful for stream switching control bar widget)
+ 'data-width', // the width of the stream
+ 'data-height', // the height of the stream
+ 'data-bandwidth', // the overall bitrate of the stream in bytes
+ 'data-sizebytes', // the size of the stream in bytes
+ 'data-framerate', // the framereate of the stream
+ 'data-flavorid', // a source flavor id ( useful for targeting devices )
+ 'data-aspect', // the aspect ratio, useful for adaptive protocal urls that don't have a strict height / width
+
+ // Used as title in download panel
+ 'data-title',
+
+ // Used for download attribute on mediawiki
+ 'data-mwtitle',
+ // used for setting the api provider for mediawiki
+ 'data-mwprovider',
+
+ // to disable menu or timedText for a given embed
+ 'data-disablecontrols',
+
+ // used for language direction of subtitles
+ 'data-dir',
+
+ // Media start time
+ 'start',
+
+ // Media end time
+ 'end',
+
+ // If the source is the default source
+ 'default'
+] );
+
+mw.MediaSource = function( element ) {
+ this.init( element );
+};
+
+mw.MediaSource.prototype = {
+ // MIME type of the source.
+ mimeType:null,
+
+ // URI of the source.
+ uri:null,
+
+ // Title of the source.
+ title: null,
+
+ // True if the source has been marked as the default.
+ markedDefault: false,
+
+ // True if the source supports url specification of offset and duration
+ URLTimeEncoding:false,
+
+ // Start offset of the requested segment
+ startOffset: 0,
+
+ // Duration of the requested segment (0 if not known)
+ duration:0,
+
+ // source id
+ id: null,
+
+ // Start time in npt format
+ startNpt: null,
+
+ // End time in npt format
+ endNpt: null,
+
+ // Language of the file
+ srclang: null,
+ /**
+ * MediaSource constructor:
+ */
+ init : function( element ) {
+ var _this = this;
+ // mw.log('EmbedPlayer::adding mediaSource: ' + element);
+ this.src = $( element ).attr( 'src' );
+
+ // Set default URLTimeEncoding if we have a time url:
+ // not ideal way to discover if content is on an oggz_chop server.
+ // should check some other way.
+ var pUrl = new mw.Uri ( this.src );
+ if ( typeof pUrl.query[ 't' ] != 'undefined' ) {
+ this.URLTimeEncoding = true;
+ }
+
+ var sourceAttr = mw.config.get( 'EmbedPlayer.SourceAttributes' );
+ $.each( sourceAttr, function( inx, attr ){
+ if ( $( element ).attr( attr ) ) {
+ // strip data- from the attribute name
+ var attrName = ( attr.indexOf('data-') === 0) ? attr.substr(5) : attr
+ _this[ attrName ] = $( element ).attr( attr );
+ }
+ });
+
+ // Normalize "label" to "title" ( label is the actual spec so use that over title )
+ if( this.label ){
+ this.title = this.label;
+ }
+
+ // Set the content type:
+ if ( $( element ).attr( 'type' ) ) {
+ this.mimeType = $( element ).attr( 'type' );
+ }else if ( $( element ).attr( 'content-type' ) ) {
+ this.mimeType = $( element ).attr( 'content-type' );
+ }else if( $( element )[0].tagName.toLowerCase() == 'audio' ){
+ // If the element is an "audio" tag set audio format
+ this.mimeType = 'audio/ogg';
+ } else {
+ this.mimeType = this.detectType( this.src );
+ }
+
+ // Conform the mime type to ogg
+ if( this.mimeType == 'video/theora') {
+ this.mimeType = 'video/ogg';
+ }
+
+ if( this.mimeType == 'audio/vorbis') {
+ this.mimeType = 'audio/ogg';
+ }
+
+ // Check for parent elements ( supplies categories in "track" )
+ if( $( element ).parent().attr('category') ) {
+ this.category = $( element ).parent().attr('category');
+ }
+
+ if( $( element ).attr( 'default' ) ){
+ this.markedDefault = true;
+ }
+
+ // Get the url duration ( if applicable )
+ this.getURLDuration();
+ },
+
+ /**
+ * Update Source title via Element
+ *
+ * @param {Element}
+ * element Source element to update attributes from
+ */
+ updateSource: function( element ) {
+ // for now just update the title:
+ if ( $( element ).attr( "title" ) ) {
+ this.title = $( element ).attr( "title" );
+ }
+ },
+
+ /**
+ * Updates the src time and start & end
+ *
+ * @param {String}
+ * start_time: in NPT format
+ * @param {String}
+ * end_time: in NPT format
+ */
+ updateSrcTime: function ( startNpt, endNpt ) {
+ // mw.log("f:updateSrcTime: "+ startNpt+'/'+ endNpt + ' from org: ' +
+ // this.startNpt+ '/'+this.endNpt);
+ // mw.log("pre uri:" + this.src);
+ // if we have time we can use:
+ if ( this.URLTimeEncoding ) {
+ // make sure its a valid start time / end time (else set default)
+ if ( !mw.npt2seconds( startNpt ) ) {
+ startNpt = this.startNpt;
+ }
+
+ if ( !mw.npt2seconds( endNpt ) ) {
+ endNpt = this.endNpt;
+ }
+
+ this.src = mw.replaceUrlParams( this.src, {
+ 't': startNpt + '/' + endNpt
+ });
+
+ // update the duration
+ this.getURLDuration();
+ }
+ },
+
+ /**
+ * Sets the duration and sets the end time if unset
+ *
+ * @param {Float}
+ * duration: in seconds
+ */
+ setDuration: function ( duration ) {
+ this.duration = duration;
+ if ( !this.endNpt ) {
+ this.endNpt = mw.seconds2npt( this.startOffset + duration );
+ }
+ },
+
+ /**
+ * MIME type accessor function.
+ *
+ * @return {String} the MIME type of the source.
+ */
+ getMIMEType: function() {
+ if( this.mimeType ) {
+ return this.mimeType;
+ }
+ this.mimeType = this.detectType( this.src );
+ return this.mimeType;
+ },
+ /**
+ * Update the local src
+ * @param {String}
+ * src The URL to the media asset
+ */
+ setSrc: function( src ){
+ this.src = src;
+ },
+
+ /**
+ * URI function.
+ *
+ * @param {Number}
+ * serverSeekTime Int: Used to adjust the URI for url based
+ * seeks)
+ * @return {String} the URI of the source.
+ */
+ getSrc: function( serverSeekTime ) {
+ if ( !serverSeekTime || !this.URLTimeEncoding ) {
+ return this.src;
+ }
+ var endvar = '';
+ if ( this.endNpt ) {
+ endvar = '/' + this.endNpt;
+ }
+ return mw.replaceUrlParams( this.src,
+ {
+ 't': mw.seconds2npt( serverSeekTime ) + endvar
+ }
+ );
+ },
+ /**
+ * Title accessor function.
+ *
+ * @return {String} Title of the source.
+ */
+ getTitle : function() {
+ if( this.title ){
+ return this.title;
+ }
+ // Text tracks use "label" instead of "title"
+ if( this.label ){
+ return this.label;
+ }
+
+ // Return a Title based on mime type:
+ var mimeType = this.getMIMEType().split( ';' )[0];
+ switch( mimeType ) {
+ case 'video/h264' :
+ case 'video/mp4' :
+ return mw.msg( 'mwe-embedplayer-video-h264' );
+ break;
+ case 'video/x-flv' :
+ return mw.msg( 'mwe-embedplayer-video-flv' );
+ break;
+ case 'video/webm' :
+ return mw.msg( 'mwe-embedplayer-video-webm');
+ break;
+ case 'video/ogg' :
+ return mw.msg( 'mwe-embedplayer-video-ogg' );
+ break;
+ case 'audio/ogg' :
+ return mw.msg( 'mwe-embedplayer-video-audio' );
+ break;
+ case 'audio/mpeg' :
+ return mw.msg('mwe-embedplayer-audio-mpeg');
+ break;
+ case 'video/3gp' :
+ return mw.msg('mwe-embedplayer-video-3gp');
+ break;
+ case 'video/mpeg' :
+ return mw.msg('mwe-embedplayer-video-mpeg');
+ break;
+ case 'video/x-msvideo' :
+ return mw.msg('mwe-embedplayer-video-msvideo' );
+ break;
+ }
+
+ // Return title based on file name:
+ try{
+ var fileName = new mw.Uri( mw.absoluteUrl( this.getSrc() ) ).path.split('/').pop();
+ if( fileName ){
+ return fileName;
+ }
+ } catch(e){}
+
+ // Return the mime type string if not known type.
+ return this.mimeType;
+ },
+ /**
+ * Get a short title for the stream
+ */
+ getShortTitle: function(){
+ var _this =this;
+ if( this.shorttitle ){
+ return this.shorttitle;
+ }
+ // Just use a short "long title"
+ var longTitle = this.getTitle();
+ if(longTitle.length > 20) {
+ longTitle = longTitle.substring(0,17)+"...";
+ }
+ return longTitle
+ },
+ /**
+ *
+ * Get Duration of the media in milliseconds from the source url.
+ *
+ * Supports media_url?t=ntp_start/ntp_end url request format
+ */
+ getURLDuration : function() {
+ // check if we have a URLTimeEncoding:
+ if ( this.URLTimeEncoding ) {
+ var annoURL = new mw.Uri( this.src );
+ if ( annoURL.query.t ) {
+ var times = annoURL.query.t.split( '/' );
+ this.startNpt = times[0];
+ this.endNpt = times[1];
+ this.startOffset = mw.npt2seconds( this.startNpt );
+ this.duration = mw.npt2seconds( this.endNpt ) - this.startOffset;
+ } else {
+ // look for this info as attributes
+ if ( this.startOffset ) {
+ this.startNpt = mw.seconds2npt( this.startOffset );
+ }
+ if ( this.duration ) {
+ this.endNpt = mw.seconds2npt( parseInt( this.duration ) + parseInt( this.startOffset ) );
+ }
+ }
+ }
+ },
+ /**
+ * Get the extension of a url
+ * @param String uri
+ */
+ getExt : function( uri ){
+ var urlParts = new mw.Uri( uri );
+ // Get the extension from the url or from the relative name:
+ var ext = ( urlParts.file ) ? /[^.]+$/.exec( urlParts.file ) : /[^.]+$/.exec( uri );
+ // remove the hash string if present
+ ext = /[^#]*/g.exec( ext.toString() );
+ ext = ext || '';
+ return ext.toString().toLowerCase();
+ },
+ /**
+ * Get the flavorId if available.
+ */
+ getFlavorId: function(){
+ if( this.flavorid ){
+ return this.flavorid;
+ }
+ return ;
+ },
+
+ /**
+ * Attempts to detect the type of a media file based on the URI.
+ *
+ * @param {String}
+ * uri URI of the media file.
+ * @return {String} The guessed MIME type of the file.
+ */
+ detectType: function( uri ) {
+ // NOTE: if media is on the same server as the javascript
+ // we can issue a HEAD request and read the mime type of the media...
+ // ( this will detect media mime type independently of the url name )
+ // http://www.jibbering.com/2002/4/httprequest.html
+ switch( this.getExt( uri ) ) {
+ case 'smil':
+ case 'sml':
+ return 'application/smil';
+ break;
+ case 'm4v':
+ case 'mp4':
+ return 'video/h264';
+ break;
+ case 'm3u8':
+ return 'application/vnd.apple.mpegurl';
+ break;
+ case 'webm':
+ return 'video/webm';
+ break;
+ case '3gp':
+ return 'video/3gp';
+ break;
+ case 'srt':
+ return 'text/x-srt';
+ break;
+ case 'flv':
+ return 'video/x-flv';
+ break;
+ case 'ogg':
+ case 'ogv':
+ return 'video/ogg';
+ break;
+ case 'oga':
+ return 'audio/ogg';
+ break;
+ case 'mp3':
+ return 'audio/mpeg';
+ case 'm4a':
+ return 'audio/mp4';
+ break;
+ case 'anx':
+ return 'video/ogg';
+ break;
+ case 'xml':
+ return 'text/xml';
+ break;
+ case 'avi':
+ return 'video/x-msvideo';
+ break;
+ case 'mpg':
+ return 'video/mpeg';
+ break;
+ case 'mpeg':
+ return 'video/mpeg';
+ break;
+ }
+ mw.log( "Error: could not detect type of media src: " + uri );
+ },
+ /**
+ * bitrate is mesured in kbs rather than bandwith bytes per second
+ */
+ getBitrate: function() {
+ if( this.bandwidth ){
+ return this.bandwidth / 1024;
+ }
+ return 0;
+ },
+ /**
+ * Get the size of the stream in bytes
+ */
+ getSize: function(){
+ if( this.sizebytes ){
+ return this.sizebytes;
+ }
+ return 0;
+ }
+};
+
+} )( mediaWiki, jQuery );