From 72e1c6c9d37e206a40fae1cda816a31dfe5dbabf Mon Sep 17 00:00:00 2001
From: probonopd <probonopd@users.noreply.github.com>
Date: Mon, 14 Apr 2025 18:55:55 +0200
Subject: [PATCH] Voice Dump, Mute, Omni Mode via MIDI

Voice Dump Request via SysEx: MiniDexed now listens for the specific SysEx message (F0 43 20 00 F7) and sends the voice dump for the requested channel.

Mute Operator via SysEx: MiniDexed now handles the SysEx message for muting operators (F0 43 11 01 1B 2F F7) and toggles the mute state of the specified operator.

Omni Mode On/Off via MIDI CC: MIDI CC 124 and 125 are now handled to switch Omni Mode Off and On, respectively.
---
 src/mididevice.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/src/mididevice.cpp b/src/mididevice.cpp
index fefe9fc..e1f96dc 100644
--- a/src/mididevice.cpp
+++ b/src/mididevice.cpp
@@ -2,7 +2,7 @@
 // mididevice.cpp
 //
 // MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
-// Copyright (C) 2022  The MiniDexed Team
+// Copyright (C) 2022-25  The MiniDexed Team
 //
 // Original author of this class:
 //	R. Stange <rsta2@o2online.de>
@@ -51,6 +51,8 @@ LOGMODULE ("mididevice");
 	#define MIDI_CC_DETUNE_LEVEL		94
 	#define MIDI_CC_ALL_SOUND_OFF		120
 	#define MIDI_CC_ALL_NOTES_OFF		123
+	#define MIDI_CC_OMNI_MODE_OFF		124
+	#define MIDI_CC_OMNI_MODE_ON		125
 #define MIDI_PROGRAM_CHANGE	0b1100
 #define MIDI_PITCH_BEND		0b1110
 
@@ -265,6 +267,30 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
 	}
 	else
 	{
+			// Add handling for Voice Dump Request SysEx
+		if (nLength == 5 &&
+			pMessage[0] == MIDI_SYSTEM_EXCLUSIVE_BEGIN &&
+			pMessage[1] == 0x43 &&
+			(pMessage[2] & 0xF0) == 0x20 && // Check for Yamaha SysEx with channel
+			pMessage[3] == 0x00 &&
+			pMessage[4] == MIDI_SYSTEM_EXCLUSIVE_END) {
+			LOGDBG("Voice Dump Request received for channel %d", pMessage[2] & 0x0F);
+			SendSystemExclusiveVoice(0, nCable, pMessage[2] & 0x0F); // Send voice dump for the requested channel
+			return;
+		}
+
+		// Add handling for Mute Operator SysEx
+		if (nLength == 7 &&
+			pMessage[0] == MIDI_SYSTEM_EXCLUSIVE_BEGIN &&
+			pMessage[1] == 0x43 &&
+			pMessage[3] == 0x1B &&
+			pMessage[4] == 0x2F &&
+			pMessage[6] == MIDI_SYSTEM_EXCLUSIVE_END) {
+			LOGDBG("Mute Operator SysEx received: Operator %d, Value %d", pMessage[4], pMessage[5]);
+			m_pSynthesizer->setOperatorMute(pMessage[5], nTG); // Implement this function in the synthesizer
+			return;
+		}
+
 		// Perform any MiniDexed level MIDI handling before specific Tone Generators
 		unsigned nPerfCh = m_pSynthesizer->GetPerformanceSelectChannel();
 		switch (ucType)
@@ -476,6 +502,20 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
 							}
 							break;
 
+						case MIDI_CC_OMNI_MODE_OFF:
+							// Sets to "Omni Off" mode
+							if (m_ChannelMap[nTG] == OmniMode) {
+								m_pSynthesizer->SetMIDIChannel(ucChannel, nTG);
+								LOGDBG("Omni Mode Off: TG %d set to MIDI channel %d", nTG, ucChannel+1);
+							}
+							break;
+						
+						case MIDI_CC_OMNI_MODE_ON:
+							// Sets to "Omni On" mode
+							m_pSynthesizer->SetMIDIChannel(OmniMode, nTG);
+							LOGDBG("Omni Mode On: TG %d set to OMNI", nTG);
+							break;
+
 						default:
 							// Check for system-level, cross-TG MIDI Controls, but only do it once.
 							// Also, if successfully handled, then no need to process other TGs,
@@ -720,4 +760,4 @@ void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable
     Iterator->second->Send (voicedump, sizeof(voicedump)*sizeof(uint8_t));
     // LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str());
   }
-} 
+}