jPlayer.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /// vwf/model/jPlayer.js is a sound driver
  2. ///
  3. /// @module vwf/model/jPlayer
  4. /// @requires vwf/model
  5. define( [
  6. "module",
  7. "vwf/model",
  8. "vwf/utility",
  9. "jquery"
  10. ], function( module, model, utility, $ ) {
  11. var modelDriver;
  12. var jPlayerInstanceCreated = false;
  13. var audioManagerProtoId = "http://vwf.example.com/jplayer/audioManager.vwf";
  14. var videoManagerProtoId = "http://vwf.example.com/jplayer/videoManager.vwf";
  15. return model.load( module, {
  16. // == Module Definition ====================================================================
  17. // -- initialize ---------------------------------------------------------------------------
  18. initialize: function( options ) {
  19. modelDriver = this;
  20. this.arguments = Array.prototype.slice.call( arguments );
  21. this.options = options || {};
  22. this.state = {
  23. "nodes": {},
  24. "stages": {},
  25. "prototypes": {},
  26. "createLocalNode": function( nodeID, childID, childExtendsID, childImplementsIDs,
  27. childSource, childType, childIndex, childName, callback ) {
  28. return {
  29. "parentID": nodeID,
  30. "ID": childID,
  31. "extendsID": childExtendsID,
  32. "implementsIDs": childImplementsIDs,
  33. "source": childSource,
  34. "type": childType,
  35. "name": childName,
  36. "prototypes": undefined,
  37. "delayedProperties": undefined,
  38. "soundObj": undefined,
  39. "playState": "unloaded",
  40. "playOnReady": false
  41. };
  42. },
  43. "isAudioManager": function( prototypes ) {
  44. var found = false;
  45. if ( prototypes ) {
  46. for ( var i = 0; i < prototypes.length && !found; i++ ) {
  47. found = ( prototypes[ i ].indexOf( audioManagerProtoId ) !== -1 );
  48. }
  49. }
  50. return found;
  51. },
  52. "isVideoManager": function( prototypes ) {
  53. var found = false;
  54. if ( prototypes ) {
  55. for ( var i = 0; i < prototypes.length && !found; i++ ) {
  56. found = ( prototypes[ i ].indexOf( videoManagerProtoId ) !== -1 );
  57. }
  58. }
  59. return found;
  60. }
  61. };
  62. // turns on logger debugger console messages
  63. this.debug = {
  64. "creation": false,
  65. "initializing": false,
  66. "parenting": false,
  67. "deleting": false,
  68. "properties": false,
  69. "setting": false,
  70. "getting": false,
  71. "method": false,
  72. "prototypes": false
  73. };
  74. },
  75. creatingNode: function( nodeID, childID, childExtendsID, childImplementsIDs,
  76. childSource, childType, childIndex, childName, callback ) {
  77. if ( this.debug.creation ) {
  78. this.logger.infox( "creatingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName );
  79. }
  80. // If the node being created is a prototype, construct it and add it to the array of prototypes,
  81. // and then return
  82. var prototypeID = utility.ifPrototypeGetId.call( this, this.kernel.application(),
  83. this.state.prototypes, nodeID, childID );
  84. if ( prototypeID !== undefined ) {
  85. if ( this.debug.prototypes ) {
  86. this.logger.infox( "prototype: ", prototypeID );
  87. }
  88. this.state.prototypes[ prototypeID ] = {
  89. parentID: nodeID,
  90. ID: childID,
  91. extendsID: childExtendsID,
  92. implementsID: childImplementsIDs,
  93. source: childSource,
  94. type: childType,
  95. name: childName
  96. };
  97. if ( prototypeID.indexOf( audioManagerProtoId ) !== -1 ) {
  98. this.state.audioManagerProto = this.state.prototypes[ prototypeID ];
  99. } else if ( prototypeID.indexOf( videoManagerProtoId ) !== -1 ) {
  100. this.state.videoManagerProto = this.state.prototypes[ prototypeID ];
  101. }
  102. return;
  103. }
  104. var protos = getPrototypes( this.kernel, childExtendsID );
  105. var isAudioManager = this.state.isAudioManager( protos );
  106. var isVideoManager = this.state.isVideoManager( protos );
  107. if ( isAudioManager || isVideoManager ) {
  108. // Create the local copy of the node properties
  109. if ( this.state.nodes[ childID ] === undefined ){
  110. this.state.nodes[ childID ] = this.state.createLocalNode( nodeID, childID,
  111. childExtendsID, childImplementsIDs, childSource,
  112. childType, childIndex, childName, callback );
  113. }
  114. node = this.state.nodes[ childID ];
  115. node.prototypes = protos;
  116. if ( isAudioManager ) {
  117. node.managerType = "audio";
  118. setWithPrototypeProperties( this.state.audioManagerProto );
  119. } else {
  120. node.managerType = "video";
  121. setWithPrototypeProperties( this.state.videoManagerProto );
  122. }
  123. }
  124. },
  125. deletingNode: function( nodeID ) {
  126. if ( this.debug.deleting ) {
  127. this.logger.infox( "deletingNode", nodeID );
  128. }
  129. if ( this.state.nodes[ nodeID ] ) {
  130. delete this.state.nodes[ nodeID ];
  131. }
  132. },
  133. // -- creatingProperty ---------------------------------------------------------------------
  134. creatingProperty: function( nodeID, propertyName, propertyValue ) {
  135. if ( this.debug.properties ) {
  136. this.logger.infox( "C === creatingProperty ", nodeID, propertyName, propertyValue );
  137. }
  138. return this.settingProperty( nodeID, propertyName, propertyValue );
  139. },
  140. // -- initializingProperty -----------------------------------------------------------------
  141. initializingProperty: function( nodeID, propertyName, propertyValue ) {
  142. if ( this.debug.properties ) {
  143. this.logger.infox( " I === initializingProperty ", nodeID, propertyName, propertyValue );
  144. }
  145. return this.settingProperty( nodeID, propertyName, propertyValue );
  146. },
  147. // -- settingProperty ----------------------------------------------------------------------
  148. settingProperty: function( nodeID, propertyName, propertyValue ) {
  149. if ( this.debug.properties || this.debug.setting ) {
  150. this.logger.infox( " S === settingProperty ", nodeID, propertyName, propertyValue );
  151. }
  152. // Prepare return value
  153. var value = undefined;
  154. var node = this.state.nodes[ nodeID ];
  155. if ( node !== undefined ) {
  156. switch ( propertyName ) {
  157. case "url":
  158. setUrl( node, propertyValue );
  159. value = node.url;
  160. break;
  161. case "loop":
  162. setLoop( node, propertyValue );
  163. value = node.loop;
  164. break;
  165. case "playerDivId":
  166. if ( propertyValue === node.playerDivId ) {
  167. break;
  168. }
  169. if ( node.playerDivId ) {
  170. $( "#" + node.playerDivId ).remove();
  171. }
  172. node.playerDivId = propertyValue;
  173. var $existingElement = $( "#" + node.playerDivId );
  174. if ( $existingElement.length ) {
  175. node.jPlayerElement = $existingElement;
  176. } else {
  177. node.jPlayerElement = $( "<div/>", {
  178. id: node.playerDivId
  179. } );
  180. $( "body" ).append( node.jPlayerElement );
  181. }
  182. var fileTypes = ( node.managerType === "audio" ) ? "mp3,wav" : "m4v";
  183. node.jPlayerElement.jPlayer( {
  184. ready: function() {
  185. if ( node.url !== undefined ) {
  186. setUrl( node, node.url );
  187. }
  188. if ( node.loop !== undefined ) {
  189. setLoop( node, node.loop );
  190. }
  191. if ( node.containerDivId !== undefined ) {
  192. setControlDivId( node, node.containerDivId );
  193. }
  194. },
  195. supplied: fileTypes
  196. } );
  197. value = node.playerDivId;
  198. break;
  199. case "containerDivId":
  200. setControlDivId( node, propertyValue );
  201. value = node.containerDivId;
  202. break;
  203. case "posterImageUrl":
  204. setPosterImageUrl( node, propertyValue );
  205. value = node.posterImageUrl;
  206. break;
  207. default:
  208. break;
  209. }
  210. } else {
  211. var proto;
  212. var audioManagerProto = this.state.audioManagerProto;
  213. var videoManagerProto = this.state.videoManagerProto;
  214. if ( audioManagerProto && ( nodeID === audioManagerProto.ID ) ) {
  215. proto = this.state.audioManagerProto;
  216. } else if ( videoManagerProto && ( nodeID === videoManagerProto.ID ) ) {
  217. proto = this.state.videoManagerProto;
  218. }
  219. if ( proto ) {
  220. switch ( propertyName ) {
  221. case "url":
  222. proto.url = propertyValue;
  223. value = proto.url;
  224. break;
  225. case "loop":
  226. proto.loop = propertyValue;
  227. value = proto.loop;
  228. break;
  229. case "playerDivId":
  230. proto.playerDivId = propertyValue;
  231. value = proto.playerDivId;
  232. break;
  233. case "containerDivId":
  234. proto.containerDivId = propertyValue;
  235. value = proto.containerDivId;
  236. break;
  237. case "posterImageUrl":
  238. proto.posterImageUrl = propertyValue;
  239. value = proto.posterImageUrl;
  240. break;
  241. default:
  242. break;
  243. }
  244. }
  245. }
  246. return value;
  247. },
  248. // -- gettingProperty ----------------------------------------------------------------------
  249. gettingProperty: function( nodeID, propertyName ) {
  250. if ( this.debug.properties || this.debug.getting ) {
  251. this.logger.infox( " G === gettingProperty ", nodeID, propertyName );
  252. }
  253. var node = this.state.nodes[ nodeID ]; // { name: childName, glgeObject: undefined }
  254. return node && node[ propertyName ];
  255. },
  256. // TODO: deletingMethod
  257. // -- callingMethod --------------------------------------------------------------------------
  258. callingMethod: function( nodeID, methodName, methodParameters ) {
  259. if ( this.debug.method ) {
  260. this.logger.infox( " G === gettingProperty ", nodeID, propertyName );
  261. }
  262. var node = this.state.nodes[ nodeID ];
  263. if ( !node ) {
  264. return;
  265. }
  266. if ( node.jPlayerElement ) {
  267. switch( methodName ) {
  268. case "play":
  269. node.jPlayerElement.jPlayer( "play" );
  270. break;
  271. case "pause":
  272. node.jPlayerElement.jPlayer( "pause" );
  273. break;
  274. case "stop":
  275. node.jPlayerElement.jPlayer( "stop" );
  276. break;
  277. }
  278. }
  279. },
  280. } );
  281. function getPrototypes( kernel, extendsID ) {
  282. var prototypes = [];
  283. var id = extendsID;
  284. while ( id !== undefined ) {
  285. prototypes.push( id );
  286. id = kernel.prototype( id );
  287. }
  288. return prototypes;
  289. }
  290. function setWithPrototypeProperties( proto ) {
  291. if ( proto.url !== null ) {
  292. vwf.setProperty( node.ID, "url", proto.url );
  293. }
  294. if ( proto.loop !== null ) {
  295. vwf.setProperty( node.ID, "loop", proto.loop );
  296. }
  297. if ( proto.playerDivId !== null ) {
  298. vwf.setProperty( node.ID, "playerDivId", proto.playerDivId );
  299. }
  300. if ( proto.containerDivId !== null ) {
  301. vwf.setProperty( node.ID, "containerDivId", proto.containerDivId );
  302. }
  303. if ( proto.posterImageUrl !== null ) {
  304. vwf.setProperty( node.ID, "posterImageUrl", proto.posterImageUrl );
  305. }
  306. }
  307. function setUrl( node, url ) {
  308. node.url = url;
  309. // If there is no jPlayerElement, there is nothing to do yet so we return.
  310. // Once the jPlayerElement is created, setUrl will run again using the saved value
  311. if ( !node.jPlayerElement ) {
  312. return;
  313. }
  314. // If there is a url, set the media for the jPlayer object appropriately
  315. // Otherwise, clear the media
  316. if ( url ) {
  317. // Construct the media object based on the type of file being passed in
  318. var mediaObject;
  319. switch ( node.managerType ) {
  320. case "audio":
  321. if ( url.search( "data:audio/mp3" ) === 0 ) {
  322. mediaObject = {
  323. mp3: url
  324. };
  325. } else if ( url.search( "data:audio/wav" ) === 0 ) {
  326. mediaObject = {
  327. wav: url
  328. };
  329. } else {
  330. modelDriver.logger.errorx( "setUrl",
  331. "Unsupported sound type for '", url, "'" );
  332. }
  333. break;
  334. case "video":
  335. if ( url.search( "data:video/mp4" ) === 0 ) {
  336. mediaObject = {
  337. m4v: url,
  338. poster: node.posterImageUrl
  339. };
  340. } else {
  341. modelDriver.logger.errorx( "setUrl",
  342. "Unsupported video type for '", url, "'" );
  343. }
  344. break;
  345. default:
  346. modelDriver.logger.errorx( "setUrl",
  347. "Unsupported manager type '", node.managerType, "'" );
  348. break;
  349. }
  350. // If we succeeded in creating a media object, set it on the jPlayer object
  351. // Otherwise, clear the current media
  352. if ( mediaObject ) {
  353. node.jPlayerElement.jPlayer( "setMedia", mediaObject );
  354. } else {
  355. node.jPlayerElement.jPlayer( "clearMedia" );
  356. }
  357. } else {
  358. node.jPlayerElement.jPlayer( "clearMedia" );
  359. }
  360. }
  361. function setLoop( node, loop ) {
  362. node.loop = loop;
  363. if ( node.jPlayerElement ) {
  364. node.jPlayerElement.jPlayer( "option", { loop: loop } );
  365. }
  366. }
  367. function setControlDivId( node, containerDivId ) {
  368. node.containerDivId = containerDivId;
  369. if ( node.jPlayerElement ) {
  370. node.jPlayerElement.jPlayer( "option", { cssSelectorAncestor: "#" + containerDivId } );
  371. }
  372. }
  373. function setPosterImageUrl( node, posterImageUrl ) {
  374. node.posterImageUrl = posterImageUrl;
  375. if ( node.jPlayerElement ) {
  376. node.jPlayerElement.jPlayer( "setMedia", {
  377. m4v: node.url,
  378. poster: posterImageUrl
  379. } );
  380. }
  381. }
  382. } );