annotate johndyer-mediaelement-13fa20a/src/flash/htmlelements/AudioElement.as @ 25:4a4bd554b4c1 tip

Closing this sub branch.
author Daniele Barchiesi <daniele.barchiesi@eecs.qmul.ac.uk>
date Mon, 25 Mar 2013 14:02:54 +0000
parents 032bc65ebafc
children
rev   line source
gyorgy@0 1 
gyorgy@0 2 package htmlelements
gyorgy@0 3 {
gyorgy@0 4 import flash.events.Event;
gyorgy@0 5 import flash.events.IOErrorEvent;
gyorgy@0 6 import flash.events.ProgressEvent;
gyorgy@0 7 import flash.events.TimerEvent;
gyorgy@0 8 import flash.media.ID3Info;
gyorgy@0 9 import flash.media.Sound;
gyorgy@0 10 import flash.media.SoundChannel;
gyorgy@0 11 import flash.media.SoundLoaderContext;
gyorgy@0 12 import flash.media.SoundTransform;
gyorgy@0 13 import flash.net.URLRequest;
gyorgy@0 14 import flash.utils.Timer;
gyorgy@0 15
gyorgy@0 16
gyorgy@0 17
gyorgy@0 18 /**
gyorgy@0 19 * ...
gyorgy@0 20 * @author DefaultUser (Tools -> Custom Arguments...)
gyorgy@0 21 */
gyorgy@0 22 public class AudioElement implements IMediaElement
gyorgy@0 23 {
gyorgy@0 24
gyorgy@0 25 private var _sound:Sound;
gyorgy@0 26 private var _soundTransform:SoundTransform;
gyorgy@0 27 private var _soundChannel:SoundChannel;
gyorgy@0 28 private var _soundLoaderContext:SoundLoaderContext;
gyorgy@0 29
gyorgy@0 30 private var _volume:Number = 1;
gyorgy@0 31 private var _preMuteVolume:Number = 0;
gyorgy@0 32 private var _isMuted:Boolean = false;
gyorgy@0 33 private var _isPaused:Boolean = true;
gyorgy@0 34 private var _isEnded:Boolean = false;
gyorgy@0 35 private var _isLoaded:Boolean = false;
gyorgy@0 36 private var _currentTime:Number = 0;
gyorgy@0 37 private var _duration:Number = 0;
gyorgy@0 38 private var _bytesLoaded:Number = 0;
gyorgy@0 39 private var _bytesTotal:Number = 0;
gyorgy@0 40 private var _bufferedTime:Number = 0;
gyorgy@0 41
gyorgy@0 42 private var _currentUrl:String = "";
gyorgy@0 43 private var _autoplay:Boolean = true;
gyorgy@0 44 private var _preload:String = "";
gyorgy@0 45
gyorgy@0 46 private var _element:FlashMediaElement;
gyorgy@0 47 private var _timer:Timer;
gyorgy@0 48 private var _firedCanPlay:Boolean = false;
gyorgy@0 49
gyorgy@0 50 public function duration():Number {
gyorgy@0 51 return _duration;
gyorgy@0 52 }
gyorgy@0 53
gyorgy@0 54 public function currentTime():Number {
gyorgy@0 55 return _currentTime;
gyorgy@0 56 }
gyorgy@0 57
gyorgy@0 58 public function AudioElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number)
gyorgy@0 59 {
gyorgy@0 60 _element = element;
gyorgy@0 61 _autoplay = autoplay;
gyorgy@0 62 _volume = startVolume;
gyorgy@0 63 _preload = preload;
gyorgy@0 64
gyorgy@0 65 _timer = new Timer(timerRate);
gyorgy@0 66 _timer.addEventListener(TimerEvent.TIMER, timerEventHandler);
gyorgy@0 67
gyorgy@0 68 _soundTransform = new SoundTransform(_volume);
gyorgy@0 69 _soundLoaderContext = new SoundLoaderContext();
gyorgy@0 70 }
gyorgy@0 71
gyorgy@0 72 // events
gyorgy@0 73 function progressHandler(e:ProgressEvent):void {
gyorgy@0 74
gyorgy@0 75 _bytesLoaded = e.bytesLoaded;
gyorgy@0 76 _bytesTotal = e.bytesTotal;
gyorgy@0 77
gyorgy@0 78 sendEvent(HtmlMediaEvent.PROGRESS);
gyorgy@0 79 }
gyorgy@0 80
gyorgy@0 81 function id3Handler(e:Event):void {
gyorgy@0 82 sendEvent(HtmlMediaEvent.LOADEDMETADATA);
gyorgy@0 83
gyorgy@0 84 try {
gyorgy@0 85 var id3:ID3Info = _sound.id3;
gyorgy@0 86 var obj = {
gyorgy@0 87 type:'id3',
gyorgy@0 88 album:id3.album,
gyorgy@0 89 artist:id3.artist,
gyorgy@0 90 comment:id3.comment,
gyorgy@0 91 genre:id3.genre,
gyorgy@0 92 songName:id3.songName,
gyorgy@0 93 track:id3.track,
gyorgy@0 94 year:id3.year
gyorgy@0 95 }
gyorgy@0 96 } catch (err:Error) {}
gyorgy@0 97
gyorgy@0 98
gyorgy@0 99 }
gyorgy@0 100
gyorgy@0 101 function timerEventHandler(e:TimerEvent) {
gyorgy@0 102 _currentTime = _soundChannel.position/1000;
gyorgy@0 103
gyorgy@0 104 // calculate duration
gyorgy@0 105 var duration = Math.round(_sound.length * _sound.bytesTotal/_sound.bytesLoaded/100) / 10;
gyorgy@0 106
gyorgy@0 107 // check to see if the estimated duration changed
gyorgy@0 108 if (_duration != duration && !isNaN(duration)) {
gyorgy@0 109
gyorgy@0 110 _duration = duration;
gyorgy@0 111 sendEvent(HtmlMediaEvent.LOADEDMETADATA);
gyorgy@0 112 }
gyorgy@0 113
gyorgy@0 114 // send timeupdate
gyorgy@0 115 sendEvent(HtmlMediaEvent.TIMEUPDATE);
gyorgy@0 116
gyorgy@0 117 // sometimes the ended event doesn't fire, here's a fake one
gyorgy@0 118 if (_duration > 0 && _currentTime >= _duration-0.2) {
gyorgy@0 119 handleEnded();
gyorgy@0 120 }
gyorgy@0 121 }
gyorgy@0 122
gyorgy@0 123 function soundCompleteHandler(e:Event) {
gyorgy@0 124 handleEnded();
gyorgy@0 125 }
gyorgy@0 126
gyorgy@0 127 function handleEnded():void {
gyorgy@0 128 _timer.stop();
gyorgy@0 129 _currentTime = 0;
gyorgy@0 130 _isEnded = true;
gyorgy@0 131
gyorgy@0 132 sendEvent(HtmlMediaEvent.ENDED);
gyorgy@0 133 }
gyorgy@0 134
gyorgy@0 135 //events
gyorgy@0 136
gyorgy@0 137
gyorgy@0 138 // METHODS
gyorgy@0 139 public function setSrc(url:String):void {
gyorgy@0 140 _currentUrl = url;
gyorgy@0 141 _isLoaded = false;
gyorgy@0 142 }
gyorgy@0 143
gyorgy@0 144
gyorgy@0 145 public function load():void {
gyorgy@0 146
gyorgy@0 147 if (_currentUrl == "")
gyorgy@0 148 return;
gyorgy@0 149
gyorgy@0 150 _sound = new Sound();
gyorgy@0 151 //sound.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
gyorgy@0 152 _sound.addEventListener(ProgressEvent.PROGRESS,progressHandler);
gyorgy@0 153 _sound.addEventListener(Event.ID3,id3Handler);
gyorgy@0 154 _sound.load(new URLRequest(_currentUrl));
gyorgy@0 155 _currentTime = 0;
gyorgy@0 156
gyorgy@0 157 sendEvent(HtmlMediaEvent.LOADSTART);
gyorgy@0 158
gyorgy@0 159 _isLoaded = true;
gyorgy@0 160
gyorgy@0 161 sendEvent(HtmlMediaEvent.LOADEDDATA);
gyorgy@0 162 sendEvent(HtmlMediaEvent.CANPLAY);
gyorgy@0 163 _firedCanPlay = true;
gyorgy@0 164
gyorgy@0 165 if (_playAfterLoading) {
gyorgy@0 166 _playAfterLoading = false;
gyorgy@0 167 play();
gyorgy@0 168 }
gyorgy@0 169 }
gyorgy@0 170
gyorgy@0 171 private var _playAfterLoading:Boolean= false;
gyorgy@0 172
gyorgy@0 173 public function play():void {
gyorgy@0 174
gyorgy@0 175 if (!_isLoaded) {
gyorgy@0 176 _playAfterLoading = true;
gyorgy@0 177 load();
gyorgy@0 178 return;
gyorgy@0 179 }
gyorgy@0 180
gyorgy@0 181 _timer.stop();
gyorgy@0 182
gyorgy@0 183 _soundChannel = _sound.play(_currentTime*1000, 0, _soundTransform);
gyorgy@0 184 _soundChannel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
gyorgy@0 185 _soundChannel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
gyorgy@0 186
gyorgy@0 187 _timer.start();
gyorgy@0 188
gyorgy@0 189 didStartPlaying();
gyorgy@0 190 }
gyorgy@0 191
gyorgy@0 192 public function pause():void {
gyorgy@0 193
gyorgy@0 194 _timer.stop();
gyorgy@0 195 if (_soundChannel != null) {
gyorgy@0 196 _currentTime = _soundChannel.position/1000;
gyorgy@0 197 _soundChannel.stop();
gyorgy@0 198 }
gyorgy@0 199
gyorgy@0 200 _isPaused = true;
gyorgy@0 201 sendEvent(HtmlMediaEvent.PAUSE);
gyorgy@0 202 }
gyorgy@0 203
gyorgy@0 204
gyorgy@0 205 public function stop():void {
gyorgy@0 206 if (_timer != null) {
gyorgy@0 207 _timer.stop();
gyorgy@0 208 }
gyorgy@0 209 if (_soundChannel != null) {
gyorgy@0 210 _soundChannel.stop();
gyorgy@0 211 _sound.close();
gyorgy@0 212 }
gyorgy@0 213 unload();
gyorgy@0 214 sendEvent(HtmlMediaEvent.STOP);
gyorgy@0 215 }
gyorgy@0 216
gyorgy@0 217 public function setCurrentTime(pos:Number):void {
gyorgy@0 218 sendEvent(HtmlMediaEvent.SEEKING);
gyorgy@0 219 _timer.stop();
gyorgy@0 220 _currentTime = pos;
gyorgy@0 221 _soundChannel.stop();
gyorgy@0 222 _sound.length
gyorgy@0 223 _soundChannel = _sound.play(_currentTime * 1000, 0, _soundTransform);
gyorgy@0 224 sendEvent(HtmlMediaEvent.SEEKED);
gyorgy@0 225
gyorgy@0 226 _timer.start();
gyorgy@0 227
gyorgy@0 228 didStartPlaying();
gyorgy@0 229 }
gyorgy@0 230
gyorgy@0 231 private function didStartPlaying():void {
gyorgy@0 232 _isPaused = false;
gyorgy@0 233 sendEvent(HtmlMediaEvent.PLAY);
gyorgy@0 234 sendEvent(HtmlMediaEvent.PLAYING);
gyorgy@0 235 if (!_firedCanPlay) {
gyorgy@0 236 sendEvent(HtmlMediaEvent.LOADEDDATA);
gyorgy@0 237 sendEvent(HtmlMediaEvent.CANPLAY);
gyorgy@0 238 _firedCanPlay = true;
gyorgy@0 239 }
gyorgy@0 240 }
gyorgy@0 241
gyorgy@0 242
gyorgy@0 243 public function setVolume(volume:Number):void {
gyorgy@0 244
gyorgy@0 245 _volume = volume;
gyorgy@0 246 _soundTransform.volume = volume;
gyorgy@0 247
gyorgy@0 248 if (_soundChannel != null) {
gyorgy@0 249 _soundChannel.soundTransform = _soundTransform;
gyorgy@0 250 }
gyorgy@0 251
gyorgy@0 252 sendEvent(HtmlMediaEvent.VOLUMECHANGE);
gyorgy@0 253 }
gyorgy@0 254
gyorgy@0 255
gyorgy@0 256 public function setMuted(muted:Boolean):void {
gyorgy@0 257
gyorgy@0 258 // ignore if already set
gyorgy@0 259 if ( (muted && _isMuted) || (!muted && !_isMuted))
gyorgy@0 260 return;
gyorgy@0 261
gyorgy@0 262 if (muted) {
gyorgy@0 263 _preMuteVolume = _soundTransform.volume;
gyorgy@0 264 setVolume(0);
gyorgy@0 265 } else {
gyorgy@0 266 setVolume(_preMuteVolume);
gyorgy@0 267 }
gyorgy@0 268
gyorgy@0 269 _isMuted = muted;
gyorgy@0 270 }
gyorgy@0 271
gyorgy@0 272 public function unload():void {
gyorgy@0 273 _sound = null;
gyorgy@0 274 _isLoaded = false;
gyorgy@0 275 }
gyorgy@0 276
gyorgy@0 277 private function sendEvent(eventName:String) {
gyorgy@0 278
gyorgy@0 279 // calculate this to mimic HTML5
gyorgy@0 280 _bufferedTime = _bytesLoaded / _bytesTotal * _duration;
gyorgy@0 281
gyorgy@0 282 // build JSON
gyorgy@0 283 var values:String = "duration:" + _duration +
gyorgy@0 284 ",currentTime:" + _currentTime +
gyorgy@0 285 ",muted:" + _isMuted +
gyorgy@0 286 ",paused:" + _isPaused +
gyorgy@0 287 ",ended:" + _isEnded +
gyorgy@0 288 ",volume:" + _volume +
gyorgy@0 289 ",src:\"" + _currentUrl + "\"" +
gyorgy@0 290 ",bytesTotal:" + _bytesTotal +
gyorgy@0 291 ",bufferedBytes:" + _bytesLoaded +
gyorgy@0 292 ",bufferedTime:" + _bufferedTime +
gyorgy@0 293 "";
gyorgy@0 294
gyorgy@0 295 _element.sendEvent(eventName, values);
gyorgy@0 296 }
gyorgy@0 297
gyorgy@0 298 }
gyorgy@0 299
gyorgy@0 300 }