1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: track.cpp,v 1.34.2.11 2009/11/30 05:05:49 terminator356 Exp $
5 //
6 //  (C) Copyright 2000-2004 Werner Schweer (ws@seh.de)
7 //  (C) Copyright 2011, 2016 Tim E. Real (terminator356 on sourceforge)
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 "track.h"
26 #include "event.h"
27 #include "midi_consts.h"
28 #include "mididev.h"
29 #include "song.h"
30 #include "audio.h"
31 #include "midictrl.h"
32 #include "helper.h"
33 #include "limits.h"
34 #include "dssihost.h"
35 #include "gconfig.h"
36 #include "operations.h"
37 #include "icons.h"
38 
39 #include "drum_ordering.h"
40 #include "globals.h"
41 #include "config.h"
42 
43 #include <QMessageBox>
44 
45 // Forwards from header:
46 #include "midiport.h"
47 #include "plugin.h"
48 #include "xml.h"
49 #include "midiedit/drummap.h"
50 #include "minstrument.h"
51 #include "latency_compensator.h"
52 
53 // Undefine if and when multiple output routes are added to midi tracks.
54 #define _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
55 
56 namespace MusECore {
57 
58 int Track::_snGen=0;
59 
60 unsigned int Track::_soloRefCnt  = 0;
61 Track* Track::_tmpSoloChainTrack = 0;
62 bool Track::_tmpSoloChainDoIns   = false;
63 bool Track::_tmpSoloChainNoDec   = false;
64 int Track::_selectionOrderCounter = 0;
65 
66 const char* Track::_cname[] = {
67       "Midi", "Drum", "Wave",
68       "AudioOut", "AudioIn", "AudioGroup", "AudioAux", "AudioSynth"
69       };
70 
71 
72 bool MidiTrack::_isVisible=true;
73 
74 
75 //---------------------------------------------------------
76 //   addPortCtrlEvents
77 //---------------------------------------------------------
78 
addPortCtrlEvents(MidiTrack * t,bool drum_ctls,bool non_drum_ctls)79 void addPortCtrlEvents(MidiTrack* t, bool drum_ctls, bool non_drum_ctls)
80 {
81   if(!drum_ctls && !non_drum_ctls)
82     return;
83 
84   bool is_drum_ctl;
85   const PartList* pl = t->cparts();
86   for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
87   {
88     Part* part = ip->second;
89     const EventList& el = part->events();
90     unsigned len = part->lenTick();
91     for(ciEvent ie = el.begin(); ie != el.end(); ++ie)
92     {
93       const Event& ev = ie->second;
94       // Do not add events which are past the end of the part.
95 #ifdef ALLOW_LEFT_HIDDEN_EVENTS
96       if((int)ev.tick() >= (int)len)
97 #else
98       if(ev.tick() >= len)
99 #endif
100         break;
101 
102 #ifdef ALLOW_LEFT_HIDDEN_EVENTS
103       if((int)ev.tick() < 0)
104         continue;
105 #endif
106 
107       if(ev.type() == Controller)
108       {
109         int tick  = ev.tick() + part->tick();
110         int cntrl = ev.dataA();
111         int val   = ev.dataB();
112 
113         // Is it a drum controller event, according to the track port's instrument?
114         MidiPort* mp;
115         int ch;
116         is_drum_ctl = t->mappedPortChanCtrl(&cntrl, nullptr, &mp, &ch);
117 
118         if((is_drum_ctl && drum_ctls) || (!is_drum_ctl && non_drum_ctls))
119           mp->setControllerVal(ch, tick, cntrl, val, part);
120       }
121     }
122   }
123 }
124 
125 //---------------------------------------------------------
126 //   removePortCtrlEvents
127 //---------------------------------------------------------
128 
removePortCtrlEvents(MidiTrack * t,bool drum_ctls,bool non_drum_ctls)129 void removePortCtrlEvents(MidiTrack* t, bool drum_ctls, bool non_drum_ctls)
130 {
131   if(!drum_ctls && !non_drum_ctls)
132     return;
133 
134   bool is_drum_ctl;
135   const PartList* pl = t->cparts();
136   for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
137   {
138     Part* part = ip->second;
139     const EventList& el = part->events();
140     for(ciEvent ie = el.begin(); ie != el.end(); ++ie)
141     {
142       const Event& ev = ie->second;
143 
144       if(ev.type() == Controller)
145       {
146         int tick  = ev.tick() + part->tick();
147         int cntrl = ev.dataA();
148         int val = ev.dataB();
149 
150         // Is it a drum controller event, according to the track port's instrument?
151         MidiPort* mp;
152         int ch;
153         is_drum_ctl = t->mappedPortChanCtrl(&cntrl, nullptr, &mp, &ch);
154 
155         if((is_drum_ctl && drum_ctls) || (!is_drum_ctl && non_drum_ctls))
156           mp->deleteController(ch, tick, cntrl, val, part);
157       }
158     }
159   }
160 }
161 
162 //---------------------------------------------------------
163 //   isVisible
164 //---------------------------------------------------------
isVisible()165 bool Track::isVisible()
166 {
167   switch (type())
168   {
169     case Track::AUDIO_AUX:
170         return AudioAux::visible();
171     case Track::AUDIO_GROUP:
172         return AudioGroup::visible();
173     case Track::AUDIO_INPUT:
174         return AudioInput::visible();
175     case Track::AUDIO_OUTPUT:
176         return AudioOutput::visible();
177     case Track::WAVE:
178         return WaveTrack::visible();
179     case Track::MIDI:
180     case Track::DRUM:
181         return MidiTrack::visible();
182     case Track::AUDIO_SOFTSYNTH:
183         return SynthI::visible();
184   default:
185     break;
186   }
187 
188   return false;
189 }
190 
191 
192 //---------------------------------------------------------
193 //   y
194 //---------------------------------------------------------
195 
y() const196 int Track::y() const
197       {
198       TrackList* tl = MusEGlobal::song->tracks();
199       int yy = 0;
200       for (ciTrack it = tl->begin(); it != tl->end(); ++it) {
201             if (this == *it)
202                   return yy;
203             yy += (*it)->height();
204             }
205       // FIXME Get this when loading a song with automation graphs showing. Benign. Likely song not fully loaded yet. p4.0.32
206       if(MusEGlobal::debugMsg)
207         printf("Track::y(%s): track not in tracklist\n", name().toLatin1().constData());
208       return -1;
209       }
210 
211 //---------------------------------------------------------
212 //   Track::init
213 //---------------------------------------------------------
214 
init(int channels)215 void Track::init(int channels)
216       {
217       _auxRouteCount = 0;
218       _nodeTraversed = false;
219       _activity      = 0;
220       _lastActivity  = 0;
221       _recordFlag    = false;
222       _mute          = false;
223       _solo          = false;
224       _internalSolo  = 0;
225       _off           = false;
226       _channels      = channels;           // 1 - mono, 2 - stereo
227       _selected      = false;
228       _selectionOrder = 0;
229       _height        = MusEGlobal::config.trackHeight;
230       _locked        = false;
231       _recMonitor    = false;
232       for (int i = 0; i < MusECore::MAX_CHANNELS; ++i) {
233             _meter[i] = 0.0;
234             _peak[i]  = 0.0;
235             _isClipped[i] = false;
236             }
237       }
238 
Track(Track::TrackType t,int channels)239 Track::Track(Track::TrackType t, int channels)
240 {
241       _type = t;
242       _sn = newSn();
243       init(channels);
244 }
245 
Track(const Track & t,int flags)246 Track::Track(const Track& t, int flags)
247 {
248   _type         = t.type();
249 
250   // This should be reset for a copy of a track.
251   _sn = newSn();
252 
253   init(t._channels);
254 
255   // moved setting the unique name to Song::duplicateTracks()
256   // we'll see if there is any draw back to that.
257   // See comments in the header about naming copied tracks,
258   //  and why we don't automatically pick a unique name.
259   _name = t.name();
260 
261   internal_assign(t, flags | ASSIGN_PROPERTIES);
262 }
263 
~Track()264 Track::~Track()
265 {
266   _parts.clearDelete();
267 }
268 
269 //---------------------------------------------------------
270 //   assign
271 //---------------------------------------------------------
272 
assign(const Track & t,int flags)273 void Track::assign(const Track& t, int flags)
274 {
275   internal_assign(t, flags);
276 }
277 
internal_assign(const Track & t,int flags)278 void Track::internal_assign(const Track& t, int flags)
279 {
280       if(flags & ASSIGN_PROPERTIES)
281       {
282         // Leave at init value. Should be set by adding routes later.
283         //_auxRouteCount = t._auxRouteCount;
284 
285         // Leave at init value. Set by anti-circular routing mechanism later.
286         //_nodeTraversed = t._nodeTraversed;
287 
288         // Leave at init value. (How can there be 'activity' yet on a new track?)
289         //_activity     = t._activity;
290         //_lastActivity = t._lastActivity;
291 
292         // Leave at init value. Likely we don't want the new track soloed,
293         //  although there may be cases where we want that (such as modifying a
294         //  track copy and then requesting the operations system switch tracks -
295         //  in that case we likely want the solo to be the same). For now, caller
296         //  can set afterwards. TODO Decide whether to copy it.
297         //_solo         = t._solo;
298 
299         // Leave at init value. Set by soloing and routing mechanisms later.
300         //_internalSolo = t._internalSolo;
301 
302         // Leave at init value. Set by init().
303         //_channels     = t._channels;
304 
305         // Special for selected. Make sure this is called.
306         // NOTE This makes this track the most recent selected. TODO Try to leave
307         //  the original track as the most recent selected. (More involved - the
308         //  '_selected' members of all tracks would need to be re-indexed).
309         setSelected(t.selected());
310 
311         // Leave at init value. Set by setSelected(), above.
312         //_selectionOrder = t.selectionOrder();
313 
314         // For now, copy this. It may be set later.
315         _y            = t._y;
316 
317         // For now, copy this. The caller may set it to some other value after.
318         _height       = t._height;
319 
320         _off          = t._off;
321         _recordFlag   = t._recordFlag;
322         _mute         = t._mute;
323         _comment      = t.comment();
324         _locked       = t.locked();
325         _recMonitor   = t._recMonitor;
326       }
327 }
328 
329 //---------------------------------------------------------
330 //   trackTypeIcon
331 //   Static
332 //---------------------------------------------------------
333 
trackTypeIcon(TrackType type)334 QIcon* Track::trackTypeIcon(TrackType type)
335 {
336   switch(type) {
337         case MusECore::Track::MIDI:
338               return MusEGui::pianorollSVGIcon;
339         case MusECore::Track::DRUM:
340               return MusEGui::drumeditSVGIcon;
341         case MusECore::Track::WAVE:
342               return MusEGui::waveeditorSVGIcon;
343         case MusECore::Track::AUDIO_OUTPUT:
344               return MusEGui::trackOutputSVGIcon;
345         case MusECore::Track::AUDIO_INPUT:
346               return MusEGui::trackInputSVGIcon;
347         case MusECore::Track::AUDIO_GROUP:
348               return MusEGui::trackGroupVGIcon;
349         case MusECore::Track::AUDIO_AUX:
350               return MusEGui::trackAuxSVGIcon;
351         case MusECore::Track::AUDIO_SOFTSYNTH:
352               return MusEGui::synthSVGIcon;
353         }
354   return nullptr;
355 }
356 
357 //---------------------------------------------------------
358 //   trackTypeColor
359 //   Static
360 //---------------------------------------------------------
361 
trackTypeColor(TrackType type)362 QColor Track::trackTypeColor(TrackType type)
363 {
364   switch(type) {
365         case MusECore::Track::MIDI:
366               return MusEGlobal::config.midiTrackBg;
367         case MusECore::Track::DRUM:
368               return MusEGlobal::config.newDrumTrackBg;
369         case MusECore::Track::WAVE:
370               return MusEGlobal::config.waveTrackBg;
371         case MusECore::Track::AUDIO_OUTPUT:
372               return MusEGlobal::config.outputTrackBg;
373         case MusECore::Track::AUDIO_INPUT:
374               return MusEGlobal::config.inputTrackBg;
375         case MusECore::Track::AUDIO_GROUP:
376               return MusEGlobal::config.groupTrackBg;
377         case MusECore::Track::AUDIO_AUX:
378               return MusEGlobal::config.auxTrackBg;
379         case MusECore::Track::AUDIO_SOFTSYNTH:
380               return MusEGlobal::config.synthTrackBg;
381         default:
382               break;
383         }
384   return QColor();
385 }
386 
387 //---------------------------------------------------------
388 //   trackTypeLabelColor
389 //   Static
390 //---------------------------------------------------------
391 
trackTypeLabelColor(TrackType type)392 QColor Track::trackTypeLabelColor(TrackType type)
393 {
394   switch(type) {
395         case MusECore::Track::MIDI:
396               return MusEGlobal::config.midiTrackLabelBg;
397         case MusECore::Track::DRUM:
398               return MusEGlobal::config.newDrumTrackLabelBg;
399         case MusECore::Track::WAVE:
400               return MusEGlobal::config.waveTrackLabelBg;
401         case MusECore::Track::AUDIO_OUTPUT:
402               return MusEGlobal::config.outputTrackLabelBg;
403         case MusECore::Track::AUDIO_INPUT:
404               return MusEGlobal::config.inputTrackLabelBg;
405         case MusECore::Track::AUDIO_GROUP:
406               return MusEGlobal::config.groupTrackLabelBg;
407         case MusECore::Track::AUDIO_AUX:
408               return MusEGlobal::config.auxTrackLabelBg;
409         case MusECore::Track::AUDIO_SOFTSYNTH:
410               return MusEGlobal::config.synthTrackLabelBg;
411         default:
412               break;
413         }
414   return QColor();
415 }
416 
417 //---------------------------------------------------------
418 //   displayName
419 //---------------------------------------------------------
420 
displayName() const421 QString Track::displayName() const
422 {
423   const int idx = MusEGlobal::song->tracks()->index(this);
424   return QString("%1:%2").arg(idx + 1).arg(_name);
425 }
426 
427 //---------------------------------------------------------
428 //   clearRecAutomation
429 //---------------------------------------------------------
430 
clearRecAutomation(bool clearList)431 void Track::clearRecAutomation(bool clearList)
432 {
433     if(isMidiTrack())
434       return;
435     AudioTrack *t = static_cast<AudioTrack*>(this);
436     // Re-enable all track and plugin controllers, and synth controllers if applicable.
437     t->enableAllControllers();
438     if(clearList)
439       t->recEvents()->clear();
440 }
441 
442 //---------------------------------------------------------
443 //   setSelected
444 //---------------------------------------------------------
445 
setSelected(bool f)446 void Track::setSelected(bool f)
447 {
448   if(f && !_selected)
449     _selectionOrder = _selectionOrderCounter++;
450   _selected = f;
451 }
452 
453 //---------------------------------------------------------
454 //   dump
455 //---------------------------------------------------------
456 
dump() const457 void Track::dump() const
458       {
459       printf("Track <%s>: typ %d, parts %zd sel %d sel order%d\n",
460          _name.toLatin1().constData(), _type, _parts.size(), _selected, _selectionOrder);
461       }
462 
463 //---------------------------------------------------------
464 //   updateAuxRoute
465 //   Internal use. Update all the Aux ref counts of tracks dst is connected to.
466 //   If dst is valid, start traversal from there, not from this track.
467 //---------------------------------------------------------
468 
updateAuxRoute(int refInc,Track * dst)469 void Track::updateAuxRoute(int refInc, Track* dst)
470 {
471   if(isMidiTrack())
472     return;
473 
474   if(dst)
475   {
476     _nodeTraversed = true;
477     dst->updateAuxRoute(refInc, NULL);
478     _nodeTraversed = false;
479     return;
480   }
481 
482   if(_type == AUDIO_AUX)
483     return;
484 
485   if(_nodeTraversed)
486   {
487     fprintf(stderr, "Track::updateAuxRoute %s _auxRouteCount:%d refInc:%d :\n", name().toLatin1().constData(), _auxRouteCount, refInc);
488     if(refInc >= 0)
489       fprintf(stderr, "  MusE Warning: Please check your routes: Circular path found!\n");
490     else
491       fprintf(stderr, "  MusE: Circular path removed.\n");
492     return;
493   }
494 
495   _nodeTraversed = true;
496 
497   _auxRouteCount += refInc;
498   if(_auxRouteCount < 0)
499   {
500     fprintf(stderr, "Track::updateAuxRoute Ref underflow! %s _auxRouteCount:%d refInc:%d\n", name().toLatin1().constData(), _auxRouteCount, refInc);
501   }
502 
503   for (iRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i)
504   {
505     if( !(*i).isValid() || (*i).type != Route::TRACK_ROUTE )
506       continue;
507     Track* t = (*i).track;
508     t->updateAuxRoute(refInc, NULL);
509   }
510 
511   _nodeTraversed = false;
512 }
513 
514 //---------------------------------------------------------
515 //   isCircularRoute
516 //   If dst is valid, start traversal from there, not from this track.
517 //   Returns true if circular.
518 //---------------------------------------------------------
519 
isCircularRoute(Track * dst)520 bool Track::isCircularRoute(Track* dst)
521 {
522   bool rv = false;
523 
524   if(dst)
525   {
526     _nodeTraversed = true;
527     rv = dst->isCircularRoute(NULL);
528     _nodeTraversed = false;
529     return rv;
530   }
531 
532   if(_nodeTraversed)
533     return true;
534 
535   _nodeTraversed = true;
536 
537   for (iRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i)
538   {
539     if( !(*i).isValid() || (*i).type != Route::TRACK_ROUTE )
540       continue;
541     Track* t = (*i).track;
542     rv = t->isCircularRoute(NULL);
543     if(rv)
544       break;
545   }
546 
547   _nodeTraversed = false;
548   return rv;
549 }
550 
routeCapabilities() const551 RouteCapabilitiesStruct Track::routeCapabilities() const
552 {
553   RouteCapabilitiesStruct s;
554   s._trackChannels._inChannels = s._trackChannels._outChannels = _channels;
555   s._trackChannels._inRoutable = s._trackChannels._outRoutable = (_channels != 0);
556   return s;
557 }
558 
canDominateOutputLatency() const559 inline bool Track::canDominateOutputLatency() const
560 {
561   // Return true only if the track is on and the user wants unterminated branches counted.
562   return !off() && MusEGlobal::config.correctUnterminatedOutBranchLatency;
563 }
564 
canDominateInputLatency() const565 inline bool Track::canDominateInputLatency() const
566 {
567   return false;
568 }
569 
canPassThruLatency() const570 bool Track::canPassThruLatency() const
571 {
572   return !off() &&
573          (!canRecordMonitor() ||
574           (MusEGlobal::config.monitoringAffectsLatency &&
575            isRecMonitored())); // || recordFlag();
576 }
577 
prepareLatencyScan()578 void Track::prepareLatencyScan() {
579   _latencyInfo.initialize();
580   _transportSource.prepareLatencyScan(transportAffectsAudioLatency());
581 }
582 
getWorstPluginLatencyAudio()583 float Track::getWorstPluginLatencyAudio()
584 {
585   // Have we been here before during this scan?
586   // Just return the cached value.
587   if(_latencyInfo._worstPluginLatencyProcessed)
588     return _latencyInfo._worstPluginLatency;
589 
590   _latencyInfo._worstPluginLatency = 0.0f;
591   _latencyInfo._worstPluginLatencyProcessed = true;
592   return _latencyInfo._worstPluginLatency;
593 }
594 
getWorstPortLatencyAudio()595 float Track::getWorstPortLatencyAudio()
596 {
597   // Have we been here before during this scan?
598   // Just return the cached value.
599   if(_latencyInfo._worstPortLatencyProcessed)
600     return _latencyInfo._worstPortLatency;
601 
602   _latencyInfo._worstPortLatency = 0.0f;
603   _latencyInfo._worstPortLatencyProcessed = true;
604   return _latencyInfo._worstPortLatency;
605 }
606 
getWorstSelfLatencyAudio()607 float Track::getWorstSelfLatencyAudio()
608 {
609   // Have we been here before during this scan?
610   // Just return the cached value.
611   if(_latencyInfo._worstSelfLatencyProcessed)
612     return _latencyInfo._worstSelfLatency;
613 
614   _latencyInfo._worstSelfLatency = 0.0f;
615   _latencyInfo._worstSelfLatencyProcessed = true;
616   return _latencyInfo._worstSelfLatency;
617 }
618 
619 //---------------------------------------------------------
620 //   MidiTrack
621 //---------------------------------------------------------
622 
MidiTrack()623 MidiTrack::MidiTrack()
624    : Track(MIDI)
625       {
626       init();
627 
628       _drummap=new DrumMap[128];
629       _workingDrumMapPatchList = new WorkingDrumMapPatchList();
630 
631       init_drummap(true /* write drummap ordering information as well */);
632       }
633 
MidiTrack(const MidiTrack & mt,int flags)634 MidiTrack::MidiTrack(const MidiTrack& mt, int flags)
635   : Track(mt, flags)
636 {
637       init();
638 
639       _drummap=new DrumMap[128];
640       _workingDrumMapPatchList = new WorkingDrumMapPatchList();
641 
642       internal_assign(mt, flags | Track::ASSIGN_PROPERTIES);
643 }
644 
internal_assign(const Track & t,int flags)645 void MidiTrack::internal_assign(const Track& t, int flags)
646 {
647       if(!t.isMidiTrack())
648         return;
649 
650       const MidiTrack& mt = (const MidiTrack&)t;
651 
652       if(flags & ASSIGN_PROPERTIES)
653       {
654         _outPort       = mt.outPort();
655         _outChannel    = mt.outChannel();
656         transposition  = mt.transposition;
657         velocity       = mt.velocity;
658         delay          = mt.delay;
659         len            = mt.len;
660         compression    = mt.compression;
661         clefType       = mt.clefType;
662         _curDrumPatchNumber = mt._curDrumPatchNumber;
663       }
664 
665       if(flags & ASSIGN_ROUTES)
666       {
667         for(ciRoute ir = mt._inRoutes.begin(); ir != mt._inRoutes.end(); ++ir)
668           // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node.
669           _inRoutes.push_back(*ir);
670 
671         for(ciRoute ir = mt._outRoutes.begin(); ir != mt._outRoutes.end(); ++ir)
672           // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node.
673          _outRoutes.push_back(*ir);
674       }
675       else if(flags & ASSIGN_DEFAULT_ROUTES)
676       {
677         // Add default track <-> midiport routes.
678         int c;
679         bool defOutFound = false;                /// TODO: Remove this if and when multiple output routes supported.
680         const int chmask = (1 << MusECore::MUSE_MIDI_CHANNELS) - 1;
681         for(int i = 0; i < MusECore::MIDI_PORTS; ++i)
682         {
683           MidiPort* mp = &MusEGlobal::midiPorts[i];
684 
685           if(mp->device())  // Only if device is valid.
686           {
687             c = mp->defaultInChannels();
688             if(c)
689             {
690               // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node.
691               // All channels set or Omni? Use an Omni route:
692               if(c == -1 || c == chmask)
693                 _inRoutes.push_back(Route(i));
694               else
695               // Add individual channels:
696               for(int ch = 0; ch < MusECore::MUSE_MIDI_CHANNELS; ++ch)
697               {
698                 if(c & (1 << ch))
699                   _inRoutes.push_back(Route(i, ch));
700               }
701             }
702           }
703 
704           if(!defOutFound)
705           {
706             c = mp->defaultOutChannels();
707             if(c)
708             {
709 
710 #ifdef _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
711                 if(c == -1)
712                   c = 1;  // Just to be safe, shouldn't happen, default to channel 0.
713                 for(int ch = 0; ch < MusECore::MUSE_MIDI_CHANNELS; ++ch)
714                 {
715                   if(c & (1 << ch))
716                   {
717                     defOutFound = true;
718                     _outPort = i;
719                     // Leave drum tracks at channel 10. TODO: Want this?
720                     //if(type() != Track::NEW_DRUM)
721                       _outChannel = ch;
722                     break;
723                   }
724                 }
725 #else
726                 // All channels set or Omni? Use an Omni route:
727                 if(c == -1 || c == chmask)
728                   _outRoutes.push_back(Route(i));
729                 else
730                 // Add individual channels:
731                 for(int ch = 0; ch < MusECore::MUSE_MIDI_CHANNELS; ++ch)
732                 {
733                   if(c & (1 << ch))
734                     _outRoutes.push_back(Route(i, ch));
735                 }
736 
737 #endif
738 
739             }
740           }
741         }
742       }
743 
744       if (flags & ASSIGN_DRUMLIST)
745       {
746         // Safety in case assignment called on an existing track which is already in global_drum_ordering.
747         remove_ourselves_from_drum_ordering();
748 
749         for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin();
750             it!=MusEGlobal::global_drum_ordering.end(); ++it)
751         {
752           if (it->first == &mt)
753           {
754              // duplicates the entry at it, set it to the first entry of both
755             it=MusEGlobal::global_drum_ordering.insert(it, *it);
756             // make it point to the second entry
757             ++it;
758             it->first=this;
759           }
760         }
761 
762         for (int i=0;i<128;i++) // no memcpy allowed here. dunno exactly why,
763           _drummap[i]=mt._drummap[i]; // seems QString-related.
764         update_drum_in_map();
765         _drummap_ordering_tied_to_patch=mt._drummap_ordering_tied_to_patch;
766         // TODO FINDMICH "assign" ordering as well
767 
768         if(mt._workingDrumMapPatchList)
769           *_workingDrumMapPatchList = *mt._workingDrumMapPatchList;
770       }
771       else
772       {
773         init_drummap(true /* write drummap ordering information as well */);
774       }
775 
776       const bool dup = flags & ASSIGN_DUPLICATE_PARTS;
777       const bool cpy = flags & ASSIGN_COPY_PARTS;
778       const bool cln = flags & ASSIGN_CLONE_PARTS;
779       if(dup || cpy || cln)
780       {
781         const PartList* pl = t.cparts();
782         for (ciPart ip = pl->begin(); ip != pl->end(); ++ip) {
783               Part* spart = ip->second;
784               Part* dpart = 0;
785               if(dup)
786                 dpart = spart->hasClones() ? spart->createNewClone() : spart->duplicate();
787               else if(cpy)
788                 dpart = spart->duplicate();
789               else if(cln)
790                 dpart = spart->createNewClone();
791               if(dpart)
792               {
793                 dpart->setTrack(this);
794                 parts()->add(dpart);
795               }
796               }
797       }
798 
799 }
800 
assign(const Track & t,int flags)801 void MidiTrack::assign(const Track& t, int flags)
802 {
803       Track::assign(t, flags);
804       internal_assign(t, flags);
805 }
806 
~MidiTrack()807 MidiTrack::~MidiTrack()
808       {
809       if(_workingDrumMapPatchList)
810         delete _workingDrumMapPatchList;
811       delete [] _drummap;
812       remove_ourselves_from_drum_ordering();
813       }
814 
815 
setRecordFlag2AndCheckMonitor(bool f)816 bool MidiTrack::setRecordFlag2AndCheckMonitor(bool f)
817 {
818   if(canRecord())
819     _recordFlag = f;
820 
821   if(MusEGlobal::config.monitorOnRecord && canRecordMonitor())
822   {
823     if(f != _recMonitor)
824     {
825       _recMonitor = f;
826       return true;
827     }
828   }
829   return false;
830 }
831 
convertToType(TrackType trackType)832 void MidiTrack::convertToType(TrackType trackType)
833 {
834   if(trackType == MusECore::Track::MIDI  ||  trackType == MusECore::Track::DRUM)
835   {
836     //
837     //    Drum -> Midi
838     //
839     MusECore::PartList* pl = parts();
840     for (MusECore::iPart ip = pl->begin(); ip != pl->end(); ++ip) {
841       for (MusECore::ciEvent ie = ip->second->events().begin(); ie != ip->second->events().end(); ++ie) {
842         MusECore::Event ev = ie->second;
843         if(ev.type() == MusECore::Note)
844         {
845           int pitch = ev.pitch();
846           pitch = MusEGlobal::drumMap[pitch].enote;
847           ev.setPitch(pitch);
848         }
849         else
850           if(ev.type() == MusECore::Controller)
851           {
852             int ctl = ev.dataA();
853             // Is it a drum controller event, according to the track port's instrument?
854             MusECore::MidiController *mc = MusEGlobal::midiPorts[outPort()].drumController(ctl);
855             if(mc)
856               // Change the controller event's index into the drum map to an instrument note.
857               ev.setA((ctl & ~0xff) | MusEGlobal::drumMap[ctl & 0x7f].enote);
858           }
859       }
860     }
861     setType(trackType);
862   }
863 }
864 
remove_ourselves_from_drum_ordering()865 void MidiTrack::remove_ourselves_from_drum_ordering()
866 {
867   for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end();)
868     if (it->first == this)
869       it=MusEGlobal::global_drum_ordering.erase(it);
870     else
871       it++;
872 }
873 
874 //---------------------------------------------------------
875 //   init
876 //---------------------------------------------------------
877 
init()878 void MidiTrack::init()
879       {
880       _outPort       = 0;
881 
882       // let's set the port to the last instantiated device
883       // if midi-channel defaults are set in the configuration it
884       // will override this setting
885       for (int i = MusECore::MIDI_PORTS - 1; i > -1; i--)
886       {
887         if (MusEGlobal::midiPorts[i].device() != NULL)
888         {
889           _outPort = i;
890           break;
891         }
892       }
893 
894       _outChannel    = (type()==DRUM) ? 9 : 0;
895 
896       clefType=trebleClef;
897 
898       _curDrumPatchNumber = CTRL_VAL_UNKNOWN;
899 
900       transposition  = 0;
901       velocity       = 0;
902       delay          = 0;
903       len            = 100;          // percent
904       compression    = 100;          // percent
905       }
906 
init_drum_ordering()907 void MidiTrack::init_drum_ordering()
908 {
909   // first display entries with non-empty names, then with empty names.
910 
911   remove_ourselves_from_drum_ordering();
912 
913   for (int i=0;i<128;i++)
914     if (_drummap[i].name!="" && _drummap[i].name!="?") // non-empty name?
915       MusEGlobal::global_drum_ordering.push_back(std::pair<MidiTrack*,int>(this,i));
916 
917   for (int i=0;i<128;i++)
918     if (!(_drummap[i].name!="" && _drummap[i].name!="?")) // empty name?
919       MusEGlobal::global_drum_ordering.push_back(std::pair<MidiTrack*,int>(this,i));
920 }
921 
init_drummap(bool write_ordering)922 void MidiTrack::init_drummap(bool write_ordering)
923 {
924   for (int i=0;i<128;i++)
925     _drummap[i]=iNewDrumMap[i];
926 
927   if (write_ordering)
928     init_drum_ordering();
929 
930   update_drum_in_map();
931 
932   _drummap_ordering_tied_to_patch=true;
933 }
934 
update_drum_in_map()935 void MidiTrack::update_drum_in_map()
936 {
937   for (int i = 0; i < 128; ++i)
938     drum_in_map[(int)_drummap[i].enote] = i;
939 }
940 
941 //---------------------------------------------------------
942 //   height
943 //---------------------------------------------------------
height() const944 int MidiTrack::height() const
945 {
946   if (_isVisible)
947     return _height;
948   return 0;
949 }
950 
951 //---------------------------------------------------------
952 //   routeCapabilities
953 //---------------------------------------------------------
954 
routeCapabilities() const955 RouteCapabilitiesStruct MidiTrack::routeCapabilities() const
956 {
957   RouteCapabilitiesStruct s;
958   s._midiPortChannels._inRoutable = true;
959   s._midiPortChannels._inChannels = MusECore::MUSE_MIDI_CHANNELS;
960   s._trackChannels._outRoutable = true;  // Support Midi Track to Audio Input Track routes (for soloing chain).
961 
962 #ifndef _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
963   s._midiPortChannels._outChannels = MusECore::MUSE_MIDI_CHANNELS;
964 #endif
965 
966   return s;
967 }
968 
969 //---------------------------------------------------------
970 //   canDominateOutputLatency
971 //---------------------------------------------------------
972 
canDominateOutputLatency() const973 inline bool MidiTrack::canDominateOutputLatency() const
974 {
975   // The midi track's own midi file contributions can never dominate latency.
976   return false;
977 }
978 
canCorrectOutputLatency() const979 inline bool MidiTrack::canCorrectOutputLatency() const
980 {
981   return true;
982 }
983 
isLatencyInputTerminal()984 bool MidiTrack::isLatencyInputTerminal()
985 {
986   // Have we been here before during this scan?
987   // Just return the cached value.
988   if(_latencyInfo._isLatencyInputTerminalProcessed)
989     return _latencyInfo._isLatencyInputTerminal;
990 
991   // If we're asking for the view from the record side, check if we're
992   //  passing the signal through the track via monitoring.
993   if(!canPassThruLatency())
994   {
995     _latencyInfo._isLatencyInputTerminal = true;
996     _latencyInfo._isLatencyInputTerminalProcessed = true;
997     return true;
998   }
999 
1000 #ifdef _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
1001   const int port = outPort();
1002   if(port >= 0 && port < MusECore::MIDI_PORTS)
1003   {
1004     MidiPort* mp = &MusEGlobal::midiPorts[port];
1005     MidiDevice* md = mp->device();
1006     if(md && (md->openFlags() & 1 /*write*/))
1007     {
1008       // If it's a non-synth device, or a synth that is not off.
1009       if(!md->isSynti() || !static_cast<SynthI*>(md)->off())
1010       {
1011         _latencyInfo._isLatencyInputTerminal = false;
1012         _latencyInfo._isLatencyInputTerminalProcessed = true;
1013         return false;
1014       }
1015     }
1016   }
1017 
1018 #else
1019 
1020   const RouteList* rl = outRoutes();
1021   for (ciRoute ir = rl->begin(); ir != rl->end(); ++ir) {
1022     switch(ir->type)
1023     {
1024       case Route::MIDI_PORT_ROUTE:
1025       {
1026         const int port = ir->midiPort;
1027         const int ch = ir->channel;
1028         if(port < 0 || port >= MusECore::MIDI_PORTS || ch < -1 || ch >= MusECore::MUSE_MIDI_CHANNELS)
1029           continue;
1030 
1031         MidiPort* mp = &MusEGlobal::midiPorts[ir->midiPort];
1032         MidiDevice* md = mp->device();
1033         if(!md)
1034           continue;
1035 
1036         if(md->openFlags() & 1 /*write*/)
1037         {
1038           _latencyInfo._isLatencyInputTerminal = false;
1039           _latencyInfo._isLatencyInputTerminalProcessed = true;
1040           return false;
1041         }
1042       }
1043       break;
1044 
1045       case Route::TRACK_ROUTE:
1046         if(!ir->track)
1047           continue;
1048         if(ir->track->isMidiTrack())
1049         {
1050           // TODO
1051         }
1052       break;
1053 
1054       default:
1055       break;
1056     }
1057   }
1058 
1059 #endif
1060 
1061   _latencyInfo._isLatencyInputTerminal = true;
1062   _latencyInfo._isLatencyInputTerminalProcessed = true;
1063   return true;
1064 }
1065 
isLatencyOutputTerminal()1066 bool MidiTrack::isLatencyOutputTerminal()
1067 {
1068   // Have we been here before during this scan?
1069   // Just return the cached value.
1070   if(_latencyInfo._isLatencyOutputTerminalProcessed)
1071     return _latencyInfo._isLatencyOutputTerminal;
1072 
1073 #ifdef _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
1074   const int port = outPort();
1075   //if((openFlags() & (capture ? 2 : 1)) && port >= 0 && port < MusECore::MIDI_PORTS)
1076   //if((openFlags() & 1 /*write*/) && port >= 0 && port < MusECore::MIDI_PORTS)
1077   if(port >= 0 && port < MusECore::MIDI_PORTS)
1078   {
1079     MidiPort* mp = &MusEGlobal::midiPorts[port];
1080     MidiDevice* md = mp->device();
1081     if(md && (md->openFlags() & 1 /*write*/))
1082     {
1083       // If it's a non-synth device, or a synth that is not off.
1084       if(!md->isSynti() || !static_cast<SynthI*>(md)->off())
1085       {
1086         _latencyInfo._isLatencyOutputTerminal = false;
1087         _latencyInfo._isLatencyOutputTerminalProcessed = true;
1088         return false;
1089       }
1090     }
1091   }
1092 
1093 #else
1094 
1095   const RouteList* rl = outRoutes();
1096   for (ciRoute ir = rl->begin(); ir != rl->end(); ++ir) {
1097     switch(ir->type)
1098     {
1099       case Route::MIDI_PORT_ROUTE:
1100       {
1101         const int port = ir->midiPort;
1102         const int ch = ir->channel;
1103         if(port < 0 || port >= MusECore::MIDI_PORTS || ch < -1 || ch >= MusECore::MUSE_MIDI_CHANNELS)
1104           continue;
1105 
1106         MidiPort* mp = &MusEGlobal::midiPorts[ir->midiPort];
1107         MidiDevice* md = mp->device();
1108         if(!md)
1109           continue;
1110 
1111         if(md->openFlags() & 1 /*write*/)
1112         {
1113           _latencyInfo._isLatencyOutputTerminal = false;
1114           _latencyInfo._isLatencyOutputTerminalProcessed = true;
1115           return false;
1116         }
1117       }
1118       break;
1119 
1120       case Route::TRACK_ROUTE:
1121         if(!ir->track)
1122           continue;
1123         if(ir->track->isMidiTrack())
1124         {
1125           // TODO
1126         }
1127       break;
1128 
1129       default:
1130       break;
1131     }
1132   }
1133 
1134 #endif
1135 
1136   _latencyInfo._isLatencyOutputTerminal = true;
1137   _latencyInfo._isLatencyOutputTerminalProcessed = true;
1138   return true;
1139 }
1140 
1141 //---------------------------------------------------------
1142 //   getDominanceInfo
1143 //---------------------------------------------------------
1144 
getDominanceInfo(bool input)1145 TrackLatencyInfo& MidiTrack::getDominanceInfo(bool input)
1146 {
1147       // Have we been here before during this scan?
1148       // Just return the cached value.
1149       if((input && _latencyInfo._canDominateInputProcessed) ||
1150         (!input && _latencyInfo._canDominateProcessed))
1151         return _latencyInfo;
1152 
1153       // Get the default domination for this track type.
1154       bool can_dominate_lat = input ? canDominateInputLatency() : canDominateOutputLatency();
1155       bool can_correct_lat = canCorrectOutputLatency();
1156 
1157       const bool passthru = canPassThruLatency();
1158 
1159       // Gather latency info from all connected input branches,
1160       //  but ONLY if the track is not off.
1161       bool item_found = false;
1162 
1163       if(!off() && (passthru || input))
1164       {
1165         RouteList* rl = inRoutes();
1166         for (iRoute ir = rl->begin(); ir != rl->end(); ++ir)
1167         {
1168           switch(ir->type)
1169           {
1170             case Route::MIDI_PORT_ROUTE:
1171             {
1172               const int port = ir->midiPort;
1173               const int ch = ir->channel;
1174               if(port < 0 || port >= MusECore::MIDI_PORTS || ch < -1 || ch >= MusECore::MUSE_MIDI_CHANNELS)
1175                 continue;
1176 
1177               MidiPort* mp = &MusEGlobal::midiPorts[ir->midiPort];
1178               MidiDevice* md = mp->device();
1179               if(!md)
1180                 continue;
1181 
1182               //if(!off() && (md->openFlags() & 2 /*read*/) &&  (passthru || input))
1183               if(md->openFlags() & 2 /*read*/)
1184               {
1185                 const TrackLatencyInfo& li = md->getDominanceInfoMidi(true /*capture*/, false);
1186 
1187                 // Whether the branch can dominate or correct latency or if we
1188                 //  want to allow unterminated input branches to
1189                 //  participate in worst branch latency calculations.
1190                 const bool participate =
1191                   (li._canCorrectOutputLatency ||
1192                   li._canDominateOutputLatency ||
1193                   MusEGlobal::config.correctUnterminatedInBranchLatency);
1194 
1195                 if(participate)
1196                 {
1197                   // Is it the first found item?
1198                   if(item_found)
1199                   {
1200                     // If any one of the branches can dominate the latency,
1201                     //  that overrides any which cannot.
1202                     if(li._canDominateOutputLatency)
1203                         can_dominate_lat = true;
1204                     if(li._canCorrectOutputLatency)
1205                       can_correct_lat = true;
1206                   }
1207                   else
1208                   {
1209                     item_found = true;
1210                     // Override the defaults with this first item's values.
1211                     //route_worst_out_corr = li._outputAvailableCorrection;
1212                     can_dominate_lat = li._canDominateOutputLatency;
1213                     can_correct_lat = li._canCorrectOutputLatency;
1214                   }
1215                 }
1216               }
1217             }
1218             break;
1219 
1220             case Route::TRACK_ROUTE:
1221               if(!ir->track)
1222                 continue;
1223               if(ir->track->isMidiTrack())
1224               {
1225                 // TODO
1226               }
1227             break;
1228 
1229             default:
1230             break;
1231           }
1232         }
1233       }
1234 
1235       // Set the correction of all connected input branches,
1236       //  but ONLY if the track is not off.
1237       if(!off())
1238       {
1239         if(input)
1240         {
1241           _latencyInfo._canDominateInputLatency = can_dominate_lat;
1242         }
1243         else
1244         {
1245           _latencyInfo._canDominateOutputLatency = can_dominate_lat;
1246           // If any of the branches can dominate, then this node cannot correct.
1247           _latencyInfo._canCorrectOutputLatency = can_correct_lat && !can_dominate_lat;
1248         }
1249       }
1250 
1251       if(input)
1252         _latencyInfo._canDominateInputProcessed = true;
1253       else
1254         _latencyInfo._canDominateProcessed = true;
1255 
1256       return _latencyInfo;
1257 }
1258 
1259 //---------------------------------------------------------
1260 //   getDominanceLatencyInfo
1261 //---------------------------------------------------------
1262 
getDominanceLatencyInfo(bool input)1263 TrackLatencyInfo& MidiTrack::getDominanceLatencyInfo(bool input)
1264 {
1265       // Have we been here before during this scan?
1266       // Just return the cached value.
1267       if((input && _latencyInfo._dominanceInputProcessed) ||
1268         (!input && _latencyInfo._dominanceProcessed))
1269         return _latencyInfo;
1270 
1271       float route_worst_latency = 0.0f;
1272 
1273       const bool passthru = canPassThruLatency();
1274 
1275       bool item_found = false;
1276 
1277       float worst_self_latency = 0.0f;
1278       if(!input && !off())
1279         worst_self_latency = getWorstSelfLatencyAudio();
1280 
1281       if(!off() && (passthru || input))
1282       {
1283         RouteList* rl = inRoutes();
1284         for (iRoute ir = rl->begin(); ir != rl->end(); ++ir)
1285         {
1286           switch(ir->type)
1287           {
1288             case Route::MIDI_PORT_ROUTE:
1289             {
1290               const int port = ir->midiPort;
1291               const int ch = ir->channel;
1292               if(port < 0 || port >= MusECore::MIDI_PORTS || ch < -1 || ch >= MusECore::MUSE_MIDI_CHANNELS)
1293                 continue;
1294 
1295               MidiPort* mp = &MusEGlobal::midiPorts[ir->midiPort];
1296               MidiDevice* md = mp->device();
1297               if(!md)
1298                 continue;
1299 
1300               //if(!off() && (md->openFlags() & 2 /*read*/) &&  (passthru || input))
1301               if(md->openFlags() & 2 /*read*/)
1302               {
1303                 const TrackLatencyInfo& li = md->getDominanceLatencyInfoMidi(true /*capture*/, false);
1304 
1305                 // Whether the branch can dominate or correct latency or if we
1306                 //  want to allow unterminated input branches to
1307                 //  participate in worst branch latency calculations.
1308                 const bool participate =
1309                   (li._canCorrectOutputLatency ||
1310                   li._canDominateOutputLatency ||
1311                   MusEGlobal::config.correctUnterminatedInBranchLatency);
1312 
1313                 if(participate)
1314                 {
1315                   // Is it the first found item?
1316                   if(item_found)
1317                   {
1318                     // If any one of the branches can dominate the latency,
1319                     //  that overrides any which cannot.
1320                     if(li._canDominateOutputLatency)
1321                     {
1322                       // Override the current worst value if the latency is greater,
1323                       //  but ONLY if the branch can dominate.
1324                       //if(li._outputLatency > route_worst_latency)
1325                       //  route_worst_latency = li._outputLatency;
1326                     }
1327                     // Override the current worst value if the latency is greater,
1328                     //  but ONLY if the branch can dominate.
1329                     if(li._outputLatency > route_worst_latency)
1330                       route_worst_latency = li._outputLatency;
1331                   }
1332                   else
1333                   {
1334                     item_found = true;
1335                     // Override the default worst value, but ONLY if the branch can dominate.
1336                     //if(li._canDominateOutputLatency)
1337                       route_worst_latency = li._outputLatency;
1338                   }
1339                 }
1340               }
1341             }
1342             break;
1343 
1344             case Route::TRACK_ROUTE:
1345               if(!ir->track)
1346                 continue;
1347               if(ir->track->isMidiTrack())
1348               {
1349                 // TODO
1350               }
1351             break;
1352 
1353             default:
1354             break;
1355           }
1356         }
1357       }
1358 
1359       // Set the correction of all connected input branches,
1360       //  but ONLY if the track is not off.
1361       if(!off())
1362       {
1363         if(input)
1364         {
1365           _latencyInfo._inputLatency = route_worst_latency;
1366         }
1367         else
1368         {
1369           if(passthru)
1370           {
1371             _latencyInfo._outputLatency = worst_self_latency + route_worst_latency;
1372             _latencyInfo._inputLatency = route_worst_latency;
1373           }
1374           else
1375           {
1376             _latencyInfo._outputLatency = worst_self_latency + _latencyInfo._sourceCorrectionValue;
1377           }
1378         }
1379       }
1380 
1381       if(input)
1382         _latencyInfo._dominanceInputProcessed = true;
1383       else
1384         _latencyInfo._dominanceProcessed = true;
1385 
1386       return _latencyInfo;
1387 }
1388 
1389 //---------------------------------------------------------
1390 //   setCorrectionLatencyInfo
1391 //---------------------------------------------------------
1392 
setCorrectionLatencyInfo(bool input,float finalWorstLatency,float callerBranchLatency)1393 TrackLatencyInfo& MidiTrack::setCorrectionLatencyInfo(bool input, float finalWorstLatency, float callerBranchLatency)
1394 {
1395   const bool passthru = canPassThruLatency();
1396 
1397   float worst_self_latency = 0.0f;
1398   if(!input && !off())
1399     worst_self_latency = getWorstSelfLatencyAudio();
1400 
1401   // The _trackLatency should already be calculated in the dominance scan.
1402   const float branch_lat = callerBranchLatency + worst_self_latency;
1403 
1404   if(!off() && (passthru || input))
1405   {
1406     RouteList* rl = inRoutes();
1407     for (iRoute ir = rl->begin(); ir != rl->end(); ++ir)
1408     {
1409       switch(ir->type)
1410       {
1411           case Route::MIDI_PORT_ROUTE:
1412           {
1413             if(ir->midiPort < 0 || ir->midiPort >= MusECore::MIDI_PORTS ||
1414                 ir->channel < -1 || ir->channel >= MusECore::MUSE_MIDI_CHANNELS)
1415               continue;
1416             const MidiPort* mp = &MusEGlobal::midiPorts[ir->midiPort];
1417             MidiDevice* md = mp->device();
1418 
1419             //if(!off() && md && (md->openFlags() & 2 /*read*/) && (passthru || input))
1420             if(md && (md->openFlags() & 2 /*read*/))
1421               md->setCorrectionLatencyInfoMidi(true /*capture*/, false, finalWorstLatency, branch_lat);
1422           }
1423           break;
1424 
1425           default:
1426           break;
1427       }
1428     }
1429   }
1430 
1431   // Set the correction of all connected input branches,
1432   //  but ONLY if the track is not off.
1433   if(!off())
1434   {
1435     if(input)
1436     {
1437     }
1438     else
1439     {
1440       if(canCorrectOutputLatency() && _latencyInfo._canCorrectOutputLatency)
1441       {
1442         float corr = 0.0f;
1443         if(MusEGlobal::config.commonProjectLatency)
1444           corr -= finalWorstLatency;
1445 
1446         corr -= branch_lat;
1447         // The _sourceCorrectionValue is initialized to zero.
1448         // Whichever calling branch needs the most correction gets it.
1449         if(corr < _latencyInfo._sourceCorrectionValue)
1450           _latencyInfo._sourceCorrectionValue = corr;
1451       }
1452     }
1453 
1454     //fprintf(stderr, "MidiTrack::setCorrectionLatencyInfo() name:%s finalWorstLatency:%f branch_lat:%f corr:%f _sourceCorrectionValue:%f\n",
1455     //        name().toLatin1().constData(), finalWorstLatency, branch_lat, corr, _latencyInfo._sourceCorrectionValue);
1456   }
1457 
1458   return _latencyInfo;
1459 }
1460 
1461 //---------------------------------------------------------
1462 //   getLatencyInfo
1463 //---------------------------------------------------------
1464 
getLatencyInfo(bool input)1465 TrackLatencyInfo& MidiTrack::getLatencyInfo(bool input)
1466 {
1467   // Have we been here before during this scan?
1468   // Just return the cached value.
1469   if((input && _latencyInfo._inputProcessed) ||
1470     (!input && _latencyInfo._processed))
1471     return _latencyInfo;
1472 
1473   float route_worst_latency = _latencyInfo._inputLatency;
1474 
1475   const bool passthru = canPassThruLatency();
1476 
1477   RouteList* rl = inRoutes();
1478 
1479   // Now that we know the worst-case latency of the connected branches,
1480   //  adjust each of the conveniently stored temporary latency values
1481   //  in the routes according to whether they can dominate...
1482   for (iRoute ir = rl->begin(); ir != rl->end(); ++ir)
1483   {
1484       switch(ir->type)
1485       {
1486         case Route::MIDI_PORT_ROUTE:
1487         {
1488           const int port = ir->midiPort;
1489           const int ch = ir->channel;
1490           if(port < 0 || port >= MusECore::MIDI_PORTS || ch < -1 || ch >= MusECore::MUSE_MIDI_CHANNELS)
1491             continue;
1492 
1493           MidiPort* mp = &MusEGlobal::midiPorts[ir->midiPort];
1494           MidiDevice* md = mp->device();
1495           if(!md)
1496             continue;
1497 
1498           if(passthru || input)
1499           {
1500             // Default to zero.
1501             ir->audioLatencyOut = 0.0f;
1502 
1503             if(!off() && (md->openFlags() & 2 /*read*/))
1504             {
1505               const TrackLatencyInfo& li = md->getLatencyInfoMidi(true /*capture*/, false);
1506               const bool participate =
1507                 (li._canCorrectOutputLatency ||
1508                 li._canDominateOutputLatency ||
1509                 MusEGlobal::config.correctUnterminatedInBranchLatency);
1510 
1511               if(participate)
1512               {
1513                 // Prepare the latency value to be passed to the compensator's writer,
1514                 //  by adjusting each route latency value. ie. the route with the worst-case
1515                 //  latency will get ZERO delay, while routes having smaller latency will get
1516                 //  MORE delay, to match all the signal timings together.
1517                 // The route's audioLatencyOut should have already been calculated and
1518                 //  conveniently stored in the route.
1519                 ir->audioLatencyOut = route_worst_latency - li._outputLatency;
1520                 // Should not happen, but just in case.
1521                 if((long int)ir->audioLatencyOut < 0)
1522                   ir->audioLatencyOut = 0.0f;
1523               }
1524             }
1525           }
1526         }
1527         break;
1528 
1529         case Route::TRACK_ROUTE:
1530           if(!ir->track)
1531             continue;
1532           if(ir->track->isMidiTrack())
1533           {
1534             // TODO
1535           }
1536         break;
1537 
1538         default:
1539         break;
1540       }
1541   }
1542 
1543   if(input)
1544     _latencyInfo._inputProcessed = true;
1545   else
1546     _latencyInfo._processed = true;
1547 
1548   return _latencyInfo;
1549 }
1550 
setLatencyCompWriteOffset(float worstCase)1551 void MidiTrack::setLatencyCompWriteOffset(float worstCase)
1552 {
1553   // If independent branches are NOT to affect project latency,
1554   //  then there should be no need for any extra delay in the branch.
1555   if(!MusEGlobal::config.commonProjectLatency)
1556   {
1557     _latencyInfo._compensatorWriteOffset = 0;
1558     //fprintf(stderr, "MidiTrack::setLatencyCompWriteOffset() name:%s worstCase:%f _outputLatency:%f _compensatorWriteOffset:%lu\n",
1559     //        name().toLatin1().constData(), worstCase, _latencyInfo._outputLatency, _latencyInfo._compensatorWriteOffset);
1560     return;
1561   }
1562 
1563   if(_latencyInfo._canDominateOutputLatency)
1564   {
1565     const long unsigned int wc = worstCase;
1566     const long unsigned int ol = _latencyInfo._outputLatency;
1567     if(ol > wc)
1568       _latencyInfo._compensatorWriteOffset = 0;
1569     else
1570       _latencyInfo._compensatorWriteOffset = wc - ol;
1571   }
1572   else
1573   {
1574 //     if(_latencyInfo._outputLatency < 0)
1575       _latencyInfo._compensatorWriteOffset = 0;
1576 //     else
1577 //       _latencyInfo._compensatorWriteOffset = _latencyInfo._outputLatency;
1578   }
1579 
1580   //fprintf(stderr, "MidiTrack::setLatencyCompWriteOffset() name:%s worstCase:%f _outputLatency:%f _canDominateOutputLatency:%d _compensatorWriteOffset:%lu\n",
1581   //        name().toLatin1().constData(), worstCase, _latencyInfo._outputLatency, _latencyInfo._canDominateOutputLatency, _latencyInfo._compensatorWriteOffset);
1582 }
1583 
1584 //---------------------------------------------------------
1585 //   noOutRoute
1586 //---------------------------------------------------------
1587 
noOutRoute() const1588 bool MidiTrack::noOutRoute() const
1589 {
1590 
1591   return _outRoutes.empty()
1592 
1593 #ifdef _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
1594     && (outChannel() < 0 || outPort() < 0 || !MusEGlobal::midiPorts[outPort()].device())
1595 #endif
1596   ;
1597 }
1598 
1599 //---------------------------------------------------------
1600 //   mappedPortChanCtrl
1601 //---------------------------------------------------------
1602 
mappedPortChanCtrl(int * ctrl,int * port,MidiPort ** mport,int * channel) const1603 bool MidiTrack::mappedPortChanCtrl(int *ctrl, int *port, MidiPort** mport, int *channel) const
1604 {
1605   bool res = false;
1606   int t_ctrl = *ctrl;
1607   int t_port = outPort();
1608   int t_ch = outChannel();
1609   MidiPort* mp = &MusEGlobal::midiPorts[t_port];
1610 
1611   const MidiController* mc = mp->drumController(t_ctrl);
1612   if(mc)
1613   {
1614     res = true;
1615     const int note = t_ctrl & 0x7f;
1616     // Is it a drum controller old_event, according to the track port's instrument?
1617     if(type() == Track::DRUM)
1618     {
1619       // Default to track port if -1 and track channel if -1.
1620       const int ch = drummap()[note].channel;
1621       if(ch != -1)
1622         t_ch = ch;
1623       const int p = drummap()[note].port;
1624       if(p != -1)
1625         t_port = p;
1626       t_ctrl &= ~0xff;
1627       t_ctrl |= drummap()[note].anote;
1628     }
1629   }
1630 
1631   *ctrl = t_ctrl;
1632   if(port)
1633     (*port) = t_port;
1634   if(mport)
1635     (*mport) = &MusEGlobal::midiPorts[t_port];
1636   if(channel)
1637     (*channel) = t_ch;
1638 
1639   return res;
1640 }
1641 
1642 //---------------------------------------------------------
1643 //   setOutChannel
1644 //---------------------------------------------------------
1645 
setOutChannel(int i,bool doSignal)1646 MidiTrack::ChangedType_t MidiTrack::setOutChannel(int i, bool doSignal)
1647 {
1648   if(_outChannel == i)
1649     return NothingChanged;
1650   _outChannel = i;
1651   ChangedType_t res = ChannelChanged;
1652   if(updateDrummap(doSignal))
1653     res |= DrumMapChanged;
1654   return res;
1655 }
1656 
1657 //---------------------------------------------------------
1658 //   setOutPort
1659 //---------------------------------------------------------
1660 
setOutPort(int i,bool doSignal)1661 MidiTrack::ChangedType_t MidiTrack::setOutPort(int i, bool doSignal)
1662 {
1663   if(_outPort == i)
1664     return NothingChanged;
1665   _outPort = i;
1666   ChangedType_t res = PortChanged;
1667   if(updateDrummap(doSignal))
1668     res |= DrumMapChanged;
1669   return res;
1670 }
1671 
1672 //---------------------------------------------------------
1673 //   setOutChanAndUpdate
1674 //---------------------------------------------------------
1675 
setOutChanAndUpdate(int i,bool doSignal)1676 MidiTrack::ChangedType_t MidiTrack::setOutChanAndUpdate(int i, bool doSignal)
1677 {
1678   if(_outChannel == i)
1679     return NothingChanged;
1680 
1681   removePortCtrlEvents(this);
1682   _outChannel = i;
1683   ChangedType_t res = ChannelChanged;
1684   if(updateDrummap(doSignal))
1685     res |= DrumMapChanged;
1686   addPortCtrlEvents(this);
1687   return res;
1688 }
1689 
1690 //---------------------------------------------------------
1691 //   setOutPortAndUpdate
1692 //---------------------------------------------------------
1693 
setOutPortAndUpdate(int i,bool doSignal)1694 MidiTrack::ChangedType_t MidiTrack::setOutPortAndUpdate(int i, bool doSignal)
1695 {
1696   if(_outPort == i)
1697     return NothingChanged;
1698 
1699   removePortCtrlEvents(this);
1700   _outPort = i;
1701   ChangedType_t res = PortChanged;
1702   if(updateDrummap(doSignal))
1703     res |= DrumMapChanged;
1704   addPortCtrlEvents(this);
1705   return res;
1706 }
1707 
1708 //---------------------------------------------------------
1709 //   setOutPortAndChannelAndUpdate
1710 //---------------------------------------------------------
1711 
setOutPortAndChannelAndUpdate(int port,int ch,bool doSignal)1712 MidiTrack::ChangedType_t MidiTrack::setOutPortAndChannelAndUpdate(int port, int ch, bool doSignal)
1713 {
1714   if(_outPort == port && _outChannel == ch)
1715     return NothingChanged;
1716 
1717   removePortCtrlEvents(this);
1718   _outPort = port;
1719   _outChannel = ch;
1720   ChangedType_t res = PortChanged | ChannelChanged;
1721   if(updateDrummap(doSignal))
1722     res |= DrumMapChanged;
1723   addPortCtrlEvents(this);
1724   return res;
1725 }
1726 
1727 //---------------------------------------------------------
1728 //   setInPortAndChannelMask
1729 //   For old song files with port mask (max 32 ports) and channel mask (16 channels),
1730 //    before midi routing was added (the iR button).
1731 //---------------------------------------------------------
1732 
setInPortAndChannelMask(unsigned int portmask,int chanmask)1733 void MidiTrack::setInPortAndChannelMask(unsigned int portmask, int chanmask)
1734 {
1735   //bool changed = false;
1736   PendingOperationList operations;
1737 
1738   for(int port = 0; port < 32; ++port)  // 32 is the old maximum number of ports.
1739   {
1740     // If the port was not used in the song file to begin with, just ignore it.
1741     // This saves from having all of the first 32 ports' channels connected.
1742     if(!MusEGlobal::midiPorts[port].foundInSongFile())
1743       continue;
1744 
1745     const int allch = (1 << MusECore::MUSE_MIDI_CHANNELS) - 1;
1746     // Check if Omni route will do...
1747     if(chanmask == allch)
1748     {
1749       // Route wanted?
1750       if(portmask & (1 << port))
1751         operations.add(MusECore::PendingOperationItem(MusECore::Route(port), MusECore::Route(this),
1752                                                       MusECore::PendingOperationItem::AddRoute));
1753       else
1754         operations.add(MusECore::PendingOperationItem(MusECore::Route(port), MusECore::Route(this),
1755                                                       MusECore::PendingOperationItem::DeleteRoute));
1756     }
1757     else
1758     // Add individual channels:
1759     for(int ch = 0; ch < MusECore::MUSE_MIDI_CHANNELS; ++ch)
1760     {
1761       // Route wanted?
1762       if(portmask & (1 << port) && (chanmask & (1 << ch)))
1763         operations.add(MusECore::PendingOperationItem(MusECore::Route(port, ch), MusECore::Route(this, ch),
1764                                                       MusECore::PendingOperationItem::AddRoute));
1765       else
1766         operations.add(MusECore::PendingOperationItem(MusECore::Route(port, ch), MusECore::Route(this, ch),
1767                                                       MusECore::PendingOperationItem::DeleteRoute));
1768     }
1769   }
1770 
1771 //   if(changed)
1772 //   {
1773 //     MusEGlobal::audio->msgUpdateSoloStates();
1774 //     MusEGlobal::song->update(SC_ROUTE);
1775 //   }
1776 
1777   if(!operations.empty())
1778   {
1779     MusEGlobal::audio->msgExecutePendingOperations(operations, true);
1780 //     MusEGlobal::song->update(SC_ROUTE);
1781   }
1782 }
1783 
1784 
1785 //---------------------------------------------------------
1786 //   newPart
1787 //---------------------------------------------------------
1788 
newPart(Part * p,bool clone)1789 Part* MidiTrack::newPart(Part*p, bool clone)
1790       {
1791       MidiPart* part;
1792       if(!p)
1793       {
1794         part = new MidiPart(this);
1795       }
1796       else
1797       {
1798         if (clone)
1799         {
1800               part = (MidiPart*)p->createNewClone();
1801               part->setTrack(this);
1802         }
1803         else
1804         {
1805               part = (MidiPart*)p->duplicate();
1806               part->setTrack(this);
1807         }
1808       }
1809       return part;
1810       }
1811 
1812 //---------------------------------------------------------
1813 //   addStuckNote
1814 //---------------------------------------------------------
1815 
addStuckNote(const MidiPlayEvent & ev)1816 bool MidiTrack::addStuckNote(const MidiPlayEvent& ev)
1817 {
1818   stuckNotes.add(ev);
1819   return true;
1820 }
1821 
1822 //---------------------------------------------------------
1823 //   addStuckLiveNote
1824 //   Return true if note was added.
1825 //---------------------------------------------------------
1826 
addStuckLiveNote(int port,int chan,int note,int vel)1827 bool MidiTrack::addStuckLiveNote(int port, int chan, int note, int vel)
1828 {
1829 //   for(ciMPEvent k = stuckLiveNotes.begin(); k != stuckLiveNotes.end(); ++k)
1830 //   {
1831 //     // We're looking for port, channel, and note. Time and velocity are not relevant.
1832 //     if((*k).port() == port &&
1833 //        (*k).channel() == chan &&
1834 //        (*k).dataA() == note)
1835 //       return false;
1836 //   }
1837   stuckLiveNotes.add(MidiPlayEvent(0, port, chan, ME_NOTEOFF, note, vel)); // Mark for immediate playback
1838   return true;
1839 }
1840 
1841 //---------------------------------------------------------
1842 //   removeStuckLiveNote
1843 //   Return true if note was removed.
1844 //---------------------------------------------------------
1845 
removeStuckLiveNote(int port,int chan,int note)1846 bool MidiTrack::removeStuckLiveNote(int port, int chan, int note)
1847 {
1848   for(ciMPEvent k = stuckLiveNotes.begin(); k != stuckLiveNotes.end(); ++k)
1849   {
1850     // We're looking for port, channel, and note. Time and velocity are not relevant.
1851     if((*k).port() == port &&
1852        (*k).channel() == chan &&
1853        (*k).dataA() == note)
1854     {
1855       stuckLiveNotes.erase(k);
1856       return true;
1857     }
1858   }
1859   return false;
1860 }
1861 
1862 //---------------------------------------------------------
1863 //   stuckLiveNoteExists
1864 //   Return true if note exists.
1865 //---------------------------------------------------------
1866 
stuckLiveNoteExists(int port,int chan,int note)1867 bool MidiTrack::stuckLiveNoteExists(int port, int chan, int note)
1868 {
1869   for(ciMPEvent k = stuckLiveNotes.begin(); k != stuckLiveNotes.end(); ++k)
1870   {
1871     // We're looking for port, channel, and note. Time and velocity are not relevant.
1872     if((*k).port() == port &&
1873        (*k).channel() == chan &&
1874        (*k).dataA() == note)
1875       return true;
1876   }
1877   return false;
1878 }
1879 
1880 //---------------------------------------------------------
1881 //   automationType
1882 //---------------------------------------------------------
1883 
automationType() const1884 AutomationType MidiTrack::automationType() const
1885       {
1886       MidiPort* port = &MusEGlobal::midiPorts[outPort()];
1887       return port->automationType(outChannel());
1888       }
1889 
1890 //---------------------------------------------------------
1891 //   setAutomationType
1892 //---------------------------------------------------------
1893 
setAutomationType(AutomationType t)1894 void MidiTrack::setAutomationType(AutomationType t)
1895       {
1896       MidiPort* port = &MusEGlobal::midiPorts[outPort()];
1897       port->setAutomationType(outChannel(), t);
1898       }
1899 
1900 //---------------------------------------------------------
1901 //   MidiTrack::write
1902 //---------------------------------------------------------
1903 
write(int level,Xml & xml) const1904 void MidiTrack::write(int level, Xml& xml) const
1905       {
1906       const char* tag;
1907 
1908       if (type() == MIDI)
1909             tag = "miditrack";
1910       else if (type() == DRUM)
1911             tag = "newdrumtrack";
1912       else {
1913             printf("THIS SHOULD NEVER HAPPEN: non-midi-type in MidiTrack::write()\n");
1914             tag="";
1915       }
1916 
1917       xml.tag(level++, tag);
1918       Track::writeProperties(level, xml);
1919 
1920       xml.intTag(level, "device", outPort());
1921       xml.intTag(level, "channel", outChannel());
1922       xml.intTag(level, "locked", _locked);
1923 
1924       xml.intTag(level, "transposition", transposition);
1925       xml.intTag(level, "velocity", velocity);
1926       xml.intTag(level, "delay", delay);
1927       xml.intTag(level, "len", len);
1928       xml.intTag(level, "compression", compression);
1929       xml.intTag(level, "automation", int(automationType()));
1930       xml.intTag(level, "clef", int(clefType));
1931 
1932       const PartList* pl = cparts();
1933       for (ciPart p = pl->begin(); p != pl->end(); ++p)
1934             p->second->write(level, xml);
1935 
1936       writeOurDrumSettings(level, xml);
1937 
1938       xml.etag(level, tag);
1939       }
1940 
writeOurDrumSettings(int level,Xml & xml) const1941 void MidiTrack::writeOurDrumSettings(int level, Xml& xml) const
1942 {
1943   xml.tag(level++, "our_drum_settings");
1944   _workingDrumMapPatchList->write(level, xml);
1945   xml.intTag(level, "ordering_tied", _drummap_ordering_tied_to_patch);
1946   xml.etag(level, "our_drum_settings");
1947 }
1948 
dumpMap()1949 void MidiTrack::dumpMap()
1950 {
1951   if(type() != DRUM)
1952     return;
1953   const int port = outPort();
1954   if(port < 0 || port >= MusECore::MIDI_PORTS)
1955     return;
1956   MidiPort* mp = &MusEGlobal::midiPorts[port];
1957   const int chan = outChannel();
1958   const int patch = mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM);
1959 
1960   fprintf(stderr, "Drum map for patch:%d\n\n", patch);
1961 
1962   fprintf(stderr, "name\t\tvol\tqnt\tlen\tchn\tprt\tlv1\tlv2\tlv3\tlv4\tenote\t\tanote\\ttmute\thide\n");
1963 
1964   DrumMap all_dm,
1965 #ifdef _USE_INSTRUMENT_OVERRIDES_
1966     instr_dm, instrdef_dm,
1967 #endif
1968     track_dm, trackdef_dm;
1969 
1970   for(int index = 0; index < 128; ++index)
1971   {
1972     getMapItem(patch, index, all_dm, WorkingDrumMapEntry::AllOverrides);
1973     getMapItem(patch, index, track_dm, WorkingDrumMapEntry::TrackOverride);
1974     getMapItem(patch, index, trackdef_dm, WorkingDrumMapEntry::TrackDefaultOverride);
1975 #ifdef _USE_INSTRUMENT_OVERRIDES_
1976     getMapItem(patch, index, instr_dm, WorkingDrumMapEntry::InstrumentOverride);
1977     getMapItem(patch, index, instrdef_dm, WorkingDrumMapEntry::InstrumentDefaultOverride);
1978 #endif
1979 
1980     fprintf(stderr, "Index:%d ", index);
1981     fprintf(stderr, "All overrides:\n");
1982     all_dm.dump();
1983 
1984 #ifdef _USE_INSTRUMENT_OVERRIDES_
1985     fprintf(stderr, "Instrument override:\n");
1986     instr_dm.dump();
1987     fprintf(stderr, "Instrument default override:\n");
1988     instrdef_dm.dump();
1989 #endif
1990 
1991     fprintf(stderr, "Track override:\n");
1992     track_dm.dump();
1993     fprintf(stderr, "Track default override:\n");
1994     trackdef_dm.dump();
1995 
1996     fprintf(stderr, "\n");
1997   }
1998 }
1999 
2000 
2001 //---------------------------------------------------------
2002 //   MidiTrack::read
2003 //---------------------------------------------------------
2004 
read(Xml & xml)2005 void MidiTrack::read(Xml& xml)
2006       {
2007       unsigned int portmask = 0;
2008       int chanmask = 0;
2009       bool portmask_found = false;
2010       bool chanmask_found = false;
2011 
2012       for (;;) {
2013             Xml::Token token = xml.parse();
2014             const QString& tag = xml.s1();
2015             switch (token) {
2016                   case Xml::Error:
2017                   case Xml::End:
2018                         goto out_of_MidiTrackRead_forloop;
2019                   case Xml::TagStart:
2020                         if (tag == "transposition")
2021                               transposition = xml.parseInt();
2022                         else if (tag == "velocity")
2023                               velocity = xml.parseInt();
2024                         else if (tag == "delay")
2025                               delay = xml.parseInt();
2026                         else if (tag == "len")
2027                               len = xml.parseInt();
2028                         else if (tag == "compression")
2029                               compression = xml.parseInt();
2030                         else if (tag == "part") {
2031                               Part* p = Part::readFromXml(xml, this);
2032                               if(p)
2033                                 parts()->add(p);
2034                               }
2035                         // TODO: These two device and channel sections will need to change
2036                         //         if and when multiple output routes are supported.
2037                         //       For now just look for the first default (there's only one)...
2038                         else if (tag == "device") {
2039                                 int port = xml.parseInt();
2040                                 if(port == -1)
2041                                 {
2042                                   for(int i = 0; i < MusECore::MIDI_PORTS; ++i)
2043                                   {
2044                                     if(MusEGlobal::midiPorts[i].defaultOutChannels())
2045                                     {
2046                                       port = i;
2047                                       break;
2048                                     }
2049                                   }
2050                                 }
2051                                 if(port == -1)
2052                                   port = 0;
2053                                 setOutPort(port);
2054                               }
2055                         else if (tag == "channel") {
2056                                 int chan = xml.parseInt();
2057                                 if(chan == -1)
2058                                 {
2059                                   for(int i = 0; i < MusECore::MIDI_PORTS; ++i)
2060                                   {
2061                                     int defchans = MusEGlobal::midiPorts[i].defaultOutChannels();
2062                                     for(int c = 0; c < MusECore::MUSE_MIDI_CHANNELS; ++c)
2063                                     {
2064                                       if(defchans & (1 << c))
2065                                       {
2066                                         chan = c;
2067                                         break;
2068                                       }
2069                                     }
2070                                     if(chan != -1)
2071                                       break;
2072                                   }
2073                                 }
2074                                 if(chan == -1)
2075                                   chan = 0;
2076                                 setOutChannel(chan);
2077                               }
2078                         else if (tag == "inportMap")
2079                         {
2080                               portmask = xml.parseUInt();           // Obsolete but support old files.
2081                               portmask_found = true;
2082                         }
2083                         else if (tag == "inchannelMap")
2084                         {
2085                               chanmask = xml.parseInt();            // Obsolete but support old files.
2086                               chanmask_found = true;
2087                         }
2088                         else if (tag == "locked")
2089                               _locked = xml.parseInt();
2090                         else if (tag == "echo")                     // Obsolete but support old files.
2091                               setRecMonitor(xml.parseInt());
2092                         else if (tag == "automation")
2093                               setAutomationType(AutomationType(xml.parseInt()));
2094                         else if (tag == "clef")
2095                               clefType = (clefTypes)xml.parseInt();
2096                         else if (tag == "our_drum_settings")
2097                               readOurDrumSettings(xml);
2098                         else if (Track::readProperties(xml, tag)) {
2099                               // version 1.0 compatibility:
2100                               if (tag == "track" && xml.majorVersion() == 1 && xml.minorVersion() == 0)
2101                                     break;
2102                               xml.unknown("MidiTrack");
2103                               }
2104                         break;
2105                   case Xml::Attribut:
2106                         break;
2107                   case Xml::TagEnd:
2108                         if (tag == "miditrack" || tag == "drumtrack" || tag == "newdrumtrack")
2109                         {
2110                           if(portmask_found && chanmask_found)
2111                             setInPortAndChannelMask(portmask, chanmask); // Support old files.
2112                           goto out_of_MidiTrackRead_forloop;
2113                         }
2114                   default:
2115                         break;
2116                   }
2117             }
2118 
2119 out_of_MidiTrackRead_forloop:
2120       chainTrackParts(this);
2121       }
2122 
readOurDrumSettings(Xml & xml)2123 void MidiTrack::readOurDrumSettings(Xml& xml)
2124 {
2125   bool doUpdateDrummap = false;
2126   for (;;)
2127   {
2128     Xml::Token token = xml.parse();
2129     if (token == Xml::Error || token == Xml::End)
2130       break;
2131     const QString& tag = xml.s1();
2132     switch (token)
2133     {
2134       case Xml::TagStart:
2135         if (tag == "tied")
2136           xml.parseInt(); // Obsolete.
2137         else if (tag == "ordering_tied")
2138           _drummap_ordering_tied_to_patch = xml.parseInt();
2139 
2140         else if (tag == "our_drummap" ||  // OBSOLETE. Support old files.
2141                  tag == "drummap" ||      // OBSOLETE. Support old files.
2142                  tag == "drumMapPatch")
2143         {
2144           // false = Do not fill in unused items.
2145           _workingDrumMapPatchList->read(xml, false);
2146           doUpdateDrummap = true;
2147         }
2148 
2149         else
2150           xml.unknown("our_drum_settings");
2151         break;
2152 
2153       case Xml::TagEnd:
2154         if (tag == "our_drum_settings")
2155         {
2156           if(doUpdateDrummap)
2157           {
2158             // We must ensure that there are NO duplicate enote fields,
2159             //  since the instrument map may have changed by now.
2160             //normalizeWorkingDrumMapPatchList();
2161 
2162             updateDrummap(false);
2163           }
2164           return;
2165         }
2166 
2167       default:
2168         break;
2169     }
2170   }
2171 }
2172 
2173 //---------------------------------------------------------
2174 //   addPart
2175 //---------------------------------------------------------
2176 
addPart(Part * p)2177 iPart Track::addPart(Part* p)
2178       {
2179       p->setTrack(this);
2180       return _parts.add(p);
2181       }
2182 
2183 //---------------------------------------------------------
2184 //   findPart
2185 //---------------------------------------------------------
2186 
findPart(unsigned tick)2187 Part* Track::findPart(unsigned tick)
2188       {
2189       for (iPart i = _parts.begin(); i != _parts.end(); ++i) {
2190             Part* part = i->second;
2191             if (tick >= part->tick() && tick < (part->tick()+part->lenTick()))
2192                   return part;
2193             }
2194       return 0;
2195       }
2196 
selectEvents(bool select,unsigned long t0,unsigned long t1)2197 bool Track::selectEvents(bool select, unsigned long t0, unsigned long t1)
2198 {
2199   bool ret = false;
2200   PartList* pl = parts();
2201   for(iPart ip = pl->begin(); ip != pl->end(); ++ip)
2202   {
2203     if(ip->second->selectEvents(select, t0, t1))
2204       ret = true;
2205   }
2206   return ret;
2207 }
2208 
2209 //---------------------------------------------------------
2210 //   Track::writeProperties
2211 //---------------------------------------------------------
2212 
writeProperties(int level,Xml & xml) const2213 void Track::writeProperties(int level, Xml& xml) const
2214 {
2215       xml.strTag(level, "name", _name);
2216       if (!_comment.isEmpty())
2217             xml.strTag(level, "comment", _comment);
2218       xml.intTag(level, "record", _recordFlag);
2219       xml.intTag(level, "mute", mute());
2220       xml.intTag(level, "solo", solo());
2221       xml.intTag(level, "off", off());
2222       xml.intTag(level, "channels", _channels);
2223       xml.intTag(level, "height", _height);
2224       xml.intTag(level, "locked", _locked);
2225       xml.intTag(level, "recMonitor", _recMonitor);
2226       if (_selected)
2227       {
2228             xml.intTag(level, "selected", _selected);
2229             xml.intTag(level, "selectionOrder", _selectionOrder);
2230       }
2231       if (m_color.isValid())
2232           xml.strTag(level, "color", m_color.name());
2233 }
2234 
2235 //---------------------------------------------------------
2236 //   Track::readProperties
2237 //---------------------------------------------------------
2238 
readProperties(Xml & xml,const QString & tag)2239 bool Track::readProperties(Xml& xml, const QString& tag)
2240       {
2241       if (tag == "name")
2242             _name = xml.parse1();
2243       else if (tag == "comment")
2244             _comment = xml.parse1();
2245       else if (tag == "record") {
2246             bool recordFlag = xml.parseInt();
2247             if (type() == TrackType::AUDIO_OUTPUT)
2248                 recordFlag = false;
2249             setRecordFlag1(recordFlag);
2250             setRecordFlag2(recordFlag);
2251             }
2252       else if (tag == "mute")
2253             _mute = xml.parseInt();
2254       else if (tag == "solo")
2255             _solo = xml.parseInt();
2256       else if (tag == "off")
2257             _off = xml.parseInt();
2258       else if (tag == "height")
2259             _height = xml.parseInt();
2260       else if (tag == "channels")
2261       {
2262         setChannels(xml.parseInt());
2263       }
2264       else if (tag == "locked")
2265             _locked = xml.parseInt();
2266       else if (tag == "recMonitor")
2267             setRecMonitor(xml.parseInt());
2268       else if (tag == "selected")
2269             _selected = xml.parseInt();
2270       else if (tag == "selectionOrder")
2271             _selectionOrder = xml.parseInt();
2272       else if (tag == "color") {
2273           QString c = xml.parse1();
2274           if (QColor::isValidColor(c))
2275               m_color.setNamedColor(c);
2276       }
2277       else
2278             return true;
2279       return false;
2280       }
2281 
2282 //---------------------------------------------------------
2283 //   writeRouting
2284 //---------------------------------------------------------
2285 
writeRouting(int level,Xml & xml) const2286 void Track::writeRouting(int level, Xml& xml) const
2287 {
2288       QString s;
2289       if (type() == Track::AUDIO_INPUT)
2290       {
2291         const RouteList* rl = &_inRoutes;
2292         for (ciRoute r = rl->begin(); r != rl->end(); ++r)
2293         {
2294           if((r->type == Route::TRACK_ROUTE && r->track) || (r->type != Route::TRACK_ROUTE && !r->name().isEmpty()))
2295           {
2296             s = "Route";
2297             if(r->channel != -1)
2298               s += QString(" channel=\"%1\"").arg(r->channel);
2299 
2300             xml.tag(level++, s.toLatin1().constData());
2301 
2302             // New routing scheme.
2303             s = "source";
2304             if(r->type == Route::TRACK_ROUTE)
2305               s += QString(" track=\"%1\"/").arg(MusEGlobal::song->tracks()->index(r->track));
2306             else
2307               s += QString(" type=\"%1\" name=\"%2\"/").arg(r->type).arg(Xml::xmlString(r->name()));
2308             xml.tag(level, s.toLatin1().constData());
2309 
2310             xml.tag(level, "dest track=\"%d\"/", MusEGlobal::song->tracks()->index(this));
2311 
2312             xml.etag(level--, "Route");
2313           }
2314         }
2315       }
2316 
2317       const RouteList* rl = &_outRoutes;
2318       for (ciRoute r = rl->begin(); r != rl->end(); ++r)
2319       {
2320         // Ignore Audio Output to Audio Input routes.
2321         // They are taken care of by Audio Input in the section above.
2322         if((r->type == Route::TRACK_ROUTE && r->track && r->track->type() != Track::AUDIO_INPUT) ||
2323            (r->type != Route::TRACK_ROUTE && (!r->name().isEmpty() || r->midiPort != -1)))
2324         {
2325           s = "Route";
2326           if(r->channel != -1)
2327             s += QString(" channel=\"%1\"").arg(r->channel);
2328           if(r->channels != -1)
2329             s += QString(" channels=\"%1\"").arg(r->channels);
2330           if(r->remoteChannel != -1)
2331             s += QString(" remch=\"%1\"").arg(r->remoteChannel);
2332 
2333           xml.tag(level++, s.toLatin1().constData());
2334 
2335           // Allow for a regular mono or stereo track to feed a multi-channel synti.
2336           xml.tag(level, "source track=\"%d\"/", MusEGlobal::song->tracks()->index(this));
2337 
2338           s = "dest";
2339 
2340           if(r->type != Route::TRACK_ROUTE && r->type != Route::MIDI_PORT_ROUTE)
2341             s += QString(" type=\"%1\"").arg(r->type);
2342 
2343           if(r->type == Route::MIDI_PORT_ROUTE)
2344             s += QString(" mport=\"%1\"/").arg(r->midiPort);
2345           else if(r->type == Route::TRACK_ROUTE)
2346             s += QString(" track=\"%1\"/").arg(MusEGlobal::song->tracks()->index(r->track));
2347           else
2348             s += QString(" name=\"%1\"/").arg(Xml::xmlString(r->name()));
2349 
2350           xml.tag(level, s.toLatin1().constData());
2351 
2352           xml.etag(level--, "Route");
2353         }
2354       }
2355 }
2356 
getFirstControllerValue(int ctrl,int def)2357 int MidiTrack::getFirstControllerValue(int ctrl, int def)
2358 {
2359   int val=def;
2360   unsigned tick=-1; // maximum integer
2361 
2362   for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++)
2363   {
2364     Part* part=pit->second;
2365     if (part->tick() > tick) break; // ignore this and the rest. we won't find anything new.
2366     for (ciEvent eit=part->events().begin(); eit!=part->events().end(); eit++)
2367     {
2368       if (eit->first+part->tick() >= tick) break;
2369       if (eit->first > part->lenTick()) break; // ignore events past the end of the part
2370       // else if (eit->first+part->tick() < tick) and
2371       if (eit->second.type()==Controller && eit->second.dataA()==ctrl)
2372       {
2373         val = eit->second.dataB();
2374         tick = eit->first+part->tick();
2375         break;
2376       }
2377     }
2378   }
2379 
2380   return val;
2381 }
2382 
getControllerChangeAtTick(unsigned tick,int ctrl,int def)2383 int MidiTrack::getControllerChangeAtTick(unsigned tick, int ctrl, int def)
2384 {
2385   for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++)
2386   {
2387     Part* part=pit->second;
2388     if (part->tick() > tick) break; // ignore this and the rest. we'd find nothing any more
2389     if (part->endTick() < tick) continue; // ignore only this.
2390     for (ciEvent eit=part->events().begin(); eit!=part->events().end(); eit++)
2391     {
2392       if (eit->first+part->tick() > tick) break; // we won't find anything in this part from now on.
2393       if (eit->first > part->lenTick()) break; // ignore events past the end of the part
2394       if (eit->first+part->tick() < tick) continue; // ignore only this
2395 
2396       // else if (eit->first+part->tick() == tick) and
2397       if (eit->second.type()==Controller && eit->second.dataA()==ctrl)
2398         return eit->second.dataB();
2399     }
2400   }
2401 
2402   return def;
2403 }
2404 
2405 // returns the tick where this CC gets overridden by a new one
2406 // returns UINT_MAX for "never"
getControllerValueLifetime(unsigned tick,int ctrl)2407 unsigned MidiTrack::getControllerValueLifetime(unsigned tick, int ctrl)
2408 {
2409   unsigned result=UINT_MAX;
2410 
2411   for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++)
2412   {
2413     Part* part=pit->second;
2414     if (part->tick() > result) break; // ignore this and the rest. we won't find anything new.
2415     if (part->endTick() < tick) continue; // ignore only this part, we won't find anything there.
2416     for (ciEvent eit=part->events().begin(); eit!=part->events().end(); eit++)
2417     {
2418       if (eit->first+part->tick() >= result) break;
2419       if (eit->first > part->lenTick()) break; // ignore events past the end of the part
2420       // else if (eit->first+part->tick() < result) and
2421       if (eit->first+part->tick() > tick &&
2422           eit->second.type()==Controller && eit->second.dataA()==ctrl)
2423       {
2424         result = eit->first+part->tick();
2425         break;
2426       }
2427     }
2428   }
2429 
2430   return result;
2431 }
2432 
2433 //---------------------------------------------------------
2434 //   updateDrummap
2435 //   If audio is running (and not idle) this should only be called by the rt audio thread.
2436 //   Returns true if map was changed.
2437 //---------------------------------------------------------
2438 
updateDrummap(int doSignal)2439 bool MidiTrack::updateDrummap(int doSignal)
2440 {
2441   if(type() != Track::DRUM || _outPort < 0 || _outPort >= MusECore::MIDI_PORTS)
2442     return false;
2443   MidiPort* mp = &MusEGlobal::midiPorts[_outPort];
2444   const int patch = mp->hwCtrlState(_outChannel, CTRL_PROGRAM);
2445   bool map_changed;
2446   DrumMap ndm;
2447 
2448   map_changed = false;
2449   for(int i = 0; i < 128; i++)
2450   {
2451     getMapItem(patch, i, ndm, WorkingDrumMapEntry::AllOverrides);
2452     DrumMap& tdm = _drummap[i];
2453     if(ndm != tdm)
2454     {
2455       tdm = ndm;
2456       map_changed = true;
2457     }
2458     // Be sure to update the drum input note map. Probably wise (and easy) to do it always.
2459     drum_in_map[(int)tdm.enote] = i;
2460   }
2461 
2462   // Ensure there are NO duplicate enote fields. Returns true if somethng was changed.
2463   if(normalizeDrumMap(patch))
2464     map_changed = true;
2465 
2466   if(map_changed)
2467   {
2468     // Update the drum in (enote) map.
2469     update_drum_in_map();
2470 
2471     // TODO Move this to gui thread where it's safe to do so - this is only gui stuff.
2472     if(drummap_ordering_tied_to_patch())
2473       // TODO This is not exactly rt friendly since it may de/allocate.
2474       init_drum_ordering();
2475   }
2476 
2477   // TODO Do this outside since we may be called as part of multiple tracks operations.
2478   if(map_changed && doSignal)
2479   {
2480     // It is possible we are being called from gui thread already, in audio idle mode.
2481     // Will this still work, and not conflict with audio sending the same message?
2482     // Are we are not supposed to write to an fd from different threads?
2483     if(!MusEGlobal::audio || MusEGlobal::audio->isIdle())
2484       // Directly emit SC_DRUMMAP song changed signal.
2485       MusEGlobal::song->update(SC_DRUMMAP);
2486     else
2487       // Tell the gui to emit SC_DRUMMAP song changed signal.
2488       MusEGlobal::audio->sendMsgToGui('D'); // Drum map changed.
2489 
2490     return true;
2491   }
2492 
2493   return map_changed;
2494 }
2495 
set_drummap_ordering_tied_to_patch(bool val)2496 void MidiTrack::set_drummap_ordering_tied_to_patch(bool val)
2497 {
2498   _drummap_ordering_tied_to_patch=val;
2499   if (val) init_drum_ordering();
2500 }
2501 
modifyWorkingDrumMap(WorkingDrumMapList & list,bool isReset,bool includeDefault,bool isInstrumentMod,bool doWholeMap)2502 void MidiTrack::modifyWorkingDrumMap(WorkingDrumMapList& list, bool isReset, bool includeDefault, bool
2503 #ifdef _USE_INSTRUMENT_OVERRIDES_
2504 isInstrumentMod
2505 #endif
2506 , bool doWholeMap)
2507 {
2508   //if(!isDrumTrack())
2509   if(type() != DRUM)
2510     return;
2511   const int port = outPort();
2512   if(port < 0 || port >= MusECore::MIDI_PORTS)
2513     return;
2514   MidiPort* mp = &MusEGlobal::midiPorts[port];
2515   const int chan = outChannel();
2516   const int patch = mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM);
2517 
2518   int index;
2519   int idx_end;
2520   int other_index;
2521   int fields;
2522   int cur_enote;
2523   int new_enote;
2524 //   DrumMap orig_dm;
2525   DrumMap other_dm;
2526   WorkingDrumMapEntry other_wdme;
2527 #ifdef _USE_INSTRUMENT_OVERRIDES_
2528   MidiInstrument* instr = mp->instrument();
2529 #endif
2530   for(iWorkingDrumMapPatch_t iwdp = list.begin(); iwdp != list.end(); ++iwdp)
2531   {
2532     index = doWholeMap ? 0 : iwdp->first;
2533     idx_end = doWholeMap ? 128 : index + 1;
2534     for( ; index < idx_end; ++index)
2535     {
2536       DrumMap& dm = _drummap[index];
2537       WorkingDrumMapEntry& wdme = iwdp->second;
2538 
2539       fields = wdme._fields;
2540 
2541 #ifdef _USE_INSTRUMENT_OVERRIDES_
2542       if(isInstrumentMod)
2543       {
2544         if(instr)
2545           instr->setWorkingDrumMapItem(patch, index, wdme, isReset);
2546       }
2547       else
2548 #endif
2549 
2550       // FIXME Possible non realtime-friendly allocation. There will be adding new list and copying of 'name' QString here.
2551       if(isReset)
2552       {
2553 //         cur_enote = dm.enote;
2554         _workingDrumMapPatchList->remove(patch, index, wdme._fields, includeDefault);
2555         getMapItem(patch, index, dm, WorkingDrumMapEntry::AllOverrides);
2556 // REMOVE Tim. newdrums. Removed.
2557 //         new_enote = dm.enote;
2558 //         other_index = drum_in_map[new_enote];
2559 //
2560 //         if(fields & WorkingDrumMapEntry::ENoteField && other_index != index)
2561 //         {
2562 //           // In doWholeMap mode, a previous index iteration may have already cleared the other ENote field.
2563 //           // So do this only if there is a track override on the ENote field.
2564 //           if(//doWholeMap &&
2565 //             (isWorkingMapItem(other_index, WorkingDrumMapEntry::ENoteField, patch) &
2566 //               (WorkingDrumMapEntry::TrackOverride | WorkingDrumMapEntry::TrackDefaultOverride)))
2567 //           {
2568 //             // Here we need to see the original map item value /before/ any overrides, so that we can
2569 //             //  tell whether this other_index brute-force 'reset' value is still technically an
2570 //             //  override, and either remove or add (modify) the list appropriately.
2571 //             getMapItem(patch, other_index, other_dm, WorkingDrumMapEntry::NoOverride);
2572 //             if(other_dm.enote == cur_enote)
2573 //             {
2574 //               // The values are equal. This is technically no longer a track override and we may remove it.
2575 //               _workingDrumMapPatchList->remove(patch, other_index, WorkingDrumMapEntry::ENoteField, includeDefault);
2576 //             }
2577 //             else
2578 //             {
2579 //               // The values are not equal. This is technically still a track override, so add (modify) it.
2580 //               other_dm.enote = cur_enote;
2581 //               WorkingDrumMapEntry other_wdme(other_dm, WorkingDrumMapEntry::ENoteField);
2582 //               _workingDrumMapPatchList->add(patch, other_index, other_wdme);
2583 //             }
2584 //
2585 //             _drummap[other_index].enote = cur_enote;
2586 //             drum_in_map[cur_enote] = other_index;
2587 //           }
2588 //           drum_in_map[new_enote] = index;
2589 //         }
2590       }
2591       else
2592       {
2593         cur_enote = dm.enote;
2594         if(includeDefault)
2595         {
2596           // We are 'promoting' the fields to default patch list...
2597           other_wdme._fields = fields;
2598           other_wdme._mapItem = dm;
2599           // Add the item to the default patch drum list.
2600           _workingDrumMapPatchList->add(CTRL_PROGRAM_VAL_DONT_CARE, index, other_wdme);
2601           // Now remove the item from the non-default patch drum list.
2602           if(patch != CTRL_PROGRAM_VAL_DONT_CARE)
2603             _workingDrumMapPatchList->remove(patch, index, WorkingDrumMapEntry::AllFields, false); // Do not include defaults.
2604         }
2605         else
2606         {
2607           if(doWholeMap)
2608           {
2609             if(fields == WorkingDrumMapEntry::AllFields)
2610             {
2611               other_wdme._fields = fields;
2612               other_wdme._mapItem = dm;
2613               _workingDrumMapPatchList->add(patch, index, other_wdme);
2614             }
2615             else
2616               _workingDrumMapPatchList->add(patch, index, wdme);
2617           }
2618           else
2619           {
2620             _workingDrumMapPatchList->add(patch, index, wdme);
2621             getMapItem(patch, index, dm, WorkingDrumMapEntry::AllOverrides);
2622           }
2623         }
2624 
2625         if(!doWholeMap && (fields & WorkingDrumMapEntry::ENoteField))
2626         {
2627           new_enote = dm.enote;
2628           other_index = drum_in_map[new_enote];
2629           // If there is already another track override on the other index we must change it.
2630           if(isWorkingMapItem(other_index, WorkingDrumMapEntry::ENoteField, patch) != WorkingDrumMapEntry::NoOverride)
2631           {
2632             other_dm.enote = cur_enote;
2633             //WorkingDrumMapEntry other_wdme(other_dm, WorkingDrumMapEntry::ENoteField);
2634             other_wdme._mapItem = other_dm;
2635             other_wdme._fields = WorkingDrumMapEntry::ENoteField;
2636             if(includeDefault)
2637             {
2638               _workingDrumMapPatchList->add(CTRL_PROGRAM_VAL_DONT_CARE, other_index, other_wdme);
2639               // Now remove the item from the non-default patch drum list.
2640               if(patch != CTRL_PROGRAM_VAL_DONT_CARE)
2641                 _workingDrumMapPatchList->remove(patch, other_index, WorkingDrumMapEntry::ENoteField, false); // Do not include defaults.
2642             }
2643             else
2644               _workingDrumMapPatchList->add(patch, other_index, other_wdme);
2645 
2646             //_drummap[other_index].enote = cur_enote;
2647             //drum_in_map[cur_enote] = other_index;
2648             //drum_in_map[new_enote] = index;
2649           }
2650         }
2651       }
2652     }
2653   }
2654 
2655   // Ensure there are NO duplicate enote fields.
2656   //if(normalizeDrumMap(patch))
2657     // If anything changed, update the drum in map.
2658   //  update_drum_in_map();
2659   updateDrummap(false); // No signal.
2660 }
2661 
setWorkingDrumMap(WorkingDrumMapPatchList * list,bool isInstrumentMod)2662 void MidiTrack::setWorkingDrumMap(WorkingDrumMapPatchList* list, bool
2663 #ifdef _USE_INSTRUMENT_OVERRIDES_
2664 isInstrumentMod
2665 #endif
2666 )
2667 {
2668   //if(!isDrumTrack())
2669   if(type() != DRUM)
2670     return;
2671 
2672 #ifdef _USE_INSTRUMENT_OVERRIDES_
2673   if(isInstrumentMod)
2674   {
2675 // TODO
2676 //     const int port = outPort();
2677 //     if(port < 0 || port >= MIDI_PORTS)
2678 //       return;
2679 //     MidiPort* mp = &MusEGlobal::midiPorts[port];
2680 //     MidiInstrument* instr = mp->instrument();
2681 //     instr->setWorkingDrumMap();
2682     return;
2683   }
2684 #endif
2685 
2686   _workingDrumMapPatchList = list;
2687 
2688   // We must ensure that there are NO duplicate enote fields,
2689   //  since the instrument map may have changed by now.
2690   //normalizeWorkingDrumMapPatchList();
2691 
2692   updateDrummap(false); // No signal.
2693   update_drum_in_map();
2694 }
2695 
getMapItemAt(int tick,int index,DrumMap & dest_map,int overrideType) const2696 void MidiTrack::getMapItemAt(int tick, int index, DrumMap& dest_map, int overrideType) const
2697 {
2698   //if(!isDrumTrack())
2699   if(type() != DRUM)
2700   {
2701     dest_map = iNewDrumMap[index];
2702     return;
2703   }
2704   const int port = outPort();
2705   if(port < 0 || port >= MusECore::MIDI_PORTS)
2706   {
2707     dest_map = iNewDrumMap[index];
2708     return;
2709   }
2710   const MidiPort* mp = &MusEGlobal::midiPorts[port];
2711   const int track_chan = outChannel();
2712 
2713   // Get the patch number at tick, contributed by any part,
2714   //  ignoring values outside of their parts. We must include
2715   //  muted or off parts or tracks in the search since this is an
2716   //  operation that must not be affected by mute or off.
2717   const int track_patch = mp->getVisibleCtrl(track_chan, tick, MusECore::CTRL_PROGRAM, true, true, true);
2718 
2719   // Get the instrument's map item, and include any requested overrides.
2720   getMapItem(track_patch, index, dest_map, overrideType);
2721 }
2722 
getMapItem(int patch,int index,DrumMap & dest_map,int overrideType) const2723 void MidiTrack::getMapItem(int patch, int index, DrumMap& dest_map, int overrideType) const
2724 {
2725   //if(!isDrumTrack())
2726   if(type() != DRUM)
2727   {
2728     dest_map = iNewDrumMap[index];
2729     return;
2730   }
2731   const int port = outPort();
2732   if(port < 0 || port >= MusECore::MIDI_PORTS)
2733   {
2734     dest_map = iNewDrumMap[index];
2735     return;
2736   }
2737   const MidiPort* mp = &MusEGlobal::midiPorts[port];
2738   const MidiInstrument* midi_instr = mp->instrument();
2739   if(!midi_instr)
2740   {
2741     dest_map = iNewDrumMap[index];
2742     return;
2743   }
2744 
2745   // Get the instrument's map item, and include any requested overrides.
2746   const int channel = outChannel();
2747   midi_instr->getMapItem(channel, patch, index, dest_map, overrideType);
2748 
2749   // Did we request to include any track default patch overrides?
2750   if(overrideType & WorkingDrumMapEntry::TrackDefaultOverride)
2751   {
2752     // Get any track default patch overrides.
2753     const WorkingDrumMapEntry* def_wdm = _workingDrumMapPatchList->find(CTRL_PROGRAM_VAL_DONT_CARE, index, false); // No default.
2754     if(def_wdm)
2755     {
2756       if(def_wdm->_fields & WorkingDrumMapEntry::NameField)
2757         dest_map.name = def_wdm->_mapItem.name;
2758 
2759       if(def_wdm->_fields & WorkingDrumMapEntry::VolField)
2760         dest_map.vol = def_wdm->_mapItem.vol;
2761 
2762       if(def_wdm->_fields & WorkingDrumMapEntry::QuantField)
2763         dest_map.quant = def_wdm->_mapItem.quant;
2764 
2765       if(def_wdm->_fields & WorkingDrumMapEntry::LenField)
2766         dest_map.len = def_wdm->_mapItem.len;
2767 
2768       if(def_wdm->_fields & WorkingDrumMapEntry::ChanField)
2769         dest_map.channel = def_wdm->_mapItem.channel;
2770 
2771       if(def_wdm->_fields & WorkingDrumMapEntry::PortField)
2772         dest_map.port = def_wdm->_mapItem.port;
2773 
2774       if(def_wdm->_fields & WorkingDrumMapEntry::Lv1Field)
2775         dest_map.lv1 = def_wdm->_mapItem.lv1;
2776 
2777       if(def_wdm->_fields & WorkingDrumMapEntry::Lv2Field)
2778         dest_map.lv2 = def_wdm->_mapItem.lv2;
2779 
2780       if(def_wdm->_fields & WorkingDrumMapEntry::Lv3Field)
2781         dest_map.lv3 = def_wdm->_mapItem.lv3;
2782 
2783       if(def_wdm->_fields & WorkingDrumMapEntry::Lv4Field)
2784         dest_map.lv4 = def_wdm->_mapItem.lv4;
2785 
2786       if(def_wdm->_fields & WorkingDrumMapEntry::ENoteField)
2787         dest_map.enote = def_wdm->_mapItem.enote;
2788 
2789       if(def_wdm->_fields & WorkingDrumMapEntry::ANoteField)
2790         dest_map.anote = def_wdm->_mapItem.anote;
2791 
2792       if(def_wdm->_fields & WorkingDrumMapEntry::MuteField)
2793         dest_map.mute = def_wdm->_mapItem.mute;
2794 
2795       if(def_wdm->_fields & WorkingDrumMapEntry::HideField)
2796         dest_map.hide = def_wdm->_mapItem.hide;
2797     }
2798   }
2799 
2800   // Did we request to include any track overrides?
2801   if(!(overrideType & WorkingDrumMapEntry::TrackOverride))
2802     return;
2803 
2804   // Get any track overrides.
2805   const WorkingDrumMapEntry* wdm = _workingDrumMapPatchList->find(patch, index, false); // No default.
2806   if(!wdm)
2807     return;
2808 
2809   if(wdm->_fields & WorkingDrumMapEntry::NameField)
2810     dest_map.name = wdm->_mapItem.name;
2811 
2812   if(wdm->_fields & WorkingDrumMapEntry::VolField)
2813     dest_map.vol = wdm->_mapItem.vol;
2814 
2815   if(wdm->_fields & WorkingDrumMapEntry::QuantField)
2816     dest_map.quant = wdm->_mapItem.quant;
2817 
2818   if(wdm->_fields & WorkingDrumMapEntry::LenField)
2819     dest_map.len = wdm->_mapItem.len;
2820 
2821   if(wdm->_fields & WorkingDrumMapEntry::ChanField)
2822     dest_map.channel = wdm->_mapItem.channel;
2823 
2824   if(wdm->_fields & WorkingDrumMapEntry::PortField)
2825     dest_map.port = wdm->_mapItem.port;
2826 
2827   if(wdm->_fields & WorkingDrumMapEntry::Lv1Field)
2828     dest_map.lv1 = wdm->_mapItem.lv1;
2829 
2830   if(wdm->_fields & WorkingDrumMapEntry::Lv2Field)
2831     dest_map.lv2 = wdm->_mapItem.lv2;
2832 
2833   if(wdm->_fields & WorkingDrumMapEntry::Lv3Field)
2834     dest_map.lv3 = wdm->_mapItem.lv3;
2835 
2836   if(wdm->_fields & WorkingDrumMapEntry::Lv4Field)
2837     dest_map.lv4 = wdm->_mapItem.lv4;
2838 
2839   if(wdm->_fields & WorkingDrumMapEntry::ENoteField)
2840     dest_map.enote = wdm->_mapItem.enote;
2841 
2842   if(wdm->_fields & WorkingDrumMapEntry::ANoteField)
2843     dest_map.anote = wdm->_mapItem.anote;
2844 
2845   if(wdm->_fields & WorkingDrumMapEntry::MuteField)
2846     dest_map.mute = wdm->_mapItem.mute;
2847 
2848   if(wdm->_fields & WorkingDrumMapEntry::HideField)
2849     dest_map.hide = wdm->_mapItem.hide;
2850 }
2851 
isWorkingMapItem(int index,int fields,int patch) const2852 int MidiTrack::isWorkingMapItem(int index, int fields, int patch) const
2853 {
2854   int ret = WorkingDrumMapEntry::NoOverride;
2855   if(type() != DRUM)
2856     return ret;
2857 
2858   // Is there an instrument override for this drum map item?
2859   const int port = outPort();
2860   if(port >= 0 && port < MusECore::MIDI_PORTS)
2861   {
2862     const MidiPort* mp = &MusEGlobal::midiPorts[port];
2863     // Grab the patch number while we are here, if we asked for it.
2864     if(patch == -1)
2865     {
2866       const int chan = outChannel();
2867       patch = mp->hwCtrlState(chan, CTRL_PROGRAM);
2868     }
2869 #ifdef _USE_INSTRUMENT_OVERRIDES_
2870     const MidiInstrument* midi_instr = mp->instrument();
2871     if(midi_instr)
2872       ret |= midi_instr->isWorkingMapItem(patch, index, fields);
2873 #endif
2874   }
2875 
2876   // Is there a local track default patch override for this drum map item?
2877   const WorkingDrumMapEntry* def_wdm = _workingDrumMapPatchList->find(CTRL_PROGRAM_VAL_DONT_CARE, index, false); // No default.
2878   if(def_wdm && (def_wdm->_fields & fields))
2879     ret |= WorkingDrumMapEntry::TrackDefaultOverride;
2880 
2881   if(patch != -1)
2882   {
2883     // Is there a local track override for this drum map item?
2884     const WorkingDrumMapEntry* wdm = _workingDrumMapPatchList->find(patch, index, false); // No default.
2885     if(wdm && (wdm->_fields & fields))
2886       ret |= WorkingDrumMapEntry::TrackOverride;
2887   }
2888 
2889   return ret;
2890 }
2891 
normalizeDrumMap(int patch)2892 bool MidiTrack::normalizeDrumMap(int patch)
2893 {
2894   if(type() != DRUM)
2895     return false;
2896   //WorkingDrumMapList* wdml = _workingDrumMapPatchList->find(patch, true);
2897   WorkingDrumMapList* wdml = _workingDrumMapPatchList->find(patch, false);
2898   WorkingDrumMapList* def_wdml = 0;
2899   if(patch != CTRL_PROGRAM_VAL_DONT_CARE)
2900     def_wdml = _workingDrumMapPatchList->find(CTRL_PROGRAM_VAL_DONT_CARE, false);
2901 
2902   int index = 0;
2903   DrumMap dm;
2904   char enote;
2905   bool changed = false;
2906 
2907   bool used_index[128];
2908   int used_enotes[128];
2909   for(int i = 0; i < 128; ++i)
2910   {
2911     used_index[i] = false;
2912     used_enotes[i] = 0;
2913   }
2914   char unused_enotes[128];
2915   int unused_enotes_sz = 0;
2916   char unused_index[128];
2917   int unused_index_sz = 0;
2918   int unused_enotes_cnt = 0;
2919 
2920   // Find all the used enote fields and their indexes in the working list.
2921   if(wdml)
2922   {
2923     for(iWorkingDrumMapPatch_t iwdml = wdml->begin(); iwdml != wdml->end(); ++iwdml)
2924     {
2925       WorkingDrumMapEntry& wdme = iwdml->second;
2926       if(wdme._fields & WorkingDrumMapEntry::ENoteField)
2927       {
2928         used_index[iwdml->first] = true;
2929         //++used_enotes[(unsigned char)wdme._mapItem.enote];
2930       }
2931     }
2932   }
2933 
2934   // Add all the used enote fields and their indexes in the default patch working list.
2935   if(def_wdml)
2936   {
2937     for(iWorkingDrumMapPatch_t iwdml = def_wdml->begin(); iwdml != def_wdml->end(); ++iwdml)
2938     {
2939       WorkingDrumMapEntry& wdme = iwdml->second;
2940       if(wdme._fields & WorkingDrumMapEntry::ENoteField)
2941       {
2942         used_index[iwdml->first] = true;
2943         //++used_enotes[(unsigned char)wdme._mapItem.enote];
2944       }
2945     }
2946   }
2947 
2948   // Find all the used enote fields and their indexes in the working list.
2949   if(wdml)
2950   {
2951     for(iWorkingDrumMapPatch_t iwdml = wdml->begin(); iwdml != wdml->end(); ++iwdml)
2952     {
2953       WorkingDrumMapEntry& wdme = iwdml->second;
2954       if(wdme._fields & WorkingDrumMapEntry::ENoteField)
2955       {
2956         //used_index[iwdml->first] = true;
2957         ++used_enotes[(unsigned char)wdme._mapItem.enote];
2958       }
2959     }
2960   }
2961 
2962   // Find all the unused indexes and enotes so far in the working list.
2963   unused_index_sz = 0;
2964   unused_enotes_sz = 0;
2965   for(int i = 0; i < 128; ++i)
2966   {
2967     if(!used_index[i])
2968       unused_index[unused_index_sz++] = i;
2969     if(used_enotes[i] == 0)
2970       unused_enotes[unused_enotes_sz++] = i;
2971   }
2972 
2973   // Ensure there are NO duplicate enotes in the existing working list items so far.
2974   unused_enotes_cnt = 0;
2975   if(wdml)
2976   {
2977     for(iWorkingDrumMapPatch_t iwdml = wdml->begin(); iwdml != wdml->end(); ++iwdml)
2978     {
2979       WorkingDrumMapEntry& wdme = iwdml->second;
2980       if(wdme._fields & WorkingDrumMapEntry::ENoteField)
2981       {
2982         // More than 1 (this) usage?
2983         if(used_enotes[(unsigned char)wdme._mapItem.enote] > 1)
2984         {
2985           fprintf(stderr, "MidiTrack::normalizeWorkingDrumMap: Warning: Duplicate enote:%d found. Overriding it.\n",
2986                   wdme._mapItem.enote);
2987           if(unused_enotes_cnt >= unused_enotes_sz)
2988           {
2989             fprintf(stderr, "MidiTrack::normalizeWorkingDrumMap: Error: unused_enotes_cnt >= unused_enotes_sz:%d\n",
2990                     unused_enotes_sz);
2991             break;
2992           }
2993           --used_enotes[(unsigned char)wdme._mapItem.enote];
2994           //wdme._mapItem.enote = unused_enotes[unused_enotes_cnt++];
2995           // Get the instrument item.
2996           index = iwdml->first;
2997           // Modify the enote field.
2998           enote = unused_enotes[unused_enotes_cnt++];
2999           _drummap[index].enote = enote;
3000           ++used_enotes[(unsigned char)enote];
3001           changed = true;
3002         }
3003       }
3004     }
3005   }
3006 
3007   // Find all the used enote fields and their indexes in the default patch working list.
3008   if(def_wdml)
3009   {
3010     for(iWorkingDrumMapPatch_t iwdml = def_wdml->begin(); iwdml != def_wdml->end(); ++iwdml)
3011     {
3012       WorkingDrumMapEntry& wdme = iwdml->second;
3013       if(wdme._fields & WorkingDrumMapEntry::ENoteField)
3014       {
3015         //used_index[iwdml->first] = true;
3016         // If there is already a non-default patch enote override for this index,
3017         //  do not increment used_notes, the non-default one takes priority over this default one.
3018         if(wdml)
3019         {
3020           ciWorkingDrumMapPatch_t def_iwdml = wdml->find(iwdml->first);
3021           if(def_iwdml != wdml->end())
3022           {
3023             const WorkingDrumMapEntry& def_wdme = def_iwdml->second;
3024             if(def_wdme._fields & WorkingDrumMapEntry::ENoteField)
3025               continue;
3026           }
3027         }
3028         ++used_enotes[(unsigned char)wdme._mapItem.enote];
3029       }
3030     }
3031   }
3032 
3033   // Find all the unused indexes and enotes so far in the working list.
3034   unused_enotes_sz = 0;
3035   for(int i = 0; i < 128; ++i)
3036   {
3037     if(used_enotes[i] == 0)
3038       unused_enotes[unused_enotes_sz++] = i;
3039   }
3040 
3041   // Ensure there are NO duplicate enotes in the existing default patch working list items so far.
3042   unused_enotes_cnt = 0;
3043   if(def_wdml)
3044   {
3045     for(iWorkingDrumMapPatch_t iwdml = def_wdml->begin(); iwdml != def_wdml->end(); ++iwdml)
3046     {
3047       WorkingDrumMapEntry& wdme = iwdml->second;
3048       if(wdme._fields & WorkingDrumMapEntry::ENoteField)
3049       {
3050         // If there is already a non-default patch enote override for this index,
3051         //  skip this one, the non-default one takes priority over this default one.
3052         if(wdml)
3053         {
3054           ciWorkingDrumMapPatch_t def_iwdml = wdml->find(iwdml->first);
3055           if(def_iwdml != wdml->end())
3056           {
3057             const WorkingDrumMapEntry& def_wdme = def_iwdml->second;
3058             if(def_wdme._fields & WorkingDrumMapEntry::ENoteField)
3059               continue;
3060           }
3061         }
3062 
3063         // More than 1 (this) usage?
3064         if(used_enotes[(unsigned char)wdme._mapItem.enote] > 1)
3065         {
3066           fprintf(stderr, "MidiTrack::normalizeWorkingDrumMap: Warning: Duplicate default enote:%d found. Overriding it.\n",
3067                   wdme._mapItem.enote);
3068           if(unused_enotes_cnt >= unused_enotes_sz)
3069           {
3070             fprintf(stderr, "MidiTrack::normalizeWorkingDrumMap: Error: Default unused_enotes_cnt >= unused_enotes_sz:%d\n",
3071                     unused_enotes_sz);
3072             break;
3073           }
3074           --used_enotes[(unsigned char)wdme._mapItem.enote];
3075           //wdme._mapItem.enote = unused_enotes[unused_enotes_cnt++];
3076           // Get the instrument item.
3077           index = iwdml->first;
3078           // Modify the enote field.
3079           enote = unused_enotes[unused_enotes_cnt++];
3080           _drummap[index].enote = enote;
3081           ++used_enotes[(unsigned char)enote];
3082           changed = true;
3083         }
3084       }
3085     }
3086   }
3087 
3088   // Add all used enotes in the unused enote indexes (the instrument fields).
3089   for(int i = 0; i < unused_index_sz; ++i)
3090     ++used_enotes[(unsigned char)_drummap[(unsigned char)unused_index[i]].enote];
3091 
3092   // Find all the unused enotes.
3093   unused_enotes_sz = 0;
3094   for(int i = 0; i < 128; ++i)
3095   {
3096     if(used_enotes[i] == 0)
3097       unused_enotes[unused_enotes_sz++] = i;
3098   }
3099 
3100   // Ensure there are NO duplicate enotes in the unused enote map fields (the instrument fields).
3101   unused_enotes_cnt = 0;
3102   for(int i = 0; i < unused_index_sz; ++i)
3103   {
3104     // Get the instrument item.
3105     index = unused_index[i];
3106     enote = _drummap[index].enote;
3107 
3108     // More than 1 (this) usage?
3109     if(used_enotes[(unsigned char)enote] > 1)
3110     {
3111       if(unused_enotes_cnt >= unused_enotes_sz)
3112       {
3113         fprintf(stderr, "MidiTrack::normalizeWorkingDrumMap: Error filling background items: unused_enotes_cnt >= unused_enotes_sz:%d\n",
3114                 unused_enotes_sz);
3115         break;
3116       }
3117 
3118       --used_enotes[(unsigned char)enote];
3119 
3120       // Modify the enote field.
3121       _drummap[index].enote = unused_enotes[unused_enotes_cnt++];
3122       ++used_enotes[(unsigned char)_drummap[index].enote];
3123       changed = true;
3124     }
3125   }
3126 
3127   return changed;
3128 }
3129 
normalizeDrumMap()3130 bool MidiTrack::normalizeDrumMap()
3131 {
3132   if(type() != DRUM)
3133     return false;
3134   const int port = outPort();
3135   if(port < 0 || port >= MusECore::MIDI_PORTS)
3136     return false;
3137   const int chan = outChannel();
3138   const int patch = MusEGlobal::midiPorts[port].hwCtrlState(chan, MusECore::CTRL_PROGRAM);
3139   return normalizeDrumMap(patch);
3140 }
3141 
3142 } // namespace MusECore
3143