1 /*
2   Copyright 2012-2016 David Robillard <http://drobilla.net>
3   Copyright 2018 Ethan Reker <http://cutthroughrecordings.com>
4 
5   Permission to use, copy, modify, and/or distribute this software for any
6   purpose with or without fee is hereby granted, provided that the above
7   copyright notice and this permission notice appear in all copies.
8 
9   THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 module dplug.lv2.midi;
18 
19 version(LV2):
20 
21 /**
22    @defgroup midi MIDI
23 
24    Definitions of standard MIDI messages, see <http://lv2plug.in/ns/ext/midi>
25    for details.
26 
27    @{
28 */
29 
30 import core.stdc.stdint;
31 
32 extern(C) {
33 
34     enum LV2_MIDI_URI    = "http://lv2plug.in/ns/ext/midi";  ///< http://lv2plug.in/ns/ext/midi
35     enum LV2_MIDI_PREFIX = LV2_MIDI_URI ~ "#";                 ///< http://lv2plug.in/ns/ext/midi#
36 
37     enum LV2_MIDI__ActiveSense      = LV2_MIDI_PREFIX ~ "ActiveSense";       ///< http://lv2plug.in/ns/ext/midi#ActiveSense
38     enum LV2_MIDI__Aftertouch       = LV2_MIDI_PREFIX ~ "Aftertouch";        ///< http://lv2plug.in/ns/ext/midi#Aftertouch
39     enum LV2_MIDI__Bender           = LV2_MIDI_PREFIX ~ "Bender";            ///< http://lv2plug.in/ns/ext/midi#Bender
40     enum LV2_MIDI__ChannelPressure  = LV2_MIDI_PREFIX ~ "ChannelPressure";   ///< http://lv2plug.in/ns/ext/midi#ChannelPressure
41     enum LV2_MIDI__Chunk            = LV2_MIDI_PREFIX ~ "Chunk";             ///< http://lv2plug.in/ns/ext/midi#Chunk
42     enum LV2_MIDI__Clock            = LV2_MIDI_PREFIX ~ "Clock";             ///< http://lv2plug.in/ns/ext/midi#Clock
43     enum LV2_MIDI__Continue         = LV2_MIDI_PREFIX ~ "Continue";          ///< http://lv2plug.in/ns/ext/midi#Continue
44     enum LV2_MIDI__Controller       = LV2_MIDI_PREFIX ~ "Controller";        ///< http://lv2plug.in/ns/ext/midi#Controller
45     enum LV2_MIDI__MidiEvent        = LV2_MIDI_PREFIX ~ "MidiEvent";         ///< http://lv2plug.in/ns/ext/midi#MidiEvent
46     enum LV2_MIDI__NoteOff          = LV2_MIDI_PREFIX ~ "NoteOff";           ///< http://lv2plug.in/ns/ext/midi#NoteOff
47     enum LV2_MIDI__NoteOn           = LV2_MIDI_PREFIX ~ "NoteOn";            ///< http://lv2plug.in/ns/ext/midi#NoteOn
48     enum LV2_MIDI__ProgramChange    = LV2_MIDI_PREFIX ~ "ProgramChange";     ///< http://lv2plug.in/ns/ext/midi#ProgramChange
49     enum LV2_MIDI__QuarterFrame     = LV2_MIDI_PREFIX ~ "QuarterFrame";      ///< http://lv2plug.in/ns/ext/midi#QuarterFrame
50     enum LV2_MIDI__Reset            = LV2_MIDI_PREFIX ~ "Reset";             ///< http://lv2plug.in/ns/ext/midi#Reset
51     enum LV2_MIDI__SongPosition     = LV2_MIDI_PREFIX ~ "SongPosition";      ///< http://lv2plug.in/ns/ext/midi#SongPosition
52     enum LV2_MIDI__SongSelect       = LV2_MIDI_PREFIX ~ "SongSelect";        ///< http://lv2plug.in/ns/ext/midi#SongSelect
53     enum LV2_MIDI__Start            = LV2_MIDI_PREFIX ~ "Start";             ///< http://lv2plug.in/ns/ext/midi#Start
54     enum LV2_MIDI__Stop             = LV2_MIDI_PREFIX ~ "Stop";              ///< http://lv2plug.in/ns/ext/midi#Stop
55     enum LV2_MIDI__SystemCommon     = LV2_MIDI_PREFIX ~ "SystemCommon";      ///< http://lv2plug.in/ns/ext/midi#SystemCommon
56     enum LV2_MIDI__SystemExclusive  = LV2_MIDI_PREFIX ~ "SystemExclusive";   ///< http://lv2plug.in/ns/ext/midi#SystemExclusive
57     enum LV2_MIDI__SystemMessage    = LV2_MIDI_PREFIX ~ "SystemMessage";     ///< http://lv2plug.in/ns/ext/midi#SystemMessage
58     enum LV2_MIDI__SystemRealtime   = LV2_MIDI_PREFIX ~ "SystemRealtime";    ///< http://lv2plug.in/ns/ext/midi#SystemRealtime
59     enum LV2_MIDI__Tick             = LV2_MIDI_PREFIX ~ "Tick";              ///< http://lv2plug.in/ns/ext/midi#Tick
60     enum LV2_MIDI__TuneRequest      = LV2_MIDI_PREFIX ~ "TuneRequest";       ///< http://lv2plug.in/ns/ext/midi#TuneRequest
61     enum LV2_MIDI__VoiceMessage     = LV2_MIDI_PREFIX ~ "VoiceMessage";      ///< http://lv2plug.in/ns/ext/midi#VoiceMessage
62     enum LV2_MIDI__benderValue      = LV2_MIDI_PREFIX ~ "benderValue";       ///< http://lv2plug.in/ns/ext/midi#benderValue
63     enum LV2_MIDI__binding          = LV2_MIDI_PREFIX ~ "binding";           ///< http://lv2plug.in/ns/ext/midi#binding
64     enum LV2_MIDI__byteNumber       = LV2_MIDI_PREFIX ~ "byteNumber";        ///< http://lv2plug.in/ns/ext/midi#byteNumber
65     enum LV2_MIDI__channel          = LV2_MIDI_PREFIX ~ "channel";           ///< http://lv2plug.in/ns/ext/midi#channel
66     enum LV2_MIDI__chunk            = LV2_MIDI_PREFIX ~ "chunk";             ///< http://lv2plug.in/ns/ext/midi#chunk
67     enum LV2_MIDI__controllerNumber = LV2_MIDI_PREFIX ~ "controllerNumber";  ///< http://lv2plug.in/ns/ext/midi#controllerNumber
68     enum LV2_MIDI__controllerValue  = LV2_MIDI_PREFIX ~ "controllerValue";   ///< http://lv2plug.in/ns/ext/midi#controllerValue
69     enum LV2_MIDI__noteNumber       = LV2_MIDI_PREFIX ~ "noteNumber";        ///< http://lv2plug.in/ns/ext/midi#noteNumber
70     enum LV2_MIDI__pressure         = LV2_MIDI_PREFIX ~ "pressure";          ///< http://lv2plug.in/ns/ext/midi#pressure
71     enum LV2_MIDI__programNumber    = LV2_MIDI_PREFIX ~ "programNumber";     ///< http://lv2plug.in/ns/ext/midi#programNumber
72     enum LV2_MIDI__property         = LV2_MIDI_PREFIX ~ "property";          ///< http://lv2plug.in/ns/ext/midi#property
73     enum LV2_MIDI__songNumber       = LV2_MIDI_PREFIX ~ "songNumber";        ///< http://lv2plug.in/ns/ext/midi#songNumber
74     enum LV2_MIDI__songPosition     = LV2_MIDI_PREFIX ~ "songPosition";      ///< http://lv2plug.in/ns/ext/midi#songPosition
75     enum LV2_MIDI__status           = LV2_MIDI_PREFIX ~ "status";            ///< http://lv2plug.in/ns/ext/midi#status
76     enum LV2_MIDI__statusMask       = LV2_MIDI_PREFIX ~ "statusMask";        ///< http://lv2plug.in/ns/ext/midi#statusMask
77     enum LV2_MIDI__velocity         = LV2_MIDI_PREFIX ~ "velocity";          ///< http://lv2plug.in/ns/ext/midi#velocity
78 
79     /**
80     MIDI Message Type.
81 
82     This includes both voice messages (which have a channel) and system messages
83     (which do not), as well as a sentinel value for invalid messages.  To get
84     the type of a message suitable for use in a switch statement, use
85     lv2_midi_get_type() on the status byte.
86     */
87     alias LV2_Midi_Message_Type = byte;
88     enum {
89         LV2_MIDI_MSG_INVALID          = 0,     /**< Invalid Message */
90         LV2_MIDI_MSG_NOTE_OFF         = 0x80,  /**< Note Off */
91         LV2_MIDI_MSG_NOTE_ON          = 0x90,  /**< Note On */
92         LV2_MIDI_MSG_NOTE_PRESSURE    = 0xA0,  /**< Note Pressure */
93         LV2_MIDI_MSG_CONTROLLER       = 0xB0,  /**< Controller */
94         LV2_MIDI_MSG_PGM_CHANGE       = 0xC0,  /**< Program Change */
95         LV2_MIDI_MSG_CHANNEL_PRESSURE = 0xD0,  /**< Channel Pressure */
96         LV2_MIDI_MSG_BENDER           = 0xE0,  /**< Pitch Bender */
97         LV2_MIDI_MSG_SYSTEM_EXCLUSIVE = 0xF0,  /**< System Exclusive Begin */
98         LV2_MIDI_MSG_MTC_QUARTER      = 0xF1,  /**< MTC Quarter Frame */
99         LV2_MIDI_MSG_SONG_POS         = 0xF2,  /**< Song Position */
100         LV2_MIDI_MSG_SONG_SELECT      = 0xF3,  /**< Song Select */
101         LV2_MIDI_MSG_TUNE_REQUEST     = 0xF6,  /**< Tune Request */
102         LV2_MIDI_MSG_CLOCK            = 0xF8,  /**< Clock */
103         LV2_MIDI_MSG_START            = 0xFA,  /**< Start */
104         LV2_MIDI_MSG_CONTINUE         = 0xFB,  /**< Continue */
105         LV2_MIDI_MSG_STOP             = 0xFC,  /**< Stop */
106         LV2_MIDI_MSG_ACTIVE_SENSE     = 0xFE,  /**< Active Sensing */
107         LV2_MIDI_MSG_RESET            = 0xFF   /**< Reset */
108     }
109 
110     /**
111     Standard MIDI Controller Numbers.
112     */
113     alias LV2_Midi_Controller = byte;
114     enum {
115         LV2_MIDI_CTL_MSB_BANK             = 0x00,  /**< Bank Selection */
116         LV2_MIDI_CTL_MSB_MODWHEEL         = 0x01,  /**< Modulation */
117         LV2_MIDI_CTL_MSB_BREATH           = 0x02,  /**< Breath */
118         LV2_MIDI_CTL_MSB_FOOT             = 0x04,  /**< Foot */
119         LV2_MIDI_CTL_MSB_PORTAMENTO_TIME  = 0x05,  /**< Portamento Time */
120         LV2_MIDI_CTL_MSB_DATA_ENTRY       = 0x06,  /**< Data Entry */
121         LV2_MIDI_CTL_MSB_MAIN_VOLUME      = 0x07,  /**< Main Volume */
122         LV2_MIDI_CTL_MSB_BALANCE          = 0x08,  /**< Balance */
123         LV2_MIDI_CTL_MSB_PAN              = 0x0A,  /**< Panpot */
124         LV2_MIDI_CTL_MSB_EXPRESSION       = 0x0B,  /**< Expression */
125         LV2_MIDI_CTL_MSB_EFFECT1          = 0x0C,  /**< Effect1 */
126         LV2_MIDI_CTL_MSB_EFFECT2          = 0x0D,  /**< Effect2 */
127         LV2_MIDI_CTL_MSB_GENERAL_PURPOSE1 = 0x10,  /**< General Purpose 1 */
128         LV2_MIDI_CTL_MSB_GENERAL_PURPOSE2 = 0x11,  /**< General Purpose 2 */
129         LV2_MIDI_CTL_MSB_GENERAL_PURPOSE3 = 0x12,  /**< General Purpose 3 */
130         LV2_MIDI_CTL_MSB_GENERAL_PURPOSE4 = 0x13,  /**< General Purpose 4 */
131         LV2_MIDI_CTL_LSB_BANK             = 0x20,  /**< Bank Selection */
132         LV2_MIDI_CTL_LSB_MODWHEEL         = 0x21,  /**< Modulation */
133         LV2_MIDI_CTL_LSB_BREATH           = 0x22,  /**< Breath */
134         LV2_MIDI_CTL_LSB_FOOT             = 0x24,  /**< Foot */
135         LV2_MIDI_CTL_LSB_PORTAMENTO_TIME  = 0x25,  /**< Portamento Time */
136         LV2_MIDI_CTL_LSB_DATA_ENTRY       = 0x26,  /**< Data Entry */
137         LV2_MIDI_CTL_LSB_MAIN_VOLUME      = 0x27,  /**< Main Volume */
138         LV2_MIDI_CTL_LSB_BALANCE          = 0x28,  /**< Balance */
139         LV2_MIDI_CTL_LSB_PAN              = 0x2A,  /**< Panpot */
140         LV2_MIDI_CTL_LSB_EXPRESSION       = 0x2B,  /**< Expression */
141         LV2_MIDI_CTL_LSB_EFFECT1          = 0x2C,  /**< Effect1 */
142         LV2_MIDI_CTL_LSB_EFFECT2          = 0x2D,  /**< Effect2 */
143         LV2_MIDI_CTL_LSB_GENERAL_PURPOSE1 = 0x30,  /**< General Purpose 1 */
144         LV2_MIDI_CTL_LSB_GENERAL_PURPOSE2 = 0x31,  /**< General Purpose 2 */
145         LV2_MIDI_CTL_LSB_GENERAL_PURPOSE3 = 0x32,  /**< General Purpose 3 */
146         LV2_MIDI_CTL_LSB_GENERAL_PURPOSE4 = 0x33,  /**< General Purpose 4 */
147         LV2_MIDI_CTL_SUSTAIN              = 0x40,  /**< Sustain Pedal */
148         LV2_MIDI_CTL_PORTAMENTO           = 0x41,  /**< Portamento */
149         LV2_MIDI_CTL_SOSTENUTO            = 0x42,  /**< Sostenuto */
150         LV2_MIDI_CTL_SOFT_PEDAL           = 0x43,  /**< Soft Pedal */
151         LV2_MIDI_CTL_LEGATO_FOOTSWITCH    = 0x44,  /**< Legato Foot Switch */
152         LV2_MIDI_CTL_HOLD2                = 0x45,  /**< Hold2 */
153         LV2_MIDI_CTL_SC1_SOUND_VARIATION  = 0x46,  /**< SC1 Sound Variation */
154         LV2_MIDI_CTL_SC2_TIMBRE           = 0x47,  /**< SC2 Timbre */
155         LV2_MIDI_CTL_SC3_RELEASE_TIME     = 0x48,  /**< SC3 Release Time */
156         LV2_MIDI_CTL_SC4_ATTACK_TIME      = 0x49,  /**< SC4 Attack Time */
157         LV2_MIDI_CTL_SC5_BRIGHTNESS       = 0x4A,  /**< SC5 Brightness */
158         LV2_MIDI_CTL_SC6                  = 0x4B,  /**< SC6 */
159         LV2_MIDI_CTL_SC7                  = 0x4C,  /**< SC7 */
160         LV2_MIDI_CTL_SC8                  = 0x4D,  /**< SC8 */
161         LV2_MIDI_CTL_SC9                  = 0x4E,  /**< SC9 */
162         LV2_MIDI_CTL_SC10                 = 0x4F,  /**< SC10 */
163         LV2_MIDI_CTL_GENERAL_PURPOSE5     = 0x50,  /**< General Purpose 5 */
164         LV2_MIDI_CTL_GENERAL_PURPOSE6     = 0x51,  /**< General Purpose 6 */
165         LV2_MIDI_CTL_GENERAL_PURPOSE7     = 0x52,  /**< General Purpose 7 */
166         LV2_MIDI_CTL_GENERAL_PURPOSE8     = 0x53,  /**< General Purpose 8 */
167         LV2_MIDI_CTL_PORTAMENTO_CONTROL   = 0x54,  /**< Portamento Control */
168         LV2_MIDI_CTL_E1_REVERB_DEPTH      = 0x5B,  /**< E1 Reverb Depth */
169         LV2_MIDI_CTL_E2_TREMOLO_DEPTH     = 0x5C,  /**< E2 Tremolo Depth */
170         LV2_MIDI_CTL_E3_CHORUS_DEPTH      = 0x5D,  /**< E3 Chorus Depth */
171         LV2_MIDI_CTL_E4_DETUNE_DEPTH      = 0x5E,  /**< E4 Detune Depth */
172         LV2_MIDI_CTL_E5_PHASER_DEPTH      = 0x5F,  /**< E5 Phaser Depth */
173         LV2_MIDI_CTL_DATA_INCREMENT       = 0x60,  /**< Data Increment */
174         LV2_MIDI_CTL_DATA_DECREMENT       = 0x61,  /**< Data Decrement */
175         LV2_MIDI_CTL_NRPN_LSB             = 0x62,  /**< Non-registered Parameter Number */
176         LV2_MIDI_CTL_NRPN_MSB             = 0x63,  /**< Non-registered Parameter Number */
177         LV2_MIDI_CTL_RPN_LSB              = 0x64,  /**< Registered Parameter Number */
178         LV2_MIDI_CTL_RPN_MSB              = 0x65,  /**< Registered Parameter Number */
179         LV2_MIDI_CTL_ALL_SOUNDS_OFF       = 0x78,  /**< All Sounds Off */
180         LV2_MIDI_CTL_RESET_CONTROLLERS    = 0x79,  /**< Reset Controllers */
181         LV2_MIDI_CTL_LOCAL_CONTROL_SWITCH = 0x7A,  /**< Local Control Switch */
182         LV2_MIDI_CTL_ALL_NOTES_OFF        = 0x7B,  /**< All Notes Off */
183         LV2_MIDI_CTL_OMNI_OFF             = 0x7C,  /**< Omni Off */
184         LV2_MIDI_CTL_OMNI_ON              = 0x7D,  /**< Omni On */
185         LV2_MIDI_CTL_MONO1                = 0x7E,  /**< Mono1 */
186         LV2_MIDI_CTL_MONO2                = 0x7F   /**< Mono2 */
187     }
188 
189     /**
190     Return true iff `msg` is a MIDI voice message (which has a channel).
191     */
192     static bool
193     lv2_midi_is_voice_message(const uint8_t* msg) {
194         return msg[0] >= 0x80 && msg[0] < 0xF0;
195     }
196 
197     /**
198     Return true iff `msg` is a MIDI system message (which has no channel).
199     */
200     static bool
201     lv2_midi_is_system_message(const uint8_t* msg) {
202         switch (msg[0]) {
203         case 0xF4: case 0xF5: case 0xF7: case 0xF9: case 0xFD:
204             return false;
205         default:
206             return (msg[0] & 0xF0) == 0xF0;
207         }
208     }
209 
210     /**
211     Return the type of a MIDI message.
212     @param msg Pointer to the start (status byte) of a MIDI message.
213     */
214     static LV2_Midi_Message_Type
215     lv2_midi_message_type(const uint8_t* msg) {
216         if (lv2_midi_is_voice_message(msg)) {
217             return cast(LV2_Midi_Message_Type)(msg[0] & 0xF0);
218         } else if (lv2_midi_is_system_message(msg)) {
219             return cast(LV2_Midi_Message_Type)msg[0];
220         } else {
221             return LV2_MIDI_MSG_INVALID;
222         }
223     }
224 
225 }