Allow MIDI notes to be used as navigation buttons for MiniDexed (#368)

* First implementation of NoteOn/NoteOff MIDI UI buttons

* First implementation of NoteOn/NoteOff MIDI UI buttons

Co-authored-by: diyelectromusic <68612569+diyelectromusic@users.noreply.github.com>
pull/390/head
probonopd 2 years ago committed by GitHub
parent 2bd6f4119f
commit f32c0c98dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/config.cpp
  2. 2
      src/config.h
  3. 4
      src/mididevice.cpp
  4. 3
      src/minidexed.ini
  5. 38
      src/uibuttons.cpp
  6. 5
      src/uibuttons.h
  7. 9
      src/userinterface.cpp
  8. 4
      src/userinterface.h

@ -105,6 +105,7 @@ void CConfig::Load (void)
m_nLongPressTimeout = m_Properties.GetNumber ("LongPressTimeout", 600); m_nLongPressTimeout = m_Properties.GetNumber ("LongPressTimeout", 600);
m_nMIDIButtonCh = m_Properties.GetNumber ("MIDIButtonCh", 0); m_nMIDIButtonCh = m_Properties.GetNumber ("MIDIButtonCh", 0);
m_nMIDIButtonNotes = m_Properties.GetNumber ("MIDIButtonNotes", 0);
m_nMIDIButtonPrev = m_Properties.GetNumber ("MIDIButtonPrev", 0); m_nMIDIButtonPrev = m_Properties.GetNumber ("MIDIButtonPrev", 0);
m_nMIDIButtonNext = m_Properties.GetNumber ("MIDIButtonNext", 0); m_nMIDIButtonNext = m_Properties.GetNumber ("MIDIButtonNext", 0);
m_nMIDIButtonBack = m_Properties.GetNumber ("MIDIButtonBack", 0); m_nMIDIButtonBack = m_Properties.GetNumber ("MIDIButtonBack", 0);
@ -310,6 +311,11 @@ unsigned CConfig::GetMIDIButtonCh (void) const
return m_nMIDIButtonCh; return m_nMIDIButtonCh;
} }
unsigned CConfig::GetMIDIButtonNotes (void) const
{
return m_nMIDIButtonNotes;
}
unsigned CConfig::GetMIDIButtonPrev (void) const unsigned CConfig::GetMIDIButtonPrev (void) const
{ {
return m_nMIDIButtonPrev; return m_nMIDIButtonPrev;

@ -119,6 +119,7 @@ public:
// MIDI Button Navigation // MIDI Button Navigation
unsigned GetMIDIButtonCh (void) const; unsigned GetMIDIButtonCh (void) const;
unsigned GetMIDIButtonNotes (void) const;
unsigned GetMIDIButtonPrev (void) const; unsigned GetMIDIButtonPrev (void) const;
unsigned GetMIDIButtonNext (void) const; unsigned GetMIDIButtonNext (void) const;
unsigned GetMIDIButtonBack (void) const; unsigned GetMIDIButtonBack (void) const;
@ -187,6 +188,7 @@ private:
unsigned m_nLongPressTimeout; unsigned m_nLongPressTimeout;
unsigned m_nMIDIButtonCh; unsigned m_nMIDIButtonCh;
unsigned m_nMIDIButtonNotes;
unsigned m_nMIDIButtonPrev; unsigned m_nMIDIButtonPrev;
unsigned m_nMIDIButtonNext; unsigned m_nMIDIButtonNext;
unsigned m_nMIDIButtonBack; unsigned m_nMIDIButtonBack;

@ -187,11 +187,13 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
switch (ucType) switch (ucType)
{ {
case MIDI_CONTROL_CHANGE: case MIDI_CONTROL_CHANGE:
case MIDI_NOTE_OFF:
case MIDI_NOTE_ON:
if (nLength < 3) if (nLength < 3)
{ {
break; break;
} }
m_pUI->UIMIDICCHandler (ucChannel, pMessage[1], pMessage[2]); m_pUI->UIMIDICmdHandler (ucChannel, ucStatus & 0xF0, pMessage[1], pMessage[2]);
break; break;
} }

@ -62,7 +62,10 @@ LongPressTimeout=400
# Specify MIDI CC to act as a button # Specify MIDI CC to act as a button
# NB: Off < 64 < ON # NB: Off < 64 < ON
# CC channel: 0=OFF; 1-16 MIDI Ch; >16 Omni # CC channel: 0=OFF; 1-16 MIDI Ch; >16 Omni
# If MIDIButtonNotes>0 then treat MIDIButton
# numbers as MIDI Note numbers note CC numbers.
MIDIButtonCh=0 MIDIButtonCh=0
MIDIButtonNotes=1
MIDIButtonPrev=00 MIDIButtonPrev=00
MIDIButtonNext=02 MIDIButtonNext=02
MIDIButtonBack=03 MIDIButtonBack=03

@ -264,7 +264,7 @@ CUIButtons::CUIButtons (
unsigned selectPin, const char *selectAction, unsigned selectPin, const char *selectAction,
unsigned homePin, const char *homeAction, unsigned homePin, const char *homeAction,
unsigned doubleClickTimeout, unsigned longPressTimeout, unsigned doubleClickTimeout, unsigned longPressTimeout,
unsigned prevMidi, unsigned nextMidi, unsigned backMidi, unsigned selectMidi, unsigned homeMidi unsigned notesMidi, unsigned prevMidi, unsigned nextMidi, unsigned backMidi, unsigned selectMidi, unsigned homeMidi
) )
: m_doubleClickTimeout(doubleClickTimeout), : m_doubleClickTimeout(doubleClickTimeout),
m_longPressTimeout(longPressTimeout), m_longPressTimeout(longPressTimeout),
@ -278,6 +278,7 @@ CUIButtons::CUIButtons (
m_selectAction(CUIButton::triggerTypeFromString(selectAction)), m_selectAction(CUIButton::triggerTypeFromString(selectAction)),
m_homePin(homePin), m_homePin(homePin),
m_homeAction(CUIButton::triggerTypeFromString(homeAction)), m_homeAction(CUIButton::triggerTypeFromString(homeAction)),
m_notesMidi(notesMidi),
m_prevMidi(ccToMidiPin(prevMidi)), m_prevMidi(ccToMidiPin(prevMidi)),
m_nextMidi(ccToMidiPin(nextMidi)), m_nextMidi(ccToMidiPin(nextMidi)),
m_backMidi(ccToMidiPin(backMidi)), m_backMidi(ccToMidiPin(backMidi)),
@ -444,7 +445,7 @@ void CUIButtons::Update (void)
for (unsigned i=0; i<MAX_BUTTONS; i++) { for (unsigned i=0; i<MAX_BUTTONS; i++) {
CUIButton::BtnEvent event = m_buttons[i].Read(); CUIButton::BtnEvent event = m_buttons[i].Read();
if (event != CUIButton::BtnEventNone) { if (event != CUIButton::BtnEventNone) {
LOGDBG("Event: %u", event); // LOGDBG("Event: %u", event);
(*m_eventHandler) (event, m_eventParam); (*m_eventHandler) (event, m_eventParam);
} }
} }
@ -459,13 +460,38 @@ void CUIButtons::ResetButton (unsigned pinNumber)
} }
} }
void CUIButtons::BtnMIDICCHandler (unsigned nMidiCC, unsigned nMidiData) void CUIButtons::BtnMIDICmdHandler (unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2)
{ {
unsigned midiPin = ccToMidiPin(nMidiCC); if (m_notesMidi > 0) {
// LOGDBG("BtnMIDICmdHandler (notes): %x %x %x)", nMidiCmd, nMidiData1, nMidiData2);
// Using MIDI Note messages for MIDI buttons
unsigned midiPin = ccToMidiPin(nMidiData1);
for (unsigned i=0; i<MAX_BUTTONS; i++) { for (unsigned i=0; i<MAX_BUTTONS; i++) {
if (m_buttons[i].getPinNumber() == midiPin) { if (m_buttons[i].getPinNumber() == midiPin) {
m_buttons[i].Write (nMidiData); if (nMidiCmd == 0x80) {
// NoteOff = Button OFF
m_buttons[i].Write (0);
} else if ((nMidiCmd == 0x90) && (nMidiData2 == 0)) {
// NoteOn with Vel == 0 = Button OFF
m_buttons[i].Write (0);
} else if (nMidiCmd == 0x90) {
// NoteOn = Button ON
m_buttons[i].Write (127);
} else {
// Ignore other MIDI commands
}
}
}
} else {
// LOGDBG("BtnMIDICmdHandler (CC): %x %x %x)", nMidiCmd, nMidiData1, nMidiData2);
// Using MIDI CC messages for MIDI buttons
if (nMidiCmd == 0xB0) { // Control Message
unsigned midiPin = ccToMidiPin(nMidiData1);
for (unsigned i=0; i<MAX_BUTTONS; i++) {
if (m_buttons[i].getPinNumber() == midiPin) {
m_buttons[i].Write (nMidiData2);
}
}
} }
} }
} }

