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