| @@ -125,7 +125,7 @@ public: | |||
| bool isMidiEffect() const override { return true; } | |||
| //============================================================================== | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (this); } | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (*this); } | |||
| bool hasEditor() const override { return true; } | |||
| //============================================================================== | |||
| @@ -74,7 +74,7 @@ public: | |||
| } | |||
| //============================================================================== | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (this); } | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (*this); } | |||
| bool hasEditor() const override { return true; } | |||
| //============================================================================== | |||
| @@ -125,7 +125,7 @@ public: | |||
| } | |||
| //============================================================================== | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (this); } | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (*this); } | |||
| bool hasEditor() const override { return true; } | |||
| //============================================================================== | |||
| @@ -108,7 +108,7 @@ public: | |||
| } | |||
| //============================================================================== | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (this); } | |||
| AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (*this); } | |||
| bool hasEditor() const override { return true; } | |||
| const String getName() const override { return "NoiseGate"; } | |||
| bool acceptsMidi() const override { return false; } | |||
| @@ -198,7 +198,8 @@ public: | |||
| private: | |||
| float getDesktopScaleFactor() const override { return 1.0f; } | |||
| static AudioProcessorEditor* createProcessorEditor (AudioProcessor& processor, PluginWindow::Type type) | |||
| static AudioProcessorEditor* createProcessorEditor (AudioProcessor& processor, | |||
| PluginWindow::Type type) | |||
| { | |||
| if (type == PluginWindow::Type::normal) | |||
| { | |||
| @@ -209,7 +210,7 @@ private: | |||
| } | |||
| if (type == PluginWindow::Type::generic) | |||
| return new GenericAudioProcessorEditor (&processor); | |||
| return new GenericAudioProcessorEditor (processor); | |||
| if (type == PluginWindow::Type::programs) | |||
| return new ProgramAudioProcessorEditor (processor); | |||
| @@ -25,58 +25,53 @@ namespace juce | |||
| namespace MidiBufferHelpers | |||
| { | |||
| inline int getEventTime (const void* const d) noexcept | |||
| inline int getEventTime (const void* d) noexcept | |||
| { | |||
| return readUnaligned<int32> (d); | |||
| } | |||
| inline uint16 getEventDataSize (const void* const d) noexcept | |||
| inline uint16 getEventDataSize (const void* d) noexcept | |||
| { | |||
| return readUnaligned<uint16> (static_cast<const char*> (d) + sizeof (int32)); | |||
| } | |||
| inline uint16 getEventTotalSize (const void* const d) noexcept | |||
| inline uint16 getEventTotalSize (const void* d) noexcept | |||
| { | |||
| return (uint16) (getEventDataSize (d) + sizeof (int32) + sizeof (uint16)); | |||
| } | |||
| static int findActualEventLength (const uint8* const data, const int maxBytes) noexcept | |||
| static int findActualEventLength (const uint8* data, int maxBytes) noexcept | |||
| { | |||
| unsigned int byte = (unsigned int) *data; | |||
| int size = 0; | |||
| auto byte = (unsigned int) *data; | |||
| if (byte == 0xf0 || byte == 0xf7) | |||
| { | |||
| const uint8* d = data + 1; | |||
| int i = 1; | |||
| while (d < data + maxBytes) | |||
| if (*d++ == 0xf7) | |||
| while (i < maxBytes) | |||
| if (data[i++] == 0xf7) | |||
| break; | |||
| size = (int) (d - data); | |||
| return i; | |||
| } | |||
| else if (byte == 0xff) | |||
| if (byte == 0xff) | |||
| { | |||
| if (maxBytes == 1) | |||
| { | |||
| size = 1; | |||
| } | |||
| else | |||
| { | |||
| int n; | |||
| const int bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n); | |||
| size = jmin (maxBytes, n + 2 + bytesLeft); | |||
| } | |||
| } | |||
| else if (byte >= 0x80) | |||
| { | |||
| size = jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte)); | |||
| return 1; | |||
| int n; | |||
| auto bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n); | |||
| return jmin (maxBytes, n + 2 + bytesLeft); | |||
| } | |||
| return size; | |||
| if (byte >= 0x80) | |||
| return jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte)); | |||
| return 0; | |||
| } | |||
| static uint8* findEventAfter (uint8* d, uint8* endData, const int samplePosition) noexcept | |||
| static uint8* findEventAfter (uint8* d, uint8* endData, int samplePosition) noexcept | |||
| { | |||
| while (d < endData && getEventTime (d) <= samplePosition) | |||
| d += getEventTotalSize (d); | |||
| @@ -107,31 +102,31 @@ void MidiBuffer::clear() noexcept { data.clearQuick(); | |||
| void MidiBuffer::ensureSize (size_t minimumNumBytes) { data.ensureStorageAllocated ((int) minimumNumBytes); } | |||
| bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; } | |||
| void MidiBuffer::clear (const int startSample, const int numSamples) | |||
| void MidiBuffer::clear (int startSample, int numSamples) | |||
| { | |||
| uint8* const start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1); | |||
| uint8* const end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1); | |||
| auto start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1); | |||
| auto end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1); | |||
| data.removeRange ((int) (start - data.begin()), (int) (end - data.begin())); | |||
| } | |||
| void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber) | |||
| void MidiBuffer::addEvent (const MidiMessage& m, int sampleNumber) | |||
| { | |||
| addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber); | |||
| } | |||
| void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const int sampleNumber) | |||
| void MidiBuffer::addEvent (const void* newData, int maxBytes, int sampleNumber) | |||
| { | |||
| const int numBytes = MidiBufferHelpers::findActualEventLength (static_cast<const uint8*> (newData), maxBytes); | |||
| auto numBytes = MidiBufferHelpers::findActualEventLength (static_cast<const uint8*> (newData), maxBytes); | |||
| if (numBytes > 0) | |||
| { | |||
| const size_t newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16); | |||
| const int offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin()); | |||
| auto newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16); | |||
| auto offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin()); | |||
| data.insertMultiple (offset, 0, (int) newItemSize); | |||
| uint8* const d = data.begin() + offset; | |||
| auto d = data.begin() + offset; | |||
| writeUnaligned<int32> (d, sampleNumber); | |||
| writeUnaligned<uint16> (d + 4, static_cast<uint16> (numBytes)); | |||
| memcpy (d + 6, newData, (size_t) numBytes); | |||
| @@ -139,9 +134,7 @@ void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const | |||
| } | |||
| void MidiBuffer::addEvents (const MidiBuffer& otherBuffer, | |||
| const int startSample, | |||
| const int numSamples, | |||
| const int sampleDeltaToAdd) | |||
| int startSample, int numSamples, int sampleDeltaToAdd) | |||
| { | |||
| Iterator i (otherBuffer); | |||
| i.setNextSamplePosition (startSample); | |||
| @@ -159,9 +152,9 @@ void MidiBuffer::addEvents (const MidiBuffer& otherBuffer, | |||
| int MidiBuffer::getNumEvents() const noexcept | |||
| { | |||
| int n = 0; | |||
| const uint8* const end = data.end(); | |||
| auto end = data.end(); | |||
| for (const uint8* d = data.begin(); d < end; ++n) | |||
| for (auto d = data.begin(); d < end; ++n) | |||
| d += MidiBufferHelpers::getEventTotalSize (d); | |||
| return n; | |||
| @@ -177,11 +170,11 @@ int MidiBuffer::getLastEventTime() const noexcept | |||
| if (data.size() == 0) | |||
| return 0; | |||
| const uint8* const endData = data.end(); | |||
| auto endData = data.end(); | |||
| for (const uint8* d = data.begin();;) | |||
| for (auto d = data.begin();;) | |||
| { | |||
| const uint8* const nextOne = d + MidiBufferHelpers::getEventTotalSize (d); | |||
| auto nextOne = d + MidiBufferHelpers::getEventTotalSize (d); | |||
| if (nextOne >= endData) | |||
| return MidiBufferHelpers::getEventTime (d); | |||
| @@ -196,24 +189,24 @@ MidiBuffer::Iterator::Iterator (const MidiBuffer& b) noexcept | |||
| { | |||
| } | |||
| MidiBuffer::Iterator::~Iterator() noexcept{} | |||
| MidiBuffer::Iterator::~Iterator() noexcept {} | |||
| void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) noexcept | |||
| void MidiBuffer::Iterator::setNextSamplePosition (int samplePosition) noexcept | |||
| { | |||
| data = buffer.data.begin(); | |||
| const uint8* const dataEnd = buffer.data.end(); | |||
| auto dataEnd = buffer.data.end(); | |||
| while (data < dataEnd && MidiBufferHelpers::getEventTime (data) < samplePosition) | |||
| data += MidiBufferHelpers::getEventTotalSize (data); | |||
| } | |||
| bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes, int& samplePosition) noexcept | |||
| bool MidiBuffer::Iterator::getNextEvent (const uint8*& midiData, int& numBytes, int& samplePosition) noexcept | |||
| { | |||
| if (data >= buffer.data.end()) | |||
| return false; | |||
| samplePosition = MidiBufferHelpers::getEventTime (data); | |||
| const int itemSize = MidiBufferHelpers::getEventDataSize (data); | |||
| auto itemSize = MidiBufferHelpers::getEventDataSize (data); | |||
| numBytes = itemSize; | |||
| midiData = data + sizeof (int32) + sizeof (uint16); | |||
| data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize; | |||
| @@ -227,7 +220,7 @@ bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePositio | |||
| return false; | |||
| samplePosition = MidiBufferHelpers::getEventTime (data); | |||
| const int itemSize = MidiBufferHelpers::getEventDataSize (data); | |||
| auto itemSize = MidiBufferHelpers::getEventDataSize (data); | |||
| result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition); | |||
| data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize; | |||
| @@ -97,6 +97,7 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParameterListener) | |||
| }; | |||
| //============================================================================== | |||
| class BooleanParameterComponent final : public Component, | |||
| private ParameterListener | |||
| { | |||
| @@ -150,6 +151,7 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BooleanParameterComponent) | |||
| }; | |||
| //============================================================================== | |||
| class SwitchParameterComponent final : public Component, | |||
| private ParameterListener | |||
| { | |||
| @@ -255,6 +257,7 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SwitchParameterComponent) | |||
| }; | |||
| //============================================================================== | |||
| class ChoiceParameterComponent final : public Component, | |||
| private ParameterListener | |||
| { | |||
| @@ -317,6 +320,7 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoiceParameterComponent) | |||
| }; | |||
| //============================================================================== | |||
| class SliderParameterComponent final : public Component, | |||
| private ParameterListener | |||
| { | |||
| @@ -340,9 +344,9 @@ public: | |||
| // Set the initial value. | |||
| handleNewParameterValue(); | |||
| slider.onValueChange = [this]() { sliderValueChanged(); }; | |||
| slider.onDragStart = [this]() { sliderStartedDragging(); }; | |||
| slider.onDragEnd = [this]() { sliderStoppedDragging(); }; | |||
| slider.onValueChange = [this] { sliderValueChanged(); }; | |||
| slider.onDragStart = [this] { sliderStartedDragging(); }; | |||
| slider.onDragEnd = [this] { sliderStoppedDragging(); }; | |||
| } | |||
| void paint (Graphics&) override {} | |||
| @@ -408,6 +412,7 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderParameterComponent) | |||
| }; | |||
| //============================================================================== | |||
| class ParameterDisplayComponent : public Component | |||
| { | |||
| public: | |||
| @@ -427,27 +432,27 @@ public: | |||
| // marking a parameter as boolean. If you want consistency across | |||
| // all formats then it might be best to use a | |||
| // SwitchParameterComponent instead. | |||
| parameterComp.reset (new BooleanParameterComponent (processor, param)); | |||
| parameterComp = std::make_unique<BooleanParameterComponent> (processor, param); | |||
| } | |||
| else if (param.getNumSteps() == 2) | |||
| { | |||
| // Most hosts display any parameter with just two steps as a switch. | |||
| parameterComp.reset (new SwitchParameterComponent (processor, param)); | |||
| parameterComp = std::make_unique<SwitchParameterComponent> (processor, param); | |||
| } | |||
| else if (! param.getAllValueStrings().isEmpty()) | |||
| { | |||
| // If we have a list of strings to represent the different states a | |||
| // parameter can be in then we should present a dropdown allowing a | |||
| // user to pick one of them. | |||
| parameterComp.reset (new ChoiceParameterComponent (processor, param)); | |||
| parameterComp = std::make_unique<ChoiceParameterComponent> (processor, param); | |||
| } | |||
| else | |||
| { | |||
| // Everything else can be represented as a slider. | |||
| parameterComp.reset (new SliderParameterComponent (processor, param)); | |||
| parameterComp = std::make_unique<SliderParameterComponent> (processor, param); | |||
| } | |||
| addAndMakeVisible (parameterComp.get()); | |||
| addAndMakeVisible (*parameterComp); | |||
| setSize (400, 40); | |||
| } | |||
| @@ -471,6 +476,7 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParameterDisplayComponent) | |||
| }; | |||
| //============================================================================== | |||
| class ParametersPanel : public Component | |||
| { | |||
| public: | |||
| @@ -480,10 +486,16 @@ public: | |||
| if (param->isAutomatable()) | |||
| addAndMakeVisible (paramComponents.add (new ParameterDisplayComponent (processor, *param))); | |||
| if (auto* comp = paramComponents[0]) | |||
| setSize (comp->getWidth(), comp->getHeight() * paramComponents.size()); | |||
| else | |||
| setSize (400, 100); | |||
| int maxWidth = 400; | |||
| int height = 0; | |||
| for (auto& comp : paramComponents) | |||
| { | |||
| maxWidth = jmax (maxWidth, comp->getWidth()); | |||
| height += comp->getHeight(); | |||
| } | |||
| setSize (maxWidth, height); | |||
| } | |||
| void paint (Graphics& g) override | |||
| @@ -508,26 +520,31 @@ private: | |||
| //============================================================================== | |||
| struct GenericAudioProcessorEditor::Pimpl | |||
| { | |||
| Pimpl (GenericAudioProcessorEditor& parent) | |||
| : owner (parent) | |||
| Pimpl (GenericAudioProcessorEditor& parent) : owner (parent) | |||
| { | |||
| auto* p = parent.getAudioProcessor(); | |||
| jassert (p != nullptr); | |||
| juceParameters.update (*p, false); | |||
| legacyParameters.update (*p, false); | |||
| owner.setOpaque (true); | |||
| view.setViewedComponent (new ParametersPanel (*p, juceParameters.params)); | |||
| view.setViewedComponent (new ParametersPanel (*p, legacyParameters.params)); | |||
| owner.addAndMakeVisible (view); | |||
| view.setScrollBarsShown (true, false); | |||
| } | |||
| void resize (Rectangle<int> size) | |||
| { | |||
| view.setBounds (size); | |||
| auto content = view.getViewedComponent(); | |||
| content->setSize (view.getMaximumVisibleWidth(), content->getHeight()); | |||
| } | |||
| //============================================================================== | |||
| GenericAudioProcessorEditor& owner; | |||
| LegacyAudioParametersWrapper juceParameters; | |||
| LegacyAudioParametersWrapper legacyParameters; | |||
| Viewport view; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) | |||
| @@ -535,7 +552,7 @@ struct GenericAudioProcessorEditor::Pimpl | |||
| //============================================================================== | |||
| GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const p) | |||
| GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor& p) | |||
| : AudioProcessorEditor (p), pimpl (new Pimpl (*this)) | |||
| { | |||
| setSize (pimpl->view.getViewedComponent()->getWidth() + pimpl->view.getVerticalScrollBar().getWidth(), | |||
| @@ -551,7 +568,7 @@ void GenericAudioProcessorEditor::paint (Graphics& g) | |||
| void GenericAudioProcessorEditor::resized() | |||
| { | |||
| pimpl->view.setBounds (getLocalBounds()); | |||
| pimpl->resize (getLocalBounds()); | |||
| } | |||
| } // namespace juce | |||
| @@ -39,17 +39,20 @@ namespace juce | |||
| @tags{Audio} | |||
| */ | |||
| class JUCE_API GenericAudioProcessorEditor : public AudioProcessorEditor | |||
| class JUCE_API GenericAudioProcessorEditor : public AudioProcessorEditor | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| GenericAudioProcessorEditor (AudioProcessor* owner); | |||
| GenericAudioProcessorEditor (AudioProcessor&); | |||
| ~GenericAudioProcessorEditor() override; | |||
| //============================================================================== | |||
| void paint (Graphics&) override; | |||
| void resized() override; | |||
| // This constructor has been changed to take a reference instead of a pointer | |||
| JUCE_DEPRECATED_WITH_BODY (GenericAudioProcessorEditor (AudioProcessor* p), : GenericAudioProcessorEditor (*p) {}) | |||
| private: | |||
| //============================================================================== | |||
| struct Pimpl; | |||