diff --git a/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.cpp b/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.cpp index 3f8c2b6b48..0a1677d0d6 100644 --- a/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.cpp +++ b/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.cpp @@ -26,6 +26,17 @@ MPEZoneLayout::MPEZoneLayout() noexcept { } +MPEZoneLayout::MPEZoneLayout (const MPEZoneLayout& other) + : zones (other.zones) +{ +} + +MPEZoneLayout& MPEZoneLayout::operator= (const MPEZoneLayout& other) +{ + zones = other.zones; + return *this; +} + //============================================================================== bool MPEZoneLayout::addZone (MPEZone newZone) { @@ -46,6 +57,7 @@ bool MPEZoneLayout::addZone (MPEZone newZone) } zones.add (newZone); + listeners.call (&MPEZoneLayout::Listener::zoneLayoutChanged, *this); return noOtherZonesModified; } @@ -66,6 +78,7 @@ MPEZone* MPEZoneLayout::getZoneByIndex (int index) const noexcept void MPEZoneLayout::clearAllZones() { zones.clear(); + listeners.call (&MPEZoneLayout::Listener::zoneLayoutChanged, *this); } //============================================================================== @@ -106,12 +119,20 @@ void MPEZoneLayout::processPitchbendRangeRpnMessage (MidiRPNMessage rpn) { if (MPEZone* zone = getZoneByFirstNoteChannel (rpn.channel)) { - zone->setPerNotePitchbendRange (rpn.value); - return; + if (zone->getPerNotePitchbendRange() != rpn.value) + { + zone->setPerNotePitchbendRange (rpn.value); + listeners.call (&MPEZoneLayout::Listener::zoneLayoutChanged, *this); + } + } + else if (MPEZone* zone = getZoneByMasterChannel (rpn.channel)) + { + if (zone->getMasterPitchbendRange() != rpn.value) + { + zone->setMasterPitchbendRange (rpn.value); + listeners.call (&MPEZoneLayout::Listener::zoneLayoutChanged, *this); + } } - - if (MPEZone* zone = getZoneByMasterChannel (rpn.channel)) - zone->setMasterPitchbendRange (rpn.value); } //============================================================================== @@ -162,6 +183,25 @@ MPEZone* MPEZoneLayout::getZoneByNoteChannel (int channel) const noexcept return nullptr; } +//============================================================================== +void MPEZoneLayout::addListener (Listener* const listenerToAdd) noexcept +{ + listeners.add (listenerToAdd); +} + +void MPEZoneLayout::removeListener (Listener* const listenerToRemove) noexcept +{ + listeners.remove (listenerToRemove); +} + +MPEZoneLayout::Listener::Listener() +{ +} + +MPEZoneLayout::Listener::~Listener() +{ +} + //============================================================================== //============================================================================== #if JUCE_UNIT_TESTS diff --git a/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.h b/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.h index eedd6e78dd..021a07f613 100644 --- a/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.h +++ b/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.h @@ -47,6 +47,16 @@ public: */ MPEZoneLayout() noexcept; + /** Copy constuctor. + This will not copy the listeners registered to the MPEZoneLayout. + */ + MPEZoneLayout (const MPEZoneLayout& other); + + /** Copy assignment operator. + This will not copy the listeners registered to the MPEZoneLayout. + */ + MPEZoneLayout& operator= (const MPEZoneLayout& other); + /** Adds a new MPE zone to the layout. @param newZone The zone to add. @@ -115,10 +125,38 @@ public: */ MPEZone* getZoneByNoteChannel (int midiChannel) const noexcept; + //========================================================================== + /** Listener class. Derive from this class to allow your class to be + notified about changes to the zone layout. + */ + class Listener + { + public: + /** Constructor. */ + Listener(); + + /** Destructor. */ + virtual ~Listener(); + + /** Implement this callback to be notified about any changes to this + MPEZoneLayout. Will be called whenever a zone is added, zones are + removed, or any zone's master or note pitchbend ranges change. + */ + virtual void zoneLayoutChanged (const MPEZoneLayout& layout) = 0; + }; + + //========================================================================== + /** Adds a listener. */ + void addListener (Listener* const listenerToAdd) noexcept; + + /** Removes a listener. */ + void removeListener (Listener* const listenerToRemove) noexcept; + private: //========================================================================== Array zones; MidiRPNDetector rpnDetector; + ListenerList listeners; void processRpnMessage (MidiRPNMessage); void processZoneLayoutRpnMessage (MidiRPNMessage);