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