add DAW Controller support for various Arturia controllers

MiniLab 3
Keylab Essential
KeyLab Essential mk3
KeyLab mkII

based on https://github.com/PrzemekBarski/arturia-keylab-essential-mk3-programming-guide

Tested on a Arturia MiniLab 3 and KeyLab mkII

Keylab Essential and Keylab Essential mk3 is not tested
pull/778/head
Gergo Koteles 5 months ago
parent 586783a928
commit ea104bac4c
  1. 3
      src/Makefile
  2. 64
      src/config.cpp
  3. 42
      src/config.h
  4. 1071
      src/dawcontroller.cpp
  5. 52
      src/dawcontroller.h
  6. 171
      src/mididevice.cpp
  7. 57
      src/mididevice.h
  8. 40
      src/midikeyboard.cpp
  9. 11
      src/midikeyboard.h
  10. 40
      src/minidexed.cpp
  11. 5
      src/minidexed.h
  12. 3
      src/minidexed.ini
  13. 16
      src/uibuttons.cpp
  14. 32
      src/uimenu.cpp
  15. 26
      src/userinterface.cpp
  16. 2
      src/userinterface.h

@ -9,7 +9,8 @@ CMSIS_DIR = ../CMSIS_5/CMSIS
OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \ OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \
mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \ mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \
sysexfileloader.o performanceconfig.o perftimer.o \ sysexfileloader.o performanceconfig.o perftimer.o \
effect_compressor.o effect_platervbstereo.o uibuttons.o midipin.o effect_compressor.o effect_platervbstereo.o uibuttons.o midipin.o \
dawcontroller.o
OPTIMIZE = -O3 OPTIMIZE = -O3

