Deluge Firmware 1.3.0
Build date: 2025.12.17
Loading...
Searching...
No Matches
midi_device.h
1/*
2 * Copyright © 2021-2023 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "definitions_cxx.hpp"
21#include "model/midi/message.h"
22#include "model/model_stack.h"
23#include "util/d_string.h"
24#include <array>
25
26// These numbers are what get stored just in the internal Deluge flash memory to represent things.
27#define VENDOR_ID_NONE 0
28#define VENDOR_ID_UPSTREAM_USB 1
29#define VENDOR_ID_DIN 2
30#define VENDOR_ID_UPSTREAM_USB2 3
31#define VENDOR_ID_UPSTREAM_USB3 4
32
33#define MIDI_DIRECTION_INPUT_TO_DELUGE 0
34#define MIDI_DIRECTION_OUTPUT_FROM_DELUGE 1
35
36#define MPE_ZONE_LOWER_NUMBERED_FROM_0 0
37#define MPE_ZONE_UPPER_NUMBERED_FROM_0 1
38
39class MIDICable;
40class Serializer;
41class Deserializer;
42
43class MIDIPort {
44public:
45 MIDIPort() {
46 mpeLowerZoneLastMemberChannel = 0;
47 mpeUpperZoneLastMemberChannel = 15;
48 }
49 int32_t channelToZone(int32_t inputChannel);
50 void writeToFile(Serializer& writer, char const* tagName);
51 bool worthWritingToFile();
52 void readFromFile(Deserializer& reader, MIDICable* deviceToSendMCMsOn);
53 void moveUpperZoneOutOfWayOfLowerZone();
54 void moveLowerZoneOutOfWayOfUpperZone();
55 bool isMasterChannel(int32_t inputChannel);
56 inline bool isChannelPartOfAnMPEZone(int32_t channel) {
57 return (channel >= 1 && channel <= 14
58 && (mpeLowerZoneLastMemberChannel >= channel || mpeUpperZoneLastMemberChannel <= channel));
59 }
60
61 uint8_t mpeLowerZoneLastMemberChannel; // 0 means off
62 uint8_t mpeUpperZoneLastMemberChannel; // 15 means off
63};
64
65class MIDIInputChannel {
66public:
67 MIDIInputChannel() {
68 bendRange = 0; // Means not set; don't copy value. Also, note this is the "main" bend range; there isn't one for
69 // finger-level because this is a non-MPE single MIDI channel.
70 rpnLSB = 127; // Means no param specified
71 rpnMSB = 127;
72 }
73
74 /* These are stored as full-range 16-bit values (scaled up from 7 or 14-bit MIDI depending on which), and you'll
75 * want to scale this up again to 32-bit to use them. X and Y may be both positive and negative, and Z may only be
76 * positive (so has been scaled up less from incoming bits). These default to 0. These are just for
77 * MelodicInstruments. For Drums, the values get stored in the Drum itself.
78 */
79 std::array<int16_t, kNumExpressionDimensions> defaultInputMPEValues{0};
80
81 uint8_t rpnLSB;
82 uint8_t rpnMSB;
83 uint8_t bendRange;
84};
85
86/*
87 * MidiDevice primarily holds configuration settings and associated data - the sendMessage function
88 * is used only during setup, and data is r/w directly from the super device (connectedUSBMIDIDevice)
89 * or the serial ports as applicable
90 * See MIDIDeviceManager or midiengine.cpp for details
91 */
92
93enum class clock_setting { NONE, RECEIVE, SEND, BOTH };
94
96class MIDICable {
97public:
98 MIDICable();
99 virtual void writeToFlash(uint8_t* memory) = 0;
100 [[nodiscard]] virtual char const* getDisplayName() const = 0;
101
102 void dataEntryMessageReceived(ModelStack* modelStack, int32_t channel, int32_t msb);
103
105 [[nodiscard]] virtual bool wantsToOutputMIDIOnChannel(MIDIMessage message, int32_t filter) const;
106
109 void writeReferenceToFile(Serializer& writer, char const* tagName = "device");
110 void writeToFile(Serializer& writer, char const* tagName);
111 void readFromFile(Deserializer& reader);
112 bool worthWritingToFile();
113 void writePorts(Serializer& writer);
115
118
120 [[nodiscard]] virtual Error sendMessage(MIDIMessage message) = 0;
121
126 [[nodiscard]] virtual Error sendSysex(const uint8_t* data, int32_t len) = 0;
127
129 [[nodiscard]] virtual size_t sendBufferSpace() const = 0;
130
134
136 void sendAllMCMs();
137
138 inline void sendCC(int32_t channel, int32_t cc, int32_t value) { sendMessage(MIDIMessage::cc(channel, cc, value)); }
139 void sendRPN(int32_t channel, int32_t rpnMSB, int32_t rpnLSB, int32_t valueMSB);
140 // @}
141
142 inline bool hasDefaultVelocityToLevelSet() { return defaultVelocityToLevel; }
143
144 // Only 2 ports per device, but this is functionally set in stone due to existing code
145 // Originally done to ease integration to the midi device setting menu
146 MIDIPort ports[2];
147
148 uint8_t mpeZoneBendRanges[2][2]; // 0 means none set. It's [zone][whichBendRange].
149
150 MIDIInputChannel inputChannels[16];
151
152 int32_t defaultVelocityToLevel;
153
154 // 0 if not connected. For USB devices, the bits signal a connection of the corresponding connectedUSBMIDIDevices[].
155 // Of course there'll usually just be one bit set, unless two of the same device are connected.
156 uint8_t connectionFlags;
157 bool sendClock; // whether to send clocks to this device
158 bool receiveClock; // whether to receive clocks from this device
159 uint8_t incomingSysexBuffer[1024];
160 int32_t incomingSysexPos = 0;
161
162protected:
163 // These go both into SETTINGS/MIDIDevices.XML and also any song/preset
164 // files where there's a reference to this Device.
165 virtual void writeReferenceAttributesToFile(Serializer& writer) = 0;
166
167 // These only go into SETTINGS/MIDIDevices.XML
168 void writeDefinitionAttributesToFile(Serializer& writer);
169};
Definition storage_manager.h:185
A MIDI cable connection. Stores all state specific to a given cable and its contained ports and chann...
Definition midi_device.h:96
void sendAllMCMs()
Send MPE control messages.
Definition midi_device.cpp:166
virtual size_t sendBufferSpace() const =0
Get the number of bytes available in the send buffer.
virtual bool wantsToOutputMIDIOnChannel(MIDIMessage message, int32_t filter) const
Used to decide if the given message should be output on a channel.
Definition midi_device.cpp:135
virtual Error sendSysex(const uint8_t *data, int32_t len)=0
virtual Error sendMessage(MIDIMessage message)=0
Send a MIDI message.
Definition model_stack.h:123
Definition storage_manager.h:119
Definition message.h:30