fix wierd rec-enable behaviour, at possible expense of adding more RT cost
[ardour.git] / libs / ardour / track.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3
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.
8
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.
13
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.
17 */
18 #include "pbd/error.h"
19
20 #include "ardour/amp.h"
21 #include "ardour/debug.h"
22 #include "ardour/delivery.h"
23 #include "ardour/diskstream.h"
24 #include "ardour/io_processor.h"
25 #include "ardour/meter.h"
26 #include "ardour/playlist.h"
27 #include "ardour/port.h"
28 #include "ardour/processor.h"
29 #include "ardour/route_group_specialized.h"
30 #include "ardour/session.h"
31 #include "ardour/session_playlists.h"
32 #include "ardour/track.h"
33 #include "ardour/utils.h"
34
35 #include "i18n.h"
36
37 using namespace std;
38 using namespace ARDOUR;
39 using namespace PBD;
40
41 Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
42         : Route (sess, name, flag, default_type)
43         , _saved_meter_point (_meter_point)
44         , _mode (mode)
45         , _monitoring (MonitorAuto)
46 {
47         _freeze_record.state = NoFreeze;
48         _declickable = true;
49 }
50
51 Track::~Track ()
52 {
53         DEBUG_TRACE (DEBUG::Destruction, string_compose ("track %1 destructor\n", _name));
54 }
55
56 int
57 Track::init ()
58 {
59         if (Route::init ()) {
60                 return -1;
61         }
62
63         boost::shared_ptr<Route> rp (shared_from_this());
64         boost::shared_ptr<Track> rt = boost::dynamic_pointer_cast<Track> (rp);
65         _rec_enable_control = boost::shared_ptr<RecEnableControl> (new RecEnableControl(rt));
66         _rec_enable_control->set_flags (Controllable::Toggle);
67
68         /* don't add rec_enable_control to controls because we don't want it to
69          * appear as an automatable parameter
70          */
71
72         return 0;
73 }
74
75 void
76 Track::use_new_diskstream ()
77 {
78         boost::shared_ptr<Diskstream> ds = create_diskstream ();
79
80         ds->do_refill_with_alloc ();
81         ds->set_block_size (_session.get_block_size ());
82         ds->playlist()->set_orig_track_id (id());
83
84         set_diskstream (ds);
85 }
86
87 XMLNode&
88 Track::get_state ()
89 {
90         return state (true);
91 }
92
93 XMLNode&
94 Track::state (bool full)
95 {
96         XMLNode& root (Route::state (full));
97         root.add_property (X_("monitoring"), enum_2_string (_monitoring));
98         root.add_property (X_("saved-meter-point"), enum_2_string (_saved_meter_point));
99         root.add_child_nocopy (_rec_enable_control->get_state());
100         root.add_child_nocopy (_diskstream->get_state ());
101         
102         return root;
103 }       
104
105 int
106 Track::set_state (const XMLNode& node, int version)
107 {
108         if (Route::set_state (node, version)) {
109                 return -1;
110         }
111
112         XMLNode* child;
113
114         if (version >= 3000) {
115                 if ((child = find_named_node (node, X_("Diskstream"))) != 0) {
116                         boost::shared_ptr<Diskstream> ds = diskstream_factory (*child);
117                         ds->do_refill_with_alloc ();
118                         set_diskstream (ds);
119                 }
120         }
121
122         if (_diskstream) {
123                 _diskstream->playlist()->set_orig_track_id (id());
124         }
125
126         /* set rec-enable control *AFTER* setting up diskstream, because it may
127            want to operate on the diskstream as it sets its own state
128         */
129
130         XMLNodeList nlist = node.children();
131         for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
132                 child = *niter;
133
134                 XMLProperty* prop;
135                 if (child->name() == Controllable::xml_node_name && (prop = child->property ("name")) != 0) {
136                         if (prop->value() == X_("recenable")) {
137                                 _rec_enable_control->set_state (*child, version);
138                         }
139                 }
140         }
141         
142         const XMLProperty* prop;
143
144         if ((prop = node.property (X_("monitoring"))) != 0) {
145                 _monitoring = MonitorChoice (string_2_enum (prop->value(), _monitoring));
146         } else {
147                 _monitoring = MonitorAuto;
148         }
149
150         if ((prop = node.property (X_("saved-meter-point"))) != 0) {
151                 _saved_meter_point = MeterPoint (string_2_enum (prop->value(), _saved_meter_point));
152         } else {
153                 _saved_meter_point = _meter_point;
154         }
155
156         return 0;
157 }
158
159 XMLNode&
160 Track::get_template ()
161 {
162         return state (false);
163 }
164
165 Track::FreezeRecord::~FreezeRecord ()
166 {
167         for (vector<FreezeRecordProcessorInfo*>::iterator i = processor_info.begin(); i != processor_info.end(); ++i) {
168                 delete *i;
169         }
170 }
171
172 Track::FreezeState
173 Track::freeze_state() const
174 {
175         return _freeze_record.state;
176 }
177
178 Track::RecEnableControl::RecEnableControl (boost::shared_ptr<Track> t)
179         : AutomationControl (t->session(), RecEnableAutomation, boost::shared_ptr<AutomationList>(), X_("recenable"))
180         , track (t)
181 {
182         boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(RecEnableAutomation)));
183         set_list (gl);
184 }
185
186 void
187 Track::RecEnableControl::set_value (double val)
188 {
189         boost::shared_ptr<Track> t = track.lock ();
190         if (!t) {
191                 return;
192         }
193         
194         t->set_record_enabled (val >= 0.5 ? true : false, this);
195 }
196
197 double
198 Track::RecEnableControl::get_value () const
199 {
200         boost::shared_ptr<Track> t = track.lock ();
201         if (!t) {
202                 return 0;
203         }
204         
205         return (t->record_enabled() ? 1.0 : 0.0);
206 }
207
208 bool
209 Track::record_enabled () const
210 {
211         return _diskstream && _diskstream->record_enabled ();
212 }
213
214 bool
215 Track::can_record()
216 {
217         bool will_record = true;
218         for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) {
219                 if (!i->connected())
220                         will_record = false;
221         }
222
223         return will_record;
224 }
225
226 void
227 Track::prep_record_enabled (bool yn, void *src)
228 {
229         if (!_session.writable()) {
230                 return;
231         }
232
233         if (_freeze_record.state == Frozen) {
234                 return;
235         }
236
237         if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) {
238                 _route_group->apply (&Track::prep_record_enabled, yn, _route_group);
239                 return;
240         }
241
242         /* keep track of the meter point as it was before we rec-enabled */
243         if (!_diskstream->record_enabled()) {
244                 _saved_meter_point = _meter_point;
245         }
246
247         bool will_follow;
248         
249         if (yn) {
250                 will_follow = _diskstream->prep_record_enable ();
251         } else {
252                 will_follow = _diskstream->prep_record_disable ();
253         }
254
255         if (will_follow) {
256                 if (yn) {
257                         if (_meter_point != MeterCustom) {
258                                 set_meter_point (MeterInput);
259                         }
260                 } else {
261                         set_meter_point (_saved_meter_point);
262                 }
263         }
264 }
265
266 void
267 Track::set_record_enabled (bool yn, void *src)
268 {
269         if (!_session.writable()) {
270                 return;
271         }
272
273         if (_freeze_record.state == Frozen) {
274                 return;
275         }
276
277         if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) {
278                 _route_group->apply (&Track::set_record_enabled, yn, _route_group);
279                 return;
280         }
281
282         _diskstream->set_record_enabled (yn);
283
284         _rec_enable_control->Changed ();
285 }
286
287 bool
288 Track::set_name (const string& str)
289 {
290         bool ret;
291
292         if (record_enabled() && _session.actively_recording()) {
293                 /* this messes things up if done while recording */
294                 return false;
295         }
296
297         boost::shared_ptr<Track> me = boost::dynamic_pointer_cast<Track> (shared_from_this ());
298         if (_diskstream->playlist()->all_regions_empty () && _session.playlists->playlists_for_track (me).size() == 1) {
299                 /* Only rename the diskstream (and therefore the playlist) if
300                    a) the playlist has never had a region added to it and
301                    b) there is only one playlist for this track.
302
303                    If (a) is not followed, people can get confused if, say,
304                    they have notes about a playlist with a given name and then
305                    it changes (see mantis #4759).
306
307                    If (b) is not followed, we rename the current playlist and not
308                    the other ones, which is a bit confusing (see mantis #4977).
309                 */
310                 _diskstream->set_name (str);
311         }
312
313         /* save state so that the statefile fully reflects any filename changes */
314
315         if ((ret = Route::set_name (str)) == 0) {
316                 _session.save_state ("");
317         }
318
319         return ret;
320 }
321
322 void
323 Track::set_latency_compensation (framecnt_t longest_session_latency)
324 {
325         Route::set_latency_compensation (longest_session_latency);
326         _diskstream->set_roll_delay (_roll_delay);
327 }
328
329 int
330 Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool session_state_changing)
331 {
332         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
333         if (!lm.locked()) {
334                 return 0;
335         }
336
337         bool can_record = _session.actively_recording ();
338
339         if (n_outputs().n_total() == 0) {
340                 return 0;
341         }
342
343         if (!_active) {
344                 silence (nframes);
345                 return 0;
346         }
347
348         if (session_state_changing) {
349                 if (_session.transport_speed() != 0.0f) {
350                         /* we're rolling but some state is changing (e.g. our diskstream contents)
351                            so we cannot use them. Be silent till this is over. Don't declick.
352
353                            XXX note the absurdity of ::no_roll() being called when we ARE rolling!
354                         */
355                         passthru_silence (start_frame, end_frame, nframes, 0);
356                         return 0;
357                 }
358                 /* we're really not rolling, so we're either delivery silence or actually
359                    monitoring, both of which are safe to do while session_state_changing is true.
360                 */
361         }
362
363         _diskstream->check_record_status (start_frame, can_record);
364
365         bool be_silent;
366
367         if (_have_internal_generator) {
368                 /* since the instrument has no input streams,
369                    there is no reason to send any signal
370                    into the route.
371                 */
372                 be_silent = true;
373         } else {
374                 MonitorState const s = monitoring_state ();
375                 /* we are not rolling, so be silent even if we are monitoring disk, as there
376                    will be no disk data coming in.
377                 */
378                 be_silent = (s == MonitoringSilence || s == MonitoringDisk);
379         }
380         
381         if (!_have_internal_generator && metering_state() == MeteringInput) {
382                 _input->process_input (_meter, start_frame, end_frame, nframes);
383         }
384
385         _amp->apply_gain_automation(false);
386
387         /* if have_internal_generator, or .. */
388         //_input->process_input (_meter, start_frame, end_frame, nframes);
389
390         if (be_silent) {
391
392                 passthru_silence (start_frame, end_frame, nframes, 0);
393
394         } else {
395
396                 /* we're sending signal, but we may still want to meter the input.
397                  */
398
399                 passthru (start_frame, end_frame, nframes, false);
400         }
401
402         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
403                 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
404                 if (d) {
405                         d->flush_buffers (nframes);
406                 }
407         }
408
409         return 0;
410 }
411
412 int
413 Track::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/, bool& need_butler)
414 {
415         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
416         if (!lm.locked()) {
417                 return 0;
418         }
419
420         if (n_outputs().n_total() == 0 && _processors.empty()) {
421                 return 0;
422         }
423
424         if (!_active) {
425                 silence (nframes);
426                 return 0;
427         }
428
429         _silent = true;
430         _amp->apply_gain_automation(false);
431
432         silence (nframes);
433
434         framecnt_t playback_distance;
435         int const dret = _diskstream->process (_session.transport_frame(), nframes, playback_distance);
436         need_butler = _diskstream->commit (playback_distance);
437         return dret;
438 }
439
440 void
441 Track::set_diskstream (boost::shared_ptr<Diskstream> ds)
442 {
443         _diskstream = ds;
444
445         ds->PlaylistChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_playlist_changed, this));
446         diskstream_playlist_changed ();
447         ds->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_record_enable_changed, this));
448         ds->SpeedChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_speed_changed, this));
449         ds->AlignmentStyleChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_alignment_style_changed, this));
450 }
451
452 void
453 Track::diskstream_playlist_changed ()
454 {
455         PlaylistChanged (); /* EMIT SIGNAL */
456 }
457
458 void
459 Track::diskstream_record_enable_changed ()
460 {
461         RecordEnableChanged (); /* EMIT SIGNAL */
462 }
463
464 void
465 Track::diskstream_speed_changed ()
466 {
467         SpeedChanged (); /* EMIT SIGNAL */
468 }
469
470 void
471 Track::diskstream_alignment_style_changed ()
472 {
473         AlignmentStyleChanged (); /* EMIT SIGNAL */
474 }
475
476 boost::shared_ptr<Playlist>
477 Track::playlist ()
478 {
479         return _diskstream->playlist ();
480 }
481
482 void
483 Track::request_jack_monitors_input (bool m)
484 {
485         _diskstream->request_jack_monitors_input (m);
486 }
487
488 void
489 Track::ensure_jack_monitors_input (bool m)
490 {
491         _diskstream->ensure_jack_monitors_input (m);
492 }
493
494 bool
495 Track::destructive () const
496 {
497         return _diskstream->destructive ();
498 }
499
500 list<boost::shared_ptr<Source> > &
501 Track::last_capture_sources ()
502 {
503         return _diskstream->last_capture_sources ();
504 }
505
506 void
507 Track::set_capture_offset ()
508 {
509         _diskstream->set_capture_offset ();
510 }
511
512 list<boost::shared_ptr<Source> >
513 Track::steal_write_sources()
514 {
515         return _diskstream->steal_write_sources ();
516 }
517
518 void
519 Track::reset_write_sources (bool r, bool force)
520 {
521         _diskstream->reset_write_sources (r, force);
522 }
523
524 float
525 Track::playback_buffer_load () const
526 {
527         return _diskstream->playback_buffer_load ();
528 }
529
530 float
531 Track::capture_buffer_load () const
532 {
533         return _diskstream->capture_buffer_load ();
534 }
535
536 int
537 Track::do_refill ()
538 {
539         return _diskstream->do_refill ();
540 }
541
542 int
543 Track::do_flush (RunContext c, bool force)
544 {
545         return _diskstream->do_flush (c, force);
546 }
547
548 void
549 Track::set_pending_overwrite (bool o)
550 {
551         _diskstream->set_pending_overwrite (o);
552 }
553
554 int
555 Track::seek (framepos_t p, bool complete_refill)
556 {
557         return _diskstream->seek (p, complete_refill);
558 }
559
560 bool
561 Track::hidden () const
562 {
563         return _diskstream->hidden ();
564 }
565
566 int
567 Track::can_internal_playback_seek (framecnt_t p)
568 {
569         return _diskstream->can_internal_playback_seek (p);
570 }
571
572 int
573 Track::internal_playback_seek (framecnt_t p)
574 {
575         return _diskstream->internal_playback_seek (p);
576 }
577
578 void
579 Track::non_realtime_input_change ()
580 {
581         _diskstream->non_realtime_input_change ();
582 }
583
584 void
585 Track::non_realtime_locate (framepos_t p)
586 {
587         Route::non_realtime_locate (p);
588
589         if (!hidden()) {
590                 /* don't waste i/o cycles and butler calls
591                    for hidden (secret) tracks
592                 */
593                 _diskstream->non_realtime_locate (p);
594         }
595 }
596
597 void
598 Track::non_realtime_set_speed ()
599 {
600         _diskstream->non_realtime_set_speed ();
601 }
602
603 int
604 Track::overwrite_existing_buffers ()
605 {
606         return _diskstream->overwrite_existing_buffers ();
607 }
608
609 framecnt_t
610 Track::get_captured_frames (uint32_t n) const
611 {
612         return _diskstream->get_captured_frames (n);
613 }
614
615 int
616 Track::set_loop (Location* l)
617 {
618         return _diskstream->set_loop (l);
619 }
620
621 void
622 Track::transport_looped (framepos_t p)
623 {
624         _diskstream->transport_looped (p);
625 }
626
627 bool
628 Track::realtime_set_speed (double s, bool g)
629 {
630         return _diskstream->realtime_set_speed (s, g);
631 }
632
633 void
634 Track::transport_stopped_wallclock (struct tm & n, time_t t, bool g)
635 {
636         _diskstream->transport_stopped_wallclock (n, t, g);
637 }
638
639 bool
640 Track::pending_overwrite () const
641 {
642         return _diskstream->pending_overwrite ();
643 }
644
645 double
646 Track::speed () const
647 {
648         return _diskstream->speed ();
649 }
650
651 void
652 Track::prepare_to_stop (framepos_t p)
653 {
654         _diskstream->prepare_to_stop (p);
655 }
656
657 void
658 Track::set_slaved (bool s)
659 {
660         _diskstream->set_slaved (s);
661 }
662
663 ChanCount
664 Track::n_channels ()
665 {
666         return _diskstream->n_channels ();
667 }
668
669 framepos_t
670 Track::get_capture_start_frame (uint32_t n) const
671 {
672         return _diskstream->get_capture_start_frame (n);
673 }
674
675 AlignStyle
676 Track::alignment_style () const
677 {
678         return _diskstream->alignment_style ();
679 }
680
681 AlignChoice
682 Track::alignment_choice () const
683 {
684         return _diskstream->alignment_choice ();
685 }
686
687 framepos_t
688 Track::current_capture_start () const
689 {
690         return _diskstream->current_capture_start ();
691 }
692
693 framepos_t
694 Track::current_capture_end () const
695 {
696         return _diskstream->current_capture_end ();
697 }
698
699 void
700 Track::playlist_modified ()
701 {
702         _diskstream->playlist_modified ();
703 }
704
705 int
706 Track::use_playlist (boost::shared_ptr<Playlist> p)
707 {
708         int ret = _diskstream->use_playlist (p);
709         if (ret == 0) {
710                 p->set_orig_track_id (id());
711         }
712         return ret;
713 }
714
715 int
716 Track::use_copy_playlist ()
717 {
718         int ret =  _diskstream->use_copy_playlist ();
719
720         if (ret == 0) {
721                 _diskstream->playlist()->set_orig_track_id (id());
722         }
723
724         return ret;
725 }
726
727 int
728 Track::use_new_playlist ()
729 {
730         int ret = _diskstream->use_new_playlist ();
731
732         if (ret == 0) {
733                 _diskstream->playlist()->set_orig_track_id (id());
734         }
735
736         return ret;
737 }
738
739 void
740 Track::set_align_style (AlignStyle s, bool force)
741 {
742         _diskstream->set_align_style (s, force);
743 }
744
745 void
746 Track::set_align_choice (AlignChoice s, bool force)
747 {
748         _diskstream->set_align_choice (s, force);
749 }
750
751 bool
752 Track::using_diskstream_id (PBD::ID id) const
753 {
754         return (id == _diskstream->id ());
755 }
756
757 void
758 Track::set_block_size (pframes_t n)
759 {
760         Route::set_block_size (n);
761         _diskstream->set_block_size (n);
762 }
763
764 void
765 Track::adjust_playback_buffering ()
766 {
767         if (_diskstream) {
768                 _diskstream->adjust_playback_buffering ();
769         }
770 }
771
772 void
773 Track::adjust_capture_buffering ()
774 {
775         if (_diskstream) {
776                 _diskstream->adjust_capture_buffering ();
777         }
778 }
779
780 MonitorState
781 Track::monitoring_state () const
782 {
783         /* Explicit requests */
784         
785         if (_monitoring & MonitorInput) {
786                 return MonitoringInput;
787         }
788                 
789         if (_monitoring & MonitorDisk) {
790                 return MonitoringDisk;
791         }
792
793         /* This is an implementation of the truth table in doc/monitor_modes.pdf;
794            I don't think it's ever going to be too pretty too look at.
795         */
796
797         bool const roll = _session.transport_rolling ();
798         bool const track_rec = _diskstream->record_enabled ();
799         bool const auto_input = _session.config.get_auto_input ();
800         bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
801         bool const tape_machine_mode = Config->get_tape_machine_mode ();
802         bool session_rec;
803
804         /* I suspect that just use actively_recording() is good enough all the
805          * time, but just to keep the semantics the same as they were before
806          * sept 26th 2012, we differentiate between the cases where punch is
807          * enabled and those where it is not.
808          */
809
810         if (_session.config.get_punch_in() || _session.config.get_punch_out()) {
811                 session_rec = _session.actively_recording ();
812         } else {
813                 session_rec = _session.get_record_enabled();
814         }
815
816         if (track_rec) {
817
818                 if (!session_rec && roll && auto_input) {
819                         return MonitoringDisk;
820                 } else {
821                         return software_monitor ? MonitoringInput : MonitoringSilence;
822                 }
823
824         } else {
825
826                 if (tape_machine_mode) {
827
828                         return MonitoringDisk;
829
830                 } else {
831
832                         if (!roll && auto_input) {
833                                 return software_monitor ? MonitoringInput : MonitoringSilence;
834                         } else {
835                                 return MonitoringDisk;
836                         }
837                         
838                 }
839         }
840
841         /* NOTREACHED */
842         return MonitoringSilence;
843 }
844
845 void
846 Track::maybe_declick (BufferSet& bufs, framecnt_t nframes, int declick)
847 {
848         /* never declick if there is an internal generator - we just want it to
849            keep generating sound without interruption.
850
851            ditto if we are monitoring inputs.
852         */
853
854         if (_have_internal_generator || monitoring_choice() == MonitorInput) {
855                 return;
856         }
857
858         if (!declick) {
859                 declick = _pending_declick;
860         }
861
862         if (declick != 0) {
863                 Amp::declick (bufs, nframes, declick);
864         }
865 }
866
867 framecnt_t
868 Track::check_initial_delay (framecnt_t nframes, framepos_t& transport_frame)
869 {
870         if (_roll_delay > nframes) {
871
872                 _roll_delay -= nframes;
873                 silence_unlocked (nframes);
874                 /* transport frame is not legal for caller to use */
875                 return 0;
876
877         } else if (_roll_delay > 0) {
878
879                 nframes -= _roll_delay;
880                 silence_unlocked (_roll_delay);
881                 transport_frame += _roll_delay;
882
883                 /* shuffle all the port buffers for things that lead "out" of this Route
884                    to reflect that we just wrote _roll_delay frames of silence.
885                 */
886
887                 Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
888                 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
889                         boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor> (*i);
890                         if (iop) {
891                                 iop->increment_port_buffer_offset (_roll_delay);
892                         }
893                 }
894                 _output->increment_port_buffer_offset (_roll_delay);
895
896                 _roll_delay = 0;
897
898         }
899
900         return nframes; 
901 }
902
903 void
904 Track::set_monitoring (MonitorChoice mc)
905 {
906         if (mc !=  _monitoring) {
907                 _monitoring = mc;
908
909                 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
910                         (*i)->monitoring_changed ();
911                 }
912
913                 MonitoringChanged (); /* EMIT SIGNAL */
914         }
915 }
916
917 MeterState
918 Track::metering_state () const
919 {
920         return _diskstream->record_enabled() ? MeteringInput : MeteringRoute;
921 }