The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

415 lines
15KB

  1. /*
  2. ==============================================================================
  3. This is an automatically generated GUI class created by the Introjucer!
  4. Be careful when adding custom code to these files, as only the code within
  5. the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
  6. and re-saved.
  7. Created with Introjucer version: 3.1.0
  8. ------------------------------------------------------------------------------
  9. The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
  10. Copyright 2004-13 by Raw Material Software Ltd.
  11. ==============================================================================
  12. */
  13. //[Headers] You can add your own extra header files here...
  14. //[/Headers]
  15. #include "AudioDemoPlaybackPage.h"
  16. //[MiscUserDefs] You can add your own user definitions and misc code here...
  17. class DemoThumbnailComp : public Component,
  18. public ChangeListener,
  19. public FileDragAndDropTarget,
  20. private Timer
  21. {
  22. public:
  23. DemoThumbnailComp (AudioFormatManager& formatManager,
  24. AudioTransportSource& transportSource_,
  25. Slider& zoomSlider_)
  26. : transportSource (transportSource_),
  27. zoomSlider (zoomSlider_),
  28. thumbnailCache (5),
  29. thumbnail (512, formatManager, thumbnailCache)
  30. {
  31. startTime = endTime = 0;
  32. thumbnail.addChangeListener (this);
  33. currentPositionMarker.setFill (Colours::purple.withAlpha (0.7f));
  34. addAndMakeVisible (&currentPositionMarker);
  35. }
  36. ~DemoThumbnailComp()
  37. {
  38. thumbnail.removeChangeListener (this);
  39. }
  40. void setFile (const File& file)
  41. {
  42. if (! file.isDirectory())
  43. {
  44. thumbnail.setSource (new FileInputSource (file));
  45. startTime = 0;
  46. endTime = thumbnail.getTotalLength();
  47. startTimer (1000 / 40);
  48. }
  49. }
  50. void setZoomFactor (double amount)
  51. {
  52. if (thumbnail.getTotalLength() > 0)
  53. {
  54. const double newScale = jmax (0.001, thumbnail.getTotalLength() * (1.0 - jlimit (0.0, 0.99, amount)));
  55. const double timeAtCentre = xToTime (getWidth() / 2.0f);
  56. startTime = timeAtCentre - newScale * 0.5;
  57. endTime = timeAtCentre + newScale * 0.5;
  58. repaint();
  59. }
  60. }
  61. void mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel) override
  62. {
  63. if (thumbnail.getTotalLength() > 0)
  64. {
  65. double newStart = startTime - wheel.deltaX * (endTime - startTime) / 10.0;
  66. newStart = jlimit (0.0, jmax (0.0, thumbnail.getTotalLength() - (endTime - startTime)), newStart);
  67. endTime = newStart + (endTime - startTime);
  68. startTime = newStart;
  69. if (wheel.deltaY != 0)
  70. zoomSlider.setValue (zoomSlider.getValue() - wheel.deltaY);
  71. repaint();
  72. }
  73. }
  74. void paint (Graphics& g) override
  75. {
  76. g.fillAll (Colours::white);
  77. g.setColour (Colours::lightblue);
  78. if (thumbnail.getTotalLength() > 0)
  79. {
  80. thumbnail.drawChannels (g, getLocalBounds().reduced (2),
  81. startTime, endTime, 1.0f);
  82. }
  83. else
  84. {
  85. g.setFont (14.0f);
  86. g.drawFittedText ("(No audio file selected)", getLocalBounds(), Justification::centred, 2);
  87. }
  88. }
  89. void changeListenerCallback (ChangeBroadcaster*) override
  90. {
  91. // this method is called by the thumbnail when it has changed, so we should repaint it..
  92. repaint();
  93. }
  94. bool isInterestedInFileDrag (const StringArray& /*files*/) override
  95. {
  96. return true;
  97. }
  98. void filesDropped (const StringArray& files, int /*x*/, int /*y*/) override
  99. {
  100. AudioDemoPlaybackPage* demoPage = findParentComponentOfClass<AudioDemoPlaybackPage>();
  101. if (demoPage != nullptr)
  102. demoPage->showFile (File (files[0]));
  103. }
  104. void mouseDown (const MouseEvent& e) override
  105. {
  106. mouseDrag (e);
  107. }
  108. void mouseDrag (const MouseEvent& e) override
  109. {
  110. transportSource.setPosition (jmax (0.0, xToTime ((float) e.x)));
  111. }
  112. void mouseUp (const MouseEvent&) override
  113. {
  114. transportSource.start();
  115. }
  116. void timerCallback() override
  117. {
  118. currentPositionMarker.setVisible (transportSource.isPlaying() || isMouseButtonDown());
  119. double currentPlayPosition = transportSource.getCurrentPosition();
  120. currentPositionMarker.setRectangle (Rectangle<float> (timeToX (currentPlayPosition) - 0.75f, 0,
  121. 1.5f, (float) getHeight()));
  122. }
  123. private:
  124. AudioTransportSource& transportSource;
  125. Slider& zoomSlider;
  126. AudioThumbnailCache thumbnailCache;
  127. AudioThumbnail thumbnail;
  128. double startTime, endTime;
  129. DrawableRectangle currentPositionMarker;
  130. float timeToX (const double time) const
  131. {
  132. return getWidth() * (float) ((time - startTime) / (endTime - startTime));
  133. }
  134. double xToTime (const float x) const
  135. {
  136. return (x / getWidth()) * (endTime - startTime) + startTime;
  137. }
  138. };
  139. //[/MiscUserDefs]
  140. //==============================================================================
  141. AudioDemoPlaybackPage::AudioDemoPlaybackPage (AudioDeviceManager& deviceManager_)
  142. : deviceManager (deviceManager_),
  143. thread ("audio file preview"),
  144. directoryList (nullptr, thread)
  145. {
  146. addAndMakeVisible (zoomLabel = new Label (String::empty,
  147. "zoom:"));
  148. zoomLabel->setFont (Font (15.00f, Font::plain));
  149. zoomLabel->setJustificationType (Justification::centredRight);
  150. zoomLabel->setEditable (false, false, false);
  151. zoomLabel->setColour (TextEditor::textColourId, Colours::black);
  152. zoomLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
  153. addAndMakeVisible (explanation = new Label (String::empty,
  154. "Select an audio file in the treeview above, and this page will display its waveform, and let you play it.."));
  155. explanation->setFont (Font (14.00f, Font::plain));
  156. explanation->setJustificationType (Justification::bottomRight);
  157. explanation->setEditable (false, false, false);
  158. explanation->setColour (TextEditor::textColourId, Colours::black);
  159. explanation->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
  160. addAndMakeVisible (zoomSlider = new Slider (String::empty));
  161. zoomSlider->setRange (0, 1, 0);
  162. zoomSlider->setSliderStyle (Slider::LinearHorizontal);
  163. zoomSlider->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
  164. zoomSlider->addListener (this);
  165. zoomSlider->setSkewFactor (2);
  166. addAndMakeVisible (thumbnail = new DemoThumbnailComp (formatManager, transportSource, *zoomSlider));
  167. addAndMakeVisible (startStopButton = new TextButton (String::empty));
  168. startStopButton->setButtonText ("Play/Stop");
  169. startStopButton->addListener (this);
  170. startStopButton->setColour (TextButton::buttonColourId, Colour (0xff79ed7f));
  171. addAndMakeVisible (fileTreeComp = new FileTreeComponent (directoryList));
  172. //[UserPreSize]
  173. //[/UserPreSize]
  174. setSize (600, 400);
  175. //[Constructor] You can add your own custom stuff here..
  176. formatManager.registerBasicFormats();
  177. directoryList.setDirectory (File::getSpecialLocation (File::userHomeDirectory), true, true);
  178. thread.startThread (3);
  179. fileTreeComp->setColour (FileTreeComponent::backgroundColourId, Colours::white);
  180. fileTreeComp->addListener (this);
  181. deviceManager.addAudioCallback (&audioSourcePlayer);
  182. audioSourcePlayer.setSource (&transportSource);
  183. //[/Constructor]
  184. }
  185. AudioDemoPlaybackPage::~AudioDemoPlaybackPage()
  186. {
  187. //[Destructor_pre]. You can add your own custom destruction code here..
  188. transportSource.setSource (nullptr);
  189. audioSourcePlayer.setSource (nullptr);
  190. deviceManager.removeAudioCallback (&audioSourcePlayer);
  191. fileTreeComp->removeListener (this);
  192. //[/Destructor_pre]
  193. zoomLabel = nullptr;
  194. explanation = nullptr;
  195. zoomSlider = nullptr;
  196. thumbnail = nullptr;
  197. startStopButton = nullptr;
  198. fileTreeComp = nullptr;
  199. //[Destructor]. You can add your own custom destruction code here..
  200. //[/Destructor]
  201. }
  202. //==============================================================================
  203. void AudioDemoPlaybackPage::paint (Graphics& g)
  204. {
  205. //[UserPrePaint] Add your own custom painting code here..
  206. //[/UserPrePaint]
  207. g.fillAll (Colours::lightgrey);
  208. //[UserPaint] Add your own custom painting code here..
  209. //[/UserPaint]
  210. }
  211. void AudioDemoPlaybackPage::resized()
  212. {
  213. zoomLabel->setBounds (16, getHeight() - 90, 55, 24);
  214. explanation->setBounds (256, getHeight() - 82, getWidth() - 275, 64);
  215. zoomSlider->setBounds (72, getHeight() - 90, 200, 24);
  216. thumbnail->setBounds (16, getHeight() - 221, getWidth() - 32, 123);
  217. startStopButton->setBounds (16, getHeight() - 46, 150, 32);
  218. fileTreeComp->setBounds (16, 8, getWidth() - 32, getHeight() - 245);
  219. //[UserResized] Add your own custom resize handling here..
  220. //[/UserResized]
  221. }
  222. void AudioDemoPlaybackPage::sliderValueChanged (Slider* sliderThatWasMoved)
  223. {
  224. //[UsersliderValueChanged_Pre]
  225. //[/UsersliderValueChanged_Pre]
  226. if (sliderThatWasMoved == zoomSlider)
  227. {
  228. //[UserSliderCode_zoomSlider] -- add your slider handling code here..
  229. thumbnail->setZoomFactor (zoomSlider->getValue());
  230. //[/UserSliderCode_zoomSlider]
  231. }
  232. //[UsersliderValueChanged_Post]
  233. //[/UsersliderValueChanged_Post]
  234. }
  235. void AudioDemoPlaybackPage::buttonClicked (Button* buttonThatWasClicked)
  236. {
  237. //[UserbuttonClicked_Pre]
  238. //[/UserbuttonClicked_Pre]
  239. if (buttonThatWasClicked == startStopButton)
  240. {
  241. //[UserButtonCode_startStopButton] -- add your button handler code here..
  242. if (transportSource.isPlaying())
  243. {
  244. transportSource.stop();
  245. }
  246. else
  247. {
  248. transportSource.setPosition (0);
  249. transportSource.start();
  250. }
  251. //[/UserButtonCode_startStopButton]
  252. }
  253. //[UserbuttonClicked_Post]
  254. //[/UserbuttonClicked_Post]
  255. }
  256. //[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
  257. void AudioDemoPlaybackPage::showFile (const File& file)
  258. {
  259. loadFileIntoTransport (file);
  260. zoomSlider->setValue (0, dontSendNotification);
  261. thumbnail->setFile (file);
  262. }
  263. void AudioDemoPlaybackPage::loadFileIntoTransport (const File& audioFile)
  264. {
  265. // unload the previous file source and delete it..
  266. transportSource.stop();
  267. transportSource.setSource (nullptr);
  268. currentAudioFileSource = nullptr;
  269. AudioFormatReader* reader = formatManager.createReaderFor (audioFile);
  270. if (reader != nullptr)
  271. {
  272. currentAudioFileSource = new AudioFormatReaderSource (reader, true);
  273. // ..and plug it into our transport source
  274. transportSource.setSource (currentAudioFileSource,
  275. 32768, // tells it to buffer this many samples ahead
  276. &thread, // this is the background thread to use for reading-ahead
  277. reader->sampleRate);
  278. }
  279. }
  280. void AudioDemoPlaybackPage::selectionChanged()
  281. {
  282. showFile (fileTreeComp->getSelectedFile());
  283. }
  284. void AudioDemoPlaybackPage::fileClicked (const File&, const MouseEvent&)
  285. {
  286. }
  287. void AudioDemoPlaybackPage::fileDoubleClicked (const File&)
  288. {
  289. }
  290. //[/MiscUserCode]
  291. //==============================================================================
  292. #if 0
  293. /* -- Introjucer information section --
  294. This is where the Introjucer stores the metadata that describe this GUI layout, so
  295. make changes in here at your peril!
  296. BEGIN_JUCER_METADATA
  297. <JUCER_COMPONENT documentType="Component" className="AudioDemoPlaybackPage" componentName=""
  298. parentClasses="public Component, public FileBrowserListener"
  299. constructorParams="AudioDeviceManager&amp; deviceManager_" variableInitialisers="deviceManager (deviceManager_),&#10;thread (&quot;audio file preview&quot;),&#10;directoryList (nullptr, thread)"
  300. snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
  301. fixedSize="0" initialWidth="600" initialHeight="400">
  302. <BACKGROUND backgroundColour="ffd3d3d3"/>
  303. <LABEL name="" id="d4f78f975d81c8d3" memberName="zoomLabel" virtualName=""
  304. explicitFocusOrder="0" pos="16 90R 55 24" edTextCol="ff000000"
  305. edBkgCol="0" labelText="zoom:" editableSingleClick="0" editableDoubleClick="0"
  306. focusDiscardsChanges="0" fontname="Default font" fontsize="15"
  307. bold="0" italic="0" justification="34"/>
  308. <LABEL name="" id="7db7d0a64ef21311" memberName="explanation" virtualName=""
  309. explicitFocusOrder="0" pos="256 82R 275M 64" edTextCol="ff000000"
  310. edBkgCol="0" labelText="Select an audio file in the treeview above, and this page will display its waveform, and let you play it.."
  311. editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
  312. fontname="Default font" fontsize="14" bold="0" italic="0" justification="18"/>
  313. <SLIDER name="" id="38bbc108f4c96092" memberName="zoomSlider" virtualName=""
  314. explicitFocusOrder="0" pos="72 90R 200 24" min="0" max="1" int="0"
  315. style="LinearHorizontal" textBoxPos="NoTextBox" textBoxEditable="1"
  316. textBoxWidth="80" textBoxHeight="20" skewFactor="2"/>
  317. <GENERICCOMPONENT name="" id="beef657b0e007936" memberName="thumbnail" virtualName=""
  318. explicitFocusOrder="0" pos="16 221R 32M 123" class="DemoThumbnailComp"
  319. params="formatManager, transportSource, *zoomSlider"/>
  320. <TEXTBUTTON name="" id="abe446e2f3f09420" memberName="startStopButton" virtualName=""
  321. explicitFocusOrder="0" pos="16 46R 150 32" bgColOff="ff79ed7f"
  322. buttonText="Play/Stop" connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  323. <GENERICCOMPONENT name="" id="1de1dc6a18a9032b" memberName="fileTreeComp" virtualName=""
  324. explicitFocusOrder="0" pos="16 8 32M 245M" class="FileTreeComponent"
  325. params="directoryList"/>
  326. </JUCER_COMPONENT>
  327. END_JUCER_METADATA
  328. */
  329. #endif
  330. //[EndFile] You can add extra defines here...
  331. //[/EndFile]