@ -204,7 +204,9 @@ void CConfig::Load (void)
m_MIDIButtonActionBankDown = m_Properties.GetString ("MIDIButtonActionBankDown", ""); m_MIDIButtonActionBankDown = m_Properties.GetString ("MIDIButtonActionBankDown", "");
m_MIDIButtonActionTGUp = m_Properties.GetString ("MIDIButtonActionTGUp", ""); m_MIDIButtonActionTGUp = m_Properties.GetString ("MIDIButtonActionTGUp", "");
m_MIDIButtonActionTGDown = m_Properties.GetString ("MIDIButtonActionTGDown", ""); m_MIDIButtonActionTGDown = m_Properties.GetString ("MIDIButtonActionTGDown", "");
m_bDAWControllerEnabled = m_Properties.GetNumber ("DAWControllerEnabled", 0) != 0;
m_bEncoderEnabled = m_Properties.GetNumber ("EncoderEnabled", 0) != 0; m_bEncoderEnabled = m_Properties.GetNumber ("EncoderEnabled", 0) != 0;
m_nEncoderPinClock = m_Properties.GetNumber ("EncoderPinClock", 10); m_nEncoderPinClock = m_Properties.GetNumber ("EncoderPinClock", 10);
m_nEncoderPinData = m_Properties.GetNumber ("EncoderPinData", 9); m_nEncoderPinData = m_Properties.GetNumber ("EncoderPinData", 9);
@ -666,6 +668,36 @@ unsigned CConfig::GetMIDIButtonHome (void) const
return m_nMIDIButtonHome; return m_nMIDIButtonHome;
} }
void CConfig::SetMIDIButtonCh (unsigned v)
{
m_nMIDIButtonCh = v;
}
void CConfig::SetMIDIButtonPrev (unsigned v)
{
m_nMIDIButtonPrev = v;
}
void CConfig::SetMIDIButtonNext (unsigned v)
{
m_nMIDIButtonNext = v;
}
void CConfig::SetMIDIButtonBack (unsigned v)
{
m_nMIDIButtonBack = v;
}
void CConfig::SetMIDIButtonSelect (unsigned v)
{
m_nMIDIButtonSelect = v;
}
void CConfig::SetMIDIButtonHome (unsigned v)
{
m_nMIDIButtonHome = v;
}
const char *CConfig::GetMIDIButtonActionPrev (void) const const char *CConfig::GetMIDIButtonActionPrev (void) const
{ {
return m_MIDIButtonActionPrev.c_str(); return m_MIDIButtonActionPrev.c_str();
@ -691,6 +723,31 @@ const char *CConfig::GetMIDIButtonActionHome (void) const
return m_MIDIButtonActionHome.c_str(); return m_MIDIButtonActionHome.c_str();
} }
void CConfig::SetMIDIButtonActionPrev (const char *v)
{
m_MIDIButtonActionPrev = v;
}
void CConfig::SetMIDIButtonActionNext (const char *v)
{
m_MIDIButtonActionNext = v;
}
void CConfig::SetMIDIButtonActionBack (const char *v)
{
m_MIDIButtonActionBack = v;
}
void CConfig::SetMIDIButtonActionSelect (const char *v)
{
m_MIDIButtonActionSelect = v;
}
void CConfig::SetMIDIButtonActionHome (const char *v)
{
m_MIDIButtonActionHome = v;
}
unsigned CConfig::GetMIDIButtonPgmUp (void) const unsigned CConfig::GetMIDIButtonPgmUp (void) const
{ {
return m_nMIDIButtonPgmUp; return m_nMIDIButtonPgmUp;
@ -751,6 +808,11 @@ const char *CConfig::GetMIDIButtonActionTGDown (void) const
return m_MIDIButtonActionTGDown.c_str(); return m_MIDIButtonActionTGDown.c_str();
} }
bool CConfig::GetDAWControllerEnabled (void) const
{
return m_bDAWControllerEnabled;
}
bool CConfig::GetEncoderEnabled (void) const bool CConfig::GetEncoderEnabled (void) const
{ {
return m_bEncoderEnabled; return m_bEncoderEnabled;

@ -217,6 +217,14 @@ public:
unsigned GetMIDIButtonSelect (void) const; unsigned GetMIDIButtonSelect (void) const;
unsigned GetMIDIButtonHome (void) const; unsigned GetMIDIButtonHome (void) const;
void SetMIDIButtonCh (unsigned v);
void SetMIDIButtonPrev (unsigned v);
void SetMIDIButtonNext (unsigned v);
void SetMIDIButtonBack (unsigned v);
void SetMIDIButtonSelect (unsigned v);
void SetMIDIButtonHome (unsigned v);
// Action type for Midi buttons: "click", "doubleclick", "longpress", "dec", "inc", "" // Action type for Midi buttons: "click", "doubleclick", "longpress", "dec", "inc", ""
const char *GetMIDIButtonActionPrev (void) const; const char *GetMIDIButtonActionPrev (void) const;
const char *GetMIDIButtonActionNext (void) const; const char *GetMIDIButtonActionNext (void) const;
@ -224,6 +232,12 @@ public:
const char *GetMIDIButtonActionSelect (void) const; const char *GetMIDIButtonActionSelect (void) const;
const char *GetMIDIButtonActionHome (void) const; const char *GetMIDIButtonActionHome (void) const;
void SetMIDIButtonActionPrev (const char *v);
void SetMIDIButtonActionNext (const char *v);
void SetMIDIButtonActionBack (const char *v);
void SetMIDIButtonActionSelect (const char *v);
void SetMIDIButtonActionHome (const char *v);
// MIDI Button Program and TG Selection // MIDI Button Program and TG Selection
unsigned GetMIDIButtonPgmUp (void) const; unsigned GetMIDIButtonPgmUp (void) const;
unsigned GetMIDIButtonPgmDown (void) const; unsigned GetMIDIButtonPgmDown (void) const;
@ -240,6 +254,8 @@ public:
const char *GetMIDIButtonActionTGUp (void) const; const char *GetMIDIButtonActionTGUp (void) const;
const char *GetMIDIButtonActionTGDown (void) const; const char *GetMIDIButtonActionTGDown (void) const;
bool GetDAWControllerEnabled (void) const;
// KY-040 Rotary Encoder // KY-040 Rotary Encoder
// GPIO pin numbers are chip numbers, not header positions // GPIO pin numbers are chip numbers, not header positions
bool GetEncoderEnabled (void) const; bool GetEncoderEnabled (void) const;
@ -341,18 +357,6 @@ private:
std::string m_ButtonActionBankDown; std::string m_ButtonActionBankDown;
std::string m_ButtonActionTGUp; std::string m_ButtonActionTGUp;
std::string m_ButtonActionTGDown; std::string m_ButtonActionTGDown;
std::string m_MIDIButtonActionPrev;
std::string m_MIDIButtonActionNext;
std::string m_MIDIButtonActionBack;
std::string m_MIDIButtonActionSelect;
std::string m_MIDIButtonActionHome;
std::string m_MIDIButtonActionPgmUp;
std::string m_MIDIButtonActionPgmDown;
std::string m_MIDIButtonActionBankUp;
std::string m_MIDIButtonActionBankDown;
std::string m_MIDIButtonActionTGUp;
std::string m_MIDIButtonActionTGDown;
unsigned m_nDoubleClickTimeout; unsigned m_nDoubleClickTimeout;
unsigned m_nLongPressTimeout; unsigned m_nLongPressTimeout;
@ -371,6 +375,20 @@ private:
unsigned m_nMIDIButtonTGUp; unsigned m_nMIDIButtonTGUp;
unsigned m_nMIDIButtonTGDown; unsigned m_nMIDIButtonTGDown;
std::string m_MIDIButtonActionPrev;
std::string m_MIDIButtonActionNext;
std::string m_MIDIButtonActionBack;
std::string m_MIDIButtonActionSelect;
std::string m_MIDIButtonActionHome;
std::string m_MIDIButtonActionPgmUp;
std::string m_MIDIButtonActionPgmDown;
std::string m_MIDIButtonActionBankUp;
std::string m_MIDIButtonActionBankDown;
std::string m_MIDIButtonActionTGUp;
std::string m_MIDIButtonActionTGDown;
bool m_bDAWControllerEnabled;
bool m_bEncoderEnabled; bool m_bEncoderEnabled;
unsigned m_nEncoderPinClock; unsigned m_nEncoderPinClock;
unsigned m_nEncoderPinData; unsigned m_nEncoderPinData;

File diff suppressed because it is too large Load Diff

@ -0,0 +1,52 @@
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
// Copyright (C) 2024 The MiniDexed Team
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef _dawcontroller_h
#define _dawcontroller_h
#include <circle/types.h>
class CMIDIKeyboard;
class CMiniDexed;
class CDAWConnection;
class CConfig;
class CUserInterface;
class CDAWController
{
public:
CDAWController (CMiniDexed *pSynthesizer, CMIDIKeyboard *pKeyboard, CConfig *pConfig, CUserInterface *pUI);
~CDAWController (void);
void OnConnect (void);
void MIDISysexHandler (u8 *pPacket, unsigned nLength, unsigned nCable);
void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);
void UpdateState (void);
void MIDIListener (u8 ucCable, u8 ucChannel, u8 ucType, u8 ucP1, u8 ucP2);
private:
CMiniDexed *m_pSynthesizer;
CMIDIKeyboard *m_pKeyboard;
CConfig *m_pConfig;
CUserInterface *m_pUI;
CDAWConnection *m_pDAWConnection;
};
#endif

@ -31,31 +31,6 @@
LOGMODULE ("mididevice"); LOGMODULE ("mididevice");
#define MIDI_NOTE_OFF 0b1000
#define MIDI_NOTE_ON 0b1001
#define MIDI_AFTERTOUCH 0b1010 // TODO
#define MIDI_CHANNEL_AFTERTOUCH 0b1101 // right now Synth_Dexed just manage Channel Aftertouch not Polyphonic AT -> 0b1010
#define MIDI_CONTROL_CHANGE 0b1011
#define MIDI_CC_BANK_SELECT_MSB 0
#define MIDI_CC_MODULATION 1
#define MIDI_CC_BREATH_CONTROLLER 2
#define MIDI_CC_FOOT_PEDAL 4
#define MIDI_CC_PORTAMENTO_TIME 5
#define MIDI_CC_VOLUME 7
#define MIDI_CC_PAN_POSITION 10
#define MIDI_CC_BANK_SELECT_LSB 32
#define MIDI_CC_BANK_SUSTAIN 64
#define MIDI_CC_PORTAMENTO 65
#define MIDI_CC_SOSTENUTO 66
#define MIDI_CC_RESONANCE 71
#define MIDI_CC_FREQUENCY_CUTOFF 74
#define MIDI_CC_REVERB_LEVEL 91
#define MIDI_CC_DETUNE_LEVEL 94
#define MIDI_CC_ALL_SOUND_OFF 120
#define MIDI_CC_ALL_NOTES_OFF 123
#define MIDI_PROGRAM_CHANGE 0b1100
#define MIDI_PITCH_BEND 0b1110
// MIDI "System" level (i.e. all TG) custom CC maps // MIDI "System" level (i.e. all TG) custom CC maps
// Note: Even if number of TGs is not 8, there are only 8 // Note: Even if number of TGs is not 8, there are only 8
// available to be used in the mappings here. // available to be used in the mappings here.
@ -81,7 +56,8 @@ CMIDIDevice::TDeviceMap CMIDIDevice::s_DeviceMap;
CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI) CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI)
: m_pSynthesizer (pSynthesizer), : m_pSynthesizer (pSynthesizer),
m_pConfig (pConfig), m_pConfig (pConfig),
m_pUI (pUI) m_pUI (pUI),
m_pRouteMap ()
{ {
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++) for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++)
{ {
@ -217,10 +193,21 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
m_MIDISpinLock.Acquire (); m_MIDISpinLock.Acquire ();
u8 ucCable = nCable;
u8 ucStatus = pMessage[0]; u8 ucStatus = pMessage[0];
u8 ucChannel = ucStatus & 0x0F; u8 ucChannel = ucStatus & 0x0F;
u8 ucType = ucStatus >> 4; u8 ucType = ucStatus >> 4;
u8 ucP1 = pMessage[1];
u8 ucP2 = nLength >= 3 ? pMessage[2] : 0xFF;
bool bSkip = false;
if (m_pRouteMap)
GetRoutedMIDI (m_pRouteMap, &ucCable, &ucChannel, &ucType, &ucP1, &ucP2, &bSkip);
if (bSkip)
{
// skip (and release mutex at the end)
}
// GLOBAL MIDI SYSEX // GLOBAL MIDI SYSEX
// //
// Master Volume is set using a MIDI SysEx message as follows: // Master Volume is set using a MIDI SysEx message as follows:
@ -239,7 +226,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
// Need to scale the volume parameter to fit // Need to scale the volume parameter to fit
// a 14-bit value: 0..16383 // a 14-bit value: 0..16383
// and then split into LSB/MSB. // and then split into LSB/MSB.
if (nLength == 8 && else if (nLength == 8 &&
pMessage[0] == MIDI_SYSTEM_EXCLUSIVE_BEGIN && pMessage[0] == MIDI_SYSTEM_EXCLUSIVE_BEGIN &&
pMessage[1] == 0x7F && pMessage[1] == 0x7F &&
pMessage[2] == 0x7F && pMessage[2] == 0x7F &&
@ -268,13 +255,13 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
{ {
if ((ucChannel == nPerfCh) || (nPerfCh == OmniMode)) if ((ucChannel == nPerfCh) || (nPerfCh == OmniMode))
{ {
if (pMessage[1] == MIDI_CC_BANK_SELECT_MSB) if (ucP1 == MIDI_CC_BANK_SELECT_MSB)
{ {
m_pSynthesizer->BankSelectMSBPerformance (pMessage[2]); m_pSynthesizer->BankSelectMSBPerformance (ucP2);
} }
else if (pMessage[1] == MIDI_CC_BANK_SELECT_LSB) else if (ucP1 == MIDI_CC_BANK_SELECT_LSB)
{ {
m_pSynthesizer->BankSelectLSBPerformance (pMessage[2]); m_pSynthesizer->BankSelectLSBPerformance (ucP2);
} }
else else
{ {
@ -284,7 +271,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
} }
if (nLength == 3) if (nLength == 3)
{ {
m_pUI->UIMIDICmdHandler (ucChannel, ucStatus & 0xF0, pMessage[1], pMessage[2]); m_pUI->UIMIDICmdHandler (ucChannel, ucType, ucP1, ucP2);
} }
break; break;
@ -294,7 +281,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
{ {
break; break;
} }
m_pUI->UIMIDICmdHandler (ucChannel, ucStatus & 0xF0, pMessage[1], pMessage[2]); m_pUI->UIMIDICmdHandler (ucChannel, ucType, ucP1, ucP2);
break; break;
case MIDI_PROGRAM_CHANGE: case MIDI_PROGRAM_CHANGE:
@ -306,7 +293,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
if ((ucChannel == nPerfCh) || (nPerfCh == OmniMode)) if ((ucChannel == nPerfCh) || (nPerfCh == OmniMode))
{ {
//printf("Performance Select Channel %d\n", nPerfCh); //printf("Performance Select Channel %d\n", nPerfCh);
m_pSynthesizer->ProgramChangePerformance (pMessage[1]); m_pSynthesizer->ProgramChangePerformance (ucP1);
} }
} }
} }
@ -344,17 +331,17 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
break; break;
} }
if (pMessage[2] > 0) if (ucP2 > 0)
{ {
if (pMessage[2] <= 127) if (ucP2 <= 127)
{ {
m_pSynthesizer->keydown (pMessage[1], m_pSynthesizer->keydown (ucP1,
pMessage[2], nTG); ucP2, nTG);
} }
} }
else else
{ {
m_pSynthesizer->keyup (pMessage[1], nTG); m_pSynthesizer->keyup (ucP1, nTG);
} }
break; break;
@ -364,12 +351,12 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
break; break;
} }
m_pSynthesizer->keyup (pMessage[1], nTG); m_pSynthesizer->keyup (ucP1, nTG);
break; break;
case MIDI_CHANNEL_AFTERTOUCH: case MIDI_CHANNEL_AFTERTOUCH:
m_pSynthesizer->setAftertouch (pMessage[1], nTG); m_pSynthesizer->setAftertouch (ucP1, nTG);
m_pSynthesizer->ControllersRefresh (nTG); m_pSynthesizer->ControllersRefresh (nTG);
break; break;
@ -379,81 +366,81 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
break; break;
} }
switch (pMessage[1]) switch (ucP1)
{ {
case MIDI_CC_MODULATION: case MIDI_CC_MODULATION:
m_pSynthesizer->setModWheel (pMessage[2], nTG); m_pSynthesizer->setModWheel (ucP2, nTG);
m_pSynthesizer->ControllersRefresh (nTG); m_pSynthesizer->ControllersRefresh (nTG);
break; break;
case MIDI_CC_FOOT_PEDAL: case MIDI_CC_FOOT_PEDAL:
m_pSynthesizer->setFootController (pMessage[2], nTG); m_pSynthesizer->setFootController (ucP2, nTG);
m_pSynthesizer->ControllersRefresh (nTG); m_pSynthesizer->ControllersRefresh (nTG);
break; break;
case MIDI_CC_PORTAMENTO_TIME: case MIDI_CC_PORTAMENTO_TIME:
m_pSynthesizer->setPortamentoTime (maplong (pMessage[2], 0, 127, 0, 99), nTG); m_pSynthesizer->setPortamentoTime (maplong (ucP2, 0, 127, 0, 99), nTG);
break; break;
case MIDI_CC_BREATH_CONTROLLER: case MIDI_CC_BREATH_CONTROLLER:
m_pSynthesizer->setBreathController (pMessage[2], nTG); m_pSynthesizer->setBreathController (ucP2, nTG);
m_pSynthesizer->ControllersRefresh (nTG); m_pSynthesizer->ControllersRefresh (nTG);
break; break;
case MIDI_CC_VOLUME: case MIDI_CC_VOLUME:
m_pSynthesizer->SetVolume (pMessage[2], nTG); m_pSynthesizer->SetVolume (ucP2, nTG);
break; break;
case MIDI_CC_PAN_POSITION: case MIDI_CC_PAN_POSITION:
m_pSynthesizer->SetPan (pMessage[2], nTG); m_pSynthesizer->SetPan (ucP2, nTG);
break; break;
case MIDI_CC_BANK_SELECT_MSB: case MIDI_CC_BANK_SELECT_MSB:
m_pSynthesizer->BankSelectMSB (pMessage[2], nTG); m_pSynthesizer->BankSelectMSB (ucP2, nTG);
break; break;
case MIDI_CC_BANK_SELECT_LSB: case MIDI_CC_BANK_SELECT_LSB:
m_pSynthesizer->BankSelectLSB (pMessage[2], nTG); m_pSynthesizer->BankSelectLSB (ucP2, nTG);
break; break;
case MIDI_CC_BANK_SUSTAIN: case MIDI_CC_BANK_SUSTAIN:
m_pSynthesizer->setSustain (pMessage[2] >= 64, nTG); m_pSynthesizer->setSustain (ucP2 >= 64, nTG);
break; break;
case MIDI_CC_SOSTENUTO: case MIDI_CC_SOSTENUTO:
m_pSynthesizer->setSostenuto (pMessage[2] >= 64, nTG); m_pSynthesizer->setSostenuto (ucP2 >= 64, nTG);
break; break;
case MIDI_CC_PORTAMENTO: case MIDI_CC_PORTAMENTO:
m_pSynthesizer->setPortamentoMode (pMessage[2] >= 64, nTG); m_pSynthesizer->setPortamentoMode (ucP2 >= 64, nTG);
break; break;
case MIDI_CC_RESONANCE: case MIDI_CC_RESONANCE:
m_pSynthesizer->SetResonance (maplong (pMessage[2], 0, 127, 0, 99), nTG); m_pSynthesizer->SetResonance (maplong (ucP2, 0, 127, 0, 99), nTG);
break; break;
case MIDI_CC_FREQUENCY_CUTOFF: case MIDI_CC_FREQUENCY_CUTOFF:
m_pSynthesizer->SetCutoff (maplong (pMessage[2], 0, 127, 0, 99), nTG); m_pSynthesizer->SetCutoff (maplong (ucP2, 0, 127, 0, 99), nTG);
break; break;
case MIDI_CC_REVERB_LEVEL: case MIDI_CC_REVERB_LEVEL:
m_pSynthesizer->SetReverbSend (maplong (pMessage[2], 0, 127, 0, 99), nTG); m_pSynthesizer->SetReverbSend (maplong (ucP2, 0, 127, 0, 99), nTG);
break; break;
case MIDI_CC_DETUNE_LEVEL: case MIDI_CC_DETUNE_LEVEL:
if (pMessage[2] == 0) if (ucP2 == 0)
{ {
// "0 to 127, with 0 being no celeste (detune) effect applied at all." // "0 to 127, with 0 being no celeste (detune) effect applied at all."
m_pSynthesizer->SetMasterTune (0, nTG); m_pSynthesizer->SetMasterTune (0, nTG);
} }
else else
{ {
m_pSynthesizer->SetMasterTune (maplong (pMessage[2], 1, 127, -99, 99), nTG); m_pSynthesizer->SetMasterTune (maplong (ucP2, 1, 127, -99, 99), nTG);
} }
break; break;
case MIDI_CC_ALL_SOUND_OFF: case MIDI_CC_ALL_SOUND_OFF:
m_pSynthesizer->panic (pMessage[2], nTG); m_pSynthesizer->panic (ucP2, nTG);
break; break;
case MIDI_CC_ALL_NOTES_OFF: case MIDI_CC_ALL_NOTES_OFF:
@ -462,7 +449,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
// "Receivers should ignore an All Notes Off message while Omni is on (Modes 1 & 2)" // "Receivers should ignore an All Notes Off message while Omni is on (Modes 1 & 2)"
if (!m_pConfig->GetIgnoreAllNotesOff () && m_ChannelMap[nTG] != OmniMode) if (!m_pConfig->GetIgnoreAllNotesOff () && m_ChannelMap[nTG] != OmniMode)
{ {
m_pSynthesizer->notesOff (pMessage[2], nTG); m_pSynthesizer->notesOff (ucP2, nTG);
} }
break; break;
@ -472,7 +459,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
// so it is possible to break out of the main TG loop too. // so it is possible to break out of the main TG loop too.
// Note: We handle this here so we get the TG MIDI channel checking. // Note: We handle this here so we get the TG MIDI channel checking.
if (!bSystemCCChecked) { if (!bSystemCCChecked) {
bSystemCCHandled = HandleMIDISystemCC(pMessage[1], pMessage[2]); bSystemCCHandled = HandleMIDISystemCC(ucP1, ucP2);
bSystemCCChecked = true; bSystemCCChecked = true;
} }
break; break;
@ -483,7 +470,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
// do program change only if enabled in config and not in "Performance Select Channel" mode // do program change only if enabled in config and not in "Performance Select Channel" mode
if( m_pConfig->GetMIDIRXProgramChange() && ( m_pSynthesizer->GetPerformanceSelectChannel() == Disabled) ) { if( m_pConfig->GetMIDIRXProgramChange() && ( m_pSynthesizer->GetPerformanceSelectChannel() == Disabled) ) {
//printf("Program Change to %d (%d)\n", ucChannel, m_pSynthesizer->GetPerformanceSelectChannel()); //printf("Program Change to %d (%d)\n", ucChannel, m_pSynthesizer->GetPerformanceSelectChannel());
m_pSynthesizer->ProgramChange (pMessage[1], nTG); m_pSynthesizer->ProgramChange (ucP1, nTG);
} }
break; break;
@ -493,8 +480,8 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
break; break;
} }
s16 nValue = pMessage[1]; s16 nValue = ucP1;
nValue |= (s16) pMessage[2] << 7; nValue |= (s16) ucP2 << 7;
nValue -= 0x2000; nValue -= 0x2000;
m_pSynthesizer->setPitchbend (nValue, nTG); m_pSynthesizer->setPitchbend (nValue, nTG);
@ -506,6 +493,9 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
} }
} }
} }
if (m_pRouteMap)
MIDIListener(ucCable, ucChannel, ucType, ucP1, ucP2);
} }
m_MIDISpinLock.Release (); m_MIDISpinLock.Release ();
} }
@ -567,6 +557,11 @@ bool CMIDIDevice::HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval)
return false; return false;
} }
void CMIDIDevice::SetRouteMap (TMIDIRoute *pRouteMap)
{
m_pRouteMap = pRouteMap;
}
void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG) void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG)
{ {
int16_t sysex_return; int16_t sysex_return;
@ -695,6 +690,11 @@ void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nL
} }
} }
void CMIDIDevice::MIDIListener (u8 ucCable, u8 ucChannel, u8 ucType, u8 ucP1, u8 ucP2)
{
}
void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG) void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG)
{ {
uint8_t voicedump[163]; uint8_t voicedump[163];
@ -711,3 +711,44 @@ void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable
// LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str()); // LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str());
} }
} }
void GetRoutedMIDI (TMIDIRoute *pMap, u8 *pCable, u8 *pCh, u8 *pType, u8 *pP1, u8 *pP2, bool *bSkip)
{
assert (pMap);
for (TMIDIRoute *r = pMap; r->ucSCable != 0xFF ; r++)
{
if (r->ucSCable == *pCable &&
(r->ucSCh == *pCh || r->ucSCh >= 16) &&
(r->ucSType == *pType || r->ucSType >= 16) &&
(r->ucSP1 == *pP1 || r->ucSP1 > 127) &&
(r->ucSP2 == *pP2 || r->ucSP2 > 127))
{
if (r->ucSType == MIDI_NOTE_ON)
r->bHandled = false;
if (r->bSkip ||
r->bSkipHandled && r->ucSType == MIDI_NOTE_OFF && (r-1)->bHandled ||
r->bSkipHandled && r->ucSType == MIDI_AFTERTOUCH && (r-2)->bHandled) {
*bSkip = true;
return;
}
if (r->bSkipHandled && r->ucSType == MIDI_NOTE_OFF)
(r-1)->bHandled = true;
if (r->bSkipHandled && r->ucSType == MIDI_AFTERTOUCH)
(r-2)->bHandled = true;
*pCh = r->ucDCh;
*pType = r->ucDType;
if (r->ucDP1 <= 127)
*pP1 = r->ucDP1;
if (r->ucDP1 == TMIDIRoute::P2)
*pP1 = *pP2;
if (r->ucDP2 <= 127)
*pP2 = r->ucDP2;
if (r->bToggle)
r->ucDP2 = r->ucDP2 ? 0x0 : 0x7F;
return;
}
}
}

