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>
39 using namespace ARDOUR;
41 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
42 : Route (sess, name, 1, -1, -1, -1, flag),
44 _midi_rec_enable_control (*this, _session.midi_port())
46 DiskStream::Flag dflags = DiskStream::Flag (0);
48 if (_flags & Hidden) {
49 dflags = DiskStream::Flag (dflags | DiskStream::Hidden);
51 dflags = DiskStream::Flag (dflags | DiskStream::Recordable);
54 if (mode == Destructive) {
55 dflags = DiskStream::Flag (dflags | DiskStream::Destructive);
58 DiskStream* ds = new DiskStream (_session, name, dflags);
61 _freeze_record.state = NoFreeze;
62 _saved_meter_point = _meter_point;
65 set_diskstream (*ds, this);
67 // we do this even though Route already did it in it's init
68 reset_midi_control (_session.midi_port(), _session.get_midi_control());
72 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
73 : Route (sess, "to be renamed", 0, 0, -1, -1),
75 _midi_rec_enable_control (*this, _session.midi_port())
77 _freeze_record.state = NoFreeze;
80 _saved_meter_point = _meter_point;
82 // we do this even though Route already did it in it's init
83 reset_midi_control (_session.midi_port(), _session.get_midi_control());
86 AudioTrack::~AudioTrack ()
94 AudioTrack::deprecated_use_diskstream_connections ()
96 if (diskstream->deprecated_io_node == 0) {
100 const XMLProperty* prop;
101 XMLNode& node (*diskstream->deprecated_io_node);
103 /* don't do this more than once. */
105 diskstream->deprecated_io_node = 0;
107 set_input_minimum (-1);
108 set_input_maximum (-1);
109 set_output_minimum (-1);
110 set_output_maximum (-1);
112 if ((prop = node.property ("gain")) != 0) {
113 set_gain (atof (prop->value().c_str()), this);
114 _gain = _desired_gain;
117 if ((prop = node.property ("input-connection")) != 0) {
118 Connection* c = _session.connection_by_name (prop->value());
121 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
123 if ((c = _session.connection_by_name (_("in 1"))) == 0) {
124 error << _("No input connections available as a replacement")
128 info << string_compose (_("Connection %1 was not available - \"in 1\" used instead"), prop->value())
133 use_input_connection (*c, this);
135 } else if ((prop = node.property ("inputs")) != 0) {
136 if (set_inputs (prop->value())) {
137 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
146 AudioTrack::set_diskstream (DiskStream& ds, void *src)
152 diskstream = &ds.ref();
153 diskstream->set_io (*this);
154 diskstream->set_destructive (_mode == Destructive);
156 if (diskstream->deprecated_io_node) {
158 if (!connecting_legal) {
159 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
161 deprecated_use_diskstream_connections ();
165 diskstream->set_record_enabled (false, this);
166 diskstream->monitor_input (false);
168 ic_connection.disconnect();
169 ic_connection = input_changed.connect (mem_fun (*diskstream, &DiskStream::handle_input_change));
171 diskstream_changed (src); /* EMIT SIGNAL */
177 AudioTrack::use_diskstream (string name)
181 if ((dstream = _session.diskstream_by_name (name)) == 0) {
182 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
186 return set_diskstream (*dstream, this);
190 AudioTrack::use_diskstream (id_t id)
194 if ((dstream = _session.diskstream_by_id (id)) == 0) {
195 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
199 return set_diskstream (*dstream, this);
203 AudioTrack::record_enabled () const
205 return diskstream->record_enabled ();
209 AudioTrack::set_record_enable (bool yn, void *src)
211 if (_freeze_record.state == Frozen) {
215 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
216 _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group);
220 /* keep track of the meter point as it was before we rec-enabled */
222 if (!diskstream->record_enabled()) {
223 _saved_meter_point = _meter_point;
226 diskstream->set_record_enabled (yn, src);
228 if (diskstream->record_enabled()) {
229 set_meter_point (MeterInput, this);
231 set_meter_point (_saved_meter_point, this);
234 if (_session.get_midi_feedback()) {
235 _midi_rec_enable_control.send_feedback (record_enabled());
241 AudioTrack::set_meter_point (MeterPoint p, void *src)
243 Route::set_meter_point (p, src);
247 AudioTrack::state(bool full_state)
249 XMLNode& track_state (Route::state (full_state));
252 /* we don't return diskstream state because we don't
253 own the diskstream exclusively. control of the diskstream
254 state is ceded to the Session, even if we create the
258 snprintf (buf, sizeof (buf), "%" PRIu64, diskstream->id());
259 track_state.add_property ("diskstream-id", buf);
265 AudioTrack::set_state (const XMLNode& node)
267 const XMLProperty *prop;
268 XMLNodeConstIterator iter;
269 XMLNodeList midi_kids;
271 if (Route::set_state (node)) {
275 if ((prop = node.property (X_("mode"))) != 0) {
276 if (prop->value() == X_("normal")) {
278 } else if (prop->value() == X_("destructive")) {
281 warning << string_compose ("unknown audio track mode \"%1\" seen and ignored", prop->value()) << endmsg;
288 midi_kids = node.children ("MIDI");
290 for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
293 XMLNodeConstIterator miter;
296 kids = (*iter)->children ();
298 for (miter = kids.begin(); miter != kids.end(); ++miter) {
302 if (child->name() == "rec_enable") {
304 MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
305 MIDI::byte additional = 0; /* ditto */
306 MIDI::channel_t chn = 0; /* ditto */
308 if (get_midi_node_info (child, ev, chn, additional)) {
309 _midi_rec_enable_control.set_control_type (chn, ev, additional);
311 error << string_compose(_("MIDI rec_enable control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
318 if ((prop = node.property ("diskstream-id")) == 0) {
320 /* some old sessions use the diskstream name rather than the ID */
322 if ((prop = node.property ("diskstream")) == 0) {
323 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
328 if (use_diskstream (prop->value())) {
334 id_t id = strtoull (prop->value().c_str(), 0, 10);
336 if (use_diskstream (id)) {
343 XMLNodeConstIterator niter;
346 nlist = node.children();
347 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
350 if (child->name() == X_("remote_control")) {
351 if ((prop = child->property (X_("id"))) != 0) {
353 sscanf (prop->value().c_str(), "%d", &x);
354 set_remote_control_id (x);
359 pending_state = const_cast<XMLNode*> (&node);
361 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
367 AudioTrack::get_state()
369 XMLNode& root (Route::get_state());
370 XMLNode* freeze_node;
373 if (_freeze_record.playlist) {
376 freeze_node = new XMLNode (X_("freeze-info"));
377 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
378 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
379 freeze_node->add_property ("state", buf);
381 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
382 inode = new XMLNode (X_("insert"));
383 snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
384 inode->add_property (X_("id"), buf);
385 inode->add_child_copy ((*i)->state);
387 freeze_node->add_child_nocopy (*inode);
390 root.add_child_nocopy (*freeze_node);
393 /* Alignment: act as a proxy for the diskstream */
395 XMLNode* align_node = new XMLNode (X_("alignment"));
396 switch (diskstream->alignment_style()) {
397 case ExistingMaterial:
398 snprintf (buf, sizeof (buf), X_("existing"));
401 snprintf (buf, sizeof (buf), X_("capture"));
404 align_node->add_property (X_("style"), buf);
405 root.add_child_nocopy (*align_node);
411 MIDI::byte additional;
412 XMLNode* midi_node = 0;
414 XMLNodeList midikids;
416 midikids = root.children ("MIDI");
417 if (!midikids.empty()) {
418 midi_node = midikids.front();
421 midi_node = root.add_child ("MIDI");
424 if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
426 child = midi_node->add_child ("rec_enable");
427 set_midi_node_info (child, ev, chn, additional);
430 XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
431 snprintf (buf, sizeof (buf), "%d", _remote_control_id);
432 remote_control_node->add_property (X_("id"), buf);
433 root.add_child_nocopy (*remote_control_node);
437 root.add_property (X_("mode"), X_("normal"));
440 root.add_property (X_("mode"), X_("destructive"));
448 AudioTrack::set_state_part_two ()
452 LocaleGuard lg (X_("POSIX"));
454 /* This is called after all session state has been restored but before
455 have been made ports and connections are established.
458 if (pending_state == 0) {
462 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
465 _freeze_record.have_mementos = false;
466 _freeze_record.state = Frozen;
468 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
471 _freeze_record.insert_info.clear ();
473 if ((prop = fnode->property (X_("playlist"))) != 0) {
474 Playlist* pl = _session.playlist_by_name (prop->value());
476 _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
478 _freeze_record.playlist = 0;
479 _freeze_record.state = NoFreeze;
484 if ((prop = fnode->property (X_("state"))) != 0) {
485 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
488 XMLNodeConstIterator citer;
489 XMLNodeList clist = fnode->children();
491 for (citer = clist.begin(); citer != clist.end(); ++citer) {
492 if ((*citer)->name() != X_("insert")) {
496 if ((prop = (*citer)->property (X_("id"))) == 0) {
500 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
502 sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
503 _freeze_record.insert_info.push_back (frii);
507 /* Alignment: act as a proxy for the diskstream */
509 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
511 if ((prop = fnode->property (X_("style"))) != 0) {
512 if (prop->value() == "existing") {
513 diskstream->set_persistent_align_style (ExistingMaterial);
514 } else if (prop->value() == "capture") {
515 diskstream->set_persistent_align_style (CaptureTime);
523 AudioTrack::n_process_buffers ()
525 return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
529 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)
531 uint32_t nbufs = n_process_buffers ();
532 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
536 AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
537 bool session_state_changing, bool can_record, bool rec_monitors_input)
539 if (n_outputs() == 0) {
544 silence (nframes, offset);
548 if (session_state_changing) {
550 /* XXX is this safe to do against transport state changes? */
552 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
556 diskstream->check_record_status (start_frame, nframes, can_record);
560 if (_have_internal_generator) {
561 /* since the instrument has no input streams,
562 there is no reason to send any signal
568 if (_session.get_auto_input()) {
569 if (Config->get_use_sw_monitoring()) {
570 send_silence = false;
575 if (diskstream->record_enabled()) {
576 if (Config->get_use_sw_monitoring()) {
577 send_silence = false;
587 apply_gain_automation = false;
591 /* if we're sending silence, but we want the meters to show levels for the signal,
595 if (_have_internal_generator) {
596 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
598 if (_meter_point == MeterInput) {
599 just_meter_input (start_frame, end_frame, nframes, offset);
601 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
606 /* we're sending signal, but we may still want to meter the input.
609 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
616 AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
617 bool can_record, bool rec_monitors_input)
622 jack_nframes_t transport_frame;
625 TentativeRWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
627 // automation snapshot can also be called from the non-rt context
628 // and it uses the redirect list, so we take the lock out here
629 automation_snapshot (start_frame);
633 if (n_outputs() == 0 && _redirects.empty()) {
638 silence (nframes, offset);
642 transport_frame = _session.transport_frame();
644 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
645 /* need to do this so that the diskstream sets its
646 playback distance to zero, thus causing diskstream::commit
649 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
653 apply_gain_automation = false;
655 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
657 silence (nframes, offset);
662 /* special condition applies */
664 if (_meter_point == MeterInput) {
665 just_meter_input (start_frame, end_frame, nframes, offset);
668 if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
670 /* not actually recording, but we want to hear the input material anyway,
671 at least potentially (depending on monitoring options)
674 passthru (start_frame, end_frame, nframes, offset, 0, true);
676 } else if ((b = diskstream->playback_buffer(0)) != 0) {
679 XXX is it true that the earlier test on n_outputs()
680 means that we can avoid checking it again here? i think
681 so, because changing the i/o configuration of an IO
682 requires holding the AudioEngine lock, which we hold
683 while in the process() tree.
687 /* copy the diskstream data to all output buffers */
689 vector<Sample*>& bufs = _session.get_passthru_buffers ();
690 uint32_t limit = n_process_buffers ();
696 for (i = 0, n = 1; i < limit; ++i, ++n) {
697 memcpy (bufs[i], b, sizeof (Sample) * nframes);
698 if (n < diskstream->n_channels()) {
699 tmpb = diskstream->playback_buffer(n);
706 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
708 if (!diskstream->record_enabled() && _session.transport_rolling()) {
709 TentativeLockMonitor am (automation_lock, __LINE__, __FILE__);
711 if (am.locked() && gain_automation_playback()) {
712 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
716 process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
719 /* problem with the diskstream; just be quiet for a bit */
720 silence (nframes, offset);
727 AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
728 bool can_record, bool rec_monitors_input)
730 if (n_outputs() == 0 && _redirects.empty()) {
735 silence (nframes, offset);
740 apply_gain_automation = false;
742 silence (nframes, offset);
744 return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
748 AudioTrack::toggle_monitor_input ()
750 for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
751 (*i)->request_monitor_input(!(*i)->monitoring_input());
756 AudioTrack::set_name (string str, void *src)
758 if (record_enabled() && _session.actively_recording()) {
759 /* this messes things up if done while recording */
763 diskstream->set_name (str, src);
764 return IO::set_name (str, src);
768 AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
770 gain_t gain_automation[nframes];
771 gain_t gain_buffer[nframes];
772 float mix_buffer[nframes];
773 RedirectList::iterator i;
774 bool post_fader_work = false;
775 gain_t this_gain = _gain;
776 vector<Sample*>::iterator bi;
779 RWLockMonitor rlock (redirect_lock, false, __LINE__, __FILE__);
781 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
786 bi = buffers.begin();
789 for (; bi != buffers.end(); ++bi, ++n) {
790 if (n < diskstream->n_channels()) {
791 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
797 /* duplicate last across remaining buffers */
798 memcpy ((*bi), b, sizeof (Sample) * nframes);
803 /* note: only run inserts during export. other layers in the machinery
804 will already have checked that there are no external port inserts.
807 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
810 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
811 switch (insert->placement()) {
813 insert->run (buffers, nbufs, nframes, 0);
816 post_fader_work = true;
822 if (_gain_automation_curve.automation_state() == Play) {
824 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
826 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
828 for (jack_nframes_t n = 0; n < nframes; ++n) {
829 b[n] *= gain_automation[n];
835 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
837 for (jack_nframes_t n = 0; n < nframes; ++n) {
843 if (post_fader_work) {
845 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
846 PluginInsert *insert;
848 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
849 switch ((*i)->placement()) {
853 insert->run (buffers, nbufs, nframes, 0);
864 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
866 Route::set_latency_delay (longest_session_latency);
867 diskstream->set_roll_delay (_roll_delay);
871 AudioTrack::update_total_latency ()
875 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
876 if ((*i)->active ()) {
877 _own_latency += (*i)->latency ();
881 set_port_latency (_own_latency);
887 AudioTrack::bounce (InterThreadInfo& itt)
889 vector<Source*> srcs;
890 _session.write_one_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
895 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
897 vector<Source*> srcs;
898 _session.write_one_track (*this, start, end, false, srcs, itt);
902 AudioTrack::freeze (InterThreadInfo& itt)
905 vector<Source*> srcs;
906 string new_playlist_name;
907 Playlist* new_playlist;
912 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
918 while (n < (UINT_MAX-1)) {
922 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
924 if (_session.playlist_by_name (candidate) == 0) {
925 new_playlist_name = candidate;
933 if (n == (UINT_MAX-1)) {
934 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
935 " to create another one"), _freeze_record.playlist->name())
940 if (_session.write_one_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
944 _freeze_record.insert_info.clear ();
945 _freeze_record.have_mementos = true;
948 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
950 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
952 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
954 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
956 frii->insert = insert;
957 frii->id = insert->id();
958 frii->memento = (*r)->get_memento();
960 _freeze_record.insert_info.push_back (frii);
962 /* now deactivate the insert */
964 insert->set_active (false, this);
969 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
970 region_name = new_playlist_name;
972 /* create a new region from all filesources, keep it private */
974 region = new AudioRegion (srcs, 0, srcs[0]->length(),
976 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
979 new_playlist->set_orig_diskstream_id (diskstream->id());
980 new_playlist->add_region (*region, 0);
981 new_playlist->set_frozen (true);
982 region->set_locked (true);
984 diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
985 diskstream->set_record_enabled (false, this);
987 _freeze_record.state = Frozen;
988 FreezeChange(); /* EMIT SIGNAL */
992 AudioTrack::unfreeze ()
994 if (_freeze_record.playlist) {
995 diskstream->use_playlist (_freeze_record.playlist);
997 if (_freeze_record.have_mementos) {
999 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
1005 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); // should this be a write lock? jlc
1006 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1007 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
1008 if ((*ii)->id == (*i)->id()) {
1009 (*i)->set_state (((*ii)->state));
1016 _freeze_record.playlist = 0;
1019 _freeze_record.state = UnFrozen;
1020 FreezeChange (); /* EMIT SIGNAL */
1023 AudioTrack::FreezeRecord::~FreezeRecord ()
1025 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
1030 AudioTrack::FreezeState
1031 AudioTrack::freeze_state() const
1033 return _freeze_record.state;
1038 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
1040 MIDI::channel_t chn;
1044 Route::reset_midi_control (port, on);
1046 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1050 _midi_rec_enable_control.midi_rebind (port, chn);
1054 AudioTrack::send_all_midi_feedback ()
1056 if (_session.get_midi_feedback()) {
1058 Route::send_all_midi_feedback();
1060 _midi_rec_enable_control.send_feedback (record_enabled());
1065 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1066 : MIDI::Controllable (port, 0), track (s), setting(false)
1068 last_written = false; /* XXX need a good out of bound value */
1072 AudioTrack::MIDIRecEnableControl::set_value (float val)
1074 bool bval = ((val >= 0.5f) ? true: false);
1077 track.set_record_enable (bval, this);
1082 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1085 if (!setting && get_midi_feedback()) {
1086 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1087 MIDI::channel_t ch = 0;
1088 MIDI::eventType ev = MIDI::none;
1089 MIDI::byte additional = 0;
1090 MIDI::EventTwoBytes data;
1092 if (get_control_info (ch, ev, additional)) {
1093 data.controller_number = additional;
1096 track._session.send_midi_message (get_port(), ev, ch, data);
1103 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1105 if (get_midi_feedback()) {
1107 MIDI::channel_t ch = 0;
1108 MIDI::eventType ev = MIDI::none;
1109 MIDI::byte additional = 0;
1111 if (get_control_info (ch, ev, additional)) {
1112 if (val != last_written || force) {
1114 *buf++ = additional; /* controller number */
1115 *buf++ = (MIDI::byte) (val ? 127: 0);
1126 AudioTrack::set_mode (TrackMode m)
1131 diskstream->set_destructive (m == Destructive);