1 /* 2 Copyright (C) 2008 - 2016 Christian Schoenebeck 3 */ 4 5 #ifndef LS_VIRTUALMIDIDEVICE_H 6 #define LS_VIRTUALMIDIDEVICE_H 7 8 #include "../../common/global.h" 9 10 namespace LinuxSampler { 11 12 /** 13 * Light-weight MIDI interface (for MIDI in & out) intended to be used by 14 * pure software MIDI "devices", that is e.g. a graphical virtual MIDI 15 * keyboard in an instrument editor or in a sampler frontend. This class 16 * should not be used for regular MIDI input device drivers for the sampler. 17 * This primitive interface by design doesn't care about jitter, fast event 18 * delivery or masses and masses of events in a short time! 19 */ 20 class VirtualMidiDevice { 21 public: 22 enum event_type_t { 23 EVENT_TYPE_NOTEON = 1, 24 EVENT_TYPE_NOTEOFF = 2, 25 EVENT_TYPE_CC = 3, 26 EVENT_TYPE_PITCHBEND, 27 EVENT_TYPE_PROGRAM, 28 EVENT_TYPE_CHPRESSURE, 29 }; 30 31 struct event_t { 32 event_type_t Type; 33 uint8_t Arg1; ///< Depends on @c Type (e.g. key number for note on/off events). 34 uint8_t Arg2; ///< Depends on @c Type (e.g. velocity for note on/off events). 35 }; 36 37 ///////////////////////////////////////////////////////////////// 38 // Device methods 39 // (called by the VirtualMidiDevice implementation) 40 41 /** 42 * Sends a MIDI @e note @e on event to the sampler. 43 * 44 * @returns true on success, false if internal FIFO full 45 * (or provided values invalid) 46 */ 47 bool SendNoteOnToSampler(uint8_t Key, uint8_t Velocity); 48 49 /** 50 * Sends a MIDI @e note @e off event to the sampler. 51 * 52 * @returns true on success, false if internal FIFO full 53 * (or provided values invalid) 54 */ 55 bool SendNoteOffToSampler(uint8_t Key, uint8_t Velocity); 56 57 /** 58 * Sends a MIDI @e Control @e Change event to the sampler. 59 * 60 * @returns true on success, false if internal FIFO full 61 * (or provided values invalid) 62 */ 63 bool SendCCToSampler(uint8_t Controller, uint8_t Value); 64 65 /** 66 * Sends a MIDI @e Channel @e Pressure (aftertouch) event to the sampler. 67 * 68 * @returns true on success, false if internal FIFO full 69 * (or provided value invalid) 70 */ 71 bool SendChannelPressureToSampler(uint8_t Pressure); 72 73 /** 74 * Sends a MIDI @e Pitch @e Bend event to the sampler. 75 * 76 * @param Pitch - MIDI pitch value (-8192 ... +8191) 77 * 78 * @returns true on success, false if internal FIFO full 79 * (or provided pitch value out of valid range) 80 */ 81 bool SendPitchBendToSampler(int Pitch); 82 83 /** 84 * Sends a MIDI @e Program @e Change event to the sampler. 85 * 86 * If you want to change the sound bank, call SendCCToSampler() (with 87 * controller = 0 for bank select MSB and/or controller = 32 for bank select 88 * LSB) before calling this method. 89 * 90 * @param Program - MIDI program number 91 * 92 * @returns true on success, false if internal FIFO full 93 * (or provided value invalid) 94 */ 95 bool SendProgramChangeToSampler(uint8_t Program); 96 97 /** 98 * Can be called by the virtual MIDI device to check whether a new note 99 * on or note off MIDI event arrived to the sampler during the last 100 * call to this method. So this is a asynchronously, "polling" based 101 * communication mechanism, which works in conjunction with the 102 * NoteIsActive() method call. 103 */ 104 bool NotesChanged(); 105 106 /** 107 * Can be called by the virtual MIDI device to check whether a new note 108 * on or note off MIDI event arrived to the sampler for @a Key during 109 * the last call to this method. So this is a asynchronously, 110 * "polling" based communication mechanism, which works in 111 * conjunction with the NoteIsActive() method call. 112 */ 113 bool NoteChanged(uint8_t Key); 114 115 /** 116 * Can be called by the virtual MIDI device to check which key / note 117 * is currently active by the sampler, e.g. to highlight the 118 * respective keys on a graphical virtual keyboard. 119 * 120 * @see NotesChanged(), NoteChanged() 121 */ 122 bool NoteIsActive(uint8_t Key); 123 124 /** 125 * Returns the velocity of the @e last note on event. No FIFO is used! 126 */ 127 uint8_t NoteOnVelocity(uint8_t Key); 128 129 /** 130 * Returns the velocity of the @e last note off event. No FIFO is used! 131 */ 132 uint8_t NoteOffVelocity(uint8_t Key); 133 134 /** 135 * Can be called by the virtual MIDI device to check whether a Control 136 * Change MIDI event arrived to the sampler during the last 137 * call to this method. So this is a asynchronously, "polling" based 138 * communication mechanism, which works in conjunction with the 139 * ControllerValue() method call. 140 */ 141 bool ControllersChanged(); 142 143 /** 144 * Can be called by the virtual MIDI device to check whether a Control 145 * Change MIDI event arrived to the sampler for @a Controller during 146 * the last call to this method. So this is a asynchronously, 147 * "polling" based communication mechanism, which works in 148 * conjunction with the ControllerValue() method call. 149 */ 150 bool ControllerChanged(uint8_t Controller); 151 152 /** 153 * Returns the value of the @e last Control Change event. No FIFO is used! 154 */ 155 uint8_t ControllerValue(uint8_t Controller); 156 157 ///////////////////////////////////////////////////////////////// 158 // Sampler methods 159 // (usually only called by the Sampler) 160 161 /** 162 * Informs the virtual MIDI device that a @e note @e on event occured 163 * (e.g. caused by a MIDI keyboard connected to the sampler). 164 * Communication acts asynchronously, that is this method call doesn't 165 * lock in any way and returns immediately. It is thus realtime safe. 166 * 167 * @e Note: this method is usually only called by the sampler. 168 * 169 * @see ActiveNotesChanged(), NoteIsActive() 170 */ 171 void SendNoteOnToDevice(uint8_t Key, uint8_t Velocity); 172 173 /** 174 * Informs the virtual MIDI device that a @e note @e off event occured 175 * (e.g. caused by a MIDI keyboard connected to the sampler). 176 * Communication acts asynchronously, that is this method call doesn't 177 * lock in any way and returns immediately. It is thus realtime safe. 178 * 179 * @e Note: this method is usually only called by the sampler. 180 * 181 * @see ActiveNotesChanged(), NoteIsActive() 182 */ 183 void SendNoteOffToDevice(uint8_t Key, uint8_t Velocity); 184 185 /** 186 * Informs the virtual MIDI device that a @e Control @e Change event 187 * occured (e.g. caused by a MIDI keyboard connected to the sampler). 188 * Communication acts asynchronously, that is this method call doesn't 189 * lock in any way and returns immediately. It is thus realtime safe. 190 * 191 * @e Note: this method is usually only called by the sampler. 192 * 193 * @see ControllersChanged(), ControllerValue() 194 */ 195 void SendCCToDevice(uint8_t Controller, uint8_t Value); 196 197 /** 198 * Gets the next pending MIDI event from the virtual MIDI device by 199 * using a lockfree FIFO. 200 * 201 * @e Note: this method is usually only called by the sampler. 202 * 203 * @param Event - destination for writing the next event to 204 * @returns true on success, false if no event pending 205 */ 206 bool GetMidiEventFromDevice(event_t& Event); 207 208 ///////////////////////////////////////////////////////////////// 209 // General Purpose Methods 210 211 /** 212 * Adjusts the internal event buffer to cover at least the given 213 * amount of MIDI events. This might be useful, since the internal 214 * event buffer is by default quite small (i.e. just 12 events). 215 * 216 * This method is not thread safe! Any operations upon this device 217 * have to be stopped before calling this method! 218 */ 219 void SetMaxEvents(int n); 220 221 /** 222 * Constructor 223 */ 224 VirtualMidiDevice(); 225 226 /** 227 * Destructor 228 */ 229 virtual ~VirtualMidiDevice(); 230 231 private: 232 struct private_data_t; 233 private_data_t* const p; 234 }; 235 236 } // namespace LinuxSampler 237 238 #endif // LS_VIRTUALMIDIDEVICE_H 239