@ -33,8 +33,57 @@
#define MAX_DX7_SYSEX_LENGTH 4104 #define MAX_DX7_SYSEX_LENGTH 4104
#define MAX_MIDI_MESSAGE MAX_DX7_SYSEX_LENGTH #define MAX_MIDI_MESSAGE MAX_DX7_SYSEX_LENGTH
#define MIDI_NOTE_OFF 0b1000
#define MIDI_NOTE_ON 0b1001
#define MIDI_AFTERTOUCH 0b1010 // TODO
#define MIDI_CHANNEL_AFTERTOUCH 0b1101 // right now Synth_Dexed just manage Channel Aftertouch not Polyphonic AT -> 0b1010
#define MIDI_CONTROL_CHANGE 0b1011
#define MIDI_CC_BANK_SELECT_MSB 0
#define MIDI_CC_MODULATION 1
#define MIDI_CC_BREATH_CONTROLLER 2
#define MIDI_CC_FOOT_PEDAL 4
#define MIDI_CC_PORTAMENTO_TIME 5
#define MIDI_CC_VOLUME 7
#define MIDI_CC_PAN_POSITION 10
#define MIDI_CC_BANK_SELECT_LSB 32
#define MIDI_CC_BANK_SUSTAIN 64
#define MIDI_CC_PORTAMENTO 65
#define MIDI_CC_SOSTENUTO 66
#define MIDI_CC_RESONANCE 71
#define MIDI_CC_FREQUENCY_CUTOFF 74
#define MIDI_CC_REVERB_LEVEL 91
#define MIDI_CC_DETUNE_LEVEL 94
#define MIDI_CC_ALL_SOUND_OFF 120
#define MIDI_CC_ALL_NOTES_OFF 123
#define MIDI_PROGRAM_CHANGE 0b1100
#define MIDI_PITCH_BEND 0b1110
class CMiniDexed; class CMiniDexed;
struct TMIDIRoute
{
enum TRouteOP
{
P2 = 0x82,
};
u8 ucSCable;
u8 ucSCh;
u8 ucSType;
u8 ucSP1;
u8 ucSP2;
u8 ucDCh;
u8 ucDType;
u8 ucDP1;
u8 ucDP2;
bool bSkip;
bool bToggle;
bool bHandled;
bool bSkipHandled;
};
void GetRoutedMIDI (TMIDIRoute *m_pRouteMap, u8 *pCable, u8 *pChannel, u8 *pType, u8 *pP1, u8 *pP2, bool *bSkip);
class CMIDIDevice class CMIDIDevice
{ {
public: public:
@ -46,6 +95,8 @@ public:
ChannelUnknown ChannelUnknown
}; };
public: public:
CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI); CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI);
virtual ~CMIDIDevice (void); virtual ~CMIDIDevice (void);
@ -53,6 +104,8 @@ public:
void SetChannel (u8 ucChannel, unsigned nTG); void SetChannel (u8 ucChannel, unsigned nTG);
u8 GetChannel (unsigned nTG) const; u8 GetChannel (unsigned nTG) const;
void SetRouteMap (TMIDIRoute *pRouteMap);
virtual void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) {} virtual void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) {}
virtual void SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG); virtual void SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG);
@ -61,6 +114,8 @@ protected:
void AddDevice (const char *pDeviceName); void AddDevice (const char *pDeviceName);
void HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG); void HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG);
virtual void MIDIListener (u8 ucCable, u8 ucChannel, u8 ucType, u8 ucP1, u8 ucP2);
private: private:
bool HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval); bool HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval);
@ -78,6 +133,8 @@ private:
std::string m_DeviceName; std::string m_DeviceName;
TMIDIRoute *m_pRouteMap;
typedef std::unordered_map<std::string, CMIDIDevice *> TDeviceMap; typedef std::unordered_map<std::string, CMIDIDevice *> TDeviceMap;
static TDeviceMap s_DeviceMap; static TDeviceMap s_DeviceMap;

