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