Index: branches/MwEmbedStandAlone/skins/common/mw.style.mwCommon.css |
— | — | @@ -188,7 +188,7 @@ |
189 | 189 | .mv-player .play-btn-large { |
190 | 190 | width : 130px; |
191 | 191 | height : 96px; |
192 | | - background : url(images/player_big_play_button.png) !important; |
| 192 | + background : url(images/player_big_play_button.png); |
193 | 193 | position : absolute; |
194 | 194 | cursor : pointer; |
195 | 195 | border : none !important; |
Index: branches/MwEmbedStandAlone/mwEmbed.js |
— | — | @@ -107,11 +107,20 @@ |
108 | 108 | } |
109 | 109 | return ; |
110 | 110 | } |
111 | | - // Only update the controls if undefined ( ie don't override false |
112 | | - // properties ) |
113 | | - if( typeof mwConfig[ name ] == 'undefined') { |
114 | | - mwConfig[ name ] = value; |
| 111 | + // Only update the controls if undefined |
| 112 | + |
| 113 | + if( typeof mwConfig[ name ] == 'undefined' ) { |
| 114 | + mwConfig[ name ] = value; |
| 115 | + return ; |
115 | 116 | } |
| 117 | + // Check if we should "merge" the config |
| 118 | + if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) { |
| 119 | + for( var i in value ){ |
| 120 | + if( typeof mwConfig[ name ][ i ] == 'undefined' ){ |
| 121 | + mwConfig[ name ][ i ] = value[ i ]; |
| 122 | + } |
| 123 | + } |
| 124 | + } |
116 | 125 | }; |
117 | 126 | |
118 | 127 | /** |
Index: branches/MwEmbedStandAlone/ResourceLoader.php |
— | — | @@ -16,14 +16,19 @@ |
17 | 17 | |
18 | 18 | // Check if we are an entry point or being used as part of MEDIAWIKI: |
19 | 19 | if ( !defined( 'MEDIAWIKI' ) && !defined( 'SCRIPTLOADER_MEDIAWIKI') ) { |
| 20 | + // Load stand alone Resource Loader config |
| 21 | + // ( if running as a remote, mediaWiki variables / functions are already included as part of mediaWiki ) |
| 22 | + require_once( realpath( dirname( __FILE__ ) ) . '/includes/noMediaWikiConfig.php' ); |
| 23 | + |
| 24 | + // Allow an installation an optional PHP customization/overrides file |
| 25 | + if ( is_file ( dirname( __FILE__ ) .'/../localSettings.php' ) ) { |
| 26 | + require_once dirname( __FILE__ ) .'/../localSettings.php'; |
| 27 | + } |
| 28 | + |
20 | 29 | $myResourceLoader = new ResourceLoader(); |
21 | 30 | if( $myResourceLoader->outputFromCache() ) { |
22 | 31 | exit(); |
23 | 32 | } |
24 | | - // No cache hit, load stand alone Resource Loader config |
25 | | - |
26 | | - // ( if running as a remote, mediaWiki variables / functions are already included as part of mediaWiki ) |
27 | | - require_once( realpath( dirname( __FILE__ ) ) . '/includes/noMediaWikiConfig.php' ); |
28 | 33 | $myResourceLoader->doResourceLoader(); |
29 | 34 | } |
30 | 35 | |
Index: branches/MwEmbedStandAlone/includes/noMediaWikiConfig.php |
— | — | @@ -82,10 +82,12 @@ |
83 | 83 | return false; |
84 | 84 | } |
85 | 85 | |
86 | | -function wfTempDir(){ |
87 | | - return realpath( dirname( __FILE__ ) ) . '/includes/cache'; |
| 86 | +if (!function_exists('wfTempDir')) |
| 87 | +{ |
| 88 | + function wfTempDir(){ |
| 89 | + return realpath( dirname( __FILE__ ) ) . '/includes/cache'; |
| 90 | + } |
88 | 91 | } |
89 | | - |
90 | 92 | /** |
91 | 93 | * Make directory, and make all parent directories if they don't exist |
92 | 94 | * |
Index: branches/MwEmbedStandAlone/modules/Playlist/mw.PlaylistHandlerMediaRss.js |
— | — | @@ -72,7 +72,7 @@ |
73 | 73 | callback( clipSources ); |
74 | 74 | }, |
75 | 75 | |
76 | | - getCustomClipAttributes: function( clipIndex ){ |
| 76 | + applyCustomClipData: function( embedPlayer, clipIndex ){ |
77 | 77 | return {}; |
78 | 78 | }, |
79 | 79 | |
Index: branches/MwEmbedStandAlone/modules/Playlist/mw.Playlist.js |
— | — | @@ -129,10 +129,10 @@ |
130 | 130 | ); |
131 | 131 | $j( _this.target ).append( $plListContainer ); |
132 | 132 | |
133 | | - var $plListSet = $j( _this.target ).find( '.playlistSet-list' ); |
| 133 | + var $plListSet = $j( _this.target ).find( '.playlistSet-list' ); |
134 | 134 | |
135 | 135 | $j.each( playlistSet, function( inx, playlist){ |
136 | | - // add a divider |
| 136 | + // Add a divider |
137 | 137 | if( inx != 0 ){ |
138 | 138 | $plListSet.append( $j('<span />').text( ' | ') ) |
139 | 139 | } |
— | — | @@ -264,7 +264,7 @@ |
265 | 265 | var myScroll = iScroll( _this.id + '_videolist' ); |
266 | 266 | setTimeout(function () { myScroll.refresh(); }, 0); |
267 | 267 | */ |
268 | | - // add space for scroll buttons: |
| 268 | + // Add space for scroll buttons: |
269 | 269 | var curTop = $j( _this.target + ' .media-rss-video-list' ).css('top'); |
270 | 270 | if(!curTop) curTop = '0px'; |
271 | 271 | $j( _this.target + ' .media-rss-video-list' ).css( { |
— | — | @@ -276,7 +276,7 @@ |
277 | 277 | }) |
278 | 278 | if( _this.layout == 'vertical' ){ |
279 | 279 | $j( _this.target + ' .media-rss-video-list' ).css({ |
280 | | - 'top' : $j( _this.target + ' .media-rss-video-player' ).height() |
| 280 | + 'top' : $j( _this.target + ' .media-rss-video-player' ).height() + 8 |
281 | 281 | }) |
282 | 282 | } |
283 | 283 | // Add scroll buttons: |
— | — | @@ -404,17 +404,19 @@ |
405 | 405 | |
406 | 406 | // Build the video tag object: |
407 | 407 | var $video = $j( '<video />' ) |
408 | | - .attr({ |
409 | | - 'id' : 'mrss_' + this.id + '_' + clipIndex, |
410 | | - 'poster' : _this.sourceHandler.getClipPoster( clipIndex ) |
411 | | - }) |
412 | | - .addClass( 'mwPlaylist' ) |
413 | | - .css( |
414 | | - playerSize |
415 | | - ) |
416 | | - // Add custom attributes: |
417 | | - .attr( _this.sourceHandler.getCustomClipAttributes( clipIndex ) ); |
| 408 | + .attr({ |
| 409 | + 'id' : _this.getVideoPlayerId( clipIndex ), |
| 410 | + 'poster' : _this.sourceHandler.getClipPoster( clipIndex ) |
| 411 | + }) |
| 412 | + .addClass( 'mwPlaylist' ) |
| 413 | + .css( |
| 414 | + playerSize |
| 415 | + ) |
418 | 416 | |
| 417 | + // Add custom attributes: |
| 418 | + _this.sourceHandler.applyCustomClipData( $video, clipIndex ); |
| 419 | + |
| 420 | + |
419 | 421 | // lookup the sources from the playlist provider: |
420 | 422 | this.sourceHandler.getClipSources( clipIndex, function( clipSources ){ |
421 | 423 | if( clipSources ){ |
— | — | @@ -424,39 +426,61 @@ |
425 | 427 | $video.append( $source ); |
426 | 428 | } |
427 | 429 | } |
428 | | - _this.addVideoPlayer( $video , callback); |
| 430 | + _this.updateVideoPlayer( $video , callback); |
429 | 431 | }); |
430 | 432 | }, |
431 | 433 | |
432 | | - addVideoPlayer: function( $video , callback){ |
433 | | - var _this = this; |
| 434 | + getVideoPlayerId: function( clipIndex ){ |
| 435 | + if( ! clipIndex ) { |
| 436 | + clipIndex = this.clipIndex; |
| 437 | + } |
| 438 | + return 'mrss_' + this.id + '_' + clipIndex; |
| 439 | + }, |
| 440 | + |
| 441 | + updateVideoPlayer: function( $video , callback){ |
| 442 | + var _this = this; |
434 | 443 | // If on mobile safari just swap the sources ( don't replace the video ) |
435 | 444 | // ( mobile safari can't javascript start the video ) |
436 | 445 | // see: http://developer.apple.com/iphone/search/search.php?simp=1&num=10&Search=html5+autoplay |
437 | | - var addVideoPlayerToDom = true; |
438 | | - if( mw.isMobileHTML5() ){ |
| 446 | + var updateVideoPlayerToDom = true; |
| 447 | + |
| 448 | + if( mw.isMobileHTML5() ){ |
439 | 449 | // Check for a current video: |
440 | 450 | var $inDomVideo = $j( _this.target + ' .media-rss-video-player video' ); |
441 | 451 | if( $inDomVideo.length == 0 ){ |
442 | | - addVideoPlayerToDom= true; |
| 452 | + updateVideoPlayerToDom = true; |
443 | 453 | } else { |
444 | | - addVideoPlayerToDom = false; |
| 454 | + updateVideoPlayerToDom = false; |
445 | 455 | // Update the inDomVideo object: |
446 | | - // NOTE: this hits a lot of internal stuff should ! |
| 456 | + // NOTE: this hits a lot of internal stuff |
447 | 457 | // XXX Should refactor to use embedPlayer interfaces! |
448 | 458 | var vidInterface = $j( _this.target + ' .media-rss-video-player' ).find('.mwplayer_interface div').get(0) |
449 | | - vidInterface.id = $video.attr('id'); |
| 459 | + // Copy over the video attributes to the the videoInterface |
| 460 | + $j( $video[0].attributes ).each( function(attrName, attrValue){ |
| 461 | + vidInterface[ attrName ] = attrValue; |
| 462 | + }) |
450 | 463 | vidInterface.pid = 'pid_' + $video.attr('id'); |
451 | | - vidInterface.duration = null; |
452 | | - if( $video.attr('kentryid') ){ |
453 | | - vidInterface.kentryid = $video.attr('kentryid'); |
| 464 | + // Update the interface restore source ( xxx this is a pretty ugly hack ) |
| 465 | + vidInterface.mediaElement.sources = []; |
| 466 | + $video.find('source').each(function(inx, source){ |
| 467 | + vidInterface.mediaElement.tryAddSource( source ) ; |
| 468 | + }); |
| 469 | + |
| 470 | + // Update the video interface id: |
| 471 | + $j( vidInterface ).attr('id', $video.attr('id')); |
| 472 | + |
| 473 | + |
| 474 | + if( $video.data('kuiconf') ){ |
| 475 | + $j( vidInterface ).data( 'kuiconf', $video.data('kuiconf') ) |
454 | 476 | } |
| 477 | + |
455 | 478 | // Update the current video target source |
456 | 479 | $inDomVideo.attr({ |
457 | 480 | 'id' : 'pid_' + $video.attr('id'), |
458 | 481 | 'src': $video.find( 'source').attr('src') |
459 | 482 | }); |
460 | | - |
| 483 | + // issue the load request |
| 484 | + $inDomVideo.get(0).load(); |
461 | 485 | } |
462 | 486 | } else { |
463 | 487 | // Remove the old video player ( non-mobile safari ) |
— | — | @@ -464,16 +488,18 @@ |
465 | 489 | $j( _this.target + ' .media-rss-video-player' ).remove( 'video' ); |
466 | 490 | } |
467 | 491 | |
468 | | - if( addVideoPlayerToDom ) { |
| 492 | + if( updateVideoPlayerToDom ) { |
469 | 493 | // replace the video: |
470 | 494 | $j( _this.target + ' .media-rss-video-player' ).append( $video ); |
471 | 495 | } |
472 | 496 | |
473 | 497 | // Update the video tag with the embedPlayer |
474 | | - $j.embedPlayers( function(){ |
| 498 | + $j.embedPlayers( function(){ |
| 499 | + var embedPlayer = $j('#' +_this.getVideoPlayerId( _this.clipIndex ) ).get(0); |
| 500 | + |
475 | 501 | // Setup ondone playing binding to play next clip (if autoContinue is true ) |
476 | 502 | if( _this.sourceHandler.autoContinue == true ){ |
477 | | - $j( '#mrss_' + _this.id + '_' + _this.clipIndex ).unbind('ended').bind( 'ended', function(event, onDoneActionObject ){ |
| 503 | + $j( embedPlayer ).unbind('ended').bind( 'ended', function(event, onDoneActionObject ){ |
478 | 504 | // Play next clip |
479 | 505 | if( _this.clipIndex + 1 < _this.sourceHandler.getClipCount() ){ |
480 | 506 | // Update the onDone action object to not run the base control done: |
— | — | @@ -492,6 +518,7 @@ |
493 | 519 | } |
494 | 520 | }) |
495 | 521 | } |
| 522 | + mw.log("player should be readY: " + _this.clipIndex + ' ' + $j('#' +_this.getVideoPlayerId() ) ); |
496 | 523 | // Run the callback if its set |
497 | 524 | if( callback ){ |
498 | 525 | callback(); |
— | — | @@ -561,11 +588,19 @@ |
562 | 589 | } ) |
563 | 590 | .click( function(){ |
564 | 591 | mw.log( 'clicked on: ' + $j( this ).data( 'clipIndex') ); |
| 592 | + // Make sure the existing player is "playing " (safari can't play async with javascript ) |
| 593 | + /*if( mw.isMobileHTML5() ){ |
| 594 | + var embedPlayer = $j('#' + _this.getVideoPlayerId() ).get(0); |
| 595 | + //embedPlayer.playerElement.play(); |
| 596 | + }*/ |
| 597 | + |
565 | 598 | // Update _this.clipIndex |
566 | 599 | _this.clipIndex = $j( this ).data( 'clipIndex' ); |
| 600 | + |
567 | 601 | _this.updatePlayer( _this.clipIndex, function(){ |
568 | 602 | _this.play(); |
569 | 603 | } ); |
| 604 | + |
570 | 605 | }) //close $itemBlock |
571 | 606 | |
572 | 607 | // Add the itemBlock to the targetItem list |
— | — | @@ -574,22 +609,17 @@ |
575 | 610 | ) |
576 | 611 | mw.log("added item block : " + $targetItemList.children().length ); |
577 | 612 | }); |
578 | | - }, |
| 613 | + }, |
579 | 614 | |
580 | | - /** |
581 | | - * Start playback for current clip |
582 | | - */ |
583 | 615 | play: function(){ |
584 | | - // Get the player and play: |
585 | | - var vid = $j('#mrss_' + this.id + '_' + this.clipIndex ).get(0); |
586 | | - //alert( 'play: '+ ) |
587 | | - if( vid && vid.play ){ |
588 | | - vid.load(); |
589 | | - vid.play(); |
| 616 | + var embedPlayer = $j('#' + this.getVideoPlayerId() ).get(0); |
| 617 | + if( mw.isMobileHTML5() ){ |
| 618 | + embedPlayer.playerElement.play(); |
| 619 | + } else{ |
| 620 | + embedPlayer.play(); |
590 | 621 | } |
591 | 622 | }, |
592 | 623 | |
593 | | - |
594 | 624 | /** |
595 | 625 | * Load the playlist driver from a source |
596 | 626 | */ |
Index: branches/MwEmbedStandAlone/modules/SwarmTransport/tests/SwarmTransprot_Url.html |
— | — | @@ -25,7 +25,7 @@ |
26 | 26 | <table border="1" cellpadding="6" width="950"> |
27 | 27 | |
28 | 28 | <tr> |
29 | | - <td id="apiExample" valign="top" width="410"> |
| 29 | + <td valign="top" width="410"> |
30 | 30 | <video |
31 | 31 | poster="http://footage.stealthisfilm.com/video/5/frame/0:03:56.640.jpg" |
32 | 32 | src="http://footage.stealthisfilm.com/stream/Yochai%20Benkler%20-%20On%20Autonomy%2C%20Control%20and%20Cultureal%20Experience.ogg" |
— | — | @@ -35,13 +35,13 @@ |
36 | 36 | <td valign="top"> |
37 | 37 | Simple Video Tag usage<br> |
38 | 38 | |
39 | | - <textarea id="apiExampleTextArea" style="width:600px;height:180px"> |
| 39 | + <textarea style="width:600px;height:180px"> |
40 | 40 | <video |
41 | 41 | poster="http://footage.stealthisfilm.com/video/5/frame/0:03:56.640.jpg" |
42 | 42 | src="http://footage.stealthisfilm.com/stream/Yochai%20Benkler%20-%20On%20Autonomy%2C%20Control%20and%20Cultureal%20Experience.ogg" |
43 | 43 | class="kskin"> |
44 | 44 | <track srclang="en" src="Yochai_Benkler_-_On_Autonomy,_Control_and_Cultural_Experience.srt" /> |
45 | | -</video> |
| 45 | +</video>s |
46 | 46 | </textarea> |
47 | 47 | </td> |
48 | 48 | </tr> |
Index: branches/MwEmbedStandAlone/modules/AddMedia/mw.RemoteSearchDriver.js |
— | — | @@ -280,7 +280,7 @@ |
281 | 281 | 'apiUrl': ( wgServer && wgScriptPath ) ? |
282 | 282 | wgServer + wgScriptPath + '/api.php' : null, |
283 | 283 | |
284 | | - 'detailsUrl' : wgServer + wgArticlePath, |
| 284 | + 'detailsUrl' : ( wgServer && wgArticlePath )? wgServer + wgArticlePath : null, |
285 | 285 | |
286 | 286 | 'lib': 'mediaWiki', |
287 | 287 | 'homepage' : ( wgServer && wgScript ) ? |
— | — | @@ -866,8 +866,8 @@ |
867 | 867 | bgiframe: true, |
868 | 868 | autoOpen: true, |
869 | 869 | modal: true, |
870 | | - width: $j(window).width()-10, |
871 | | - height: $j(window).height()-10, |
| 870 | + width: $j(window).width()-50, |
| 871 | + height: $j(window).height()-50, |
872 | 872 | position : 'center', |
873 | 873 | draggable: false, |
874 | 874 | resizable: false, |
— | — | @@ -2029,7 +2029,7 @@ |
2030 | 2030 | 'position' : 'absolute', |
2031 | 2031 | 'top' : '0px', |
2032 | 2032 | 'left' : '0px', |
2033 | | - 'bottom' : '0px', |
| 2033 | + 'bottom' : '30px', |
2034 | 2034 | 'right' : '4px', |
2035 | 2035 | 'background-color' : '#FFF' |
2036 | 2036 | } ) |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/loader.js |
— | — | @@ -177,10 +177,10 @@ |
178 | 178 | // Add JSON lib if browsers does not define "JSON" natively |
179 | 179 | 'JSON', |
180 | 180 | '$j.ui', |
181 | | - '$j.widget', |
182 | | - '$j.ui.mouse' |
| 181 | + '$j.widget' |
183 | 182 | ], |
184 | | - [ |
| 183 | + [ |
| 184 | + '$j.ui.mouse', |
185 | 185 | '$j.fn.menu', |
186 | 186 | 'mw.style.jquerymenu', |
187 | 187 | '$j.ui.slider' |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js |
— | — | @@ -12,11 +12,10 @@ |
13 | 13 | */ |
14 | 14 | |
15 | 15 | mw.includeAllModuleMessages(); |
16 | | - |
17 | 16 | /* |
18 | 17 | * The default video attributes supported by embedPlayer |
19 | 18 | */ |
20 | | -mw.setConfig( 'EmbedPlayer.Attributes', { |
| 19 | +mw.setDefaultConfig( 'EmbedPlayer.Attributes', { |
21 | 20 | /* |
22 | 21 | * Base html element attributes: |
23 | 22 | */ |
— | — | @@ -231,10 +230,14 @@ |
232 | 231 | attributes = {}; |
233 | 232 | } |
234 | 233 | |
235 | | - |
236 | | - // If we are dynamically embedding on a "div" check if we can |
237 | | - // add a poster image behind the loader: |
238 | 234 | $j( playerSelect ).each( function( index, playerElement) { |
| 235 | + // make sure the playerElement has an id: |
| 236 | + if( $j( playerElement ).attr('id') =='' ){ |
| 237 | + $j( playerElement ).attr( "id", 'mwe_v' + ( index ) ); |
| 238 | + } |
| 239 | + |
| 240 | + // If we are dynamically embedding on a "div" check if we can |
| 241 | + // add a poster image behind the loader: |
239 | 242 | if( playerElement.nodeName.toLowerCase() == 'div' |
240 | 243 | && ( attributes.poster || $j(playerElement).attr( 'poster' ) ) ){ |
241 | 244 | var posterSrc = ( attributes.poster ) ? attributes.poster : $j(playerElement).attr( 'poster' ); |
— | — | @@ -402,7 +405,7 @@ |
403 | 406 | // Let extensions determine if its worthwhile to wait for metadata: |
404 | 407 | // We pass an object to the trigger to preserve reference values |
405 | 408 | var eventObject = { |
406 | | - 'playerElement':playerElement, |
| 409 | + 'playerElement' : playerElement, |
407 | 410 | 'waitForMeta' : waitForMeta |
408 | 411 | }; |
409 | 412 | $j( mw ).trigger( 'addElementWaitForMetaEvent', eventObject ); |
— | — | @@ -426,13 +429,21 @@ |
427 | 430 | ranPlayerSwapFlag = true; |
428 | 431 | mw.log("EmbedPlayer::runPlayerSwap::" + $j( playerElement ).attr('id') ); |
429 | 432 | |
430 | | - var playerInterface = new mw.EmbedPlayer( playerElement , attributes); |
| 433 | + var playerInterface = new mw.EmbedPlayer( playerElement , attributes); |
| 434 | + var swapPlayer = _this.swapEmbedPlayerElement( playerElement, playerInterface ); |
431 | 435 | |
432 | | - _this.swapEmbedPlayerElement( playerElement, playerInterface ); |
433 | | - |
| 436 | + // Copy over any data attributes from the playerElement |
| 437 | + if( mw.getConfig( 'EmbedPlayer.DataAttributes' ) ) { |
| 438 | + var dataAttr = mw.getConfig( 'EmbedPlayer.DataAttributes' ) |
| 439 | + for( var i in dataAttr ){ |
| 440 | + if( $j( playerElement ).data( i ) ){ |
| 441 | + $j( '#' + playerInterface.id ).data( i, $j( playerElement ).data( i ) ); |
| 442 | + } |
| 443 | + } |
| 444 | + } |
434 | 445 | |
435 | 446 | // Pass the id to any hook that needs to interface prior to checkPlayerSources |
436 | | - mw.log("EmbedPlayer::addElement :trigger :: newEmbedPlayerEvent"); |
| 447 | + mw.log("EmbedPlayer::addElement :trigger " + playerInterface.id ); |
437 | 448 | $j( mw ).trigger ( 'newEmbedPlayerEvent', playerInterface.id ); |
438 | 449 | |
439 | 450 | // Issue the checkPlayerSources call to the new player interface: |
— | — | @@ -546,7 +557,7 @@ |
547 | 558 | // Create a new element to swap the player interface into |
548 | 559 | var swapPlayerElement = document.createElement('div'); |
549 | 560 | |
550 | | - // get properties / methods from playerInterface |
| 561 | + // Get properties / methods from playerInterface |
551 | 562 | for ( var method in playerInterface ) { |
552 | 563 | if ( method != 'readyState' ) { // readyState crashes IE ( don't include ) |
553 | 564 | swapPlayerElement[ method ] = playerInterface[ method ]; |
— | — | @@ -554,13 +565,13 @@ |
555 | 566 | } |
556 | 567 | |
557 | 568 | // Check if we are using native controls ( should keep the video embed around ) |
558 | | - if( playerInterface.shouldUseNativeControls() ) { |
| 569 | + if( playerInterface.useNativePlayerControls() ) { |
559 | 570 | $j( targetElement ) |
560 | | - .attr('id', playerInterface.pid ) |
| 571 | + .attr( 'id', playerInterface.pid ) |
561 | 572 | .addClass( 'nativeEmbedPlayerPid' ) |
562 | 573 | .show() |
563 | 574 | .after( |
564 | | - $j( swapPlayerElement ).css('display', 'none') |
| 575 | + $j( swapPlayerElement ).css( 'display', 'none' ) |
565 | 576 | ) |
566 | 577 | } else { |
567 | 578 | $j( targetElement ).replaceWith( swapPlayerElement ); |
— | — | @@ -575,7 +586,7 @@ |
576 | 587 | |
577 | 588 | // If we don't already have a loadSpiner add one: |
578 | 589 | if( $j('#loadingSpinner_' + playerInterface.id ).length == 0 ){ |
579 | | - if( playerInterface.shouldUseNativeControls() ) { |
| 590 | + if( playerInterface.useNativePlayerControls() ) { |
580 | 591 | $j( targetElement ) |
581 | 592 | .getAbsoluteOverlaySpinner() |
582 | 593 | .attr('id', 'loadingSpinner_' + playerInterface.id ) |
— | — | @@ -586,7 +597,7 @@ |
587 | 598 | ); |
588 | 599 | } |
589 | 600 | } |
590 | | - return true; |
| 601 | + return swapPlayerElement; |
591 | 602 | }, |
592 | 603 | |
593 | 604 | |
— | — | @@ -862,7 +873,7 @@ |
863 | 874 | |
864 | 875 | // Return the mime type string if not known type. |
865 | 876 | return this.mimeType; |
866 | | - }, |
| 877 | + }, |
867 | 878 | |
868 | 879 | /** |
869 | 880 | * |
— | — | @@ -1357,7 +1368,7 @@ |
1358 | 1369 | } |
1359 | 1370 | |
1360 | 1371 | var playerAttributes = mw.getConfig( 'EmbedPlayer.Attributes' ); |
1361 | | - // Setup the player Interface from supported attributes: |
| 1372 | + // Setup the player Interface from supported attributes: |
1362 | 1373 | for ( var attr in playerAttributes ) { |
1363 | 1374 | if ( customAttributes[ attr ] || customAttributes[ attr ] === false ) { |
1364 | 1375 | this[ attr ] = customAttributes[ attr ]; |
— | — | @@ -1374,14 +1385,14 @@ |
1375 | 1386 | // string -> boolean |
1376 | 1387 | if( this[ attr ] == "false" ) this[attr] = false; |
1377 | 1388 | if( this[ attr ] == "true" ) this[attr] = true; |
1378 | | - } |
| 1389 | + } |
1379 | 1390 | |
1380 | 1391 | if( this.apiTitleKey ){ |
1381 | 1392 | this.apiTitleKey = unescape( this.apiTitleKey ); |
1382 | 1393 | } |
1383 | 1394 | |
1384 | 1395 | // Hide "controls" if using native player controls: |
1385 | | - if( this.shouldUseNativeControls() ){ |
| 1396 | + if( this.useNativePlayerControls() ){ |
1386 | 1397 | _this.controls = false; |
1387 | 1398 | } |
1388 | 1399 | |
— | — | @@ -1607,9 +1618,19 @@ |
1608 | 1619 | finishCheckPlayerSources(); |
1609 | 1620 | } |
1610 | 1621 | }, |
| 1622 | + /** |
| 1623 | + * Insert and play a video source ( useful for ads or bumper videos ) |
| 1624 | + * |
| 1625 | + * Only works while video is in active play back. |
| 1626 | + * Only tested with native playback atm. |
| 1627 | + */ |
| 1628 | + insertAndPlaySource: function( source ){ |
| 1629 | + mw.log("Error: only native playback supports insertAndPlaySource right now"); |
| 1630 | + }, |
1611 | 1631 | |
1612 | 1632 | /** |
1613 | 1633 | * Load Source video info from mediaWiki Api title key ( this.apiTitleKey ) |
| 1634 | + * @@todo move this to mediaWiki 'api' module |
1614 | 1635 | * @param {Function} callback Function called once loading is complete |
1615 | 1636 | */ |
1616 | 1637 | loadSourceFromApi: function( callback ){ |
— | — | @@ -2023,7 +2044,7 @@ |
2024 | 2045 | this.controlBuilder.addControlBindings(); |
2025 | 2046 | |
2026 | 2047 | // Once the thumbnail is shown run the mediaReady trigger (if not using native controls) |
2027 | | - if( !this.shouldUseNativeControls() ){ |
| 2048 | + if( !this.useNativePlayerControls() ){ |
2028 | 2049 | mw.log("mediaLoaded"); |
2029 | 2050 | $j( this ).trigger( 'mediaLoaded' ); |
2030 | 2051 | } |
— | — | @@ -2301,7 +2322,7 @@ |
2302 | 2323 | var style_atr = ''; |
2303 | 2324 | |
2304 | 2325 | |
2305 | | - if( this.shouldUseNativeControls() ){ |
| 2326 | + if( this.useNativePlayerControls() ){ |
2306 | 2327 | this.showNativePlayer(); |
2307 | 2328 | return ; |
2308 | 2329 | } |
— | — | @@ -2342,7 +2363,7 @@ |
2343 | 2364 | * @returns boolean true if the mwEmbed player interface should be used |
2344 | 2365 | * false if the mwEmbed player interface should not be used |
2345 | 2366 | */ |
2346 | | - shouldUseNativeControls: function() { |
| 2367 | + useNativePlayerControls: function() { |
2347 | 2368 | if( this.usenativecontrols === true ){ |
2348 | 2369 | return true; |
2349 | 2370 | } |
— | — | @@ -2483,6 +2504,7 @@ |
2484 | 2505 | } else if( this.apiTitleKey ) { |
2485 | 2506 | iframeUrl += 'apiTitleKey=' + escape( this.apiTitleKey ) + '&'; |
2486 | 2507 | if ( this.apiProvider ) { |
| 2508 | + // Commons always uses the commons api provider ( special hack should refactor ) |
2487 | 2509 | if( mw.parseUri( document.URL ).host == 'commons.wikimedia.org'){ |
2488 | 2510 | this.apiProvider = 'commons'; |
2489 | 2511 | } |
— | — | @@ -2645,9 +2667,8 @@ |
2646 | 2668 | * Starts the "monitor" |
2647 | 2669 | */ |
2648 | 2670 | play: function() { |
2649 | | - var _this = this; |
2650 | | - mw.log( "EmbedPlayer:: play" ); |
2651 | | - |
| 2671 | + var _this = this; |
| 2672 | + mw.log( "EmbedPlayer:: play" ); |
2652 | 2673 | // Hide any overlay: |
2653 | 2674 | this.controlBuilder.closeMenuOverlay(); |
2654 | 2675 | |
— | — | @@ -2669,7 +2690,7 @@ |
2670 | 2691 | // Run play hook (if we were previously in paused state ) |
2671 | 2692 | if( this.paused ){ |
2672 | 2693 | this.paused = false; |
2673 | | - mw.log("trigger play event::"); |
| 2694 | + mw.log("trigger play event::"); |
2674 | 2695 | $j( this ).trigger( 'play' ); |
2675 | 2696 | } |
2676 | 2697 | |
— | — | @@ -2714,12 +2735,13 @@ |
2715 | 2736 | * must be overwritten by embed object to support this functionality. |
2716 | 2737 | */ |
2717 | 2738 | pause: function( event ) { |
2718 | | - var _this = this; |
| 2739 | + var _this = this; |
| 2740 | + |
2719 | 2741 | // only trigger the pause event if not already in paused state: |
2720 | 2742 | if( this.paused === false ){ |
2721 | 2743 | this.paused = true; |
2722 | 2744 | mw.log('EmbedPlayer:trigger pause'); |
2723 | | - $j( this ).trigger('pause'); |
| 2745 | + //$j( this ).trigger('pause' ); |
2724 | 2746 | } |
2725 | 2747 | |
2726 | 2748 | // update the ctrl "paused state" |
— | — | @@ -2747,7 +2769,7 @@ |
2748 | 2770 | */ |
2749 | 2771 | stop: function() { |
2750 | 2772 | var _this = this; |
2751 | | - mw.log( 'mvEmbed:stop:' + this.id ); |
| 2773 | + mw.log( 'EmbedPlayer::stop:' + this.id ); |
2752 | 2774 | |
2753 | 2775 | // no longer seeking: |
2754 | 2776 | this.didSeekJump = false; |
— | — | @@ -2808,7 +2830,7 @@ |
2809 | 2831 | * Update volume function ( called from interface updates ) |
2810 | 2832 | * @param {float} percent Percent of full volume |
2811 | 2833 | */ |
2812 | | - setVolume: function( percent, dissableTrigger ) { |
| 2834 | + setVolume: function( percent ) { |
2813 | 2835 | // ignore NaN percent: |
2814 | 2836 | if( isNaN( percent ) ){ |
2815 | 2837 | return ; |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerJava.js |
— | — | @@ -220,7 +220,7 @@ |
221 | 221 | this.parent_play(); |
222 | 222 | if ( this.playerElement ) { |
223 | 223 | try{ |
224 | | - this.playerElement.play(); |
| 224 | + this.playerElement.play(); |
225 | 225 | }catch( e ){ |
226 | 226 | mw.log("EmbedPlayerJava::Could not issue play request"); |
227 | 227 | } |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerHtml.js |
— | — | @@ -92,8 +92,8 @@ |
93 | 93 | * @param {Float} perc Percentage to seek into the virtual player |
94 | 94 | * @param {Function} callback Function called once time has been updated |
95 | 95 | */ |
96 | | - setCurrentTime:function( perc, callback ) { |
97 | | - this.pauseTime = perc * this.getDuration(); |
| 96 | + setCurrentTime:function( time, callback ) { |
| 97 | + this.pauseTime = time; |
98 | 98 | if( callback ) |
99 | 99 | callback(); |
100 | 100 | }, |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerNative.js |
— | — | @@ -40,6 +40,9 @@ |
41 | 41 | 'volumeControl' : true, |
42 | 42 | 'overlays' : true |
43 | 43 | }, |
| 44 | + |
| 45 | + insertAndPlayingConfig : false, |
| 46 | + |
44 | 47 | /** |
45 | 48 | * updates the supported features given the "type of player" |
46 | 49 | */ |
— | — | @@ -64,7 +67,7 @@ |
65 | 68 | mw.log( "native play url:" + this.getSrc() + ' startOffset: ' + this.start_ntp + ' end: ' + this.end_ntp ); |
66 | 69 | |
67 | 70 | // Check if using native controls and already the "pid" is already in the DOM |
68 | | - if( this.shouldUseNativeControls() && $j( '#' + this.pid ).length && |
| 71 | + if( this.useNativePlayerControls() && $j( '#' + this.pid ).length && |
69 | 72 | typeof $j( '#' + this.pid ).get(0).play != 'undefined' ) { |
70 | 73 | _this.postEmbedJS(); |
71 | 74 | return ; |
— | — | @@ -205,9 +208,8 @@ |
206 | 209 | mw.log( 'Native::doSeek p: ' + percentage + ' : ' + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec ); |
207 | 210 | this.seeking = true; |
208 | 211 | // Run the seeking hook |
209 | | - $j( this.embedPlayer ).trigger( 'onSeek' ); |
| 212 | + $j( this.embedPlayer ).trigger( 'onSeek' ); |
210 | 213 | |
211 | | - |
212 | 214 | // Run the onSeeking interface update |
213 | 215 | this.controlBuilder.onSeek(); |
214 | 216 | |
— | — | @@ -239,12 +241,81 @@ |
240 | 242 | mw.log( 'native::doNativeSeek::' + percentage ); |
241 | 243 | this.seeking = true; |
242 | 244 | this.seek_time_sec = 0; |
243 | | - this.doSeekedCallback( ( percentage * this.duration ) , function(){ |
| 245 | + this.setCurrentTime( ( percentage * this.duration ) , function(){ |
244 | 246 | _this.seeking = false; |
245 | 247 | _this.monitor(); |
246 | | - }) |
| 248 | + }) |
| 249 | + }, |
| 250 | + |
| 251 | + insertAndPlaySource: function( src , options ){ |
| 252 | + mw.log("NativeEmbed:: insertAndPlaySource: " + src + ' insertAndPlayingConfig:' + this.insertAndPlayingConfig); |
| 253 | + if(!options) |
| 254 | + options = {}; |
247 | 255 | |
| 256 | + if( options.lockUI ){ |
| 257 | + this.playerElement.controls = false; |
| 258 | + } |
| 259 | + |
| 260 | + // Make sure to capture the original source |
| 261 | + if(! this.insertAndPlayingConfig ){ |
| 262 | + //alert( 'setup this.insertAndPlayingConfig '); |
| 263 | + this.insertAndPlayingConfig = { |
| 264 | + 'src' : this.getSrc(), |
| 265 | + 'time' : this.currentTime, |
| 266 | + 'callback' : options.callback, |
| 267 | + 'restoreControls' : options.lockUI |
| 268 | + } |
| 269 | + } |
| 270 | + // Try to directly playback the source |
| 271 | + this.switchSrc( src ); |
| 272 | + |
248 | 273 | }, |
| 274 | + restoreSourcePlayback: function( ){ |
| 275 | + var _this = this; |
| 276 | + mw.log( "RestoreSourcePlayback:: empty out insertAndPlayingConfig" ); |
| 277 | + if( !this.insertAndPlayingConfig) { |
| 278 | + mw.log("Error: called restored playback with empty insertAndPlayingConfig") |
| 279 | + return; |
| 280 | + } |
| 281 | + this.switchSrc( this.insertAndPlayingConfig.src ); |
| 282 | + //this.playerElement.play(); |
| 283 | + // Remove insert and playing config flag |
| 284 | + this.insertAndPlayingConfig = false; |
| 285 | + |
| 286 | + var time = this.insertAndPlayingConfig.time; |
| 287 | + var callback = this.insertAndPlayingConfig.callback; |
| 288 | + |
| 289 | + // run the seek: |
| 290 | + this.setCurrentTime( time ,function(){ |
| 291 | + if( this.insertAndPlayingConfig.restoreControls ){ |
| 292 | + this.playerElement.controls = true; |
| 293 | + } |
| 294 | + }); |
| 295 | + // Give some time for ipad to figure out whats going on: |
| 296 | + setTimeout(function(){ |
| 297 | + _this.playerElement.load(); |
| 298 | + _this.playerElement.play(); |
| 299 | + },100); |
| 300 | + |
| 301 | + //alert("insertAndPlayingConfig:: " + this.insertAndPlayingConfig); |
| 302 | + // Run the callback |
| 303 | + if( callback ){ |
| 304 | + callback(); |
| 305 | + } |
| 306 | + }, |
| 307 | + switchSrc: function( src ){ |
| 308 | + mw.log( 'switchSrc' ) |
| 309 | + if( this.getPlayerElement() ){ |
| 310 | + try{ |
| 311 | + //this.playerElement.pause(); |
| 312 | + this.playerElement.src = src; |
| 313 | + this.playerElement.load(); |
| 314 | + this.playerElement.play(); |
| 315 | + } catch( e ){ |
| 316 | + mw.log("Error: possible error in swiching source playback"); |
| 317 | + } |
| 318 | + } |
| 319 | + }, |
249 | 320 | |
250 | 321 | /** |
251 | 322 | * Seek in a existing stream |
— | — | @@ -281,37 +352,36 @@ |
282 | 353 | * @param {Float} position Seconds to set the time to |
283 | 354 | * @param {Function} callback Function called once time has been set. |
284 | 355 | */ |
285 | | - setCurrentTime: function( position , callback ) { |
286 | | - var _this = this; |
287 | | - //mw.log( 'native:setCurrentTime::: ' + position + ' : dur: ' + _this.getDuration() ); |
288 | | - this.getPlayerElement(); |
289 | | - if ( !this.playerElement ) { |
290 | | - this.load( function() { |
291 | | - _this.doSeekedCallback( position, callback ); |
292 | | - } ); |
293 | | - } else { |
294 | | - _this.doSeekedCallback( position, callback ); |
295 | | - } |
296 | | - }, |
297 | | - |
298 | | - /** |
299 | | - * Do the seek request with a callback |
300 | | - * |
301 | | - * @param {Float} position Position in seconds |
302 | | - * @param {Function} callback Function to call once seeking completes |
303 | | - */ |
304 | | - doSeekedCallback : function( position, callback ) { |
| 356 | + setCurrentTime: function( time , callback, callbackCount ) { |
305 | 357 | var _this = this; |
| 358 | + if( !callbackCount ) |
| 359 | + callbackCount = 0; |
306 | 360 | this.getPlayerElement(); |
307 | | - var once = function( event ) { |
308 | | - callback(); |
309 | | - _this.playerElement.removeEventListener( 'seeked', once, false ); |
310 | | - }; |
311 | | - // Assume we will get to add the Listener before the seek is done |
312 | | - _this.playerElement.currentTime = position; |
313 | | - _this.playerElement.addEventListener( 'seeked', once, false ); |
| 361 | + if( _this.playerElement.readyState >= 1 ){ |
| 362 | + if( _this.playerElement.currentTime == time ){ |
| 363 | + callback(); |
| 364 | + return; |
| 365 | + } |
| 366 | + var once = function( event ) { |
| 367 | + if( callback ){ |
| 368 | + callback(); |
| 369 | + } |
| 370 | + _this.playerElement.removeEventListener( 'seeked', once, false ); |
| 371 | + }; |
| 372 | + // Assume we will get to add the Listener before the seek is done |
| 373 | + _this.playerElement.addEventListener( 'seeked', once, false ); |
| 374 | + _this.playerElement.currentTime = time; |
| 375 | + } else { |
| 376 | + if( callbackCount >= 300 ){ |
| 377 | + mw.log("Error with seek request, media never in ready state"); |
| 378 | + return ; |
| 379 | + } |
| 380 | + setTimeout( function(){ |
| 381 | + _this.setCurrentTime( time, callback , callbackCount++); |
| 382 | + }, 10 ); |
| 383 | + } |
314 | 384 | }, |
315 | | - |
| 385 | + |
316 | 386 | /** |
317 | 387 | * Get the embed player time |
318 | 388 | */ |
— | — | @@ -343,11 +413,13 @@ |
344 | 414 | * Pause the video playback |
345 | 415 | * calls parent_pause to update the interface |
346 | 416 | */ |
347 | | - pause: function() { |
348 | | - this.getPlayerElement(); |
| 417 | + pause: function( ) { |
| 418 | + this.getPlayerElement(); |
349 | 419 | this.parent_pause(); // update interface |
350 | 420 | if ( this.playerElement ) { // update player |
351 | | - this.playerElement.pause(); |
| 421 | + if( !this.playerElement.paused ){ |
| 422 | + this.playerElement.pause(); |
| 423 | + } |
352 | 424 | } |
353 | 425 | }, |
354 | 426 | |
— | — | @@ -355,11 +427,15 @@ |
356 | 428 | * Play back the video stream |
357 | 429 | * calls parent_play to update the interface |
358 | 430 | */ |
359 | | - play: function() { |
360 | | - this.getPlayerElement(); |
| 431 | + play: function( ) { |
| 432 | + |
| 433 | + this.getPlayerElement(); |
361 | 434 | this.parent_play(); // update interface |
362 | 435 | if ( this.playerElement && this.playerElement.play ) { |
363 | | - this.playerElement.play(); |
| 436 | + // issue a play request if the media is paused: |
| 437 | + if( this.playerElement.paused ){ |
| 438 | + this.playerElement.play(); |
| 439 | + } |
364 | 440 | // re-start the monitor: |
365 | 441 | this.monitor(); |
366 | 442 | } |
— | — | @@ -508,18 +584,17 @@ |
509 | 585 | * Handle the native paused event |
510 | 586 | */ |
511 | 587 | onPaused: function(){ |
512 | | - mw.log( "embedPlayer:native:paused" ); |
513 | | - this.pause(); |
| 588 | + mw.log( "EmbedPlayer:native: OnPaused" ); |
| 589 | + this.parent_pause(); |
514 | 590 | }, |
515 | 591 | |
516 | 592 | /** |
517 | 593 | * Handle the native play event |
518 | 594 | */ |
519 | 595 | onPlay: function(){ |
520 | | - mw.log("embedPlayer:native::play"); |
521 | | - if( !this.isPlaying () ){ |
522 | | - this.play(); |
523 | | - } |
| 596 | + mw.log("EmbedPlayer:native:: OnPlay"); |
| 597 | + // Update the interface |
| 598 | + this.parent_play(); |
524 | 599 | }, |
525 | 600 | |
526 | 601 | /** |
— | — | @@ -568,8 +643,15 @@ |
569 | 644 | * Used to update the bufferedPercent |
570 | 645 | */ |
571 | 646 | onended: function() { |
572 | | - var _this = this; |
573 | | - mw.log( 'EmbedPlayer:native:onended:' + this.playerElement.currentTime + ' real dur:' + this.getDuration() ); |
| 647 | + var _this = this; |
| 648 | + mw.log( 'EmbedPlayer:native: onended:' + this.playerElement.currentTime + ' real dur:' + this.getDuration() + |
| 649 | + ' insertAndPlayingConfig: ' + this.insertAndPlayingConfig); |
| 650 | + |
| 651 | + if( this.insertAndPlayingConfig ){ |
| 652 | + this.restoreSourcePlayback(); |
| 653 | + this.insertAndPlayingConfig = false; |
| 654 | + return ; |
| 655 | + } |
574 | 656 | this.onClipDone(); |
575 | 657 | } |
576 | 658 | }; |
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerMenu.js |
— | — | @@ -63,6 +63,14 @@ |
64 | 64 | return ( _this.sequencer.getServer().isConfigured() ) |
65 | 65 | } |
66 | 66 | }, |
| 67 | + 'help_divider': 'divider', |
| 68 | + 'help': { |
| 69 | + 'icon' : 'info', |
| 70 | + 'action' : function(){ |
| 71 | + // follow link to |
| 72 | + //$j( this ).attr('href', ) |
| 73 | + } |
| 74 | + }, |
67 | 75 | 'exit_divider': 'divider', |
68 | 76 | 'exit' : { |
69 | 77 | 'icon' : 'power', |