_Media.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.av._Media"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.av._Media"] = true;
  8. dojo.provide("dojox.av._Media");
  9. dojo.declare("dojox.av._Media", null, {
  10. // summary:
  11. // Used as a mixin for dojox and AIR media
  12. // description:
  13. // Calculates the current status of the playing media and fires
  14. // the appropriate events.
  15. //
  16. mediaUrl:"",
  17. //
  18. // initialVolume: Float?
  19. // The initial volume setting of the player. Acccepts between 0 and 1.
  20. initialVolume:1,
  21. //
  22. // autoPlay:Boolean?
  23. // Whether the video automatically plays on load or not.
  24. autoPlay: false,
  25. //
  26. // bufferTime: Number?
  27. // Time in milliseconds that the video should be loaded before it will
  28. // play. May pause and resume to build up buffer. Prevents stuttering.
  29. // Note:
  30. // Older FLVs, without a duration, cannot be buffered.
  31. bufferTime: 2000,
  32. //
  33. // minBufferTime: Number
  34. // Time in milliseconds bwteen the playhead time and loaded time that
  35. // will trigger the buffer. When buffer is triggered, video will pause
  36. // until the bufferTime amount is buffered.
  37. // Note: Should be a small number, greater than zero.
  38. minBufferTime:300,
  39. //
  40. // updateTime: Number
  41. // How often, in milliseconds to get an update of the video position.
  42. updateTime: 100,
  43. //
  44. // id: String?
  45. // The id of this widget and the id of the SWF movie.
  46. id:"",
  47. //
  48. // isDebug: Boolean?
  49. // Setting to true tells the SWF to output log messages to Firebug.
  50. isDebug: false,
  51. //
  52. // percentDownloaded: read-only-Number
  53. // The percentage the media has downloaded; from 0-100
  54. percentDownloaded:0,
  55. //
  56. // _flashObject: read-only-Object
  57. // The dojox.embed object
  58. _flashObject:null,
  59. //
  60. // flashMedia: read-only-SWF
  61. // The SWF object. Methods are passed to this.
  62. flashMedia:null,
  63. //
  64. // allowScriptAccess: String
  65. // Whether the SWF can access the container JS
  66. allowScriptAccess:"always",
  67. //
  68. // allowNetworking: String
  69. // Whether SWF is restricted to a domain
  70. allowNetworking: "all",
  71. //
  72. // wmode: String
  73. // The render type of the SWF
  74. wmode: "transparent",
  75. //
  76. // allowFullScreen: Boolean
  77. // Whether to allow the SWF to go to fullscreen
  78. allowFullScreen:true,
  79. _initStatus: function(){
  80. // summary:
  81. // Connect mediaStatus to the media.
  82. //
  83. this.status = "ready";
  84. this._positionHandle = dojo.connect(this, "onPosition", this, "_figureStatus");
  85. },
  86. // ============== //
  87. // Player Getters //
  88. // ============== //
  89. getTime: function(){
  90. // summary:
  91. // Returns the current time of the video
  92. // Note:
  93. // Consider the onPosition event, which returns
  94. // the time at a set interval. Too many trips to
  95. // the SWF could impact performance.
  96. return this.flashMedia.getTime(); // Float
  97. },
  98. // ============= //
  99. // Player Events //
  100. // ============= //
  101. onLoad: function(/* SWF */ mov){
  102. // summary:
  103. // Fired when the SWF player has loaded
  104. // NOT when the video has loaded
  105. //
  106. },
  107. onDownloaded: function(/* Number */percent){
  108. // summary:
  109. // Fires the amount of that the media has been
  110. // downloaded. Number, 0-100
  111. },
  112. onClick: function(/* Object */ evt){
  113. // summary:
  114. // TODO: Return x/y of click
  115. // Fires when the player is clicked
  116. // Could be used to toggle play/pause, or
  117. // do an external activity, like opening a new
  118. // window.
  119. },
  120. onSwfSized: function(/* Object */ data){
  121. // summary:
  122. // Fired on SWF resize, or when its
  123. // toggled between fullscreen.
  124. },
  125. onMetaData: function(/* Object */ data, /* Object */ evt){
  126. // summary:
  127. // The video properties. Width, height, duration, etc.
  128. // NOTE: if data is empty, this is an older FLV with no meta data.
  129. // Duration cannot be determined. In original FLVs, duration
  130. // could only be obtained with Flash Media Server.
  131. // NOTE: Older FLVs can still return width and height
  132. // and will do so on a second event call
  133. this.duration = data.duration;
  134. },
  135. onPosition: function(/* Float */ time){
  136. // summary:
  137. // The position of the playhead in seconds
  138. },
  139. onStart: function(/* Object */ data){
  140. // summary:
  141. // Fires when video starts
  142. // Good for setting the play button to pause
  143. // during an autoPlay for example
  144. },
  145. onPlay: function(/* Object */ data){
  146. // summary:
  147. // Fires when video starts and resumes
  148. },
  149. onPause: function(/* Object */ data){
  150. // summary:
  151. // Fires when the pause button is clicked
  152. },
  153. onEnd: function(/* Object */ data){
  154. // summary:
  155. // Fires when video ends
  156. // Could be used to change pause button to play
  157. // or show a post video graphic, like YouTube
  158. },
  159. onStop: function(){
  160. // summary:
  161. // Fire when the Stop button is clicked
  162. // TODO: This is not hooked up yet and shouldn't
  163. // fire.
  164. },
  165. onBuffer: function(/* Boolean */ isBuffering){
  166. // summary:
  167. // Fires a boolean to tell if media
  168. // is paused for buffering or if buffering
  169. // has finished
  170. this.isBuffering = isBuffering;
  171. },
  172. onError: function(/* Object */ data, /* String */ url){
  173. // summary:
  174. // Fired when the player encounters an error
  175. // example:
  176. // | console.warn("ERROR-"+data.type.toUpperCase()+":",
  177. // | data.info.code, " - URL:", url);
  178. console.warn("ERROR-"+data.type.toUpperCase()+":", data.info.code, " - URL:", url);
  179. },
  180. onStatus: function(/* Object */data){
  181. // summary:
  182. // Simple status
  183. },
  184. onPlayerStatus: function(/* Object */data){
  185. // summary:
  186. // The status of the video from the SWF
  187. // playing, stopped, bufering, etc.
  188. },
  189. onResize: function(){
  190. },
  191. _figureStatus: function(){
  192. // summary:
  193. // Calculate media status, based on playhead movement, and
  194. // onStop and onStart events
  195. // TODO:
  196. // Figure in real status from the media for more accurate results.
  197. //
  198. var pos = this.getTime();
  199. //console.log(pos, this.duration, (pos>this.duration-.5), (this.duration && pos>this.duration-.5))
  200. if(this.status=="stopping"){
  201. // stop was fired, need to fake pos==0
  202. this.status = "stopped";
  203. this.onStop(this._eventFactory());
  204. }else if(this.status=="ending" && pos==this._prevPos){
  205. this.status = "ended";
  206. this.onEnd(this._eventFactory());
  207. }else if(this.duration && pos>this.duration-.5){
  208. this.status="ending"
  209. }else if(pos===0 ){//|| this.status == "stopped"
  210. if(this.status == "ready"){
  211. //never played
  212. }else{
  213. //stopped
  214. this.status = "stopped";
  215. if(this._prevStatus != "stopped"){
  216. this.onStop(this._eventFactory());
  217. }
  218. }
  219. }else{
  220. // pos > 0
  221. if(this.status == "ready"){
  222. //started
  223. this.status = "started";
  224. this.onStart(this._eventFactory());
  225. this.onPlay(this._eventFactory());
  226. }else if(this.isBuffering){
  227. this.status = "buffering";
  228. }else if(this.status == "started" || (this.status == "playing" && pos != this._prevPos)){
  229. this.status = "playing";
  230. //this.onPosition(this._eventFactory());
  231. }else if(!this.isStopped && this.status == "playing" && pos == this._prevPos){
  232. this.status = "paused";
  233. console.warn("pause", pos, this._prevPos)
  234. if(this.status != this._prevStatus){
  235. this.onPause(this._eventFactory());
  236. }
  237. }else if((this.status == "paused" ||this.status == "stopped") && pos != this._prevPos){
  238. this.status = "started";
  239. this.onPlay(this._eventFactory());
  240. }
  241. }
  242. this._prevPos = pos;
  243. this._prevStatus = this.status;
  244. this.onStatus(this.status);
  245. },
  246. _eventFactory: function(){
  247. // summary:
  248. // Creates a generic event object.
  249. //
  250. var evt = {
  251. //position:this._channel.position,
  252. //seconds:this.toSeconds(this._channel.position*.001),
  253. //percentPlayed:this._getPercent(),
  254. status:this.status
  255. }
  256. return evt; // Object
  257. },
  258. _sub: function(topic, method){
  259. // summary:
  260. // helper for subscribing to topics
  261. dojo.subscribe(this.id+"/"+topic, this, method);
  262. },
  263. _normalizeVolume: function(vol){
  264. // summary:
  265. // Ensures volume is less than one
  266. //
  267. if(vol>1){
  268. while(vol>1){
  269. vol*=.1
  270. }
  271. }
  272. return vol;
  273. },
  274. _normalizeUrl: function(_url){
  275. // summary:
  276. // Checks that path is relative to HTML file or
  277. // convertes it to an absolute path.
  278. //
  279. console.log(" url:", _url);
  280. if(_url && (_url.toLowerCase().indexOf("http")<0 || _url.indexOf("/") == 0)){
  281. //
  282. // Appears to be a relative path. Attempt to convert it to absolute,
  283. // so it will better target the SWF.
  284. var loc = window.location.href.split("/");
  285. loc.pop();
  286. loc = loc.join("/")+"/";
  287. console.log(" loc:", loc);
  288. _url = loc+_url;
  289. }
  290. return _url;
  291. },
  292. destroy: function(){
  293. // summary:
  294. // destroys flash
  295. if(!this.flashMedia){
  296. this._cons.push(dojo.connect(this, "onLoad", this, "destroy"));
  297. return;
  298. }
  299. dojo.forEach(this._subs, function(s){
  300. dojo.unsubscribe(s);
  301. });
  302. dojo.forEach(this._cons, function(c){
  303. dojo.disconnect(c);
  304. });
  305. this._flashObject.destroy();
  306. //dojo._destroyElement(this.flashDiv);
  307. }
  308. });
  309. }