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.

171 lines
6.4KB

  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. }
  61. //==============================================================================
  62. // This timer periodically checks whether any of the filter's parameters have changed...
  63. void JuceDemoPluginAudioProcessorEditor::timerCallback()
  64. {
  65. JuceDemoPluginAudioProcessor* ourProcessor = getProcessor();
  66. AudioPlayHead::CurrentPositionInfo newPos (ourProcessor->lastPosInfo);
  67. if (lastDisplayedPosition != newPos)
  68. displayPositionInfo (newPos);
  69. gainSlider->setValue (ourProcessor->gain, false);
  70. delaySlider->setValue (ourProcessor->delay, false);
  71. }
  72. // This is our SliderListener callback, when the user drags a slider.
  73. void JuceDemoPluginAudioProcessorEditor::sliderValueChanged (Slider* slider)
  74. {
  75. if (slider == gainSlider)
  76. {
  77. // It's vital to use setParameterNotifyingHost to change any parameters that are automatable
  78. // by the host, rather than just modifying them directly, otherwise the host won't know
  79. // that they've changed.
  80. getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::gainParam,
  81. (float) gainSlider->getValue());
  82. }
  83. else if (slider == delaySlider)
  84. {
  85. getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::delayParam,
  86. (float) delaySlider->getValue());
  87. }
  88. }
  89. //==============================================================================
  90. // quick-and-dirty function to format a timecode string
  91. static const String timeToTimecodeString (const double seconds)
  92. {
  93. const double absSecs = fabs (seconds);
  94. const int hours = (int) (absSecs / (60.0 * 60.0));
  95. const int mins = ((int) (absSecs / 60.0)) % 60;
  96. const int secs = ((int) absSecs) % 60;
  97. String s;
  98. if (seconds < 0)
  99. s = "-";
  100. s << String (hours).paddedLeft ('0', 2) << ":"
  101. << String (mins).paddedLeft ('0', 2) << ":"
  102. << String (secs).paddedLeft ('0', 2) << ":"
  103. << String (roundToInt (absSecs * 1000) % 1000).paddedLeft ('0', 3);
  104. return s;
  105. }
  106. // quick-and-dirty function to format a bars/beats string
  107. static const String ppqToBarsBeatsString (double ppq, double lastBarPPQ, int numerator, int denominator)
  108. {
  109. if (numerator == 0 || denominator == 0)
  110. return "1|1|0";
  111. const int ppqPerBar = (numerator * 4 / denominator);
  112. const double beats = (fmod (ppq, ppqPerBar) / ppqPerBar) * numerator;
  113. const int bar = ((int) ppq) / ppqPerBar + 1;
  114. const int beat = ((int) beats) + 1;
  115. const int ticks = ((int) (fmod (beats, 1.0) * 960.0));
  116. String s;
  117. s << bar << '|' << beat << '|' << ticks;
  118. return s;
  119. }
  120. // Updates the text in our position label.
  121. void JuceDemoPluginAudioProcessorEditor::displayPositionInfo (const AudioPlayHead::CurrentPositionInfo& pos)
  122. {
  123. lastDisplayedPosition = pos;
  124. String displayText;
  125. displayText.preallocateStorage (64);
  126. displayText << String (pos.bpm, 2) << " bpm, "
  127. << pos.timeSigNumerator << '/' << pos.timeSigDenominator
  128. << " - " << timeToTimecodeString (pos.timeInSeconds)
  129. << " - " << ppqToBarsBeatsString (pos.ppqPosition, pos.ppqPositionOfLastBarStart,
  130. pos.timeSigNumerator, pos.timeSigDenominator);
  131. if (pos.isRecording)
  132. displayText << " (recording)";
  133. else if (pos.isPlaying)
  134. displayText << " (playing)";
  135. infoLabel->setText (displayText, false);
  136. }