diff --git a/examples/Audio/MidiDemo.h b/examples/Audio/MidiDemo.h index 2e0cb60be1..94ac1446f1 100644 --- a/examples/Audio/MidiDemo.h +++ b/examples/Audio/MidiDemo.h @@ -65,7 +65,7 @@ struct MidiDeviceListEntry : ReferenceCountedObject //============================================================================== class MidiDemo : public Component, private Timer, - private MidiKeyboardStateListener, + private MidiKeyboardState::Listener, private MidiInputCallback, private AsyncUpdater { diff --git a/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp b/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp index 4d93e41ae9..8d9ad2cd37 100644 --- a/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp +++ b/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp @@ -76,9 +76,7 @@ void MidiKeyboardState::noteOnInternal (const int midiChannel, const int midiNo if (isPositiveAndBelow (midiNoteNumber, 128)) { noteStates[midiNoteNumber] = static_cast (noteStates[midiNoteNumber] | (1 << (midiChannel - 1))); - - for (int i = listeners.size(); --i >= 0;) - listeners.getUnchecked(i)->handleNoteOn (this, midiChannel, midiNoteNumber, velocity); + listeners.call ([&] (Listener& l) { l.handleNoteOn (this, midiChannel, midiNoteNumber, velocity); }); } } @@ -101,9 +99,7 @@ void MidiKeyboardState::noteOffInternal (const int midiChannel, const int midiN if (isNoteOn (midiChannel, midiNoteNumber)) { noteStates[midiNoteNumber] = static_cast (noteStates[midiNoteNumber] & ~(1 << (midiChannel - 1))); - - for (int i = listeners.size(); --i >= 0;) - listeners.getUnchecked(i)->handleNoteOff (this, midiChannel, midiNoteNumber, velocity); + listeners.call ([&] (Listener& l) { l.handleNoteOff (this, midiChannel, midiNoteNumber, velocity); }); } } @@ -166,16 +162,16 @@ void MidiKeyboardState::processNextMidiBuffer (MidiBuffer& buffer, } //============================================================================== -void MidiKeyboardState::addListener (MidiKeyboardStateListener* const listener) +void MidiKeyboardState::addListener (Listener* listener) { const ScopedLock sl (lock); - listeners.addIfNotAlreadyThere (listener); + listeners.add (listener); } -void MidiKeyboardState::removeListener (MidiKeyboardStateListener* const listener) +void MidiKeyboardState::removeListener (Listener* listener) { const ScopedLock sl (lock); - listeners.removeFirstMatchingValue (listener); + listeners.remove (listener); } } // namespace juce diff --git a/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h b/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h index 601308f09f..b8dc9f4fab 100644 --- a/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h +++ b/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h @@ -23,51 +23,6 @@ namespace juce { -class MidiKeyboardState; - - -//============================================================================== -/** - Receives events from a MidiKeyboardState object. - - @see MidiKeyboardState - - @tags{Audio} -*/ -class JUCE_API MidiKeyboardStateListener -{ -public: - //============================================================================== - MidiKeyboardStateListener() = default; - virtual ~MidiKeyboardStateListener() = default; - - //============================================================================== - /** Called when one of the MidiKeyboardState's keys is pressed. - - This will be called synchronously when the state is either processing a - buffer in its MidiKeyboardState::processNextMidiBuffer() method, or - when a note is being played with its MidiKeyboardState::noteOn() method. - - Note that this callback could happen from an audio callback thread, so be - careful not to block, and avoid any UI activity in the callback. - */ - virtual void handleNoteOn (MidiKeyboardState* source, - int midiChannel, int midiNoteNumber, float velocity) = 0; - - /** Called when one of the MidiKeyboardState's keys is released. - - This will be called synchronously when the state is either processing a - buffer in its MidiKeyboardState::processNextMidiBuffer() method, or - when a note is being played with its MidiKeyboardState::noteOff() method. - - Note that this callback could happen from an audio callback thread, so be - careful not to block, and avoid any UI activity in the callback. - */ - virtual void handleNoteOff (MidiKeyboardState* source, - int midiChannel, int midiNoteNumber, float velocity) = 0; -}; - - //============================================================================== /** Represents a piano keyboard, keeping track of which keys are currently pressed. @@ -180,27 +135,62 @@ public: bool injectIndirectEvents); //============================================================================== + /** Receives events from a MidiKeyboardState object. */ + class Listener + { + public: + //============================================================================== + virtual ~Listener() = default; + + //============================================================================== + /** Called when one of the MidiKeyboardState's keys is pressed. + + This will be called synchronously when the state is either processing a + buffer in its MidiKeyboardState::processNextMidiBuffer() method, or + when a note is being played with its MidiKeyboardState::noteOn() method. + + Note that this callback could happen from an audio callback thread, so be + careful not to block, and avoid any UI activity in the callback. + */ + virtual void handleNoteOn (MidiKeyboardState* source, + int midiChannel, int midiNoteNumber, float velocity) = 0; + + /** Called when one of the MidiKeyboardState's keys is released. + + This will be called synchronously when the state is either processing a + buffer in its MidiKeyboardState::processNextMidiBuffer() method, or + when a note is being played with its MidiKeyboardState::noteOff() method. + + Note that this callback could happen from an audio callback thread, so be + careful not to block, and avoid any UI activity in the callback. + */ + virtual void handleNoteOff (MidiKeyboardState* source, + int midiChannel, int midiNoteNumber, float velocity) = 0; + }; + /** Registers a listener for callbacks when keys go up or down. @see removeListener */ - void addListener (MidiKeyboardStateListener* listener); + void addListener (Listener* listener); /** Deregisters a listener. @see addListener */ - void removeListener (MidiKeyboardStateListener* listener); + void removeListener (Listener* listener); private: //============================================================================== CriticalSection lock; - uint16 noteStates[128]; + std::atomic noteStates[128]; MidiBuffer eventsToAdd; - Array listeners; + ListenerList listeners; - void noteOnInternal (int midiChannel, int midiNoteNumber, float velocity); + void noteOnInternal (int midiChannel, int midiNoteNumber, float velocity); void noteOffInternal (int midiChannel, int midiNoteNumber, float velocity); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiKeyboardState) }; +using MidiKeyboardStateListener = MidiKeyboardState::Listener; + } // namespace juce diff --git a/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h b/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h index 953a42d38c..b9344e9f26 100644 --- a/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h +++ b/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h @@ -28,14 +28,14 @@ namespace juce Collects incoming realtime MIDI messages and turns them into blocks suitable for processing by a block-based audio callback. - The class can also be used as either a MidiKeyboardStateListener or a MidiInputCallback + The class can also be used as either a MidiKeyboardState::Listener or a MidiInputCallback so it can easily use a midi input or keyboard component as its source. @see MidiMessage, MidiInput @tags{Audio} */ -class JUCE_API MidiMessageCollector : public MidiKeyboardStateListener, +class JUCE_API MidiMessageCollector : public MidiKeyboardState::Listener, public MidiInputCallback { public: diff --git a/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.h b/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.h index 6351b89633..16619a7791 100644 --- a/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.h +++ b/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.h @@ -40,7 +40,7 @@ namespace juce @tags{Audio} */ class JUCE_API MidiKeyboardComponent : public Component, - public MidiKeyboardStateListener, + public MidiKeyboardState::Listener, public ChangeBroadcaster, private Timer {