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.

414 lines
15KB

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