1
0

MIDIMapping.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * MIDIMapping.h
  3. * -------------
  4. * Purpose: MIDI Mapping management classes
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include <vector>
  12. #include <algorithm>
  13. #include "../common/FileReaderFwd.h"
  14. OPENMPT_NAMESPACE_BEGIN
  15. class CMIDIMappingDirective
  16. {
  17. public:
  18. CMIDIMappingDirective()
  19. : m_Active(true), m_CaptureMIDI(false), m_AllowPatternEdit(true), m_AnyChannel(true)
  20. {
  21. }
  22. void SetActive(const bool b) { m_Active = b; }
  23. bool IsActive() const { return m_Active; }
  24. void SetCaptureMIDI(const bool b) { m_CaptureMIDI = b; }
  25. bool GetCaptureMIDI() const { return m_CaptureMIDI; }
  26. void SetAllowPatternEdit(const bool b) { m_AllowPatternEdit = b; }
  27. bool GetAllowPatternEdit() const { return m_AllowPatternEdit; }
  28. bool GetAnyChannel() const { return m_AnyChannel; }
  29. //Note: In these functions, channel value is in range [1,16],
  30. //GetChannel() returns 0 on 'any channel'.
  31. void SetChannel(const int c) { if(c < 1 || c > 16) m_AnyChannel = true; else { m_ChnEvent &= ~0x0F; m_ChnEvent |= c - 1; m_AnyChannel = false; } }
  32. uint8 GetChannel() const {return (m_AnyChannel) ? 0 : (m_ChnEvent & 0xF) + 1;}
  33. void SetEvent(uint8 e) { if(e > 15) e = 15; m_ChnEvent &= ~0xF0; m_ChnEvent |= (e << 4); }
  34. uint8 GetEvent() const {return (m_ChnEvent >> 4) & 0x0F;}
  35. void SetController(int controller) { if(controller > 127) controller = 127; m_MIDIByte1 = static_cast<uint8>(controller); }
  36. uint8 GetController() const { return m_MIDIByte1; }
  37. //Note: Plug index starts from 1.
  38. void SetPlugIndex(const int i) { m_PluginIndex = static_cast<PLUGINDEX>(i); }
  39. PLUGINDEX GetPlugIndex() const { return m_PluginIndex; }
  40. void SetParamIndex(const int i) { m_Parameter = i; }
  41. uint32 GetParamIndex() const { return m_Parameter; }
  42. bool IsDefault() const { return *this == CMIDIMappingDirective{}; }
  43. bool operator==(const CMIDIMappingDirective &other) const { return memcmp(this, &other, sizeof(*this)) == 0; }
  44. bool operator<(const CMIDIMappingDirective &other) const { return GetController() < other.GetController(); }
  45. uint8 GetChnEvent() const {return m_ChnEvent;}
  46. private:
  47. uint32 m_Parameter = 0;
  48. PLUGINDEX m_PluginIndex = 1;
  49. uint8 m_MIDIByte1 = 0;
  50. uint8 m_ChnEvent = (0xB << 4); // 0-3 channel, 4-7 event
  51. bool m_Active : 1;
  52. bool m_CaptureMIDI : 1; // When true, MIDI data should not be processed beyond this directive
  53. bool m_AllowPatternEdit : 1; // When true, the mapping can be used for modifying pattern.
  54. bool m_AnyChannel : 1;
  55. };
  56. class CSoundFile;
  57. class CMIDIMapper
  58. {
  59. public:
  60. CMIDIMapper(CSoundFile& sndfile) : m_rSndFile(sndfile) {}
  61. // If mapping found:
  62. // - mappedIndex is set to mapped value(plug index)
  63. // - paramindex to mapped parameter
  64. // - paramvalue to parameter value.
  65. // In case of multiple mappings, these get the values from the last mapping found.
  66. // Returns true if MIDI was 'captured' by some directive, false otherwise.
  67. bool OnMIDImsg(const DWORD midimsg, PLUGINDEX &mappedIndex, PlugParamIndex &paramindex, uint16 &paramvalue);
  68. // Swaps the positions of two elements.
  69. void Swap(const size_t a, const size_t b);
  70. // Return the index after sorting for the added element
  71. size_t SetDirective(const size_t i, const CMIDIMappingDirective& d) { m_Directives[i] = d; Sort(); return std::find(m_Directives.begin(), m_Directives.end(), d) - m_Directives.begin(); }
  72. // Return the index after sorting for the added element
  73. size_t AddDirective(const CMIDIMappingDirective& d) { m_Directives.push_back(d); Sort(); return std::find(m_Directives.begin(), m_Directives.end(), d) - m_Directives.begin(); }
  74. void RemoveDirective(const size_t i) { m_Directives.erase(m_Directives.begin() + i); }
  75. const CMIDIMappingDirective &GetDirective(const size_t i) const { return m_Directives[i]; }
  76. size_t GetCount() const { return m_Directives.size(); }
  77. // Serialize to file, or just return the serialization size if no file handle is provided.
  78. size_t Serialize(std::ostream *file = nullptr) const;
  79. // Deserialize MIDI Mappings from file. Returns true if no errors were encountered.
  80. bool Deserialize(FileReader &file);
  81. bool AreOrderEqual(const size_t a, const size_t b) const { return !(m_Directives[a] < m_Directives[b] || m_Directives[b] < m_Directives[a]); }
  82. private:
  83. void Sort() { std::stable_sort(m_Directives.begin(), m_Directives.end()); }
  84. private:
  85. CSoundFile &m_rSndFile;
  86. std::vector<CMIDIMappingDirective> m_Directives;
  87. uint16 m_lastCCvalue = 0;
  88. uint8 m_lastCC = uint8_max;
  89. };
  90. OPENMPT_NAMESPACE_END