src/js/popcorn.youtube.js
branchpopcorn-port
changeset 51 1444edeae73f
child 91 a66b10b06c01
equal deleted inserted replaced
50:b5849024c5c5 51:1444edeae73f
       
     1 // A global callback for youtube... that makes me angry
       
     2 var onYouTubePlayerReady = function( containerId ) {
       
     3 
       
     4   onYouTubePlayerReady[ containerId ] && onYouTubePlayerReady[ containerId ]();
       
     5 };
       
     6 onYouTubePlayerReady.stateChangeEventHandler = {};
       
     7 
       
     8 Popcorn.player( "youtube", {
       
     9   _setup: function( options ) {
       
    10 
       
    11     var media = this,
       
    12         youtubeObject,
       
    13         container = document.createElement( "div" ),
       
    14         currentTime = 0,
       
    15         seekTime = 0,
       
    16         seeking = false,
       
    17         dataLoaded = false,
       
    18 
       
    19         // state code for volume changed polling
       
    20         volumeChanged = false,
       
    21         lastMuted = false,
       
    22         lastVolume = 0;
       
    23 
       
    24     container.id = media.id + Popcorn.guid();
       
    25 
       
    26     media.appendChild( container );
       
    27 
       
    28     var youtubeInit = function() {
       
    29 
       
    30       var flashvars,
       
    31           params,
       
    32           attributes,
       
    33           src;
       
    34 
       
    35       // expose a callback to this scope, that is called from the global callback youtube calls
       
    36       onYouTubePlayerReady[ container.id ] = function() {
       
    37 
       
    38         youtubeObject = document.getElementById( container.id );
       
    39 
       
    40         // more youtube callback nonsense
       
    41         onYouTubePlayerReady.stateChangeEventHandler[ container.id ] = function( state ) {
       
    42 
       
    43           // playing is state 1
       
    44           // paused is state 2
       
    45           if ( state === 1 ) {
       
    46 
       
    47             media.paused && media.play();
       
    48           // youtube fires paused events while seeking
       
    49           // this is the only way to get seeking events
       
    50           } else if ( state === 2 ) {
       
    51 
       
    52             // silly logic forced on me by the youtube API
       
    53             // calling youtube.seekTo triggers multiple events
       
    54             // with the second events getCurrentTime being the old time
       
    55             if ( seeking && seekTime === currentTime && seekTime !== youtubeObject.getCurrentTime() ) {
       
    56 
       
    57               seeking = false;
       
    58               youtubeObject.seekTo( currentTime );
       
    59               return;
       
    60             }
       
    61 
       
    62             currentTime = youtubeObject.getCurrentTime();
       
    63             media.dispatchEvent( "timeupdate" );
       
    64             !media.paused && media.pause();
       
    65           }
       
    66         };
       
    67 
       
    68         // youtube requires callbacks to be a string to a function path from the global scope
       
    69         youtubeObject.addEventListener( "onStateChange", "onYouTubePlayerReady.stateChangeEventHandler." + container.id );
       
    70 
       
    71         var timeupdate = function() {
       
    72 
       
    73           if ( !media.paused ) {
       
    74 
       
    75             currentTime = youtubeObject.getCurrentTime();
       
    76             media.dispatchEvent( "timeupdate" );
       
    77             setTimeout( timeupdate, 10 );
       
    78           }
       
    79         };
       
    80 
       
    81         var volumeupdate = function() {
       
    82 
       
    83           if ( lastMuted !== youtubeObject.isMuted() ) {
       
    84 
       
    85             lastMuted = youtubeObject.isMuted();
       
    86             media.dispatchEvent( "volumechange" );
       
    87           }
       
    88 
       
    89           if ( lastVolume !== youtubeObject.getVolume() ) {
       
    90 
       
    91             lastVolume = youtubeObject.getVolume();
       
    92             media.dispatchEvent( "volumechange" );
       
    93           }
       
    94 
       
    95           setTimeout( volumeupdate, 250 );
       
    96         };
       
    97 
       
    98         media.play = function() {
       
    99 
       
   100           media.paused = false;
       
   101           media.dispatchEvent( "play" );
       
   102 
       
   103           if ( dataLoaded ) {
       
   104 
       
   105             media.dispatchEvent( "loadeddata" );
       
   106             dataLoaded = false;
       
   107           }
       
   108 
       
   109           media.dispatchEvent( "playing" );
       
   110           timeupdate();
       
   111           youtubeObject.playVideo();
       
   112         };
       
   113 
       
   114         media.pause = function() {
       
   115 
       
   116           if ( !media.paused ) {
       
   117 
       
   118             media.paused = true;
       
   119             media.dispatchEvent( "pause" );
       
   120             youtubeObject.pauseVideo();
       
   121           }
       
   122         };
       
   123 
       
   124         Popcorn.player.defineProperty( media, "currentTime", {
       
   125           set: function( val ) {
       
   126 
       
   127             // make sure val is a number
       
   128             currentTime = seekTime = +val;
       
   129             seeking = true;
       
   130             media.dispatchEvent( "seeked" );
       
   131             media.dispatchEvent( "timeupdate" );
       
   132             youtubeObject.seekTo( currentTime );
       
   133             return currentTime;
       
   134           },
       
   135           get: function() {
       
   136 
       
   137             return currentTime;
       
   138           }
       
   139         });
       
   140 
       
   141         Popcorn.player.defineProperty( media, "muted", {
       
   142           set: function( val ) {
       
   143 
       
   144             if ( youtubeObject.isMuted() !== val ) {
       
   145 
       
   146               if ( val ) {
       
   147 
       
   148                 youtubeObject.mute();
       
   149               } else {
       
   150 
       
   151                 youtubeObject.unMute();
       
   152               }
       
   153 
       
   154               lastMuted = youtubeObject.isMuted();
       
   155               media.dispatchEvent( "volumechange" );
       
   156             }
       
   157 
       
   158             return youtubeObject.isMuted();
       
   159           },
       
   160           get: function() {
       
   161 
       
   162             return youtubeObject.isMuted();
       
   163           }
       
   164         });
       
   165 
       
   166         Popcorn.player.defineProperty( media, "volume", {
       
   167           set: function( val ) {
       
   168 
       
   169             if ( youtubeObject.getVolume() !== val ) {
       
   170 
       
   171               youtubeObject.setVolume( val );
       
   172               lastVolume = youtubeObject.getVolume();
       
   173               media.dispatchEvent( "volumechange" );
       
   174             }
       
   175 
       
   176             return youtubeObject.getVolume();
       
   177           },
       
   178           get: function() {
       
   179 
       
   180             return youtubeObject.getVolume();
       
   181           }
       
   182         });
       
   183 
       
   184         media.readyState = 4;
       
   185         media.dispatchEvent( "load" );
       
   186         dataLoaded = true;
       
   187         media.duration = youtubeObject.getDuration();
       
   188         media.dispatchEvent( "durationchange" );
       
   189         volumeupdate();
       
   190 
       
   191         if ( !media.paused ) {
       
   192 
       
   193           media.play();
       
   194         }
       
   195 
       
   196         media.paused && media.dispatchEvent( "loadeddata" );
       
   197       };
       
   198 
       
   199       options.controls = +options.controls === 0 || +options.controls === 1 ? options.controls : 1;
       
   200       options.annotations = +options.annotations === 1 || +options.annotations === 3 ? options.annotations : 1;
       
   201 
       
   202       flashvars = {
       
   203         playerapiid: container.id,
       
   204         controls: options.controls,
       
   205         iv_load_policy: options.annotations
       
   206       };
       
   207 
       
   208       params = {
       
   209         wmode: "transparent",
       
   210         allowScriptAccess: "always"
       
   211       };
       
   212 
       
   213       attributes = {
       
   214         id: container.id
       
   215       };
       
   216 
       
   217       src = /^.*[\/=](.{11})/.exec( media.src )[ 1 ];
       
   218 
       
   219       swfobject.embedSWF( "http://www.youtube.com/e/" + src + "?enablejsapi=1&playerapiid=" + container.id + "&version=3",
       
   220                           container.id, media.offsetWidth, media.offsetHeight, "8", null,
       
   221                           flashvars, params, attributes );
       
   222     };
       
   223 
       
   224     if ( !window.swfobject ) {
       
   225 
       
   226       Popcorn.getScript( "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js", youtubeInit );
       
   227     } else {
       
   228 
       
   229       youtubeInit();
       
   230     }
       
   231   }
       
   232 });
       
   233