summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/av/_Media.js
blob: 4930b8ddfbd7e7124774e989f5041fe1c5237a8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
//>>built
define("dojox/av/_Media", ['dojo'],function(dojo){

dojo.experimental("dojox.av.FLVideo");

	return dojo.declare("dojox.av._Media", null, {
		// summary:
		//		Used as a mixin for dojox and AIR media
		//	description:
		//		Calculates the current status of the playing media and fires
		//		the appropriate events.
		//
		mediaUrl:"",
		//
		// initialVolume: Float?
		//		The initial volume setting of the player. Acccepts between 0 and 1.
		initialVolume:1,
		//
		//  autoPlay:Boolean?
		//		Whether the video automatically plays on load or not.
		autoPlay: false,
		//
		//	bufferTime: Number?
		//		Time in milliseconds that the video should be loaded before it will
		//		play. May pause and resume to build up buffer. Prevents stuttering.
		//	Note:
		//		Older FLVs, without a duration, cannot be buffered.
		bufferTime: 2000,
		//
		//	minBufferTime: Number
		//		Time in milliseconds bwteen the playhead time and loaded time that
		//		will trigger the buffer. When buffer is triggered, video will pause
		//		until the bufferTime amount is buffered.
		//		Note: Should be a small number, greater than zero.
		minBufferTime:300,
		//
		// updateTime: Number
		//		How often, in milliseconds to get an update of the video position.
		updateTime: 100,
		//
		//  id: String?
		//		The id of this widget and the id of the SWF movie.
		id:"",
		//
		// isDebug: Boolean?
		//		Setting to true tells the SWF to output log messages to Firebug.
		isDebug: false,
		//
		// percentDownloaded: read-only-Number
		//		The percentage the media has downloaded; from 0-100
		percentDownloaded:0,
		//
		// _flashObject: read-only-Object
		//	The dojox.embed object
		_flashObject:null,
		//
		// flashMedia: read-only-SWF
		//		The SWF object. Methods are passed to this.
		flashMedia:null,
		//
		// allowScriptAccess: String
		//		Whether the SWF can access the container JS
		allowScriptAccess:"always",
		//
		// allowNetworking: String
		//		Whether SWF is restricted to a domain
		allowNetworking: "all",
		//
		//	wmode: String
		//		The render type of the SWF
		wmode: "transparent",
		//
		//	allowFullScreen: Boolean
		//		Whether to allow the SWF to go to fullscreen
		allowFullScreen:true,
	
		_initStatus: function(){
			// summary:
			//		Connect mediaStatus to the media.
			//
			this.status = "ready";
			this._positionHandle = dojo.connect(this, "onPosition", this, "_figureStatus");
	
		},
	
		//  ==============  //
		//  Player Getters  //
		//  ==============  //
	
		getTime: function(){
			// summary:
			// 		Returns the current time of the video
			//	Note:
			//		Consider the onPosition event, which returns
			//		the time at a set interval. Too many trips to
			//		the SWF could impact performance.
			return this.flashMedia.getTime(); // Float
		},
	
		//  =============  //
		//  Player Events  //
		//  =============  //
	
		onLoad: function(/* SWF */ mov){
			// summary:
			// 		Fired when the SWF player has loaded
			// 		NOT when the video has loaded
			//
		},
	
		onDownloaded: function(/* Number */percent){
			// summary:
			//		Fires the amount of that the media has been
			//		downloaded. Number, 0-100
		},
	
		onClick: function(/* Object */ evt){
			// summary:
			// 		TODO: Return x/y of click
			// 		Fires when the player is clicked
			// 		Could be used to toggle play/pause, or
			// 		do an external activity, like opening a new
			//		window.
		},
	
		onSwfSized: function(/* Object */ data){
			// summary:
			// 		Fired on SWF resize, or when its
			// 		toggled between fullscreen.
		},
	
		onMetaData: function(/* Object */ data, /* Object */ evt){
			// summary:
			// 		The video properties. Width, height, duration, etc.
			// 		NOTE: 	if data is empty, this is an older FLV with no meta data.
			// 				Duration cannot be determined. In original FLVs, duration
			//				could only be obtained with Flash Media Server.
			// 		NOTE: 	Older FLVs can still return width and height
			//				and will do so on a second event call
			console.warn("onMeta", data)
			this.duration = data.duration;
		},
	
		onPosition: function(/* Float */ time){
			// summary:
			//		The position of the playhead in seconds
		},
	
		onStart: function(/* Object */ data){
			// summary:
			// 		Fires when video starts
			// 		Good for setting the play button to pause
			// 		during an autoPlay for example
		},
	
		onPlay: function(/* Object */ data){
			// summary:
			// 		Fires when video starts and resumes
		},
	
		onPause: function(/* Object */ data){
			// summary:
			// 		Fires when the pause button is clicked
		},
	
		onEnd: function(/* Object */ data){
			// summary:
			// 		Fires when video ends
			// 		Could be used to change pause button to play
			// 		or show a post video graphic, like YouTube
		},
	
		onStop: function(){
			// summary:
			// Fire when the Stop button is clicked
			// TODO: 	This is not hooked up yet and shouldn't
			//			fire.
		},
	
		onBuffer: function(/* Boolean */ isBuffering){
			// summary:
			//		Fires a boolean to tell if media
			//		is paused for buffering or if buffering
			//		has finished
			this.isBuffering = isBuffering;
		},
	
		onError: function(/* Object */ data, /* String */ url){
			// summary:
			// 		Fired when the player encounters an error
			// example:
			//		| console.warn("ERROR-"+data.type.toUpperCase()+":",
			//		|		data.info.code, " - URL:", url);
			console.warn("ERROR-"+data.type.toUpperCase()+":", data.info.code, " - URL:", url);
		},
	
		onStatus: function(/* Object */data){
			// summary:
			// 		Simple status
		},
	
		onPlayerStatus: function(/* Object */data){
			// summary:
			// 		The status of the video from the SWF
			// 		playing, stopped, bufering, etc.
		},
	
		onResize: function(){
	
		},
	
		_figureStatus: function(){
			// summary:
			//		Calculate media status, based on playhead movement, and
			//		onStop and onStart events
			// TODO:
			//		Figure in real status from the media for more accurate results.
			//
			var pos = this.getTime();
			//console.log(pos, this.duration,  (pos>this.duration-.5), (this.duration && pos>this.duration-.5))
	
			if(this.status=="stopping"){
				// stop was fired, need to fake pos==0
				this.status = "stopped";
				this.onStop(this._eventFactory());
	
			}else if(this.status=="ending" && pos==this._prevPos){
				this.status = "ended";
				this.onEnd(this._eventFactory());
	
			}else if(this.duration && pos>this.duration-.5){
				this.status="ending"
	
			}else if(pos===0 ){//|| this.status == "stopped"
				if(this.status == "ready"){
					//never played
				}else{
					//stopped
					this.status = "stopped";
					if(this._prevStatus != "stopped"){
						this.onStop(this._eventFactory());
					}
				}
	
			}else{
				// pos > 0
				if(this.status == "ready"){
					//started
					this.status = "started";
					this.onStart(this._eventFactory());
					this.onPlay(this._eventFactory());
	
				}else if(this.isBuffering){
					this.status = "buffering";
	
				}else if(this.status == "started" || (this.status == "playing" &&  pos != this._prevPos)){
					this.status = "playing";
					//this.onPosition(this._eventFactory());
	
				}else if(!this.isStopped && this.status == "playing" && pos == this._prevPos){
					this.status = "paused";
					console.warn("pause", pos, this._prevPos)
					if(this.status != this._prevStatus){
						this.onPause(this._eventFactory());
					}
	
				}else if((this.status == "paused" ||this.status == "stopped") && pos != this._prevPos){
					this.status = "started";
					this.onPlay(this._eventFactory());
				}
			}
	
			this._prevPos = pos;
			this._prevStatus = this.status;
			this.onStatus(this.status);
	
	
		},
	
		_eventFactory: function(){
			// summary:
			//		Creates a generic event object.
			//
			var evt = {
				//position:this._channel.position,
				//seconds:this.toSeconds(this._channel.position*.001),
				//percentPlayed:this._getPercent(),
				status:this.status
			}
			return evt; // Object
		},
	
	
	
		_sub: function(topic, method){
			// summary:
			// helper for subscribing to topics
			dojo.subscribe(this.id+"/"+topic, this, method);
		},
	
		_normalizeVolume: function(vol){
			// summary:
			//		Ensures volume is less than one
			//
			if(vol>1){
				while(vol>1){
					vol*=.1
				}
			}
			return vol;
		},
	
		_normalizeUrl: function(_url){
			// summary:
			//		Checks that path is relative to HTML file or
			//		convertes it to an absolute path.
			//
	
			console.log("  url:", _url);
	
			if(_url && (_url.toLowerCase().indexOf("http")<0 || _url.indexOf("/") == 0)){
				//
				// Appears to be a relative path. Attempt to  convert it to absolute,
				// so it will better target the SWF.
				var loc = window.location.href.split("/");
				loc.pop();
	
				loc = loc.join("/")+"/";
				console.log("  loc:", loc);
				_url = loc+_url;
			}
			return _url;
		},
	
		destroy: function(){
			// summary:
			// 		destroys flash
			if(!this.flashMedia){
				this._cons.push(dojo.connect(this, "onLoad", this, "destroy"));
				return;
			}
			dojo.forEach(this._subs, function(s){
				dojo.unsubscribe(s);
			});
			dojo.forEach(this._cons, function(c){
				dojo.disconnect(c);
			});
			this._flashObject.destroy();
			//dojo._destroyElement(this.flashDiv);
	
		}
	});
});