1 /*
2     Drumstick MIDI realtime input-output
3     Copyright (C) 2009-2021 Pedro Lopez-Cabanillas <plcl@users.sf.net>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #ifndef MIDIOUTPUT_H
20 #define MIDIOUTPUT_H
21 
22 #include <QObject>
23 #include <QString>
24 #include <QStringList>
25 #include <QtPlugin>
26 #include <QSettings>
27 #include "macros.h"
28 
29 /**
30  * @file rtmidioutput.h
31  * Realtime MIDI output interface
32  */
33 
34 namespace drumstick { namespace rt {
35 
36 /**
37  * @addtogroup RT
38  * @{
39  */
40 
41 const quint8 MIDI_STD_CHANNELS              = 16; ///< Standard number of MIDI channels
42 const quint8 MIDI_GM_STD_DRUM_CHANNEL       = (10-1); ///< Number of the GM percussion channel
43 const quint8 MIDI_CONTROL_MSB_BANK_SELECT   = 0x00; ///< MIDI Controller number for MSB Bank number
44 const quint8 MIDI_CONTROL_MSB_MAIN_VOLUME   = 0x07; ///< MIDI Controller number for MSB volume
45 const quint8 MIDI_CONTROL_LSB_BANK_SELECT   = 0x20; ///< MIDI Controller number for LSB Bank number
46 const quint8 MIDI_CONTROL_REVERB_SEND       = 0x5b; ///< MIDI Controller number for Reverb send
47 const quint8 MIDI_CONTROL_ALL_SOUNDS_OFF    = 0x78; ///< MIDI Controller number for All sounds off
48 const quint8 MIDI_CONTROL_ALL_NOTES_OFF     = 0x7b; ///< MIDI Controller number for All notes off
49 const quint8 MIDI_CONTROL_RESET_CONTROLLERS = 0x79; ///< MIDI Controller number for Reset all controllers
50 
51 const quint8 MIDI_STATUS_NOTEOFF         = 0x80; ///< MIDI status byte for NOTE OFF messages
52 const quint8 MIDI_STATUS_NOTEON          = 0x90; ///< MIDI status byte for NOTE ON messages
53 const quint8 MIDI_STATUS_KEYPRESURE      = 0xa0; ///< MIDI status byte for KEY pressure messages
54 const quint8 MIDI_STATUS_CONTROLCHANGE   = 0xb0; ///< MIDI status byte for CONTROL change messages
55 const quint8 MIDI_STATUS_PROGRAMCHANGE   = 0xc0; ///< MIDI status byte for PROGRAM change messages
56 const quint8 MIDI_STATUS_CHANNELPRESSURE = 0xd0; ///< MIDI status byte for CHANNEL PRESSURE messages
57 const quint8 MIDI_STATUS_PITCHBEND       = 0xe0; ///< MIDI status byte for PITCH bend messages
58 const quint8 MIDI_STATUS_SYSEX           = 0xf0; ///< MIDI status byte for System Exclusive START messages
59 const quint8 MIDI_STATUS_ENDSYSEX        = 0xf7; ///< MIDI status byte for System Exclusive END messages
60 const quint8 MIDI_STATUS_REALTIME        = 0xf8; ///< Minimum value for MIDI Realtime messages status
61 
62 const quint8 MIDI_STATUS_MASK            = 0xf0; ///< Mask to extract the MIDI status byte from a MIDI message
63 const quint8 MIDI_CHANNEL_MASK           = 0x0f; ///< Mask to extract the MIDI channel byte from a MIDI message
64 
65 const quint8 MIDI_COMMON_QTRFRAME        = 0xF1; ///< MIDI Quarter frame status message
66 const quint8 MIDI_COMMON_SONGPP          = 0xF2; ///< MIDI Song Position status message
67 const quint8 MIDI_COMMON_SONGSELECT      = 0xF3; ///< MIDI Song Select status message
68 const quint8 MIDI_COMMON_TUNEREQ         = 0xF6; ///< MIDI Tune Request status message
69 
70 const quint8 MIDI_REALTIME_CLOCK         = 0xF8; ///< MIDI Clock status message
71 const quint8 MIDI_REALTIME_START         = 0xFA; ///< MIDI Start status message
72 const quint8 MIDI_REALTIME_CONTINUE      = 0xFB; ///< MIDI Continue status message
73 const quint8 MIDI_REALTIME_STOP          = 0xFC; ///< MIDI Stop status message
74 const quint8 MIDI_REALTIME_SENSING       = 0xFE; ///< MIDI Active Sensing status message
75 const quint8 MIDI_REALTIME_RESET         = 0xFF; ///< MIDI Reset status message
76 
77 /**
78  * @brief MIDI_LSB is a function to extract the least significative byte of a MIDI value
79  * @param x a MIDI integer value
80  * @return the least significative byte of the input value
81  */
MIDI_LSB(int x)82 inline int MIDI_LSB(int x)
83 {
84     return (x % 0x80);
85 }
86 
87 /**
88  * @brief MIDI_MSB is a function to extract the most significative byte of a MIDI value
89  * @param x MIDI integer value
90  * @return the most significative byte of the input value
91  */
MIDI_MSB(int x)92 inline int MIDI_MSB(int x)
93 {
94     return (x / 0x80);
95 }
96 
97     /**
98      * @brief MIDIConnection represents a connection identifier
99      *
100      * MIDIConnection is an alias for QPair<QString,QVariant> where the
101      * first component is a QString representing the symbolic name of the MIDI Port
102      * and the second component is a QVariant that represents the native identification
103      * of the MIDI port, which may be a string, a number, or any other data type
104      * accepted as a QVariant.
105      */
106     typedef QPair<QString,QVariant> MIDIConnection;
107 
108     /**
109      * @brief MIDI OUT interface
110      */
111     class DRUMSTICK_EXPORT MIDIOutput : public QObject
112     {
113         Q_OBJECT
114 
115     public:
116         /**
117          * @brief MIDIOutput constructor
118          * @param parent
119          */
QObject(parent)120         explicit MIDIOutput(QObject *parent = nullptr) : QObject(parent) {}
121         /**
122          * @brief ~MIDIOutput destructor
123          */
124         virtual ~MIDIOutput() = default;
125         /**
126          * @brief initialize
127          * @param settings
128          */
129         virtual void initialize(QSettings* settings) = 0;
130         /**
131          * @brief backendName
132          * @return plugin name
133          */
134         virtual QString backendName() = 0;
135         /**
136          * @brief publicName
137          * @return MIDI port name
138          */
139         virtual QString publicName() = 0;
140         /**
141          * @brief setPublicName
142          * @param name MIDI port name
143          */
144         virtual void setPublicName(QString name) = 0;
145         /**
146          * @brief connections
147          * @param advanced whether the advanced connections are included or not
148          * @return list of available MIDI ports
149          */
150         virtual QList<MIDIConnection> connections(bool advanced = false) = 0;
151         /**
152          * @brief setExcludedConnections
153          * @param conns
154          */
155         virtual void setExcludedConnections(QStringList conns) = 0;
156         /**
157          * @brief open the MIDI port by name
158          * @param conn the MIDI connection to be opened
159          */
160         virtual void open(const MIDIConnection& conn) = 0;
161         /**
162          * @brief close the MIDI port
163          */
164         virtual void close() = 0;
165         /**
166          * @brief currentConnection
167          * @return name of the current connection if it is opened
168          */
169         virtual MIDIConnection currentConnection() = 0;
170 
171     public Q_SLOTS:
172         /**
173          * @brief sendNoteOff 0x8
174          * @param chan
175          * @param note
176          * @param vel
177          */
178         virtual void sendNoteOff(int chan, int note, int vel) = 0;
179 
180         /**
181          * @brief sendNoteOn 0x9
182          * @param chan
183          * @param note
184          * @param vel
185          */
186         virtual void sendNoteOn(int chan, int note, int vel) = 0;
187 
188         /**
189          * @brief sendKeyPressure 0xA
190          * @param chan
191          * @param note
192          * @param value
193          */
194         virtual void sendKeyPressure(int chan, int note, int value) = 0;
195 
196         /**
197          * @brief sendController 0xB
198          * @param chan
199          * @param control
200          * @param value
201          */
202         virtual void sendController(int chan, int control, int value) = 0;
203 
204         /**
205          * @brief sendProgram 0xC
206          * @param chan
207          * @param program
208          */
209         virtual void sendProgram(int chan, int program) = 0;
210 
211         /**
212          * @brief sendChannelPressure 0xD
213          * @param chan
214          * @param value
215          */
216         virtual void sendChannelPressure(int chan, int value) = 0;
217 
218         /**
219          * @brief sendPitchBend 0xE
220          * @param chan
221          * @param value
222          */
223         virtual void sendPitchBend(int chan, int value) = 0;
224 
225         /**
226          * @brief sendSysex
227          * @param data 0xF0 ... 0xF7
228          */
229         virtual void sendSysex(const QByteArray& data) = 0;
230 
231         /**
232          * @brief sendSystemMsg
233          * @param status 0xF
234          */
235         virtual void sendSystemMsg(const int status) = 0;
236     };
237 
238     /** @} */
239 
240 }} // namespace drumstick::rt
241 
242 Q_DECLARE_INTERFACE(drumstick::rt::MIDIOutput, "net.sourceforge.drumstick.rt.MIDIOutput/2.0")
243 Q_DECLARE_METATYPE(drumstick::rt::MIDIConnection)
244 
245 #endif /* MIDIOUTPUT_H */
246