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

Revision 596, 14.8 KB checked in by pablo, 4 years ago (diff)

Removed view component to locking mechanism
V4 control bar locks user input to the sliders when the player is in the locked state

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.PlaylistEvent;
7        import com.longtailvideo.jwplayer.events.ViewEvent;
8        import com.longtailvideo.jwplayer.model.Model;
9        import com.longtailvideo.jwplayer.model.PlaylistItem;
10        import com.longtailvideo.jwplayer.parsers.JWParser;
11        import com.longtailvideo.jwplayer.player.IPlayer;
12        import com.longtailvideo.jwplayer.player.PlayerState;
13        import com.longtailvideo.jwplayer.plugins.IPlugin;
14        import com.longtailvideo.jwplayer.utils.Configger;
15        import com.longtailvideo.jwplayer.utils.Logger;
16        import com.longtailvideo.jwplayer.utils.RootReference;
17        import com.longtailvideo.jwplayer.utils.Strings;
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                private var _player:IPlayer;
48                private var _model:Model;
49                private var _view:View;
50
51                /** Setup completed **/
52                private var _setupComplete:Boolean;
53                /** Setup finalized **/
54                private var _setupFinalized:Boolean;
55                /** Current blocking Plugin **/
56                private var _blocking:Array = [];
57                /** Whether to resume on unblock **/
58                private var _blockingResume:Boolean;
59               
60                /** A list with legacy CDN classes that are now redirected to buit-in ones. **/
61                private var cdns:Object = {
62                                bitgravity:{'http.startparam':'starttime', provider:'http'},
63                                edgecast:{'http.startparam':'ec_seek', provider:'http'},
64                                flvseek:{'http.startparam':'fs', provider:'http'},
65                                highwinds:{'rtmp.loadbalance':true, provider:'rtmp'},
66                                lighttpd:{'http.startparam':'start', provider:'http'},
67                                vdox:{'rtmp.loadbalance':true, provider:'rtmp'}
68                };
69               
70                /** Reference to a PlaylistItem which has triggered an external MediaProvider load **/
71                private var _delayedItem:PlaylistItem;
72               
73                public function Controller(player:IPlayer, model:Model, view:View) {
74                        _player = player;
75                        _model = model;
76                        _view = view;
77                }
78
79                /**
80                 * Begin player setup
81                 * @param readyConfig If a PlayerConfig object is already available, use it to configure the player.
82                 * Otherwise, load the config from XML / flashvars.
83                 */
84                public function setupPlayer():void {
85                        var setup:PlayerSetup = new PlayerSetup(_player, _model, _view);
86
87                        setup.addEventListener(Event.COMPLETE, setupComplete);
88                        setup.addEventListener(ErrorEvent.ERROR, setupError);
89
90                        addViewListeners();
91
92                        setup.setupPlayer();
93                }
94
95                private function addViewListeners():void {
96                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_PLAY, playHandler);
97                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_PAUSE, pauseHandler);
98                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_STOP, stopHandler);
99                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_NEXT, nextHandler);
100                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_PREV, prevHandler);
101                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_SEEK, seekHandler);
102                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_MUTE, muteHandler);
103                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_VOLUME, volumeHandler);
104                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_FULLSCREEN, fullscreenHandler);
105                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_LOAD, loadHandler);
106                        _view.addEventListener(ViewEvent.JWPLAYER_VIEW_REDRAW, redrawHandler);
107                }
108
109                private function playHandler(evt:ViewEvent):void { play(); }
110                private function stopHandler(evt:ViewEvent):void { stop(); }
111                private function pauseHandler(evt:ViewEvent):void { pause(); }
112                private function nextHandler(evt:ViewEvent):void { next(); }
113                private function prevHandler(evt:ViewEvent):void { previous(); }
114                private function seekHandler(evt:ViewEvent):void { seek(evt.data); }
115                private function muteHandler(evt:ViewEvent):void { mute(evt.data); }
116                private function volumeHandler(evt:ViewEvent):void { setVolume(evt.data); }
117                private function fullscreenHandler(evt:ViewEvent):void { fullscreen(evt.data); }
118                private function loadHandler(evt:ViewEvent):void { load(evt.data); }
119                private function redrawHandler(evt:ViewEvent):void { redraw(); }
120
121                private function setupComplete(evt:Event):void {
122                        _setupComplete = true;
123                        _view.completeView();
124                        finalizeSetup();
125                }
126               
127                private function setupError(evt:ErrorEvent):void {
128                        Logger.log("STARTUP: Error occurred during player startup: " + evt.text);
129                        _view.completeView(true, evt.text);
130                }
131               
132                private function finalizeSetup():void {
133                        if (!blocking && _setupComplete && !_setupFinalized) {
134                                _setupFinalized = true;
135                               
136                                dispatchEvent(new PlayerEvent(PlayerEvent.JWPLAYER_READY));
137       
138                                _model.playlist.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_LOADED, playlistLoadHandler, false, 1000);
139                                _model.playlist.addEventListener(ErrorEvent.ERROR, errorHandler);
140                                _model.playlist.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_ITEM, playlistItemHandler, false, 1000);
141                               
142                                _model.addEventListener(MediaEvent.JWPLAYER_MEDIA_COMPLETE, completeHandler);
143                       
144                                // Broadcast playlist loaded (which was swallowed during player setup);
145                                if (_model.playlist.length > 0) {
146                                        _model.playlist.dispatchEvent(new PlaylistEvent(PlaylistEvent.JWPLAYER_PLAYLIST_LOADED, _model.playlist));
147                                }
148               
149                                RootReference.stage.dispatchEvent(new Event(Event.RESIZE));
150                        }
151                }
152               
153                private function playlistLoadHandler(evt:PlaylistEvent=null):void {
154                        if (_model.config.shuffle) {
155                                shuffleItem();
156                        } else {
157                                _model.playlist.currentIndex = _model.config.item;
158                        }
159                       
160                        if (_player.config.autostart) {
161                                load(_model.playlist.currentItem);
162                        }
163                }
164
165                private function shuffleItem():void {
166                        _model.playlist.currentIndex = Math.floor(Math.random() * _model.playlist.length);
167                }
168
169                private function playlistItemHandler(evt:PlaylistEvent):void {
170                        _model.config.item = _model.playlist.currentIndex;
171                }
172
173                private function errorHandler(evt:ErrorEvent):void {
174                        errorState(evt.text);
175                }
176
177                private function errorState(message:String=""):void {
178                        dispatchEvent(new PlayerEvent(PlayerEvent.JWPLAYER_ERROR, message));
179                }
180
181                private function completeHandler(evt:MediaEvent):void {
182                        switch (_model.config.repeat) {
183                                case RepeatOptions.SINGLE:
184                                        play();
185                                        break;
186                                case RepeatOptions.ALWAYS:
187                                        if (_model.playlist.currentIndex == _model.playlist.length-1 && !_model.config.shuffle) {
188                                                _model.playlist.currentIndex = 0;
189                                                play();
190                                        } else {
191                                                next();
192                                        }
193                                        break;
194                                case RepeatOptions.LIST:
195                                        if (_model.playlist.currentIndex == _model.playlist.length-1 && !_model.config.shuffle) {
196                                                _model.playlist.currentIndex = 0;
197                                        } else {
198                                                next();
199                                        }
200                                        break;
201                        }
202                }
203
204                ////////////////////
205                // Public methods //
206                ////////////////////
207
208                public function get blocking():Boolean {
209                        return (_blocking.length > 0);
210                }
211
212                /**
213                 * @private
214                 * @copy com.longtailvideo.jwplayer.player.Player#blockPlayback
215                 */
216                public function blockPlayback(plugin:IPlugin):Boolean {
217                        if (_blocking.indexOf(plugin) < 0) {
218                                _blocking.push(plugin);
219                                // If it was playing, pause playback and plan to resume when you're done
220                                if (_player.state == PlayerState.BUFFERING || _player.state == PlayerState.PLAYING) {
221                                        _model.media.pause();
222                                        _blockingResume = true;
223                                }
224                                // If it wasn't playing
225                                if (_player.config.autostart || _blockingResume) {
226                                        _blockingResume = true;
227                                }
228                                return true;
229                        }
230                        return false;
231                }
232
233                /**
234                 * @private
235                 * @copy com.longtailvideo.jwplayer.player.Player#unblockPlayback
236                 */
237                public function unblockPlayback(target:IPlugin):Boolean {
238                        var targetIndex:Number = _blocking.indexOf(target);
239                        if (targetIndex >= 0) {
240                                _blocking.splice(targetIndex, 1);
241                                if (!blocking && _blockingResume){
242                                        _blockingResume = false;
243                                        _model.media.play();
244                                }
245                                if (!_setupFinalized){
246                                        finalizeSetup();
247                                }
248                                return true;
249                        }
250                        return false;
251                }
252
253                public function setVolume(vol:Number):Boolean {
254                        if (blocking){ return false; }
255                        if (_model.media){
256                                _model.config.volume = vol;
257                                _model.media.setVolume(vol);
258                                setCookie('volume', vol);
259                                return true;
260                        }
261                        return false;
262                }
263               
264               
265                public function mute(muted:Boolean):Boolean {
266                        if (blocking) { return false; }
267                        if (muted && !_model.mute) {
268                                _model.mute = true;
269                                setCookie('mute', true);
270                                return true;
271                        } else if (!muted && _model.mute) {
272                                _model.mute = false;
273                                setCookie('mute', false);
274                                return true;
275                        }
276                        return false;
277                }
278
279                public function play():Boolean {
280                        if (blocking){ return false; }
281                        if (_model.playlist.currentItem) {
282                                switch (_player.state) {
283                                        case PlayerState.IDLE:
284                                                load(_model.playlist.currentItem);
285                                                break;
286                                        case PlayerState.BUFFERING:
287                                        case PlayerState.PLAYING:
288                                                _model.media.seek(_model.playlist.currentItem.start);
289                                        case PlayerState.PAUSED:
290                                                _model.media.play();
291                                                break;
292                                }
293                        }
294                        return true;
295                }
296
297                public function pause():Boolean {
298                        if (blocking){ return false; }
299                        if (!_model.media)
300                                return false;
301
302                        switch (_model.media.state) {
303                                case PlayerState.PLAYING:
304                                case PlayerState.BUFFERING:
305                                        _model.media.pause();
306                                        return true;
307                                        break;
308                        }
309
310                        return false;
311                }
312
313                public function stop():Boolean {
314                        if (blocking){ return false; }
315                        if (!_model.media)
316                                return false;
317
318                        switch (_model.media.state) {
319                                case PlayerState.PLAYING:
320                                case PlayerState.BUFFERING:
321                                case PlayerState.PAUSED:
322                                        _model.media.stop();
323                                        return true;
324                                        break;
325                        }
326
327                        return false;
328                }
329
330                public function next():Boolean {
331                        if (blocking){ return false; }
332                        if (_model.config.shuffle) {
333                                shuffleItem();                         
334                                play();
335                                return true;
336                        } else if (_model.playlist.currentIndex == _model.playlist.length-1) {
337                                return false;
338                        } else {
339                                _player.playlist.currentIndex = _player.playlist.currentIndex+1;
340                                play();
341                                return true;
342                        }
343                }
344               
345                public function previous():Boolean {
346                        if (blocking){ return false; }
347                        if (_model.playlist.currentIndex <= 0) {
348                                return false;
349                        } else {
350                                _player.playlist.currentIndex = _player.playlist.currentIndex-1;
351                                play();
352                                return true;
353                        }
354                }
355               
356                public function setPlaylistIndex(index:Number):Boolean {
357                        if (blocking){ return false; }
358                        if (0 <= index && index < _player.playlist.length) {
359                                _player.playlist.currentIndex = index;
360                                load(index);
361                                return true;
362                        }
363                        return false;
364                }
365
366                public function seek(pos:Number):Boolean {
367                        if (blocking){ return false; }
368                        if (!_model.media)
369                                return false;
370
371                        switch (_model.media.state) {
372                                case PlayerState.PLAYING:
373                                case PlayerState.BUFFERING:
374                                case PlayerState.PAUSED:
375                                        _model.media.seek(pos);
376                                        return true;
377                                        break;
378                        }
379
380                        return false;
381                }
382
383                public function load(item:*):Boolean {
384                        if (blocking){ return false; }
385
386                        if (_model.state != ModelStates.IDLE) {
387                                _model.media.stop();
388                        }
389                       
390                        if (item is PlaylistItem) {
391                                return loadPlaylistItem(item as PlaylistItem);
392                        } else if (item is String) {
393                                return loadString(item as String);
394                        } else if (item is Number) {
395                                return loadNumber(item as Number);
396                        } else if (item is Object) {
397                                return loadObject(item as Object);
398                        }
399                        return false;
400                }
401
402                private function loadPlaylistItem(item:PlaylistItem):Boolean {
403                        var result:Boolean = false;
404                        try {
405                                if (!item.provider) {
406                                        JWParser.updateProvider(item);
407                                }
408
409                                if (setProvider(item)) {
410                                        _model.media.addEventListener(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL, lockHandler);
411                                        _model.media.load(item);
412                                        result = true;
413                                } else if (item.file) {
414                                        _model.playlist.load(item.file)
415                                }
416                        } catch (err:Error) {
417                                result = false;
418                        }
419                        return result;
420                }
421
422                private function loadString(item:String):Boolean {
423                        if (Strings.extension(item) == "xml"){
424                                _model.playlist.load(item);
425                                return true;
426                        } else {
427                                return loadPlaylistItem(new PlaylistItem({file:item}));
428                        }
429                        return false;
430                }
431
432                private function loadNumber(item:Number):Boolean {
433                        if (item >= 0 && item < _model.playlist.length) {
434                                return loadPlaylistItem(_model.playlist.getItemAt(item));
435                        }
436                        return false;
437                }
438
439                private function loadObject(item:Object):Boolean {
440                        if ((item as Object).hasOwnProperty('file')) {
441                                return loadPlaylistItem(new PlaylistItem(item));
442                        }
443                        return false;
444                }
445
446                private function setProvider(item:PlaylistItem):Boolean {
447                        var provider:String = item.provider;
448                        if (provider) {
449                               
450                                // Backwards compatibility for CDNs in the 'type' flashvar.
451                                if (cdns.hasOwnProperty(provider)) {
452                                        _model.config.setConfig(cdns[provider]);
453                                        provider = cdns[provider]['provider'];
454                                }
455                               
456                                // If the model doesn't have an instance of the provider, load & instantiate it
457                                if (!_model.hasMediaProvider(provider)) {
458                                        _delayedItem = item;
459                                       
460                                        var mediaLoader:MediaProviderLoader = new MediaProviderLoader();
461                                        mediaLoader.addEventListener(Event.COMPLETE, mediaSourceLoaded);
462                                        mediaLoader.addEventListener(ErrorEvent.ERROR, errorHandler);
463                                        mediaLoader.loadSource(provider);
464                                        return false;
465                                }
466                               
467                                _model.setActiveMediaProvider(provider);
468                                return true;
469                        }
470                       
471                        return false;
472                }
473               
474                private function mediaSourceLoaded(evt:Event):void {
475                        var loader:MediaProviderLoader = evt.target as MediaProviderLoader;
476                        var item:PlaylistItem = _delayedItem;
477                        _delayedItem = null;
478                        _model.setMediaProvider(item.provider, loader.loadedSource);
479                        load(item);
480                }
481
482               
483                private function lockHandler(evt:MediaEvent):void {
484                        _model.media.play();
485                }
486
487                public function redraw():Boolean {
488                        if (blocking){ return false; }
489                        _view.redraw();
490                        return true;
491                }
492
493                public function fullscreen(mode:Boolean):Boolean {
494                        if (blocking){ return false; }
495                        _model.fullscreen = mode;
496                        _view.fullscreen(mode);
497                        return true;
498                }
499
500                public function link(playlistIndex:Number=NaN):Boolean {
501                        if (blocking){ return false; }
502                        if (isNaN(playlistIndex))
503                                playlistIndex = _model.playlist.currentIndex;
504
505                        if (playlistIndex >= 0 && playlistIndex < _model.playlist.length) {
506                                navigateToURL(new URLRequest(_model.playlist.getItemAt(playlistIndex).link), _model.config.linktarget);
507                                return true;
508                        }
509
510                        return false;
511                }
512               
513                private function setCookie(name:String, value:*):void {
514                        Configger.saveCookie(name, value);                     
515                }
516               
517        }
518}
Note: See TracBrowser for help on using the repository browser.