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::set_state (const XMLNode& node)
249 const XMLProperty *prop;
250 XMLNodeConstIterator iter;
251 XMLNodeList midi_kids;
253 if (Route::set_state (node)) {
257 if ((prop = node.property (X_("mode"))) != 0) {
258 if (prop->value() == X_("normal")) {
260 } else if (prop->value() == X_("destructive")) {
263 warning << string_compose ("unknown audio track mode \"%1\" seen and ignored", prop->value()) << endmsg;
270 midi_kids = node.children ("MIDI");
272 for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
275 XMLNodeConstIterator miter;
278 kids = (*iter)->children ();
280 for (miter = kids.begin(); miter != kids.end(); ++miter) {
284 if (child->name() == "rec_enable") {
286 MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
287 MIDI::byte additional = 0; /* ditto */
288 MIDI::channel_t chn = 0; /* ditto */
290 if (get_midi_node_info (child, ev, chn, additional)) {
291 _midi_rec_enable_control.set_control_type (chn, ev, additional);
293 error << string_compose(_("MIDI rec_enable control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
300 if ((prop = node.property ("diskstream-id")) == 0) {
302 /* some old sessions use the diskstream name rather than the ID */
304 if ((prop = node.property ("diskstream")) == 0) {
305 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
310 if (use_diskstream (prop->value())) {
316 id_t id = strtoull (prop->value().c_str(), 0, 10);
318 if (use_diskstream (id)) {
325 XMLNodeConstIterator niter;
328 nlist = node.children();
329 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
332 if (child->name() == X_("remote_control")) {
333 if ((prop = child->property (X_("id"))) != 0) {
335 sscanf (prop->value().c_str(), "%d", &x);
336 set_remote_control_id (x);
341 pending_state = const_cast<XMLNode*> (&node);
343 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
349 AudioTrack::get_template ()
351 return state (false);
355 AudioTrack::get_state ()
361 AudioTrack::state(bool full_state)
363 XMLNode& root (Route::state(full_state));
364 XMLNode* freeze_node;
367 if (_freeze_record.playlist) {
370 freeze_node = new XMLNode (X_("freeze-info"));
371 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
372 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
373 freeze_node->add_property ("state", buf);
375 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
376 inode = new XMLNode (X_("insert"));
377 snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
378 inode->add_property (X_("id"), buf);
379 inode->add_child_copy ((*i)->state);
381 freeze_node->add_child_nocopy (*inode);
384 root.add_child_nocopy (*freeze_node);
387 /* Alignment: act as a proxy for the diskstream */
389 XMLNode* align_node = new XMLNode (X_("alignment"));
390 switch (diskstream->alignment_style()) {
391 case ExistingMaterial:
392 snprintf (buf, sizeof (buf), X_("existing"));
395 snprintf (buf, sizeof (buf), X_("capture"));
398 align_node->add_property (X_("style"), buf);
399 root.add_child_nocopy (*align_node);
405 MIDI::byte additional;
406 XMLNode* midi_node = 0;
408 XMLNodeList midikids;
410 midikids = root.children ("MIDI");
411 if (!midikids.empty()) {
412 midi_node = midikids.front();
415 midi_node = root.add_child ("MIDI");
418 if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
420 child = midi_node->add_child ("rec_enable");
421 set_midi_node_info (child, ev, chn, additional);
424 XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
425 snprintf (buf, sizeof (buf), "%d", _remote_control_id);
426 remote_control_node->add_property (X_("id"), buf);
427 root.add_child_nocopy (*remote_control_node);
431 root.add_property (X_("mode"), X_("normal"));
434 root.add_property (X_("mode"), X_("destructive"));
438 /* we don't return diskstream state because we don't
439 own the diskstream exclusively. control of the diskstream
440 state is ceded to the Session, even if we create the
444 snprintf (buf, sizeof (buf), "%" PRIu64, diskstream->id());
445 root.add_property ("diskstream-id", buf);
451 AudioTrack::set_state_part_two ()
455 LocaleGuard lg (X_("POSIX"));
457 /* This is called after all session state has been restored but before
458 have been made ports and connections are established.
461 if (pending_state == 0) {
465 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
468 _freeze_record.have_mementos = false;
469 _freeze_record.state = Frozen;
471 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
474 _freeze_record.insert_info.clear ();
476 if ((prop = fnode->property (X_("playlist"))) != 0) {
477 Playlist* pl = _session.playlist_by_name (prop->value());
479 _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
481 _freeze_record.playlist = 0;
482 _freeze_record.state = NoFreeze;
487 if ((prop = fnode->property (X_("state"))) != 0) {
488 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
491 XMLNodeConstIterator citer;
492 XMLNodeList clist = fnode->children();
494 for (citer = clist.begin(); citer != clist.end(); ++citer) {
495 if ((*citer)->name() != X_("insert")) {
499 if ((prop = (*citer)->property (X_("id"))) == 0) {
503 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
505 sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
506 _freeze_record.insert_info.push_back (frii);
510 /* Alignment: act as a proxy for the diskstream */
512 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
514 if ((prop = fnode->property (X_("style"))) != 0) {
515 if (prop->value() == "existing") {
516 diskstream->set_persistent_align_style (ExistingMaterial);
517 } else if (prop->value() == "capture") {
518 diskstream->set_persistent_align_style (CaptureTime);
526 AudioTrack::n_process_buffers ()
528 return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
532 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)
534 uint32_t nbufs = n_process_buffers ();
535 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
539 AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
540 bool session_state_changing, bool can_record, bool rec_monitors_input)
542 if (n_outputs() == 0) {
547 silence (nframes, offset);
551 if (session_state_changing) {
553 /* XXX is this safe to do against transport state changes? */
555 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
559 diskstream->check_record_status (start_frame, nframes, can_record);
563 if (_have_internal_generator) {
564 /* since the instrument has no input streams,
565 there is no reason to send any signal
571 if (_session.get_auto_input()) {
572 if (Config->get_use_sw_monitoring()) {
573 send_silence = false;
578 if (diskstream->record_enabled()) {
579 if (Config->get_use_sw_monitoring()) {
580 send_silence = false;
590 apply_gain_automation = false;
594 /* if we're sending silence, but we want the meters to show levels for the signal,
598 if (_have_internal_generator) {
599 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
601 if (_meter_point == MeterInput) {
602 just_meter_input (start_frame, end_frame, nframes, offset);
604 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
609 /* we're sending signal, but we may still want to meter the input.
612 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
619 AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
620 bool can_record, bool rec_monitors_input)
625 jack_nframes_t transport_frame;
628 TentativeRWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
630 // automation snapshot can also be called from the non-rt context
631 // and it uses the redirect list, so we take the lock out here
632 automation_snapshot (start_frame);
636 if (n_outputs() == 0 && _redirects.empty()) {
641 silence (nframes, offset);
645 transport_frame = _session.transport_frame();
647 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
648 /* need to do this so that the diskstream sets its
649 playback distance to zero, thus causing diskstream::commit
652 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
656 apply_gain_automation = false;
658 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
660 silence (nframes, offset);
665 /* special condition applies */
667 if (_meter_point == MeterInput) {
668 just_meter_input (start_frame, end_frame, nframes, offset);
671 if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
673 /* not actually recording, but we want to hear the input material anyway,
674 at least potentially (depending on monitoring options)
677 passthru (start_frame, end_frame, nframes, offset, 0, true);
679 } else if ((b = diskstream->playback_buffer(0)) != 0) {
682 XXX is it true that the earlier test on n_outputs()
683 means that we can avoid checking it again here? i think
684 so, because changing the i/o configuration of an IO
685 requires holding the AudioEngine lock, which we hold
686 while in the process() tree.
690 /* copy the diskstream data to all output buffers */
692 vector<Sample*>& bufs = _session.get_passthru_buffers ();
693 uint32_t limit = n_process_buffers ();
699 for (i = 0, n = 1; i < limit; ++i, ++n) {
700 memcpy (bufs[i], b, sizeof (Sample) * nframes);
701 if (n < diskstream->n_channels()) {
702 tmpb = diskstream->playback_buffer(n);
709 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
711 if (!diskstream->record_enabled() && _session.transport_rolling()) {
712 TentativeLockMonitor am (automation_lock, __LINE__, __FILE__);
714 if (am.locked() && gain_automation_playback()) {
715 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
719 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));
722 /* problem with the diskstream; just be quiet for a bit */
723 silence (nframes, offset);
730 AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
731 bool can_record, bool rec_monitors_input)
733 if (n_outputs() == 0 && _redirects.empty()) {
738 silence (nframes, offset);
743 apply_gain_automation = false;
745 silence (nframes, offset);
747 return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
751 AudioTrack::toggle_monitor_input ()
753 for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
754 (*i)->request_monitor_input(!(*i)->monitoring_input());
759 AudioTrack::set_name (string str, void *src)
763 if (record_enabled() && _session.actively_recording()) {
764 /* this messes things up if done while recording */
768 if (diskstream->set_name (str, src)) {
772 /* save state so that the statefile fully reflects any filename changes */
774 if ((ret = IO::set_name (str, src)) == 0) {
775 _session.save_state ("");
781 AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
783 gain_t gain_automation[nframes];
784 gain_t gain_buffer[nframes];
785 float mix_buffer[nframes];
786 RedirectList::iterator i;
787 bool post_fader_work = false;
788 gain_t this_gain = _gain;
789 vector<Sample*>::iterator bi;
792 RWLockMonitor rlock (redirect_lock, false, __LINE__, __FILE__);
794 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
799 bi = buffers.begin();
802 for (; bi != buffers.end(); ++bi, ++n) {
803 if (n < diskstream->n_channels()) {
804 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
810 /* duplicate last across remaining buffers */
811 memcpy ((*bi), b, sizeof (Sample) * nframes);
816 /* note: only run inserts during export. other layers in the machinery
817 will already have checked that there are no external port inserts.
820 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
823 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
824 switch (insert->placement()) {
826 insert->run (buffers, nbufs, nframes, 0);
829 post_fader_work = true;
835 if (_gain_automation_curve.automation_state() == Play) {
837 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
839 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
841 for (jack_nframes_t n = 0; n < nframes; ++n) {
842 b[n] *= gain_automation[n];
848 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
850 for (jack_nframes_t n = 0; n < nframes; ++n) {
856 if (post_fader_work) {
858 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
859 PluginInsert *insert;
861 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
862 switch ((*i)->placement()) {
866 insert->run (buffers, nbufs, nframes, 0);
877 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
879 Route::set_latency_delay (longest_session_latency);
880 diskstream->set_roll_delay (_roll_delay);
884 AudioTrack::update_total_latency ()
888 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
889 if ((*i)->active ()) {
890 _own_latency += (*i)->latency ();
894 set_port_latency (_own_latency);
900 AudioTrack::bounce (InterThreadInfo& itt)
902 vector<Source*> srcs;
903 _session.write_one_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
908 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
910 vector<Source*> srcs;
911 _session.write_one_track (*this, start, end, false, srcs, itt);
915 AudioTrack::freeze (InterThreadInfo& itt)
918 vector<Source*> srcs;
919 string new_playlist_name;
920 Playlist* new_playlist;
925 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
931 while (n < (UINT_MAX-1)) {
935 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
937 if (_session.playlist_by_name (candidate) == 0) {
938 new_playlist_name = candidate;
946 if (n == (UINT_MAX-1)) {
947 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
948 " to create another one"), _freeze_record.playlist->name())
953 if (_session.write_one_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
957 _freeze_record.insert_info.clear ();
958 _freeze_record.have_mementos = true;
961 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
963 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
965 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
967 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
969 frii->insert = insert;
970 frii->id = insert->id();
971 frii->memento = (*r)->get_memento();
973 _freeze_record.insert_info.push_back (frii);
975 /* now deactivate the insert */
977 insert->set_active (false, this);
982 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
983 region_name = new_playlist_name;
985 /* create a new region from all filesources, keep it private */
987 region = new AudioRegion (srcs, 0, srcs[0]->length(),
989 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
992 new_playlist->set_orig_diskstream_id (diskstream->id());
993 new_playlist->add_region (*region, 0);
994 new_playlist->set_frozen (true);
995 region->set_locked (true);
997 diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
998 diskstream->set_record_enabled (false, this);
1000 _freeze_record.state = Frozen;
1001 FreezeChange(); /* EMIT SIGNAL */
1005 AudioTrack::unfreeze ()
1007 if (_freeze_record.playlist) {
1008 diskstream->use_playlist (_freeze_record.playlist);
1010 if (_freeze_record.have_mementos) {
1012 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
1018 RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); // should this be a write lock? jlc
1019 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1020 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
1021 if ((*ii)->id == (*i)->id()) {
1022 (*i)->set_state (((*ii)->state));
1029 _freeze_record.playlist = 0;
1032 _freeze_record.state = UnFrozen;
1033 FreezeChange (); /* EMIT SIGNAL */
1036 AudioTrack::FreezeRecord::~FreezeRecord ()
1038 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
1043 AudioTrack::FreezeState
1044 AudioTrack::freeze_state() const
1046 return _freeze_record.state;
1051 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
1053 MIDI::channel_t chn;
1057 Route::reset_midi_control (port, on);
1059 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1063 _midi_rec_enable_control.midi_rebind (port, chn);
1067 AudioTrack::send_all_midi_feedback ()
1069 if (_session.get_midi_feedback()) {
1071 Route::send_all_midi_feedback();
1073 _midi_rec_enable_control.send_feedback (record_enabled());
1078 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1079 : MIDI::Controllable (port, 0), track (s), setting(false)
1081 last_written = false; /* XXX need a good out of bound value */
1085 AudioTrack::MIDIRecEnableControl::set_value (float val)
1087 bool bval = ((val >= 0.5f) ? true: false);
1090 track.set_record_enable (bval, this);
1095 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1098 if (!setting && get_midi_feedback()) {
1099 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1100 MIDI::channel_t ch = 0;
1101 MIDI::eventType ev = MIDI::none;
1102 MIDI::byte additional = 0;
1103 MIDI::EventTwoBytes data;
1105 if (get_control_info (ch, ev, additional)) {
1106 data.controller_number = additional;
1109 track._session.send_midi_message (get_port(), ev, ch, data);
1116 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1118 if (get_midi_feedback()) {
1120 MIDI::channel_t ch = 0;
1121 MIDI::eventType ev = MIDI::none;
1122 MIDI::byte additional = 0;
1124 if (get_control_info (ch, ev, additional)) {
1125 if (val != last_written || force) {
1127 *buf++ = additional; /* controller number */
1128 *buf++ = (MIDI::byte) (val ? 127: 0);
1139 AudioTrack::set_mode (TrackMode m)
1144 diskstream->set_destructive (m == Destructive);