Skip to content

Commit

Permalink
add DAW Display support for newer Arturia Keyboards with Display
Browse files Browse the repository at this point in the history
based on https://github.com/PrzemekBarski/arturia-keylab-essential-mk3-programming-guide

Tested on a Arturia MiniLab 3

Probably works also on Keylab Essential mk3 / Keylab mk3
  • Loading branch information
soyersoyer committed Nov 7, 2024
1 parent a4dcd4d commit 0211e16
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 16 deletions.
7 changes: 7 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ void CConfig::Load (void)
m_MIDIButtonActionTGUp = m_Properties.GetString ("MIDIButtonActionTGUp", "");
m_MIDIButtonActionTGDown = m_Properties.GetString ("MIDIButtonActionTGDown", "");

m_bDAWDisplayArturiaEnabled = m_Properties.GetNumber ("DAWDisplayArturiaEnabled", 0) != 0;

m_bEncoderEnabled = m_Properties.GetNumber ("EncoderEnabled", 0) != 0;
m_nEncoderPinClock = m_Properties.GetNumber ("EncoderPinClock", 10);
m_nEncoderPinData = m_Properties.GetNumber ("EncoderPinData", 9);
Expand Down Expand Up @@ -703,6 +705,11 @@ const char *CConfig::GetMIDIButtonActionTGDown (void) const
return m_MIDIButtonActionTGDown.c_str();
}

bool CConfig::GetDAWDisplayArturiaEnabled (void) const
{
return m_bDAWDisplayArturiaEnabled;
}

bool CConfig::GetEncoderEnabled (void) const
{
return m_bEncoderEnabled;
Expand Down
4 changes: 4 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ class CConfig // Configuration for MiniDexed
const char *GetMIDIButtonActionTGUp (void) const;
const char *GetMIDIButtonActionTGDown (void) const;

bool GetDAWDisplayArturiaEnabled (void) const;

// KY-040 Rotary Encoder
// GPIO pin numbers are chip numbers, not header positions
bool GetEncoderEnabled (void) const;
Expand Down Expand Up @@ -355,6 +357,8 @@ class CConfig // Configuration for MiniDexed
std::string m_MIDIButtonActionTGUp;
std::string m_MIDIButtonActionTGDown;

bool m_bDAWDisplayArturiaEnabled;

bool m_bEncoderEnabled;
unsigned m_nEncoderPinClock;
unsigned m_nEncoderPinData;
Expand Down
57 changes: 57 additions & 0 deletions src/midikeyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ CMIDIKeyboard::CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserI
: CMIDIDevice (pSynthesizer, pConfig, pUI),
m_nSysExIdx (0),
m_nInstance (nInstance),
m_bDAWDisplayArturiaEnabled (pConfig->GetDAWDisplayArturiaEnabled ()),
m_bDAWDisplayInitialized (false),
m_pMIDIDevice (0)
{
assert (m_nInstance < MaxInstances);
Expand Down Expand Up @@ -87,6 +89,8 @@ void CMIDIKeyboard::Process (boolean bPlugAndPlayUpdated)
m_pMIDIDevice->RegisterRemovedHandler (DeviceRemovedHandler, this);
}
}

m_bDAWDisplayInitialized = false;
}

void CMIDIKeyboard::Send (const u8 *pMessage, size_t nLength, unsigned nCable)
Expand Down Expand Up @@ -190,3 +194,56 @@ void CMIDIKeyboard::DeviceRemovedHandler (CDevice *pDevice, void *pContext)

pThis->m_pMIDIDevice = 0;
}

void CMIDIKeyboard::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp)
{
if (!m_bDAWDisplayArturiaEnabled)
return;

static unsigned L1MaxLen = 18;
static const uint8_t connect[] = {0xF0, 0x00, 0x20, 0x6B, 0x7F, 0x42, 0x02, 0x00, 0x40, 0x6A, 0x21, 0xF7};
static const uint8_t linesHdr[] = {0xF0, 0x00, 0x20, 0x6B, 0x7F, 0x42, 0x04, 0x02, 0x60, 0x12, 0x01};

CString line1 (pParam);
CString line2 (pValue);

size_t nLen = strlen (pParam) + strlen (pMenu);
if (nLen < L1MaxLen)
{
for (unsigned i = L1MaxLen - nLen; i > 0; i--)
{
line1.Append (" ");
}
}

line1.Append (pMenu);

int hdrLen = sizeof linesHdr;
int line1Len = strlen (line1);
int line2Len = strlen (line2);
int offset = 0;

uint8_t lines[hdrLen + line1Len + 2 + line2Len + 2];

memcpy (lines, linesHdr, hdrLen);
offset += hdrLen;

memcpy (&lines[offset], line1, line1Len + 1);
offset += line1Len + 1;

lines[offset] = 0x02;
offset += 1;

memcpy (&lines[offset], line2, line2Len + 1);
offset += line2Len + 1;

lines[offset] = 0xf7;
offset += 1;

if (!m_bDAWDisplayInitialized) {
Send (connect, sizeof connect, 0);
m_bDAWDisplayInitialized = true;
}
Send (lines, offset, 0);
}
5 changes: 5 additions & 0 deletions src/midikeyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class CMIDIKeyboard : public CMIDIDevice

