source: trunk/fl5/src/com/longtailvideo/jwplayer/controller/Controller.as @ 919

Revision 919, 16.9 KB checked in by pablo, 3 years ago (diff)
Line 
1package com.longtailvideo.jwplayer.controller {
2        import com.jeroenwijering.events.ModelStates;
3        import com.longtailvideo.jwplayer.events.GlobalEventDispatcher;
4        import com.longtailvideo.jwplayer.events.MediaEvent;
5        import com.longtailvideo.jwplayer.events.PlayerEvent;
6        import com.longtailvideo.jwplayer.events.PlayerStateEvent;
7        import com.longtailvideo.jwplayer.events.PlaylistEvent;
8        import com.longtailvideo.jwplayer.events.ViewEvent;
9        import com.longtailvideo.jwplayer.model.Model;
10        import com.longtailvideo.jwplayer.model.PlaylistItem;
11        import com.longtailvideo.jwplayer.parsers.JWParser;
12        import com.longtailvideo.jwplayer.player.IPlayer;
13        import com.longtailvideo.jwplayer.player.PlayerState;
14        import com.longtailvideo.jwplayer.plugins.IPlugin;
15        import com.longtailvideo.jwplayer.utils.Configger;
16        import com.longtailvideo.jwplayer.utils.Logger;
17        import com.longtailvideo.jwplayer.utils.RootReference;
18        import com.longtailvideo.jwplayer.view.View;
19       
20        import flash.events.ErrorEvent;
21        import flash.events.Event;
22        import flash.net.URLRequest;
23        import flash.net.navigateToURL;
24
25        /**
26         * Sent when the player has been initialized and skins and plugins have been successfully loaded.
27         *
28         * @eventType com.longtailvideo.jwplayer.events.PlayerEvent.JWPLAYER_READY
29         */
30        [Event(name="jwplayerReady", type = "com.longtailvideo.jwplayer.events.PlayerEvent")]
31
32        /**
33         * Sent when the player has entered the ERROR state
34         *
35         * @eventType com.longtailvideo.jwplayer.events.PlayerEvent.JWPLAYER_ERROR
36         */
37        [Event(name="jwplayerError", type = "com.longtailvideo.jwplayer.events.PlayerEvent")]
38
39        /**
40         * The Controller is responsible for handling Model / View events and calling the appropriate responders
41         *
42         * @author Pablo Schklowsky
43         */
44        public class Controller extends GlobalEventDispatcher {
45
46                /** MVC References **/
47                protected var _player:IPlayer;
48                protected var _model:Model;
49                protected var _view:View;
50
51                /** Setup completed **/
52                protected var _setupComplete:Boolean = false;
53                /** Setup finalized **/
54                protected var _setupFinalized:Boolean = false;
55                /** Whether to autostart on unlock **/
56                protected var _unlockAutostart:Boolean = false;
57                /** Whether to resume on unlock **/
58                protected var _lockingResume:Boolean = false;
59                /** Lock manager **/
60                protected var _lockManager:LockManager;
61                /** Load after unlock - My favorite variable ever **/
62                protected var _unlockAndLoad:Boolean;
63               
64               
65                /** A list with legacy CDN classes that are now redirected to buit-in ones. **/
66                protected var cdns:Object = {
67                                bitgravity:{'http.startparam':'starttime', provider:'http'},
68                                edgecast:{'http.startparam':'ec_seek', provider:'http'},
69                                flvseek:{'http.startparam':'fs', provider:'http'},
70                                highwinds:{'rtmp.loadbalance':true, provider:'rtmp'},
71                                lighttpd:{'http.startparam':'start', provider:'http'},
72                                vdox:{'rtmp.loadbalance':true, provider:'rtmp'}
73                };
74               
75                /** Reference to a PlaylistItem which has triggered an external MediaProvider load **/
76                protected var _delayedItem:PlaylistItem;
77                /** Loader for external MediaProviders **/
78                protected var _mediaLoader:MediaProviderLoader;
79               
80                public function Controller(player:IPlayer, model:Model, view:View) {
81                        _player = player;
82                        _model = model;
83                        _view = view;
84                        _lockManager = new LockManager();
85                }
86
87                /**
88                 * Begin player setup
89                 * @param readyConfig If a PlayerConfig object is already available, use it to configure the player.
90                 * Otherwise, load the config from XML / flashvars.
91                 */
92                public function setupPlayer():void {
93                        var setup:PlayerSetup = new PlayerSetup(_player, _model, _view);
94
95                        setup.addEventListener(Event.COMPLETE, setupComplete);
96                        setup.addEventListener(ErrorEvent.ERROR, setupError);
97
98                        addViewListeners();
99
100                        setup.setupPlayer();
101                }
102
103                protected function addViewListeners():void {
104                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_PLAY, playHandler);
105                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_PAUSE, pauseHandler);
106                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_STOP, stopHandler);
107                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_NEXT, nextHandler);
108                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_PREV, prevHandler);
109                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_SEEK, seekHandler);
110                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_MUTE, muteHandler);
111                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_VOLUME, volumeHandler);
112                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_FULLSCREEN, fullscreenHandler);
113                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_LOAD, loadHandler);
114                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_REDRAW, redrawHandler);
115                }
116
117                protected function playHandler(evt:ViewEvent):void { play(); }
118                protected function stopHandler(evt:ViewEvent):void { stop(); }
119                protected function pauseHandler(evt:ViewEvent):void { pause(); }
120                protected function nextHandler(evt:ViewEvent):void { next(); }
121                protected function prevHandler(evt:ViewEvent):void { previous(); }
122                protected function seekHandler(evt:ViewEvent):void { seek(evt.data); }
123                protected function muteHandler(evt:ViewEvent):void { mute(evt.data); }
124                protected function volumeHandler(evt:ViewEvent):void { mute(false); setVolume(evt.data); }
125                protected function fullscreenHandler(evt:ViewEvent):void { fullscreen(evt.data); }
126                protected function loadHandler(evt:ViewEvent):void { load(evt.data); }
127                protected function redrawHandler(evt:ViewEvent):void { redraw(); }
128
129
130                protected function setupComplete(evt:Event):void {
131                        _setupComplete = true;
132                        RootReference.stage.dispatchEvent(new Event(Event.RESIZE));
133                        _view.completeView();
134                        finalizeSetup();
135                }
136
137
138                protected function setupError(evt:ErrorEvent):void {
139                        Logger.log("STARTUP: Error occurred during player startup: " + evt.text);
140                        _view.completeView(true, evt.text);
141                        dispatchEvent(evt.clone());
142                }
143
144
145                protected function finalizeSetup():void {
146                        if (!locking && _setupComplete && !_setupFinalized) {
147                                _setupFinalized = true;
148
149                                dispatchEvent(new PlayerEvent(PlayerEvent.JWPLAYER_READY));
150
151                                _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_LOADED, playlistLoadHandler);
152                                _player.addEventListener(ErrorEvent.ERROR, errorHandler);
153                                _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_ITEM, playlistItemHandler);
154
155                                _model.addEventListener(MediaEvent.JWPLAYER_MEDIA_COMPLETE, completeHandler);
156
157                                // Broadcast playlist loaded (which was swallowed during player setup);
158                                if (_model.playlist.length > 0) {
159                                        dispatchEvent(new PlaylistEvent(PlaylistEvent.JWPLAYER_PLAYLIST_LOADED, _model.playlist));
160                                }
161
162                        }
163                }
164
165
166                protected function playlistLoadHandler(evt:PlaylistEvent=null):void {
167                        if (_model.config.shuffle) {
168                                shuffleItem();
169                        } else {
170                                if (_model.config.item >= _model.playlist.length) {
171                                        _model.config.item = _model.playlist.length - 1;
172                                }
173                                _model.playlist.currentIndex = _model.config.item;
174                        }
175
176                        if(_model.config.autostart) {
177                                if (locking) {
178                                        _unlockAutostart = true;
179                                } else {
180                                        play();
181                                }
182                        }
183                }
184
185
186                protected function shuffleItem():void {
187                        _model.playlist.currentIndex = Math.floor(Math.random() * _model.playlist.length);
188                }
189
190
191                protected function playlistItemHandler(evt:PlaylistEvent):void {
192                        _model.config.item = _model.playlist.currentIndex;
193                }
194
195
196                protected function errorHandler(evt:ErrorEvent):void {
197                        _delayedItem = null;
198                        _mediaLoader = null;
199                        errorState(evt.text);
200                }
201
202
203                protected function errorState(message:String=""):void {
204                        dispatchEvent(new PlayerEvent(PlayerEvent.JWPLAYER_ERROR, message));
205                }
206
207
208                protected function completeHandler(evt:MediaEvent):void {
209                        switch (_model.config.repeat) {
210                                case RepeatOptions.SINGLE:
211                                        play();
212                                        break;
213                                case RepeatOptions.ALWAYS:
214                                        if (_model.playlist.currentIndex == _model.playlist.length - 1 && !_model.config.shuffle) {
215                                                _model.playlist.currentIndex = 0;
216                                                play();
217                                        } else {
218                                                next();
219                                        }
220                                        break;
221                                case RepeatOptions.LIST:
222                                        if (_model.playlist.currentIndex == _model.playlist.length - 1 && !_model.config.shuffle) {
223                                                _lockingResume = false;
224                                                _model.playlist.currentIndex = 0;
225                                        } else {
226                                                next();
227                                        }
228                                        break;
229                        }
230                }
231
232
233                ////////////////////
234                // Public methods //
235                ////////////////////
236
237                public function get locking():Boolean {
238                        return _lockManager.locked();
239                }
240
241
242                /**
243                 * @private
244                 * @copy com.longtailvideo.jwplayer.player.Player#lockPlayback
245                 */
246                public function lockPlayback(plugin:IPlugin, callback:Function):void {
247                        var wasLocked:Boolean = locking;
248                        if (_lockManager.lock(plugin, callback)) {
249                                // If it was playing, pause playback and plan to resume when you're done
250                                if (_player.state == PlayerState.PLAYING || _player.state == PlayerState.BUFFERING) {
251                                        _model.media.pause();
252                                        _lockingResume = true;
253                                }
254                               
255                                // Tell everyone you're locked
256                                if (!wasLocked) {
257                                        Logger.log(plugin.id + " locking playback", "LOCK");
258                                        dispatchEvent(new PlayerEvent(PlayerEvent.JWPLAYER_LOCKED));
259                                        _lockManager.executeCallback();
260                                }
261                        }
262                }
263
264
265                /**
266                 * @private
267                 * @copy com.longtailvideo.jwplayer.player.Player#unlockPlayback
268                 */
269                public function unlockPlayback(target:IPlugin):Boolean {
270                        if (_lockManager.unlock(target)) {
271                                if (!locking) {
272                                        dispatchEvent(new PlayerEvent(PlayerEvent.JWPLAYER_UNLOCKED));
273                                }
274                                if (_setupComplete && !_setupFinalized) {
275                                        finalizeSetup();
276                                }
277                                if (!locking && (_lockingResume || _unlockAutostart)) {
278                                        _lockingResume = false;
279                                        play();
280                                        if (_unlockAutostart) {
281                                                _unlockAutostart = false;
282                                        } else if (_unlockAndLoad) {
283                                                _unlockAndLoad = false;
284                                        }
285                                }
286                                return true;
287                        }
288                        return false;
289                }
290
291
292                public function setVolume(vol:Number):Boolean {
293                        if (locking) {
294                                return false;
295                        }
296                        if (_model.media) {
297                                _model.config.volume = vol;
298                                _model.media.setVolume(vol);
299                                setCookie('volume', vol);
300                                return true;
301                        }
302                        return false;
303                }
304
305
306                public function mute(muted:Boolean):Boolean {
307                        if (locking) {
308                                return false;
309                        }
310                        if (muted && !_model.mute) {
311                                _model.mute = true;
312                                setCookie('mute', true);
313                                return true;
314                        } else if (!muted && _model.mute) {
315                                _model.mute = false;
316                                setCookie('mute', false);
317                                return true;
318                        }
319                        return false;
320                }
321
322
323                public function play():Boolean {
324                        if (_mediaLoader) {
325                                _delayedItem = _model.playlist.currentItem;
326                                return false;
327                        }
328
329                        if (locking) {
330                                return false;
331                        }
332
333                        if (_model.playlist.currentItem) {
334                                switch (_player.state) {
335                                        case PlayerState.IDLE:
336                                                load(_model.playlist.currentItem);
337                                                _model.media.addEventListener(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL, bufferFullHandler);
338                                                _model.media.load(_model.playlist.currentItem);
339                                                break;
340                                        case PlayerState.PAUSED:
341                                                _model.media.play();
342                                                break;
343                                }
344                        }
345                        return true;
346                }
347
348
349                public function pause():Boolean {
350                        if (locking) {
351                                return false;
352                        }
353                        if (!_model.media)
354                                return false;
355
356                        switch (_model.media.state) {
357                                case PlayerState.PLAYING:
358                                case PlayerState.BUFFERING:
359                                        _model.media.pause();
360                                        return true;
361                                        break;
362                        }
363
364                        return false;
365                }
366
367
368                public function stop():Boolean {
369                        if (locking) {
370                                return false;
371                        }
372                        if (!_model.media)
373                                return false;
374
375                        switch (_model.media.state) {
376                                case PlayerState.PLAYING:
377                                case PlayerState.BUFFERING:
378                                case PlayerState.PAUSED:
379                                        _model.media.stop();
380                                        return true;
381                                        break;
382                        }
383
384                        return false;
385                }
386
387
388                public function next():Boolean {
389                        if (locking) {
390                                _unlockAndLoad = true;
391                                return false;
392                        }
393
394                        _lockingResume = true;
395                        stop();
396                        if (_model.config.shuffle) {
397                                shuffleItem();
398                        } else if (_model.playlist.currentIndex == _model.playlist.length - 1) {
399                                _player.playlist.currentIndex = 0;
400                        } else {
401                                _player.playlist.currentIndex = _player.playlist.currentIndex + 1;
402                        }
403                        play();
404                       
405                        return true;
406                }
407
408
409                public function previous():Boolean {
410                        if (locking) {
411                                _unlockAndLoad = true;
412                                return false;
413                        }
414
415                        _lockingResume = true;
416                        stop();
417                        if (_model.config.shuffle) {
418                                shuffleItem();
419                        } else if (_model.playlist.currentIndex <= 0) {
420                                _model.playlist.currentIndex = _model.playlist.length - 1;
421                        } else {
422                                _player.playlist.currentIndex = _player.playlist.currentIndex - 1;
423                        }
424                        play();
425                       
426                        return true;
427                }
428
429
430                public function setPlaylistIndex(index:Number):Boolean {
431                        if (locking) {
432                                _unlockAndLoad = true;
433                                return false;
434                        }
435
436                        _lockingResume = true;
437                        if (0 <= index && index < _player.playlist.length) {
438                                stop();
439                                _player.playlist.currentIndex = index;
440                                play();
441                                return true;
442                        }
443                        return false;
444                }
445
446
447                public function seek(pos:Number):Boolean {
448                        if (locking) {
449                                return false;
450                        }
451                        if (!_model.media)
452                                return false;
453
454                        switch (_model.media.state) {
455                                case PlayerState.PLAYING:
456                                case PlayerState.BUFFERING:
457                                case PlayerState.PAUSED:
458                                        _model.media.seek(pos);
459                                        return true;
460                                        break;
461                        }
462
463                        return false;
464                }
465
466
467                public function load(item:*):Boolean {
468                        if (locking) {
469                                _unlockAndLoad = true;
470                                return false;
471                        }
472                       
473                        if (_model.state != ModelStates.IDLE) {
474                                _model.media.stop();
475                        }
476                        if (item is PlaylistItem) {
477                                return loadPlaylistItem(item as PlaylistItem);
478                        } else if (item is String) {
479                                return loadString(item as String);
480                        } else if (item is Number) {
481                                return loadNumber(item as Number);
482                        } else if (item is Array) {
483                                return loadArray(item as Array);
484                        } else if (item is Object) {
485                                return loadObject(item as Object);
486                        }
487                        return false;
488                }
489
490
491                protected function loadPlaylistItem(item:PlaylistItem):Boolean {
492                        if (locking) {
493                                _lockingResume = true;
494                                return false;
495                        }
496
497                        if (!_model.playlist.contains(item)) {
498                                _model.playlist.load(item);
499                                return false;
500                        }
501                       
502                        try {
503                                if (!item.streamer && _model.config.streamer) { item.streamer = _model.config.streamer; }
504                                if (!item.provider) { item.provider = JWParser.getProvider(item); }
505                               
506                                if (!setProvider(item) && item.file) {
507                                        _model.playlist.load(item.file);
508                                } else if(_mediaLoader) {
509                                        _delayedItem = item;
510                                        _model.setActiveMediaProvider('default');
511                                        dispatchEvent(new PlayerStateEvent(PlayerStateEvent.JWPLAYER_PLAYER_STATE, PlayerState.BUFFERING, PlayerState.IDLE));
512                                }
513                        } catch (err:Error) {
514                                Logger.log(err.message, "ERROR");
515                                return false;
516                        }
517                        Logger.log("Loading PlaylistItem: " + item.toString(), "LOAD");
518                        return true;
519                }
520
521
522                protected function loadString(item:String):Boolean {
523                        _model.playlist.load(new PlaylistItem({file: item}));
524                        return true;
525                }
526
527
528                protected function loadArray(item:Array):Boolean {
529                        if (item.length > 0) {
530                                _model.playlist.load(item);
531                                return true;
532                        }
533                        return false;
534                }
535
536                protected function loadNumber(item:Number):Boolean {
537                        if (item >= 0 && item < _model.playlist.length) {
538                                _model.playlist.currentIndex = item;
539                                return loadPlaylistItem(_model.playlist.currentItem);
540                        }
541                        return false;
542                }
543
544
545                protected function loadObject(item:Object):Boolean {
546                        if ((item as Object).hasOwnProperty('file')) {
547                                _model.playlist.load(new PlaylistItem(item));
548                                return true;
549                        }
550                        return false;
551                }
552
553
554                protected function setProvider(item:PlaylistItem):Boolean {
555                        var provider:String = item.provider;
556
557                        if (provider) {
558
559                                // Backwards compatibility for CDNs in the 'type' flashvar.
560                                if (cdns.hasOwnProperty(provider)) {
561                                        _model.config.setConfig(cdns[provider]);
562                                        provider = cdns[provider]['provider'];
563                                }
564
565                                // If the model doesn't have an instance of the provider, load & instantiate it
566                                if (!_model.hasMediaProvider(provider)) {
567                                        _mediaLoader = new MediaProviderLoader();
568                                        _mediaLoader.addEventListener(Event.COMPLETE, mediaSourceLoaded);
569                                        _mediaLoader.addEventListener(ErrorEvent.ERROR, errorHandler);
570                                        _mediaLoader.loadSource(provider);
571                                        return true;
572                                }
573
574                                _model.setActiveMediaProvider(provider);
575                                return true;
576                        }
577
578                        return false;
579                }
580
581
582                protected function mediaSourceLoaded(evt:Event):void {
583                        var loader:MediaProviderLoader = _mediaLoader;
584                        _mediaLoader = null;
585                        if (_delayedItem) {
586                                _model.setMediaProvider(_delayedItem.provider, loader.loadedSource);
587                                _delayedItem = null;
588                                play();
589                        } else {
590                                _delayedItem = null;
591                                _model.setMediaProvider(_model.playlist.currentItem.provider, loader.loadedSource);                             
592                        }
593                }
594
595
596                private function bufferFullHandler(evt:MediaEvent):void {
597                        if (!locking) {
598                                _model.media.play();
599                        } else {
600                                _lockingResume = true;
601                        }
602                }
603
604
605                public function redraw():Boolean {
606                        if (locking) {
607                                return false;
608                        }
609                        _view.redraw();
610                        return true;
611                }
612
613
614                public function fullscreen(mode:Boolean):Boolean {
615                        _model.fullscreen = mode;
616                        _view.fullscreen(mode);
617                        return true;
618                }
619
620
621                public function link(playlistIndex:Number=NaN):Boolean {
622                        if (locking) {
623                                return false;
624                        }
625                        if (isNaN(playlistIndex))
626                                playlistIndex = _model.playlist.currentIndex;
627
628                        if (playlistIndex >= 0 && playlistIndex < _model.playlist.length) {
629                                navigateToURL(new URLRequest(_model.playlist.getItemAt(playlistIndex).link), _model.config.linktarget);
630                                return true;
631                        }
632
633                        return false;
634                }
635
636
637                protected function setCookie(name:String, value:*):void {
638                        Configger.saveCookie(name, value);
639                }
640
641        }
642}
Note: See TracBrowser for help on using the repository browser.