diff --git a/src/config.cpp b/src/config.cpp index d8ba0cf..c12e195 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -48,6 +48,26 @@ void CConfig::Load (void) m_nMIDIBaudRate = m_Properties.GetNumber ("MIDIBaudRate", 31250); + const char *pMIDIThrough = m_Properties.GetString ("MIDIThrough"); + if (pMIDIThrough) + { + std::string Arg (pMIDIThrough); + + size_t nPos = Arg.find (','); + if (nPos != std::string::npos) + { + m_MIDIThroughIn = Arg.substr (0, nPos); + m_MIDIThroughOut = Arg.substr (nPos+1); + + if ( m_MIDIThroughIn.empty () + || m_MIDIThroughOut.empty ()) + { + m_MIDIThroughIn.clear (); + m_MIDIThroughOut.clear (); + } + } + } + m_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0; m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 17); m_nLCDPinRegisterSelect = m_Properties.GetNumber ("LCDPinRegisterSelect", 27); @@ -96,6 +116,16 @@ unsigned CConfig::GetMIDIBaudRate (void) const return m_nMIDIBaudRate; } +const char *CConfig::GetMIDIThroughIn (void) const +{ + return m_MIDIThroughIn.c_str (); +} + +const char *CConfig::GetMIDIThroughOut (void) const +{ + return m_MIDIThroughOut.c_str (); +} + bool CConfig::GetLCDEnabled (void) const { return m_bLCDEnabled; diff --git a/src/config.h b/src/config.h index 2b24ffc..1c24c8e 100644 --- a/src/config.h +++ b/src/config.h @@ -71,6 +71,8 @@ public: // MIDI unsigned GetMIDIBaudRate (void) const; + const char *GetMIDIThroughIn (void) const; // "" if not specified + const char *GetMIDIThroughOut (void) const; // "" if not specified // HD44780 LCD // GPIO pin numbers are chip numbers, not header positions @@ -104,6 +106,8 @@ private: bool m_bChannelsSwapped; unsigned m_nMIDIBaudRate; + std::string m_MIDIThroughIn; + std::string m_MIDIThroughOut; bool m_bLCDEnabled; unsigned m_nLCDPinEnable; diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 45c2342..494acb1 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -48,6 +48,8 @@ #define MIDI_TIMING_CLOCK 0xF8 #define MIDI_ACTIVE_SENSING 0xFE +CMIDIDevice::TDeviceMap CMIDIDevice::s_DeviceMap; + CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig) : m_pSynthesizer (pSynthesizer), m_pConfig (pConfig) @@ -107,6 +109,18 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign } } + // handle MIDI through + if (m_DeviceName.compare (m_pConfig->GetMIDIThroughIn ()) == 0) + { + TDeviceMap::const_iterator Iterator; + + Iterator = s_DeviceMap.find (m_pConfig->GetMIDIThroughOut ()); + if (Iterator != s_DeviceMap.end ()) + { + Iterator->second->Send (pMessage, nLength, nCable); + } + } + if (nLength < 2) { return; @@ -230,3 +244,14 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign } } } + +void CMIDIDevice::AddDevice (const char *pDeviceName) +{ + assert (pDeviceName); + + assert (m_DeviceName.empty ()); + m_DeviceName = pDeviceName; + assert (!m_DeviceName.empty ()); + + s_DeviceMap.insert (std::pair (pDeviceName, this)); +} diff --git a/src/mididevice.h b/src/mididevice.h index 166351d..d4e3079 100644 --- a/src/mididevice.h +++ b/src/mididevice.h @@ -24,6 +24,8 @@ #define _mididevice_h #include "config.h" +#include +#include #include class CMiniDexed; @@ -41,19 +43,28 @@ public: public: CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig); - ~CMIDIDevice (void); + virtual ~CMIDIDevice (void); void SetChannel (u8 ucChannel, unsigned nTG); u8 GetChannel (unsigned nTG) const; + virtual void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) {} + protected: void MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsigned nCable = 0); + void AddDevice (const char *pDeviceName); + private: CMiniDexed *m_pSynthesizer; CConfig *m_pConfig; u8 m_ChannelMap[CConfig::ToneGenerators]; + + std::string m_DeviceName; + + typedef std::unordered_map TDeviceMap; + static TDeviceMap s_DeviceMap; }; #endif diff --git a/src/midikeyboard.cpp b/src/midikeyboard.cpp index 240d0b3..054352c 100644 --- a/src/midikeyboard.cpp +++ b/src/midikeyboard.cpp @@ -22,6 +22,7 @@ // #include "midikeyboard.h" #include +#include #include CMIDIKeyboard *CMIDIKeyboard::s_pThis[MaxInstances] = {0}; @@ -43,6 +44,8 @@ CMIDIKeyboard::CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, unsign s_pThis[m_nInstance] = this; m_DeviceName.Format ("umidi%u", nInstance+1); + + AddDevice (m_DeviceName); } CMIDIKeyboard::~CMIDIKeyboard (void) @@ -53,6 +56,19 @@ CMIDIKeyboard::~CMIDIKeyboard (void) void CMIDIKeyboard::Process (boolean bPlugAndPlayUpdated) { + while (!m_SendQueue.empty ()) + { + TSendQueueEntry Entry = m_SendQueue.front (); + m_SendQueue.pop (); + + if (m_pMIDIDevice) + { + m_pMIDIDevice->SendPlainMIDI (Entry.nCable, Entry.pMessage, Entry.nLength); + } + + delete [] Entry.pMessage; + } + if (!bPlugAndPlayUpdated) { return; @@ -72,6 +88,18 @@ void CMIDIKeyboard::Process (boolean bPlugAndPlayUpdated) } } +void CMIDIKeyboard::Send (const u8 *pMessage, size_t nLength, unsigned nCable) +{ + TSendQueueEntry Entry; + Entry.pMessage = new u8[nLength]; + Entry.nLength = nLength; + Entry.nCable = nCable; + + memcpy (Entry.pMessage, pMessage, nLength); + + m_SendQueue.push (Entry); +} + void CMIDIKeyboard::MIDIPacketHandler0 (unsigned nCable, u8 *pPacket, unsigned nLength) { assert (s_pThis[0] != 0); diff --git a/src/midikeyboard.h b/src/midikeyboard.h index 386d83b..a530c25 100644 --- a/src/midikeyboard.h +++ b/src/midikeyboard.h @@ -29,6 +29,7 @@ #include #include #include +#include class CMiniDexed; @@ -43,6 +44,8 @@ public: void Process (boolean bPlugAndPlayUpdated); + void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) override; + private: static void MIDIPacketHandler0 (unsigned nCable, u8 *pPacket, unsigned nLength); static void MIDIPacketHandler1 (unsigned nCable, u8 *pPacket, unsigned nLength); @@ -51,12 +54,22 @@ private: static void DeviceRemovedHandler (CDevice *pDevice, void *pContext); +private: + struct TSendQueueEntry + { + u8 *pMessage; + size_t nLength; + unsigned nCable; + }; + private: unsigned m_nInstance; CString m_DeviceName; CUSBMIDIDevice * volatile m_pMIDIDevice; + std::queue m_SendQueue; + static CMIDIKeyboard *s_pThis[MaxInstances]; static TMIDIPacketHandler * const s_pMIDIPacketHandler[MaxInstances]; diff --git a/src/minidexed.ini b/src/minidexed.ini index 4ecc003..4cb8a5f 100644 --- a/src/minidexed.ini +++ b/src/minidexed.ini @@ -13,6 +13,7 @@ ChannelsSwapped=0 # MIDI MIDIBaudRate=31250 +#MIDIThrough=umidi1,ttyS1 # HD44780 LCD LCDEnabled=1 diff --git a/src/pckeyboard.cpp b/src/pckeyboard.cpp index a3f6878..fbd8ea5 100644 --- a/src/pckeyboard.cpp +++ b/src/pckeyboard.cpp @@ -67,6 +67,8 @@ CPCKeyboard::CPCKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig) s_pThis = this; memset (m_LastKeys, 0, sizeof m_LastKeys); + + AddDevice ("ukbd1"); } CPCKeyboard::~CPCKeyboard (void) diff --git a/src/serialmididevice.cpp b/src/serialmididevice.cpp index cd7ad47..2c11a33 100644 --- a/src/serialmididevice.cpp +++ b/src/serialmididevice.cpp @@ -28,8 +28,10 @@ CSerialMIDIDevice::CSerialMIDIDevice (CMiniDexed *pSynthesizer, CInterruptSystem : CMIDIDevice (pSynthesizer, pConfig), m_pConfig (pConfig), m_Serial (pInterrupt, TRUE), - m_nSerialState (0) + m_nSerialState (0), + m_SendBuffer (&m_Serial) { + AddDevice ("ttyS1"); } CSerialMIDIDevice::~CSerialMIDIDevice (void) @@ -45,6 +47,8 @@ boolean CSerialMIDIDevice::Initialize (void) void CSerialMIDIDevice::Process (void) { + m_SendBuffer.Update (); + // Read serial MIDI data u8 Buffer[100]; int nResult = m_Serial.Read (Buffer, sizeof Buffer); @@ -96,3 +100,8 @@ void CSerialMIDIDevice::Process (void) } } } + +void CSerialMIDIDevice::Send (const u8 *pMessage, size_t nLength, unsigned nCable) +{ + m_SendBuffer.Write (pMessage, nLength); +} diff --git a/src/serialmididevice.h b/src/serialmididevice.h index 82c2618..0e6d9f5 100644 --- a/src/serialmididevice.h +++ b/src/serialmididevice.h @@ -27,6 +27,7 @@ #include "config.h" #include #include +#include #include class CMiniDexed; @@ -41,12 +42,16 @@ public: void Process (void); + void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) override; + private: CConfig *m_pConfig; CSerialDevice m_Serial; unsigned m_nSerialState; u8 m_SerialMessage[3]; + + CWriteBufferDevice m_SendBuffer; }; #endif