source: trunk/fl5/src/com/longtailvideo/jwplayer/view/components/ControlbarComponentV4.as @ 528

Revision 528, 19.2 KB checked in by pablo, 4 years ago (diff)

V4 controlbar behavior fixes

Line 
1package com.longtailvideo.jwplayer.view.components {
2        import com.longtailvideo.jwplayer.events.MediaEvent;
3        import com.longtailvideo.jwplayer.events.PlayerEvent;
4        import com.longtailvideo.jwplayer.events.PlayerStateEvent;
5        import com.longtailvideo.jwplayer.events.PlaylistEvent;
6        import com.longtailvideo.jwplayer.events.ViewEvent;
7        import com.longtailvideo.jwplayer.player.Player;
8        import com.longtailvideo.jwplayer.player.PlayerState;
9        import com.longtailvideo.jwplayer.plugins.PluginConfig;
10        import com.longtailvideo.jwplayer.utils.Animations;
11        import com.longtailvideo.jwplayer.utils.Draw;
12        import com.longtailvideo.jwplayer.utils.Logger;
13        import com.longtailvideo.jwplayer.utils.Stacker;
14        import com.longtailvideo.jwplayer.utils.Strings;
15        import com.longtailvideo.jwplayer.view.interfaces.IControlbarComponent;
16       
17        import flash.accessibility.AccessibilityProperties;
18        import flash.display.DisplayObject;
19        import flash.display.MovieClip;
20        import flash.display.Sprite;
21        import flash.events.MouseEvent;
22        import flash.geom.ColorTransform;
23        import flash.geom.Rectangle;
24        import flash.text.TextField;
25        import flash.ui.Mouse;
26        import flash.utils.clearTimeout;
27        import flash.utils.setTimeout;
28       
29       
30        public class ControlbarComponentV4 extends CoreComponent implements IControlbarComponent {
31                /** Reference to the original skin **/
32                private var skin:Sprite;
33                /** A list with all controls. **/
34                private var stacker:Stacker;
35                /** Timeout for hiding the  **/
36                private var hiding:Number;
37                /** When scrubbing, icon shouldn't be set. **/
38                private var scrubber:MovieClip;
39                /** Color object for frontcolor. **/
40                private var front:ColorTransform;
41                /** Color object for lightcolor. **/
42                private var light:ColorTransform;
43                /** The actions for all controlbar buttons. **/
44                private var BUTTONS:Object;
45                /** The actions for all sliders **/
46                private var SLIDERS:Object = {timeSlider: ViewEvent.JWPLAYER_VIEW_SEEK, volumeSlider: ViewEvent.JWPLAYER_VIEW_VOLUME};
47                /** The button to clone for all custom buttons. **/
48                private var clonee:MovieClip;
49                /** Saving the block state of the controlbar. **/
50                private var blocking:Boolean;
51                /** Controlbar config **/
52                private var controlbarConfig:PluginConfig;
53                /** Animations handler **/
54                private var animations:Animations;
55               
56                public function ControlbarComponentV4(player:Player) {
57                        super(player);
58                        animations = new Animations(this);
59                        controlbarConfig = _player.config.pluginConfig("controlbar");
60                        controlbarConfig['margin'] = 20;
61                        // TODO: Remove Link button
62                        BUTTONS = {
63                                playButton: ViewEvent.JWPLAYER_VIEW_PLAY,
64                                pauseButton: ViewEvent.JWPLAYER_VIEW_PAUSE,
65                                stopButton: ViewEvent.JWPLAYER_VIEW_STOP,
66                                prevButton: ViewEvent.JWPLAYER_VIEW_PREV,
67                                nextButton: ViewEvent.JWPLAYER_VIEW_NEXT,
68                                fullscreenButton: ViewEvent.JWPLAYER_VIEW_FULLSCREEN,
69                                normalscreenButton: ViewEvent.JWPLAYER_VIEW_FULLSCREEN,
70                                muteButton: ViewEvent.JWPLAYER_VIEW_MUTE,
71                                unmuteButton: ViewEvent.JWPLAYER_VIEW_MUTE
72                        };
73                        skin = _player.skin.getSWFSkin().getChildByName('controlbar') as Sprite;
74                        skin.x = 0;
75                        skin.y = 0;
76                        addChild(skin);
77                        _player.addEventListener(PlayerStateEvent.JWPLAYER_PLAYER_STATE, stateHandler);
78                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_TIME, timeHandler);
79                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_MUTE, muteHandler);
80                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_VOLUME, volumeHandler);
81                        _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_BUFFER, bufferHandler);
82                        _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_LOADED, itemHandler);
83                        _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_UPDATED, itemHandler);
84                        _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_ITEM, itemHandler);
85                        stacker = new Stacker(skin as MovieClip);
86                        getSkinElement("linkButton").visible = false;
87                        setButtons();
88                        setColors();
89                        itemHandler();
90                        muteHandler();
91                        stateHandler();
92                        timeHandler();
93                        volumeHandler();
94                }
95               
96               
97                /**
98                 * Add a new button to the control
99                 *
100                 * @param icn   A graphic to show as icon
101                 * @param nam   Name of the button
102                   getSkinElement('* @param hdl The function to call when clicking the Button').
103                 **/
104                public function addButton(icon:DisplayObject, name:String, handler:Function = null):MovieClip {
105                        var btn:MovieClip;
106                        if (getSkinElement('linkButton') && getSkinElementChild('linkButton', 'back')) {
107                                btn = Draw.clone(getSkinElement('linkButton') as MovieClip) as MovieClip;
108                                btn.name = name + 'Button';
109                                btn.visible = true;
110                                btn.tabEnabled = true;
111                                btn.tabIndex = 6;
112                                var acs:AccessibilityProperties = new AccessibilityProperties();
113                                acs.name = name + 'Button';
114                                btn.accessibilityProperties = acs;
115                                addChild(btn);
116                                var off:Number = Math.round((btn.height - icon.height) / 2);
117                                Draw.clear(btn['icon']);
118                                btn['icon'].addChild(icon);
119                                icon.x = icon.y = 0;
120                                btn['icon'].x = btn['icon'].y = off;
121                                btn['back'].width = icon.width + 2 * off;
122                                btn.buttonMode = true;
123                                btn.mouseChildren = false;
124                                btn.addEventListener(MouseEvent.CLICK, handler);
125                                if (front) {
126                                        btn['icon'].transform.colorTransform = front;
127                                        btn.addEventListener(MouseEvent.MOUSE_OVER, overHandler);
128                                        btn.addEventListener(MouseEvent.MOUSE_OUT, outHandler);
129                                }
130                                stacker.insert(btn, getSkinElement('linkButton') as MovieClip);
131                        }
132                        return btn;
133                }
134               
135               
136                public function removeButton(name:String):void {
137                        skin.removeChild(getSkinElement(name));
138                }
139               
140               
141                public function resize(width:Number, height:Number):void {
142                        var wid:Number = width;
143                        if (controlbarConfig['position'] == 'over' || _player.fullscreen == true) {
144                                skin.x = controlbarConfig['margin'];
145                                skin.y = height - skin.height - controlbarConfig['margin'];
146                                wid = width - 2 * controlbarConfig['margin'];
147                        } else {
148                                skin.x = 0;
149                                skin.y = 0;
150                        }
151                        try {
152                                getSkinElement('fullscreenButton').visible = false;
153                                getSkinElement('normalscreenButton').visible = false;
154                                if (stage['displayState'] && _player.config.height > 40) {
155                                        if (_player.fullscreen) {
156                                                getSkinElement('fullscreenButton').visible = false;
157                                                getSkinElement('normalscreenButton').visible = true;
158                                        } else {
159                                                getSkinElement('fullscreenButton').visible = true;
160                                                getSkinElement('normalscreenButton').visible = false;
161                                        }
162                                }
163                        } catch (err:Error) {
164                        }
165                        stacker.rearrange(wid);
166                        stateHandler();
167                        fixTime();
168                        Mouse.show();
169                }
170               
171               
172                public function getButton(buttonName:String):DisplayObject {
173                        return null;
174                }
175               
176               
177                /** Hide the controlbar **/
178                public function block(stt:Boolean):void {
179                        blocking = stt;
180                        timeHandler();
181                }
182               
183               
184                /** Handle clicks from all buttons. **/
185                private function clickHandler(evt:MouseEvent):void {
186                        var act:String = BUTTONS[evt.target.name];
187                        var data:Object = null;
188                        if (blocking != true || act == ViewEvent.JWPLAYER_VIEW_FULLSCREEN || act == ViewEvent.JWPLAYER_VIEW_MUTE) {
189                                switch (act) {
190                                        case ViewEvent.JWPLAYER_VIEW_FULLSCREEN:
191                                                data = Boolean(!_player.fullscreen);
192                                                break;
193                                        case ViewEvent.JWPLAYER_VIEW_PAUSE:
194                                                data = Boolean(_player.state == PlayerState.IDLE || _player.state == PlayerState.PAUSED);
195                                                break;
196                                        case ViewEvent.JWPLAYER_VIEW_MUTE:
197                                                data = Boolean(!_player.mute);
198                                                break;
199                                }
200                                var event:ViewEvent = new ViewEvent(act, data);
201                                dispatchEvent(event);
202                        }
203                }
204               
205               
206                /** Handle mouse presses on sliders. **/
207                private function downHandler(evt:MouseEvent):void {
208                        scrubber = MovieClip(evt.target);
209                        if (blocking != true || scrubber.name == 'volumeSlider') {
210                                var rct:Rectangle = new Rectangle(scrubber.rail.x, scrubber.icon.y, scrubber.rail.width - scrubber.icon.width, 0);
211                                scrubber.icon.startDrag(true, rct);
212                                stage.addEventListener(MouseEvent.MOUSE_UP, upHandler);
213                        } else {
214                                scrubber = undefined;
215                        }
216                }
217               
218               
219                /** Handle a change in the current item **/
220                private function itemHandler(evt:PlaylistEvent = null):void {
221                        try {
222                                if (_player.playlist && _player.playlist.length > 1) {
223                                        getSkinElement('prevButton').visible = getSkinElement('nextButton').visible = true;
224                                } else {
225                                        getSkinElement('prevButton').visible = getSkinElement('nextButton').visible = false;
226                                }
227                        } catch (err:Error) {
228                        }
229                        timeHandler();
230                        stacker.rearrange();
231                        fixTime();
232                }
233               
234               
235                /** Show above controlbar on mousemove. **/
236                private function moveHandler(evt:MouseEvent = null):void {
237                        if (alpha == 0) {
238                                animations.fade(1);
239                        }
240                        clearTimeout(hiding);
241                        hiding = setTimeout(moveTimeout, 2000);
242                        Mouse.show();
243                }
244               
245               
246                /** Hide above controlbar again when move has timed out. **/
247                private function moveTimeout():void {
248                        animations.fade(0);
249                }
250               
251               
252                /** Show a mute icon if playing. **/
253                private function muteHandler(evt:MediaEvent = null):void {
254                        if (_player.mute == true) {
255                                try {
256                                        getSkinElement('muteButton').visible = false;
257                                        getSkinElement('unmuteButton').visible = true;
258                                } catch (err:Error) {
259                                }
260                                try {
261                                        getSkinElementChild('volumeSlider', 'mark').visible = false;
262                                        getSkinElementChild('volumeSlider', 'icon').x = getSkinElementChild('volumeSlider', 'rail').x;
263                                } catch (err:Error) {
264                                }
265                        } else {
266                                try {
267                                        getSkinElement('muteButton').visible = true;
268                                        getSkinElement('unmuteButton').visible = false;
269                                } catch (err:Error) {
270                                }
271                                try {
272                                        getSkinElementChild('volumeSlider', 'mark').visible = true;
273                                        volumeHandler();
274                                } catch (err:Error) {
275                                }
276                        }
277                }
278               
279               
280                /** Handle mouseouts from all buttons **/
281                private function outHandler(evt:MouseEvent):void {
282                        if (front && evt.target['icon']) {
283                                evt.target['icon'].transform.colorTransform = front;
284                        } else {
285                                evt.target.gotoAndPlay('out');
286                        }
287                }
288               
289               
290                /** Handle clicks from all buttons **/
291                private function overHandler(evt:MouseEvent):void {
292                        if (front && evt.target['icon']) {
293                                evt.target['icon'].transform.colorTransform = light;
294                        } else {
295                                evt.target.gotoAndPlay('over');
296                        }
297                }
298               
299               
300                /** Clickhandler for all buttons. **/
301                private function setButtons():void {
302                        for (var btn:String in BUTTONS) {
303                                if (getSkinElement(btn)) {
304                                        (getSkinElement(btn) as MovieClip).mouseChildren = false;
305                                        (getSkinElement(btn) as MovieClip).buttonMode = true;
306                                        getSkinElement(btn).addEventListener(MouseEvent.CLICK, clickHandler);
307                                        getSkinElement(btn).addEventListener(MouseEvent.MOUSE_OVER, overHandler);
308                                        getSkinElement(btn).addEventListener(MouseEvent.MOUSE_OUT, outHandler);
309                                }
310                        }
311                        for (var sld:String in SLIDERS) {
312                                if (getSkinElement(sld)) {
313                                        (getSkinElement(sld) as MovieClip).mouseChildren = false;
314                                        (getSkinElement(sld) as MovieClip).buttonMode = true;
315                                        getSkinElement(sld).addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
316                                        getSkinElement(sld).addEventListener(MouseEvent.MOUSE_OVER, overHandler);
317                                        getSkinElement(sld).addEventListener(MouseEvent.MOUSE_OUT, outHandler);
318                                }
319                        }
320                }
321               
322               
323                /** Init the colors. **/
324                private function setColors():void {
325                        if (_player.config.backcolor && getSkinElementChild('playButton', 'icon')) {
326                                var clr:ColorTransform = new ColorTransform();
327                                clr.color = _player.config.backcolor.color;
328                                getSkinElement('back').transform.colorTransform = clr;
329                        }
330                        if (_player.config.frontcolor) {
331                                try {
332                                        front = new ColorTransform();
333                                        front.color = _player.config.frontcolor.color;
334                                        for (var btn:String in BUTTONS) {
335                                                if (getSkinElement(btn)) {
336                                                        getSkinElementChild(btn, 'icon').transform.colorTransform = front;
337                                                }
338                                        }
339                                        for (var sld:String in SLIDERS) {
340                                                if (getSkinElement(sld)) {
341                                                        getSkinElementChild(sld, 'icon').transform.colorTransform = front;
342                                                        getSkinElementChild(sld, 'mark').transform.colorTransform = front;
343                                                        getSkinElementChild(sld, 'rail').transform.colorTransform = front;
344                                                }
345                                        }
346                                        (getSkinElement('elapsedText') as TextField).textColor = front.color;
347                                        (getSkinElement('totalText') as TextField).textColor = front.color;
348                                } catch (err:Error) {
349                                }
350                        }
351                        if (_player.config.lightcolor) {
352                                light = new ColorTransform();
353                                light.color = _player.config.lightcolor.color;
354                        } else {
355                                light = front;
356                        }
357                        if (light) {
358                                try {
359                                        getSkinElementChild('timeSlider', 'done').transform.colorTransform = light;
360                                        getSkinElementChild('volumeSlider', 'mark').transform.colorTransform = light;
361                                } catch (err:Error) {
362                                }
363                        }
364                }
365               
366               
367                /** Process state changes **/
368                private function stateHandler(evt:PlayerEvent = undefined):void {
369                        clearTimeout(hiding);
370                        _player.skin.removeEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
371                        try {
372                                var dps:String = stage['displayState'];
373
374                                switch (_player.state) {
375                                        case PlayerState.PLAYING:
376                                                if (controlbarConfig['position'] == 'over' || dps == 'fullScreen') {
377                                                        Mouse.show();
378                                                        animations.fade(1);
379                                                }
380                                                break;
381                                        case PlayerState.PAUSED:
382                                                getSkinElement('playButton').visible = true;
383                                                getSkinElement('pauseButton').visible = false;
384                                               
385                                                if (controlbarConfig['position'] == 'over' || dps == 'fullScreen') {
386                                                        Mouse.show();
387                                                        animations.fade(1);
388                                                }
389                                                break;
390                                        case PlayerState.BUFFERING:
391                                                getSkinElement('playButton').visible = false;
392                                                getSkinElement('pauseButton').visible = true;
393                                               
394                                                if (controlbarConfig['position'] == 'over' || (dps == 'fullScreen' && controlbarConfig['position'] != 'none')) {
395                                                        hiding = setTimeout(moveTimeout, 2000);
396                                                        _player.skin.addEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
397                                                } else {
398                                                        animations.fade(1);
399                                                }
400                                                break;
401                                        case PlayerState.IDLE:
402                                                getSkinElement('playButton').visible = true;
403                                                getSkinElement('pauseButton').visible = false;
404                                                timeHandler();
405                                               
406                                                if (controlbarConfig['position'] == 'over' || dps == 'fullScreen') {
407                                                        Mouse.show();
408                                                        animations.fade(1);
409                                                }
410                                                break;
411                                }
412                        } catch (e:Error) {}
413                }
414               
415                /** Process time updates given by the model. **/
416                private function timeHandler(evt:MediaEvent = null):void {
417                        var dur:Number = 0;
418                        var pos:Number = 0;
419                        if (evt) {
420                                if (evt.duration >= 0) {
421                                        dur = evt.duration;
422                                }
423                                if (evt.position >= 0) {
424                                        pos = evt.position;
425                                }
426                        } else if (_player.playlist.length > 0 && _player.playlist.currentItem) {
427                                if (_player.playlist.currentItem.duration >= 0) {
428                                        dur = _player.playlist.currentItem.duration;
429                                }
430                        }
431                        var pct:Number = pos / dur;
432                        if (isNaN(pct)) {
433                                pct = 1;
434                        }
435                        try {
436                                (getSkinElement('elapsedText') as TextField).text = Strings.digits(pos);
437                                (getSkinElement('totalText') as TextField).text = Strings.digits(dur);
438                        } catch (err:Error) {
439                                Logger.log(err);
440                        }
441                        try {
442                                var xps:Number = Math.round(pct * (getSkinElementChild('timeSlider', 'rail').width - getSkinElementChild('timeSlider', 'icon').width));
443                                if (dur > 0) {
444                                        getSkinElementChild('timeSlider', 'icon').visible = _player.state != PlayerState.IDLE;
445                                        getSkinElementChild('timeSlider', 'mark').visible = _player.state != PlayerState.IDLE;
446                                        if (!scrubber) {
447                                                getSkinElementChild('timeSlider', 'icon').x = xps;
448                                                getSkinElementChild('timeSlider', 'done').width = xps;
449                                        }
450                                        bufferHandler(evt);
451                                        getSkinElementChild('timeSlider', 'done').visible = _player.state != PlayerState.IDLE;
452                                } else {
453                                        if (_player.state != PlayerState.PLAYING) {
454                                                getSkinElementChild('timeSlider', 'icon').visible = false;
455                                                getSkinElementChild('timeSlider', 'mark').visible = false;
456                                                getSkinElementChild('timeSlider', 'done').visible = false;
457                                        }
458                                }
459                        } catch (err:Error) {
460                        }
461                }
462               
463               
464                private function bufferHandler(evt:MediaEvent):void {
465                        if (evt.bufferPercent < 0)
466                                return;
467                       
468                        var mark:DisplayObject = getSkinElementChild('timeSlider', 'mark');
469                        var railWidth:Number = getSkinElementChild('timeSlider', 'rail').width;
470                        var markWidth:Number = _player.state == PlayerState.IDLE ? 0 : Math.round((evt.bufferPercent / 100) * railWidth);
471                       
472                        try {
473                                mark.x = 0;
474                                mark.width = markWidth;
475                                mark.visible = _player.state != PlayerState.IDLE;
476                        } catch (e:Error) {}
477                       
478/*                     
479                        if (evt.bufferPercent >= 0 || evt.type == MediaEvent.JWPLAYER_MEDIA_BUFFER) {
480                                try {
481                                        var xps:Number;
482                                        if (!scrubber) {
483                                                xps = getSkinElementChild('timeSlider', 'icon').x;
484                                        } else {
485                                                xps = getSkinElementChild('timeSlider', 'done').width;
486                                        }
487                                        var mark:DisplayObject = getSkinElementChild('timeSlider', 'mark');
488                                        var markWidth:Number = _player.state == PlayerState.IDLE ? 0 : Math.round(evt.bufferPercent / 100 * (getSkinElementChild('timeSlider', 'rail').width - xps));
489                                        mark.x = xps;
490                                        mark.width = markWidth;
491                                        mark.visible = _player.state != PlayerState.IDLE;
492                        } catch (err:Error) {
493                                }
494                        }
495*/                     
496                }
497               
498               
499                /** Fix the timeline display. **/
500                private function fixTime():void {
501                        try {
502                                var scp:Number = getSkinElement('timeSlider').scaleX;
503                                getSkinElement('timeSlider').scaleX = 1;
504                                getSkinElementChild('timeSlider', 'icon').x = scp * getSkinElementChild('timeSlider', 'icon').x;
505                                getSkinElementChild('timeSlider', 'mark').x = scp * getSkinElementChild('timeSlider', 'mark').x;
506                                getSkinElementChild('timeSlider', 'mark').width = scp * getSkinElementChild('timeSlider', 'mark').width;
507                                getSkinElementChild('timeSlider', 'rail').width = scp * getSkinElementChild('timeSlider', 'rail').width;
508                                getSkinElementChild('timeSlider', 'done').x = scp * getSkinElementChild('timeSlider', 'done').x;
509                                getSkinElementChild('timeSlider', 'done').width = scp * getSkinElementChild('timeSlider', 'done').width;
510                        } catch (err:Error) {
511                        }
512                }
513               
514               
515                /** Handle mouse releases on sliders. **/
516                private function upHandler(evt:MouseEvent):void {
517                        var mpl:Number = 0;
518                        stage.removeEventListener(MouseEvent.MOUSE_UP, upHandler);
519                        scrubber.icon.stopDrag();
520                        if (scrubber.name == 'timeSlider' && _player.playlist) {
521                                mpl = _player.playlist.currentItem.duration;
522                        } else if (scrubber.name == 'volumeSlider') {
523                                if (_player.mute) return;
524                                else mpl = 100;
525                        }
526                        var pct:Number = (scrubber.icon.x - scrubber.rail.x) / (scrubber.rail.width - scrubber.icon.width) * mpl;
527                        dispatchEvent(new ViewEvent(SLIDERS[scrubber.name], Math.round(pct)));
528                        scrubber = undefined;
529                }
530               
531               
532                /** Reflect the new volume in the controlbar **/
533                private function volumeHandler(evt:MediaEvent = null):void {
534                        try {
535                                var vsl:MovieClip = getSkinElement('volumeSlider') as MovieClip;
536                                vsl.mark.width = _player.config.volume * (vsl.rail.width - vsl.icon.width / 2) / 100;
537                                vsl.icon.x = vsl.mark.x + _player.config.volume * (vsl.rail.width - vsl.icon.width) / 100;
538                        } catch (err:Error) {
539                        }
540                }
541               
542               
543                private function getSkinElement(element:String):DisplayObject {
544                        return skin.getChildByName(element) as DisplayObject;
545                }
546               
547               
548                private function getSkinElementChild(element:String, child:String):DisplayObject {
549                        return (skin.getChildByName(element) as MovieClip).getChildByName(child);
550                }
551        }
552}
Note: See TracBrowser for help on using the repository browser.