1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: midiport.h,v 1.9.2.6 2009/11/17 22:08:22 terminator356 Exp $
5 //
6 //  (C) Copyright 1999-2004 Werner Schweer (ws@seh.de)
7 //  (C) Copyright 2012, 2017 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 __MIDIPORT_H__
26 #define __MIDIPORT_H__
27 
28 #include <QString>
29 
30 #include "globaldefs.h"
31 #include "sync.h"
32 #include "route.h"
33 
34 namespace MusECore {
35 
36 
37 // Forward declarations:
38 class MidiDevice;
39 class MidiInstrument;
40 class MidiController;
41 class MidiControllerList;
42 class MidiCtrlValListList;
43 class MidiCtrlValList;
44 class Part;
45 class MidiPlayEvent;
46 class Xml;
47 
48 //---------------------------------------------------------
49 //   MidiPort
50 //---------------------------------------------------------
51 
52 class MidiPort {
53   public:
54       // IDs for the various IPC FIFOs that are used.
55       enum EventFifoIds
56       {
57         // Playback queued events put by the audio process thread.
58         PlayFifo=0,
59         // Gui events put by our gui thread.
60         GuiFifo=1,
61         // OSC events put by the OSC thread.
62         OSCFifo=2,
63         // Monitor input passthrough events put by Jack devices (audio process thread).
64         JackFifo=3,
65         // Monitor input passthrough events put by ALSA devices (midi seq thread).
66         ALSAFifo=4
67       };
68 
69   private:
70       MidiCtrlValListList* _controller;
71       MidiDevice* _device;
72       QString _state;               // result of device open
73       MidiInstrument* _instrument;
74       // A corresponding synth track's index in the song file, if used. Can be -1.
75       // Temporary during loading to avoid using globally or locally
76       //  'unique' identifiers in the song file, such as the serial,
77       //  to resolve references.
78       int _tmpTrackIdx;
79       // Temporary during loading. String ref to an instrument.
80       // It also helps support older files where only a string was used.
81       QString _tmpInstrRef;
82 
83       AutomationType _automationType[MusECore::MUSE_MIDI_CHANNELS];
84       // Holds sync settings and detection monitors.
85       MidiSyncInfo _syncInfo;
86       // Just a flag to say the port was found in the song file, even if it has no device right now.
87       bool _foundInSongFile;
88       // When creating a new midi track, add these global default channel routes to/from this port. Ignored if 0.
89       int _defaultInChannels;    // These are bit-wise channel masks.
90       int _defaultOutChannels;   //
91       // Whether Init sysexes and default controller values have been sent. To be reset whenever
92       //  something about the port changes like device, Jack routes, or instrument.
93       bool _initializationsSent;
94 
95       RouteList _inRoutes, _outRoutes;
96 
97       void clearDevice();
98 
99       // Creates a controller in this port's controller list.
100       // Returns true if the controller was created.
101       // To be called by gui thread only.
102       bool createController(int chan, int ctrl);
103 
104    public:
105       MidiPort();
106       ~MidiPort();
107 
108       // Temporary, used during loading to resolve references to instruments.
setTmpFileRefs(int i,const QString & s)109       void setTmpFileRefs(int i, const QString& s) { _tmpTrackIdx = i; _tmpInstrRef = s; }
clearTmpFileRefs()110       void clearTmpFileRefs() { _tmpTrackIdx = -1; _tmpInstrRef = QString(); }
tmpTrackRef()111       int tmpTrackRef() const { return _tmpTrackIdx; }
tmpInstrRef()112       const QString& tmpInstrRef() const { return _tmpInstrRef; }
113 
114       //
115       // manipulate active midi controller
116       //
controller()117       MidiCtrlValListList* controller() { return _controller; }
118       // Determine controller value at tick on channel, using values stored by ANY part.
119       int getCtrl(int ch, unsigned int tick, int ctrl) const;
120       // Determine controller value at tick on channel, using values stored by the SPECIFIC part.
121       int getCtrl(int ch, unsigned int tick, int ctrl, Part* part) const;
122       // Determine controller value at tick on channel, using values stored by ANY part,
123       //  ignoring values that are OUTSIDE of their parts, or muted or off parts or tracks.
124       int getVisibleCtrl(int ch, unsigned int tick, int ctrl, bool inclMutedParts, bool inclMutedTracks, bool inclOffTracks) const;
125       // Determine controller value at tick on channel, using values stored by the SPECIFIC part,
126       //  ignoring values that are OUTSIDE of the part, or muted or off part or track.
127       int getVisibleCtrl(int ch, unsigned int tick, int ctrl, Part* part, bool inclMutedParts, bool inclMutedTracks, bool inclOffTracks) const;
128       bool setControllerVal(int ch, unsigned int tick, int ctrl, int val, Part* part);
129       // Can be CTRL_VAL_UNKNOWN until a valid state is set
130       int lastValidHWCtrlState(int ch, int ctrl) const;
131       double lastValidHWDCtrlState(int ch, int ctrl) const;
132       int hwCtrlState(int ch, int ctrl) const;
133       double hwDCtrlState(int ch, int ctrl) const;
134       bool setHwCtrlState(int ch, int ctrl, int val);
135       bool setHwCtrlState(int ch, int ctrl, double val);
136       bool setHwCtrlStates(int ch, int ctrl, int val, int lastval);
137       bool setHwCtrlStates(int ch, int ctrl, double val, double lastval);
138       bool setHwCtrlState(const MidiPlayEvent&);
139       void deleteController(int ch, unsigned int tick, int ctrl, int val, Part* part);
140       void addDefaultControllers();
141 
142       bool guiVisible() const;
143       void showGui(bool);
144       bool hasGui() const;
145       bool nativeGuiVisible() const;
146       void showNativeGui(bool);
147       bool hasNativeGui() const;
148 
149       int portno() const;
foundInSongFile()150       bool foundInSongFile() const              { return _foundInSongFile; }
setFoundInSongFile(bool b)151       void setFoundInSongFile(bool b)           { _foundInSongFile = b; }
152 
device()153       MidiDevice* device() const                { return _device; }
state()154       const QString& state() const              { return _state; }
setState(const QString & s)155       void setState(const QString& s)           { _state = s; }
156       // If instrument is given it will be set, otherwise it won't touch the existing instrument.
157       void setMidiDevice(MidiDevice* dev, MidiInstrument* instrument = nullptr);
158       const QString& portname() const;
instrument()159       MidiInstrument* instrument() const   { return _instrument; }
setInstrument(MidiInstrument * i)160       void setInstrument(MidiInstrument* i) { _instrument = i; }
161       void changeInstrument(MidiInstrument* i);
162       MidiController* midiController(int num, int chan = -1, bool createIfNotFound = true) const;
163       MidiCtrlValList* addManagedController(int channel, int ctrl);
164       // To be called from realtime audio thread only.
165       void tryCtrlInitVal(int chan, int ctl, int val);
166       int limitValToInstrCtlRange(int ctl, int val, int chan = -1);
167       double limitValToInstrCtlRange(int ctl, double val, int chan = -1);
168       int limitValToInstrCtlRange(const MidiController* mc, int val);
169       double limitValToInstrCtlRange(const MidiController* mc, double val);
170       MidiController* drumController(int ctl);
171       // Update drum maps when patch is known.
172       // If audio is running (and not idle) this should only be called by the rt audio thread.
173       // Returns true if maps were changed.
174       bool updateDrumMaps(int chan, int patch);
175       // Update drum maps when patch is not known.
176       // If audio is running (and not idle) this should only be called by the rt audio thread.
177       // Returns true if maps were changed.
178       bool updateDrumMaps();
179 
defaultInChannels()180       int defaultInChannels() const { return _defaultInChannels; }
defaultOutChannels()181       int defaultOutChannels() const { return _defaultOutChannels; }
setDefaultInChannels(int c)182       void setDefaultInChannels(int c) { _defaultInChannels = c; }
setDefaultOutChannels(int c)183       void setDefaultOutChannels(int c) { _defaultOutChannels = c; }
inRoutes()184       RouteList* inRoutes()    { return &_inRoutes; }
outRoutes()185       RouteList* outRoutes()   { return &_outRoutes; }
noInRoute()186       bool noInRoute() const   { return _inRoutes.empty();  }
noOutRoute()187       bool noOutRoute() const  { return _outRoutes.empty(); }
188       void writeRouting(int, Xml&) const;
189 
190       // send events to midi device and keep track of
191       // device state:
192       void sendGmOn();
193       void sendGsOn();
194       void sendXgOn();
195       void sendGmInitValues();
196       void sendGsInitValues();
197       void sendXgInitValues();
198       void sendStart();
199       void sendStop();
200       void sendContinue();
201       void sendSongpos(int);
202       void sendClock();
203       void sendSysex(const unsigned char* p, int n);
204       void sendMMCLocate(unsigned char ht, unsigned char m,
205                          unsigned char s, unsigned char f, unsigned char sf, int devid = -1);
206       void sendMMCStop(int devid = -1);
207       void sendMMCDeferredPlay(int devid = -1);
208 
209       // Send Instrument Init sequences and controller defaults etc. Return true if success.
210       // To be called from realtime audio thread only.
211       bool sendPendingInitializations(bool force = true);  // Per port
212       // Send initial controller values. Called by above method, and elsewhere.
213       bool sendInitialControllers(unsigned start_time = 0);
initSent()214       bool initSent() const { return _initializationsSent; }
clearInitSent()215       void clearInitSent() { _initializationsSent = false; }
216 
217       // Put an event into the gui2audio fifo for playback. Calls stageEvent().
218       // Called from gui thread only. Returns true if event cannot be delivered.
219       bool putHwCtrlEvent(const MidiPlayEvent&);
220       // Put an event into both the device and the gui2audio fifos for playback. Calls stageEvent().
221       // Called from gui thread only. Returns true if event cannot be delivered.
222       bool putEvent(const MidiPlayEvent&);
223       // Special method for incrementing a value: Handles getting the current hw value,
224       //  incrementing it (as dB if specified), and sending it and setting the current hw value.
225       // Called from gui thread only. Returns true if event cannot be delivered.
226       // NOTE: Caller should use the Audio::msgAudioWait() to wait for the current value
227       //        to change in the audio thread before calling again, especially rapidly.
228       //       This method looks at the current value, so the current value must be up to date.
229       //       It will not call Audio::msgAudioWait(), to allow caller to optimize multiple calls.
230 // TODO: An increment method seems possible: Wait for gui2audio to increment, then send to driver,
231 //        which incurs up to one extra segment delay (if Jack midi).
232       bool putControllerValue(int port, int chan, int ctlnum, double val, bool isDb);
233       // To be called from audio thread only. Returns true on success.
234       // If createAsNeeded is true, automatically send a message to the gui thread to
235       //  create items such as controllers, and cache the events sent to it and re-put
236       //  them after the controller has been created.
237       bool handleGui2AudioEvent(const MidiPlayEvent&, bool createAsNeeded);
238 
239       bool sendHwCtrlState(const MidiPlayEvent&, bool forceSend = false );
automationType(int channel)240       AutomationType automationType(int channel) { return _automationType[channel]; }
setAutomationType(int channel,AutomationType t)241       void setAutomationType(int channel, AutomationType t) {
242             _automationType[channel] = t;
243             }
syncInfo()244       MidiSyncInfo& syncInfo() { return _syncInfo; }
245       };
246 
247 extern void initMidiPorts();
248 
249 // p4.0.17 Turn off if and when multiple output routes supported.
250 #if 1
251 extern void setPortExclusiveDefOutChan(int /*port*/, int /*chan*/);
252 #endif
253 
254 extern MidiControllerList defaultManagedMidiController;
255 
256 } // namespace MusECore
257 
258 namespace MusEGlobal {
259 extern MusECore::MidiPort midiPorts[MusECore::MIDI_PORTS];
260 }
261 
262 #endif
263 
264