1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: mididev.h,v 1.3.2.4 2009/04/04 01:49:50 terminator356 Exp $
5 //
6 //  (C) Copyright 2000 Werner Schweer (ws@seh.de)
7 //  (C) Copyright 2011, 2016 Tim E. Real (terminator356 on users dot sourceforge dot net)
8 //
9 //  This program is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU General Public License
11 //  as published by the Free Software Foundation; version 2 of
12 //  the License, or (at your option) any later version.
13 //
14 //  This program is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //  GNU General Public License for more details.
18 //
19 //  You should have received a copy of the GNU General Public License
20 //  along with this program; if not, write to the Free Software
21 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23 //=========================================================
24 
25 #ifndef __MIDIDEV_H__
26 #define __MIDIDEV_H__
27 
28 #include <list>
29 
30 #include "mpevent.h"
31 #include "route.h"
32 #include "globaldefs.h"
33 #include <vector>
34 #include <atomic>
35 #include "lock_free_buffer.h"
36 #include "sync.h"
37 #include "evdata.h"
38 #include "latency_info.h"
39 
40 #include <QString>
41 
42 
43 namespace MusECore {
44 
45 
46 // Forward declarations:
47 class Xml;
48 
49 struct MidiOutputParams {
50       int BANKH;
51       int BANKL;
52       int PROG;
53       int RPNL;
54       int RPNH;
55       int NRPNL;
56       int NRPNH;
57       int DATAH;
58       int DATAL;
59 
MidiOutputParamsMidiOutputParams60       MidiOutputParams() { reset(); }
61 
resetMidiOutputParams62       void reset() { BANKH = BANKL = PROG = 0xff; RPNL = RPNH = NRPNL = NRPNH = DATAH = DATAL = -1; }
resetParamNumsMidiOutputParams63       void resetParamNums() { RPNL = RPNH = NRPNL = NRPNH = DATAH = DATAL = -1; }
resetPatchMidiOutputParams64       void resetPatch() { BANKH = BANKL = PROG = 0xff; }
setRPNLMidiOutputParams65       void setRPNL(int a)  { RPNL = a;  NRPNL = NRPNH = -1; }
setRPNHMidiOutputParams66       void setRPNH(int a)  { RPNH = a;  NRPNL = NRPNH = -1; }
setNRPNLMidiOutputParams67       void setNRPNL(int a) { NRPNL = a; RPNL  = RPNH = -1; }
setNRPNHMidiOutputParams68       void setNRPNH(int a) { NRPNH = a; RPNL  = RPNH = -1; }
setDATAHMidiOutputParams69       void setDATAH(int a) { DATAH = a; }
setDATALMidiOutputParams70       void setDATAL(int a) { DATAL = a; }
setBANKHMidiOutputParams71       void setBANKH(int a) { BANKH = a;}
setBANKLMidiOutputParams72       void setBANKL(int a) { BANKL = a;}
setPROGMidiOutputParams73       void setPROG(int a)  { PROG = a;}
currentProgMidiOutputParams74       void currentProg(int *prg, int *lbank, int *hbank)
75            {  if(prg) *prg=PROG&0xff; if(lbank) *lbank=BANKL&0xff; if(hbank) *hbank=BANKH&0xff;  }
setCurrentProgMidiOutputParams76       void setCurrentProg(int prg, int lbank, int hbank)
77            {  PROG=prg&0xff; BANKL=lbank&0xff; BANKH=hbank&0xff;  }
78 };
79 
80 //---------------------------------------------------------
81 //   MidiDevice
82 //---------------------------------------------------------
83 
84 class MidiDevice {
85    public:
86       // Types of MusE midi devices.
87       enum MidiDeviceType { ALSA_MIDI=0, JACK_MIDI=1, SYNTH_MIDI=2 };
88 
89       // IDs for the various IPC FIFOs that are used.
90       enum EventFifoIds
91       {
92         // Playback queued events put by the audio process thread.
93         PlayFifo=0,
94         // Gui events put by our gui thread.
95         GuiFifo=1,
96         // OSC events put by the OSC thread.
97         OSCFifo=2,
98         // Monitor input passthrough events put by Jack devices (audio process thread).
99         JackFifo=3,
100         // Monitor input passthrough events put by ALSA devices (midi seq thread).
101         ALSAFifo=4
102       };
103 
104       // The desired event buffer when putting an event.
105       enum EventBufferType
106       {
107         // Playback queue for events that are scheduled by the playback engine.
108         PlaybackBuffer=0,
109         // User queue for non-playback events such as from GUI controls or external hw.
110         UserBuffer=1
111       };
112 
113       // Describes latency of events passed to putEvent().
114       enum LatencyType
115       {
116         // The given event's time will be used 'as is' without modification.
117         NotLate = 0,
118         // The given event's time has some latency. Automatically compensate
119         //  by adding an appropriate number of frames, depending on device type.
120         // For example, events sent from a GUI control to the GuiFifo are usually
121         //  time-stamped in the past. For Synths and Jack midi (buffer-based systems)
122         //  we add a forward offset (one segment size). For ALSA (a poll-based system),
123         //  no offset is required. Similarly, events sent from OSC handlers to the
124         //  OSCFifo are also usually time-stamped in the past.
125         // Another example, events sent by the play scheduler to the PlayFifo are
126         //  /already/ scheduled properly for the future and need /no/ further compensation
127         //  for either Jack midi or ALSA devices.
128         Late = 1
129       };
130 
131    private:
132       // Used for multiple reads of fifos during process.
133       int _tmpRecordCount[MusECore::MUSE_MIDI_CHANNELS + 1];
134       bool _sysexFIFOProcessed;
135 
136    protected:
137       QString _name;
138       int _port;         // connected to midi port; -1 - not connected
139       int _rwFlags;      // possible open flags, 1 write, 2 read, 3 rw
140       int _openFlags;    // configured open flags
141       bool _readEnable;  // set when opened/closed.
142       bool _writeEnable; //
143       QString _state;
144       std::atomic<bool> _stopFlag;
145 
146       // For processing system exclusive input chunks.
147       SysExInputProcessor _sysExInProcessor;
148       // For processing system exclusive output chunks.
149       SysExOutputProcessor _sysExOutProcessor;
150       // Holds all non-realtime events while the sysex processor is in the Sending state.
151       // The official midi specs say only realtime messages can be mingled in the middle of a sysex.
152       std::vector<MidiPlayEvent> *_sysExOutDelayedEvents;
153 
154       MPEventList _stuckNotes; // Playback: Pending note-offs put directly to the device corresponding to currently playing notes
155 
156       // Playback IPC buffers. For playback events ONLY. Any thread can use this.
157       LockFreeMPSCRingBuffer<MidiPlayEvent> *_playbackEventBuffers;
158       // Various IPC buffers. NOT for playback events. Any thread can use this.
159       LockFreeMPSCRingBuffer<MidiPlayEvent> *_userEventBuffers;
160 
161       // Recording fifos. To speed up processing, one per channel plus one special system 'channel' for channel-less events like sysex.
162       MidiRecFifo _recordFifo[MusECore::MUSE_MIDI_CHANNELS + 1];
163 
164       // To hold current output program, and RPN/NRPN parameter numbers and values.
165       MidiOutputParams _curOutParamNums[MusECore::MUSE_MIDI_CHANNELS];
166 
167       RouteList _inRoutes, _outRoutes;
168 
169       // Fifo holds brief history of incoming external clock messages.
170       // Timestamped with both tick and frame so that pending play events can
171       //  be scheduled by frame.
172       // The audio thread processes this fifo and clears it.
173       LockFreeBuffer<ExtMidiClock> *_extClockHistoryFifo;
174 
175       // Holds latency computations each cycle.
176       TrackLatencyInfo _captureLatencyInfo;
177       TrackLatencyInfo _playbackLatencyInfo;
178 
179       // Returns the number of frames to shift forward output event scheduling times when putting events
180       //  into the eventFifos. This is not quite the same as latency (requiring a backwards shift)
181       //  although its requirement is a result of the latency.
182       // For any driver running in the audio thread (Jack midi, synth, metro etc) this value typically
183       //  will equal one segment size.
184       // For drivers running in their own thread (ALSA, OSC input) this will typically be near zero:
185       //  1 ms for ALSA given a standard sequencer timer f = 1000Hz, or near zero for OSC input.
pbForwardShiftFrames()186       inline virtual unsigned int pbForwardShiftFrames() const { return 0; }
187 
188       // Various IPC buffers. Any thread can use this.
eventBuffers(EventBufferType bufferType)189       inline LockFreeMPSCRingBuffer<MidiPlayEvent> *eventBuffers(EventBufferType bufferType)
190       {
191         switch(bufferType)
192         {
193           case PlaybackBuffer:
194             return _playbackEventBuffers;
195 
196           case UserBuffer:
197             return _userEventBuffers;
198         }
199         return _userEventBuffers;
200       }
201 
202       // Informs the device to clear (flush) the outEvents and event buffers.
203       // To be called by audio thread only. Typically from the device's handleStop routine.
setStopFlag(bool flag)204       void setStopFlag(bool flag) { _stopFlag.store(flag); }
205       // Returns whether the device is flagged to clear the outEvents and event buffers.
206       // To be called from the device's thread in the process routine.
stopFlag()207       bool stopFlag() const { return _stopFlag.load(); }
208 
209       void init();
210 
211    public:
212       MidiDevice();
213       MidiDevice(const QString& name);
214       virtual ~MidiDevice();
215 
sysExInProcessor()216       inline SysExInputProcessor* sysExInProcessor() { return &_sysExInProcessor; }
sysExOutProcessor()217       inline SysExOutputProcessor* sysExOutProcessor() { return &_sysExOutProcessor; }
218 
219       virtual MidiDeviceType deviceType() const = 0;
220       virtual QString deviceTypeString() const;
221 
222       // The meaning of the returned pointer depends on the driver.
223       // For Jack it returns the address of a Jack port, for ALSA it return the address of a snd_seq_addr_t.
inClientPort()224       inline virtual void* inClientPort() { return 0; }
outClientPort()225       inline virtual void* outClientPort() { return 0; }
226 
227       // These three are generally for ALSA.
setAddressClient(int)228       inline virtual void setAddressClient(int) { }
setAddressPort(int)229       inline virtual void setAddressPort(int) { }
230       // We (ab)use the ALSA value SND_SEQ_ADDRESS_UNKNOWN to
231       //  mean 'unavailable' if either client and port equal it.
isAddressUnknown()232       inline virtual bool isAddressUnknown() const { return true; }
233 
234       virtual QString open() = 0;
235       virtual void close() = 0;
writeRouting(int,Xml &)236       virtual void writeRouting(int, Xml&) const {  };
237 
inRoutes()238       RouteList* inRoutes()   { return &_inRoutes; }
outRoutes()239       RouteList* outRoutes()   { return &_outRoutes; }
noInRoute()240       bool noInRoute() const   { return _inRoutes.empty();  }
noOutRoute()241       bool noOutRoute() const  { return _outRoutes.empty(); }
242 
name()243       inline const QString& name() const      { return _name; }
244       // setName can be overloaded to do other things like setting port names, while setNameText just sets the text.
setName(const QString & s)245       inline virtual void setName(const QString& s)   { _name = s; }
246       // setNameText just sets the text, while setName can be overloaded to do other things like setting port names.
setNameText(const QString & s)247       inline void setNameText(const QString& s)  { _name = s; }
248 
midiPort()249       inline int midiPort() const             { return _port; }
250       void setPort(int p);
251 
rwFlags()252       inline int rwFlags() const              { return _rwFlags; }
openFlags()253       inline int openFlags() const            { return _openFlags; }
setOpenFlags(int val)254       inline void setOpenFlags(int val)       { _openFlags = val; }
setrwFlags(int val)255       inline void setrwFlags(int val)         { _rwFlags = val; }
state()256       inline const QString& state() const     { return _state; }
setState(const QString & s)257       inline void setState(const QString& s)  { _state = s; }
258 
isSynti()259       inline virtual bool isSynti() const     { return false; }
selectRfd()260       inline virtual int selectRfd()          { return -1; }
selectWfd()261       inline virtual int selectWfd()          { return -1; }
bytesToWrite()262       inline virtual int bytesToWrite()       { return 0; }
flush()263       inline virtual void flush()             {}
processInput()264       inline virtual void processInput()      {}
discardInput()265       inline virtual void discardInput()      {}
266 
267       // Event time and tick must be set by caller beforehand.
268       virtual void recordEvent(MidiRecordEvent&);
269 
270       // Add a stuck note. Returns false if event cannot be delivered.
addStuckNote(const MidiPlayEvent & ev)271       virtual bool addStuckNote(const MidiPlayEvent& ev) { _stuckNotes.add(ev); return true; }
272       // Put either a playback or a user event. Returns true if event cannot be delivered.
273       virtual bool putEvent(const MidiPlayEvent& ev,
274                                 LatencyType latencyType,
275                                 EventBufferType bufferType = UserBuffer);
curOutParamNums(int chan)276       MidiOutputParams* curOutParamNums(int chan) { return &_curOutParamNums[chan]; }
277       void resetCurOutParamNums(int chan = -1); // Reset channel's current parameter numbers to -1. All channels if chan = -1.
278 
279       virtual void handleStop();
280       virtual void handleSeek();
281 
282       virtual void processStuckNotes();
283 
collectMidiEvents()284       virtual void collectMidiEvents() {}
285       // Process midi events. The frame is used by devices such as ALSA
286       //  that require grabbing a timestamp as early as possible and
287       //  passing it along to all the devices. The other devices don't
288       //  require the frame since they 'compose' a buffer based on the
289       //  frame at cycle start.
290       virtual void processMidi(unsigned int /*curFrame*/ = 0) {}
291 
292       void beforeProcess();
293       void afterProcess();
tmpRecordCount(const unsigned int ch)294       int tmpRecordCount(const unsigned int ch)     { return _tmpRecordCount[ch]; }
recordEvents(const unsigned int ch)295       MidiRecFifo& recordEvents(const unsigned int ch) { return _recordFifo[ch]; }
sysexFIFOProcessed()296       bool sysexFIFOProcessed()                     { return _sysexFIFOProcessed; }
setSysexFIFOProcessed(bool v)297       void setSysexFIFOProcessed(bool v)            { _sysexFIFOProcessed = v; }
298 
299       static const int extClockHistoryCapacity;
extClockHistory()300       LockFreeBuffer<ExtMidiClock> *extClockHistory() { return _extClockHistoryFifo; }
301       void midiClockInput(unsigned int frame);
302 
303 
304       // Initializes this track's latency information in preparation for a latency scan.
305       virtual void prepareLatencyScan();
306       // Returns the latency of a given capture or playback port of the device.
portLatency(void *,bool)307       inline virtual unsigned int portLatency(void* /*port*/, bool /*capture*/) const { return 0; }
308       // The contribution to latency by the device's own members (midi effect rack, Jack ports etc).
309       // A midi device can contain both an input and an output. The 'capture' parameter determines which one.
selfLatencyMidi(int,bool)310       inline virtual float selfLatencyMidi(int /*channel*/, bool /*capture*/) const { return 0.0f; }
311       // The cached worst latency of all the contributions from the track's own members (audio effect rack, etc)
312       //  plus any port latency if applicable.
313       virtual float getWorstSelfLatencyMidi(bool capture);
314       // Whether this track (and the branch it is in) can force other parallel branches to
315       //  increase their latency compensation to match this one.
316       // If false, this branch will NOT disturb other parallel branches' compensation,
317       //  intead only allowing compensation UP TO the worst case in other branches.
318       virtual bool canDominateOutputLatencyMidi(bool capture) const;
319       virtual bool canDominateInputLatencyMidi(bool capture) const;
320       // Whether this track (and the branch it is in) can force other parallel branches to
321       //  increase their latency compensation to match this one - IF this track is an end-point
322       //  and the branch allows domination.
323       // If false, this branch will NOT disturb other parallel branches' compensation,
324       //  intead only allowing compensation UP TO the worst case in other branches.
325       virtual bool canDominateEndPointLatencyMidi(bool capture) const;
326       // Whether this track and its branch can correct for latency, not just compensate.
canCorrectOutputLatencyMidi()327       inline virtual bool canCorrectOutputLatencyMidi() const { return false; }
328       // Whether the track can pass latency values through, the SAME as if record monitor is
329       //  supported and on BUT does not require record monitor support.
330       // This is for example in the metronome MetronomeSynthI, since it is unique in that it
331       //  can correct its own latency unlike other synths, but it does not 'pass through'
332       //  the latency values to what drives it like other synths.
333       virtual bool canPassThruLatencyMidi(bool capture) const;
334       // Whether any of the connected output routes are effectively connected.
335       // That means track is not off, track is monitored where applicable, etc,
336       //   ie. signal can actually flow.
337       // For Wave Tracks for example, asks whether the track is an end-point from the view of the input side.
338       virtual bool isLatencyInputTerminalMidi(bool capture);
339       // Whether any of the connected output routes are effectively connected.
340       // That means track is not off, track is monitored where applicable, etc,
341       //   ie. signal can actually flow.
342       // For Wave Tracks for example, asks whether the track is an end-point from the view of the playback side.
343       virtual bool isLatencyOutputTerminalMidi(bool capture);
344 
345       virtual TrackLatencyInfo& getDominanceInfoMidi(bool capture, bool input);
346       virtual TrackLatencyInfo& getDominanceLatencyInfoMidi(bool capture, bool input);
347       // The finalWorstLatency is the grand final worst-case latency, of any output track or open branch,
348       //  determined in the complete getDominanceLatencyInfo() scan.
349       // The callerBranchLatency is the inherent branch latency of the calling track, or zero if calling from
350       //  the very top outside of the branch heads (outside of output tracks or open branches).
351       // The callerBranchLatency is accumulated as setCorrectionLatencyInfo() is called on each track
352       //  in a branch of the graph.
353       virtual TrackLatencyInfo& setCorrectionLatencyInfoMidi(bool capture, bool input, float finalWorstLatency, float callerBranchLatency = 0.0f);
354       virtual TrackLatencyInfo& getLatencyInfoMidi(bool capture, bool input);
355       // Used during latency compensation processing. When analyzing in 'reverse' this mechansim is
356       //  needed only to equalize the timing of all the AudioOutput tracks.
357       // It is applied as a direct offset in the latency delay compensator in getData().
358       virtual unsigned long latencyCompWriteOffsetMidi(bool capture) const;
359       virtual void setLatencyCompWriteOffsetMidi(float worstCase, bool capture);
360       };
361 
362 //---------------------------------------------------------
363 //   MidiDeviceList
364 //---------------------------------------------------------
365 
366 typedef std::list<MidiDevice*>::iterator iMidiDevice;
367 typedef std::list<MidiDevice*>::const_iterator ciMidiDevice;
368 
369 class MidiDeviceList : public std::list<MidiDevice*>
370 {
371    public:
372       void add(MidiDevice* dev);
373       void remove(MidiDevice* dev);
374       MidiDevice* find(const QString& name, int typeHint = -1);
375 
find(const MidiDevice * dev)376       iterator find(const MidiDevice* dev)
377       {
378         for(iterator i = begin(); i != end(); ++i)
379           if(*i == dev)
380             return i;
381         return end();
382       }
383 
find(const MidiDevice * dev)384       const_iterator find(const MidiDevice* dev) const
385       {
386         for(const_iterator i = begin(); i != end(); ++i)
387           if(*i == dev)
388             return i;
389         return end();
390       }
391 
contains(const MidiDevice * dev)392       bool contains(const MidiDevice* dev) const
393       {
394         for(const_iterator i = begin(); i != end(); ++i)
395           if(*i == dev)
396             return true;
397         return false;
398       }
399 };
400 
401 extern void initMidiDevices();
402 extern bool filterEvent(const MEvent& event, int type, bool thru);
403 
404 } // namespace MusECore
405 
406 namespace MusEGlobal {
407 extern MusECore::MidiDeviceList midiDevices;
408 }
409 
410 #endif
411 
412