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_nMIDIButtonCh = m_Properties.GetNumber ("MIDIButtonCh", 0);
m_nMIDIButtonNotes = m_Properties.GetNumber ("MIDIButtonNotes", 0);
m_nMIDIButtonPrev = m_Properties.GetNumber ("MIDIButtonPrev", 0);
m_nMIDIButtonNext = m_Properties.GetNumber ("MIDIButtonNext", 0);
m_nMIDIButtonBack = m_Properties.GetNumber ("MIDIButtonBack", 0);
@ -310,6 +311,11 @@ unsigned CConfig::GetMIDIButtonCh (void) const
return m_nMIDIButtonCh;
}
unsigned CConfig::GetMIDIButtonNotes (void) const
{
return m_nMIDIButtonNotes;
}
unsigned CConfig::GetMIDIButtonPrev (void) const
{
return m_nMIDIButtonPrev;

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

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

@ -62,7 +62,10 @@ LongPressTimeout=400
# Specify MIDI CC to act as a button
# NB: Off < 64 < ON
# 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
MIDIButtonNotes=1
MIDIButtonPrev=00
MIDIButtonNext=02
MIDIButtonBack=03

@ -264,7 +264,7 @@ CUIButtons::CUIButtons (
unsigned selectPin, const char *selectAction,
unsigned homePin, const char *homeAction,
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_longPressTimeout(longPressTimeout),
@ -278,6 +278,7 @@ CUIButtons::CUIButtons (
m_selectAction(CUIButton::triggerTypeFromString(selectAction)),
m_homePin(homePin),
m_homeAction(CUIButton::triggerTypeFromString(homeAction)),
m_notesMidi(notesMidi),
m_prevMidi(ccToMidiPin(prevMidi)),
m_nextMidi(ccToMidiPin(nextMidi)),
m_backMidi(ccToMidiPin(backMidi)),
@ -444,7 +445,7 @@ void CUIButtons::Update (void)
for (unsigned i=0; i<MAX_BUTTONS; i++) {
CUIButton::BtnEvent event = m_buttons[i].Read();
if (event != CUIButton::BtnEventNone) {
LOGDBG("Event: %u", event);
// LOGDBG("Event: %u", event);
(*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++) {
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 homePin, const char *homeAction,
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);
@ -126,7 +126,7 @@ public:
void ResetButton (unsigned pinNumber);
void BtnMIDICCHandler (unsigned nMidiCC, unsigned nMidiData);
void BtnMIDICmdHandler (unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2);
private:
// Array of normal GPIO buttons and "MIDI buttons"
@ -150,6 +150,7 @@ private:
CUIButton::BtnTrigger m_homeAction;
// MIDI button configuration
unsigned m_notesMidi;
unsigned m_prevMidi;
unsigned m_nextMidi;
unsigned m_backMidi;

@ -115,6 +115,7 @@ bool CUserInterface::Initialize (void)
m_pConfig->GetButtonActionHome (),
m_pConfig->GetDoubleClickTimeout (),
m_pConfig->GetLongPressTimeout (),
m_pConfig->GetMIDIButtonNotes (),
m_pConfig->GetMIDIButtonPrev (),
m_pConfig->GetMIDIButtonNext (),
m_pConfig->GetMIDIButtonBack (),
@ -129,7 +130,7 @@ bool CUserInterface::Initialize (void)
}
m_pUIButtons->RegisterEventHandler (UIButtonsEventStub, this);
UISetMIDICCChannel (m_pConfig->GetMIDIButtonCh ());
UISetMIDIButtonChannel (m_pConfig->GetMIDIButtonCh ());
LOGDBG ("Button User Interface initialized");
@ -330,7 +331,7 @@ void CUserInterface::UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam
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)
{
@ -345,11 +346,11 @@ void CUserInterface::UIMIDICCHandler (unsigned nMidiCh, unsigned nMidiCC, unsign
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
if (uCh == 0)

@ -53,7 +53,7 @@ public:
bool bArrowDown, bool bArrowUp);
// 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:
void LCDWrite (const char *pString); // Print to optional HD44780 display
@ -62,7 +62,7 @@ private:
static void EncoderEventStub (CKY040::TEvent Event, void *pParam);
void UIButtonsEventHandler (CUIButton::BtnEvent Event);
static void UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam);
void UISetMIDICCChannel (unsigned uCh);
void UISetMIDIButtonChannel (unsigned uCh);
private:
CMiniDexed *m_pMiniDexed;

Loading…
Cancel
Save