PageRenderTime 961ms CodeModel.GetById 818ms app.highlight 3ms RepoModel.GetById 138ms app.codeStats 0ms

/flash/src/editor/player.mxml

http://echo-nest-remix.googlecode.com/
Macromedia eXtensible Markup Language | 285 lines | 232 code | 53 blank | 0 comment | 0 complexity | c775e67addaf667de0c803e18784f8e5 MD5 | raw file
  1<?xml version="1.0" encoding="utf-8"?>
  2
  3<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init();" paddingTop="0" paddingRight="0" paddingBottom="0" paddingLeft="0">
  4  <mx:VBox width="100%" paddingTop="10" paddingRight="10" paddingLeft="10">
  5    <mx:HBox paddingBottom="10">
  6      <mx:Button id="browseButton" label="Choose a songÂ…" click="chooseFile();"/>
  7      <mx:CheckBox id="calculateMd5checkBox" label="Check for analysis before uploading" selected="true"/>
  8    </mx:HBox>
  9    <mx:ProgressBar id="progressBar" mode="manual" label="" width="100%"/>
 10    <mx:HBox>
 11      <mx:Button id="remixButton" label="Remix" enabled="false" click="remixButtonHandler();"/>
 12      <mx:Button id="playButton" label="Play" enabled="false" click="togglePlayPause();"/>
 13    </mx:HBox>
 14  </mx:VBox>
 15
 16  <mx:Script><![CDATA[
 17    import com.adobe.serialization.json.JSON;
 18    import com.ryanberdeen.audio.ISampleSource;
 19    import com.ryanberdeen.audio.DiscontinuousSampleSource;
 20    import com.ryanberdeen.audio.SampleRange;
 21    import com.ryanberdeen.audio.SampleSourcePlayer;
 22    import com.ryanberdeen.audio.SoundSampleSource;
 23    import com.ryanberdeen.echonest.api.v3.EchoNestErrorEvent;
 24    import com.ryanberdeen.echonest.api.v3.track.AnalysisEvent;
 25    import com.ryanberdeen.echonest.api.v3.track.TrackApi;
 26    import com.ryanberdeen.echonest.api.v3.track.utils.TrackLoader;
 27    import com.ryanberdeen.echonest.api.v3.track.utils.TrackLoaderEvent;
 28
 29    import flash.events.Event;
 30    import flash.media.Sound;
 31    import flash.utils.Timer;
 32
 33    private var trackApi:TrackApi = new TrackApi();
 34    private var trackLoader:TrackLoader;
 35    private var sound:Sound;
 36
 37    private var bars:Array;
 38    private var beats:Array;
 39
 40    private var remixPlayer:SampleSourcePlayer;
 41    private var samples:Array;
 42    private var playing:Boolean;
 43    private var positionUpdateTimer:Timer;
 44
 45    private function init():void {
 46      trackApi.apiKey = YOUR_API_KEY;
 47
 48      positionUpdateTimer = new Timer(10);
 49      positionUpdateTimer.addEventListener('timer', positionUpdateTimerHandler);
 50      ExternalInterface.addCallback('setRemixString', setRemixString);
 51      callJs('init');
 52    }
 53
 54    private function setStatus(status:String, indeterminate:Boolean = false):void {
 55      progressBar.label = status;
 56      progressBar.indeterminate = indeterminate;
 57      if (indeterminate) {
 58        progressBar.mode = 'event';
 59      }
 60      else {
 61        progressBar.mode = 'manual';
 62      }
 63    }
 64
 65    private function clearStatus():void {
 66      setStatus('');
 67    }
 68
 69    private function resetAnalysis():void {
 70      bars = null;
 71      beats = null;
 72      playButton.enabled = false;
 73      remixButton.enabled = false;
 74
 75      sound = null;
 76      samples = null;
 77
 78      resetPlayer();
 79    }
 80
 81    private function chooseFile():void {
 82      setStatus('Choose file');
 83
 84      resetAnalysis();
 85      trackLoader = new TrackLoader(trackApi);
 86      trackLoader.alwaysUpload = !calculateMd5checkBox.selected;
 87      trackLoader.addEventListener(TrackLoaderEvent.LOADING_SOUND, loadingSoundHandler);
 88      trackLoader.addEventListener(TrackLoaderEvent.SOUND_LOADED, soundLoadedHandler);
 89      trackLoader.addEventListener(TrackLoaderEvent.CALCULATING_MD5, calculatingMd5Handler);
 90      trackLoader.md5Calculator.addEventListener(ProgressEvent.PROGRESS, md5ProgressHandler);
 91      trackLoader.addEventListener(TrackLoaderEvent.MD5_CALCULATED, md5CalculatedHandler);
 92      trackLoader.addEventListener(TrackLoaderEvent.CHECKING_ANALYSIS, checkingAnalysisHandler);
 93      trackLoader.addEventListener(TrackLoaderEvent.UPLOADING_FILE, uploadingFileHandler);
 94      trackLoader.fileReference.addEventListener(ProgressEvent.PROGRESS, uploadProgressHandler);
 95      trackLoader.addEventListener(TrackLoaderEvent.FILE_UPLOADED, fileUploadedHandler);
 96      trackLoader.addEventListener(TrackLoaderEvent.LOADING_ANALYSIS, loadingAnalysisHandler);
 97      trackLoader.analysisLoader.addEventListener(AnalysisEvent.ERROR, analysisErrorHandler);
 98      trackLoader.analysisLoader.addEventListener(AnalysisEvent.COMPLETE, analysisCompleteHandler);
 99      trackLoader.analysisLoader.addEventListener(Event.COMPLETE, analysisLoaderCompleteHandler);
100      trackLoader.analysisLoader.addEventListener(EchoNestErrorEvent.ECHO_NEST_ERROR, echoNestErrorEventHandler);
101      trackLoader.analysisLoader.addEventListener(IOErrorEvent.IO_ERROR, errorEventHandler);
102      trackLoader.analysisLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorEventHandler);
103
104      trackLoader.load();
105    }
106
107    private function loadingSoundHandler(e:TrackLoaderEvent):void {
108      setStatus('Load sound', true);
109    }
110
111    private function soundLoadedHandler(e:TrackLoaderEvent):void {
112      clearStatus();
113      sound = trackLoader.sound;
114    }
115
116    private function calculatingMd5Handler(e:TrackLoaderEvent):void {
117      setStatus('Calculate MD5');
118    }
119
120    private function md5ProgressHandler(e:ProgressEvent):void {
121      progressBar.setProgress(e.bytesLoaded, e.bytesTotal);
122    }
123
124    private function md5CalculatedHandler(e:TrackLoaderEvent):void {
125      clearStatus();
126    }
127
128    private function checkingAnalysisHandler(e:TrackLoaderEvent):void {
129      setStatus('Check for analysis', true);
130    }
131
132    private function uploadingFileHandler(e:TrackLoaderEvent):void {
133      setStatus('Upload');
134    }
135
136    private function uploadProgressHandler(e:ProgressEvent):void {
137      progressBar.setProgress(e.bytesLoaded, e.bytesTotal);
138    }
139
140    private function fileUploadedHandler(e:TrackLoaderEvent):void {
141      clearStatus();
142    }
143
144    private function loadingAnalysisHandler(e:TrackLoaderEvent):void {
145      setStatus('Wait for analysis', true);
146    }
147
148    private function analysisErrorHandler(e:Event):void {
149      // TODO
150    }
151
152    private function analysisCompleteHandler(e:Event):void {
153      setStatus('Download analysis', true);
154    }
155
156    private function analysisLoaderCompleteHandler(e:Event):void {
157      clearStatus();
158
159      bars = trackLoader.analysisLoader.analysis.bars;
160      beats = trackLoader.analysisLoader.analysis.beats;
161
162      callJs('setAnalysis', trackLoader.analysisLoader.analysis);
163      clearStatus();
164      remixButton.enabled = true;
165      preparePlayer();
166    }
167
168    private function echoNestErrorEventHandler(error:EchoNestErrorEvent):void {
169      // TODO
170      clearStatus();
171    }
172
173    private function errorEventHandler(e:Event):void {
174      // TODO
175    }
176
177    private function errorHandler(e:Error):void {
178      // TODO
179    }
180
181    private function resetPlayer():void {
182      if (remixPlayer != null) {
183        remixPlayer.stop();
184
185        remixPlayer = null;
186      }
187      playButton.label = "Play";
188      playing = false;
189      callJs('setProgress', 0);
190      positionUpdateTimer.stop();
191    }
192
193    private function preparePlayer():void {
194      resetPlayer();
195
196      remixPlayer = new SampleSourcePlayer();
197      remixPlayer.addEventListener(Event.SOUND_COMPLETE, playerSoundCompleteHandler);
198      if (samples) {
199        remixPlayer.sampleSource = discontinuousRemix(samples);
200        enablePlayer();
201      }
202    }
203
204    private function enablePlayer():void {
205      playButton.enabled = true;
206      playButton.label = "Play";
207    }
208
209    private function playerSoundCompleteHandler(e:Event):void {
210      positionUpdateTimer.stop();
211      preparePlayer();
212    }
213
214    private function discontinuousRemix(sampleRanges:Array):ISampleSource {
215      var sampleSource:DiscontinuousSampleSource = new DiscontinuousSampleSource();
216
217      sampleSource.sampleRanges = sampleRanges;
218      sampleSource.sampleSource = new SoundSampleSource(sound);
219
220      return sampleSource;
221    }
222
223    private function togglePlayPause():void {
224      if (!playing) {
225        play();
226      }
227      else {
228        pause();
229      }
230    }
231
232    private function play():void {
233      try {
234        remixPlayer.start();
235        positionUpdateTimer.start();
236        playButton.label = "Pause";
237        playing = true;
238      }
239      catch(e:Error) {
240        errorHandler(e);
241      }
242    }
243
244    private function pause():void {
245      remixPlayer.stop();
246      positionUpdateTimer.stop();
247      playButton.label = "Play";
248      playing = false;
249    }
250
251    private function positionUpdateTimerHandler(e:Event):void {
252      callJs('setProgress', remixPlayer.sourcePosition / (sound.length * 44.1))
253    }
254
255    private function callJs(fn:String, ...args):* {
256      args.unshift('Remix.__' + fn);
257      return ExternalInterface.call.apply(ExternalInterface, args);
258    }
259
260    private function remixButtonHandler():void {
261      preparePlayer();
262      callJs('remix');
263    }
264
265    private function setRemixString(string:String):void {
266      setRemixArray(string.split(','));
267    }
268
269    private function setRemixArray(array:Array):void {
270      var result:Array = [];
271      for (var i:int = 0; i < array.length - 1; i++) {
272        result.push(new SampleRange(Math.round(Number(array[i]) * 44100), Math.round(Number(array[++i]) * 44100)));
273      }
274
275      setRemix(result);
276    }
277
278    private function setRemix(sampleRanges:Array):void {
279      samples = sampleRanges;
280      remixPlayer.sampleSource = discontinuousRemix(sampleRanges);
281      preparePlayer();
282      play();
283    }
284  ]]></mx:Script>
285</mx:Application>