Advertisement
Guest User

Untitled

a guest
Jan 29th, 2015
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.77 KB | None | 0 0
  1. (function( Popcorn ) {
  2.  
  3. // combines calls of two function calls into one
  4. var combineFn = function( first, second ) {
  5.  
  6. first = first || Popcorn.nop;
  7. second = second || Popcorn.nop;
  8.  
  9. return function() {
  10.  
  11. first.apply( this, arguments );
  12. second.apply( this, arguments );
  13. };
  14. };
  15.  
  16. // ID string matching
  17. var rIdExp = /^(#([\w\-\_\.]+))$/;
  18.  
  19. var audioExtensions = "ogg|oga|aac|mp3|wav",
  20. videoExtensions = "ogg|ogv|mp4|webm",
  21. mediaExtensions = audioExtensions + "|" + videoExtensions;
  22.  
  23. var audioExtensionRegexp = new RegExp( "^.*\\.(" + audioExtensions + ")($|\\?)" ),
  24. mediaExtensionRegexp = new RegExp( "^.*\\.(" + mediaExtensions + ")($|\\?)" );
  25.  
  26. Popcorn.player = function( name, player ) {
  27.  
  28. // return early if a player already exists under this name
  29. if ( Popcorn[ name ] ) {
  30.  
  31. return;
  32. }
  33.  
  34. player = player || {};
  35.  
  36. var playerFn = function( target, src, options ) {
  37.  
  38. options = options || {};
  39.  
  40. // List of events
  41. var date = new Date() / 1000,
  42. baselineTime = date,
  43. currentTime = 0,
  44. readyState = 0,
  45. volume = 1,
  46. muted = false,
  47. events = {},
  48.  
  49. // The container div of the resource
  50. container = typeof target === "string" ? Popcorn.dom.find( target ) : target,
  51. basePlayer = {},
  52. timeout,
  53. popcorn;
  54.  
  55. if ( !Object.prototype.__defineGetter__ ) {
  56.  
  57. basePlayer = container || document.createElement( "div" );
  58. }
  59.  
  60. // copies a div into the media object
  61. for( var val in container ) {
  62.  
  63. // don't copy properties if using container as baseplayer
  64. if ( val in basePlayer ) {
  65.  
  66. continue;
  67. }
  68.  
  69. if ( typeof container[ val ] === "object" ) {
  70.  
  71. basePlayer[ val ] = container[ val ];
  72. } else if ( typeof container[ val ] === "function" ) {
  73.  
  74. basePlayer[ val ] = (function( value ) {
  75.  
  76. // this is a stupid ugly kludgy hack in honour of Safari
  77. // in Safari a NodeList is a function, not an object
  78. if ( "length" in container[ value ] && !container[ value ].call ) {
  79.  
  80. return container[ value ];
  81. } else {
  82.  
  83. return function() {
  84.  
  85. return container[ value ].apply( container, arguments );
  86. };
  87. }
  88. }( val ));
  89. } else {
  90.  
  91. Popcorn.player.defineProperty( basePlayer, val, {
  92. get: (function( value ) {
  93.  
  94. return function() {
  95.  
  96. return container[ value ];
  97. };
  98. }( val )),
  99. set: Popcorn.nop,
  100. configurable: true
  101. });
  102. }
  103. }
  104.  
  105. var timeupdate = function() {
  106.  
  107. date = new Date() / 1000;
  108.  
  109. if ( !basePlayer.paused ) {
  110.  
  111. basePlayer.currentTime = basePlayer.currentTime + ( date - baselineTime );
  112. basePlayer.dispatchEvent( "timeupdate" );
  113. timeout = setTimeout( timeupdate, 10 );
  114. }
  115.  
  116. baselineTime = date;
  117. };
  118.  
  119. basePlayer.play = function() {
  120.  
  121. this.paused = false;
  122.  
  123. if ( basePlayer.readyState >= 4 ) {
  124.  
  125. baselineTime = new Date() / 1000;
  126. basePlayer.dispatchEvent( "play" );
  127. timeupdate();
  128. }
  129. };
  130.  
  131. basePlayer.pause = function() {
  132.  
  133. this.paused = true;
  134. basePlayer.dispatchEvent( "pause" );
  135. };
  136.  
  137. Popcorn.player.defineProperty( basePlayer, "currentTime", {
  138. get: function() {
  139.  
  140. return currentTime;
  141. },
  142. set: function( val ) {
  143.  
  144. // make sure val is a number
  145. currentTime = +val;
  146. basePlayer.dispatchEvent( "timeupdate" );
  147.  
  148. return currentTime;
  149. },
  150. configurable: true
  151. });
  152.  
  153. Popcorn.player.defineProperty( basePlayer, "volume", {
  154. get: function() {
  155.  
  156. return volume;
  157. },
  158. set: function( val ) {
  159.  
  160. // make sure val is a number
  161. volume = +val;
  162. basePlayer.dispatchEvent( "volumechange" );
  163. return volume;
  164. },
  165. configurable: true
  166. });
  167.  
  168. Popcorn.player.defineProperty( basePlayer, "muted", {
  169. get: function() {
  170.  
  171. return muted;
  172. },
  173. set: function( val ) {
  174.  
  175. // make sure val is a number
  176. muted = +val;
  177. basePlayer.dispatchEvent( "volumechange" );
  178. return muted;
  179. },
  180. configurable: true
  181. });
  182.  
  183. Popcorn.player.defineProperty( basePlayer, "readyState", {
  184. get: function() {
  185.  
  186. return readyState;
  187. },
  188. set: function( val ) {
  189.  
  190. readyState = val;
  191. return readyState;
  192. },
  193. configurable: true
  194. });
  195.  
  196. // Adds an event listener to the object
  197. basePlayer.addEventListener = function( evtName, fn ) {
  198.  
  199. if ( !events[ evtName ] ) {
  200.  
  201. events[ evtName ] = [];
  202. }
  203.  
  204. events[ evtName ].push( fn );
  205. return fn;
  206. };
  207.  
  208. // Removes an event listener from the object
  209. basePlayer.removeEventListener = function( evtName, fn ) {
  210.  
  211. var i,
  212. listeners = events[ evtName ];
  213.  
  214. if ( !listeners ){
  215.  
  216. return;
  217. }
  218.  
  219. // walk backwards so we can safely splice
  220. for ( i = events[ evtName ].length - 1; i >= 0; i-- ) {
  221.  
  222. if( fn === listeners[ i ] ) {
  223.  
  224. listeners.splice(i, 1);
  225. }
  226. }
  227.  
  228. return fn;
  229. };
  230.  
  231. // Can take event object or simple string
  232. basePlayer.dispatchEvent = function( oEvent ) {
  233.  
  234. var evt,
  235. self = this,
  236. eventInterface,
  237. eventName = oEvent.type;
  238.  
  239. // A string was passed, create event object
  240. if ( !eventName ) {
  241.  
  242. eventName = oEvent;
  243. eventInterface = Popcorn.events.getInterface( eventName );
  244.  
  245. if ( eventInterface ) {
  246.  
  247. evt = document.createEvent( eventInterface );
  248. evt.initEvent( eventName, true, true, window, 1 );
  249. }
  250. }
  251.  
  252. if ( events[ eventName ] ) {
  253.  
  254. for ( var i = events[ eventName ].length - 1; i >= 0; i-- ) {
  255.  
  256. events[ eventName ][ i ].call( self, evt, self );
  257. }
  258. }
  259. };
  260.  
  261. // Attempt to get src from playerFn parameter
  262. basePlayer.src = src || "";
  263. basePlayer.duration = 0;
  264. basePlayer.paused = true;
  265. basePlayer.ended = 0;
  266.  
  267. options && options.events && Popcorn.forEach( options.events, function( val, key ) {
  268.  
  269. basePlayer.addEventListener( key, val, false );
  270. });
  271.  
  272. // true and undefined returns on canPlayType means we should attempt to use it,
  273. // false means we cannot play this type
  274. if ( player._canPlayType( container.nodeName, src ) !== false ) {
  275.  
  276. if ( player._setup ) {
  277.  
  278. player._setup.call( basePlayer, options );
  279. } else {
  280.  
  281. // there is no setup, which means there is nothing to load
  282. basePlayer.readyState = 4;
  283. basePlayer.dispatchEvent( "loadedmetadata" );
  284. basePlayer.dispatchEvent( "loadeddata" );
  285. basePlayer.dispatchEvent( "canplaythrough" );
  286. }
  287. } else {
  288.  
  289. // Asynchronous so that users can catch this event
  290. setTimeout( function() {
  291. basePlayer.dispatchEvent( "error" );
  292. }, 0 );
  293. }
  294.  
  295. popcorn = new Popcorn.p.init( basePlayer, options );
  296.  
  297. if ( player._teardown ) {
  298.  
  299. popcorn.destroy = combineFn( popcorn.destroy, function() {
  300.  
  301. player._teardown.call( basePlayer, options );
  302. });
  303. }
  304.  
  305. return popcorn;
  306. };
  307.  
  308. playerFn.canPlayType = player._canPlayType = player._canPlayType || Popcorn.nop;
  309.  
  310. Popcorn[ name ] = Popcorn.player.registry[ name ] = playerFn;
  311. };
  312.  
  313. Popcorn.player.registry = {};
  314.  
  315. Popcorn.player.defineProperty = Object.defineProperty || function( object, description, options ) {
  316.  
  317. object.__defineGetter__( description, options.get || Popcorn.nop );
  318. object.__defineSetter__( description, options.set || Popcorn.nop );
  319. };
  320.  
  321. // player queue is to help players queue things like play and pause
  322. // HTML5 video's play and pause are asynch, but do fire in sequence
  323. // play() should really mean "requestPlay()" or "queuePlay()" and
  324. // stash a callback that will play the media resource when it's ready to be played
  325. Popcorn.player.playerQueue = function() {
  326.  
  327. var _queue = [],
  328. _running = false;
  329.  
  330. return {
  331. next: function() {
  332.  
  333. _running = false;
  334. _queue.shift();
  335. _queue[ 0 ] && _queue[ 0 ]();
  336. },
  337. add: function( callback ) {
  338.  
  339. _queue.push(function() {
  340.  
  341. _running = true;
  342. callback && callback();
  343. });
  344.  
  345. // if there is only one item on the queue, start it
  346. !_running && _queue[ 0 ]();
  347. }
  348. };
  349. };
  350.  
  351. // smart will attempt to find you a match, if it does not find a match,
  352. // it will attempt to create a video element with the source,
  353. // if that failed, it will throw.
  354. Popcorn.smart = function( target, src, options ) {
  355. var playerType,
  356. elementTypes = [ "AUDIO", "VIDEO" ],
  357. sourceNode,
  358. firstSrc,
  359. node = Popcorn.dom.find( target ),
  360. i, srcResult,
  361. canPlayTypeTester = document.createElement( "video" ),
  362. canPlayTypes = {
  363. "ogg": "video/ogg",
  364. "ogv": "video/ogg",
  365. "oga": "audio/ogg",
  366. "webm": "video/webm",
  367. "mp4": "video/mp4",
  368. "mp3": "audio/mp3"
  369. };
  370.  
  371. var canPlayType = function( type ) {
  372.  
  373. return canPlayTypeTester.canPlayType( canPlayTypes[ type ] );
  374. };
  375.  
  376. var canPlaySrc = function( src ) {
  377.  
  378. srcResult = mediaExtensionRegexp.exec( src );
  379.  
  380. if ( !srcResult || !srcResult[ 1 ] ) {
  381. return false;
  382. }
  383.  
  384. return canPlayType( srcResult[ 1 ] );
  385. };
  386.  
  387. if ( !node ) {
  388.  
  389. Popcorn.error( "Specified target " + target + " was not found." );
  390. return;
  391. }
  392.  
  393. // For when no src is defined.
  394. // Usually this is a video element with a src already on it.
  395. if ( elementTypes.indexOf( node.nodeName ) > -1 && !src ) {
  396.  
  397. if ( typeof src === "object" ) {
  398.  
  399. options = src;
  400. src = undefined;
  401. }
  402.  
  403. return Popcorn( node, options );
  404. }
  405.  
  406. // if our src is not an array, create an array of one.
  407. if ( typeof( src ) === "string" ) {
  408.  
  409. src = [ src ];
  410. }
  411.  
  412. // go through each src, and find the first playable.
  413. // this only covers player sources popcorn knows of,
  414. // and not things like a youtube src that is private.
  415. // it will still consider a private youtube video to be playable.
  416. for ( i = 0, srcLength = src.length; i < srcLength; i++ ) {
  417.  
  418. // src is a playable HTML5 video, we don't need to check custom players.
  419. if ( canPlaySrc( src[ i ] ) ) {
  420.  
  421. src = src[ i ];
  422. break;
  423. }
  424.  
  425. // for now we loop through and use the first valid player we find.
  426. for ( var key in Popcorn.player.registry ) {
  427.  
  428. if ( Popcorn.player.registry.hasOwnProperty( key ) ) {
  429.  
  430. if ( Popcorn.player.registry[ key ].canPlayType( node.nodeName, src[ i ] ) ) {
  431.  
  432. // Popcorn.smart( player, src, /* options */ )
  433. return Popcorn[ key ]( node, src[ i ], options );
  434. }
  435. }
  436. }
  437. }
  438.  
  439. // Popcorn.smart( div, src, /* options */ )
  440. // attempting to create a video in a container
  441. if ( elementTypes.indexOf( node.nodeName ) === -1 ) {
  442.  
  443. firstSrc = typeof( src ) === "string" ? src : src.length ? src[ 0 ] : src;
  444.  
  445. target = document.createElement( !!audioExtensionRegexp.exec( firstSrc ) ? elementTypes[ 0 ] : elementTypes[ 1 ] );
  446.  
  447. // Controls are defaulted to being present
  448. target.controls = true;
  449.  
  450. node.appendChild( target );
  451. node = target;
  452. }
  453.  
  454. options && options.events && options.events.error && node.addEventListener( "error", options.events.error, false );
  455. node.src = src;
  456.  
  457. return Popcorn( node, options );
  458.  
  459. };
  460. })( Popcorn );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement