2 Copyright (C) 2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <pbd/error.h>
21 #include <sigc++/retype.h>
22 #include <sigc++/retype_return.h>
23 #include <sigc++/bind.h>
25 #include <ardour/audio_track.h>
26 #include <ardour/diskstream.h>
27 #include <ardour/session.h>
28 #include <ardour/redirect.h>
29 #include <ardour/audioregion.h>
30 #include <ardour/route_group_specialized.h>
31 #include <ardour/insert.h>
32 #include <ardour/audioplaylist.h>
33 #include <ardour/panner.h>
34 #include <ardour/utils.h>
41 //using namespace sigc;
42 using namespace ARDOUR;
44 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag)
45 : Route (sess, name, 1, -1, -1, -1, flag),
47 _midi_rec_enable_control (*this, _session.midi_port())
49 DiskStream::Flag dflags = DiskStream::Flag (0);
51 if (_flags & Hidden) {
52 dflags = DiskStream::Flag (dflags | DiskStream::Hidden);
54 dflags = DiskStream::Flag (dflags | DiskStream::Recordable);
57 DiskStream* ds = new DiskStream (_session, name, dflags);
59 set_diskstream (*ds, this);
62 _freeze_record.state = NoFreeze;
63 _saved_meter_point = _meter_point;
65 // we do this even though Route already did it in it's init
66 reset_midi_control (_session.midi_port(), _session.get_midi_control());
70 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
71 : Route (sess, "to be renamed", 0, 0, -1, -1),
73 _midi_rec_enable_control (*this, _session.midi_port())
75 _freeze_record.state = NoFreeze;
78 _saved_meter_point = _meter_point;
80 // we do this even though Route already did it in it's init
81 reset_midi_control (_session.midi_port(), _session.get_midi_control());
84 AudioTrack::~AudioTrack ()
92 AudioTrack::deprecated_use_diskstream_connections ()
94 if (diskstream->deprecated_io_node == 0) {
98 const XMLProperty* prop;
99 XMLNode& node (*diskstream->deprecated_io_node);
101 /* don't do this more than once. */
103 diskstream->deprecated_io_node = 0;
105 set_input_minimum (-1);
106 set_input_maximum (-1);
107 set_output_minimum (-1);
108 set_output_maximum (-1);
110 if ((prop = node.property ("gain")) != 0) {
111 set_gain (atof (prop->value().c_str()), this);
112 _gain = _desired_gain;
115 if ((prop = node.property ("input-connection")) != 0) {
116 Connection* c = _session.connection_by_name (prop->value());
119 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
121 if ((c = _session.connection_by_name (_("in 1"))) == 0) {
122 error << _("No input connections available as a replacement")
126 info << string_compose (_("Connection %1 was not available - \"in 1\" used instead"), prop->value())
131 use_input_connection (*c, this);
133 } else if ((prop = node.property ("inputs")) != 0) {
134 if (set_inputs (prop->value())) {
135 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
144 AudioTrack::set_diskstream (DiskStream& ds, void *src)
150 diskstream = &ds.ref();
151 diskstream->set_io (*this);
153 if (diskstream->deprecated_io_node) {
155 if (!connecting_legal) {
156 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
158 deprecated_use_diskstream_connections ();
162 diskstream->set_record_enabled (false, this);
163 diskstream->monitor_input (false);
165 ic_connection.disconnect();
166 ic_connection = input_changed.connect (mem_fun (*diskstream, &DiskStream::handle_input_change));
168 diskstream_changed (src); /* EMIT SIGNAL */
174 AudioTrack::use_diskstream (string name)
178 if ((dstream = _session.diskstream_by_name (name)) == 0) {
179 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
183 return set_diskstream (*dstream, this);
187 AudioTrack::use_diskstream (id_t id)
191 if ((dstream = _session.diskstream_by_id (id)) == 0) {
192 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
196 return set_diskstream (*dstream, this);
200 AudioTrack::record_enabled () const
202 return diskstream->record_enabled ();
206 AudioTrack::set_record_enable (bool yn, void *src)
208 if (_freeze_record.state == Frozen) {
212 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
213 _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group);
217 /* keep track of the meter point as it was before we rec-enabled */
219 if (!diskstream->record_enabled()) {
220 _saved_meter_point = _meter_point;
223 diskstream->set_record_enabled (yn, src);
225 if (diskstream->record_enabled()) {
226 set_meter_point (MeterInput, this);
228 set_meter_point (_saved_meter_point, this);
231 if (_session.get_midi_feedback()) {
232 _midi_rec_enable_control.send_feedback (record_enabled());
238 AudioTrack::set_meter_point (MeterPoint p, void *src)
240 Route::set_meter_point (p, src);
244 AudioTrack::state(bool full_state)
246 XMLNode& track_state (Route::state (full_state));
249 /* we don't return diskstream state because we don't
250 own the diskstream exclusively. control of the diskstream
251 state is ceded to the Session, even if we create the
255 snprintf (buf, sizeof (buf), "%" PRIu64, diskstream->id());
256 track_state.add_property ("diskstream-id", buf);
262 AudioTrack::set_state (const XMLNode& node)
264 const XMLProperty *prop;
265 XMLNodeConstIterator iter;
266 XMLNodeList midi_kids;
268 if (Route::set_state (node)) {
272 midi_kids = node.children ("MIDI");
274 for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
277 XMLNodeConstIterator miter;
280 kids = (*iter)->children ();
282 for (miter = kids.begin(); miter != kids.end(); ++miter) {
286 if (child->name() == "rec_enable") {
288 MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
289 MIDI::byte additional = 0; /* ditto */
290 MIDI::channel_t chn = 0; /* ditto */
292 if (get_midi_node_info (child, ev, chn, additional)) {
293 _midi_rec_enable_control.set_control_type (chn, ev, additional);
295 error << string_compose(_("MIDI rec_enable control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
302 if ((prop = node.property ("diskstream-id")) == 0) {
304 /* some old sessions use the diskstream name rather than the ID */
306 if ((prop = node.property ("diskstream")) == 0) {
307 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
312 if (use_diskstream (prop->value())) {
318 id_t id = strtoull (prop->value().c_str(), 0, 10);
320 if (use_diskstream (id)) {
325 pending_state = const_cast<XMLNode*> (&node);
327 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
333 AudioTrack::get_state()
335 XMLNode& root (Route::get_state());
336 XMLNode* freeze_node;
339 if (_freeze_record.playlist) {
342 freeze_node = new XMLNode (X_("freeze-info"));
343 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
344 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
345 freeze_node->add_property ("state", buf);
347 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
348 inode = new XMLNode (X_("insert"));
349 snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
350 inode->add_property (X_("id"), buf);
351 inode->add_child_copy ((*i)->state);
353 freeze_node->add_child_nocopy (*inode);
356 root.add_child_nocopy (*freeze_node);
359 /* Alignment: act as a proxy for the diskstream */
361 XMLNode* align_node = new XMLNode (X_("alignment"));
362 switch (diskstream->alignment_style()) {
363 case ExistingMaterial:
364 snprintf (buf, sizeof (buf), X_("existing"));
367 snprintf (buf, sizeof (buf), X_("capture"));
370 align_node->add_property (X_("style"), buf);
371 root.add_child_nocopy (*align_node);
377 MIDI::byte additional;
378 XMLNode* midi_node = 0;
380 XMLNodeList midikids;
382 midikids = root.children ("MIDI");
383 if (!midikids.empty()) {
384 midi_node = midikids.front();
387 midi_node = root.add_child ("MIDI");
390 if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
392 child = midi_node->add_child ("rec_enable");
393 set_midi_node_info (child, ev, chn, additional);
401 AudioTrack::set_state_part_two ()
405 LocaleGuard lg (X_("POSIX"));
407 /* This is called after all session state has been restored but before
408 have been made ports and connections are established.
411 if (pending_state == 0) {
415 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
418 _freeze_record.have_mementos = false;
419 _freeze_record.state = Frozen;
421 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
424 _freeze_record.insert_info.clear ();
426 if ((prop = fnode->property (X_("playlist"))) != 0) {
427 Playlist* pl = _session.playlist_by_name (prop->value());
429 _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
431 _freeze_record.playlist = 0;
432 _freeze_record.state = NoFreeze;
437 if ((prop = fnode->property (X_("state"))) != 0) {
438 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
441 XMLNodeConstIterator citer;
442 XMLNodeList clist = fnode->children();
444 for (citer = clist.begin(); citer != clist.end(); ++citer) {
445 if ((*citer)->name() != X_("insert")) {
449 if ((prop = (*citer)->property (X_("id"))) == 0) {
453 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
455 sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
456 _freeze_record.insert_info.push_back (frii);
460 /* Alignment: act as a proxy for the diskstream */
462 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
464 if ((prop = fnode->property (X_("style"))) != 0) {
465 if (prop->value() == "existing") {
466 diskstream->set_persistent_align_style (ExistingMaterial);
467 } else if (prop->value() == "capture") {
468 diskstream->set_persistent_align_style (CaptureTime);
476 AudioTrack::n_process_buffers ()
478 return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
482 AudioTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
484 uint32_t nbufs = n_process_buffers ();
485 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
489 AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
490 bool session_state_changing, bool can_record, bool rec_monitors_input)
492 if (n_outputs() == 0) {
497 silence (nframes, offset);
501 if (session_state_changing) {
503 /* XXX is this safe to do against transport state changes? */
505 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
509 diskstream->check_record_status (start_frame, nframes, can_record);
513 if (_have_internal_generator) {
514 /* since the instrument has no input streams,
515 there is no reason to send any signal
521 if (_session.get_auto_input()) {
522 if (Config->get_no_sw_monitoring()) {
525 send_silence = false;
528 if (diskstream->record_enabled()) {
529 if (Config->get_no_sw_monitoring()) {
532 send_silence = false;
540 apply_gain_automation = false;
544 /* if we're sending silence, but we want the meters to show levels for the signal,
548 if (_have_internal_generator) {
549 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
551 if (_meter_point == MeterInput) {
552 just_meter_input (start_frame, end_frame, nframes, offset);
554 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
559 /* we're sending signal, but we may still want to meter the input.
562 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
569 AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
570 bool can_record, bool rec_monitors_input)
575 jack_nframes_t transport_frame;
578 TentativeRWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
580 // automation snapshot can also be called from the non-rt context
581 // and it uses the redirect list, so we take the lock out here
582 automation_snapshot (start_frame);
586 if (n_outputs() == 0 && _redirects.empty()) {
591 silence (nframes, offset);
595 transport_frame = _session.transport_frame();
597 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
598 /* need to do this so that the diskstream sets its
599 playback distance to zero, thus causing diskstream::commit
602 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
606 apply_gain_automation = false;
608 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
610 silence (nframes, offset);
615 /* special condition applies */
617 if (_meter_point == MeterInput) {
618 just_meter_input (start_frame, end_frame, nframes, offset);
621 if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
623 /* not actually recording, but we want to hear the input material anyway,
624 at least potentially (depending on monitoring options)
627 passthru (start_frame, end_frame, nframes, offset, 0, true);
629 } else if ((b = diskstream->playback_buffer(0)) != 0) {
632 XXX is it true that the earlier test on n_outputs()
633 means that we can avoid checking it again here? i think
634 so, because changing the i/o configuration of an IO
635 requires holding the AudioEngine lock, which we hold
636 while in the process() tree.
640 /* copy the diskstream data to all output buffers */
642 vector<Sample*>& bufs = _session.get_passthru_buffers ();
643 uint32_t limit = n_process_buffers ();
649 for (i = 0, n = 1; i < limit; ++i, ++n) {
650 memcpy (bufs[i], b, sizeof (Sample) * nframes);
651 if (n < diskstream->n_channels()) {
652 tmpb = diskstream->playback_buffer(n);
659 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
661 if (!diskstream->record_enabled() && _session.transport_rolling()) {
662 TentativeLockMonitor am (automation_lock, __LINE__, __FILE__);
664 if (am.locked() && gain_automation_playback()) {
665 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
669 process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || _session.get_recording_plugins()), declick, (_meter_point != MeterInput));
672 /* problem with the diskstream; just be quiet for a bit */
673 silence (nframes, offset);
680 AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
681 bool can_record, bool rec_monitors_input)
683 if (n_outputs() == 0 && _redirects.empty()) {
688 silence (nframes, offset);
693 apply_gain_automation = false;
695 silence (nframes, offset);
697 return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
701 AudioTrack::toggle_monitor_input ()
703 for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
704 (*i)->request_monitor_input(!(*i)->monitoring_input());
709 AudioTrack::set_name (string str, void *src)
711 if (record_enabled() && _session.actively_recording()) {
712 /* this messes things up if done while recording */
716 diskstream->set_name (str, src);
717 return IO::set_name (str, src);
721 AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
723 gain_t gain_automation[nframes];
724 gain_t gain_buffer[nframes];
725 float mix_buffer[nframes];
726 RedirectList::iterator i;
727 bool post_fader_work = false;
728 gain_t this_gain = _gain;
729 vector<Sample*>::iterator bi;
732 RWLockMonitor rlock (redirect_lock, false, __LINE__, __FILE__);
734 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
739 bi = buffers.begin();
742 for (; bi != buffers.end(); ++bi, ++n) {
743 if (n < diskstream->n_channels()) {
744 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
750 /* duplicate last across remaining buffers */
751 memcpy ((*bi), b, sizeof (Sample) * nframes);
756 /* note: only run inserts during export. other layers in the machinery
757 will already have checked that there are no external port inserts.
760 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
763 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
764 switch (insert->placement()) {
766 insert->run (buffers, nbufs, nframes, 0);
769 post_fader_work = true;
775 if (_gain_automation_curve.automation_state() == Play) {
777 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
779 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
781 for (jack_nframes_t n = 0; n < nframes; ++n) {
782 b[n] *= gain_automation[n];
788 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
790 for (jack_nframes_t n = 0; n < nframes; ++n) {
796 if (post_fader_work) {
798 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
799 PluginInsert *insert;
801 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
802 switch ((*i)->placement()) {
806 insert->run (buffers, nbufs, nframes, 0);
817 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
819 Route::set_latency_delay (longest_session_latency);
820 diskstream->set_roll_delay (_roll_delay);
824 AudioTrack::update_total_latency ()
828 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
829 if ((*i)->active ()) {
830 _own_latency += (*i)->latency ();
834 set_port_latency (_own_latency);
840 AudioTrack::bounce (InterThreadInfo& itt)
842 vector<Source*> srcs;
843 _session.write_one_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
848 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
850 vector<Source*> srcs;
851 _session.write_one_track (*this, start, end, false, srcs, itt);
855 AudioTrack::freeze (InterThreadInfo& itt)
858 vector<Source*> srcs;
859 string new_playlist_name;
860 Playlist* new_playlist;
865 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
871 while (n < (UINT_MAX-1)) {
875 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
877 if (_session.playlist_by_name (candidate) == 0) {
878 new_playlist_name = candidate;
886 if (n == (UINT_MAX-1)) {
887 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
888 " to create another one"), _freeze_record.playlist->name())
893 if (_session.write_one_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
897 _freeze_record.insert_info.clear ();
898 _freeze_record.have_mementos = true;
901 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
903 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
905 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
907 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
909 frii->insert = insert;
910 frii->id = insert->id();
911 frii->memento = (*r)->get_memento();
913 _freeze_record.insert_info.push_back (frii);
915 /* now deactivate the insert */
917 insert->set_active (false, this);
922 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
923 region_name = new_playlist_name;
925 /* create a new region from all filesources, keep it private */
927 region = new AudioRegion (srcs, 0, srcs[0]->length(),
929 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
932 new_playlist->set_orig_diskstream_id (diskstream->id());
933 new_playlist->add_region (*region, 0);
934 new_playlist->set_frozen (true);
935 region->set_locked (true);
937 diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
938 diskstream->set_record_enabled (false, this);
940 _freeze_record.state = Frozen;
941 FreezeChange(); /* EMIT SIGNAL */
945 AudioTrack::unfreeze ()
947 if (_freeze_record.playlist) {
948 diskstream->use_playlist (_freeze_record.playlist);
950 if (_freeze_record.have_mementos) {
952 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
958 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); // should this be a write lock? jlc
959 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
960 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
961 if ((*ii)->id == (*i)->id()) {
962 (*i)->set_state (((*ii)->state));
969 _freeze_record.playlist = 0;
972 _freeze_record.state = UnFrozen;
973 FreezeChange (); /* EMIT SIGNAL */
976 AudioTrack::FreezeRecord::~FreezeRecord ()
978 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
983 AudioTrack::FreezeState
984 AudioTrack::freeze_state() const
986 return _freeze_record.state;
991 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
997 Route::reset_midi_control (port, on);
999 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1003 _midi_rec_enable_control.midi_rebind (port, chn);
1007 AudioTrack::send_all_midi_feedback ()
1009 if (_session.get_midi_feedback()) {
1011 Route::send_all_midi_feedback();
1013 _midi_rec_enable_control.send_feedback (record_enabled());
1018 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1019 : MIDI::Controllable (port, 0), track (s), setting(false)
1021 last_written = false; /* XXX need a good out of bound value */
1025 AudioTrack::MIDIRecEnableControl::set_value (float val)
1027 bool bval = ((val >= 0.5f) ? true: false);
1030 track.set_record_enable (bval, this);
1035 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1038 if (!setting && get_midi_feedback()) {
1039 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1040 MIDI::channel_t ch = 0;
1041 MIDI::eventType ev = MIDI::none;
1042 MIDI::byte additional = 0;
1043 MIDI::EventTwoBytes data;
1045 if (get_control_info (ch, ev, additional)) {
1046 data.controller_number = additional;
1049 track._session.send_midi_message (get_port(), ev, ch, data);
1056 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1058 if (get_midi_feedback()) {
1060 MIDI::channel_t ch = 0;
1061 MIDI::eventType ev = MIDI::none;
1062 MIDI::byte additional = 0;
1064 if (get_control_info (ch, ev, additional)) {
1065 if (val != last_written || force) {
1067 *buf++ = additional; /* controller number */
1068 *buf++ = (MIDI::byte) (val ? 127: 0);