@ -29,15 +29,20 @@ CMIDIKeyboard::CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserI
: CMIDIDevice (pSynthesizer, pConfig, pUI), : CMIDIDevice (pSynthesizer, pConfig, pUI),
m_nSysExIdx (0), m_nSysExIdx (0),
m_nInstance (nInstance), m_nInstance (nInstance),
m_pMIDIDevice (0) m_pMIDIDevice (0),
m_pDAWController (0)
{ {
m_DeviceName.Format ("umidi%u", nInstance+1); m_DeviceName.Format ("umidi%u", nInstance+1);
AddDevice (m_DeviceName); AddDevice (m_DeviceName);
if (pConfig->GetDAWControllerEnabled ())
m_pDAWController = new CDAWController (pSynthesizer, this, pConfig, pUI);
} }
CMIDIKeyboard::~CMIDIKeyboard (void) CMIDIKeyboard::~CMIDIKeyboard (void)
{ {
delete m_pDAWController;
} }
void CMIDIKeyboard::Process (boolean bPlugAndPlayUpdated) void CMIDIKeyboard::Process (boolean bPlugAndPlayUpdated)
@ -69,6 +74,9 @@ void CMIDIKeyboard::Process (boolean bPlugAndPlayUpdated)
m_pMIDIDevice->RegisterPacketHandler (MIDIPacketHandler, this); m_pMIDIDevice->RegisterPacketHandler (MIDIPacketHandler, this);
m_pMIDIDevice->RegisterRemovedHandler (DeviceRemovedHandler, this); m_pMIDIDevice->RegisterRemovedHandler (DeviceRemovedHandler, this);
if (m_pDAWController)
m_pDAWController->OnConnect();
} }
} }
} }
@ -85,6 +93,13 @@ void CMIDIKeyboard::Send (const u8 *pMessage, size_t nLength, unsigned nCable)
m_SendQueue.push (Entry); m_SendQueue.push (Entry);
} }
void CMIDIKeyboard::SendDebounce (const u8 *pMessage, size_t nLength, unsigned nCable)
{
TSendQueueEntry Entry = m_SendQueue.back ();
if (Entry.nLength != nLength || Entry.nCable != nCable || memcmp (Entry.pMessage, pMessage, nLength) != 0)
Send (pMessage, nLength, nCable);
}
// Most packets will be passed straight onto the main MIDI message handler // Most packets will be passed straight onto the main MIDI message handler
// but SysEx messages are multiple USB packets and so will need building up // but SysEx messages are multiple USB packets and so will need building up
// before parsing. // before parsing.
@ -122,6 +137,10 @@ void CMIDIKeyboard::USBMIDIMessageHandler (u8 *pPacket, unsigned nLength, unsign
m_SysEx[m_nSysExIdx++] = pPacket[i]; m_SysEx[m_nSysExIdx++] = pPacket[i];
//printf ("SysEx End Idx=%d\n", m_nSysExIdx); //printf ("SysEx End Idx=%d\n", m_nSysExIdx);
MIDIMessageHandler (m_SysEx, m_nSysExIdx, nCable); MIDIMessageHandler (m_SysEx, m_nSysExIdx, nCable);
if (m_pDAWController)
m_pDAWController->MIDISysexHandler (m_SysEx, m_nSysExIdx, nCable);
// Reset ready for next time // Reset ready for next time
m_nSysExIdx = 0; m_nSysExIdx = 0;
} }
@ -160,3 +179,22 @@ void CMIDIKeyboard::DeviceRemovedHandler (CDevice *pDevice, void *pContext)
pThis->m_pMIDIDevice = 0; pThis->m_pMIDIDevice = 0;
} }
void CMIDIKeyboard::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp)
{
if (m_pMIDIDevice && m_pDAWController)
m_pDAWController->DisplayWrite (pMenu, pParam, pValue, bArrowDown, bArrowUp);
}
void CMIDIKeyboard::UpdateDAWState (void)
{
if (m_pMIDIDevice && m_pDAWController)
m_pDAWController->UpdateState ();
}
void CMIDIKeyboard::MIDIListener (u8 ucCable, u8 ucChannel, u8 ucType, u8 ucP1, u8 ucP2)
{
if (m_pDAWController)
m_pDAWController->MIDIListener (ucCable, ucChannel, ucType, ucP1, ucP2);
}

