source: trunk/fl5/src/com/longtailvideo/jwplayer/media/SoundMediaProvider.as @ 1995

Revision 1995, 6.7 KB checked in by pablo, 21 months ago (diff)
  • Fixes issue with sound buffer underrun on initial play (1468)
  • Fixes an issue introduced in [1994] where a return from fullscreen in IE9 / HTML5 would result in the play button's icon disappearing from the display.
Line 
1/**
2 * Wrapper for playback of mp3 sounds.
3 **/
4package com.longtailvideo.jwplayer.media {
5        import com.jeroenwijering.events.*;
6        import com.longtailvideo.jwplayer.events.MediaEvent;
7        import com.longtailvideo.jwplayer.model.PlayerConfig;
8        import com.longtailvideo.jwplayer.model.PlaylistItem;
9        import com.longtailvideo.jwplayer.player.PlayerState;
10        import com.longtailvideo.jwplayer.utils.Logger;
11       
12        import flash.events.*;
13        import flash.media.*;
14        import flash.net.URLRequest;
15        import flash.utils.*;
16
17
18        public class SoundMediaProvider extends MediaProvider {
19                /** _sound object to be instantiated. **/
20                private var _sound:Sound;
21                /** Sound control object. **/
22                private var _transformer:SoundTransform;
23                /** Sound _channel object. **/
24                private var _channel:SoundChannel;
25                /** Sound _context object. **/
26                private var _context:SoundLoaderContext;
27                /** ID for the position interval. **/
28                protected var _positionInterval:Number;
29                /** Whether the buffer has filled **/
30                private var _bufferFull:Boolean;
31                /** Whether the enitre sound file has been buffered **/
32                private var _bufferingComplete:Boolean;
33                /** User-defined item duration **/
34                private var _userDuration:Number = -1;
35               
36                /** Constructor; sets up the connection and display. **/
37                public function SoundMediaProvider() {
38                        super('_sound');
39
40                }
41
42
43                public override function initializeMediaProvider(cfg:PlayerConfig):void {
44                        super.initializeMediaProvider(cfg);
45                        _transformer = new SoundTransform();
46                        _context = new SoundLoaderContext(0, true);
47                }
48
49
50                /** Sound completed; send event. **/
51                private function completeHandler(evt:Event):void {
52                        complete();
53                }
54
55
56                /** Catch errors. **/
57                private function errorHandler(evt:ErrorEvent):void {
58                        stop();
59                        error(evt.text);
60                }
61
62
63                /** Forward ID3 data from the _sound. **/
64                private function id3Handler(evt:Event):void {
65                        try {
66                                var id3:ID3Info = _sound.id3;
67                                var obj:Object = {type: 'id3', album: id3.album,
68                                                artist: id3.artist, comment: id3.comment,
69                                                genre: id3.genre, name: id3.songName, track: id3.track,
70                                                year: id3.year}
71                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata:obj});
72                        } catch (err:Error) {
73                        }
74                }
75
76
77                /** Load the _sound. **/
78                override public function load(itm:PlaylistItem):void {
79                        _position = 0;
80                        _bufferFull = false;
81                        _userDuration = itm.duration;
82                        if (!_item || _item.file != itm.file || !_bufferingComplete) {
83                                _bufferingComplete = false;
84                                _sound = new Sound();
85                                _sound.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
86                                _sound.addEventListener(Event.ID3, id3Handler);
87                                _sound.addEventListener(ProgressEvent.PROGRESS, positionHandler);
88                                _sound.load(new URLRequest(itm.file), _context);
89                        }
90                        _item = itm;
91                        if (!_positionInterval) {
92                                _positionInterval = setInterval(positionHandler, 100);
93                        }
94
95                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED);
96                        setState(PlayerState.BUFFERING);
97                        sendBufferEvent(0);
98                        streamVolume(config.mute ? 0 : config.volume);
99                }
100
101
102                /** Pause the _sound. **/
103                override public function pause():void {
104                        if (_positionInterval){
105                                clearInterval(_positionInterval);
106                                _positionInterval = undefined;
107                        }
108                       
109                        if (_channel) {
110                                _channel.stop();
111                        }
112                        super.pause();
113                }
114
115
116                /** Play the _sound. **/
117                override public function play():void {
118                        if (position == 0 && _item.start > 0) {
119                                seek(item.start);
120                                return;
121                        }
122                        if (!_positionInterval) {
123                                _positionInterval = setInterval(positionHandler, 100);
124                        }
125                        if (_channel){
126                                _channel.stop();
127                                _channel = null;
128                        }
129                        _channel = _sound.play(_position * 1000, 0, _transformer);
130                        _channel.addEventListener(Event.SOUND_COMPLETE, completeHandler);
131                        super.play();
132                }
133
134
135                /** Interval for the _position progress **/
136                protected function positionHandler(progressEvent:ProgressEvent=null):void {
137                        var bufferPercent:Number = 0;
138                        var bufferTime:Number = 0;
139                        var bufferLength:Number = config.bufferlength;
140                       
141                        if (_userDuration < 0) {
142                                if (_sound.bytesTotal > 0 && _sound.bytesLoaded / _sound.bytesTotal > 0.1) {
143                                        _item.duration = _sound.length / 1000 / _sound.bytesLoaded * _sound.bytesTotal;
144                                } else if (_sound.length > 0) {
145                                        _item.duration = Math.floor(_sound.length / 100) / 10;
146                                }
147                        }
148                       
149                        if (_channel) {
150                                _position = Math.floor(_channel.position / 100) / 10;
151                        }
152                        if (_item.duration != 0 || _userDuration == 0) {
153                                if (_sound.bytesTotal > 0) {
154                                        bufferPercent = Math.floor(_sound.bytesLoaded / _sound.bytesTotal * 100);
155                                        bufferTime = Math.max(0, (_sound.bytesLoaded / _sound.bytesTotal) * _item.duration - _position);
156                                        bufferLength = Math.min(bufferLength, _item.duration - _position);
157                                } else {
158                                        bufferPercent = 0;
159                                        bufferTime = 1;
160                                        bufferLength = 0;
161                                }
162                        }
163
164                               
165                        if (state == PlayerState.BUFFERING && !_bufferFull && bufferTime >= bufferLength && _sound.bytesLoaded > 0) {
166                                _bufferFull = true;
167                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL);
168                        } else if (state == PlayerState.PLAYING && bufferTime < (bufferLength / 3)) {
169                                // Buffer underrun condition
170                                _bufferFull = false;
171                                if (_channel) {
172                                        _channel.stop();
173                                }
174                                setState(PlayerState.BUFFERING);
175                                return;
176                        }
177                       
178                        if (_sound && !isNaN(bufferPercent) && bufferPercent > 0 && !_bufferingComplete){
179                                if (bufferPercent == 100 && _bufferingComplete == false) {
180                                        _bufferingComplete = true;
181                                }
182                                sendBufferEvent(bufferPercent, 0, {loaded:_sound.bytesLoaded, total:_sound.bytesTotal});
183                        }
184                       
185                        if (state != PlayerState.PLAYING) {
186                                return;
187                        }
188                       
189                        if (_position < _item.duration) {
190                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: _position, duration: _item.duration});
191                        } else if (_item.duration > 0 && _sound.bytesTotal > 0) {
192                                complete();
193                        }
194                }
195               
196                /** Seek in the _sound. **/
197                override public function seek(pos:Number):void {
198                        if ( (_userDuration >= 0 && pos < _userDuration) || (_userDuration < 0 && _sound && pos < _sound.length) || item.start) {
199                                clearInterval(_positionInterval);
200                                _positionInterval = undefined;
201                                if (_channel) {
202                                        _channel.stop();
203                                }
204                                _position = pos;
205                                play();
206                        }
207                }
208
209
210                /** Destroy the _sound. **/
211                override public function stop():void {
212                        clearInterval(_positionInterval);
213                        _positionInterval = undefined;
214                        if (item) {
215                                item.duration = _userDuration;
216                        }
217                        super.stop();
218                        if (_channel) {
219                                _channel.stop();
220                                _channel = null;
221                        }
222                        try {
223                                _sound.close();
224                        } catch (err:Error) {
225                        }
226                }
227
228
229                /** Set the volume level. **/
230                override public function setVolume(vol:Number):void {
231                        streamVolume(vol);
232                        super.setVolume(vol);
233                }
234               
235
236                /** Set the stream's volume, without sending a volume event **/
237                protected function streamVolume(level:Number):void {
238                        _transformer.volume = level / 100;
239                        if (_channel) {
240                                _channel.soundTransform = _transformer;
241                        }
242                }
243        }
244}
Note: See TracBrowser for help on using the repository browser.