void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) override;

void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);

private:
static void MIDIPacketHandler0 (unsigned nCable, u8 *pPacket, unsigned nLength);
static void MIDIPacketHandler1 (unsigned nCable, u8 *pPacket, unsigned nLength);
Expand All @@ -70,6 +73,8 @@ class CMIDIKeyboard : public CMIDIDevice

private:
unsigned m_nInstance;
bool m_bDAWDisplayArturiaEnabled;
bool m_bDAWDisplayInitialized;
CString m_DeviceName;

CUSBMIDIDevice * volatile m_pMIDIDevice;
Expand Down
11 changes: 11 additions & 0 deletions src/minidexed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,17 @@ void CMiniDexed::setMasterVolume (float32_t 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);
}
}

std::string CMiniDexed::GetPerformanceFileName(unsigned nID)
{
return m_PerformanceConfig.GetPerformanceFileName(nID);
Expand Down
3 changes: 3 additions & 0 deletions src/minidexed.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ class CMiniDexed

void setMasterVolume (float32_t vol);

void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);

private:
int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note
uint8_t m_uchOPMask[CConfig::AllToneGenerators];
Expand Down
3 changes: 3 additions & 0 deletions src/minidexed.ini
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ MIDIButtonActionTGUp=
MIDIButtonTGDown=0
MIDIButtonActionTGDown=

# DAW Display (Arturia MiniLab 3 or other newer Arturias)
DAWDisplayArturiaEnabled=0

# KY-040 Rotary Encoder
EncoderEnabled=1
EncoderPinClock=10
Expand Down
32 changes: 16 additions & 16 deletions src/uimenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event)

if (pUIMenu->m_pCurrentMenu) // if this is another menu?
{
pUIMenu->m_pUI->DisplayWrite (
pUIMenu->m_pMiniDexed->DisplayWrite (
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
"",
pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name,
Expand Down Expand Up @@ -587,7 +587,7 @@ void CUIMenu::EditGlobalParameter (CUIMenu *pUIMenu, TMenuEvent Event)

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,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
Expand Down Expand Up @@ -631,7 +631,7 @@ void CUIMenu::EditVoiceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = to_string (nValue+1) + "="
+ 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,
Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::MaxVoiceBankID);
Expand Down Expand Up @@ -701,7 +701,7 @@ void CUIMenu::EditProgramNumber (CUIMenu *pUIMenu, TMenuEvent Event)

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,
Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::VoicesPerBank-1);
Expand Down Expand Up @@ -754,7 +754,7 @@ void CUIMenu::EditTGParameter (CUIMenu *pUIMenu, TMenuEvent Event)

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,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
Expand Down Expand Up @@ -807,7 +807,7 @@ void CUIMenu::EditTGParameter2 (CUIMenu *pUIMenu, TMenuEvent Event) // second me

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,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
Expand Down Expand Up @@ -860,7 +860,7 @@ void CUIMenu::EditVoiceParameter (CUIMenu *pUIMenu, TMenuEvent Event)

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,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
Expand Down Expand Up @@ -963,7 +963,7 @@ void CUIMenu::EditOPParameter (CUIMenu *pUIMenu, TMenuEvent Event)
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,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
Expand All @@ -982,7 +982,7 @@ void CUIMenu::SavePerformance (CUIMenu *pUIMenu, TMenuEvent Event)
pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth-1]
[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,
bOK ? "Completed" : "Error",
false, false);
Expand Down Expand Up @@ -1564,7 +1564,7 @@ void CUIMenu::PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event)
{
pUIMenu->m_nSelectedPerformanceID = 0;
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;
CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandlerNoBack, 0, pUIMenu);
return;
Expand Down Expand Up @@ -1597,13 +1597,13 @@ void CUIMenu::PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event)
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);
// (int) nValue > 0, (int) nValue < (int) pUIMenu->m_pMiniDexed->GetLastPerformance());
}
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);
}
}

Expand Down Expand Up @@ -1685,7 +1685,7 @@ void CUIMenu::EditPerformanceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
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 (),
nValue > 0,
nValue < pUIMenu->m_pMiniDexed->GetLastPerformanceBank()-1);
Expand Down Expand Up @@ -1798,7 +1798,7 @@ void CUIMenu::InputTxt (CUIMenu *pUIMenu, TMenuEvent Event)
pUIMenu->m_pMiniDexed->SetNewPerformanceName(pUIMenu->m_InputText);
bOK = pUIMenu->m_pMiniDexed->SavePerformanceNewFile ();
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);
return;
}
Expand Down Expand Up @@ -1849,7 +1849,7 @@ void CUIMenu::InputTxt (CUIMenu *pUIMenu, TMenuEvent Event)
}

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);


}
Expand Down Expand Up @@ -1903,7 +1903,7 @@ void CUIMenu::EditTGParameterModulation (CUIMenu *pUIMenu, TMenuEvent Event)

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,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
Expand Down

0 comments on commit 0211e16

Please sign in to comment.