1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: midiport.cpp,v 1.21.2.15 2009/12/07 20:11:51 terminator356 Exp $
5 //
6 //  (C) Copyright 2000-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 #include <set>
26 
27 #include <QString>
28 
29 #include "midiport.h"
30 #include "midi_consts.h"
31 #include "midiseq.h"
32 #include "gconfig.h"
33 #include "globals.h"
34 #include "synth.h"
35 #include "app.h"
36 #include "song.h"
37 #include "menutitleitem.h"
38 #include "icons.h"
39 #include "track.h"
40 #include "drummap.h"
41 #include "audio.h"
42 #include "muse_math.h"
43 #include "sysex_helper.h"
44 
45 // Forwards from header:
46 #include "mididev.h"
47 #include "instruments/minstrument.h"
48 #include "part.h"
49 #include "midi_controller.h"
50 #include "midictrl.h"
51 #include "mpevent.h"
52 #include "xml.h"
53 
54 namespace MusEGlobal {
55 MusECore::MidiPort midiPorts[MusECore::MIDI_PORTS];
56 }
57 
58 namespace MusECore {
59 
60 MidiControllerList defaultManagedMidiController;
61 
62 //---------------------------------------------------------
63 //   initMidiPorts
64 //---------------------------------------------------------
65 
initMidiPorts()66 void initMidiPorts()
67       {
68       defaultManagedMidiController.add(&pitchCtrl);
69       defaultManagedMidiController.add(&programCtrl);
70       defaultManagedMidiController.add(&volumeCtrl);
71       defaultManagedMidiController.add(&panCtrl);
72       defaultManagedMidiController.add(&reverbSendCtrl);
73       defaultManagedMidiController.add(&chorusSendCtrl);
74       defaultManagedMidiController.add(&variationSendCtrl);
75 
76       for (int i = 0; i < MusECore::MIDI_PORTS; ++i) {
77             MidiPort* port = &MusEGlobal::midiPorts[i];
78 
79             //
80             // create minimum set of managed controllers
81             // to make midi mixer operational
82             //
83             port->addDefaultControllers();
84 
85             port->changeInstrument(registerMidiInstrument("GM"));
86             port->syncInfo().setPort(i);
87             // Set the first channel on the first port to auto-connect to midi track outputs.
88             if(i == 0)
89             {
90 
91               // robert: removing the default init on several places to allow for the case
92               // where you rather want the midi track to default to the last created port
93               // this can only happen if there is _no_ default set
94               //
95               // port->setDefaultOutChannels(1);
96 
97               port->setDefaultInChannels(1);
98             }
99             }
100       }
101 
102 //---------------------------------------------------------
103 //   MidiPort
104 //---------------------------------------------------------
105 
MidiPort()106 MidiPort::MidiPort()
107    : _state("not configured")
108       {
109       _initializationsSent = false;
110       _defaultInChannels  = 0;
111       _defaultOutChannels = 0;
112       _device     = 0;
113       _instrument = 0;
114       _tmpTrackIdx = -1;
115       _controller = new MidiCtrlValListList();
116       _foundInSongFile = false;
117       }
118 
119 //---------------------------------------------------------
120 //   MidiPort
121 //---------------------------------------------------------
122 
~MidiPort()123 MidiPort::~MidiPort()
124       {
125       delete _controller;
126       }
127 
128 //---------------------------------------------------------
129 //   guiVisible
130 //---------------------------------------------------------
131 
guiVisible() const132 bool MidiPort::guiVisible() const
133       {
134       if(!_device)
135         return false;
136       SynthI* synth = 0;
137       if(_device->isSynti())
138         synth = static_cast<SynthI*>(_device);
139       if(!synth)
140         return false;
141       return synth->guiVisible();
142       }
143 
144 //---------------------------------------------------------
145 //   showGui
146 //---------------------------------------------------------
147 
showGui(bool v)148 void MidiPort::showGui(bool v)
149 {
150   if(!_device)
151     return;
152   SynthI* synth = 0;
153   if(_device->isSynti())
154     synth = static_cast<SynthI*>(_device);
155   if(!synth)
156     return;
157   synth->showGui(v);
158 }
159 
160 //---------------------------------------------------------
161 //   hasGui
162 //---------------------------------------------------------
163 
hasGui() const164 bool MidiPort::hasGui() const
165       {
166       if(!_device)
167         return false;
168       SynthI* synth = 0;
169       if(_device->isSynti())
170         synth = static_cast<SynthI*>(_device);
171       if(!synth)
172         return false;
173       return synth->hasGui();
174       }
175 
176 //---------------------------------------------------------
177 //   nativeGuiVisible
178 //---------------------------------------------------------
179 
nativeGuiVisible() const180 bool MidiPort::nativeGuiVisible() const
181       {
182       if(!_device)
183         return false;
184       SynthI* synth = 0;
185       if(_device->isSynti())
186         synth = static_cast<SynthI*>(_device);
187       if(!synth)
188         return false;
189       return synth->nativeGuiVisible();
190       }
191 
192 //---------------------------------------------------------
193 //   showNativeGui
194 //---------------------------------------------------------
195 
showNativeGui(bool v)196 void MidiPort::showNativeGui(bool v)
197 {
198   if(!_device)
199     return;
200   SynthI* synth = 0;
201   if(_device->isSynti())
202     synth = static_cast<SynthI*>(_device);
203   if(!synth)
204     return;
205   synth->showNativeGui(v);
206 }
207 
208 //---------------------------------------------------------
209 //   hasNativeGui
210 //---------------------------------------------------------
211 
hasNativeGui() const212 bool MidiPort::hasNativeGui() const
213       {
214       if(!_device)
215         return false;
216       SynthI* synth = 0;
217       if(_device->isSynti())
218         synth = static_cast<SynthI*>(_device);
219       if(!synth)
220         return false;
221       return synth->hasNativeGui();
222       }
223 
224 //---------------------------------------------------------
225 //   setDevice
226 //---------------------------------------------------------
227 
setMidiDevice(MidiDevice * dev,MidiInstrument * instrument)228 void MidiPort::setMidiDevice(MidiDevice* dev, MidiInstrument* instrument)
229       {
230       if (_device) {
231             if (_device->isSynti())
232                   _instrument = genericMidiInstrument;
233             _device->setPort(-1);
234             _device->close();
235             _initializationsSent = false;
236             // Wait until upcoming process call has finished. Otherwise Jack may crash!
237             MusEGlobal::audio->msgAudioWait();
238             }
239       if (dev) {
240             for (int i = 0; i < MusECore::MIDI_PORTS; ++i) {
241                   MidiPort* mp = &MusEGlobal::midiPorts[i];
242                   if (mp->device() == dev) {
243                         if(dev->isSynti())
244                           mp->changeInstrument(genericMidiInstrument);
245                         // move device
246                         _state = mp->state();
247                         mp->clearDevice();
248                         break;
249                         }
250                   }
251             _device = dev;
252             // If an instrument was given, use it. Otherwise don't touch the instrument.
253             if(instrument)
254               _instrument = instrument;
255             _state = _device->open();
256             _device->setPort(portno());
257             _initializationsSent = false;
258             }
259 
260       else
261             clearDevice();
262       }
263 
264 //---------------------------------------------------------
265 //   sendPendingInitializations
266 //   Return true if success.
267 //   To be called from realtime audio thread only.
268 //---------------------------------------------------------
269 
sendPendingInitializations(bool force)270 bool MidiPort::sendPendingInitializations(bool force)
271 {
272   if(!_device || !(_device->openFlags() & 1))   // Not writable?
273     return false;
274 
275   bool rv = true;
276   int port = portno();
277 
278   //
279   // test for explicit instrument initialization
280   //
281 
282 //   unsigned last_tick = 0;
283   unsigned last_frame = 0;
284   MusECore::MidiInstrument* instr = instrument();
285   if(instr && MusEGlobal::config.midiSendInit && (force || !_initializationsSent))
286   {
287     // Send the Instrument Init sequences.
288     EventList* events = instr->midiInit();
289     if(!events->empty())
290     {
291       for(iEvent ie = events->begin(); ie != events->end(); ++ie)
292       {
293         if(ie->second.type() == Sysex)
294           last_frame += sysexDuration(ie->second.dataLen(), MusEGlobal::sampleRate);
295         MusECore::MidiPlayEvent ev = ie->second.asMidiPlayEvent(last_frame + MusEGlobal::audio->curSyncFrame(), port, 0);
296         _device->putEvent(ev, MidiDevice::NotLate);
297       }
298       // Give a bit of time for the last Init sysex to settle?
299       last_frame += 100;
300     }
301     _initializationsSent = true; // Mark as having been sent.
302   }
303 
304   // Send the Instrument controller default values.
305   sendInitialControllers(last_frame);
306 
307   return rv;
308 }
309 
310 //---------------------------------------------------------
311 //   sendInitialControllers
312 //   Return true if success.
313 //---------------------------------------------------------
314 
sendInitialControllers(unsigned start_time)315 bool MidiPort::sendInitialControllers(unsigned start_time)
316 {
317   MusECore::MetronomeSettings* metro_settings =
318     MusEGlobal::metroUseSongSettings ? &MusEGlobal::metroSongSettings : &MusEGlobal::metroGlobalSettings;
319 
320   bool rv = true;
321   int port = portno();
322 
323   // Find all channels of this port used in the song...
324   bool usedChans[MusECore::MUSE_MIDI_CHANNELS];
325   int usedChanCount = 0;
326   for(int i = 0; i < MusECore::MUSE_MIDI_CHANNELS; ++i)
327     usedChans[i] = false;
328   if(MusEGlobal::song->click() && metro_settings->clickPort == port)
329   {
330     usedChans[metro_settings->clickChan] = true;
331     ++usedChanCount;
332   }
333   for(ciMidiTrack imt = MusEGlobal::song->midis()->begin(); imt != MusEGlobal::song->midis()->end(); ++imt)
334   {
335     if((*imt)->type() == MusECore::Track::DRUM)
336     {
337       for(int i = 0; i < DRUM_MAPSIZE; ++i)
338       {
339         // Default to track port if -1 and track channel if -1.
340         int mport = (*imt)->drummap()[i].port;
341         if(mport == -1)
342           mport = (*imt)->outPort();
343         int mchan = (*imt)->drummap()[i].channel;
344         if(mchan == -1)
345           mchan = (*imt)->outChannel();
346         if(mport != port || usedChans[mchan])
347           continue;
348         usedChans[mchan] = true;
349         ++usedChanCount;
350         if(usedChanCount >= MusECore::MUSE_MIDI_CHANNELS)
351           break;  // All are used, done searching.
352       }
353     }
354     else
355     {
356       if((*imt)->outPort() != port || usedChans[(*imt)->outChannel()])
357         continue;
358       usedChans[(*imt)->outChannel()] = true;
359       ++usedChanCount;
360     }
361 
362     if(usedChanCount >= MusECore::MUSE_MIDI_CHANNELS)
363       break;  // All are used, done searching.
364   }
365 
366   // NOT for syntis. Use midiState and/or initParams for that.
367   if(MusEGlobal::config.midiSendInit && MusEGlobal::config.midiSendCtlDefaults && _instrument && !_device->isSynti())
368   {
369     MusECore::MidiControllerList* cl = new MusECore::MidiControllerList();
370 
371     MidiController* mc;
372 
373     for(int chan = 0; chan < MusECore::MUSE_MIDI_CHANNELS; ++chan)
374     {
375       if(!usedChans[chan])
376         continue;  // This channel on this port is not used in the song.
377 
378       const int patch = hwCtrlState(chan, CTRL_PROGRAM);
379       cl->clear();
380       instrument()->getControllers(cl, chan, patch);
381 
382       for(ciMidiController imc = cl->begin(); imc != cl->end(); ++imc)
383       {
384         mc = imc->second;
385         ciMidiCtrlValList i;
386 
387         // Look for an initial value for this midi controller, on this midi channel, in the song...
388         for(i = _controller->begin(); i != _controller->end(); ++i)
389         {
390           int channel = i->first >> 24;
391           int cntrl   = i->first & 0xffffff;
392           int val     = i->second->hwVal();
393           if(channel == chan && cntrl == mc->num() && val != CTRL_VAL_UNKNOWN)
394             break;
395         }
396         // If no initial value was found for this midi controller, on this midi channel, in the song...
397         if(i == _controller->end())
398         {
399           // If the instrument's midi controller has an initial value, send it now.
400           if(mc->initVal() != CTRL_VAL_UNKNOWN)
401           {
402             int ctl = mc->num();
403             // Note the addition of bias!
404             _device->putEvent(MidiPlayEvent(start_time, port, chan,
405               ME_CONTROLLER, ctl, mc->initVal() + mc->bias()), MidiDevice::NotLate);
406             // Set it once so the 'last HW value' is set, and control knobs are positioned at the value...
407             // Set it again so that control labels show 'off'...
408             setHwCtrlStates(chan, ctl, CTRL_VAL_UNKNOWN, mc->initVal() + mc->bias());
409           }
410         }
411       }
412     }
413     delete cl;
414   }
415 
416   // init HW controller state
417   for (iMidiCtrlValList i = _controller->begin(); i != _controller->end(); ++i)
418   {
419       int channel = i->first >> 24;
420       if(!usedChans[channel])
421         continue;  // This channel on this port is not used in the song.
422       int cntrl   = i->first & 0xffffff;
423       int val     = i->second->hwVal();
424       if (val != CTRL_VAL_UNKNOWN)
425       {
426         _device->putEvent(MidiPlayEvent(start_time, port, channel,
427           ME_CONTROLLER, cntrl, val), MidiDevice::NotLate);
428         // Set it once so the 'last HW value' is set, and control knobs are positioned at the value...
429         setHwCtrlState(channel, cntrl, val);
430       }
431   }
432 
433   return rv;
434 }
435 
436 //---------------------------------------------------------
437 //   changeInstrument
438 //   If audio is running (and not idle) this should only be called by the rt audio thread.
439 //---------------------------------------------------------
440 
changeInstrument(MidiInstrument * i)441 void MidiPort::changeInstrument(MidiInstrument* i)
442 {
443   if(_instrument == i)
444     return;
445   _instrument = i;
446   _initializationsSent = false;
447   updateDrumMaps();
448 }
449 
450 //---------------------------------------------------------
451 //   clearDevice
452 //---------------------------------------------------------
453 
clearDevice()454 void MidiPort::clearDevice()
455       {
456       _device = 0;
457       _initializationsSent = false;
458       _state  = "not configured";
459       }
460 
461 //---------------------------------------------------------
462 //   portno
463 //---------------------------------------------------------
464 
portno() const465 int MidiPort::portno() const
466       {
467       for (int i = 0; i < MusECore::MIDI_PORTS; ++i) {
468             if (&MusEGlobal::midiPorts[i] == this)
469                   return i;
470             }
471       return -1;
472       }
473 
474 //---------------------------------------------------------
475 //   portname
476 //---------------------------------------------------------
477 
portname() const478 const QString& MidiPort::portname() const
479       {
480       static const QString none(QT_TRANSLATE_NOOP("@default", "<none>"));
481       if (_device)
482             return _device->name();
483       else
484             return none;
485       }
486 
487 //---------------------------------------------------------
488 //   tryCtrlInitVal
489 //   To be called from realtime audio thread only.
490 //---------------------------------------------------------
491 
tryCtrlInitVal(int chan,int ctl,int val)492 void MidiPort::tryCtrlInitVal(int chan, int ctl, int val)
493 {
494   // Look for an initial value in the song for this midi controller, on this midi channel... (p4.0.27)
495   iMidiCtrlValList i = _controller->find(chan, ctl);
496   if(i != _controller->end())
497   {
498     int v = i->second->value(0);   // Value at tick 0.
499     if(v != CTRL_VAL_UNKNOWN)
500     {
501       if(_device)
502         _device->putEvent(MidiPlayEvent(0, portno(), chan, ME_CONTROLLER, ctl, v), MidiDevice::NotLate);
503 
504       // Set it once so the 'last HW value' is set, and control knobs are positioned at the value...
505       setHwCtrlState(chan, ctl, v);
506 
507       return;
508     }
509   }
510 
511   // No initial value was found in the song for this midi controller on this midi channel. Try the instrument...
512   if(_instrument)
513   {
514     const int patch = hwCtrlState(chan, CTRL_PROGRAM);
515     const MidiController* mc = instrument()->findController(ctl, chan, patch);
516 
517     int initval = mc->initVal();
518 
519     // Initialize from either the instrument controller's initial value, or the supplied value.
520     if(initval != CTRL_VAL_UNKNOWN)
521     {
522       if(_device)
523       {
524         MidiPlayEvent ev(0, portno(), chan, ME_CONTROLLER, ctl, initval + mc->bias());
525       _device->putEvent(ev, MidiDevice::NotLate);
526       }
527       setHwCtrlStates(chan, ctl, CTRL_VAL_UNKNOWN, initval + mc->bias());
528 
529       return;
530     }
531   }
532 
533   // No initial value was found in the song or instrument for this midi controller. Just send the given value.
534   if(_device)
535   {
536     MidiPlayEvent ev(0, portno(), chan, ME_CONTROLLER, ctl, val);
537     _device->putEvent(ev, MidiDevice::NotLate);
538   }
539   setHwCtrlStates(chan, ctl, CTRL_VAL_UNKNOWN, val);
540 }
541 
542 //---------------------------------------------------------
543 //   sendGmInitValues
544 //---------------------------------------------------------
545 
sendGmInitValues()546 void MidiPort::sendGmInitValues()
547 {
548   for (int i = 0; i < MusECore::MUSE_MIDI_CHANNELS; ++i) {
549         // By T356. Initialize from instrument controller if it has an initial value, otherwise use the specified value.
550         // Tested: Ultimately, a track's controller stored values take priority by sending any 'zero time' value
551         //  AFTER these GM/GS/XG init routines are called via initDevices().
552         tryCtrlInitVal(i, CTRL_PROGRAM,      0);
553         tryCtrlInitVal(i, CTRL_PITCH,        0);
554         tryCtrlInitVal(i, CTRL_VOLUME,     100);
555         tryCtrlInitVal(i, CTRL_PANPOT,      64);
556         tryCtrlInitVal(i, CTRL_REVERB_SEND, 40);
557         tryCtrlInitVal(i, CTRL_CHORUS_SEND,  0);
558         }
559 }
560 
561 //---------------------------------------------------------
562 //   sendGsInitValues
563 //---------------------------------------------------------
564 
sendGsInitValues()565 void MidiPort::sendGsInitValues()
566 {
567   sendGmInitValues();
568 }
569 
570 //---------------------------------------------------------
571 //   sendXgInitValues
572 //---------------------------------------------------------
573 
sendXgInitValues()574 void MidiPort::sendXgInitValues()
575 {
576   for (int i = 0; i < MusECore::MUSE_MIDI_CHANNELS; ++i) {
577         // By T356. Initialize from instrument controller if it has an initial value, otherwise use the specified value.
578         tryCtrlInitVal(i, CTRL_PROGRAM, 0);
579         tryCtrlInitVal(i, CTRL_MODULATION, 0);
580         tryCtrlInitVal(i, CTRL_PORTAMENTO_TIME, 0);
581         tryCtrlInitVal(i, CTRL_VOLUME, 0x64);
582         tryCtrlInitVal(i, CTRL_PANPOT, 0x40);
583         tryCtrlInitVal(i, CTRL_EXPRESSION, 0x7f);
584         tryCtrlInitVal(i, CTRL_SUSTAIN, 0x0);
585         tryCtrlInitVal(i, CTRL_PORTAMENTO, 0x0);
586         tryCtrlInitVal(i, CTRL_SOSTENUTO, 0x0);
587         tryCtrlInitVal(i, CTRL_SOFT_PEDAL, 0x0);
588         tryCtrlInitVal(i, CTRL_HARMONIC_CONTENT, 0x40);
589         tryCtrlInitVal(i, CTRL_RELEASE_TIME, 0x40);
590         tryCtrlInitVal(i, CTRL_ATTACK_TIME, 0x40);
591         tryCtrlInitVal(i, CTRL_BRIGHTNESS, 0x40);
592         tryCtrlInitVal(i, CTRL_REVERB_SEND, 0x28);
593         tryCtrlInitVal(i, CTRL_CHORUS_SEND, 0x0);
594         tryCtrlInitVal(i, CTRL_VARIATION_SEND, 0x0);
595         }
596 }
597 
598 //---------------------------------------------------------
599 //   sendGmOn
600 //    send GM-On message to midi device and keep track
601 //    of device state
602 //---------------------------------------------------------
603 
sendGmOn()604 void MidiPort::sendGmOn()
605       {
606       sendSysex(gmOnMsg, gmOnMsgLen);
607       }
608 
609 //---------------------------------------------------------
610 //   sendGsOn
611 //    send Roland GS-On message to midi device and keep track
612 //    of device state
613 //---------------------------------------------------------
614 
sendGsOn()615 void MidiPort::sendGsOn()
616       {
617       sendSysex(gsOnMsg2, gsOnMsg2Len);
618       sendSysex(gsOnMsg3, gsOnMsg3Len);
619       }
620 
621 //---------------------------------------------------------
622 //   sendXgOn
623 //    send Yamaha XG-On message to midi device and keep track
624 //    of device state
625 //---------------------------------------------------------
626 
sendXgOn()627 void MidiPort::sendXgOn()
628       {
629       sendSysex(xgOnMsg, xgOnMsgLen);
630       }
631 
632 //---------------------------------------------------------
633 //   sendSysex
634 //    send SYSEX message to midi device
635 //---------------------------------------------------------
636 
sendSysex(const unsigned char * p,int n)637 void MidiPort::sendSysex(const unsigned char* p, int n)
638       {
639       if (_device) {
640             MidiPlayEvent event(0, 0, ME_SYSEX, p, n);
641            _device->putEvent(event, MidiDevice::NotLate);
642             }
643       }
644 
645 //---------------------------------------------------------
646 //   sendMMCLocate
647 //---------------------------------------------------------
648 
sendMMCLocate(unsigned char ht,unsigned char m,unsigned char s,unsigned char f,unsigned char sf,int devid)649 void MidiPort::sendMMCLocate(unsigned char ht, unsigned char m, unsigned char s, unsigned char f, unsigned char sf, int devid)
650 {
651   unsigned char msg[mmcLocateMsgLen];
652   memcpy(msg, mmcLocateMsg, mmcLocateMsgLen);
653   if(devid != -1)
654     msg[1]  = devid;
655   else
656     msg[1]  = _syncInfo.idOut();
657   msg[6]    = ht;
658   msg[7]    = m;
659   msg[8]    = s;
660   msg[9]    = f;
661   msg[10]   = sf;
662   sendSysex(msg, mmcLocateMsgLen);
663 }
664 
665 //---------------------------------------------------------
666 //   sendMMCStop
667 //---------------------------------------------------------
668 
sendMMCStop(int devid)669 void MidiPort::sendMMCStop(int devid)
670 {
671   unsigned char msg[mmcStopMsgLen];
672   memcpy(msg, mmcStopMsg, mmcStopMsgLen);
673   if(devid != -1)
674     msg[1] = devid;
675   else
676     msg[1] = _syncInfo.idOut();
677   sendSysex(msg, mmcStopMsgLen);
678 }
679 
680 //---------------------------------------------------------
681 //   sendMMCDeferredPlay
682 //---------------------------------------------------------
683 
sendMMCDeferredPlay(int devid)684 void MidiPort::sendMMCDeferredPlay(int devid)
685 {
686   unsigned char msg[mmcDeferredPlayMsgLen];
687   memcpy(msg, mmcDeferredPlayMsg, mmcDeferredPlayMsgLen);
688   if(devid != -1)
689     msg[1] = devid;
690   else
691     msg[1] = _syncInfo.idOut();
692   sendSysex(msg, mmcDeferredPlayMsgLen);
693 }
694 
695 //---------------------------------------------------------
696 //   sendStart
697 //---------------------------------------------------------
698 
sendStart()699 void MidiPort::sendStart()
700       {
701       if (_device) {
702             MidiPlayEvent event(0, 0, 0, ME_START, 0, 0);
703            _device->putEvent(event, MidiDevice::NotLate);
704             }
705       }
706 
707 //---------------------------------------------------------
708 //   sendStop
709 //---------------------------------------------------------
710 
sendStop()711 void MidiPort::sendStop()
712       {
713       if (_device) {
714             MidiPlayEvent event(0, 0, 0, ME_STOP, 0, 0);
715            _device->putEvent(event, MidiDevice::NotLate);
716             }
717       }
718 
719 //---------------------------------------------------------
720 //   sendClock
721 //---------------------------------------------------------
722 
sendClock()723 void MidiPort::sendClock()
724       {
725       if (_device) {
726             MidiPlayEvent event(0, 0, 0, ME_CLOCK, 0, 0);
727            _device->putEvent(event, MidiDevice::NotLate);
728             }
729       }
730 
731 //---------------------------------------------------------
732 //   sendContinue
733 //---------------------------------------------------------
734 
sendContinue()735 void MidiPort::sendContinue()
736       {
737       if (_device) {
738             MidiPlayEvent event(0, 0, 0, ME_CONTINUE, 0, 0);
739            _device->putEvent(event, MidiDevice::NotLate);
740             }
741       }
742 
743 //---------------------------------------------------------
744 //   sendSongpos
745 //---------------------------------------------------------
746 
sendSongpos(int pos)747 void MidiPort::sendSongpos(int pos)
748       {
749       if (_device) {
750             MidiPlayEvent event(0, 0, 0, ME_SONGPOS, pos, 0);
751            _device->putEvent(event, MidiDevice::NotLate);
752             }
753       }
754 
755 //---------------------------------------------------------
756 //   addManagedController
757 //---------------------------------------------------------
758 
addManagedController(int channel,int ctrl)759 MidiCtrlValList* MidiPort::addManagedController(int channel, int ctrl)
760       {
761       iMidiCtrlValList cl = _controller->find(channel, ctrl);
762       if (cl == _controller->end()) {
763             MidiCtrlValList* pvl = new MidiCtrlValList(ctrl);
764             _controller->add(channel, pvl);
765             return pvl;
766             }
767       else
768         return cl->second;
769       }
770 
771 //---------------------------------------------------------
772 //   addDefaultControllers
773 //---------------------------------------------------------
774 
addDefaultControllers()775 void MidiPort::addDefaultControllers()
776 {
777   for (int i = 0; i < MusECore::MUSE_MIDI_CHANNELS; ++i) {
778         for(ciMidiController imc = defaultManagedMidiController.begin(); imc != defaultManagedMidiController.end(); ++imc)
779           addManagedController(i, imc->second->num());
780         _automationType[i] = AUTO_READ;
781         }
782 }
783 
784 //---------------------------------------------------------
785 //   limitValToInstrCtlRange
786 //---------------------------------------------------------
787 
limitValToInstrCtlRange(const MidiController * mc,int val)788 int MidiPort::limitValToInstrCtlRange(const MidiController* mc, int val)
789 {
790   if(!_instrument || !mc || val == CTRL_VAL_UNKNOWN)
791     return val;
792 
793   //MidiController* mc = imc->second;
794   int mn = mc->minVal();
795   int mx = mc->maxVal();
796   int bias = mc->bias();
797 
798   // Subtract controller bias from value.
799   val -= bias;
800 
801   // Limit value to controller range.
802   if(val < mn)
803     val = mn;
804   else
805   if(val > mx)
806     val = mx;
807 
808   // Re-add controller bias to value.
809   val += bias;
810 
811   return val;
812 }
813 
limitValToInstrCtlRange(int ctl,int val,int chan)814 int MidiPort::limitValToInstrCtlRange(int ctl, int val, int chan)
815 {
816   if(!_instrument || val == CTRL_VAL_UNKNOWN)
817     return val;
818 
819   // FIXME: This might be optimized by calling midiController instead,
820   //         and simply asking if it's a drum controller. Saves one list iteration.
821   // Is it a drum controller?
822   // Note: Midnam apparently has no concept of drum controllers, so the fact
823   //  that this only asks in the instrument's controllers and not the midnam is OK.
824   const MidiController *mc = drumController(ctl);
825   if(!mc)
826   {
827     // It's not a drum controller. Find it as a regular controller instead.
828     const int patch = hwCtrlState(chan, CTRL_PROGRAM);
829     mc = _instrument->findController(ctl, chan, patch);
830   }
831 
832   // If it's a valid controller, limit the value to the instrument controller range.
833   if(mc)
834     return limitValToInstrCtlRange(mc, val);
835 
836   return val;
837 }
838 
limitValToInstrCtlRange(const MidiController * mc,double val)839 double MidiPort::limitValToInstrCtlRange(const MidiController* mc, double val)
840 {
841   if(!_instrument || !mc || int(val) == CTRL_VAL_UNKNOWN)
842     return val;
843 
844   const double mn = double(mc->minVal());
845   const double mx = double(mc->maxVal());
846   const double bias = double(mc->bias());
847 
848   // Subtract controller bias from value.
849   val -= double(bias);
850 
851   // Limit value to controller range.
852   if(val < mn)
853     val = mn;
854   else
855   if(val > mx)
856     val = mx;
857 
858   // Re-add controller bias to value.
859   val += bias;
860 
861   return val;
862 }
863 
limitValToInstrCtlRange(int ctl,double val,int chan)864 double MidiPort::limitValToInstrCtlRange(int ctl, double val, int chan)
865 {
866   if(!_instrument || int(val) == CTRL_VAL_UNKNOWN)
867     return val;
868 
869   // FIXME: This might be optimized by calling midiController instead,
870   //         and simply asking if it's a drum controller. Saves one list iteration.
871   // Is it a drum controller?
872   // Note: Midnam apparently has no concept of drum controllers, so the fact
873   //  that this only asks in the instrument's controllers and not the midnam is OK.
874   const MidiController *mc = drumController(ctl);
875   if(!mc)
876   {
877     // It's not a drum controller. Find it as a regular controller instead.
878     const int patch = hwCtrlState(chan, CTRL_PROGRAM);
879     mc = _instrument->findController(ctl, chan, patch);
880   }
881 
882   // If it's a valid controller, limit the value to the instrument controller range.
883   if(mc)
884     return limitValToInstrCtlRange(mc, val);
885 
886   return val;
887 }
888 
889 //---------------------------------------------------------
890 //  createController
891 //   Creates a controller in this port's controller list.
892 //   Returns true if the controller was created.
893 //   To be called by gui thread only.
894 //---------------------------------------------------------
895 
createController(int chan,int ctrl)896 bool MidiPort::createController(int chan, int ctrl)
897 {
898   if(ctrl < 0 || chan < 0 || chan >= MusECore::MUSE_MIDI_CHANNELS)
899     return false;
900 
901   PendingOperationList operations;
902 
903   // Make sure the controller exists, create it if not.
904   iMidiCtrlValList cl = _controller->find(chan, ctrl);
905   if(cl != _controller->end())
906     return false;
907 
908   PendingOperationItem poi(_controller, 0, chan, ctrl, PendingOperationItem::AddMidiCtrlValList);
909 
910   // This step is intended in case we ever pass an operations list to this function.
911   if(operations.findAllocationOp(poi) != operations.end())
912     return false;
913 
914   MidiCtrlValList* mcvl = new MidiCtrlValList(ctrl);
915   poi._mcvl = mcvl;
916   operations.add(poi);
917   // This waits for audio process thread to execute it.
918   MusEGlobal::audio->msgExecutePendingOperations(operations, true);
919 
920   return true;
921 }
922 
923 //---------------------------------------------------------
924 //   putHwCtrlEvent
925 //   To be called from gui thread only.
926 //   Returns true if event cannot be delivered.
927 //---------------------------------------------------------
928 
putHwCtrlEvent(const MidiPlayEvent & ev)929 bool MidiPort::putHwCtrlEvent(const MidiPlayEvent& ev)
930 {
931   const int ctrl = ev.translateCtrlNum();
932 
933   // Event not translatable to a controller?
934   if(ctrl < 0)
935     return true;
936 
937   // Make sure to create the controller if necessary.
938   //createController(chan, ctrl);
939 
940   // Make sure the controller exists, create it if not.
941   const int chan = ev.channel();
942   ciMidiCtrlValList cl = _controller->find(chan, ctrl);
943   // Controller does not exist?
944   if(cl == _controller->end())
945   {
946     // Tell the gui thread to create and add a new controller.
947     // It will store and re-deliver the events directly to the buffers
948     //  after the controller is created.
949     MusEGlobal::song->putIpcInEvent(ev);
950     // Technically the event is being delivered.
951     return false;
952   }
953 
954   if(!MusEGlobal::song->putIpcOutEvent(ev))
955   {
956     fprintf(stderr, "MidiPort::putHwCtrlEvent: Error: gui2AudioFifo fifo overflow\n");
957     return true;
958   }
959 
960   return false;
961 }
962 
963 //---------------------------------------------------------
964 //   putEvent
965 //   To be called from gui thread only.
966 //   Returns true if event cannot be delivered.
967 //---------------------------------------------------------
968 
putEvent(const MidiPlayEvent & ev)969 bool MidiPort::putEvent(const MidiPlayEvent& ev)
970 {
971   // Send the event to the device first so that current parameters could be updated on process.
972   bool res = false;
973   if(_device)
974   {
975     res = !_device->putEvent(ev, MidiDevice::Late);
976   }
977   putHwCtrlEvent(ev);
978   return res;
979 }
980 
981 //---------------------------------------------------------
982 //   putControllerValue
983 //   To be called from gui thread only.
984 //   Returns true if event cannot be delivered.
985 //---------------------------------------------------------
986 
putControllerValue(int port,int chan,int ctlnum,double val,bool isDb)987 bool MidiPort::putControllerValue(int port, int chan, int ctlnum, double val, bool isDb)
988 {
989   iMidiCtrlValList imcvl = _controller->find(chan, ctlnum);
990   if(imcvl == _controller->end())
991     return true;
992 
993   // Don't create if not found.
994   MusECore::MidiController* mc = midiController(ctlnum, chan, false);
995   if(!mc)
996     return true;
997   const int max = mc->maxVal();
998 
999   if(isDb)
1000     val = double(max) * muse_db2val(val / 2.0);
1001 
1002   const int i_new_val = MidiController::dValToInt(val);
1003 
1004   // Time-stamp the event.
1005   MidiPlayEvent ev(MusEGlobal::audio->curFrame(), port, chan, MusECore::ME_CONTROLLER, ctlnum, i_new_val);
1006   bool res = false;
1007   if(_device)
1008   {
1009     res = !_device->putEvent(ev, MidiDevice::Late);
1010   }
1011 
1012   putHwCtrlEvent(ev);
1013   return res;
1014 }
1015 
1016 //---------------------------------------------------------
1017 //   handleGui2AudioEvent
1018 //   To be called from audio thread only.
1019 //   Returns true on success.
1020 //   If createAsNeeded is true, automatically send a message to the gui thread to
1021 //    create items such as controllers, and cache the events sent to it and re-put
1022 //    them after the controller has been created.
1023 //---------------------------------------------------------
1024 
handleGui2AudioEvent(const MidiPlayEvent & ev,bool createAsNeeded)1025 bool MidiPort::handleGui2AudioEvent(const MidiPlayEvent& ev, bool createAsNeeded)
1026 {
1027   const int chn = ev.channel();
1028   const int type = ev.type();
1029   const int i_dataA = ev.dataA();
1030   const double d_dataB = ev.dataB();
1031   const int i_dataB = MidiController::dValToInt(d_dataB);
1032 
1033   int fin_db = i_dataB;
1034   switch(type)
1035   {
1036     case ME_CONTROLLER:
1037       switch(i_dataA)
1038       {
1039         case CTRL_HBANK:
1040         {
1041           // Does the CTRL_PROGRAM controller exist?
1042           iMidiCtrlValList imcvl = _controller->find(chn, CTRL_PROGRAM);
1043           if(imcvl == _controller->end())
1044           {
1045             // Tell the gui to create the controller and add the value.
1046             if(createAsNeeded)
1047               return MusEGlobal::song->putIpcInEvent(ev);
1048             return false;
1049           }
1050 
1051           int hb = 0xff;
1052           if(!MidiController::iValIsUnknown(i_dataB))
1053             hb = i_dataB & 0xff;
1054           if(hb != 0xff)
1055             hb = limitValToInstrCtlRange(i_dataA, hb, chn);
1056           int lb = 0xff;
1057           int pr = 0xff;
1058 
1059           MidiCtrlValList* mcvl = imcvl->second;
1060           if(!mcvl->hwValIsUnknown())
1061           {
1062             const int hw_val = mcvl->hwVal();
1063             lb = (hw_val >> 8) & 0xff;
1064             pr = hw_val & 0xff;
1065           }
1066 
1067           if((hb != 0xff || lb != 0xff) && pr == 0xff)
1068             pr = 0x01;
1069           if(hb == 0xff && lb == 0xff && pr == 0xff)
1070             fin_db = CTRL_VAL_UNKNOWN;
1071           else
1072             fin_db = (hb << 16) | (lb << 8) | pr;
1073 
1074           // Set the value. Be sure to update drum maps (and inform the gui).
1075           if(mcvl->setHwVal(fin_db))
1076             updateDrumMaps(chn, fin_db);
1077 
1078           return true;
1079         }
1080         break;
1081 
1082         case CTRL_LBANK:
1083         {
1084           // Does the CTRL_PROGRAM controller exist?
1085           iMidiCtrlValList imcvl = _controller->find(chn, CTRL_PROGRAM);
1086           if(imcvl == _controller->end())
1087           {
1088             // Tell the gui to create the controller and add the value.
1089             if(createAsNeeded)
1090               return MusEGlobal::song->putIpcInEvent(ev);
1091             return false;
1092           }
1093 
1094           int hb = 0xff;
1095           int lb = 0xff;
1096           if(!MidiController::iValIsUnknown(i_dataB))
1097             lb = i_dataB & 0xff;
1098           if(lb != 0xff)
1099             lb = limitValToInstrCtlRange(i_dataA, lb, chn);
1100           int pr = 0xff;
1101 
1102           MidiCtrlValList* mcvl = imcvl->second;
1103           if(!mcvl->hwValIsUnknown())
1104           {
1105             const int hw_val = mcvl->hwVal();
1106             hb = (hw_val >> 16) & 0xff;
1107             pr = hw_val & 0xff;
1108           }
1109 
1110           if((hb != 0xff || lb != 0xff) && pr == 0xff)
1111             pr = 0x01;
1112           if(hb == 0xff && lb == 0xff && pr == 0xff)
1113             fin_db = CTRL_VAL_UNKNOWN;
1114           else
1115             fin_db = (hb << 16) | (lb << 8) | pr;
1116 
1117           // Set the value. Be sure to update drum maps (and inform the gui).
1118           if(mcvl->setHwVal(fin_db))
1119             updateDrumMaps(chn, fin_db);
1120 
1121           return true;
1122         }
1123         break;
1124 
1125         case CTRL_PROGRAM:
1126         {
1127           // TODO: Maybe update CTRL_HBANK/CTRL_LBANK - but ONLY if they are specifically
1128           //        defined by the user in the controller list.
1129 
1130           // Does the CTRL_PROGRAM controller exist?
1131           iMidiCtrlValList imcvl = _controller->find(chn, CTRL_PROGRAM);
1132           if(imcvl == _controller->end())
1133           {
1134             // Tell the gui to create the controller and add the value.
1135             if(createAsNeeded)
1136               return MusEGlobal::song->putIpcInEvent(ev);
1137             return false;
1138           }
1139 
1140           // Set the value. Be sure to update drum maps (and inform the gui).
1141           if(imcvl->second->setHwVal(fin_db))
1142             updateDrumMaps(chn, fin_db);
1143 
1144           return true;
1145         }
1146         break;
1147 
1148         default:
1149         {
1150           // Does the controller exist?
1151           iMidiCtrlValList imcvl = _controller->find(chn, i_dataA);
1152           if(imcvl == _controller->end())
1153           {
1154             // Tell the gui to create the controller and add the value.
1155             if(createAsNeeded)
1156               return MusEGlobal::song->putIpcInEvent(ev);
1157             return false;
1158           }
1159 
1160           fin_db = limitValToInstrCtlRange(i_dataA, i_dataB, chn);
1161           // Set the value.
1162           imcvl->second->setHwVal(fin_db);
1163 
1164           return true;
1165         }
1166         break;
1167       }
1168     break;
1169 
1170     case ME_POLYAFTER:
1171     {
1172       const int pitch = i_dataA & 0x7f;
1173       const int fin_da = (CTRL_POLYAFTER & ~0xff) | pitch;
1174 
1175       // Does the controller exist?
1176       iMidiCtrlValList imcvl = _controller->find(chn, fin_da);
1177       if(imcvl == _controller->end())
1178       {
1179         // Tell the gui to create the controller and add the value.
1180         if(createAsNeeded)
1181           return MusEGlobal::song->putIpcInEvent(ev);
1182         return false;
1183       }
1184 
1185       fin_db = limitValToInstrCtlRange(fin_da, i_dataB, chn);
1186       // Set the value.
1187       imcvl->second->setHwVal(fin_db);
1188 
1189       return true;
1190     }
1191     break;
1192 
1193     case ME_AFTERTOUCH:
1194     {
1195       // Does the controller exist?
1196       iMidiCtrlValList imcvl = _controller->find(chn, CTRL_AFTERTOUCH);
1197       if(imcvl == _controller->end())
1198       {
1199         // Tell the gui to create the controller and add the value.
1200         if(createAsNeeded)
1201           return MusEGlobal::song->putIpcInEvent(ev);
1202         return false;
1203       }
1204 
1205       fin_db = limitValToInstrCtlRange(CTRL_AFTERTOUCH, i_dataA, chn);
1206       // Set the value.
1207       imcvl->second->setHwVal(fin_db);
1208 
1209       return true;
1210     }
1211     break;
1212 
1213     case ME_PITCHBEND:
1214     {
1215       // Does the controller exist?
1216       iMidiCtrlValList imcvl = _controller->find(chn, CTRL_PITCH);
1217       if(imcvl == _controller->end())
1218       {
1219         // Tell the gui to create the controller and add the value.
1220         if(createAsNeeded)
1221           return MusEGlobal::song->putIpcInEvent(ev);
1222         return false;
1223       }
1224 
1225       fin_db = limitValToInstrCtlRange(CTRL_PITCH, i_dataA, chn);
1226       // Set the value.
1227       imcvl->second->setHwVal(fin_db);
1228 
1229       return true;
1230     }
1231     break;
1232 
1233     case ME_PROGRAM:
1234     {
1235       // Does the controller exist?
1236       iMidiCtrlValList imcvl = _controller->find(chn, CTRL_PROGRAM);
1237       if(imcvl == _controller->end())
1238       {
1239         // Tell the gui to create the controller and add the value.
1240         if(createAsNeeded)
1241           return MusEGlobal::song->putIpcInEvent(ev);
1242         return false;
1243       }
1244 
1245       int hb = 0xff;
1246       int lb = 0xff;
1247       int pr = 0xff;
1248       if(!MidiController::iValIsUnknown(i_dataA))
1249         pr = i_dataA & 0xff;
1250       //if(pr != 0xff)
1251       //  pr = limitValToInstrCtlRange(da, pr, chn);
1252 
1253       MidiCtrlValList* mcvl = imcvl->second;
1254       if(!mcvl->hwValIsUnknown())
1255       {
1256         const int hw_val = mcvl->hwVal();
1257         hb = (hw_val >> 16) & 0xff;
1258         lb = (hw_val >> 8) & 0xff;
1259       }
1260 
1261       if((hb != 0xff || lb != 0xff) && pr == 0xff)
1262         pr = 0x01;
1263       if(hb == 0xff && lb == 0xff && pr == 0xff)
1264         fin_db = CTRL_VAL_UNKNOWN;
1265       else
1266         fin_db = (hb << 16) | (lb << 8) | pr;
1267 
1268       // Set the value. Be sure to update drum maps (and inform the gui).
1269       if(mcvl->setHwVal(fin_db))
1270         updateDrumMaps(chn, fin_db);
1271 
1272       return true;
1273     }
1274     break;
1275 
1276     default:
1277     break;
1278   }
1279 
1280   return false;
1281 }
1282 
1283 //---------------------------------------------------------
1284 //   sendHwCtrlState
1285 //   Return true if it is OK to go ahead and deliver the event.
1286 //---------------------------------------------------------
1287 
sendHwCtrlState(const MidiPlayEvent & ev,bool forceSend)1288 bool MidiPort::sendHwCtrlState(const MidiPlayEvent& ev, bool forceSend)
1289       {
1290       const int type = ev.type();
1291       const int chn = ev.channel();
1292       const int da = ev.dataA();
1293       int fin_da = da;
1294       const int db = ev.dataB();
1295 
1296       switch(type)
1297       {
1298         case ME_CONTROLLER:
1299           switch(da)
1300           {
1301             case CTRL_HBANK:
1302             {
1303               int hb = 0xff;
1304               if(!MidiController::iValIsUnknown(db))
1305                 hb = db & 0xff;
1306               if(hb != 0xff)
1307                 hb = limitValToInstrCtlRange(da, hb, chn);
1308               int lb = 0xff;
1309               int pr = 0xff;
1310 
1311               fin_da = CTRL_PROGRAM;
1312               // This will create a new value list if necessary, otherwise it returns the existing list.
1313               // FIXME: This is not realtime safe because it may allocate.
1314               MidiCtrlValList* mcvl = addManagedController(chn, fin_da);
1315               if(!mcvl->hwValIsUnknown())
1316               {
1317                 const int hw_val = mcvl->hwVal();
1318                 lb = (hw_val >> 8) & 0xff;
1319                 pr = hw_val & 0xff;
1320               }
1321 
1322               if((hb != 0xff || lb != 0xff) && pr == 0xff)
1323                 pr = 0x01;
1324             }
1325             break;
1326 
1327             case CTRL_LBANK:
1328             {
1329               int hb = 0xff;
1330               int lb = 0xff;
1331               if(!MidiController::iValIsUnknown(db))
1332                 lb = db & 0xff;
1333               if(lb != 0xff)
1334                 lb = limitValToInstrCtlRange(da, lb, chn);
1335               int pr = 0xff;
1336 
1337               fin_da = CTRL_PROGRAM;
1338               // This will create a new value list if necessary, otherwise it returns the existing list.
1339               // FIXME: This is not realtime safe because it may allocate.
1340               MidiCtrlValList* mcvl = addManagedController(chn, fin_da);
1341               if(!mcvl->hwValIsUnknown())
1342               {
1343                 const int hw_val = mcvl->hwVal();
1344                 hb = (hw_val >> 16) & 0xff;
1345                 pr = hw_val & 0xff;
1346               }
1347 
1348               if((hb != 0xff || lb != 0xff) && pr == 0xff)
1349                 pr = 0x01;
1350             }
1351             break;
1352 
1353             case CTRL_PROGRAM:
1354               // This will create a new value list if necessary, otherwise it returns the existing list.
1355               // FIXME: This is not realtime safe because it may allocate.
1356               addManagedController(chn, da);
1357               // TODO: Maybe update CTRL_HBANK/CTRL_LBANK - but ONLY if they are specifically
1358               //        defined by the user in the controller list.
1359             break;
1360 
1361             default:
1362               // This will create a new value list if necessary, otherwise it returns the existing list.
1363               // FIXME: This is not realtime safe because it may allocate.
1364               addManagedController(chn, da);
1365             break;
1366           }
1367         break;
1368 
1369         case ME_POLYAFTER:
1370         {
1371           const int pitch = da & 0x7f;
1372           fin_da = (CTRL_POLYAFTER & ~0xff) | pitch;
1373           // This will create a new value list if necessary, otherwise it returns the existing list.
1374           // FIXME: This is not realtime safe because it may allocate.
1375           addManagedController(chn, fin_da);
1376         }
1377         break;
1378 
1379         case ME_AFTERTOUCH:
1380         {
1381           fin_da = CTRL_AFTERTOUCH;
1382           // This will create a new value list if necessary, otherwise it returns the existing list.
1383           // FIXME: This is not realtime safe because it may allocate.
1384           addManagedController(chn, fin_da);
1385         }
1386         break;
1387 
1388         case ME_PITCHBEND:
1389         {
1390           fin_da = CTRL_PITCH;
1391           // This will create a new value list if necessary, otherwise it returns the existing list.
1392           // FIXME: This is not realtime safe because it may allocate.
1393           addManagedController(chn, fin_da);
1394         }
1395         break;
1396 
1397         case ME_PROGRAM:
1398         {
1399           int hb = 0xff;
1400           int lb = 0xff;
1401           int pr = 0xff;
1402           if(!MidiController::iValIsUnknown(da))
1403             pr = da & 0xff;
1404           //if(pr != 0xff)
1405           //  pr = limitValToInstrCtlRange(da, pr, chn);
1406 
1407           fin_da = CTRL_PROGRAM;
1408           // This will create a new value list if necessary, otherwise it returns the existing list.
1409           // FIXME: This is not realtime safe because it may allocate.
1410           MidiCtrlValList* mcvl = addManagedController(chn, fin_da);
1411           if(!mcvl->hwValIsUnknown())
1412           {
1413             const int hw_val = mcvl->hwVal();
1414             hb = (hw_val >> 16) & 0xff;
1415             lb = (hw_val >> 8) & 0xff;
1416           }
1417 
1418           if((hb != 0xff || lb != 0xff) && pr == 0xff)
1419             pr = 0x01;
1420         }
1421         break;
1422 
1423         default:
1424           // For all other event types, just return true.
1425           return true;
1426         break;
1427       }
1428 
1429       if(!setHwCtrlState(chn, da, db)) {
1430           if (MusEGlobal::debugMsg && forceSend)
1431             printf("sendHwCtrlState: State already set. Forcing anyway...\n");
1432           if (!forceSend)
1433             return false;
1434         }
1435 
1436       return true;
1437       }
1438 
1439 //---------------------------------------------------------
1440 //   lastValidHWCtrlState
1441 //---------------------------------------------------------
1442 
lastValidHWCtrlState(int ch,int ctrl) const1443 int MidiPort::lastValidHWCtrlState(int ch, int ctrl) const
1444 {
1445       ch &= 0xff;
1446       ciMidiCtrlValList cl = ((const MidiCtrlValListList*)_controller)->find(ch, ctrl);
1447       if (cl == _controller->end()) {
1448             return CTRL_VAL_UNKNOWN;
1449             }
1450       MidiCtrlValList* vl = cl->second;
1451       return vl->lastValidHWVal();
1452 }
1453 
1454 //---------------------------------------------------------
1455 //   lastValidHWCtrlState
1456 //---------------------------------------------------------
1457 
lastValidHWDCtrlState(int ch,int ctrl) const1458 double MidiPort::lastValidHWDCtrlState(int ch, int ctrl) const
1459 {
1460       ch &= 0xff;
1461       ciMidiCtrlValList cl = ((const MidiCtrlValListList*)_controller)->find(ch, ctrl);
1462       if (cl == _controller->end()) {
1463             return CTRL_VAL_UNKNOWN;
1464             }
1465       MidiCtrlValList* vl = cl->second;
1466       return vl->lastValidHWDVal();
1467 }
1468 
1469 //---------------------------------------------------------
1470 //   hwCtrlState
1471 //---------------------------------------------------------
1472 
hwCtrlState(int ch,int ctrl) const1473 int MidiPort::hwCtrlState(int ch, int ctrl) const
1474       {
1475       ch &= 0xff;
1476       ciMidiCtrlValList cl = ((const MidiCtrlValListList*)_controller)->find(ch, ctrl);
1477       if (cl == _controller->end())
1478             return CTRL_VAL_UNKNOWN;
1479       MidiCtrlValList* vl = cl->second;
1480       return vl->hwVal();
1481       }
1482 
1483 //---------------------------------------------------------
1484 //   hwDCtrlState
1485 //---------------------------------------------------------
1486 
hwDCtrlState(int ch,int ctrl) const1487 double MidiPort::hwDCtrlState(int ch, int ctrl) const
1488       {
1489       ch &= 0xff;
1490       ciMidiCtrlValList cl = ((const MidiCtrlValListList*)_controller)->find(ch, ctrl);
1491       if (cl == _controller->end())
1492             return CTRL_VAL_UNKNOWN;
1493       MidiCtrlValList* vl = cl->second;
1494       return vl->hwDVal();
1495       }
1496 
1497 //---------------------------------------------------------
1498 //   setHwCtrlState
1499 //   If audio is running (and not idle) this should only be called by the rt audio thread.
1500 //   Returns false if value is already equal, true if value is set.
1501 //---------------------------------------------------------
1502 
setHwCtrlState(const MidiPlayEvent & ev)1503 bool MidiPort::setHwCtrlState(const MidiPlayEvent& ev)
1504 {
1505   const int port = ev.port();
1506   if(port < 0 || port >= MusECore::MIDI_PORTS)
1507     return false;
1508 
1509   // Handle the event. Tell the gui to create controllers as needed.
1510   return MusEGlobal::midiPorts[port].handleGui2AudioEvent(ev, true);
1511 }
1512 
setHwCtrlState(int ch,int ctrl,int val)1513 bool MidiPort::setHwCtrlState(int ch, int ctrl, int val)
1514       {
1515       // This will create a new value list if necessary, otherwise it returns the existing list.
1516       MidiCtrlValList* vl = addManagedController(ch, ctrl);
1517 
1518       bool res = vl->setHwVal(val);
1519       // If program controller be sure to update drum maps (and inform the gui).
1520       if(res && ctrl == CTRL_PROGRAM)
1521         updateDrumMaps(ch, val);
1522 
1523       return res;
1524       }
1525 
setHwCtrlState(int ch,int ctrl,double val)1526 bool MidiPort::setHwCtrlState(int ch, int ctrl, double val)
1527       {
1528       // This will create a new value list if necessary, otherwise it returns the existing list.
1529       MidiCtrlValList* vl = addManagedController(ch, ctrl);
1530 
1531       bool res = vl->setHwVal(val);
1532       // If program controller be sure to update drum maps (and inform the gui).
1533       if(res && ctrl == CTRL_PROGRAM)
1534         updateDrumMaps(ch, val);
1535 
1536       return res;
1537       }
1538 
1539 //---------------------------------------------------------
1540 //   setHwCtrlStates
1541 //   If audio is running (and not idle) this should only be called by the rt audio thread.
1542 //   Sets current and last HW values.
1543 //   Handy for forcing labels to show 'off' and knobs to show specific values
1544 //    without having to send two messages.
1545 //   Returns false if both values are already set, true if either value is changed.
1546 //---------------------------------------------------------
1547 
setHwCtrlStates(int ch,int ctrl,int val,int lastval)1548 bool MidiPort::setHwCtrlStates(int ch, int ctrl, int val, int lastval)
1549       {
1550       // This will create a new value list if necessary, otherwise it returns the existing list.
1551       MidiCtrlValList* vl = addManagedController(ch, ctrl);
1552 
1553       // This is not perfectly ideal, drum maps should not have to (check) change if last hw val changed.
1554       bool res = vl->setHwVals(val, lastval);
1555       // If program controller be sure to update drum maps (and inform the gui).
1556       if(res && ctrl == CTRL_PROGRAM)
1557         updateDrumMaps(ch, val);
1558 
1559       return res;
1560       }
1561 
setHwCtrlStates(int ch,int ctrl,double val,double lastval)1562 bool MidiPort::setHwCtrlStates(int ch, int ctrl, double val, double lastval)
1563       {
1564       // This will create a new value list if necessary, otherwise it returns the existing list.
1565       MidiCtrlValList* vl = addManagedController(ch, ctrl);
1566 
1567       // This is not perfectly ideal, drum maps should not have to (check) change if last hw val changed.
1568       bool res = vl->setHwVals(val, lastval);
1569       // If program controller be sure to update drum maps (and inform the gui).
1570       if(res && ctrl == CTRL_PROGRAM)
1571         updateDrumMaps(ch, val);
1572 
1573       return res;
1574       }
1575 
1576 //---------------------------------------------------------
1577 //   setControllerVal
1578 //   This function sets a controller value,
1579 //   creating the controller if necessary.
1580 //   Returns true if a value was actually added.
1581 //---------------------------------------------------------
1582 
setControllerVal(int ch,unsigned int tick,int ctrl,int val,Part * part)1583 bool MidiPort::setControllerVal(int ch, unsigned int tick, int ctrl, int val, Part* part)
1584 {
1585       MidiCtrlValList* pvl;
1586       iMidiCtrlValList cl = _controller->find(ch, ctrl);
1587       if (cl == _controller->end())
1588       {
1589         pvl = new MidiCtrlValList(ctrl);
1590         _controller->add(ch, pvl);
1591       }
1592       else
1593         pvl = cl->second;
1594 
1595       return pvl->addMCtlVal(tick, val, part);
1596 }
1597 
1598 //---------------------------------------------------------
1599 //   updateDrumMaps
1600 //   If audio is running (and not idle) this should only be called by the rt audio thread.
1601 //   Returns true if maps were changed.
1602 //---------------------------------------------------------
1603 
updateDrumMaps(int chan,int patch)1604 bool MidiPort::updateDrumMaps(int chan, int patch)
1605 {
1606   int port;
1607   int tpatch;
1608   int tchan;
1609   bool map_changed = false;
1610   MidiTrack* mt;
1611   for(iMidiTrack t = MusEGlobal::song->midis()->begin(); t != MusEGlobal::song->midis()->end(); ++t)
1612   {
1613     mt = *t;
1614     if(mt->type() != Track::DRUM)
1615       continue;
1616     port = mt->outPort();
1617     if(port < 0 || port >= MusECore::MIDI_PORTS || &MusEGlobal::midiPorts[port] != this)
1618       continue;
1619     tchan = mt->outChannel();
1620     if(tchan != chan)
1621       continue;
1622     tpatch = hwCtrlState(tchan, CTRL_PROGRAM);
1623     if(tpatch != patch)
1624       continue;
1625     if(mt->updateDrummap(false)) // false = don't signal gui thread, we'll do that here.
1626       map_changed = true;
1627   }
1628 
1629   if(map_changed)
1630   {
1631     // It is possible we are being called from gui thread already, in audio idle mode.
1632     // Will this still work, and not conflict with audio sending the same message?
1633     // Are we are not supposed to write to an fd from different threads?
1634     if(!MusEGlobal::audio || MusEGlobal::audio->isIdle())
1635       // Directly emit SC_DRUMMAP song changed signal.
1636       MusEGlobal::song->update(SC_DRUMMAP);
1637     else
1638       // Tell the gui to emit SC_DRUMMAP song changed signal.
1639       MusEGlobal::audio->sendMsgToGui('D'); // Drum map changed.
1640 
1641     return true;
1642   }
1643 
1644   return false;
1645 }
1646 
1647 //---------------------------------------------------------
1648 //   updateDrumMaps
1649 //   If audio is running (and not idle) this should only be called by the rt audio thread.
1650 //   Returns true if maps were changed.
1651 //---------------------------------------------------------
1652 
updateDrumMaps()1653 bool MidiPort::updateDrumMaps()
1654 {
1655   int port;
1656   bool map_changed = false;
1657   MidiTrack* mt;
1658   for(iMidiTrack t = MusEGlobal::song->midis()->begin(); t != MusEGlobal::song->midis()->end(); ++t)
1659   {
1660     mt = *t;
1661     if(mt->type() != Track::DRUM)
1662       continue;
1663     port = mt->outPort();
1664     if(port < 0 || port >= MusECore::MIDI_PORTS || &MusEGlobal::midiPorts[port] != this)
1665       continue;
1666     if(mt->updateDrummap(false)) // false = don't signal gui thread, we'll do that here.
1667       map_changed = true;
1668   }
1669 
1670   if(map_changed)
1671   {
1672     // It is possible we are being called from gui thread already, in audio idle mode.
1673     // Will this still work, and not conflict with audio sending the same message?
1674     // Are we are not supposed to write to an fd from different threads?
1675     //if(MusEGlobal::audio && MusEGlobal::audio->isIdle() && MusEGlobal::midiSeq && MusEGlobal::midiSeq->isIdle())
1676     if(!MusEGlobal::audio || MusEGlobal::audio->isIdle())
1677       // Directly emit SC_DRUMMAP song changed signal.
1678       //MusEGlobal::song->update(SC_DRUMMAP, true);
1679       MusEGlobal::song->update(SC_DRUMMAP);
1680     else
1681       // Tell the gui to emit SC_DRUMMAP song changed signal.
1682       MusEGlobal::audio->sendMsgToGui('D'); // Drum map changed.
1683 
1684     return true;
1685   }
1686 
1687   return false;
1688 }
1689 
1690 //---------------------------------------------------------
1691 //   getCtrl
1692 //---------------------------------------------------------
1693 
getCtrl(int ch,unsigned int tick,int ctrl) const1694 int MidiPort::getCtrl(int ch, unsigned int tick, int ctrl) const
1695       {
1696       iMidiCtrlValList cl = _controller->find(ch, ctrl);
1697       if (cl == _controller->end())
1698             return CTRL_VAL_UNKNOWN;
1699 
1700       return cl->second->value(tick);
1701       }
1702 
getCtrl(int ch,unsigned int tick,int ctrl,Part * part) const1703 int MidiPort::getCtrl(int ch, unsigned int tick, int ctrl, Part* part) const
1704       {
1705       iMidiCtrlValList cl = _controller->find(ch, ctrl);
1706       if (cl == _controller->end())
1707             return CTRL_VAL_UNKNOWN;
1708 
1709       return cl->second->value(tick, part);
1710       }
1711 
getVisibleCtrl(int ch,unsigned int tick,int ctrl,bool inclMutedParts,bool inclMutedTracks,bool inclOffTracks) const1712 int MidiPort::getVisibleCtrl(int ch, unsigned int tick, int ctrl, bool inclMutedParts, bool inclMutedTracks, bool inclOffTracks) const
1713       {
1714       iMidiCtrlValList cl = _controller->find(ch, ctrl);
1715       if (cl == _controller->end())
1716             return CTRL_VAL_UNKNOWN;
1717 
1718       return cl->second->visibleValue(tick, inclMutedParts, inclMutedTracks, inclOffTracks);
1719       }
1720 
getVisibleCtrl(int ch,unsigned int tick,int ctrl,Part * part,bool inclMutedParts,bool inclMutedTracks,bool inclOffTracks) const1721 int MidiPort::getVisibleCtrl(int ch, unsigned int tick, int ctrl, Part* part, bool inclMutedParts, bool inclMutedTracks, bool inclOffTracks) const
1722       {
1723       iMidiCtrlValList cl = _controller->find(ch, ctrl);
1724       if (cl == _controller->end())
1725             return CTRL_VAL_UNKNOWN;
1726 
1727       return cl->second->visibleValue(tick, part, inclMutedParts, inclMutedTracks, inclOffTracks);
1728       }
1729 
1730 //---------------------------------------------------------
1731 //   deleteController
1732 //---------------------------------------------------------
1733 
deleteController(int ch,unsigned int tick,int ctrl,int val,Part * part)1734 void MidiPort::deleteController(int ch, unsigned int tick, int ctrl, int val, Part* part)
1735     {
1736       iMidiCtrlValList cl = _controller->find(ch, ctrl);
1737       if (cl == _controller->end()) {
1738             if (MusEGlobal::debugMsg)
1739                   printf("deleteController: controller %d(0x%x) for channel %d not found size %zd\n",
1740                      ctrl, ctrl, ch, _controller->size());
1741             return;
1742             }
1743 
1744       cl->second->delMCtlVal(tick, part, val);
1745       }
1746 
1747 //---------------------------------------------------------
1748 //   midiController
1749 //---------------------------------------------------------
1750 
midiController(int num,int chan,bool createIfNotFound) const1751 MidiController* MidiPort::midiController(int num, int chan, bool createIfNotFound) const
1752       {
1753       MidiController* mc = nullptr;
1754 
1755       // Search the instrument's controller lists (including midnam controllers).
1756       if (_instrument) {
1757             const int patch = hwCtrlState(chan, CTRL_PROGRAM);
1758             mc = _instrument->findController(num, chan, patch);
1759             if(mc)
1760               return mc;
1761             }
1762 
1763       // Search the global default controller list.
1764       mc = defaultMidiController.findController(num);
1765       if(mc)
1766         return mc;
1767 
1768       if(!createIfNotFound)
1769         return nullptr;
1770 
1771       const QString name = midiCtrlName(num);
1772       int min = 0;
1773       int max = 127;
1774 
1775       MidiController::ControllerType t = midiControllerType(num);
1776       switch (t) {
1777             case MidiController::RPN:
1778             case MidiController::NRPN:
1779             case MidiController::Controller7:
1780             case MidiController::PolyAftertouch:
1781             case MidiController::Aftertouch:
1782                   max = 127;
1783                   break;
1784             case MidiController::Controller14:
1785             case MidiController::RPN14:
1786             case MidiController::NRPN14:
1787                   max = 16383;
1788                   break;
1789             case MidiController::Program:
1790                   max = 0xffffff;
1791                   break;
1792             case MidiController::Pitch:
1793                   max = 8191;
1794                   min = -8192;
1795                   break;
1796             case MidiController::Velo:        // cannot happen
1797                   return nullptr;
1798                   break;
1799             }
1800       mc = new MidiController(name, num, min, max, 0, 0);
1801       defaultMidiController.add(mc);
1802       return mc;
1803       }
1804 
1805 //---------------------------------------------------------
1806 //   drumController
1807 //   Returns instrument drum controller if ctl is a drum controller number.
1808 //   Otherwise returns zero.
1809 //   NOTE: Midnam apparently has no concept of drum controllers, so the fact
1810 //    that this only asks in the instrument's controllers and not the midnam is OK.
1811 //---------------------------------------------------------
1812 
drumController(int ctl)1813 MidiController* MidiPort::drumController(int ctl)
1814 {
1815   if(!_instrument)
1816     return nullptr;
1817   MidiControllerList* cl = _instrument->controller();
1818   if(!cl)
1819     return nullptr;
1820   return cl->perNoteController(ctl);
1821 }
1822 
1823 //---------------------------------------------------------
1824 //   writeRouting
1825 //---------------------------------------------------------
1826 
writeRouting(int level,Xml & xml) const1827 void MidiPort::writeRouting(int level, Xml& xml) const
1828 {
1829       // If this device is not actually in use by the song, do not write any routes.
1830       // This prevents bogus routes from being saved and propagated in the med file.
1831       // p4.0.17 Reverted. Allow ports with no device to save.
1832       //if(!device())
1833       //  return;
1834 
1835       QString s;
1836 
1837       for (ciRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r)
1838       {
1839         if(r->type == Route::TRACK_ROUTE && r->track)
1840         {
1841           // Ignore Midi Port to Audio Input routes. Handled by Track route writer. p4.0.14 Tim.
1842           if(r->track->type() == Track::AUDIO_INPUT)
1843             continue;
1844 
1845           s = "Route";
1846           if(r->channel != -1)
1847             s += QString(" channel=\"%1\"").arg(r->channel);
1848           xml.tag(level++, s.toLatin1().constData());
1849 
1850           xml.tag(level, "source mport=\"%d\"/", portno());
1851 
1852           s = "dest";
1853           s += QString(" track=\"%1\"/").arg(MusEGlobal::song->tracks()->index(r->track));
1854           xml.tag(level, s.toLatin1().constData());
1855 
1856           xml.etag(level--, "Route");
1857         }
1858       }
1859 }
1860 
1861 // p4.0.17 Turn off if and when multiple output routes supported.
1862 #if 1
1863 //---------------------------------------------------------
1864 //   setPortExclusiveDefOutChan
1865 //---------------------------------------------------------
1866 
setPortExclusiveDefOutChan(int port,int c)1867 void setPortExclusiveDefOutChan(int port, int c)
1868 {
1869   if(port < 0 || port >= MusECore::MIDI_PORTS)
1870     return;
1871   MusEGlobal::midiPorts[port].setDefaultOutChannels(c);
1872   for(int i = 0; i < MusECore::MIDI_PORTS; ++i)
1873     if(i != port)
1874       MusEGlobal::midiPorts[i].setDefaultOutChannels(0);
1875 }
1876 #endif
1877 
1878 } // namespace MusECore
1879