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

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

Implemented fading for PNG controlbar
Disabled PNG volume slider when player is muted.

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