[cvs] / ossdk / InnerServiceRIAC / lib / V2Components / mx / video / VideoPlayer.as Repository:
Cosoft CVS

Annotation of /ossdk/InnerServiceRIAC/lib/V2Components/mx/video/VideoPlayer.as

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (view) (download)

1 : thiswind 1.1 //****************************************************************************
2 :     //Copyright (C) 2004-2005 Macromedia, Inc. All Rights Reserved.
3 :     //The following is Sample Code and is subject to all restrictions on
4 :     //such code as contained in the End User License Agreement accompanying
5 :     //this product.
6 :     //****************************************************************************
7 :    
8 :     import mx.events.EventDispatcher;
9 :     import mx.video.*;
10 :    
11 :     /**
12 :     * <p>Event dispatched when <code>NetConnection</code> is closed,
13 :     * whether by being timed out or by calling <code>close()</code> API.
14 :     * Only dispatched with RTMP streams, never HTTP. Event Object has
15 :     * properties state and playheadTime.</p>
16 :     *
17 :     */
18 :     [Event("close")]
19 :    
20 :     /**
21 :     * <p>Event dispatched when playing completes by reaching the end of
22 :     * the FLV. Is not dispatched if the APIs <code>stop()</code> or
23 :     * <code>pause()</code> are called. Event Object has properties state and
24 :     * playheadTime.</p>
25 :     *
26 :     * <p>When using progressive download and not setting totalTime
27 :     * explicitly and downloading an FLV with no metadata duration,
28 :     * the totalTime will be set to an approximate total value, now
29 :     * that we have played the whole file we can make a guess. That
30 :     * value is set by the time this event is dispatched.</p>
31 :     *
32 :     */
33 :     [Event("complete")]
34 :    
35 :     /**
36 :     * <p>Event dispatched when a cue point is reached. Event Object has an
37 :     * info property that contains the info object received by the
38 :     * <code>NetStream.onCuePoint</code> callback for FLV cue points or
39 :     * the object passed into the AS cue point APIs for AS cue points.</p>
40 :     *
41 :     */
42 :     [Event("cuePoint")]
43 :    
44 :     /**
45 :     * <p>Event dispatched the first time the FLV metadata is reached.
46 :     * Event Object has an info property that contains the info object
47 :     * received by the <code>NetStream.onMetaData</code> callback.</p>
48 :     *
49 :     */
50 :     [Event("metadataReceived")]
51 :    
52 :     /**
53 :     * <p>While FLV is playing, this event is dispatched every .25
54 :     * seconds. Not dispatched when we are paused or stopped, unless a
55 :     * seek occurs. Event Object has properties state and playheadTime.</p>
56 :     *
57 :     */
58 :     [Event("playheadUpdate")]
59 :    
60 :     /**
61 :     * <p>Indicates progress made in number of bytes downloaded. User can
62 :     * use this to check bytes loaded or number of bytes in the buffer.
63 :     * Fires every .25 seconds, starting when load is called and ending
64 :     * when all bytes are loaded or if there is a network error. Event Object is
65 :     * of type <code>mx.events.ProgressEvent</code>.</p>
66 :     *
67 :     */
68 :     [Event("progress")]
69 :    
70 :     /**
71 :     * <p>Event dispatched when FLV is loaded and ready to display. Event
72 :     * object has properties state and playheadTime.</p>
73 :     *
74 :     * <p>Fired the first time we enter a responsive state after we
75 :     * load a new flv with play() or load() API. Only fires once
76 :     * for each FLV loaded.</p>
77 :     *
78 :     */
79 :     [Event("ready")]
80 :    
81 :     /**
82 :     * <p>Event dispatched when video is autoresized due to
83 :     * maintainAspectRatio or autoSize properties set to true. Event
84 :     * Object has properties x, y, width and height.</p>
85 :     *
86 :     */
87 :     [Event("resize")]
88 :    
89 :     /**
90 :     * <p>Event dispatched when video autorewinds. Event Object has properties
91 :     * state and playheadTime.</p>
92 :     *
93 :     */
94 :     [Event("rewind")]
95 :    
96 :     /**
97 :     * <p>Event dispatched when playback state changes. Event Object has
98 :     * properties state and playheadTime.</p>
99 :     *
100 :     * <p>This event can be used to track when playback enters/leaves
101 :     * unresponsive states (for example in the middle of connecting,
102 :     * resizing or rewinding) during which times APIs <code>play()</code>,
103 :     * <code>pause()</code>, <code>stop()</code> and <code>seek()</code>
104 :     * will queue the requests to be executed when the player enters
105 :     * a responsive state.</p>
106 :     */
107 :     [Event("stateChange")]
108 :    
109 :     /**
110 :     * <p>VideoPlayer is an easy to use wrapper for Video, NetConnection,
111 :     * NetStream, etc. that makes playing FLV easy. It supports streaming
112 :     * from Flash Communication Server (FCS) and http download of FLVs.</p>
113 :     *
114 :     * <p>VideoPlayer extends MovieClip and wraps a Video object. It also
115 :     * "extends" EventDispatcher using mixins.</p>
116 :     *
117 :     * @author copyright 2004-2005 Macromedia, Inc.
118 :     */
119 :    
120 :     class mx.video.VideoPlayer extends MovieClip {
121 :    
122 :     #include "ComponentVersion.as"
123 :    
124 :     // public state constants
125 :    
126 :     /**
127 :     * <p>State constant. This is the state when the VideoPlayer is
128 :     * constructed and when the stream is closed by a call to
129 :     * <code>close()</code> or timed out on idle.</p>
130 :     *
131 :     * <p>This is a responsive state.</p>
132 :     *
133 :     * @see #state
134 :     * @see #stateResponsive
135 :     * @see #connected
136 :     * @see #idleTimeout
137 :     * @see #close()
138 :     */
139 :     public static var DISCONNECTED:String = "disconnected";
140 :    
141 :     /**
142 :     * <p>State constant. FLV is loaded and play is stopped. This state
143 :     * is entered when <code>stop()</code> is called and when the
144 :     * playhead reaches the end of the stream.</p>
145 :     *
146 :     * <p>This is a responsive state.</p>
147 :     *
148 :     * @see #state
149 :     * @see #stateResponsive
150 :     * @see #stop()
151 :     */
152 :     public static var STOPPED:String = "stopped";
153 :    
154 :     /**
155 :     * <p>State constant. FLV is loaded and is playing.
156 :     * This state is entered when <code>play()</code>
157 :     * is called.</p>
158 :     *
159 :     * <p>This is a responsive state.</p>
160 :     *
161 :     * @see #state
162 :     * @see #stateResponsive
163 :     * @see #play()
164 :     */
165 :     public static var PLAYING:String = "playing";
166 :    
167 :     /**
168 :     * <p>State constant. FLV is loaded, but play is paused.
169 :     * This state is entered when <code>pause()</code> is
170 :     * called or when <code>load()</code> is called.</p>
171 :     *
172 :     * <p>This is a responsive state.</p>
173 :     *
174 :     * @see #state
175 :     * @see #stateResponsive
176 :     * @see #pause()
177 :     * @see #load()
178 :     */
179 :     public static var PAUSED:String = "paused";
180 :    
181 :     /**
182 :     * <p>State constant. State entered immediately after
183 :     * <code>play()</code> or <code>load()</code> is called.</p>
184 :     *
185 :     * <p>This is a responsive state.</p>
186 :     *
187 :     * @see #state
188 :     * @see #stateResponsive
189 :     */
190 :     public static var BUFFERING:String = "buffering";
191 :    
192 :     /**
193 :     * <p>State constant. State entered immediately after
194 :     * <code>play()</code> or <code>load()</code> is called.</p>
195 :     *
196 :     * <p>This is a unresponsive state.</p>
197 :     *
198 :     * @see #state
199 :     * @see #stateResponsive
200 :     * @see #load()
201 :     * @see #play()
202 :     */
203 :     public static var LOADING:String = "loading";
204 :    
205 :     /**
206 :     * <p>State constant. Stream attempted to load was unable to load
207 :     * for some reason. Could be no connection to server, stream not
208 :     * found, etc.</p>
209 :     *
210 :     * <p>This is a unresponsive state.</p>
211 :     *
212 :     * @see #state
213 :     * @see #stateResponsive
214 :     */
215 :     public static var CONNECTION_ERROR:String = "connectionError";
216 :    
217 :     /**
218 :     * <p>State constant. State entered during a autorewind triggered
219 :     * by a stop. After rewind is complete, the state will be
220 :     * <code>STOPPED</code>.</p>
221 :     *
222 :     * <p>This is a unresponsive state.</p>
223 :     *
224 :     * @see #autoRewind
225 :     * @see #state
226 :     * @see #stateResponsive
227 :     */
228 :     public static var REWINDING:String = "rewinding";
229 :    
230 :     /**
231 :     * <p>State constant. State entered after <code>seek()</code>
232 :     * is called.</p>
233 :     *
234 :     * <p>This is a unresponsive state.</p>
235 :     *
236 :     * @see #state
237 :     * @see #stateResponsive
238 :     * @see #seek()
239 :     */
240 :     public static var SEEKING:String = "seeking";
241 :    
242 :     /**
243 :     * <p>State constant. State entered during autoresize.</p>
244 :     *
245 :     * <p>This is a unresponsive state.</p>
246 :     *
247 :     * @see #autoSize
248 :     * @see #maintainAspectRatio
249 :     * @see #state
250 :     * @see #stateResponsive
251 :     */
252 :     public static var RESIZING:String = "resizing";
253 :    
254 :     /**
255 :     * <P>State constant. State during execution of queued command.
256 :     * There will never get a "stateChange" event notification with
257 :     * this state; it is internal only.</p>
258 :     *
259 :     * <p>This is a unresponsive state.</p>
260 :     *
261 :     * @see #state
262 :     * @see #stateResponsive
263 :     */
264 :     static var EXEC_QUEUED_CMD:String = "execQueuedCmd";
265 :    
266 :     // buffer states
267 :     private static var BUFFER_EMPTY:String = "bufferEmpty";
268 :     private static var BUFFER_FULL:String = "bufferFull";
269 :     private static var BUFFER_FULL_SAW_PLAY_STOP:String = "bufferFullSawPlayStop";
270 :    
271 :     // state
272 :     private var _state:String;
273 :     private var _cachedState:String;
274 :     private var _bufferState:String;
275 :     private var _cachedPlayheadTime:Number;
276 :     private var _metadata:Object;
277 :     private var _startingPlay:Boolean;
278 :     private var _invalidSeekTime:Boolean;
279 :     private var _invalidSeekRecovery:Boolean;
280 :     private var _readyDispatched:Boolean;
281 :     private var _autoResizeDone:Boolean;
282 :     private var _lastUpdateTime:Number;
283 :     private var _sawSeekNotify:Boolean;
284 :    
285 :     // Video object
286 :     private var _video:Video;
287 :    
288 :     // INCManager
289 :     private var _ncMgr:INCManager;
290 :     public var ncMgrClassName:String;
291 :    
292 :     /**
293 :     * <p>Set this property to the name of your custom class to
294 :     * make all VideoPlayer objects created use that class as the
295 :     * default INCManager implementation. The default value is
296 :     * "mx.video.NCManager".</p>
297 :     */
298 :     public static var DEFAULT_INCMANAGER:String = "mx.video.NCManager";
299 :    
300 :     // info about NetStream
301 :     private var _ns:NetStream;
302 :     private var _currentPos:Number;
303 :     private var _atEnd:Boolean;
304 :     private var _streamLength:Number;
305 :    
306 :     // store properties
307 :     private var _autoSize:Boolean;
308 :     private var _aspectRatio:Boolean;
309 :    
310 :     /**
311 :     * <p>If true, then video plays immediately, if false waits for
312 :     * <code>play</code> to be called. Set to true if stream is
313 :     * loaded with call to <code>play()</code>, false if loaded
314 :     * by call to <code>load()</code>.</p>
315 :     *
316 :     * <p>Even if <code>_autoPlay</code> is set to false, we will start
317 :     * loading the video after <code>initialize()</code> is called.
318 :     * In the case of FCS, this means creating the stream and loading
319 :     * the first frame to display (and loading more if
320 :     * <code>autoSize</code> or <code>aspectRatio</code> is true). In
321 :     * the case of HTTP download, we will start downloading the stream
322 :     * and show the first frame.</p>
323 :     *
324 :     * @private
325 :     */
326 :     private var _autoPlay:Boolean;
327 :    
328 :     private var _autoRewind:Boolean;
329 :     private var _contentPath:String;
330 :     private var _bufferTime:Number;
331 :     private var _isLive:Boolean;
332 :     private var _volume:Number;
333 :     private var _sound:Sound;
334 :     private var __visible:Boolean;
335 :     private var _hiddenForResize:Boolean;
336 :     private var _hiddenForResizeMetadataDelay:Number;
337 :     private var _hiddenRewindPlayheadTime:Number;
338 :     private var _videoWidth:Number;
339 :     private var _videoHeight:Number;
340 :     private var _prevVideoWidth:Number;
341 :     private var _prevVideoHeight:Number;
342 :    
343 :     // intervals
344 :     private var _updateTimeIntervalID:Number;
345 :     private var _updateTimeInterval:Number;
346 :     private var _updateProgressIntervalID:Number;
347 :     private var _updateProgressInterval:Number;
348 :     private var _idleTimeoutIntervalID:Number;
349 :     private var _idleTimeoutInterval:Number;
350 :     private var _autoResizeIntervalID:Number;
351 :     private var _rtmpDoStopAtEndIntervalID:Number;
352 :     private var _rtmpDoSeekIntervalID:Number;
353 :     private var _httpDoSeekIntervalID:Number;
354 :     private var _httpDoSeekCount:Number
355 :     private var _finishAutoResizeIntervalID:Number;
356 :     private var _delayedBufferingIntervalID:Number;
357 :     private var _delayedBufferingInterval:Number
358 :    
359 :     // default times for intervals
360 :     static var DEFAULT_UPDATE_TIME_INTERVAL:Number = 250; // .25 seconds
361 :     static var DEFAULT_UPDATE_PROGRESS_INTERVAL:Number = 250; // .25 seconds
362 :     static var DEFAULT_IDLE_TIMEOUT_INTERVAL:Number = 300000; // five minutes
363 :     private static var AUTO_RESIZE_INTERVAL:Number = 100; // .1 seconds
364 :     private static var AUTO_RESIZE_PLAYHEAD_TIMEOUT = .5; // .5 seconds
365 :     private static var AUTO_RESIZE_METADATA_DELAY_MAX:Number = 5; // .5 seconds
366 :     private static var FINISH_AUTO_RESIZE_INTERVAL:Number = 250; // .25 seconds
367 :     private static var RTMP_DO_STOP_AT_END_INTERVAL:Number = 500; // .5 seconds
368 :     private static var RTMP_DO_SEEK_INTERVAL:Number = 100; // .1 seconds
369 :     private static var HTTP_DO_SEEK_INTERVAL:Number = 250; // .25 seconds
370 :     private static var HTTP_DO_SEEK_MAX_COUNT:Number = 4; // 4 times * .25 seconds = 1 second
371 :     private static var CLOSE_NS_INTERVAL:Number = .25; // .25 secconds
372 :     private static var HTTP_DELAYED_BUFFERING_INTERVAL:Number = 100; // .1 seconds
373 :    
374 :     // queues up Objects describing queued commands to be run later
375 :     private var _cmdQueue:Array;
376 :    
377 :     // values for command types for _cmdQueue
378 :     static var PLAY:Number = 0;
379 :     static var LOAD:Number = 1;
380 :     static var PAUSE:Number = 2;
381 :     static var STOP:Number = 3;
382 :     static var SEEK:Number = 4;
383 :    
384 :     // EventDispatcher mixins
385 :     public var addEventListener:Function;
386 :     public var removeEventListener:Function;
387 :     public var dispatchEvent:Function;
388 :     public var dispatchQueue:Function;
389 :    
390 :     //ifdef DEBUG
391 :     //private static var _debugSingleton:VideoPlayer;
392 :     //endif
393 :    
394 :     //
395 :     // public APIs
396 :     //
397 :    
398 :     /**
399 :     * <p>Constructor.</p>
400 :     *
401 :     * @see INCManager
402 :     * @see NCManager
403 :     */
404 :     public function VideoPlayer() {
405 :     // add EventDispatcher mixins
406 :     EventDispatcher.initialize(this);
407 :    
408 :     // init state variables
409 :     _state = DISCONNECTED;
410 :     _cachedState = _state;
411 :     _bufferState = BUFFER_EMPTY;
412 :     _cachedPlayheadTime = 0;
413 :     _metadata = null;
414 :     _startingPlay = false;
415 :     _invalidSeekTime = false;
416 :     _invalidSeekRecovery = false;
417 :     _currentPos = 0;
418 :     _atEnd = false;
419 :     _cmdQueue = new Array();
420 :     _readyDispatched = false;
421 :     _autoResizeDone = false;
422 :     _lastUpdateTime = -1;
423 :     _sawSeekNotify = false;
424 :    
425 :     // put off creation of INCManager until last minute to
426 :     // give time to customize DEFAULT_INCMANAGER
427 :    
428 :     // setup intervals
429 :     _updateTimeIntervalID = 0;
430 :     _updateTimeInterval = DEFAULT_UPDATE_TIME_INTERVAL;
431 :     _updateProgressIntervalID = 0;
432 :     _updateProgressInterval = DEFAULT_UPDATE_PROGRESS_INTERVAL;
433 :     _idleTimeoutIntervalID = 0;
434 :     _idleTimeoutInterval = DEFAULT_IDLE_TIMEOUT_INTERVAL;
435 :     _autoResizeIntervalID = 0;
436 :     _rtmpDoStopAtEndIntervalID = 0;
437 :     _rtmpDoSeekIntervalID = 0;
438 :     _httpDoSeekIntervalID = 0;
439 :     _httpDoSeekCount = 0;
440 :     _finishAutoResizeIntervalID = 0;
441 :     _delayedBufferingIntervalID = 0;
442 :     _delayedBufferingInterval = HTTP_DELAYED_BUFFERING_INTERVAL;
443 :    
444 :     // init get/set properties
445 :     if (_isLive == undefined) _isLive = false;
446 :     if (_autoSize == undefined) _autoSize = false;
447 :     if (_aspectRatio == undefined) _aspectRatio = true;
448 :     if (_autoPlay == undefined) _autoPlay = true;
449 :     if (_autoRewind == undefined) _autoRewind = true;
450 :     if (_bufferTime == undefined) _bufferTime = 0.1;
451 :     if (_volume == undefined) _volume = 100;
452 :     _sound = new Sound(this);
453 :     _sound.setVolume(_volume);
454 :     __visible = true;
455 :     _hiddenForResize = false;
456 :     _hiddenForResizeMetadataDelay = 0;
457 :     _contentPath = "";
458 :    
459 :     //ifdef DEBUG
460 :     //_debugSingleton = this;
461 :     //endif
462 :     }
463 :    
464 :     /**
465 :     * <p>set width and height simultaneously. Since setting either
466 :     * one can trigger an autoresize, this can be better than invoking
467 :     * set width and set height individually.</p>
468 :     *
469 :     * <p>If autoSize is true then this has no effect, since the player
470 :     * sets its own dimensions. If maintainAspectRatio is true and
471 :     * autoSize is false, then changing width or height will trigger
472 :     * an autoresize.</p>
473 :     *
474 :     * @param width
475 :     * @param height
476 :     * @see width
477 :     * @see height
478 :     */
479 :     public function setSize(w:Number, h:Number):Void
480 :     {
481 :     if ( (w == _video._width && h == _video._height) || _autoSize ) return;
482 :     _video._width = w;
483 :     _video._height = h;
484 :     if (_aspectRatio) {
485 :     startAutoResize();
486 :     }
487 :     }
488 :    
489 :     /**
490 :     * <p>set scaleX and scaleY simultaneously. Since setting either
491 :     * one can trigger an autoresize, this can be better than invoking
492 :     * set width and set height individually.</p>
493 :     *
494 :     * <p>If autoSize is true then this has no effect, since the player
495 :     * sets its own dimensions. If maintainAspectRatio is true and
496 :     * autoSize is false, then changing scaleX or scaleY will trigger an
497 :     * autoresize.</p>
498 :     *
499 :     * @param scaleX
500 :     * @param scaleY
501 :     * @see scaleX
502 :     * @see scaleY
503 :     */
504 :     public function setScale(xs:Number, ys:Number) {
505 :     if ( (xs == _video._xscale && ys == _video._yscale) || _autoSize ) return;
506 :     _video._xscale = xs;
507 :     _video._yscale = ys;
508 :     if (_aspectRatio) {
509 :     startAutoResize();
510 :     }
511 :     }
512 :    
513 :     /**
514 :     * <p>Causes the video to play. Can be called while the video is
515 :     * paused, stopped, or while the video is already playing. Call this
516 :     * method with no arguments to play an already loaded video or pass
517 :     * in a url to load a new stream.</p>
518 :     *
519 :     * <p>If player is in an unresponsive state, queues the request.</p>
520 :     *
521 :     * <p>Throws an exception if called with no args and no stream
522 :     * is connected. Use "stateChange" event and
523 :     * <code>connected</code> property to determine when it is
524 :     * safe to call this method.</p>
525 :     *
526 :     * @param url Pass in a url string if you want to load and play a
527 :     * new FLV. If you have already loaded an FLV and want to continue
528 :     * playing it, pass in <code>null</code>.
529 :     * @param isLive Pass in true if streaming a live feed from FCS.
530 :     * Defaults to false.
531 :     * @param totalTime Pass in length of FLV. Pass in 0 or null or
532 :     * undefined to automatically detect length from metadata, server
533 :     * or xml. If <code>INCManager.streamLength</code> is not 0 or
534 :     * null or undefined when <code>ncConnected</code> is called, then
535 :     * that value will trump this one in any case. Default is
536 :     * undefined.
537 :     * @see #connected
538 :     * @see #stateResponsive
539 :     * @see #load()
540 :     */
541 :     public function play(url:String, isLive:Boolean, totalTime:Number):Void {
542 :     //ifdef DEBUG
543 :     //debugTrace("play(" + url + ")");
544 :     //endif
545 :    
546 :     // if new url passed, ask the INCManager to reconnect for us
547 :     if (url != null && url != undefined) {
548 :     if (_state == EXEC_QUEUED_CMD) {
549 :     _state = _cachedState;
550 :     } else if (!stateResponsive) {
551 :     queueCmd(PLAY, url, isLive, totalTime);
552 :     return;
553 :     } else {
554 :     execQueuedCmds();
555 :     }
556 :     _autoPlay = true;
557 :     _load(url, isLive, totalTime);
558 :     // playing will start automatically once stream is setup, so return.
559 :     return;
560 :     }
561 :    
562 :     if (!isXnOK()) {
563 :     if ( _state == CONNECTION_ERROR ||
564 :     _ncMgr == null || _ncMgr == undefined ||
565 :     _ncMgr.getNetConnection() == null ||
566 :     _ncMgr.getNetConnection() == undefined ) {
567 :     throw new VideoError(VideoError.NO_CONNECTION);
568 :     } else {
569 :     //ifdef DEBUG
570 :     //debugTrace("RECONNECTING!!!");
571 :     //endif
572 :     flushQueuedCmds();
573 :     queueCmd(PLAY);
574 :     setState(LOADING);
575 :     _cachedState = LOADING;
576 :     _ncMgr.reconnect();
577 :     // playing will start automatically once stream is setup, so return.
578 :     return;
579 :     }
580 :     } else if (_state == EXEC_QUEUED_CMD) {
581 :     _state = _cachedState;
582 :     } else if (!stateResponsive) {
583 :     queueCmd(PLAY);
584 :     return;
585 :     } else {
586 :     execQueuedCmds();
587 :     }
588 :    
589 :     // recreate stream if necessary (this will never happen with
590 :     // http download, just rtmp)
591 :     if (_ns == null || _ns == undefined) {
592 :     _createStream();
593 :     _video.attachVideo(_ns);
594 :     this.attachAudio(_ns);
595 :     }
596 :    
597 :     switch (_state) {
598 :     case BUFFERING:
599 :     if (_ncMgr.isRTMP()) {
600 :     _play(0);
601 :     if (_atEnd) {
602 :     _atEnd = false;
603 :     _currentPos = 0;
604 :     setState(REWINDING);
605 :     } else if (_currentPos > 0) {
606 :     _seek(_currentPos);
607 :     _currentPos = 0;
608 :     }
609 :     }
610 :     // no break
611 :     case PLAYING:
612 :     // already playing
613 :     return;
614 :     case STOPPED:
615 :     if (_ncMgr.isRTMP()) {
616 :     if (_isLive) {
617 :     _play(-1);
618 :     setState(BUFFERING);
619 :     } else {
620 :     _play(0);
621 :     if (_atEnd) {
622 :     _atEnd = false;
623 :     _currentPos = 0;
624 :     _state = BUFFERING;
625 :     setState(REWINDING);
626 :     } else if (_currentPos > 0) {
627 :     _seek(_currentPos);
628 :     _currentPos = 0;
629 :     setState(BUFFERING);
630 :     } else {
631 :     setState(BUFFERING);
632 :     }
633 :     }
634 :     } else {
635 :     _pause(false);
636 :     if (_atEnd) {
637 :     _atEnd = false;
638 :     _seek(0);
639 :     _state = BUFFERING;
640 :     setState(REWINDING);
641 :     } else {
642 :     if (_bufferState == BUFFER_EMPTY) {
643 :     setState(BUFFERING);
644 :     } else {
645 :     setState(PLAYING);
646 :     }
647 :     }
648 :     }
649 :     break;
650 :     case PAUSED:
651 :     _pause(false);
652 :     if (!_ncMgr.isRTMP()) {
653 :     if (_bufferState == BUFFER_EMPTY) {
654 :     setState(BUFFERING);
655 :     } else {
656 :     setState(PLAYING);
657 :     }
658 :     } else {
659 :     setState(BUFFERING);
660 :     }
661 :     break;
662 :     } // switch
663 :     }
664 :    
665 :     /**
666 :     * <p>Similar to play, but causes the FLV to be loaded without
667 :     * playing. Autoresizing will occur if appropriate and the first
668 :     * frame of FLV will be shown (except for maybe not in the live case).
669 :     * After initial load and autoresize, state will be <code>PAUSED</code>.</p>
670 :     *
671 :     * <p>Takes same arguments as <code>play()</code>, but unlike that
672 :     * method it is never acceptable to call <code>load()</code> with
673 :     * no url. If you do, an <code>Error</code> will be thrown.</p>
674 :     *
675 :     * <p>If player is in an unresponsive state, queues the request.</p>
676 :     *
677 :     * @param url Pass in a url string for the FLV you want to load.
678 :     * @param isLive Pass in true if streaming a live feed from FCS.
679 :     * Defaults to false.
680 :     * @param totalTime Pass in length of FLV. Pass in 0 or null or
681 :     * undefined to automatically detect length from metadata, server
682 :     * or xml. If <code>INCManager.streamLength</code> is not 0 or
683 :     * null or undefined when <code>ncConnected</code> is called, then
684 :     * that value will trump this one in any case. Default is
685 :     * undefined.
686 :     * @see #connected
687 :     * @see #play()
688 :     */
689 :     public function load(url:String, isLive:Boolean, totalTime:Number):Void {
690 :     if (url == null || url == undefined) {
691 :     throw new Error("null url sent to VideoPlayer.load");
692 :     }
693 :    
694 :     //ifdef DEBUG
695 :     //debugTrace("load(" + url + ")");
696 :     //endif
697 :    
698 :     if (_state == EXEC_QUEUED_CMD) {
699 :     _state = _cachedState;
700 :     } else if (!stateResponsive) {
701 :     queueCmd(LOAD, url, isLive, totalTime);
702 :     return;
703 :     } else {
704 :     execQueuedCmds();
705 :     }
706 :     _autoPlay = false;
707 :     _load(url, isLive, totalTime);
708 :     }
709 :    
710 :     /*
711 :     * does loading work for play and load
712 :     */
713 :     private function _load(url:String, isLive:Boolean, totalTime:Number):Void {
714 :     //ifdef DEBUG
715 :     //debugTrace("_load(" + url + ", " + isLive + ", " + totalTime + ")");
716 :     //endif
717 :     _prevVideoWidth = this.videoWidth;
718 :     if (_prevVideoWidth == undefined) {
719 :     _prevVideoWidth = _video.width;
720 :     if (_prevVideoWidth == undefined) _prevVideoWidth = 0;
721 :     }
722 :     _prevVideoHeight = this.videoHeight;
723 :     if (_prevVideoHeight == undefined) {
724 :     _prevVideoHeight = _video.height;
725 :     if (_prevVideoHeight == undefined) _prevVideoHeight = 0;
726 :     }
727 :    
728 :     // reset state
729 :     _autoResizeDone = false;
730 :     _cachedPlayheadTime = 0;
731 :     _bufferState = BUFFER_EMPTY;
732 :     _metadata = null;
733 :     _startingPlay = false;
734 :     _invalidSeekTime = false;
735 :     _invalidSeekRecovery = false;
736 :     _isLive = (isLive == undefined) ? false : isLive;
737 :     _contentPath = url;
738 :     _currentPos = 0;
739 :     _streamLength = totalTime;
740 :     _atEnd = false;
741 :     _videoWidth = undefined;
742 :     _videoHeight = undefined;
743 :     _readyDispatched = false;
744 :     _lastUpdateTime = -1;
745 :     _sawSeekNotify = false;
746 :    
747 :     // must stop ALL intervals here
748 :     clearInterval(_updateTimeIntervalID);
749 :     _updateTimeIntervalID = 0;
750 :     clearInterval(_updateProgressIntervalID);
751 :     _updateProgressIntervalID = 0;
752 :     clearInterval(_idleTimeoutIntervalID);
753 :     _idleTimeoutIntervalID = 0;
754 :     clearInterval(_autoResizeIntervalID);
755 :     _autoResizeIntervalID = 0;
756 :     clearInterval(_rtmpDoStopAtEndIntervalID);
757 :     _rtmpDoStopAtEndIntervalID = 0;
758 :     clearInterval(_rtmpDoSeekIntervalID);
759 :     _rtmpDoSeekIntervalID = 0;
760 :     clearInterval(_httpDoSeekIntervalID);
761 :     _httpDoSeekIntervalID = 0;
762 :     clearInterval(_finishAutoResizeIntervalID);
763 :     _finishAutoResizeIntervalID = 0;
764 :     clearInterval(_delayedBufferingIntervalID);
765 :     _delayedBufferingIntervalID = 0;
766 :    
767 :     // close netstream
768 :     closeNS(false);
769 :    
770 :     // if returns false, wait for a "connected" message and
771 :     // then do these things
772 :     if (_ncMgr == null || _ncMgr == undefined) {
773 :     createINCManager();
774 :     }
775 :     var instantConnect:Boolean = _ncMgr.connectToURL(_contentPath);
776 :     setState(LOADING);
777 :     _cachedState = LOADING;
778 :     if (instantConnect) {
779 :     _createStream();
780 :     _setUpStream();
781 :     }
782 :     if (!_ncMgr.isRTMP()) {
783 :     clearInterval(_updateProgressIntervalID);
784 :     _updateProgressIntervalID = setInterval(this, "doUpdateProgress", _updateProgressInterval);
785 :     }
786 :     }
787 :    
788 :     /**
789 :     * <p>Pauses video playback. If video is paused or stopped, has
790 :     * no effect. To start playback again, call <code>play()</code>.
791 :     * Takes no parameters</p>
792 :     *
793 :     * <p>If player is in an unresponsive state, queues the request.</p>
794 :     *
795 :     * <p>Throws an exception if called when no stream is
796 :     * connected. Use "stateChange" event and
797 :     * <code>connected</code> property to determine when it is
798 :     * safe to call this method.</p>
799 :     *
800 :     * <p>If state is already stopped, pause is does nothing and state
801 :     * remains stopped.</p>
802 :     *
803 :     * @see #connected
804 :     * @see #stateResponsive
805 :     * @see #play()
806 :     */
807 :     public function pause():Void {
808 :     //ifdef DEBUG
809 :     //debugTrace("pause()");
810 :     //endif
811 :    
812 :     if (!isXnOK()) {
813 :     if ( _state == CONNECTION_ERROR ||
814 :     _ncMgr == null || _ncMgr == undefined ||
815 :     _ncMgr.getNetConnection() == null ||
816 :     _ncMgr.getNetConnection() == undefined ) {
817 :     throw new VideoError(VideoError.NO_CONNECTION);
818 :     } else {
819 :     return;
820 :     }
821 :     } else if (_state == EXEC_QUEUED_CMD) {
822 :     _state = _cachedState;
823 :     } else if (!stateResponsive) {
824 :     queueCmd(PAUSE);
825 :     return;
826 :     } else {
827 :     execQueuedCmds();
828 :     }
829 :     if (_state == PAUSED || _state == STOPPED || _ns == null || _ns == undefined) return;
830 :     _pause(true);
831 :     setState(PAUSED);
832 :     }
833 :    
834 :     /**
835 :     * <p>Stops video playback. If <code>autoRewind</code> is set to
836 :     * <code>true</code>, rewinds to first frame. If video is already
837 :     * stopped, has no effect. To start playback again, call
838 :     * <code>play()</code>. Takes no parameters</p>
839 :     *
840 :     * <p>If player is in an unresponsive state, queues the request.</p>
841 :     *
842 :     * <p>Throws an exception if called when no stream is
843 :     * connected. Use "stateChange" event and
844 :     * <code>connected</code> property to determine when it is
845 :     * safe to call this method.</p>
846 :     *
847 :     * @see #connected
848 :     * @see #stateResponsive
849 :     * @see #autoRewind
850 :     * @see #play()
851 :     */
852 :     public function stop():Void
853 :     {
854 :     //ifdef DEBUG
855 :     //debugTrace("stop()");
856 :     //endif
857 :    
858 :     if (!isXnOK()) {
859 :     if ( _state == CONNECTION_ERROR ||
860 :     _ncMgr == null || _ncMgr == undefined ||
861 :     _ncMgr.getNetConnection() == null ||
862 :     _ncMgr.getNetConnection() == undefined ) {
863 :     throw new VideoError(VideoError.NO_CONNECTION);
864 :     } else {
865 :     return;
866 :     }
867 :     } else if (_state == EXEC_QUEUED_CMD) {
868 :     _state = _cachedState;
869 :     } else if (!stateResponsive) {
870 :     queueCmd(STOP);
871 :     return;
872 :     } else {
873 :     execQueuedCmds();
874 :     }
875 :     if (_state == STOPPED || _ns == null || _ns == undefined) return;
876 :     if (_ncMgr.isRTMP()) {
877 :     if (_autoRewind && !_isLive) {
878 :     _currentPos = 0;
879 :     _play(0, 0);
880 :     _state = STOPPED;
881 :     setState(REWINDING);
882 :     } else {
883 :     closeNS(true);
884 :     setState(STOPPED);
885 :     }
886 :     } else {
887 :     _pause(true);
888 :     if (_autoRewind) {
889 :     _seek(0);
890 :     _state = STOPPED;
891 :     setState(REWINDING);
892 :     } else {
893 :     setState(STOPPED);
894 :     }
895 :     }
896 :     }
897 :    
898 :     /**
899 :     * <p>Seeks to given second in video. If video is playing,
900 :     * continues playing from that point. If video is paused, seek to
901 :     * that point and remain paused. If video is stopped, seek to
902 :     * that point and enters paused state. Has no effect with live
903 :     * streams.</p>
904 :     *
905 :     * <p>If time is less than 0 or NaN, throws exeption. If time
906 :     * is past the end of the stream, or past the amount of file
907 :     * downloaded so far, then will attempt seek and when fails
908 :     * will recover.</p>
909 :     *
910 :     * <p>If player is in an unresponsive state, queues the request.</p>
911 :     *
912 :     * <p>Throws an exception if called when no stream is
913 :     * connected. Use "stateChange" event and
914 :     * <code>connected</code> property to determine when it is
915 :     * safe to call this method.</p>
916 :     *
917 :     * @param time seconds
918 :     * @throws VideoError if time is < 0
919 :     * @see #connected
920 :     * @see #stateResponsive
921 :     */
922 :     public function seek(time:Number):Void
923 :     {
924 :     //ifdef DEBUG
925 :     //debugTrace("seek:"+time);
926 :     //endif
927 :     // we do not allow more seeks until we are out of an invalid seek time state
928 :     if (_invalidSeekTime) return;
929 :     if (isNaN(time) || time < 0) throw new VideoError(VideoError.INVALID_SEEK);
930 :     if (!isXnOK()) {
931 :     if ( _state == CONNECTION_ERROR ||
932 :     _ncMgr == null || _ncMgr == undefined ||
933 :     _ncMgr.getNetConnection() == null ||
934 :     _ncMgr.getNetConnection() == undefined ) {
935 :     throw new VideoError(VideoError.NO_CONNECTION);
936 :     } else {
937 :     //ifdef DEBUG
938 :     //debugTrace("RECONNECTING!!!");
939 :     //endif
940 :     flushQueuedCmds();
941 :     queueCmd(SEEK, null, false, time);
942 :     setState(LOADING);
943 :     _cachedState = LOADING;
944 :     _ncMgr.reconnect();
945 :     // playing will start automatically once stream is setup, so return.
946 :     return;
947 :     }
948 :     } else if (_state == EXEC_QUEUED_CMD) {
949 :     _state = _cachedState;
950 :     } else if (!stateResponsive) {
951 :     queueCmd(SEEK, null, false, time);
952 :     return;
953 :     } else {
954 :     execQueuedCmds();
955 :     }
956 :    
957 :     // recreate stream if necessary (this will never happen with
958 :     // http download, just rtmp)
959 :     if (_ns == null || _ns == undefined) {
960 :     _createStream();
961 :     _video.attachVideo(_ns);
962 :     this.attachAudio(_ns);
963 :     }
964 :    
965 :     if (_atEnd && time < playheadTime) {
966 :     _atEnd = false;
967 :     }
968 :    
969 :     switch (_state) {
970 :     case PLAYING:
971 :     _state = BUFFERING;
972 :     // no break;
973 :     case BUFFERING:
974 :     case PAUSED:
975 :     _seek(time);
976 :     setState(SEEKING);
977 :     break;
978 :     case STOPPED:
979 :     if (_ncMgr.isRTMP()) {
980 :     _play(0);
981 :     _pause(true);
982 :     }
983 :     _seek(time);
984 :     _state = PAUSED;
985 :     setState(SEEKING);
986 :     break;
987 :     }
988 :     }
989 :    
990 :     /**
991 :     * <p>Forces close of video stream and FCS connection. Triggers
992 :     * "close" event. Typically calling this directly is not necessary
993 :     * because the idle timeout functionality will take care of this.</p>
994 :     *
995 :     * @see idleTimeout
996 :     */
997 :     public function close():Void {
998 :     //ifdef DEBUG
999 :     //debugTrace("close()");
1000 :     //endif
1001 :     closeNS(true);
1002 :     // never makes sense to close an http NetConnection, it doesn't really maintain
1003 :     // any kind of network connection!
1004 :     if (_ncMgr != null && _ncMgr != undefined && _ncMgr.isRTMP()) {
1005 :     _ncMgr.close();
1006 :     }
1007 :     setState(DISCONNECTED);
1008 :     dispatchEvent({type:"close", state:_state, playheadTime:playheadTime});
1009 :     }
1010 :    
1011 :    
1012 :     //
1013 :     // public getters, setters
1014 :     //
1015 :    
1016 :    
1017 :     public function get x():Number {
1018 :     return this._x;
1019 :     }
1020 :     public function set x(xpos:Number) {
1021 :     this._x = xpos;
1022 :     }
1023 :    
1024 :     public function get y():Number {
1025 :     return this._y;
1026 :     }
1027 :     public function set y(ypos:Number) {
1028 :     this._y = ypos;
1029 :     }
1030 :    
1031 :     /**
1032 :     * 100 is standard scale
1033 :     *
1034 :     * @see #setScale()
1035 :     */
1036 :     function get scaleX():Number
1037 :     {
1038 :     return _video._xscale;
1039 :     }
1040 :     function set scaleX(xs:Number):Void
1041 :     {
1042 :     setScale(xs, this.scaleY);
1043 :     }
1044 :    
1045 :     /**
1046 :     * 100 is standard scale
1047 :     *
1048 :     * @see #setScale()
1049 :     */
1050 :     function get scaleY():Number
1051 :     {
1052 :     return _video._yscale;
1053 :     }
1054 :     function set scaleY(ys:Number):Void
1055 :     {
1056 :     setScale(this.scaleX, ys);
1057 :     }
1058 :    
1059 :     /**
1060 :     * <p>Width of video instance. Not same as Video.width, that is videoWidth.</p>
1061 :     *
1062 :     * @see #setSize()
1063 :     * @see #videoWidth
1064 :     */
1065 :     public function get width():Number {
1066 :     return _video._width;
1067 :     }
1068 :     public function set width(w:Number):Void
1069 :     {
1070 :     setSize(w, _video._height);
1071 :     }
1072 :    
1073 :     /**
1074 :     * <p>Height of video. Not same as Video.height, that is videoHeight.</p>
1075 :     *
1076 :     * @see #setSize()
1077 :     * @see #videoHeight
1078 :     */
1079 :     public function get height():Number {
1080 :     return _video._height;
1081 :     }
1082 :     public function set height(h:Number):Void
1083 :     {
1084 :     setSize(_video._width, h);
1085 :     }
1086 :    
1087 :     /**
1088 :     * <p>Source width of loaded FLV file. Read only. Returns
1089 :     * undefined if no information available yet.</p>
1090 :     *
1091 :     * @see #width
1092 :     */
1093 :     public function get videoWidth() {
1094 :     if (_readyDispatched) {
1095 :     _videoWidth = _video.width;
1096 :     }
1097 :     return _videoWidth;
1098 :     }
1099 :    
1100 :     /**
1101 :     * <p>Source height of loaded FLV file. Read only. Returns
1102 :     * undefined if no information available yet.</p>
1103 :     *
1104 :     * @see #height
1105 :     */
1106 :     public function get videoHeight() {
1107 :     if (_readyDispatched) {
1108 :     _videoHeight = _video.height;
1109 :     }
1110 :     return _videoHeight;
1111 :     }
1112 :    
1113 :     /**
1114 :     * <p>Use this instead of <code>_visible</code> because we
1115 :     * sometimes do internal visibility management when doing an
1116 :     * autoresize.</p>
1117 :     */
1118 :     public function get visible():Boolean {
1119 :     if (!_hiddenForResize) {
1120 :     __visible = _visible;
1121 :     }
1122 :     return __visible;
1123 :     }
1124 :    
1125 :     public function set visible(v:Boolean):Void {
1126 :     __visible = v;
1127 :     if (!_hiddenForResize) {
1128 :     _visible = __visible;
1129 :     }
1130 :     }
1131 :    
1132 :     /**
1133 :     * <p>Determines whether the instance is automatically resized to
1134 :     * the source dimensions. If this is set from false to true after
1135 :     * an FLV has been loaded, an automatic resize will start
1136 :     * immediately.</p>
1137 :     *
1138 :     */
1139 :     public function get autoSize():Boolean
1140 :     {
1141 :     return _autoSize;
1142 :     }
1143 :     public function set autoSize(flag:Boolean):Void
1144 :     {
1145 :     if (_autoSize != flag) {
1146 :     _autoSize = flag;
1147 :     if (_autoSize) {
1148 :     startAutoResize();
1149 :     }
1150 :     }
1151 :     }
1152 :    
1153 :     /**
1154 :     * <p>Determines whether video aspect ratio is maintained. If
1155 :     * this is set from false to true and <code>autoSize</code is
1156 :     * false after an FLV has been loaded, an automatic resize will
1157 :     * start immediately.</p>
1158 :     *
1159 :     * @see #autoSize
1160 :     */
1161 :     public function get maintainAspectRatio():Boolean
1162 :     {
1163 :     return _aspectRatio;
1164 :     }
1165 :     public function set maintainAspectRatio(flag:Boolean):Void
1166 :     {
1167 :     if (_aspectRatio != flag) {
1168 :     _aspectRatio = flag;
1169 :     if (_aspectRatio && !_autoSize) {
1170 :     startAutoResize();
1171 :     }
1172 :     }
1173 :     }
1174 :    
1175 :     /**
1176 :     * <p>Determines whether the FLV is rewound to the first frame
1177 :     * when play stops, either by calling <code>stop()</code> or by
1178 :     * reaching the end of the stream. Meaningless for live streams.</p>
1179 :     *
1180 :     */
1181 :     public function get autoRewind():Boolean
1182 :     {
1183 :     return _autoRewind;
1184 :     }
1185 :     public function set autoRewind(flag:Boolean):Void
1186 :     {
1187 :     _autoRewind = flag;
1188 :     }
1189 :    
1190 :     /**
1191 :     * <p>The current playhead time in seconds. Setting does a seek
1192 :     * and has all the restrictions of a seek.</p>
1193 :     *
1194 :     * <p>The event "playheadUpdate" is dispatched when the playhead
1195 :     * time changes, including every .25 seconds while the FLV is
1196 :     * playing.</p>
1197 :     *
1198 :     * @return The playhead position, measured in seconds since the start. Will return a fractional value.
1199 :     * @see #seek()
1200 :     */
1201 :     public function get playheadTime():Number
1202 :     {
1203 :     var nowTime:Number = (_ns == null || _ns == undefined) ? _currentPos : _ns.time;
1204 :     if (_metadata.audiodelay != undefined) {
1205 :     nowTime -= _metadata.audiodelay;
1206 :     if (nowTime < 0) nowTime = 0;
1207 :     }
1208 :     return nowTime;
1209 :     }
1210 :     public function set playheadTime(position:Number):Void
1211 :     {
1212 :     seek(position);
1213 :     }
1214 :    
1215 :     /**
1216 :     * <p>url of currently loaded (or loading) stream. Will be url
1217 :     * last sent to <code>play()</code> or <code>load()</code>, <code>null</code>
1218 :     * if no stream is loaded.</p>
1219 :     *
1220 :     */
1221 :     public function get url():String
1222 :     {
1223 :     return _contentPath;
1224 :     }
1225 :    
1226 :     /**
1227 :     * <p>Volume control in range from 0 to 100.</p>
1228 :     *
1229 :     * @return The most recent volume setting
1230 :     * @see #transform
1231 :     */
1232 :     public function get volume():Number
1233 :     {
1234 :     return _volume;
1235 :     }
1236 :     public function set volume(aVol:Number):Void
1237 :     {
1238 :     _volume = aVol;
1239 :     if (!_hiddenForResize) {
1240 :     _sound.setVolume(_volume);
1241 :     }
1242 :     }
1243 :    
1244 :     /**
1245 :     * <p>Provides direct access to the
1246 :     * <code>Sound.setTransform()</code> and
1247 :     * <code>Sound.getTransform()</code> APIs. to expose more sound
1248 :     * control. Must set property for changes to take effect, get
1249 :     * property just to get a copy of the current settings to tweak.</p>
1250 :     *
1251 :     * @see #volume
1252 :     */
1253 :     public function get transform():Object {
1254 :     return _sound.getTransform();
1255 :     }
1256 :     public function set transform(s:Object):Void {
1257 :     _sound.setTransform(s);
1258 :     }
1259 :    
1260 :     /**
1261 :     * True if stream is RTMP download (streaming from Flash
1262 :     * Communication Server), read only.
1263 :     */
1264 :     public function get isRTMP():Boolean {
1265 :     if (_ncMgr == null || _ncMgr == undefined) return undefined;
1266 :     return _ncMgr.isRTMP();
1267 :     }
1268 :    
1269 :     /**
1270 :     * <p>True if stream is live, read only. isLive only makes sense when
1271 :     * streaming from FVSS or FCS, value is ignored when doing http
1272 :     * download.</p>
1273 :     */
1274 :     public function get isLive():Boolean {
1275 :     return _isLive;
1276 :     }
1277 :    
1278 :     /**
1279 :     * Get state. Read only. Set with <code>load</code>,
1280 :     * <code>play()</code>, <code>stop()</code>,
1281 :     * <code>pause()</code> and <code>seek()</code>.
1282 :     */
1283 :     public function get state():String {
1284 :     return _state;
1285 :     }
1286 :    
1287 :     /**
1288 :     * Read only. Gets whether state is responsive. If state is
1289 :     * unresponsive, calls to APIs <code>play()</code>,
1290 :     * <code>load()</code>, <code>stop()</code>,
1291 :     * <code>pause()</code> and <code>seek()</code> will queue the
1292 :     * requests for later, when the state changes to a responsive
1293 :     * one.
1294 :     *
1295 :     * @see #connected
1296 :     * @see #DISCONNECTED
1297 :     * @see #STOPPED
1298 :     * @see #PLAYING
1299 :     * @see #PAUSED
1300 :     * @see #LOADING
1301 :     * @see #RESIZING
1302 :     * @see #CONNECTION_ERROR
1303 :     * @see #REWINDING
1304 :     */
1305 :     public function get stateResponsive():Boolean {
1306 :     switch (_state) {
1307 :     case DISCONNECTED:
1308 :     case STOPPED:
1309 :     case PLAYING:
1310 :     case PAUSED:
1311 :     case BUFFERING:
1312 :     return true;
1313 :     default:
1314 :     return false;
1315 :     }
1316 :     }
1317 :    
1318 :     /**
1319 :     * <p>property bytesLoaded, read only. Returns -1 when there
1320 :     * is no stream, when the stream is FCS or if the information
1321 :     * is not yet available. Return value only useful for HTTP
1322 :     * download.</p>
1323 :     *
1324 :     */
1325 :     public function get bytesLoaded():Number
1326 :     {
1327 :     if (_ns == null || _ns == undefined || _ncMgr.isRTMP()) return -1;
1328 :     return _ns.bytesLoaded;
1329 :     }
1330 :    
1331 :     /**
1332 :     * <p>property bytesTotal, read only. Returns -1 when there
1333 :     * is no stream, when the stream is FCS or if the information
1334 :     * is not yet available. Return value only useful for HTTP
1335 :     * download.</p>
1336 :     *
1337 :     */
1338 :     public function get bytesTotal():Number
1339 :     {
1340 :     if (_ns == null || _ns == undefined || _ncMgr.isRTMP()) return -1;
1341 :     return _ns.bytesTotal;
1342 :     }
1343 :    
1344 :     /**
1345 :     * <p>property totalTime. read only. 0 or null or undefined
1346 :     * means that property was not passed into <code>play()</code> or
1347 :     * <code>load()</code> and was unable to detect automatically, or
1348 :     * have not yet.</p>
1349 :     *
1350 :     * @return The total running time of the FLV in seconds
1351 :     */
1352 :     public function get totalTime():Number
1353 :     {
1354 :     return _streamLength;
1355 :     }
1356 :    
1357 :     /**
1358 :     * <p>Sets number of seconds to buffer in memory before playing
1359 :     * back stream. For slow connections streaming over rtmp, it is
1360 :     * important to increase this from the default. Default is
1361 :     * 0.1</p>
1362 :     */
1363 :     public function get bufferTime():Number
1364 :     {
1365 :     return _bufferTime;
1366 :     }
1367 :     public function set bufferTime(aTime:Number):Void
1368 :     {
1369 :     _bufferTime = aTime;
1370 :     if (_ns != null && _ns != undefined) {
1371 :     _ns.setBufferTime(_bufferTime);
1372 :     }
1373 :     }
1374 :    
1375 :     /**
1376 :     * <p>Property idleTimeout, which is amount of time in
1377 :     * milliseconds before connection is idle (playing is paused
1378 :     * or stopped) before connection to the FCS server is
1379 :     * terminated. Has no effect to HTTP download of FLV.</p>
1380 :     *
1381 :     * <p>If set when stream already idle, restarts idle timeout with
1382 :     * new value.</p>
1383 :     */
1384 :     public function get idleTimeout():Number {
1385 :     return _idleTimeoutInterval;
1386 :     }
1387 :     public function set idleTimeout(aTime:Number):Void {
1388 :     _idleTimeoutInterval = aTime;
1389 :     if (_idleTimeoutIntervalID > 0) {
1390 :     clearInterval(_idleTimeoutIntervalID);
1391 :     _idleTimeoutIntervalID = setInterval(this, "doIdleTimeout", _idleTimeoutInterval);
1392 :     }
1393 :     }
1394 :    
1395 :     /**
1396 :     * <p>Property playheadUpdateInterval, which is amount of time
1397 :     * in milliseconds between each "playheadUpdate" event.</p>
1398 :     *
1399 :     * <p>If set when stream is playing, will restart interval.</p>
1400 :     */
1401 :     public function get playheadUpdateInterval():Number {
1402 :     return _updateTimeInterval;
1403 :     }
1404 :     public function set playheadUpdateInterval(aTime:Number):Void {
1405 :     _updateTimeInterval = aTime;
1406 :     if (_updateTimeIntervalID > 0) {
1407 :     clearInterval(_updateTimeIntervalID);
1408 :     _updateTimeIntervalID = setInterval(this, "doUpdateTime", _updateTimeInterval);
1409 :     }
1410 :     }
1411 :    
1412 :     /**
1413 :     * <p>Property progressInterval, which is amount of time
1414 :     * in milliseconds between each "progress" event.</p>
1415 :     *
1416 :     * <p>If set when stream is playing, will restart interval.</p>
1417 :     */
1418 :     public function get progressInterval():Number {
1419 :     return _updateProgressInterval;
1420 :     }
1421 :     public function set progressInterval(aTime:Number):Void {
1422 :     _updateProgressInterval = aTime;
1423 :     if (_updateProgressIntervalID > 0) {
1424 :     clearInterval(_updateProgressIntervalID);
1425 :     _updateProgressIntervalID = setInterval(this, "doUpdateProgress", _updateProgressInterval);
1426 :     }
1427 :     }
1428 :    
1429 :     /**
1430 :     * <p>Access to instance of the class implementing
1431 :     * <code>INCManager</code>. Read only.</p>
1432 :     *
1433 :     * <p>One use case for this is that a custom
1434 :     * <code>INCManager</code> implementation may require custom
1435 :     * initialization.</p>
1436 :     */
1437 :     public function get ncMgr():INCManager {
1438 :     if (_ncMgr == null || _ncMgr == undefined) {
1439 :     createINCManager();
1440 :     }
1441 :     return _ncMgr;
1442 :     }
1443 :    
1444 :     /**
1445 :     * <p>Read only. Object received by call to onMetaData callback.
1446 :     * null if onMetaData callback has not been called since the last
1447 :     * load or play call. Always null with FLVs with no onMetaData
1448 :     * packet.</p>
1449 :     *
1450 :     * @see #load()
1451 :     * @see #play()
1452 :     */
1453 :     public function get metadata() { return _metadata; };
1454 :    
1455 :     //
1456 :     // public callbacks, not really APIs
1457 :     //
1458 :    
1459 :    
1460 :     /**
1461 :     * <p>Called on interval determined by
1462 :     * <code>playheadUpdateInterval</code> to send "playheadUpdate"
1463 :     * events. Events only sent when playhead is moving, sent every
1464 :     * .25 seconds by default.</p>
1465 :     *
1466 :     * @private
1467 :     */
1468 :     public function doUpdateTime():Void {
1469 :     //ifdef DEBUG
1470 :     ////debugTrace("doUpdateTime()");
1471 :     //endif
1472 :     var theTime:Number = playheadTime;
1473 :    
1474 :     // stop interval if we are stopped or paused
1475 :     switch (_state) {
1476 :     case STOPPED:
1477 :     case PAUSED:
1478 :     case DISCONNECTED:
1479 :     case CONNECTION_ERROR:
1480 :     clearInterval(_updateTimeIntervalID);
1481 :     _updateTimeIntervalID = 0;
1482 :     break;
1483 :     }
1484 :    
1485 :     if (_lastUpdateTime != theTime) {
1486 :     dispatchEvent({type:"playheadUpdate", state:_state, playheadTime:theTime});
1487 :     _lastUpdateTime = theTime;
1488 :     }
1489 :     }
1490 :    
1491 :     /**
1492 :     * <p>Called at interval determined by
1493 :     * <code>progressInterval</code> to send "progress" events.
1494 :     * Object dispatch starts when <code>_load</code> is called, ends
1495 :     * when all bytes downloaded or a network error of some kind
1496 :     * occurs, dispatched every .25 seconds by default.</p>
1497 :     *
1498 :     * @private
1499 :     */
1500 :     public function doUpdateProgress():Void {
1501 :     if (_ns == null || _ns == undefined) return;
1502 :     //ifdef DEBUG
1503 :     ////debugTrace("doUpdateProgress()");
1504 :     ////debugTrace("_ns.bytesLoaded = " + _ns.bytesLoaded);
1505 :     ////debugTrace("_ns.bytesTotal = " + _ns.bytesTotal);
1506 :     //endif
1507 :    
1508 :     if (_ns.bytesTotal >= 0 && _ns.bytesTotal >= 0) {
1509 :     dispatchEvent({type:"progress", bytesLoaded:_ns.bytesLoaded, bytesTotal:_ns.bytesTotal});
1510 :     }
1511 :     if ( _state == DISCONNECTED || _state == CONNECTION_ERROR ||
1512 :     _ns.bytesLoaded == _ns.bytesTotal ) {
1513 :     clearInterval(_updateProgressIntervalID);
1514 :     _updateProgressIntervalID = 0;
1515 :     }
1516 :     }
1517 :    
1518 :     /**
1519 :     * <p><code>NetStream.onStatus</code> callback for rtmp. Handles
1520 :     * automatic resizing, autorewind and buffering messaging.</p>
1521 :     *
1522 :     * @private
1523 :     */
1524 :     public function rtmpOnStatus(info:Object):Void
1525 :     {
1526 :     //ifdef DEBUG
1527 :     //debugTrace("rtmpOnStatus:"+info.code);
1528 :     //debugTrace("_state == " + _state);
1529 :     //debugTrace("_cachedState == " + _cachedState);
1530 :     //debugTrace("_bufferState == " + _bufferState);
1531 :     //debugTrace("_cachedPlayheadTime == " + _cachedPlayheadTime);
1532 :     //debugTrace("playheadTime == " + playheadTime);
1533 :     //endif
1534 :    
1535 :     if (_state == CONNECTION_ERROR) {
1536 :     // always do nothing
1537 :     return;
1538 :     }
1539 :    
1540 :     switch (info.code) {
1541 :     case "NetStream.Play.Stop":
1542 :     if (_startingPlay) return;
1543 :     switch (_state) {
1544 :     case RESIZING:
1545 :     if (_hiddenForResize) finishAutoResize();
1546 :     break;
1547 :     case LOADING:
1548 :     case STOPPED:
1549 :     case PAUSED:
1550 :     // yes we are stopped, we already know this
1551 :     break;
1552 :     default:
1553 :     if (_bufferState == BUFFER_EMPTY || _bufferTime <= 0.1) {
1554 :     // if we did a seek toward the end of the file so that
1555 :     // there is less file left to show than we have
1556 :     // buffer, than we will get a NetStream.Play.Stop when
1557 :     // the buffer loads rest of the file, but never get
1558 :     // a NetStream.Buffer.Full, since it won't fill, so
1559 :     // we check if we are done on a timer
1560 :     _cachedPlayheadTime = playheadTime;
1561 :     clearInterval(_rtmpDoStopAtEndIntervalID);
1562 :     _rtmpDoStopAtEndIntervalID = setInterval(this, "rtmpDoStopAtEnd", RTMP_DO_STOP_AT_END_INTERVAL);
1563 :     } else if (_bufferState == BUFFER_FULL) {
1564 :     _bufferState = BUFFER_FULL_SAW_PLAY_STOP;
1565 :     } else {
1566 :     //ifdef DEBUG
1567 :     //debugTrace("Unexpected buffer state with " + info.code + ": " + _bufferState);
1568 :     //endif
1569 :     }
1570 :     break;
1571 :     } // switch (_state)
1572 :     break;
1573 :     case "NetStream.Buffer.Empty":
1574 :     switch (_bufferState) {
1575 :     case BUFFER_FULL_SAW_PLAY_STOP:
1576 :     rtmpDoStopAtEnd(true);
1577 :     break;
1578 :     case BUFFER_FULL:
1579 :     if (_state == PLAYING) {
1580 :     setState(BUFFERING);
1581 :     }
1582 :     break;
1583 :     default:
1584 :     //ifdef DEBUG
1585 :     //debugTrace("Unexpected buffer state with " + info.code + ": " + _bufferState);
1586 :     //endif
1587 :     break;
1588 :     }
1589 :     _bufferState = BUFFER_EMPTY;
1590 :     break;
1591 :     case "NetStream.Buffer.Flush":
1592 :     case "NetStream.Buffer.Full":
1593 :     if (_sawSeekNotify && _state == SEEKING) {
1594 :     _bufferState = BUFFER_EMPTY;
1595 :     setStateFromCachedState();
1596 :     doUpdateTime();
1597 :     }
1598 :     switch (_bufferState) {
1599 :     case BUFFER_EMPTY:
1600 :     if ( !_hiddenForResize ) {
1601 :     if ((_state == LOADING && _cachedState == PLAYING) || _state == BUFFERING) {
1602 :     setState(PLAYING);
1603 :     } else if (_cachedState == BUFFERING) {
1604 :     _cachedState = PLAYING;
1605 :     }
1606 :     }
1607 :     _bufferState = BUFFER_FULL;
1608 :     break;
1609 :     default:
1610 :     //ifdef DEBUG
1611 :     //debugTrace("Unexpected buffer state with " + info.code + ": " + _bufferState);
1612 :     //endif
1613 :     break;
1614 :     } // switch (_bufferState)
1615 :     break;
1616 :     case "NetStream.Pause.Notify":
1617 :     if (_state == RESIZING && _hiddenForResize) {
1618 :     finishAutoResize();
1619 :     }
1620 :     break;
1621 :     case "NetStream.Play.Start":
1622 :     clearInterval(_rtmpDoStopAtEndIntervalID);
1623 :     _rtmpDoStopAtEndIntervalID = 0;
1624 :     _bufferState = BUFFER_EMPTY;
1625 :     if (_startingPlay) {
1626 :     _startingPlay = false;
1627 :     _cachedPlayheadTime = playheadTime;
1628 :     } else if (_state == PLAYING) {
1629 :     setState(BUFFERING);
1630 :     }
1631 :     break;
1632 :     case "NetStream.Play.Reset":
1633 :     clearInterval(_rtmpDoStopAtEndIntervalID);
1634 :     _rtmpDoStopAtEndIntervalID = 0;
1635 :     if (_state == REWINDING) {
1636 :     clearInterval(_rtmpDoSeekIntervalID);
1637 :     _rtmpDoSeekIntervalID = 0;
1638 :     if (playheadTime == 0 || playheadTime < _cachedPlayheadTime) {
1639 :     setStateFromCachedState();
1640 :     } else {
1641 :     _cachedPlayheadTime = playheadTime;
1642 :     _rtmpDoSeekIntervalID = setInterval(this, "rtmpDoSeek", RTMP_DO_SEEK_INTERVAL);
1643 :     }
1644 :     }
1645 :     break;
1646 :     case "NetStream.Seek.Notify":
1647 :     if (playheadTime != _cachedPlayheadTime) {
1648 :     setStateFromCachedState();
1649 :     doUpdateTime();
1650 :     } else {
1651 :     _sawSeekNotify = true;
1652 :     if (_rtmpDoSeekIntervalID == 0) {
1653 :     _rtmpDoSeekIntervalID = setInterval(this, "rtmpDoSeek", RTMP_DO_SEEK_INTERVAL);
1654 :     }
1655 :     }
1656 :     break;
1657 :     case "Netstream.Play.UnpublishNotify":
1658 :     break;
1659 :     case "Netstream.Play.PublishNotify":
1660 :     break;
1661 :     case "NetStream.Play.StreamNotFound":
1662 :     if (!_ncMgr.connectAgain()) {
1663 :     setState(CONNECTION_ERROR);
1664 :     }
1665 :     break;
1666 :     case "NetStream.Play.Failed":
1667 :     case "NetStream.Failed":
1668 :     setState(CONNECTION_ERROR);
1669 :     break;
1670 :     } // switch (info.code)
1671 :     }
1672 :    
1673 :     /**
1674 :     * <p><code>NetStream.onStatus</code> callback for http. Handles
1675 :     * autorewind.</p>
1676 :     *
1677 :     * @private
1678 :     */
1679 :     public function httpOnStatus(info:Object):Void
1680 :     {
1681 :     //ifdef DEBUG
1682 :     //debugTrace("httpOnStatus:"+info.code);
1683 :     //debugTrace("_state == " + _state);
1684 :     //debugTrace("playheadTime == " + playheadTime);
1685 :     //debugTrace("_bufferState = " + _bufferState);
1686 :     //endif
1687 :    
1688 :     switch (info.code) {
1689 :     case "NetStream.Play.Stop":
1690 :     clearInterval(_delayedBufferingIntervalID);
1691 :     _delayedBufferingIntervalID = 0;
1692 :     if (_invalidSeekTime) {
1693 :     _invalidSeekTime = false;
1694 :     _invalidSeekRecovery = true;
1695 :     setState(_cachedState);
1696 :     seek(playheadTime);
1697 :     } else {
1698 :     switch (_state) {
1699 :     case PLAYING:
1700 :     case BUFFERING:
1701 :     case SEEKING:
1702 :     httpDoStopAtEnd();
1703 :     break;
1704 :     }
1705 :     }
1706 :     break;
1707 :     case "NetStream.Seek.InvalidTime":
1708 :     if (_invalidSeekRecovery) {
1709 :     _invalidSeekTime = false;
1710 :     _invalidSeekRecovery = false;
1711 :     setState(_cachedState);
1712 :     seek(0);
1713 :     } else {
1714 :     _invalidSeekTime = true;
1715 :     }
1716 :     break;
1717 :     case "NetStream.Buffer.Empty":
1718 :     _bufferState = BUFFER_EMPTY;
1719 :     if (_state == PLAYING) {
1720 :     clearInterval(_delayedBufferingIntervalID);
1721 :     _delayedBufferingIntervalID = setInterval(this, "doDelayedBuffering", _delayedBufferingInterval);
1722 :     }
1723 :     break;
1724 :     case "NetStream.Buffer.Full":
1725 :     case "NetStream.Buffer.Flush":
1726 :     clearInterval(_delayedBufferingIntervalID);
1727 :     _delayedBufferingIntervalID = 0;
1728 :     _bufferState = BUFFER_FULL;
1729 :     if ( !_hiddenForResize ) {
1730 :     if ((_state == LOADING && _cachedState == PLAYING) || _state == BUFFERING) {
1731 :     setState(PLAYING);
1732 :     } else if (_cachedState == BUFFERING) {
1733 :     _cachedState = PLAYING;
1734 :     }
1735 :     }
1736 :     break;
1737 :     case "NetStream.Seek.Notify":
1738 :     _invalidSeekRecovery = false;
1739 :     switch (_state) {
1740 :     case SEEKING:
1741 :     case REWINDING:
1742 :     if (_httpDoSeekIntervalID == 0) {
1743 :     _httpDoSeekCount = 0;
1744 :     _httpDoSeekIntervalID = setInterval(this, "httpDoSeek", HTTP_DO_SEEK_INTERVAL);
1745 :     }
1746 :     break;
1747 :     } // switch (_state)
1748 :     break;
1749 :     case "NetStream.Play.StreamNotFound":
1750 :     setState(CONNECTION_ERROR);
1751 :     break;
1752 :     } // switch (info.code)
1753 :     }
1754 :    
1755 :     /**
1756 :     * <p>Called by INCManager after when connection complete or
1757 :     * failed after call to <code>INCManager.connectToURL</code>.
1758 :     * If connection failed, set <code>INCManager.nc = null</code>
1759 :     * before calling.</p>
1760 :     *
1761 :     * @see #ncReconnected()
1762 :     * @see INCManager#connectToURL
1763 :     * @see NCManager#connectToURL
1764 :     */
1765 :     public function ncConnected():Void {
1766 :     //ifdef DEBUG
1767 :     //debugTrace("ncConnected()");
1768 :     //endif
1769 :    
1770 :     if ( _ncMgr == null || _ncMgr == undefined ||
1771 :     _ncMgr.getNetConnection() == null ||
1772 :     _ncMgr.getNetConnection() == undefined ) {
1773 :     setState(CONNECTION_ERROR);
1774 :     } else {
1775 :     _createStream();
1776 :     _setUpStream();
1777 :     }
1778 :     }
1779 :    
1780 :     /**
1781 :     * <p>Called by INCManager after when reconnection complete or
1782 :     * failed after call to <code>INCManager.reconnect</code>. If
1783 :     * connection failed, set <code>INCManager.nc = null</code>
1784 :     * before calling.</p>
1785 :     *
1786 :     * @see #ncConnected()
1787 :     * @see INCManager#reconnect
1788 :     * @see NCManager#reconnect
1789 :     */
1790 :     public function ncReconnected():Void
1791 :     {
1792 :     //ifdef DEBUG
1793 :     //debugTrace("reconnected called!");
1794 :     //endif
1795 :     if ( _ncMgr == null || _ncMgr == undefined ||
1796 :     _ncMgr.getNetConnection() == null ||
1797 :     _ncMgr.getNetConnection() == undefined ) {
1798 :     setState(CONNECTION_ERROR);
1799 :     } else {
1800 :     _ns = null;
1801 :     _state = STOPPED;
1802 :     execQueuedCmds();
1803 :     }
1804 :     }
1805 :    
1806 :     /**
1807 :     * handles NetStream.onMetaData callback
1808 :     *
1809 :     * @private
1810 :     */
1811 :     public function onMetaData(info:Object):Void {
1812 :     if (_metadata != null) return;
1813 :     _metadata = info;
1814 :     if ( _streamLength == undefined ||
1815 :     _streamLength == null ||
1816 :     _streamLength <= 0 ) {
1817 :     _streamLength = info.duration;
1818 :     }
1819 :     if (isNaN(_videoWidth) || _videoWidth <= 0) _videoWidth = info.width;
1820 :     if (isNaN(_videoHeight) || _videoHeight <= 0) _videoHeight = info.height;
1821 :     dispatchEvent({type:"metadataReceived", info:info});
1822 :     }
1823 :    
1824 :     /**
1825 :     * handles NetStream.onCuePoint callback
1826 :     *
1827 :     * @private
1828 :     */
1829 :     public function onCuePoint(info:Object):Void {
1830 :     if (!_hiddenForResize || (!isNaN(_hiddenRewindPlayheadTime) && playheadTime < _hiddenRewindPlayheadTime)) {
1831 :     dispatchEvent({type:"cuePoint", info:info});
1832 :     }
1833 :     }
1834 :    
1835 :    
1836 :     //
1837 :     // private functions
1838 :     //
1839 :    
1840 :    
1841 :     /**
1842 :     * sets state, dispatches event, execs queued commands. Always try to call
1843 :     * this AFTER you do your work, because the state might change again after
1844 :     * you call this if you set it to a responsive state becasue of the call
1845 :     * to exec queued commands. If you set this to a responsive state and
1846 :     * then do more state based logic, check _state to make sure it did not
1847 :     * change out from under you.
1848 :     *
1849 :     * @private
1850 :     */
1851 :     private function setState(s:String):Void {
1852 :     if (s == _state) return;
1853 :     _hiddenRewindPlayheadTime = undefined;
1854 :     _cachedState = _state;
1855 :     _cachedPlayheadTime = playheadTime;
1856 :     _state = s;
1857 :     var newState:String = _state;
1858 :     //ifdef DEBUG
1859 :     //debugTrace("state = " + newState);
1860 :     //debugTrace("_cachedState == " + _cachedState);
1861 :     ////debugTrace("_cachedPlayheadTime == " + _cachedPlayheadTime);
1862 :     //endif
1863 :     dispatchEvent({type:"stateChange", state:newState, playheadTime:playheadTime});
1864 :     if (!_readyDispatched) {
1865 :     switch (newState) {
1866 :     case STOPPED:
1867 :     case PLAYING:
1868 :     case PAUSED:
1869 :     case BUFFERING:
1870 :     _readyDispatched = true;
1871 :     dispatchEvent({type:"ready", state:newState, playheadTime:playheadTime});
1872 :     break;
1873 :     } // switch
1874 :     }
1875 :     switch (_cachedState) {
1876 :     case REWINDING:
1877 :     dispatchEvent({type:"rewind", state:newState, playheadTime:playheadTime});
1878 :     if (_ncMgr.isRTMP() && newState == STOPPED) {
1879 :     closeNS();
1880 :     }
1881 :     break;
1882 :     } // switch
1883 :     switch (newState) {
1884 :     case STOPPED:
1885 :     case PAUSED:
1886 :     if (_ncMgr.isRTMP() && _idleTimeoutIntervalID == 0) {
1887 :     _idleTimeoutIntervalID = setInterval(this, "doIdleTimeout", _idleTimeoutInterval);
1888 :     }
1889 :     break;
1890 :     case SEEKING:
1891 :     case REWINDING:
1892 :     _bufferState = BUFFER_EMPTY;
1893 :     // no break
1894 :     case PLAYING:
1895 :     case BUFFERING:
1896 :     if (_updateTimeIntervalID == 0) {
1897 :     _updateTimeIntervalID = setInterval(this, "doUpdateTime", _updateTimeInterval);
1898 :     }
1899 :     // no break
1900 :     case LOADING:
1901 :     case RESIZING:
1902 :     clearInterval(_idleTimeoutIntervalID);
1903 :     _idleTimeoutIntervalID = 0;
1904 :     break;
1905 :     } // switch
1906 :     execQueuedCmds();
1907 :     }
1908 :    
1909 :     /**
1910 :     * Sets state to _cachedState if the _cachedState is PLAYING,
1911 :     * PAUSED or BUFFERING, otherwise sets state to STOPPED.
1912 :     *
1913 :     * @private
1914 :     */
1915 :     private function setStateFromCachedState():Void {
1916 :     switch (_cachedState) {
1917 :     case PLAYING:
1918 :     case PAUSED:
1919 :     setState(_cachedState);
1920 :     break;
1921 :     case BUFFERING:
1922 :     if (_bufferState == BUFFER_EMPTY) {
1923 :     setState(BUFFERING);
1924 :     } else {
1925 :     setState(_cachedState);
1926 :     }
1927 :     break;
1928 :     default:
1929 :     setState(STOPPED);
1930 :     break;
1931 :     }
1932 :     }
1933 :    
1934 :     /**
1935 :     * creates our implementatino of the <code>INCManager</code>.
1936 :     * We put this off until we need to do it to give time for the
1937 :     * user to customize the <code>DEFAULT_INCMANAGER</code>
1938 :     * static variable.
1939 :     *
1940 :     * @private
1941 :     */
1942 :     private function createINCManager():Void {
1943 :     if (ncMgrClassName == null || ncMgrClassName == undefined) {
1944 :     ncMgrClassName = DEFAULT_INCMANAGER;
1945 :     }
1946 :     var ncMgrConstructor:Function = eval( (ncMgrClassName) );
1947 :     _ncMgr = new ncMgrConstructor;
1948 :     _ncMgr.setVideoPlayer(this);
1949 :     }
1950 :    
1951 :     /**
1952 :     * <p>ONLY CALL THIS WITH RTMP STREAMING</p>
1953 :     *
1954 :     * <p>Has the logic for what to do when we decide we have come to
1955 :     * a stop by coming to the end of an rtmp stream. There are a few
1956 :     * different ways we decide this has happened, and we sometimes
1957 :     * even set an interval that calls this function repeatedly to
1958 :     * check if the time is still changing, which is why it has its
1959 :     * own special function.</p>
1960 :     *
1961 :     * @private
1962 :     */
1963 :     private function rtmpDoStopAtEnd(force:Boolean):Void {
1964 :     //ifdef DEBUG
1965 :     //debugTrace("rtmpDoStopAtEnd()");
1966 :     //endif
1967 :     // check if we really want to stop if this was triggered on an
1968 :     // interval. If we are running this on an interval (see
1969 :     // rtmpOnStatus) we do a stop when the playhead hasn't moved
1970 :     // since last time we checked, we check every .25 seconds.
1971 :     if (_rtmpDoStopAtEndIntervalID > 0) {
1972 :     switch (_state) {
1973 :     case DISCONNECTED:
1974 :     case CONNECTION_ERROR:
1975 :     clearInterval(_rtmpDoStopAtEndIntervalID);
1976 :     _rtmpDoStopAtEndIntervalID = 0;
1977 :     return;
1978 :     }
1979 :     if (force || _cachedPlayheadTime == playheadTime) {
1980 :     clearInterval(_rtmpDoStopAtEndIntervalID);
1981 :     _rtmpDoStopAtEndIntervalID = 0;
1982 :     } else {
1983 :     _cachedPlayheadTime = playheadTime;
1984 :     return;
1985 :     }
1986 :     }
1987 :     _bufferState = BUFFER_EMPTY;
1988 :     _atEnd = true;
1989 :     // all this triggers callbacks, so need to keep checking if
1990 :     // _state == STOPPED--if no longer, then we bail
1991 :     setState(STOPPED);
1992 :     if (_state != STOPPED) return;
1993 :     doUpdateTime();
1994 :     if (_state != STOPPED) return;
1995 :     dispatchEvent({type:"complete", state:_state, playheadTime:playheadTime});
1996 :     if (_state != STOPPED) return;
1997 :     if (_autoRewind && !_isLive && playheadTime != 0) {
1998 :     _atEnd = false;
1999 :     _currentPos = 0;
2000 :     _play(0, 0);
2001 :     setState(REWINDING);
2002 :     } else {
2003 :     closeNS();
2004 :     }
2005 :     }
2006 :    
2007 :     /**
2008 :     * <p>ONLY CALL THIS WITH RTMP STREAMING</p>
2009 :     *
2010 :     * <p>Wait until time goes back to zero to leave rewinding state.</p>
2011 :     *
2012 :     * @private
2013 :     */
2014 :     private function rtmpDoSeek():Void {
2015 :     //ifdef DEBUG
2016 :     //debugTrace("rtmpDoSeek()");
2017 :     //endif
2018 :     if (_state != REWINDING && _state != SEEKING) {
2019 :     clearInterval(_rtmpDoSeekIntervalID);
2020 :     _rtmpDoSeekIntervalID = 0;
2021 :     _sawSeekNotify = false;
2022 :     } else if (playheadTime != _cachedPlayheadTime) {
2023 :     clearInterval(_rtmpDoSeekIntervalID);
2024 :     _rtmpDoSeekIntervalID = 0;
2025 :     _sawSeekNotify = false;
2026 :     setStateFromCachedState();
2027 :     doUpdateTime();
2028 :     }
2029 :     }
2030 :    
2031 :     /**
2032 :     * <p>ONLY CALL THIS WITH HTTP PROGRESSIVE DOWNLOAD</p>
2033 :     *
2034 :     * <p>Call this when playing stops by hitting the end.</p>
2035 :     *
2036 :     * @private
2037 :     */
2038 :     private function httpDoStopAtEnd():Void {
2039 :     //ifdef DEBUG
2040 :     //debugTrace("httpDoStopAtEnd()");
2041 :     //endif
2042 :     _atEnd = true;
2043 :     if ( _streamLength == undefined ||
2044 :     _streamLength == null ||
2045 :     _streamLength <= 0 ) {
2046 :     _streamLength = _ns.time;
2047 :     }
2048 :     _pause(true);
2049 :     setState(STOPPED);
2050 :     if (_state != STOPPED) return;
2051 :     doUpdateTime();
2052 :     if (_state != STOPPED) return;
2053 :     dispatchEvent({type:"complete", state:_state, playheadTime:playheadTime});
2054 :     if (_state != STOPPED) return;
2055 :     if (_autoRewind) {
2056 :     _atEnd = false;
2057 :     _pause(true);
2058 :     _seek(0);
2059 :     setState(REWINDING);
2060 :     }
2061 :     }
2062 :    
2063 :     /**
2064 :     * <p>ONLY CALL THIS WITH HTTP PROGRESSIVE DOWNLOAD</p>
2065 :     *
2066 :     * <p>If we get an onStatus callback indicating a seek is over,
2067 :     * but the playheadTime has not updated yet, then we wait on a
2068 :     * timer before moving forward.</p>
2069 :     *
2070 :     * @private
2071 :     */
2072 :     private function httpDoSeek():Void {
2073 :     //ifdef DEBUG
2074 :     //debugTrace("httpDoSeek()");
2075 :     //debugTrace("playheadTime = " + playheadTime);
2076 :     //debugTrace("_cachedPlayheadTime = " + _cachedPlayheadTime);
2077 :     //endif
2078 :     var seekState:Boolean = (_state == REWINDING || _state == SEEKING);
2079 :     // if seeking or rewinding, then need to wait for playhead time to
2080 :     // change or for timeout
2081 :     if ( seekState && _httpDoSeekCount < HTTP_DO_SEEK_MAX_COUNT &&
2082 :     (_cachedPlayheadTime == playheadTime || _invalidSeekTime) ) {
2083 :     _httpDoSeekCount++;
2084 :     return;
2085 :     }
2086 :    
2087 :     // reset
2088 :     _httpDoSeekCount = 0;
2089 :     clearInterval(_httpDoSeekIntervalID);
2090 :     _httpDoSeekIntervalID = 0;
2091 :    
2092 :     // only do the rest if were seeking or rewinding to start with
2093 :     if (!seekState) return;
2094 :    
2095 :     setStateFromCachedState();
2096 :     if (_invalidSeekTime) {
2097 :     _invalidSeekTime = false;
2098 :     _invalidSeekRecovery = true;
2099 :     seek(playheadTime);
2100 :     } else {
2101 :     doUpdateTime();
2102 :     }
2103 :     }
2104 :    
2105 :     /**
2106 :     * <p>Wrapper for <code>NetStream.close()</code>. Never call
2107 :     * <code>NetStream.close()</code> directly, always call this
2108 :     * method because it does some other housekeeping.</p>
2109 :     *
2110 :     * @private
2111 :     */
2112 :     private function closeNS(updateCurrentPos:Boolean):Void {
2113 :     //ifdef DEBUG
2114 :     //debugTrace("closeNS()");
2115 :     //endif
2116 :     if (_ns != null && _ns != undefined) {
2117 :     if (updateCurrentPos) {
2118 :     clearInterval(_updateTimeIntervalID);
2119 :     _updateTimeIntervalID = 0;
2120 :     doUpdateTime();
2121 :     _currentPos = _ns.time;
2122 :     }
2123 :     delete _ns.onStatus;
2124 :     _ns.onStatus = null;
2125 :     _ns.close();
2126 :     _ns = null;
2127 :     }
2128 :     }
2129 :    
2130 :     /**
2131 :     * <p>We do a brief timer before entering BUFFERING state to avoid
2132 :     * quick switches from BUFFERING to PLAYING and back.</p>
2133 :     *
2134 :     * @private
2135 :     */
2136 :     private function doDelayedBuffering():Void {
2137 :     //ifdef DEBUG
2138 :     //debugTrace("doDelayedBuffering()");
2139 :     //endif
2140 :     switch (_state) {
2141 :     case LOADING:
2142 :     case RESIZING:
2143 :     // if loading or resizing, still at beginning so keep whirring, might go into buffering state
2144 :     break;
2145 :     case PLAYING:
2146 :     // still in that playing state, let's go to buffering
2147 :     clearInterval(_delayedBufferingIntervalID);
2148 :     _delayedBufferingIntervalID = 0;
2149 :     setState(BUFFERING);
2150 :     break;
2151 :     default:
2152 :     // any other state, bail and kill timer
2153 :     clearInterval(_delayedBufferingIntervalID);
2154 :     _delayedBufferingIntervalID = 0;
2155 :     break;
2156 :     }
2157 :     }
2158 :    
2159 :     /**
2160 :     * Wrapper for <code>NetStream.pause()</code>. Never call
2161 :     * <code>NetStream.pause()</code> directly, always call this
2162 :     * method because it does some other housekeeping.
2163 :     *
2164 :     * @private
2165 :     */
2166 :     private function _pause(doPause:Boolean):Void {
2167 :     //ifdef DEBUG
2168 :     //debugTrace("_pause(" + doPause + ")");
2169 :     //endif
2170 :     _ns.pause(doPause);
2171 :     }
2172 :    
2173 :     /**
2174 :     * Wrapper for <code>NetStream.play()</code>. Never call
2175 :     * <code>NetStream.play()</code> directly, always call this
2176 :     * method because it does some other housekeeping.
2177 :     *
2178 :     * @private
2179 :     */
2180 :     private function _play():Void {
2181 :     //ifdef DEBUG
2182 :     //var debugString:String = "_play("
2183 :     //if (arguments.length > 0) {
2184 :     // debugString += arguments[0];
2185 :     // if (arguments.length > 1) {
2186 :     // debugString += ", " + arguments[1];
2187 :     // }
2188 :     //}
2189 :     //debugString += ")";
2190 :     //debugTrace(debugString);
2191 :     //debugTrace("_ncMgr.getStreamName() = " + _ncMgr.getStreamName());
2192 :     //endif
2193 :     _startingPlay = true;
2194 :     switch (arguments.length) {
2195 :     case 0:
2196 :     _ns.play(_ncMgr.getStreamName(), (_isLive) ? -1 : 0, -1);
2197 :     break;
2198 :     case 1:
2199 :     _ns.play(_ncMgr.getStreamName(), (_isLive) ? -1 : arguments[0], -1);
2200 :     break;
2201 :     case 2:
2202 :     _ns.play(_ncMgr.getStreamName(), (_isLive) ? -1 : arguments[0], arguments[1]);
2203 :     break;
2204 :     default:
2205 :     throw new Error("bad args to _play");
2206 :     }
2207 :     }
2208 :    
2209 :     /**
2210 :     * Wrapper for <code>NetStream.seek()</code>. Never call
2211 :     * <code>NetStream.seek()</code> directly, always call
2212 :     * this method because it does some other housekeeping.
2213 :     *
2214 :     * @private
2215 :     */
2216 :     private function _seek(time:Number):Void {
2217 :     //ifdef DEBUG
2218 :     //debugTrace("_seek(" + time + ")");
2219 :     //endif
2220 :     if (_metadata.audiodelay != undefined && time + _metadata.audiodelay < _streamLength) {
2221 :     time += _metadata.audiodelay;
2222 :     }
2223 :     _ns.seek(time);
2224 :     _invalidSeekTime = false;
2225 :     _bufferState = BUFFER_EMPTY;
2226 :     _sawSeekNotify = false;
2227 :     }
2228 :    
2229 :     /**
2230 :     * Gets whether connected to a stream. If not, then calls to APIs
2231 :     * <code>play() with no args</code>, <code>stop()</code>,
2232 :     * <code>pause()</code> and <code>seek()</code> will throw
2233 :     * exceptions.
2234 :     *
2235 :     * @see #stateResponsive
2236 :     * @private
2237 :     */
2238 :     private function isXnOK():Boolean {
2239 :     if (_state == LOADING) return true;
2240 :     if (_state == CONNECTION_ERROR) return false;
2241 :     if (_state != DISCONNECTED) {
2242 :     if ( _ncMgr == null || _ncMgr == undefined ||
2243 :     _ncMgr.getNetConnection() == null ||
2244 :     _ncMgr.getNetConnection() == undefined ||
2245 :     !_ncMgr.getNetConnection().isConnected ) {
2246 :     setState(DISCONNECTED);
2247 :     return false;
2248 :     }
2249 :     return true;
2250 :     }
2251 :     return false;
2252 :     }
2253 :    
2254 :     /**
2255 :     * Kicks off autoresize process
2256 :     *
2257 :     * @private
2258 :     */
2259 :     private function startAutoResize() {
2260 :     switch (_state) {
2261 :     case DISCONNECTED:
2262 :     case CONNECTION_ERROR:
2263 :     // autoresize will happen later automatically
2264 :     return;
2265 :     default:
2266 :     _autoResizeDone = false;
2267 :     if (stateResponsive && _videoWidth != undefined && _videoHeight != undefined) {
2268 :     // do it now!
2269 :     doAutoResize();
2270 :     } else {
2271 :     // do it on an interval, it won't happen until we are
2272 :     // back in a responsive state
2273 :     clearInterval(_autoResizeIntervalID);
2274 :     _autoResizeIntervalID = setInterval(this, "doAutoResize", AUTO_RESIZE_INTERVAL);
2275 :     break;
2276 :     }
2277 :     }
2278 :     }
2279 :    
2280 :     /**
2281 :     * <p>Does the actual work of resetting the width and height.</p>
2282 :     *
2283 :     * <p>Called on an interval which is stopped when width and height
2284 :     * of the <code>Video</code> object are not zero. Finishing the
2285 :     * resize is done in another method which is either called on a
2286 :     * interval set up here for live streams or on a
2287 :     * NetStream.Play.Stop event in <code>rtmpOnStatus</code> after
2288 :     * stream is rewound if it is not a live stream. Still need to
2289 :     * get a http solution.</p>
2290 :     *
2291 :     * @private
2292 :     */
2293 :     private function doAutoResize():Void {
2294 :     //ifdef DEBUG
2295 :     //debugTrace("doAutoResize(), _video.width = " + _video.width + ", _video.height = " + _video.height);
2296 :     //endif
2297 :    
2298 :     if (_autoResizeIntervalID > 0) {
2299 :     switch (_state) {
2300 :     case RESIZING:
2301 :     case LOADING:
2302 :     break;
2303 :     case DISCONNECTED:
2304 :     case CONNECTION_ERROR:
2305 :     // autoresize will happen later automatically
2306 :     clearInterval(_autoResizeIntervalID);
2307 :     _autoResizeIntervalID = 0;
2308 :     return;
2309 :     default:
2310 :     if (!stateResponsive) {
2311 :     // keep trying until we get into a responsive state
2312 :     return;
2313 :     }
2314 :     }
2315 :     if ( _video.width != _prevVideoWidth || _video.height != _prevVideoHeight ||
2316 :     _bufferState >= BUFFER_FULL || _ns.time > AUTO_RESIZE_PLAYHEAD_TIMEOUT ) {
2317 :     // if have not received metadata yet, slight delay to avoid race condition in player
2318 :     // but there may not be any metadata, so cannot wait forever
2319 :     if (_hiddenForResize && _metadata == null && _hiddenForResizeMetadataDelay < AUTO_RESIZE_METADATA_DELAY_MAX) {
2320 :     //ifdef DEBUG
2321 :     //debugTrace("Delaying for metadata: " + _hiddenForResizeMetadataDelay);
2322 :     //endif
2323 :     _hiddenForResizeMetadataDelay++;
2324 :     return;
2325 :     }
2326 :     _videoWidth = _video.width;
2327 :     _videoHeight = _video.height;
2328 :     clearInterval(_autoResizeIntervalID);
2329 :     _autoResizeIntervalID = 0;
2330 :     } else {
2331 :     // keep trying until our size is set
2332 :     return;
2333 :     }
2334 :     }
2335 :     // do not need to do autoresize, but DO need to signal readyness
2336 :     if ((!_autoSize && !_aspectRatio) || _autoResizeDone) {
2337 :     setState(_cachedState);
2338 :     return;
2339 :     }
2340 :     //ifdef DEBUG
2341 :     //debugTrace("Actually doing autoResize, _videoWidth = " + _videoWidth + ", _videoHeight = " + _videoHeight);
2342 :     //endif
2343 :     _autoResizeDone = true;
2344 :     if (_autoSize) {
2345 :     _video._width = _videoWidth;
2346 :     _video._height = _videoHeight;
2347 :     } else if (_aspectRatio) {
2348 :     var newWidth:Number = (_videoWidth * height / _videoHeight);
2349 :     var newHeight:Number = (_videoHeight * width / _videoWidth);
2350 :     if (newHeight < height) {
2351 :     _video._height = newHeight;
2352 :     } else if (newWidth < width) {
2353 :     _video._width = newWidth;
2354 :     }
2355 :     }
2356 :     if (_hiddenForResize) {
2357 :     _hiddenRewindPlayheadTime = playheadTime;
2358 :     if (_state == LOADING) {
2359 :     _cachedState = PLAYING;
2360 :     }
2361 :     if (!_ncMgr.isRTMP()) {
2362 :     _pause(true);
2363 :     _seek(0);
2364 :     clearInterval(_finishAutoResizeIntervalID);
2365 :     _finishAutoResizeIntervalID = setInterval(this, "finishAutoResize", FINISH_AUTO_RESIZE_INTERVAL);
2366 :     } else if (!_isLive) {
2367 :     _currentPos = 0;
2368 :     _play(0, 0);
2369 :     setState(RESIZING)
2370 :     } else if (_autoPlay) {
2371 :     clearInterval(_finishAutoResizeIntervalID);
2372 :     _finishAutoResizeIntervalID = setInterval(this, "finishAutoResize", FINISH_AUTO_RESIZE_INTERVAL);
2373 :     } else {
2374 :     finishAutoResize();
2375 :     }
2376 :     } else {
2377 :     dispatchEvent({type:"resize", x:_x, y:_y, width:_width, height:_height});
2378 :     }
2379 :     }
2380 :    
2381 :     /**
2382 :     * <p>Makes video visible, turns on sound and starts
2383 :     * playing if live or autoplay.</p>
2384 :     */
2385 :     private function finishAutoResize():Void {
2386 :     //ifdef DEBUG
2387 :     //debugTrace("finishAutoResize()");
2388 :     //endif
2389 :     clearInterval(_finishAutoResizeIntervalID);
2390 :     _finishAutoResizeIntervalID = 0;
2391 :     if (stateResponsive) return;
2392 :     _visible = __visible;
2393 :     _sound.setVolume(_volume);
2394 :     _hiddenForResize = false;
2395 :     //ifdef DEBUG
2396 :     //debugTrace("_autoPlay = " + _autoPlay);
2397 :     //endif
2398 :     dispatchEvent({type:"resize", x:_x, y:_y, width:_width, height:_height});
2399 :     if (_autoPlay) {
2400 :     if (_ncMgr.isRTMP()) {
2401 :     if (!_isLive) {
2402 :     _currentPos = 0;
2403 :     _play(0);
2404 :     }
2405 :     if (_state == RESIZING) {
2406 :     setState(LOADING);
2407 :     _cachedState = PLAYING;
2408 :     }
2409 :     } else {
2410 :     _pause(false);
2411 :     _cachedState = PLAYING;
2412 :     }
2413 :     } else {
2414 :     setState(STOPPED);
2415 :     }
2416 :     }
2417 :    
2418 :     /**
2419 :     * <p>Creates <code>NetStream</code> and does some basic
2420 :     * initialization.</p>
2421 :     *
2422 :     * @private
2423 :     */
2424 :     private function _createStream():Void {
2425 :     //ifdef DEBUG
2426 :     //debugTrace("_createStream()");
2427 :     //endif
2428 :     _ns = new NetStream(_ncMgr.getNetConnection());
2429 :     _ns.mc = this;
2430 :     if (_ncMgr.isRTMP()) {
2431 :     _ns.onStatus = function(info:Object):Void { this.mc.rtmpOnStatus(info); };
2432 :     } else {
2433 :     _ns.onStatus = function(info:Object):Void { this.mc.httpOnStatus(info); };
2434 :     }
2435 :     _ns.onMetaData = function (info:Object) { this.mc.onMetaData(info); };
2436 :     _ns.onCuePoint = function (info:Object) { this.mc.onCuePoint(info); };
2437 :     _ns.setBufferTime(_bufferTime);
2438 :     }
2439 :    
2440 :     /**
2441 :     * <p>Does initialization after first connecting to the server
2442 :     * and creating the stream. Will get the stream duration from
2443 :     * the <code>INCManager</code> if it has it for us.</p>
2444 :     *
2445 :     * <p>Starts resize if necessary, otherwise starts playing if
2446 :     * necessary, otherwise loads first frame of video. In http case,
2447 :     * starts progressive download in any case.</p>
2448 :     *
2449 :     * @private
2450 :     */
2451 :     private function _setUpStream():Void {
2452 :     //ifdef DEBUG
2453 :     //debugTrace("_setUpStream()");
2454 :     //endif
2455 :    
2456 :     _video.attachVideo(_ns);
2457 :     this.attachAudio(_ns);
2458 :    
2459 :     // INCManager MIGHT have gotten the stream length, width and height for
2460 :     // us. If its length is null, undefined or < 0, then it did not.
2461 :     if ( !isNaN(_ncMgr.getStreamLength()) && _ncMgr.getStreamLength() >= 0 ) {
2462 :     _streamLength = _ncMgr.getStreamLength();
2463 :     }
2464 :     if ( !isNaN(_ncMgr.getStreamWidth()) && _ncMgr.getStreamWidth() >= 0 ) {
2465 :     _videoWidth = _ncMgr.getStreamWidth();
2466 :     } else {
2467 :     _videoWidth = undefined;
2468 :     }
2469 :     if ( !isNaN(_ncMgr.getStreamHeight()) && _ncMgr.getStreamHeight() >= 0 ) {
2470 :     _videoHeight = _ncMgr.getStreamHeight();
2471 :     } else {
2472 :     _videoHeight = undefined;
2473 :     }
2474 :    
2475 :     // resize immediately if height and width set above
2476 :     if ((_autoSize || _aspectRatio) && _videoWidth != undefined && _videoHeight != undefined) {
2477 :     _prevVideoWidth = undefined;
2478 :     _prevVideoHeight = undefined;
2479 :     doAutoResize();
2480 :     }
2481 :    
2482 :     // just start if static, start resize otherwise
2483 :     if ((!_autoSize && !_aspectRatio) || (_videoWidth != undefined && _videoHeight != undefined)) {
2484 :     if (_autoPlay) {
2485 :     if (!_ncMgr.isRTMP()) {
2486 :     _cachedState = BUFFERING;
2487 :     _play();
2488 :     } else if (_isLive) {
2489 :     _cachedState = BUFFERING;
2490 :     _play(-1);
2491 :     } else {
2492 :     _cachedState = BUFFERING;
2493 :     _play(0);
2494 :     }
2495 :     } else {
2496 :     _cachedState = STOPPED;
2497 :     if (_ncMgr.isRTMP()) {
2498 :     _play(0, 0);
2499 :     } else {
2500 :     _play();
2501 :     _pause(true);
2502 :     _seek(0);
2503 :     }
2504 :     }
2505 :     } else {
2506 :     _hiddenForResize = true;
2507 :     _hiddenForResizeMetadataDelay = 0;
2508 :     __visible = _visible;
2509 :     _visible = false;
2510 :     _volume = _sound.getVolume();
2511 :     _sound.setVolume(0);
2512 :     _play(0);
2513 :     if (_currentPos > 0) {
2514 :     _seek(_currentPos);
2515 :     _currentPos = 0;
2516 :     }
2517 :     }
2518 :     clearInterval(_autoResizeIntervalID);
2519 :     _autoResizeIntervalID = setInterval(this, "doAutoResize", AUTO_RESIZE_INTERVAL);
2520 :     }
2521 :    
2522 :     /**
2523 :     * <p>ONLY CALL THIS WITH RTMP STREAMING</p>
2524 :     *
2525 :     * <p>Only used for rtmp connections. When we pause or stop,
2526 :     * setup an interval to call this after a delay (see property
2527 :     * <code>idleTimeout</code>). We do this to spare the server from
2528 :     * having a bunch of extra xns hanging around, although this needs
2529 :     * to be balanced with the load that creating connections puts on
2530 :     * the server, and keep in mind that FCS can be configured to
2531 :     * terminate idle connections on its own, which is a better way to
2532 :     * manage the issue.</p>
2533 :     *
2534 :     * @private
2535 :     */
2536 :     private function doIdleTimeout():Void
2537 :     {
2538 :     //ifdef DEBUG
2539 :     //debugTrace("Closing NetConnection NOW");
2540 :     //endif
2541 :     clearInterval(_idleTimeoutIntervalID);
2542 :     _idleTimeoutIntervalID = 0;
2543 :     close();
2544 :     }
2545 :    
2546 :     /**
2547 :     * Dumps all queued commands without executing them
2548 :     *
2549 :     * @private
2550 :     */
2551 :     private function flushQueuedCmds():Void {
2552 :     //ifdef DEBUG
2553 :     //debugTrace("flushQueuedCmds()");
2554 :     //endif
2555 :     while (_cmdQueue.length > 0) _cmdQueue.pop();
2556 :     }
2557 :    
2558 :     /**
2559 :     * Executes as many queued commands as possible, obviously
2560 :     * stopping when state becomes unresponsive.
2561 :     *
2562 :     * @private
2563 :     */
2564 :     private function execQueuedCmds():Void {
2565 :     //ifdef DEBUG
2566 :     //debugTrace("execQueuedCmds()");
2567 :     //endif
2568 :     while ( _cmdQueue.length > 0 && (stateResponsive || _state == CONNECTION_ERROR) &&
2569 :     ( (_cmdQueue[0].url != null && _cmdQueue[0].url != undefined) ||
2570 :     (_state != DISCONNECTED && _state != CONNECTION_ERROR) ) ) {
2571 :     //ifdef DEBUG
2572 :     //debugTrace("Exec Queued Command!");
2573 :     //endif
2574 :     var nextCmd:Object = _cmdQueue.shift();
2575 :     _cachedState = _state;
2576 :     _state = EXEC_QUEUED_CMD;
2577 :     switch (nextCmd.type) {
2578 :     case PLAY:
2579 :     this.play(nextCmd.url, nextCmd.isLive, nextCmd.time);
2580 :     break;
2581 :     case LOAD:
2582 :     this.load(nextCmd.url, nextCmd.isLive, nextCmd.time);
2583 :     break;
2584 :     case PAUSE:
2585 :     this.pause();
2586 :     break;
2587 :     case STOP:
2588 :     this.stop();
2589 :     break;
2590 :     case SEEK:
2591 :     this.seek(nextCmd.time);
2592 :     break;
2593 :     } // switch
2594 :     }
2595 :     }
2596 :    
2597 :     private function queueCmd( type:Number, url:String, isLive:Boolean, time:Number):Void {
2598 :     //ifdef DEBUG
2599 :     //debugTrace("queueCmd(" + type + ", " + url + ", " + isLive + ", " + time + ")");
2600 :     //endif
2601 :     _cmdQueue.push( {type:type, url:url, isLive:false, time:time} );
2602 :     }
2603 :    
2604 :     //ifdef DEBUG
2605 :     //function debugTrace(s:String):Void {
2606 :     //if (_parent != null && _parent != undefined) {
2607 :     // _parent.debugTrace(s);
2608 :     //}
2609 :     //}
2610 :     //endif
2611 :    
2612 :     } // class mx.video.VideoPlayer

cvs-admin
ViewVC Help
Powered by ViewVC 1.0.0