@ -25,6 +25,7 @@
#include "mididevice.h" #include "mididevice.h"
#include "config.h" #include "config.h"
#include "dawcontroller.h"
#include <circle/usb/usbmidi.h> #include <circle/usb/usbmidi.h>
#include <circle/device.h> #include <circle/device.h>
#include <circle/string.h> #include <circle/string.h>
@ -44,6 +45,12 @@ public:
void Process (boolean bPlugAndPlayUpdated); void Process (boolean bPlugAndPlayUpdated);
void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) override; void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) override;
void SendDebounce (const u8 *pMessage, size_t nLength, unsigned nCable = 0);
void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);
void UpdateDAWState (void);
private: private:
static void MIDIPacketHandler (unsigned nCable, u8 *pPacket, unsigned nLength, unsigned nDevice, void *pParam); static void MIDIPacketHandler (unsigned nCable, u8 *pPacket, unsigned nLength, unsigned nDevice, void *pParam);
@ -51,6 +58,8 @@ private:
void USBMIDIMessageHandler (u8 *pPacket, unsigned nLength, unsigned nCable, unsigned nDevice); void USBMIDIMessageHandler (u8 *pPacket, unsigned nLength, unsigned nCable, unsigned nDevice);
void MIDIListener (u8 ucCable, u8 ucChannel, u8 ucType, u8 ucP1, u8 ucP2) override;
private: private:
struct TSendQueueEntry struct TSendQueueEntry
{ {
@ -68,6 +77,8 @@ private:
CUSBMIDIDevice * volatile m_pMIDIDevice; CUSBMIDIDevice * volatile m_pMIDIDevice;
std::queue<TSendQueueEntry> m_SendQueue; std::queue<TSendQueueEntry> m_SendQueue;
CDAWController *m_pDAWController;
}; };
#endif #endif