@ -114,7 +114,7 @@ public:
unsigned selectPin, const char *selectAction, unsigned selectPin, const char *selectAction,
unsigned homePin, const char *homeAction, unsigned homePin, const char *homeAction,
unsigned doubleClickTimeout, unsigned longPressTimeout, unsigned doubleClickTimeout, unsigned longPressTimeout,
unsigned prevMidi, unsigned nextMidi, unsigned backMidi, unsigned selectMidi, unsigned homeMidi unsigned notesMidi, unsigned prevMidi, unsigned nextMidi, unsigned backMidi, unsigned selectMidi, unsigned homeMidi
); );
~CUIButtons (void); ~CUIButtons (void);
@ -126,7 +126,7 @@ public:
void ResetButton (unsigned pinNumber); void ResetButton (unsigned pinNumber);
void BtnMIDICCHandler (unsigned nMidiCC, unsigned nMidiData); void BtnMIDICmdHandler (unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2);
private: private:
// Array of normal GPIO buttons and "MIDI buttons" // Array of normal GPIO buttons and "MIDI buttons"
@ -150,6 +150,7 @@ private:
CUIButton::BtnTrigger m_homeAction; CUIButton::BtnTrigger m_homeAction;
// MIDI button configuration // MIDI button configuration
unsigned m_notesMidi;
unsigned m_prevMidi; unsigned m_prevMidi;
unsigned m_nextMidi; unsigned m_nextMidi;
unsigned m_backMidi; unsigned m_backMidi;

