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.

174 lines
6.5KB

  1. /*
  2. ==============================================================================
  3. This file was auto-generated by the Jucer!
  4. It contains the basic startup code for a Juce application.
  5. ==============================================================================
  6. */
  7. #include "PluginProcessor.h"
  8. #include "PluginEditor.h"
  9. //==============================================================================
  10. JuceDemoPluginAudioProcessorEditor::JuceDemoPluginAudioProcessorEditor (JuceDemoPluginAudioProcessor* ownerFilter)
  11. : AudioProcessorEditor (ownerFilter)
  12. {
  13. addAndMakeVisible (gainSlider = new Slider ("gain"));
  14. gainSlider->setSliderStyle (Slider::Rotary);
  15. gainSlider->addListener (this);
  16. gainSlider->setRange (0.0, 1.0, 0.01);
  17. Label* l = new Label ("", "Throughput level:");
  18. l->attachToComponent (gainSlider, false);
  19. l->setFont (Font (11.0f));
  20. addAndMakeVisible (delaySlider = new Slider ("delay"));
  21. delaySlider->setSliderStyle (Slider::Rotary);
  22. delaySlider->addListener (this);
  23. delaySlider->setRange (0.0, 1.0, 0.01);
  24. l = new Label ("", "Delay:");
  25. l->attachToComponent (delaySlider, false);
  26. l->setFont (Font (11.0f));
  27. // create and add the midi keyboard component..
  28. addAndMakeVisible (midiKeyboard
  29. = new MidiKeyboardComponent (ownerFilter->keyboardState,
  30. MidiKeyboardComponent::horizontalKeyboard));
  31. // add a label that will display the current timecode and status..
  32. addAndMakeVisible (infoLabel = new Label (String::empty, String::empty));
  33. infoLabel->setColour (Label::textColourId, Colours::blue);
  34. // add the triangular resizer component for the bottom-right of the UI
  35. addAndMakeVisible (resizer = new ResizableCornerComponent (this, &resizeLimits));
  36. resizeLimits.setSizeLimits (150, 150, 800, 300);
  37. // set our component's initial size to be the last one that was stored in the filter's settings
  38. setSize (ownerFilter->lastUIWidth,
  39. ownerFilter->lastUIHeight);
  40. startTimer (50);
  41. }
  42. JuceDemoPluginAudioProcessorEditor::~JuceDemoPluginAudioProcessorEditor()
  43. {
  44. deleteAllChildren();
  45. }
  46. //==============================================================================
  47. void JuceDemoPluginAudioProcessorEditor::paint (Graphics& g)
  48. {
  49. g.setGradientFill (ColourGradient (Colours::white, 0, 0, Colours::grey, 0, (float) getHeight(), false));
  50. g.fillAll();
  51. }
  52. void JuceDemoPluginAudioProcessorEditor::resized()
  53. {
  54. infoLabel->setBounds (10, 4, 400, 25);
  55. gainSlider->setBounds (20, 60, 150, 40);
  56. delaySlider->setBounds (200, 60, 150, 40);
  57. const int keyboardHeight = 70;
  58. midiKeyboard->setBounds (4, getHeight() - keyboardHeight - 4, getWidth() - 8, keyboardHeight);
  59. resizer->setBounds (getWidth() - 16, getHeight() - 16, 16, 16);
  60. getProcessor()->lastUIWidth = getWidth();
  61. getProcessor()->lastUIHeight = getHeight();
  62. }
  63. //==============================================================================
  64. // This timer periodically checks whether any of the filter's parameters have changed...
  65. void JuceDemoPluginAudioProcessorEditor::timerCallback()
  66. {
  67. JuceDemoPluginAudioProcessor* ourProcessor = getProcessor();
  68. AudioPlayHead::CurrentPositionInfo newPos (ourProcessor->lastPosInfo);
  69. if (lastDisplayedPosition != newPos)
  70. displayPositionInfo (newPos);
  71. gainSlider->setValue (ourProcessor->gain, false);
  72. delaySlider->setValue (ourProcessor->delay, false);
  73. }
  74. // This is our Slider::Listener callback, when the user drags a slider.
  75. void JuceDemoPluginAudioProcessorEditor::sliderValueChanged (Slider* slider)
  76. {
  77. if (slider == gainSlider)
  78. {
  79. // It's vital to use setParameterNotifyingHost to change any parameters that are automatable
  80. // by the host, rather than just modifying them directly, otherwise the host won't know
  81. // that they've changed.
  82. getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::gainParam,
  83. (float) gainSlider->getValue());
  84. }
  85. else if (slider == delaySlider)
  86. {
  87. getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::delayParam,
  88. (float) delaySlider->getValue());
  89. }
  90. }
  91. //==============================================================================
  92. // quick-and-dirty function to format a timecode string
  93. static const String timeToTimecodeString (const double seconds)
  94. {
  95. const double absSecs = fabs (seconds);
  96. const int hours = (int) (absSecs / (60.0 * 60.0));
  97. const int mins = ((int) (absSecs / 60.0)) % 60;
  98. const int secs = ((int) absSecs) % 60;
  99. String s;
  100. if (seconds < 0)
  101. s = "-";
  102. s << String (hours).paddedLeft ('0', 2) << ":"
  103. << String (mins).paddedLeft ('0', 2) << ":"
  104. << String (secs).paddedLeft ('0', 2) << ":"
  105. << String (roundToInt (absSecs * 1000) % 1000).paddedLeft ('0', 3);
  106. return s;
  107. }
  108. // quick-and-dirty function to format a bars/beats string
  109. static const String ppqToBarsBeatsString (double ppq, double lastBarPPQ, int numerator, int denominator)
  110. {
  111. if (numerator == 0 || denominator == 0)
  112. return "1|1|0";
  113. const int ppqPerBar = (numerator * 4 / denominator);
  114. const double beats = (fmod (ppq, ppqPerBar) / ppqPerBar) * numerator;
  115. const int bar = ((int) ppq) / ppqPerBar + 1;
  116. const int beat = ((int) beats) + 1;
  117. const int ticks = ((int) (fmod (beats, 1.0) * 960.0));
  118. String s;
  119. s << bar << '|' << beat << '|' << ticks;
  120. return s;
  121. }
  122. // Updates the text in our position label.
  123. void JuceDemoPluginAudioProcessorEditor::displayPositionInfo (const AudioPlayHead::CurrentPositionInfo& pos)
  124. {
  125. lastDisplayedPosition = pos;
  126. String displayText;
  127. displayText.preallocateStorage (64);
  128. displayText << String (pos.bpm, 2) << " bpm, "
  129. << pos.timeSigNumerator << '/' << pos.timeSigDenominator
  130. << " - " << timeToTimecodeString (pos.timeInSeconds)
  131. << " - " << ppqToBarsBeatsString (pos.ppqPosition, pos.ppqPositionOfLastBarStart,
  132. pos.timeSigNumerator, pos.timeSigDenominator);
  133. if (pos.isRecording)
  134. displayText << " (recording)";
  135. else if (pos.isPlaying)
  136. displayText << " (playing)";
  137. infoLabel->setText (displayText, false);
  138. }