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)) {
327 XMLNodeConstIterator niter;
330 nlist = node.children();
331 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
334 if (child->name() == X_("remote_control")) {
335 if ((prop = child->property (X_("id"))) != 0) {
337 sscanf (prop->value().c_str(), "%d", &x);
338 set_remote_control_id (x);
343 pending_state = const_cast<XMLNode*> (&node);
345 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
351 AudioTrack::get_state()
353 XMLNode& root (Route::get_state());
354 XMLNode* freeze_node;
357 if (_freeze_record.playlist) {
360 freeze_node = new XMLNode (X_("freeze-info"));
361 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
362 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
363 freeze_node->add_property ("state", buf);
365 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
366 inode = new XMLNode (X_("insert"));
367 snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
368 inode->add_property (X_("id"), buf);
369 inode->add_child_copy ((*i)->state);
371 freeze_node->add_child_nocopy (*inode);
374 root.add_child_nocopy (*freeze_node);
377 /* Alignment: act as a proxy for the diskstream */
379 XMLNode* align_node = new XMLNode (X_("alignment"));
380 switch (diskstream->alignment_style()) {
381 case ExistingMaterial:
382 snprintf (buf, sizeof (buf), X_("existing"));
385 snprintf (buf, sizeof (buf), X_("capture"));
388 align_node->add_property (X_("style"), buf);
389 root.add_child_nocopy (*align_node);
395 MIDI::byte additional;
396 XMLNode* midi_node = 0;
398 XMLNodeList midikids;
400 midikids = root.children ("MIDI");
401 if (!midikids.empty()) {
402 midi_node = midikids.front();
405 midi_node = root.add_child ("MIDI");
408 if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
410 child = midi_node->add_child ("rec_enable");
411 set_midi_node_info (child, ev, chn, additional);
414 XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
415 snprintf (buf, sizeof (buf), "%d", _remote_control_id);
416 remote_control_node->add_property (X_("id"), buf);
417 root.add_child_nocopy (*remote_control_node);
423 AudioTrack::set_state_part_two ()
427 LocaleGuard lg (X_("POSIX"));
429 /* This is called after all session state has been restored but before
430 have been made ports and connections are established.
433 if (pending_state == 0) {
437 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
440 _freeze_record.have_mementos = false;
441 _freeze_record.state = Frozen;
443 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
446 _freeze_record.insert_info.clear ();
448 if ((prop = fnode->property (X_("playlist"))) != 0) {
449 Playlist* pl = _session.playlist_by_name (prop->value());
451 _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
453 _freeze_record.playlist = 0;
454 _freeze_record.state = NoFreeze;
459 if ((prop = fnode->property (X_("state"))) != 0) {
460 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
463 XMLNodeConstIterator citer;
464 XMLNodeList clist = fnode->children();
466 for (citer = clist.begin(); citer != clist.end(); ++citer) {
467 if ((*citer)->name() != X_("insert")) {
471 if ((prop = (*citer)->property (X_("id"))) == 0) {
475 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
477 sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
478 _freeze_record.insert_info.push_back (frii);
482 /* Alignment: act as a proxy for the diskstream */
484 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
486 if ((prop = fnode->property (X_("style"))) != 0) {
487 if (prop->value() == "existing") {
488 diskstream->set_persistent_align_style (ExistingMaterial);
489 } else if (prop->value() == "capture") {
490 diskstream->set_persistent_align_style (CaptureTime);
498 AudioTrack::n_process_buffers ()
500 return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
504 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)
506 uint32_t nbufs = n_process_buffers ();
507 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
511 AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
512 bool session_state_changing, bool can_record, bool rec_monitors_input)
514 if (n_outputs() == 0) {
519 silence (nframes, offset);
523 if (session_state_changing) {
525 /* XXX is this safe to do against transport state changes? */
527 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
531 diskstream->check_record_status (start_frame, nframes, can_record);
535 if (_have_internal_generator) {
536 /* since the instrument has no input streams,
537 there is no reason to send any signal
543 if (_session.get_auto_input()) {
544 if (Config->get_use_sw_monitoring()) {
545 send_silence = false;
550 if (diskstream->record_enabled()) {
551 if (Config->get_use_sw_monitoring()) {
552 send_silence = false;
562 apply_gain_automation = false;
566 /* if we're sending silence, but we want the meters to show levels for the signal,
570 if (_have_internal_generator) {
571 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
573 if (_meter_point == MeterInput) {
574 just_meter_input (start_frame, end_frame, nframes, offset);
576 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
581 /* we're sending signal, but we may still want to meter the input.
584 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
591 AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
592 bool can_record, bool rec_monitors_input)
597 jack_nframes_t transport_frame;
600 TentativeRWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
602 // automation snapshot can also be called from the non-rt context
603 // and it uses the redirect list, so we take the lock out here
604 automation_snapshot (start_frame);
608 if (n_outputs() == 0 && _redirects.empty()) {
613 silence (nframes, offset);
617 transport_frame = _session.transport_frame();
619 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
620 /* need to do this so that the diskstream sets its
621 playback distance to zero, thus causing diskstream::commit
624 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
628 apply_gain_automation = false;
630 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
632 silence (nframes, offset);
637 /* special condition applies */
639 if (_meter_point == MeterInput) {
640 just_meter_input (start_frame, end_frame, nframes, offset);
643 if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
645 /* not actually recording, but we want to hear the input material anyway,
646 at least potentially (depending on monitoring options)
649 passthru (start_frame, end_frame, nframes, offset, 0, true);
651 } else if ((b = diskstream->playback_buffer(0)) != 0) {
654 XXX is it true that the earlier test on n_outputs()
655 means that we can avoid checking it again here? i think
656 so, because changing the i/o configuration of an IO
657 requires holding the AudioEngine lock, which we hold
658 while in the process() tree.
662 /* copy the diskstream data to all output buffers */
664 vector<Sample*>& bufs = _session.get_passthru_buffers ();
665 uint32_t limit = n_process_buffers ();
671 for (i = 0, n = 1; i < limit; ++i, ++n) {
672 memcpy (bufs[i], b, sizeof (Sample) * nframes);
673 if (n < diskstream->n_channels()) {
674 tmpb = diskstream->playback_buffer(n);
681 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
683 if (!diskstream->record_enabled() && _session.transport_rolling()) {
684 TentativeLockMonitor am (automation_lock, __LINE__, __FILE__);
686 if (am.locked() && gain_automation_playback()) {
687 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
691 process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || _session.get_recording_plugins()), declick, (_meter_point != MeterInput));
694 /* problem with the diskstream; just be quiet for a bit */
695 silence (nframes, offset);
702 AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
703 bool can_record, bool rec_monitors_input)
705 if (n_outputs() == 0 && _redirects.empty()) {
710 silence (nframes, offset);
715 apply_gain_automation = false;
717 silence (nframes, offset);
719 return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
723 AudioTrack::toggle_monitor_input ()
725 for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
726 (*i)->request_monitor_input(!(*i)->monitoring_input());
731 AudioTrack::set_name (string str, void *src)
733 if (record_enabled() && _session.actively_recording()) {
734 /* this messes things up if done while recording */
738 diskstream->set_name (str, src);
739 return IO::set_name (str, src);
743 AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
745 gain_t gain_automation[nframes];
746 gain_t gain_buffer[nframes];
747 float mix_buffer[nframes];
748 RedirectList::iterator i;
749 bool post_fader_work = false;
750 gain_t this_gain = _gain;
751 vector<Sample*>::iterator bi;
754 RWLockMonitor rlock (redirect_lock, false, __LINE__, __FILE__);
756 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
761 bi = buffers.begin();
764 for (; bi != buffers.end(); ++bi, ++n) {
765 if (n < diskstream->n_channels()) {
766 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
772 /* duplicate last across remaining buffers */
773 memcpy ((*bi), b, sizeof (Sample) * nframes);
778 /* note: only run inserts during export. other layers in the machinery
779 will already have checked that there are no external port inserts.
782 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
785 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
786 switch (insert->placement()) {
788 insert->run (buffers, nbufs, nframes, 0);
791 post_fader_work = true;
797 if (_gain_automation_curve.automation_state() == Play) {
799 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
801 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
803 for (jack_nframes_t n = 0; n < nframes; ++n) {
804 b[n] *= gain_automation[n];
810 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
812 for (jack_nframes_t n = 0; n < nframes; ++n) {
818 if (post_fader_work) {
820 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
821 PluginInsert *insert;
823 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
824 switch ((*i)->placement()) {
828 insert->run (buffers, nbufs, nframes, 0);
839 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
841 Route::set_latency_delay (longest_session_latency);
842 diskstream->set_roll_delay (_roll_delay);
846 AudioTrack::update_total_latency ()
850 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
851 if ((*i)->active ()) {
852 _own_latency += (*i)->latency ();
856 set_port_latency (_own_latency);
862 AudioTrack::bounce (InterThreadInfo& itt)
864 vector<Source*> srcs;
865 _session.write_one_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
870 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
872 vector<Source*> srcs;
873 _session.write_one_track (*this, start, end, false, srcs, itt);
877 AudioTrack::freeze (InterThreadInfo& itt)
880 vector<Source*> srcs;
881 string new_playlist_name;
882 Playlist* new_playlist;
887 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
893 while (n < (UINT_MAX-1)) {
897 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
899 if (_session.playlist_by_name (candidate) == 0) {
900 new_playlist_name = candidate;
908 if (n == (UINT_MAX-1)) {
909 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
910 " to create another one"), _freeze_record.playlist->name())
915 if (_session.write_one_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
919 _freeze_record.insert_info.clear ();
920 _freeze_record.have_mementos = true;
923 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
925 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
927 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
929 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
931 frii->insert = insert;
932 frii->id = insert->id();
933 frii->memento = (*r)->get_memento();
935 _freeze_record.insert_info.push_back (frii);
937 /* now deactivate the insert */
939 insert->set_active (false, this);
944 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
945 region_name = new_playlist_name;
947 /* create a new region from all filesources, keep it private */
949 region = new AudioRegion (srcs, 0, srcs[0]->length(),
951 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
954 new_playlist->set_orig_diskstream_id (diskstream->id());
955 new_playlist->add_region (*region, 0);
956 new_playlist->set_frozen (true);
957 region->set_locked (true);
959 diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
960 diskstream->set_record_enabled (false, this);
962 _freeze_record.state = Frozen;
963 FreezeChange(); /* EMIT SIGNAL */
967 AudioTrack::unfreeze ()
969 if (_freeze_record.playlist) {
970 diskstream->use_playlist (_freeze_record.playlist);
972 if (_freeze_record.have_mementos) {
974 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
980 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); // should this be a write lock? jlc
981 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
982 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
983 if ((*ii)->id == (*i)->id()) {
984 (*i)->set_state (((*ii)->state));
991 _freeze_record.playlist = 0;
994 _freeze_record.state = UnFrozen;
995 FreezeChange (); /* EMIT SIGNAL */
998 AudioTrack::FreezeRecord::~FreezeRecord ()
1000 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
1005 AudioTrack::FreezeState
1006 AudioTrack::freeze_state() const
1008 return _freeze_record.state;
1013 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
1015 MIDI::channel_t chn;
1019 Route::reset_midi_control (port, on);
1021 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1025 _midi_rec_enable_control.midi_rebind (port, chn);
1029 AudioTrack::send_all_midi_feedback ()
1031 if (_session.get_midi_feedback()) {
1033 Route::send_all_midi_feedback();
1035 _midi_rec_enable_control.send_feedback (record_enabled());
1040 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1041 : MIDI::Controllable (port, 0), track (s), setting(false)
1043 last_written = false; /* XXX need a good out of bound value */
1047 AudioTrack::MIDIRecEnableControl::set_value (float val)
1049 bool bval = ((val >= 0.5f) ? true: false);
1052 track.set_record_enable (bval, this);
1057 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1060 if (!setting && get_midi_feedback()) {
1061 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1062 MIDI::channel_t ch = 0;
1063 MIDI::eventType ev = MIDI::none;
1064 MIDI::byte additional = 0;
1065 MIDI::EventTwoBytes data;
1067 if (get_control_info (ch, ev, additional)) {
1068 data.controller_number = additional;
1071 track._session.send_midi_message (get_port(), ev, ch, data);
1078 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1080 if (get_midi_feedback()) {
1082 MIDI::channel_t ch = 0;
1083 MIDI::eventType ev = MIDI::none;
1084 MIDI::byte additional = 0;
1086 if (get_control_info (ch, ev, additional)) {
1087 if (val != last_written || force) {
1089 *buf++ = additional; /* controller number */
1090 *buf++ = (MIDI::byte) (val ? 127: 0);