@ -115,6 +115,7 @@ bool CUserInterface::Initialize (void)
m_pConfig->GetButtonActionHome (), m_pConfig->GetButtonActionHome (),
m_pConfig->GetDoubleClickTimeout (), m_pConfig->GetDoubleClickTimeout (),
m_pConfig->GetLongPressTimeout (), m_pConfig->GetLongPressTimeout (),
m_pConfig->GetMIDIButtonNotes (),
m_pConfig->GetMIDIButtonPrev (), m_pConfig->GetMIDIButtonPrev (),
m_pConfig->GetMIDIButtonNext (), m_pConfig->GetMIDIButtonNext (),
m_pConfig->GetMIDIButtonBack (), m_pConfig->GetMIDIButtonBack (),
@ -129,7 +130,7 @@ bool CUserInterface::Initialize (void)
} }
m_pUIButtons->RegisterEventHandler (UIButtonsEventStub, this); m_pUIButtons->RegisterEventHandler (UIButtonsEventStub, this);
UISetMIDICCChannel (m_pConfig->GetMIDIButtonCh ()); UISetMIDIButtonChannel (m_pConfig->GetMIDIButtonCh ());
LOGDBG ("Button User Interface initialized"); LOGDBG ("Button User Interface initialized");
@ -330,7 +331,7 @@ void CUserInterface::UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam
pThis->UIButtonsEventHandler (Event); pThis->UIButtonsEventHandler (Event);
} }
void CUserInterface::UIMIDICCHandler (unsigned nMidiCh, unsigned nMidiCC, unsigned nMidiData) void CUserInterface::UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2)
{ {
if (m_nMIDIButtonCh == CMIDIDevice::Disabled) if (m_nMIDIButtonCh == CMIDIDevice::Disabled)
{ {
@ -345,11 +346,11 @@ void CUserInterface::UIMIDICCHandler (unsigned nMidiCh, unsigned nMidiCC, unsign
if (m_pUIButtons) if (m_pUIButtons)
{ {
m_pUIButtons->BtnMIDICCHandler (nMidiCC, nMidiData); m_pUIButtons->BtnMIDICmdHandler (nMidiCmd, nMidiData1, nMidiData2);
} }
} }
void CUserInterface::UISetMIDICCChannel (unsigned uCh) void CUserInterface::UISetMIDIButtonChannel (unsigned uCh)
{ {
// Mirrors the logic in Performance Config for handling MIDI channel configuration // Mirrors the logic in Performance Config for handling MIDI channel configuration
if (uCh == 0) if (uCh == 0)

@ -53,7 +53,7 @@ public:
bool bArrowDown, bool bArrowUp); bool bArrowDown, bool bArrowUp);
// To be called from the MIDI device on reception of a MIDI CC message // To be called from the MIDI device on reception of a MIDI CC message
void UIMIDICCHandler (unsigned nMidiCh, unsigned nMidiCC, unsigned nMidiData); void UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2);
private: private:
void LCDWrite (const char *pString); // Print to optional HD44780 display void LCDWrite (const char *pString); // Print to optional HD44780 display
@ -62,7 +62,7 @@ private:
static void EncoderEventStub (CKY040::TEvent Event, void *pParam); static void EncoderEventStub (CKY040::TEvent Event, void *pParam);
void UIButtonsEventHandler (CUIButton::BtnEvent Event); void UIButtonsEventHandler (CUIButton::BtnEvent Event);
static void UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam); static void UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam);
void UISetMIDICCChannel (unsigned uCh); void UISetMIDIButtonChannel (unsigned uCh);
private: private:
CMiniDexed *m_pMiniDexed; CMiniDexed *m_pMiniDexed;

Loading…
Cancel
Save