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 }
|