@ -1059,6 +1059,24 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT
assert (0); assert (0);
break; break;
} }
switch (Parameter)
{
case TGParameterCutoff:
case TGParameterEnabled:
case TGParameterMasterTune:
case TGParameterMIDIChannel:
case TGParameterPan:
case TGParameterProgram:
case TGParameterResonance:
case TGParameterReverbSend:
case TGParameterPortamentoTime:
case TGParameterPortamentoMode:
UpdateDAWState ();
break;
default:
break;
}
} }
int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG)
@ -1799,6 +1817,25 @@ void CMiniDexed::setMasterVolume (float32_t vol)
nMasterVolume=vol; nMasterVolume=vol;
} }
void CMiniDexed::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp)
{
m_UI.DisplayWrite (pMenu, pParam, pValue, bArrowDown, bArrowUp);
for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++)
{
m_pMIDIKeyboard[i]->DisplayWrite (pMenu, pParam, pValue, bArrowDown, bArrowUp);
}
}
void CMiniDexed::UpdateDAWState ()
{
for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++)
{
m_pMIDIKeyboard[i]->UpdateDAWState ();
}
}
std::string CMiniDexed::GetPerformanceFileName(unsigned nID) std::string CMiniDexed::GetPerformanceFileName(unsigned nID)
{ {
return m_PerformanceConfig.GetPerformanceFileName(nID); return m_PerformanceConfig.GetPerformanceFileName(nID);
@ -1962,6 +1999,7 @@ void CMiniDexed::LoadPerformanceParameters(void)
m_pTG[nTG]->loadVoiceParameters(tVoiceData); m_pTG[nTG]->loadVoiceParameters(tVoiceData);
} }
setMonoMode(m_PerformanceConfig.GetMonoMode(nTG) ? 1 : 0, nTG); setMonoMode(m_PerformanceConfig.GetMonoMode(nTG) ? 1 : 0, nTG);
setEnabled(1, nTG);
SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG); SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG);
setModWheelRange (m_PerformanceConfig.GetModulationWheelRange (nTG), nTG); setModWheelRange (m_PerformanceConfig.GetModulationWheelRange (nTG), nTG);
@ -1985,6 +2023,8 @@ void CMiniDexed::LoadPerformanceParameters(void)
SetParameter (ParameterReverbLowPass, m_PerformanceConfig.GetReverbLowPass ()); SetParameter (ParameterReverbLowPass, m_PerformanceConfig.GetReverbLowPass ());
SetParameter (ParameterReverbDiffusion, m_PerformanceConfig.GetReverbDiffusion ()); SetParameter (ParameterReverbDiffusion, m_PerformanceConfig.GetReverbDiffusion ());
SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ()); SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ());
UpdateDAWState ();
} }
std::string CMiniDexed::GetNewPerformanceDefaultName(void) std::string CMiniDexed::GetNewPerformanceDefaultName(void)

