1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: seqmsg.cpp,v 1.32.2.17 2009/12/20 05:00:35 terminator356 Exp $
5 //
6 //  (C) Copyright 2001 Werner Schweer (ws@seh.de)
7 //
8 //  This program is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU General Public License
10 //  as published by the Free Software Foundation; version 2 of
11 //  the License, or (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 //=========================================================
23 
24 #include <stdio.h>
25 
26 #include "song.h"
27 #include "midiseq.h"
28 #include "midiport.h"
29 #include "minstrument.h"
30 #include "app.h"
31 #include "amixer.h"
32 #include "tempo.h"
33 ///#include "sig.h"
34 #include "sig.h"
35 #include "audio.h"
36 #include "mididev.h"
37 #include "audiodev.h"
38 #include "alsamidi.h"
39 #include "audio.h"
40 #include "arranger.h"
41 #include "plugin.h"
42 #include "driver/jackmidi.h"
43 #include "midi_warn_init_pending_impl.h"
44 #include "gconfig.h"
45 #include "operations.h"
46 #include "ctrl.h"
47 #include "globals.h"
48 #include "metronome_class.h"
49 #include "undo.h"
50 
51 namespace MusECore {
52 
53 //---------------------------------------------------------
54 //   sendMsg
55 //---------------------------------------------------------
56 
57 // this function blocks until the request has been processed
sendMsg(AudioMsg * m)58 void Audio::sendMsg(AudioMsg* m)
59       {
60       static int sno = 0;
61 
62       if (_running) {
63             m->serialNo = sno++;
64             //DEBUG:
65             msg = m;
66             // wait for next audio "process" call to finish operation
67             int no = -1;
68             int rv = read(fromThreadFdr, &no, sizeof(int));
69             if (rv != sizeof(int))
70                   perror("Audio: read pipe failed");
71             else if (no != (sno-1)) {
72                   fprintf(stderr, "audio: bad serial number, read %d expected %d\n",
73                      no, sno-1);
74                   }
75             }
76       else {
77             // if audio is not running (during initialization)
78             // process commands immediately
79             processMsg(m);
80             }
81       }
82 
83 //---------------------------------------------------------
84 //   sendMessage
85 //    send request from gui to sequencer
86 //    wait until request is processed
87 //---------------------------------------------------------
88 
sendMessage(AudioMsg * m,bool doUndo)89 bool Audio::sendMessage(AudioMsg* m, bool doUndo)
90       {
91       if (doUndo)
92            MusEGlobal::song->startUndo();
93       sendMsg(m);
94       if (doUndo)
95             MusEGlobal::song->endUndo(0);
96       return false;
97       }
98 
99 //---------------------------------------------------------
100 //   msgRemoveRoute
101 //---------------------------------------------------------
102 
msgRemoveRoute(Route src,Route dst)103 void Audio::msgRemoveRoute(Route src, Route dst)
104 {
105   //fprintf(stderr, "Audio::msgRemoveRoute:\n");
106   msgRemoveRoute1(src, dst);
107   MusEGlobal::song->connectJackRoutes(src, dst, true);
108 }
109 
110 //---------------------------------------------------------
111 //   msgRemoveRoute1
112 //---------------------------------------------------------
113 
msgRemoveRoute1(Route src,Route dst)114 void Audio::msgRemoveRoute1(Route src, Route dst)
115       {
116       AudioMsg msg;
117       msg.id     = AUDIO_ROUTEREMOVE;
118       msg.sroute = src;
119       msg.droute = dst;
120       sendMsg(&msg);
121       }
122 
123 //---------------------------------------------------------
124 //   msgAddRoute
125 //---------------------------------------------------------
126 
msgAddRoute(Route src,Route dst)127 void Audio::msgAddRoute(Route src, Route dst)
128 {
129   //fprintf(stderr, "Audio::msgAddRoute:\n");
130   msgAddRoute1(src, dst);
131   MusEGlobal::song->connectJackRoutes(src, dst);
132 }
133 
134 //---------------------------------------------------------
135 //   msgAddRoute1
136 //---------------------------------------------------------
137 
msgAddRoute1(Route src,Route dst)138 void Audio::msgAddRoute1(Route src, Route dst)
139       {
140       AudioMsg msg;
141       msg.id = AUDIO_ROUTEADD;
142       msg.sroute = src;
143       msg.droute = dst;
144       sendMsg(&msg);
145       }
146 
147 //---------------------------------------------------------
148 //   msgAddPlugin
149 //---------------------------------------------------------
150 
msgAddPlugin(AudioTrack * node,int idx,PluginI * plugin)151 void Audio::msgAddPlugin(AudioTrack* node, int idx, PluginI* plugin)
152       {
153       AudioMsg msg;
154       msg.id     = AUDIO_ADDPLUGIN;
155       msg.snode  = node;
156       msg.ival   = idx;
157       msg.plugin = plugin;
158       sendMsg(&msg);
159       }
160 
161 //---------------------------------------------------------
162 //   msgSetPrefader
163 //---------------------------------------------------------
164 
msgSetPrefader(AudioTrack * node,int val)165 void Audio::msgSetPrefader(AudioTrack* node, int val)
166       {
167       AudioMsg msg;
168       msg.id    = AUDIO_SET_PREFADER;
169       msg.snode = node;
170       msg.ival  = val;
171       sendMsg(&msg);
172       }
173 
174 //---------------------------------------------------------
175 //   msgSetChannels
176 //---------------------------------------------------------
177 
msgSetChannels(AudioTrack * node,int n)178 void Audio::msgSetChannels(AudioTrack* node, int n)
179       {
180       if (n == node->channels())
181             return;
182       QString name = node->name();
183       int mc       = std::max(n, node->channels());
184 
185       if (!name.isEmpty())
186       {
187             if (node->type() == Track::AUDIO_INPUT)
188             {
189               if (!MusEGlobal::checkAudioDevice()) return;
190               AudioInput* ai = (AudioInput*)node;
191               for (int i = 0; i < mc; ++i)
192               {
193                 if (i < n && ai->jackPort(i) == 0)
194                 {
195                   ai->registerPorts(i);
196                 }
197                 else if ((i >= n) && ai->jackPort(i))
198                 {
199                   RouteList* ir = node->inRoutes();
200                   for (ciRoute ii = ir->begin(); ii != ir->end(); ++ii)
201                   {
202                     Route r = *ii;
203                     if ((r.type == Route::JACK_ROUTE) && (r.channel == i))
204                     {
205                       msgRemoveRoute(r, Route(node,i));
206                       break;
207                     }
208                   }
209                   MusEGlobal::audioDevice->unregisterPort(ai->jackPort(i));
210                   ai->setJackPort(i, 0);
211                 }
212               }
213             }
214             else if (node->type() == Track::AUDIO_OUTPUT)
215             {
216                   if (!MusEGlobal::checkAudioDevice()) return;
217                   AudioOutput* ao = (AudioOutput*)node;
218                   for (int i = 0; i < mc; ++i)
219                   {
220                         void* jp = ao->jackPort(i);
221                         if (i < n && jp == 0)
222                         {
223                               ao->registerPorts(i);
224                         }
225                         else if (i >= n && jp)
226                         {
227                               RouteList* ir = node->outRoutes();
228                               for (ciRoute ii = ir->begin(); ii != ir->end(); ++ii)
229                               {
230                                     Route r = *ii;
231                                     if ((r.type == Route::JACK_ROUTE) && (r.channel == i))
232                                     {
233                                           msgRemoveRoute(Route(node,i), r);
234                                           break;
235                                     }
236                               }
237                               MusEGlobal::audioDevice->unregisterPort(jp);
238                               ao->setJackPort(i, 0);
239                         }
240                   }
241             }
242       }
243 
244       // DELETETHIS 47
245       /* TODO TODO: Change all stereo routes to mono.
246       // If we are going from stereo to mono we need to disconnect any stray synti 'mono last channel'...
247       if(n == 1 && node->channels() > 1)
248       {
249         // This should always happen - syntis are fixed channels, user cannot change them. But to be safe...
250         if(node->type() != Track::AUDIO_SOFTSYNTH)
251         {
252           if(node->type() != Track::AUDIO_INPUT)
253           {
254             RouteList* rl = node->inRoutes();
255             for(iRoute r = rl->begin(); r != rl->end(); ++r)
256             {
257               // Only interested in synth tracks.
258               if(r->type != Route::TRACK_ROUTE || r->track->type() != Track::AUDIO_SOFTSYNTH)
259                 continue;
260               // If it's the last channel...
261               if(r->channel + 1 == ((AudioTrack*)r->track)->totalOutChannels())
262               {
263                 msgRemoveRoute(*r, Route(node, r->channel));
264                 //msgRemoveRoute(r, Route(node, r->remoteChannel));
265                 break;
266               }
267             }
268           }
269 
270           if(node->type() != Track::AUDIO_OUTPUT)
271           {
272             RouteList* rl = node->outRoutes();
273             for(iRoute r = rl->begin(); r != rl->end(); ++r)
274             {
275               // Only interested in synth tracks.
276               if(r->type != Route::TRACK_ROUTE || r->track->type() != Track::AUDIO_SOFTSYNTH)
277                 continue;
278               // If it's the last channel...
279               if(r->channel + 1 == ((AudioTrack*)r->track)->totalOutChannels())
280               {
281                 msgRemoveRoute(Route(node, r->channel), *r);
282                 //msgRemoveRoute(Route(node, r->remoteChannel), r);
283                 break;
284               }
285             }
286           }
287         }
288       }
289       */
290 
291       AudioMsg msg;
292       msg.id    = AUDIO_SET_CHANNELS;
293       msg.snode = node;
294       msg.ival  = n;
295       sendMsg(&msg);
296       }
297 
298 //---------------------------------------------------------
299 //   msgSwapControllerIDX
300 //---------------------------------------------------------
301 
msgSwapControllerIDX(AudioTrack * node,int idx1,int idx2)302 void Audio::msgSwapControllerIDX(AudioTrack* node, int idx1, int idx2)
303 {
304       AudioMsg msg;
305 
306       msg.id     = AUDIO_SWAP_CONTROLLER_IDX;
307       msg.snode  = node;
308       msg.a      = idx1;
309       msg.b      = idx2;
310       sendMsg(&msg);
311 }
312 
313 //---------------------------------------------------------
314 //   msgClearControllerEvents
315 //---------------------------------------------------------
316 
msgClearControllerEvents(AudioTrack * node,int acid)317 void Audio::msgClearControllerEvents(AudioTrack* node, int acid)
318 {
319 //       AudioMsg msg;
320 //
321 //       msg.id     = AUDIO_CLEAR_CONTROLLER_EVENTS;
322 //       msg.snode  = node;
323 //       msg.ival   = acid;
324 //       sendMsg(&msg);
325 
326 
327   ciCtrlList icl = node->controller()->find(acid);
328   if(icl == node->controller()->end())
329     return;
330 
331   CtrlList* cl = icl->second;
332   if(cl->empty())
333       return;
334 
335   CtrlList& clr = *icl->second;
336 
337   // The Undo system will take 'ownership' of these and delete them at the appropriate time.
338   CtrlList* erased_list_items = new CtrlList(clr, CtrlList::ASSIGN_PROPERTIES);
339   erased_list_items->insert(cl->begin(), cl->end());
340 
341   if(erased_list_items->empty())
342   {
343     delete erased_list_items;
344     return;
345   }
346 
347   MusEGlobal::song->applyOperation(UndoOp(UndoOp::ModifyAudioCtrlValList, node->controller(), erased_list_items, 0));
348 }
349 
350 //---------------------------------------------------------
351 //   msgSeekPrevACEvent
352 //---------------------------------------------------------
353 
msgSeekPrevACEvent(AudioTrack * node,int acid)354 void Audio::msgSeekPrevACEvent(AudioTrack* node, int acid)
355 {
356       AudioMsg msg;
357 
358       msg.id     = AUDIO_SEEK_PREV_AC_EVENT;
359       msg.snode  = node;
360       msg.ival   = acid;
361       sendMsg(&msg);
362 }
363 
364 //---------------------------------------------------------
365 //   msgSeekNextACEvent
366 //---------------------------------------------------------
367 
msgSeekNextACEvent(AudioTrack * node,int acid)368 void Audio::msgSeekNextACEvent(AudioTrack* node, int acid)
369 {
370       AudioMsg msg;
371 
372       msg.id     = AUDIO_SEEK_NEXT_AC_EVENT;
373       msg.snode  = node;
374       msg.ival   = acid;
375       sendMsg(&msg);
376 }
377 
378 //---------------------------------------------------------
379 //   msgEraseRangeACEvents
380 //---------------------------------------------------------
381 
msgEraseRangeACEvents(AudioTrack * node,int acid,unsigned int frame1,unsigned int frame2)382 void Audio::msgEraseRangeACEvents(AudioTrack* node, int acid, unsigned int frame1, unsigned int frame2)
383 {
384   ciCtrlList icl = node->controller()->find(acid);
385   if(icl == node->controller()->end())
386     return;
387 
388   CtrlList* cl = icl->second;
389   if(cl->empty())
390       return;
391 
392   if(frame2 < frame1)
393   {
394     const unsigned int tmp = frame1;
395     frame1 = frame2;
396     frame2 = tmp;
397   }
398 
399   iCtrl s = cl->lower_bound(frame1);
400   iCtrl e = cl->lower_bound(frame2);
401 
402   // No elements to erase?
403   if(s == cl->end())
404     return;
405 
406   CtrlList& clr = *icl->second;
407 
408   // The Undo system will take 'ownership' of these and delete them at the appropriate time.
409   CtrlList* erased_list_items = new CtrlList(clr, CtrlList::ASSIGN_PROPERTIES);
410   erased_list_items->insert(s, e);
411 
412   if(erased_list_items->empty())
413   {
414     delete erased_list_items;
415     return;
416   }
417 
418   MusEGlobal::song->applyOperation(UndoOp(UndoOp::ModifyAudioCtrlValList, node->controller(), erased_list_items, 0));
419 }
420 
421 //---------------------------------------------------------
422 //   msgChangeACEvent
423 //---------------------------------------------------------
424 
msgChangeACEvent(AudioTrack * node,int acid,int frame,int newFrame,double val)425 void Audio::msgChangeACEvent(AudioTrack* node, int acid, int frame, int newFrame, double val)
426 {
427       AudioMsg msg;
428 
429       msg.id     = AUDIO_CHANGE_AC_EVENT;
430       msg.snode  = node;
431       msg.ival   = acid;
432       msg.a      = frame;
433       msg.b      = newFrame;
434       msg.dval   = val;
435       sendMsg(&msg);
436 }
437 
438 //---------------------------------------------------------
439 //   msgSeek
440 //---------------------------------------------------------
441 
msgSeek(const Pos & pos)442 void Audio::msgSeek(const Pos& pos)
443       {
444       if (!MusEGlobal::checkAudioDevice()) return;
445       MusEGlobal::audioDevice->seekTransport(pos);
446       }
447 
448 //---------------------------------------------------------
449 //   msgExecuteOperationGroup
450 //---------------------------------------------------------
451 
msgExecuteOperationGroup(Undo & operations)452 void Audio::msgExecuteOperationGroup(Undo& operations)
453 {
454 	MusEGlobal::song->executeOperationGroup1(operations);
455 
456 	AudioMsg msg;
457 	msg.id = SEQM_EXECUTE_OPERATION_GROUP;
458 	msg.operations=&operations;
459 	sendMsg(&msg);
460 
461 	MusEGlobal::song->executeOperationGroup3(operations);
462 }
463 
464 //---------------------------------------------------------
465 //   msgRevertOperationGroup
466 //---------------------------------------------------------
467 
msgRevertOperationGroup(Undo & operations)468 void Audio::msgRevertOperationGroup(Undo& operations)
469 {
470 	MusEGlobal::song->revertOperationGroup1(operations);
471 
472 
473 	AudioMsg msg;
474 	msg.id = SEQM_REVERT_OPERATION_GROUP;
475 	msg.operations=&operations;
476 	sendMsg(&msg);
477 
478 	MusEGlobal::song->revertOperationGroup3(operations);
479 }
480 
481 //---------------------------------------------------------
482 //   msgExecutePendingOperations
483 //   Bypass the Undo system and directly execute the pending operations.
484 //---------------------------------------------------------
485 
msgExecutePendingOperations(PendingOperationList & operations,bool doUpdate,SongChangedStruct_t extraFlags)486 void Audio::msgExecutePendingOperations(PendingOperationList& operations, bool doUpdate, SongChangedStruct_t extraFlags)
487 {
488         if(operations.empty())
489           return;
490         AudioMsg msg;
491         msg.id = SEQM_EXECUTE_PENDING_OPERATIONS;
492         msg.pendingOps=&operations;
493         sendMsg(&msg);
494         operations.executeNonRTStage();
495         const SongChangedStruct_t flags = operations.flags() | extraFlags;
496         if(doUpdate && flags != SC_NOTHING)
497         {
498           MusEGlobal::song->update(flags);
499           MusEGlobal::song->setDirty();
500         }
501 }
502 
503 //---------------------------------------------------------
504 //   msgPlay
505 //---------------------------------------------------------
506 
msgPlay(bool val)507 void Audio::msgPlay(bool val)
508       {
509       if (val) {
510             if (MusEGlobal::audioDevice)
511             {
512 // REMOVE Tim. countin. Removed. This is not good. It's been here for years, and the idea
513 //  was that the transport frame should start at what the user sees - the cursor tick position.
514 // But cursor tick position should follow audio frame position, not the other way around.
515 // The transport stops on some frame in-between ticks, and here virtually always it wants to jump back
516 //  to the cursor position's frame value upon play. It is almost never the same as the device frame position.
517 // Nothing should ever set the cursor position then seek the audio. All seeking is done
518 //  through audio, and gui is informed that way. This causes problems with audio sync callback:
519 //  the seek happens while it is starting play mode, which it supports, but we don't want that.
520 // Since this only happens with OUR transport buttons and NOT any another Jack Transport client (QJackCtl),
521 //  it is a strong argument among others pro and con, to remove this for consistency with the other clients.
522 // Whatever issues removing this may cause should be fixable (they might be mistakes in the first place).
523 // User will need to be aware that the transport may be in-between ticks, ie. should view the frames,
524 //  which currently are really only seen via the BigTime window.
525 //                 unsigned sfr = MusEGlobal::song->cPos().frame();
526 //                 unsigned dcfr = MusEGlobal::audioDevice->getCurFrame();
527 //                 if(dcfr != sfr)
528 //                   MusEGlobal::audioDevice->seekTransport(MusEGlobal::song->cPos());
529                 MusEGlobal::audioDevice->startTransport();
530             }
531 
532       }else {
533             if (MusEGlobal::audioDevice)
534                 MusEGlobal::audioDevice->stopTransport();
535             _bounceState = BounceOff;
536             }
537       }
538 
539 
540 //---------------------------------------------------------
541 //   msgExternalPlay
542 //---------------------------------------------------------
543 
msgExternalPlay(bool val,bool doRewind)544 void Audio::msgExternalPlay(bool val, bool doRewind)
545       {
546       if (val) {
547             // Force the state to play immediately.
548             state = PLAY;
549             if (MusEGlobal::audioDevice)
550             {
551                 //unsigned sfr = MusEGlobal::song->cPos().frame();
552                 //unsigned dcfr = MusEGlobal::audioDevice->getCurFrame();
553                 //if(dcfr != sfr)
554                 if(doRewind)
555                   MusEGlobal::audioDevice->seekTransport(0);
556                 MusEGlobal::audioDevice->startTransport();
557             }
558 
559       }else {
560             state = STOP;
561             if (MusEGlobal::audioDevice)
562                 MusEGlobal::audioDevice->stopTransport();
563             _bounceState = BounceOff;
564             }
565       }
566 
567 
568 
569 //---------------------------------------------------------
570 //   msgRemoveTracks
571 //    remove all selected tracks
572 //---------------------------------------------------------
573 
msgRemoveTracks()574 void Audio::msgRemoveTracks()
575 {
576       Undo operations;
577       TrackList* tl = MusEGlobal::song->tracks();
578 
579       // NOTICE: This must be done in reverse order so that
580       //          'undo' will repopulate in ascending index order!
581       ciTrack it = tl->end();
582       while(it != tl->begin())
583       {
584         --it;
585         Track* tr = *it;
586         if(tr->selected())
587           operations.push_back(UndoOp(UndoOp::DeleteTrack, MusEGlobal::song->tracks()->index(tr), tr));
588       }
589 
590       MusEGlobal::song->applyOperationGroup(operations);
591 }
592 
593 //---------------------------------------------------------
594 //   msgResetMidiDevices
595 //---------------------------------------------------------
596 
msgResetMidiDevices()597 void Audio::msgResetMidiDevices()
598       {
599       AudioMsg msg;
600       msg.id = SEQM_RESET_DEVICES;
601       sendMessage(&msg, false);
602       }
603 
604 //---------------------------------------------------------
605 //   msgInitMidiDevices
606 //---------------------------------------------------------
607 
msgInitMidiDevices(bool force)608 void Audio::msgInitMidiDevices(bool force)
609       {
610       MusECore::MetronomeSettings* metro_settings =
611         MusEGlobal::metroUseSongSettings ? &MusEGlobal::metroSongSettings : &MusEGlobal::metroGlobalSettings;
612 
613       //
614       // test for explicit instrument initialization
615       //
616 
617       if(!force && MusEGlobal::config.warnInitPending)
618       {
619         bool found = false;
620         if(MusEGlobal::song->click())
621         {
622           MidiPort* mp = &MusEGlobal::midiPorts[metro_settings->clickPort];
623           if(mp->device() &&
624              (mp->device()->openFlags() & 1) &&
625              mp->instrument() && !mp->instrument()->midiInit()->empty() &&
626              !mp->initSent())
627             found = true;
628         }
629 
630         if(!found)
631         {
632           for(int i = 0; i < MusECore::MIDI_PORTS; ++i)
633           {
634             MidiPort* mp = &MusEGlobal::midiPorts[i];
635             if(mp->device() && (mp->device()->openFlags() & 1) &&
636               mp->instrument() && !mp->instrument()->midiInit()->empty() &&
637               !mp->initSent())
638             {
639               found = true;
640               break;
641             }
642           }
643         }
644 
645         if(found)
646         {
647           MusEGui::MidiWarnInitPendingDialog dlg;
648           int rv = dlg.exec();
649           bool warn = !dlg.dontAsk();
650           if(warn != MusEGlobal::config.warnInitPending)
651           {
652             MusEGlobal::config.warnInitPending = warn;
653             // Save settings. Use simple version - do NOT set style or stylesheet, this has nothing to do with that.
654             //MusEGlobal::muse->changeConfig(true);  // Save settings? No, wait till close.
655           }
656           if(rv != QDialog::Accepted)
657           {
658             if(MusEGlobal::config.midiSendInit)
659               MusEGlobal::config.midiSendInit = false;
660             //return;
661           }
662           else
663           {
664             if(!MusEGlobal::config.midiSendInit)
665               MusEGlobal::config.midiSendInit = true;
666           }
667         }
668       }
669 
670 // We can either try to do it in one cycle with one message,
671 //  or by idling the sequencer (gaining safe access to all structures)
672 //  for as much time as we need.
673 // Here we COULD get away with the audio 'hiccup' that idling causes,
674 //  because it's unlikely someone would initialize during play...
675 // But no midi is processed, so let's switch this only if requiring
676 //  large numbers of init values causes a problem later...
677 #if 1
678       AudioMsg msg;
679       msg.id = SEQM_INIT_DEVICES;
680       msg.a = force;
681       sendMessage(&msg, false);
682 #else
683       msgIdle(true);
684       initDevices(force);
685       msgIdle(false);
686 #endif
687 
688       }
689 
690 //---------------------------------------------------------
691 //   panic
692 //---------------------------------------------------------
693 
msgPanic()694 void Audio::msgPanic()
695       {
696       AudioMsg msg;
697       msg.id = SEQM_PANIC;
698       sendMessage(&msg, false);
699       }
700 
701 //---------------------------------------------------------
702 //   localOff
703 //---------------------------------------------------------
704 
msgLocalOff()705 void Audio::msgLocalOff()
706       {
707       AudioMsg msg;
708       msg.id = SEQM_MIDI_LOCAL_OFF;
709       sendMessage(&msg, false);
710       }
711 
712 //---------------------------------------------------------
713 //   msgUpdateSoloStates
714 //---------------------------------------------------------
715 
msgUpdateSoloStates()716 void Audio::msgUpdateSoloStates()
717       {
718       AudioMsg msg;
719       msg.id    = SEQM_UPDATE_SOLO_STATES;
720       sendMsg(&msg);
721       }
722 
723 //---------------------------------------------------------
724 //   msgSetAux
725 //---------------------------------------------------------
726 
msgSetAux(AudioTrack * track,int idx,double val)727 void Audio::msgSetAux(AudioTrack* track, int idx, double val)
728       {
729       AudioMsg msg;
730       msg.id    = SEQM_SET_AUX;
731       msg.snode = track;
732       msg.ival  = idx;
733       msg.dval  = val;
734       sendMessage(&msg, false);
735       }
736 
737 //---------------------------------------------------------
738 //   msgPlayMidiEvent
739 //---------------------------------------------------------
740 
msgPlayMidiEvent(const MidiPlayEvent * event)741 void Audio::msgPlayMidiEvent(const MidiPlayEvent* event)
742       {
743       AudioMsg msg;
744       msg.id = SEQM_PLAY_MIDI_EVENT;
745       msg.p1 = event;
746       sendMessage(&msg, false);
747       }
748 
749 //---------------------------------------------------------
750 //   msgSetHwCtrlState
751 //---------------------------------------------------------
752 
msgSetHwCtrlState(MidiPort * port,int ch,int ctrl,int val)753 void Audio::msgSetHwCtrlState(MidiPort* port, int ch, int ctrl, int val)
754       {
755       AudioMsg msg;
756       msg.id = SEQM_SET_HW_CTRL_STATE;
757       msg.p1 = port;
758       msg.a = ch;
759       msg.b = ctrl;
760       msg.c = val;
761       sendMessage(&msg, false);
762       }
763 
764 //---------------------------------------------------------
765 //   msgSetHwCtrlState
766 //---------------------------------------------------------
767 
msgSetHwCtrlStates(MidiPort * port,int ch,int ctrl,int val,int lastval)768 void Audio::msgSetHwCtrlStates(MidiPort* port, int ch, int ctrl, int val, int lastval)
769       {
770       AudioMsg msg;
771       msg.id = SEQM_SET_HW_CTRL_STATES;
772       msg.p1 = port;
773       msg.a = ch;
774       msg.b = ctrl;
775       msg.c = val;
776       msg.ival = lastval;
777       sendMessage(&msg, false);
778       }
779 
780 //---------------------------------------------------------
781 //   msgSetTrackAutomationType
782 //---------------------------------------------------------
783 
msgSetTrackAutomationType(Track * track,int type)784 void Audio::msgSetTrackAutomationType(Track* track, int type)
785 {
786       AudioMsg msg;
787       msg.id = SEQM_SET_TRACK_AUTO_TYPE;
788       msg.track = track;
789       msg.ival = type;
790       sendMessage(&msg, false);
791 }
792 
793 //---------------------------------------------------------
794 //   msgSetSendMetronome
795 //---------------------------------------------------------
796 
msgSetSendMetronome(AudioTrack * track,bool b)797 void Audio::msgSetSendMetronome(AudioTrack* track, bool b)
798 {
799       AudioMsg msg;
800       msg.id    = AUDIO_SET_SEND_METRONOME;
801       msg.snode = track;
802       msg.ival  = (int)b;
803       sendMessage(&msg, false);
804 }
805 
806 //---------------------------------------------------------
807 //   msgStartMidiLearn
808 //    Start learning midi
809 //---------------------------------------------------------
810 
msgStartMidiLearn()811 void Audio::msgStartMidiLearn()
812 {
813       AudioMsg msg;
814       msg.id    = AUDIO_START_MIDI_LEARN;
815       sendMessage(&msg, false);
816 }
817 
818 //---------------------------------------------------------
819 //   msgBounce
820 //    start bounce operation
821 //---------------------------------------------------------
822 
msgBounce()823 void Audio::msgBounce()
824       {
825       if (!MusEGlobal::checkAudioDevice()) return;
826 
827       MusEGlobal::audioDevice->seekTransport(MusEGlobal::song->lPos());
828       // Wait until seek takes effect.
829       msgAudioWait();
830       msgAudioWait();
831       for(int i = 0; i < 100; ++i)
832       {
833         if(_syncReady)
834           break;
835         msgAudioWait();
836       }
837       // Check if seek is really done.
838       if(!_syncReady)
839       {
840         fprintf(stderr, "ERROR: Audio::msgBounce(): Sync not ready!\n");
841         return;
842       }
843 
844       _bounceState = BounceStart;
845 
846 // REMOVE Tim. latency. Added. Moved here from audio thread process code (via Song::seqSignal()).
847       if(MusEGlobal::config.freewheelMode)
848       {
849         MusEGlobal::audioDevice->setFreewheel(true);
850         // Wait a few cycles for the freewheel to take effect.
851         for(int i = 0; i < 4; ++i)
852         {
853           if(freewheel())
854             break;
855           msgAudioWait();
856         }
857         // Check if freewheel was really set.
858         if(!freewheel())
859         {
860           fprintf(stderr, "ERROR: Audio::msgBounce(): Freewheel mode did not start yet!\n");
861         }
862       }
863 
864       }
865 
866 //---------------------------------------------------------
867 //   msgIdle
868 //---------------------------------------------------------
869 
msgIdle(bool on)870 void Audio::msgIdle(bool on)
871       {
872       AudioMsg msg;
873       msg.id = SEQM_IDLE;
874       msg.a  = on;
875       sendMessage(&msg, false);
876       }
877 
878 //---------------------------------------------------------
879 //   msgAudioWait
880 //---------------------------------------------------------
881 
msgAudioWait()882 void Audio::msgAudioWait()
883       {
884       AudioMsg msg;
885       msg.id     = AUDIO_WAIT;
886       sendMsg(&msg);
887       }
888 
889 //---------------------------------------------------------
890 //   msgSetMidiDevice
891 //    to avoid timeouts in the RT-thread, setMidiDevice
892 //    is done in GUI context after setting the audio and midi threads
893 //    into idle mode
894 //---------------------------------------------------------
895 
msgSetMidiDevice(MidiPort * port,MidiDevice * device,MidiInstrument * instrument)896 void Audio::msgSetMidiDevice(MidiPort* port, MidiDevice* device, MidiInstrument* instrument)
897 {
898   MusECore::AudioMsg msg;
899   msg.id = MusECore::SEQM_IDLE;
900   msg.a  = true;
901   //MusEGlobal::midiSeq->sendMsg(&msg);
902   sendMsg(&msg); // Idle both audio and midi.
903 
904   port->setMidiDevice(device, instrument);
905 
906   msg.id = MusECore::SEQM_IDLE;
907   msg.a  = false;
908   //MusEGlobal::midiSeq->sendMsg(&msg);
909   sendMsg(&msg); // Idle both audio and midi.
910 }
911 
912 } // namespace MusECore
913