aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/mptrack/MIDIMapping.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/mptrack/MIDIMapping.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/mptrack/MIDIMapping.cpp')
-rw-r--r--Src/external_dependencies/openmpt-trunk/mptrack/MIDIMapping.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/mptrack/MIDIMapping.cpp b/Src/external_dependencies/openmpt-trunk/mptrack/MIDIMapping.cpp
new file mode 100644
index 00000000..0364fc4a
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/mptrack/MIDIMapping.cpp
@@ -0,0 +1,172 @@
+/*
+ * MIDIMapping.cpp
+ * ---------------
+ * Purpose: MIDI Mapping management classes
+ * Notes : (currently none)
+ * Authors: OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+
+#include "stdafx.h"
+#include "Moddoc.h"
+#include "MIDIMapping.h"
+#include "../common/FileReader.h"
+#include "../soundlib/MIDIEvents.h"
+#include "../soundlib/plugins/PlugInterface.h"
+#include "mpt/io/io.hpp"
+#include "mpt/io/io_stdstream.hpp"
+
+
+OPENMPT_NAMESPACE_BEGIN
+
+
+size_t CMIDIMapper::Serialize(std::ostream *file) const
+{
+ //Bytes: 1 Flags, 2 key, 1 plugindex, 1,2,4,8 plug/etc.
+ size_t size = 0;
+ for(const auto &d : m_Directives)
+ {
+ uint16 temp16 = (d.GetChnEvent() << 1) + (d.GetController() << 9);
+ if(d.GetAnyChannel()) temp16 |= 1;
+ uint32 temp32 = d.GetParamIndex();
+
+ uint8 temp8 = d.IsActive(); //bit 0
+ if(d.GetCaptureMIDI()) temp8 |= (1 << 1); //bit 1
+ //bits 2-4: Mapping type: 0 for plug param control.
+ //bit 5:
+ if(d.GetAllowPatternEdit()) temp8 |= (1 << 5);
+ //bits 6-7: Size: 5, 6, 8, 12
+
+ uint8 parambytes = 4;
+ if(temp32 <= uint16_max)
+ {
+ if(temp32 <= uint8_max) parambytes = 1;
+ else {parambytes = 2; temp8 |= (1 << 6);}
+ }
+ else temp8 |= (2 << 6);
+
+ if(file)
+ {
+ std::ostream & f = *file;
+ mpt::IO::WriteIntLE<uint8>(f, temp8);
+ mpt::IO::WriteIntLE<uint16>(f, temp16);
+ mpt::IO::WriteIntLE<uint8>(f, d.GetPlugIndex());
+ mpt::IO::WritePartial<uint32le>(f, mpt::as_le(temp32), parambytes);
+ }
+ size += sizeof(temp8) + sizeof(temp16) + sizeof(temp8) + parambytes;
+ }
+ return size;
+}
+
+
+bool CMIDIMapper::Deserialize(FileReader &file)
+{
+ m_Directives.clear();
+ while(file.CanRead(1))
+ {
+ uint8 i8 = file.ReadUint8();
+ uint8 psize = 0;
+ // Determine size of this event (depends on size of plugin parameter index)
+ switch(i8 >> 6)
+ {
+ case 0: psize = 4; break;
+ case 1: psize = 5; break;
+ case 2: psize = 7; break;
+ case 3: default: psize = 11; break;
+ }
+
+ if(!file.CanRead(psize)) return false;
+ if(((i8 >> 2) & 7) != 0) { file.Skip(psize); continue;} //Skipping unrecognised mapping types.
+
+ CMIDIMappingDirective s;
+ s.SetActive((i8 & 1) != 0);
+ s.SetCaptureMIDI((i8 & (1 << 1)) != 0);
+ s.SetAllowPatternEdit((i8 & (1 << 5)) != 0);
+ uint16 i16 = file.ReadUint16LE(); //Channel, event, MIDIbyte1.
+ i8 = file.ReadUint8(); //Plugindex
+ uint32le i32;
+ file.ReadStructPartial(i32, psize - 3);
+
+ s.SetChannel(((i16 & 1) != 0) ? 0 : 1 + ((i16 >> 1) & 0xF));
+ s.SetEvent(static_cast<uint8>((i16 >> 5) & 0xF));
+ s.SetController(i16 >> 9);
+ s.SetPlugIndex(i8);
+ s.SetParamIndex(i32);
+ AddDirective(s);
+ }
+
+ return true;
+}
+
+
+bool CMIDIMapper::OnMIDImsg(const DWORD midimsg, PLUGINDEX &mappedIndex, PlugParamIndex &paramindex, uint16 &paramval)
+{
+ const MIDIEvents::EventType eventType = MIDIEvents::GetTypeFromEvent(midimsg);
+ const uint8 controller = MIDIEvents::GetDataByte1FromEvent(midimsg);
+ const uint8 channel = MIDIEvents::GetChannelFromEvent(midimsg) & 0x7F;
+ const uint8 controllerVal = MIDIEvents::GetDataByte2FromEvent(midimsg) & 0x7F;
+
+ for(const auto &d : m_Directives)
+ {
+ if(!d.IsActive()) continue;
+ if(d.GetEvent() != eventType) continue;
+ if(eventType == MIDIEvents::evControllerChange
+ && d.GetController() != controller
+ && (d.GetController() >= 32 || d.GetController() + 32 != controller))
+ continue;
+ if(!d.GetAnyChannel() && channel + 1 != d.GetChannel()) continue;
+
+ const PLUGINDEX plugindex = d.GetPlugIndex();
+ const uint32 param = d.GetParamIndex();
+ uint16 val = (d.GetEvent() == MIDIEvents::evChannelAftertouch ? controller : controllerVal) << 7;
+
+ if(eventType == MIDIEvents::evControllerChange)
+ {
+ // Fine (0...31) / Coarse (32...63) controller pairs - Fine should be sent first.
+ if(controller == m_lastCC + 32 && m_lastCC < 32)
+ {
+ val = (val >> 7) | m_lastCCvalue;
+ }
+ m_lastCC = controller;
+ m_lastCCvalue = val;
+ }
+
+ if(d.GetAllowPatternEdit())
+ {
+ mappedIndex = plugindex;
+ paramindex = param;
+ paramval = val;
+ }
+
+ if(plugindex > 0 && plugindex <= MAX_MIXPLUGINS)
+ {
+#ifndef NO_PLUGINS
+ IMixPlugin *pPlug = m_rSndFile.m_MixPlugins[plugindex - 1].pMixPlugin;
+ if(!pPlug) continue;
+ pPlug->SetParameter(param, val / 16383.0f);
+ if(m_rSndFile.GetpModDoc() != nullptr)
+ m_rSndFile.GetpModDoc()->SetModified();
+#endif // NO_PLUGINS
+ }
+ if(d.GetCaptureMIDI())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+void CMIDIMapper::Swap(const size_t a, const size_t b)
+{
+ if(a < m_Directives.size() && b < m_Directives.size())
+ {
+ std::swap(m_Directives[a], m_Directives[b]);
+ Sort();
+ }
+}
+
+
+OPENMPT_NAMESPACE_END