@ -232,6 +232,11 @@ public:
void setMasterVolume (float32_t vol); void setMasterVolume (float32_t vol);
void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);
void UpdateDAWState ();
private: private:
int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note
uint8_t m_uchOPMask[CConfig::AllToneGenerators]; uint8_t m_uchOPMask[CConfig::AllToneGenerators];

@ -151,6 +151,9 @@ MIDIButtonActionTGUp=click
MIDIButtonTGDown=56 MIDIButtonTGDown=56
MIDIButtonActionTGDown=click MIDIButtonActionTGDown=click
# DAW Controller (Arturia MiniLab 3, KeyLab Essential, KeyLab Essential 3, Keylab mkII)
DAWControllerEnabled=0
# KY-040 Rotary Encoder # KY-040 Rotary Encoder
EncoderEnabled=1 EncoderEnabled=1
EncoderPinClock=10 EncoderPinClock=10

@ -18,6 +18,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
#include "uibuttons.h" #include "uibuttons.h"
#include "mididevice.h"
#include <circle/logger.h> #include <circle/logger.h>
#include <assert.h> #include <assert.h>
#include <circle/timer.h> #include <circle/timer.h>
@ -548,21 +549,20 @@ void CUIButtons::ResetButton (unsigned pinNumber)
} }
} }
void CUIButtons::BtnMIDICmdHandler (unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2) void CUIButtons::BtnMIDICmdHandler (unsigned nMidiType, unsigned nMidiData1, unsigned nMidiData2)
{ {
if (m_notesMidi > 0) { if (m_notesMidi > 0) {
// LOGDBG("BtnMIDICmdHandler (notes): %x %x %x)", nMidiCmd, nMidiData1, nMidiData2); // LOGDBG("BtnMIDICmdHandler (notes): %x %x %x)", nMidiType, nMidiData1, nMidiData2);
// Using MIDI Note messages for MIDI buttons // Using MIDI Note messages for MIDI buttons
unsigned midiPin = ccToMidiPin(nMidiData1); 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) {
if (nMidiCmd == 0x80) { if (nMidiType == MIDI_NOTE_OFF) {
// NoteOff = Button OFF
m_buttons[i].Write (0); m_buttons[i].Write (0);
} else if ((nMidiCmd == 0x90) && (nMidiData2 == 0)) { } else if ((nMidiType == MIDI_NOTE_ON) && (nMidiData2 == 0)) {
// NoteOn with Vel == 0 = Button OFF // NoteOn with Vel == 0 = Button OFF
m_buttons[i].Write (0); m_buttons[i].Write (0);
} else if (nMidiCmd == 0x90) { } else if (nMidiType == MIDI_NOTE_ON) {
// NoteOn = Button ON // NoteOn = Button ON
m_buttons[i].Write (127); m_buttons[i].Write (127);
} else { } else {
@ -571,9 +571,9 @@ void CUIButtons::BtnMIDICmdHandler (unsigned nMidiCmd, unsigned nMidiData1, unsi
} }
} }
} else { } else {
// LOGDBG("BtnMIDICmdHandler (CC): %x %x %x)", nMidiCmd, nMidiData1, nMidiData2); // LOGDBG("BtnMIDICmdHandler (CC): %x %x %x)", nMidiType, nMidiData1, nMidiData2);
// Using MIDI CC messages for MIDI buttons // Using MIDI CC messages for MIDI buttons
if (nMidiCmd == 0xB0) { // Control Message if (nMidiType == MIDI_CONTROL_CHANGE) { // Control Message
unsigned midiPin = ccToMidiPin(nMidiData1); 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) {

@ -542,7 +542,7 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event)
if (pUIMenu->m_pCurrentMenu) // if this is another menu? if (pUIMenu->m_pCurrentMenu) // if this is another menu?
{ {
bool bIsMainMenu = pUIMenu->m_pCurrentMenu == s_MainMenu; bool bIsMainMenu = pUIMenu->m_pCurrentMenu == s_MainMenu;
pUIMenu->m_pUI->DisplayWrite ( pUIMenu->m_pMiniDexed->DisplayWrite (
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
"", "",
pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name, pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name,
@ -595,7 +595,7 @@ void CUIMenu::EditGlobalParameter (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetGlobalValueString (Param, pUIMenu->m_pMiniDexed->GetParameter (Param)); string Value = GetGlobalValueString (Param, pUIMenu->m_pMiniDexed->GetParameter (Param));
pUIMenu->m_pUI->DisplayWrite (pMenuName, pUIMenu->m_pMiniDexed->DisplayWrite (pMenuName,
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum); nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -639,7 +639,7 @@ void CUIMenu::EditVoiceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = to_string (nValue+1) + "=" string Value = to_string (nValue+1) + "="
+ pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetBankName (nValue); + pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetBankName (nValue);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (), pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::MaxVoiceBankID); nValue > 0, nValue < (int) CSysExFileLoader::MaxVoiceBankID);
@ -709,7 +709,7 @@ void CUIMenu::EditProgramNumber (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = to_string (nValue+1) + "=" + pUIMenu->m_pMiniDexed->GetVoiceName (nTG); string Value = to_string (nValue+1) + "=" + pUIMenu->m_pMiniDexed->GetVoiceName (nTG);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (), pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::VoicesPerBank-1); nValue > 0, nValue < (int) CSysExFileLoader::VoicesPerBank-1);
@ -762,7 +762,7 @@ void CUIMenu::EditTGParameter (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG)); string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG));
pUIMenu->m_pUI->DisplayWrite (TG.c_str (), pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum); nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -815,7 +815,7 @@ void CUIMenu::EditTGParameter2 (CUIMenu *pUIMenu, TMenuEvent Event) // second me
string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG)); string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG));
pUIMenu->m_pUI->DisplayWrite (TG.c_str (), pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum); nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -868,7 +868,7 @@ void CUIMenu::EditVoiceParameter (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetVoiceValueString (nParam, nValue); string Value = GetVoiceValueString (nParam, nValue);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (), pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum); nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -971,7 +971,7 @@ void CUIMenu::EditOPParameter (CUIMenu *pUIMenu, TMenuEvent Event)
Value = GetOPValueString (nParam, nValue); Value = GetOPValueString (nParam, nValue);
} }
pUIMenu->m_pUI->DisplayWrite (OP.c_str (), pUIMenu->m_pMiniDexed->DisplayWrite (OP.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum); nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -990,7 +990,7 @@ void CUIMenu::SavePerformance (CUIMenu *pUIMenu, TMenuEvent Event)
pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth-1] pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth-1]
[pUIMenu->m_nMenuStackItem[pUIMenu->m_nCurrentMenuDepth-1]].Name; [pUIMenu->m_nMenuStackItem[pUIMenu->m_nCurrentMenuDepth-1]].Name;
pUIMenu->m_pUI->DisplayWrite (pMenuName, pUIMenu->m_pMiniDexed->DisplayWrite (pMenuName,
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
bOK ? "Completed" : "Error", bOK ? "Completed" : "Error",
false, false); false, false);
@ -1653,7 +1653,7 @@ void CUIMenu::PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event)
{ {
pUIMenu->m_nSelectedPerformanceID = 0; pUIMenu->m_nSelectedPerformanceID = 0;
pUIMenu->m_bConfirmDeletePerformance=false; pUIMenu->m_bConfirmDeletePerformance=false;
pUIMenu->m_pUI->DisplayWrite ("", "Delete", pUIMenu->m_pMiniDexed->DeletePerformance(nValue) ? "Completed" : "Error", false, false); pUIMenu->m_pMiniDexed->DisplayWrite ("", "Delete", pUIMenu->m_pMiniDexed->DeletePerformance(nValue) ? "Completed" : "Error", false, false);
pUIMenu->m_bSplashShow=true; pUIMenu->m_bSplashShow=true;
CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandlerNoBack, 0, pUIMenu); CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandlerNoBack, 0, pUIMenu);
return; return;
@ -1686,13 +1686,13 @@ void CUIMenu::PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event)
nPSelected += " [L]"; nPSelected += " [L]";
} }
pUIMenu->m_pUI->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(), pUIMenu->m_pMiniDexed->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(),
Value.c_str (), true, true); Value.c_str (), true, true);
// (int) nValue > 0, (int) nValue < (int) pUIMenu->m_pMiniDexed->GetLastPerformance()); // (int) nValue > 0, (int) nValue < (int) pUIMenu->m_pMiniDexed->GetLastPerformance());
} }
else else
{ {
pUIMenu->m_pUI->DisplayWrite ("", "Delete?", pUIMenu->m_bConfirmDeletePerformance ? "Yes" : "No", false, false); pUIMenu->m_pMiniDexed->DisplayWrite ("", "Delete?", pUIMenu->m_bConfirmDeletePerformance ? "Yes" : "No", false, false);
} }
} }
@ -1774,7 +1774,7 @@ void CUIMenu::EditPerformanceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
nPSelected += " [L]"; nPSelected += " [L]";
} }
pUIMenu->m_pUI->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(), pUIMenu->m_pMiniDexed->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(),
Value.c_str (), Value.c_str (),
nValue > 0, nValue > 0,
nValue < pUIMenu->m_pMiniDexed->GetLastPerformanceBank()-1); nValue < pUIMenu->m_pMiniDexed->GetLastPerformanceBank()-1);
@ -1887,7 +1887,7 @@ void CUIMenu::InputTxt (CUIMenu *pUIMenu, TMenuEvent Event)
pUIMenu->m_pMiniDexed->SetNewPerformanceName(pUIMenu->m_InputText); pUIMenu->m_pMiniDexed->SetNewPerformanceName(pUIMenu->m_InputText);
bOK = pUIMenu->m_pMiniDexed->SavePerformanceNewFile (); bOK = pUIMenu->m_pMiniDexed->SavePerformanceNewFile ();
MsgOk=bOK ? "Completed" : "Error"; MsgOk=bOK ? "Completed" : "Error";
pUIMenu->m_pUI->DisplayWrite (OkTitleR.c_str(), OkTitleL.c_str(), MsgOk.c_str(), false, false); pUIMenu->m_pMiniDexed->DisplayWrite (OkTitleR.c_str(), OkTitleL.c_str(), MsgOk.c_str(), false, false);
CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandler, 0, pUIMenu); CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandler, 0, pUIMenu);
return; return;
} }
@ -1938,7 +1938,7 @@ void CUIMenu::InputTxt (CUIMenu *pUIMenu, TMenuEvent Event)
} }
Value = Value + " " + escCursor ; Value = Value + " " + escCursor ;
pUIMenu->m_pUI->DisplayWrite (MenuTitleR.c_str(),MenuTitleL.c_str(), Value.c_str(), false, false); pUIMenu->m_pMiniDexed->DisplayWrite (MenuTitleR.c_str(),MenuTitleL.c_str(), Value.c_str(), false, false);
} }
@ -1992,7 +1992,7 @@ void CUIMenu::EditTGParameterModulation (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG)); string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG));
pUIMenu->m_pUI->DisplayWrite (TG.c_str (), pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (), Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum); nValue > rParam.Minimum, nValue < rParam.Maximum);

