3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 Christian Schoenebeck * |
* Copyright (C) 2005 - 2008 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
9 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
26 |
|
|
27 |
#include "../../common/global.h" |
#include "../../common/global.h" |
28 |
#include "../../common/Mutex.h" |
#include "../../common/Mutex.h" |
29 |
#include "../../common/LinuxSamplerException.h" |
#include "../../common/Exception.h" |
30 |
#include "../DeviceParameter.h" |
#include "../DeviceParameter.h" |
31 |
#include "midi.h" |
#include "midi.h" |
32 |
#include "MidiInputDevice.h" |
#include "MidiInputDevice.h" |
33 |
#include "../../engines/common/EngineChannel.h" |
#include "../../engines/EngineChannel.h" |
34 |
#include "../../common/SynchronizedConfig.h" |
#include "../../common/SynchronizedConfig.h" |
35 |
|
|
36 |
namespace LinuxSampler { |
namespace LinuxSampler { |
38 |
// just symbol prototyping |
// just symbol prototyping |
39 |
class MidiInputDevice; |
class MidiInputDevice; |
40 |
class EngineChannel; |
class EngineChannel; |
41 |
|
class VirtualMidiDevice; |
42 |
|
|
43 |
class MidiInputPort { |
class MidiInputPort { |
44 |
public: |
public: |
57 |
virtual String Description(); |
virtual String Description(); |
58 |
virtual bool Fix(); |
virtual bool Fix(); |
59 |
virtual std::vector<String> PossibilitiesAsString(); |
virtual std::vector<String> PossibilitiesAsString(); |
60 |
virtual void OnSetValue(String s) throw (LinuxSamplerException); |
virtual void OnSetValue(String s) throw (Exception); |
61 |
protected: |
protected: |
62 |
MidiInputPort* pPort; |
MidiInputPort* pPort; |
63 |
}; |
}; |
69 |
// (usually not to be overriden by descendant) |
// (usually not to be overriden by descendant) |
70 |
|
|
71 |
/** |
/** |
72 |
* Connect given sampler engine with this MIDI input device. |
* Connect given sampler engine channel with this MIDI input |
73 |
* The engine can either be connected to one specific MIDI |
* device. The engine channel can either be connected to one |
74 |
* channel or all MIDI channels. If an engine gets connected |
* specific MIDI channel or all MIDI channels. If an engine |
75 |
* twice to this MIDI input device, then the engine's old |
* channel gets connected twice to this MIDI input device, then |
76 |
* connection will be detached (no matter on which MIDI channel). |
* the engine's old connection will be detached (no matter on |
77 |
|
* which MIDI channel). |
78 |
* |
* |
79 |
* @param pEngine - sampler engine |
* @param pEngineChannel - sampler engine |
80 |
* @param MidiChannel - MIDI channel to connect to |
* @param MidiChannel - MIDI channel to connect to |
81 |
* @throws MidiInputException if MidiChannel argument invalid |
* @throws MidiInputException if MidiChannel argument invalid |
82 |
*/ |
*/ |
83 |
void Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel); |
void Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel); |
84 |
|
|
85 |
/** |
/** |
86 |
* Disconnect given sampler engine from this MIDI input device. |
* Disconnect given sampler engine channel from this MIDI input |
87 |
* If the given engine was not connected with this device, |
* device. If the given engine channel was not connected with |
88 |
* nothing happens. |
* this device, nothing happens. |
89 |
* |
* |
90 |
* @param pEngine - sampler engine |
* @param pEngineChannel - sampler engine |
91 |
*/ |
*/ |
92 |
void Disconnect(EngineChannel* pEngineChannel); |
void Disconnect(EngineChannel* pEngineChannel); |
93 |
|
|
121 |
*/ |
*/ |
122 |
static bool RemoveSysexListener(Engine* engine); |
static bool RemoveSysexListener(Engine* engine); |
123 |
|
|
124 |
|
/** |
125 |
|
* Connects the given virtual MIDI device to this MIDI input |
126 |
|
* device. This can be used to listen to MIDI data arriving on |
127 |
|
* the MIDI input device's MIDI ports, e.g. to show an MIDI |
128 |
|
* activity indicator somewhere. |
129 |
|
*/ |
130 |
|
void Connect(VirtualMidiDevice* pDevice); |
131 |
|
|
132 |
|
/** |
133 |
|
* Disconnect the previously connected virtual MIDI device. |
134 |
|
*/ |
135 |
|
void Disconnect(VirtualMidiDevice* pDevice); |
136 |
|
|
137 |
|
|
138 |
///////////////////////////////////////////////////////////////// |
///////////////////////////////////////////////////////////////// |
139 |
// dispatch methods |
// dispatch methods |
145 |
* event to be forwarded to all connected engines on the |
* event to be forwarded to all connected engines on the |
146 |
* corresponding MIDI channel. |
* corresponding MIDI channel. |
147 |
* |
* |
148 |
|
* This method is meant for realtime rendering, this way an event |
149 |
|
* is immediately created with the current system time as time |
150 |
|
* stamp. |
151 |
|
* |
152 |
* @param Key - MIDI key number of the triggered key |
* @param Key - MIDI key number of the triggered key |
153 |
* @param Velocity - MIDI velocity of the triggered key |
* @param Velocity - MIDI velocity of the triggered key |
154 |
* @param MidiChannel - MIDI channel on which event occured on |
* @param MidiChannel - MIDI channel on which event occured on |
158 |
|
|
159 |
/** |
/** |
160 |
* Should be called by the implementing MIDI input device |
* Should be called by the implementing MIDI input device |
161 |
|
* whenever a note on event arrived, this will cause the note on |
162 |
|
* event to be forwarded to all connected engines on the |
163 |
|
* corresponding MIDI channel. |
164 |
|
* |
165 |
|
* This method is meant for offline rendering and / or in case the |
166 |
|
* exact fragment position of the event is already known. |
167 |
|
* |
168 |
|
* @param Key - MIDI key number of the triggered key |
169 |
|
* @param Velocity - MIDI velocity of the triggered key |
170 |
|
* @param MidiChannel - MIDI channel on which event occured on |
171 |
|
* (low level indexing, means 0..15) |
172 |
|
* @param FragmentPos - event's sample point position in the |
173 |
|
* current audio fragment |
174 |
|
*/ |
175 |
|
void DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos); |
176 |
|
|
177 |
|
/** |
178 |
|
* Should be called by the implementing MIDI input device |
179 |
* whenever a note off event arrived, this will cause the note |
* whenever a note off event arrived, this will cause the note |
180 |
* off event to be forwarded to all connected engines on the |
* off event to be forwarded to all connected engines on the |
181 |
* corresponding MIDI channel. |
* corresponding MIDI channel. |
182 |
* |
* |
183 |
|
* This method is meant for realtime rendering, this way an event |
184 |
|
* is immediately created with the current system time as time |
185 |
|
* stamp. |
186 |
|
* |
187 |
* @param Key - MIDI key number of the released key |
* @param Key - MIDI key number of the released key |
188 |
* @param Velocity - MIDI velocity of the released key |
* @param Velocity - MIDI velocity of the released key |
189 |
* @param MidiChannel - MIDI channel on which event occured on |
* @param MidiChannel - MIDI channel on which event occured on |
193 |
|
|
194 |
/** |
/** |
195 |
* Should be called by the implementing MIDI input device |
* Should be called by the implementing MIDI input device |
196 |
|
* whenever a note off event arrived, this will cause the note |
197 |
|
* off event to be forwarded to all connected engines on the |
198 |
|
* corresponding MIDI channel. |
199 |
|
* |
200 |
|
* This method is meant for offline rendering and / or in case the |
201 |
|
* exact fragment position of the event is already known. |
202 |
|
* |
203 |
|
* @param Key - MIDI key number of the released key |
204 |
|
* @param Velocity - MIDI velocity of the released key |
205 |
|
* @param MidiChannel - MIDI channel on which event occured on |
206 |
|
* (low level indexing, means 0..15) |
207 |
|
* @param FragmentPos - event's sample point position in the |
208 |
|
* current audio fragment |
209 |
|
*/ |
210 |
|
void DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos); |
211 |
|
|
212 |
|
/** |
213 |
|
* Should be called by the implementing MIDI input device |
214 |
* whenever a pitchbend event arrived, this will cause the |
* whenever a pitchbend event arrived, this will cause the |
215 |
* pitchbend event to be forwarded to all connected engines. |
* pitchbend event to be forwarded to all connected engines. |
216 |
* |
* |
217 |
|
* This method is meant for realtime rendering, this way an event |
218 |
|
* is immediately created with the current system time as time |
219 |
|
* stamp. |
220 |
|
* |
221 |
* @param Pitch - MIDI pitch value |
* @param Pitch - MIDI pitch value |
222 |
* @param MidiChannel - MIDI channel on which event occured on |
* @param MidiChannel - MIDI channel on which event occured on |
223 |
* (low level indexing, means 0..15) |
* (low level indexing, means 0..15) |
226 |
|
|
227 |
/** |
/** |
228 |
* Should be called by the implementing MIDI input device |
* Should be called by the implementing MIDI input device |
229 |
|
* whenever a pitchbend event arrived, this will cause the |
230 |
|
* pitchbend event to be forwarded to all connected engines. |
231 |
|
* |
232 |
|
* This method is meant for offline rendering and / or in case the |
233 |
|
* exact fragment position of the event is already known. |
234 |
|
* |
235 |
|
* @param Pitch - MIDI pitch value |
236 |
|
* @param MidiChannel - MIDI channel on which event occured on |
237 |
|
* (low level indexing, means 0..15) |
238 |
|
* @param FragmentPos - event's sample point position in the |
239 |
|
* current audio fragment |
240 |
|
*/ |
241 |
|
void DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos); |
242 |
|
|
243 |
|
/** |
244 |
|
* Should be called by the implementing MIDI input device |
245 |
* whenever a control change event arrived, this will cause the |
* whenever a control change event arrived, this will cause the |
246 |
* control change event to be forwarded to all engines on the |
* control change event to be forwarded to all engines on the |
247 |
* corresponding MIDI channel. |
* corresponding MIDI channel. |
248 |
* |
* |
249 |
|
* This method is meant for realtime rendering, this way an event |
250 |
|
* is immediately created with the current system time as time |
251 |
|
* stamp. |
252 |
|
* |
253 |
* @param Controller - MIDI controller number |
* @param Controller - MIDI controller number |
254 |
* @param Value - MIDI control change value |
* @param Value - MIDI control change value |
255 |
* @param MidiChannel - MIDI channel on which event occured on |
* @param MidiChannel - MIDI channel on which event occured on |
259 |
|
|
260 |
/** |
/** |
261 |
* Should be called by the implementing MIDI input device |
* Should be called by the implementing MIDI input device |
262 |
|
* whenever a control change event arrived, this will cause the |
263 |
|
* control change event to be forwarded to all engines on the |
264 |
|
* corresponding MIDI channel. |
265 |
|
* |
266 |
|
* This method is meant for offline rendering and / or in case the |
267 |
|
* exact fragment position of the event is already known. |
268 |
|
* |
269 |
|
* @param Controller - MIDI controller number |
270 |
|
* @param Value - MIDI control change value |
271 |
|
* @param MidiChannel - MIDI channel on which event occured on |
272 |
|
* (low level indexing, means 0..15) |
273 |
|
* @param FragmentPos - event's sample point position in the |
274 |
|
* current audio fragment |
275 |
|
*/ |
276 |
|
void DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos); |
277 |
|
|
278 |
|
/** |
279 |
|
* Should be called by the implementing MIDI input device |
280 |
* whenever a program change event arrived, this will cause the |
* whenever a program change event arrived, this will cause the |
281 |
* appropriate sampler channel to be connected with this MIDI |
* appropriate sampler channel to be connected with this MIDI |
282 |
* device. |
* device. |
298 |
*/ |
*/ |
299 |
void DispatchProgramChange(uint8_t Program, uint MidiChannel); |
void DispatchProgramChange(uint8_t Program, uint MidiChannel); |
300 |
|
|
301 |
|
void DispatchBankSelectMsb(uint8_t BankMsb, uint MidiChannel); |
302 |
|
|
303 |
|
void DispatchBankSelectLsb(uint8_t BankLsb, uint MidiChannel); |
304 |
|
|
305 |
/** |
/** |
306 |
* Should be called by the implementing MIDI input device |
* Should be called by the implementing MIDI input device |
307 |
* whenever a system exclusive message arrived, this will cause |
* whenever a system exclusive message arrived, this will cause |
321 |
SynchronizedConfig<MidiChannelMap_t>::Reader MidiChannelMapReader; ///< MIDI thread access to MidiChannelMap |
SynchronizedConfig<MidiChannelMap_t>::Reader MidiChannelMapReader; ///< MIDI thread access to MidiChannelMap |
322 |
Mutex MidiChannelMapMutex; ///< Used to protect the MidiChannelMap from being used at the same time by different threads. |
Mutex MidiChannelMapMutex; ///< Used to protect the MidiChannelMap from being used at the same time by different threads. |
323 |
SynchronizedConfig<std::set<Engine*> >::Reader SysexListenersReader; ///< MIDI thread access to SysexListeners |
SynchronizedConfig<std::set<Engine*> >::Reader SysexListenersReader; ///< MIDI thread access to SysexListeners |
324 |
|
SynchronizedConfig<std::vector<VirtualMidiDevice*> > virtualMidiDevices; |
325 |
|
SynchronizedConfig<std::vector<VirtualMidiDevice*> >::Reader virtualMidiDevicesReader; |
326 |
|
Mutex virtualMidiDevicesMutex; |
327 |
|
|
328 |
/** |
/** |
329 |
* Constructor |
* Constructor |
338 |
friend class MidiInputDevice; |
friend class MidiInputDevice; |
339 |
|
|
340 |
private: |
private: |
|
EngineChannel* pPreviousProgramChangeEngineChannel; ///< Points to the engine channel which was connected by the previous DispatchProgramChange() call. |
|
341 |
static SynchronizedConfig<std::set<Engine*> > SysexListeners; ///< All engines that are listening to sysex messages. |
static SynchronizedConfig<std::set<Engine*> > SysexListeners; ///< All engines that are listening to sysex messages. |
342 |
}; |
}; |
343 |
|
|