Index: trunk/extensions/TimedMediaHandler/TimedTextPage.php |
— | — | @@ -74,6 +74,6 @@ |
75 | 75 | if( !$this->exists() ){ |
76 | 76 | return wfMessage( 'timedmedia-subtitle-no-subtitles', $languageName ); |
77 | 77 | } |
78 | | - return '<pre style="margin-top:0px;">'. $this->getContent() . "</pre>"; |
| 78 | + return '<pre style="margin-top:0px;">'. $this->getContent() . '</pre>''; |
79 | 79 | } |
80 | 80 | } |
\ No newline at end of file |
Index: trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaElement.js |
— | — | @@ -43,14 +43,16 @@ |
44 | 44 | this.sources = new Array(); |
45 | 45 | |
46 | 46 | // Process the videoElement as a source element: |
47 | | - if ( $( videoElement ).attr( "src" ) ) { |
48 | | - _this.tryAddSource( videoElement ); |
| 47 | + if( videoElement ){ |
| 48 | + if ( $( videoElement ).attr( "src" ) ) { |
| 49 | + _this.tryAddSource( videoElement ); |
| 50 | + } |
| 51 | + |
| 52 | + // Process elements source children |
| 53 | + $( videoElement ).find( 'source,track' ).each( function( ) { |
| 54 | + _this.tryAddSource( this ); |
| 55 | + } ); |
49 | 56 | } |
50 | | - |
51 | | - // Process elements source children |
52 | | - $( videoElement ).find( 'source,track' ).each( function( ) { |
53 | | - _this.tryAddSource( this ); |
54 | | - } ); |
55 | 57 | }, |
56 | 58 | |
57 | 59 | /** |
— | — | @@ -113,7 +115,7 @@ |
114 | 116 | * Selects a source by id |
115 | 117 | * |
116 | 118 | * @param {String} |
117 | | - * source_id Id of the source to select. |
| 119 | + * sourceId Id of the source to select. |
118 | 120 | * @return {MediaSource} The selected mediaSource or null if not found |
119 | 121 | */ |
120 | 122 | getSourceById:function( sourceId ) { |
— | — | @@ -167,8 +169,7 @@ |
168 | 170 | var _this = this; |
169 | 171 | // Select the default source |
170 | 172 | var playableSources = this.getPlayableSources(); |
171 | | - var flash_flag, oggflag; |
172 | | - flash_flag = ogg_flag = false; |
| 173 | + var flash_flag = ogg_flag = false; |
173 | 174 | |
174 | 175 | // Check if there are any playableSources |
175 | 176 | if( playableSources.length == 0 ){ |
— | — | @@ -176,25 +177,25 @@ |
177 | 178 | } |
178 | 179 | var setSelectedSource = function( source ){ |
179 | 180 | _this.selectedSource = source; |
| 181 | + return true; |
180 | 182 | }; |
181 | | - |
| 183 | + |
182 | 184 | // Set via user-preference |
183 | 185 | $.each( playableSources, function( inx, source ){ |
184 | 186 | var mimeType =source.mimeType; |
185 | 187 | if ( mw.EmbedTypes.getMediaPlayers().preference[ 'format_preference' ] == mimeType ) { |
186 | 188 | mw.log( 'MediaElement::autoSelectSource: Set via preference: ' + source.mimeType ); |
187 | | - setSelectedSource( source ); |
188 | | - return true; |
| 189 | + return setSelectedSource( source ); |
189 | 190 | } |
190 | 191 | }); |
191 | | - |
| 192 | + |
192 | 193 | // Set via module driven preference: |
193 | 194 | $(this).trigger( 'AutoSelectSource', [ playableSources ] ); |
194 | 195 | if( _this.selectedSource ){ |
195 | 196 | mw.log('MediaElement::autoSelectSource: Set via trigger::' ); |
196 | 197 | return true; |
197 | 198 | } |
198 | | - |
| 199 | + |
199 | 200 | // Set via marked default: |
200 | 201 | $.each( playableSources, function( inx, source ){ |
201 | 202 | if ( source.markedDefault ) { |
— | — | @@ -203,7 +204,7 @@ |
204 | 205 | return true; |
205 | 206 | } |
206 | 207 | }); |
207 | | - |
| 208 | + |
208 | 209 | //Set via user bandwith pref |
209 | 210 | if( $.cookie('EmbedPlayer.UserBandwidth') ){ |
210 | 211 | $.each( playableSources, function(inx, source ){ |
— | — | @@ -244,30 +245,32 @@ |
245 | 246 | var namedSources = []; |
246 | 247 | $.each( playableSources, function(inx, source ){ |
247 | 248 | var mimeType = source.mimeType; |
248 | | - var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType ); |
| 249 | + var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType ); |
249 | 250 | if ( player && player.library == 'Native' ) { |
250 | 251 | switch( player.id ){ |
251 | | - case 'oggNative': |
252 | | - namedSources['ogg'] = source; |
| 252 | + case 'mp3Native': |
| 253 | + namedSources['mp3'] = playableSources[ source ]; |
253 | 254 | break; |
| 255 | + case 'oggNative': |
| 256 | + namedSources['ogg'] = playableSources[ source ]; |
| 257 | + break; |
254 | 258 | case 'webmNative': |
255 | | - namedSources['webm'] = source; |
| 259 | + namedSources['webm'] = playableSources[ source ]; |
256 | 260 | break; |
257 | 261 | case 'h264Native': |
258 | | - namedSources['h264'] = source; |
| 262 | + namedSources['h264'] = playableSources[ source ]; |
259 | 263 | break; |
260 | 264 | } |
261 | 265 | } |
262 | 266 | }); |
| 267 | + |
263 | 268 | var codecPref =mw.getConfig( 'EmbedPlayer.CodecPreference'); |
264 | 269 | for(var i =0; i < codecPref.length; i++){ |
265 | 270 | var codec = codecPref[ i ]; |
266 | 271 | if( namedSources[ codec ]){ |
267 | | - setSelectedSource( namedSources[ codec ] ); |
268 | | - return true; |
| 272 | + return setSelectedSource( namedSources[ codec ] ); |
269 | 273 | } |
270 | 274 | }; |
271 | | - |
272 | 275 | |
273 | 276 | // Set h264 via native or flash fallback |
274 | 277 | $.each( playableSources, function(inx, source ){ |
— | — | @@ -282,16 +285,14 @@ |
283 | 286 | ) |
284 | 287 | ) { |
285 | 288 | mw.log('MediaElement::autoSelectSource: Set h264 via native or flash fallback'); |
286 | | - setSelectedSource( source ); |
287 | | - return true; |
| 289 | + return setSelectedSource( playableSources[ source ] ); |
288 | 290 | } |
289 | 291 | }); |
290 | 292 | |
291 | 293 | // Else just select first source |
292 | | - if ( !this.selectedSource ) { |
| 294 | + if ( !this.selectedSource && playableSources[0] ) { |
293 | 295 | mw.log( 'MediaElement::autoSelectSource: Set via first source:' + playableSources[0] ); |
294 | | - setSelectedSource( playableSources[0] ); |
295 | | - return true; |
| 296 | + return setSelectedSource( playableSources[0] ); |
296 | 297 | } |
297 | 298 | // No Source found so no source selected |
298 | 299 | return false; |
— | — | @@ -389,10 +390,12 @@ |
390 | 391 | for ( var i = 0; i < this.sources.length; i++ ) { |
391 | 392 | if ( this.isPlayableType( this.sources[i].mimeType ) ) { |
392 | 393 | playableSources.push( this.sources[i] ); |
393 | | - } |
| 394 | + } else { |
| 395 | + mw.log( "type " + this.sources[i].mimeType + ' is not playable' ); |
| 396 | + } |
394 | 397 | }; |
395 | 398 | return playableSources; |
396 | | - } |
| 399 | + } |
397 | 400 | }; |
398 | 401 | |
399 | 402 | } )( mediaWiki, jQuery ); |
Index: trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js |
— | — | @@ -57,9 +57,18 @@ |
58 | 58 | |
59 | 59 | mw.MediaSource = function( element ) { |
60 | 60 | this.init( element ); |
61 | | -} |
| 61 | +}; |
62 | 62 | |
63 | 63 | mw.MediaSource.prototype = { |
| 64 | + // MIME type of the source. |
| 65 | + mimeType:null, |
| 66 | + |
| 67 | + // URI of the source. |
| 68 | + uri:null, |
| 69 | + |
| 70 | + // Title of the source. |
| 71 | + title: null, |
| 72 | + |
64 | 73 | // True if the source has been marked as the default. |
65 | 74 | markedDefault: false, |
66 | 75 | |
— | — | @@ -72,10 +81,25 @@ |
73 | 82 | // Duration of the requested segment (0 if not known) |
74 | 83 | duration:0, |
75 | 84 | |
| 85 | + // Is the source playable |
| 86 | + is_playable: null, |
| 87 | + |
| 88 | + // source id |
| 89 | + id: null, |
| 90 | + |
| 91 | + // Start time in npt format |
| 92 | + start_npt: null, |
| 93 | + |
| 94 | + // End time in npt format |
| 95 | + end_npt: null, |
| 96 | + |
| 97 | + // Language of the file |
| 98 | + srclang: null, |
76 | 99 | /** |
77 | 100 | * MediaSource constructor: |
78 | 101 | */ |
79 | 102 | init : function( element ) { |
| 103 | + var _this = this; |
80 | 104 | // mw.log('EmbedPlayer::adding mediaSource: ' + element); |
81 | 105 | this.src = $( element ).attr( 'src' ); |
82 | 106 | |
— | — | @@ -88,16 +112,19 @@ |
89 | 113 | } |
90 | 114 | |
91 | 115 | var sourceAttr = mw.getConfig( 'EmbedPlayer.SourceAttributes' ); |
92 | | - for ( var i = 0; i < sourceAttr.length; i++ ) { // array loop: |
93 | | - var attr = sourceAttr[ i ]; |
94 | | - var attrValue = $( element ).attr( attr ); |
95 | | - if ( attrValue ) { |
| 116 | + $.each(sourceAttr, function(inx, attr){ |
| 117 | + if ( $j( element ).attr( attr ) ) { |
96 | 118 | // strip data- from the attribute name |
97 | 119 | if( attr.indexOf('data-') === 0){ |
98 | 120 | attr = attr.substr(5); |
99 | 121 | } |
100 | | - this[ attr ] = attrValue; |
| 122 | + _this[ attr ] = $j( element ).attr( attr ); |
101 | 123 | } |
| 124 | + }); |
| 125 | + |
| 126 | + // Normalize "label" to "title" ( label is the actual spec so use that over title ) |
| 127 | + if( this.label ){ |
| 128 | + this.title = this.label; |
102 | 129 | } |
103 | 130 | |
104 | 131 | // Set the content type: |
— | — | @@ -120,6 +147,12 @@ |
121 | 148 | if( this.mimeType == 'audio/vorbis') { |
122 | 149 | this.mimeType = 'audio/ogg'; |
123 | 150 | } |
| 151 | + |
| 152 | + // Conform long form "video/ogg; codecs=theora" based attributes |
| 153 | + // @@TODO we should support codec in the type arguments |
| 154 | + if( this.mimeType ){ |
| 155 | + this.mimeType = this.mimeType.split(';')[0]; |
| 156 | + } |
124 | 157 | |
125 | 158 | // Check for parent elements ( supplies categories in "track" ) |
126 | 159 | if( $( element ).parent().attr('category') ) { |
— | — | @@ -259,6 +292,12 @@ |
260 | 293 | case 'audio/ogg' : |
261 | 294 | return gM( 'mwe-embedplayer-video-audio' ); |
262 | 295 | break; |
| 296 | + case 'audio/mpeg' : |
| 297 | + return 'MPEG audio'; // FIXME: i18n |
| 298 | + break; |
| 299 | + case 'video/3gp' : |
| 300 | + return '3gp video'; // FIXME: i18n |
| 301 | + break; |
263 | 302 | case 'video/mpeg' : |
264 | 303 | return 'MPEG video'; // FIXME: i18n |
265 | 304 | break; |
— | — | @@ -306,8 +345,17 @@ |
307 | 346 | } |
308 | 347 | } |
309 | 348 | }, |
310 | | - |
311 | 349 | /** |
| 350 | + * Get the extension of a url |
| 351 | + * @param String uri |
| 352 | + */ |
| 353 | + getExt : function( uri ){ |
| 354 | + var urlParts = new mw.Uri( uri ); |
| 355 | + // Get the extension from the url or from the relative name: |
| 356 | + var ext = ( urlParts.file )? /[^.]+$/.exec( urlParts.file ) : /[^.]+$/.exec( uri ); |
| 357 | + return ext.toString().toLowerCase() |
| 358 | + }, |
| 359 | + /** |
312 | 360 | * Attempts to detect the type of a media file based on the URI. |
313 | 361 | * |
314 | 362 | * @param {String} |
— | — | @@ -319,15 +367,7 @@ |
320 | 368 | // we can issue a HEAD request and read the mime type of the media... |
321 | 369 | // ( this will detect media mime type independently of the url name ) |
322 | 370 | // http://www.jibbering.com/2002/4/httprequest.html |
323 | | - var ext =''; |
324 | | - try{ |
325 | | - ext = /[^.]+$/.exec( new mw.Uri( uri ).path ); |
326 | | - } catch ( e){ |
327 | | - ext = /[^.]+$/.exec( uri ); |
328 | | - }; |
329 | | - |
330 | | - // Get the extension from the url or from the relative name: |
331 | | - switch( ext.toString().toLowerCase() ) { |
| 371 | + switch( this.getExt( uri ) ) { |
332 | 372 | case 'smil': |
333 | 373 | case 'sml': |
334 | 374 | return 'application/smil'; |
— | — | @@ -336,9 +376,15 @@ |
337 | 377 | case 'mp4': |
338 | 378 | return 'video/h264'; |
339 | 379 | break; |
| 380 | + case 'm3u8': |
| 381 | + return 'application/vnd.apple.mpegurl'; |
| 382 | + break; |
340 | 383 | case 'webm': |
341 | 384 | return 'video/webm'; |
342 | 385 | break; |
| 386 | + case '3gp': |
| 387 | + return 'video/3gp'; |
| 388 | + break; |
343 | 389 | case 'srt': |
344 | 390 | return 'text/x-srt'; |
345 | 391 | break; |
— | — | @@ -352,6 +398,9 @@ |
353 | 399 | case 'oga': |
354 | 400 | return 'audio/ogg'; |
355 | 401 | break; |
| 402 | + case 'mp3': |
| 403 | + return 'audio/mpeg'; |
| 404 | + break; |
356 | 405 | case 'anx': |
357 | 406 | return 'video/ogg'; |
358 | 407 | break; |