@ -162,16 +162,7 @@ bool CUserInterface::Initialize (void)
LOGDBG ("LCD initialized"); LOGDBG ("LCD initialized");
} }
m_pUIButtons = new CUIButtons ( m_pConfig ); InitButtonsWithConfig (m_pConfig);
assert (m_pUIButtons);
if (!m_pUIButtons->Initialize ())
{
return false;
}
m_pUIButtons->RegisterEventHandler (UIButtonsEventStub, this);
UISetMIDIButtonChannel (m_pConfig->GetMIDIButtonCh ());
LOGDBG ("Button User Interface initialized"); LOGDBG ("Button User Interface initialized");
@ -198,6 +189,17 @@ bool CUserInterface::Initialize (void)
return true; return true;
} }
void CUserInterface::InitButtonsWithConfig (CConfig *pConfig)
{
delete m_pUIButtons;
m_pUIButtons = new CUIButtons (pConfig);
assert (m_pUIButtons);
m_pUIButtons->Initialize ();
m_pUIButtons->RegisterEventHandler (UIButtonsEventStub, this);
UISetMIDIButtonChannel (pConfig->GetMIDIButtonCh ());
}
void CUserInterface::Process (void) void CUserInterface::Process (void)
{ {
if (m_pLCDBuffered) if (m_pLCDBuffered)
@ -396,7 +398,7 @@ void CUserInterface::UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam
pThis->UIButtonsEventHandler (Event); pThis->UIButtonsEventHandler (Event);
} }
void CUserInterface::UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2) void CUserInterface::UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiType, unsigned nMidiData1, unsigned nMidiData2)
{ {
if (m_nMIDIButtonCh == CMIDIDevice::Disabled) if (m_nMIDIButtonCh == CMIDIDevice::Disabled)
{ {
@ -411,7 +413,7 @@ void CUserInterface::UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsi
if (m_pUIButtons) if (m_pUIButtons)
{ {
m_pUIButtons->BtnMIDICmdHandler (nMidiCmd, nMidiData1, nMidiData2); m_pUIButtons->BtnMIDICmdHandler (nMidiType, nMidiData1, nMidiData2);
} }
} }

@ -57,6 +57,8 @@ public:
// 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 UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2); void UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2);
void InitButtonsWithConfig (CConfig *pConfig);
private: private:
void LCDWrite (const char *pString); // Print to optional HD44780 display void LCDWrite (const char *pString); // Print to optional HD44780 display

Loading…
Cancel
Save