switch to using boost::signals2 instead of sigc++, at least for libardour. not finish...
[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/audioplaylist.h"
22 #include "ardour/audioregion.h"
23 #include "ardour/audiosource.h"
24 #include "ardour/debug.h"
25 #include "ardour/delivery.h"
26 #include "ardour/diskstream.h"
27 #include "ardour/io_processor.h"
28 #include "ardour/meter.h"
29 #include "ardour/port.h"
30 #include "ardour/processor.h"
31 #include "ardour/route_group_specialized.h"
32 #include "ardour/session.h"
33 #include "ardour/track.h"
34 #include "ardour/utils.h"
35
36 #include "i18n.h"
37
38 using namespace std;
39 using namespace ARDOUR;
40 using namespace PBD;
41
42 Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
43         : Route (sess, name, flag, default_type)
44         , _rec_enable_control (new RecEnableControllable(*this))
45 {
46         _declickable = true;
47         _freeze_record.state = NoFreeze;
48         _saved_meter_point = _meter_point;
49         _mode = mode;
50 }
51
52 Track::Track (Session& sess, const XMLNode& node, DataType default_type)
53         : Route (sess, node, default_type)
54         , _rec_enable_control (new RecEnableControllable(*this))
55 {
56         _freeze_record.state = NoFreeze;
57         _declickable = true;
58         _saved_meter_point = _meter_point;
59 }
60
61 Track::~Track ()
62 {
63         DEBUG_TRACE (DEBUG::Destruction, string_compose ("track %1 destructor\n", _name));
64 }
65
66 XMLNode&
67 Track::get_state ()
68 {
69         return state (true);
70 }
71
72 XMLNode&
73 Track::get_template ()
74 {
75         return state (false);
76 }
77
78 void
79 Track::toggle_monitor_input ()
80 {
81         for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
82                 i->ensure_monitor_input(!i->monitoring_input());
83         }
84 }
85
86 ARDOUR::nframes_t
87 Track::update_total_latency ()
88 {
89         nframes_t old = _output->effective_latency();
90         nframes_t own_latency = _output->user_latency();
91
92         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
93                 if ((*i)->active ()) {
94                         own_latency += (*i)->signal_latency ();
95                 }
96         }
97
98 #undef DEBUG_LATENCY
99 #ifdef DEBUG_LATENCY
100         cerr << _name << ": internal redirect (final) latency = " << own_latency << endl;
101 #endif
102
103         _output->set_port_latency (own_latency);
104
105         if (old != own_latency) {
106                 _output->set_latency_delay (own_latency);
107                 signal_latency_changed (); /* EMIT SIGNAL */
108         }
109
110         return _output->effective_latency();
111 }
112
113 Track::FreezeRecord::~FreezeRecord ()
114 {
115         for (vector<FreezeRecordProcessorInfo*>::iterator i = processor_info.begin(); i != processor_info.end(); ++i) {
116                 delete *i;
117         }
118 }
119
120 Track::FreezeState
121 Track::freeze_state() const
122 {
123         return _freeze_record.state;
124 }
125
126 Track::RecEnableControllable::RecEnableControllable (Track& s)
127         : Controllable (X_("recenable"), string() /* XXX missing URI */), track (s)
128 {
129 }
130
131 void
132 Track::RecEnableControllable::set_value (float val)
133 {
134         bool bval = ((val >= 0.5f) ? true: false);
135         track.set_record_enable (bval, this);
136 }
137
138 float
139 Track::RecEnableControllable::get_value (void) const
140 {
141         if (track.record_enabled()) { return 1.0f; }
142         return 0.0f;
143 }
144
145 bool
146 Track::record_enabled () const
147 {
148         return _diskstream && _diskstream->record_enabled ();
149 }
150
151 bool
152 Track::can_record()
153 {
154         bool will_record = true;
155         for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) {
156                 if (!i->connected())
157                         will_record = false;
158         }
159
160         return will_record;
161 }
162
163 void
164 Track::set_record_enable (bool yn, void *src)
165 {
166         if (!_session.writable()) {
167                 return;
168         }
169
170         if (_freeze_record.state == Frozen) {
171                 return;
172         }
173
174         if (_route_group && src != _route_group && _route_group->active_property (RouteGroup::RecEnable)) {
175                 _route_group->apply (&Track::set_record_enable, yn, _route_group);
176                 return;
177         }
178
179         /* keep track of the meter point as it was before we rec-enabled */
180         if (!_diskstream->record_enabled()) {
181                 _saved_meter_point = _meter_point;
182         }
183
184         _diskstream->set_record_enabled (yn);
185
186         if (_diskstream->record_enabled()) {
187                 if (_meter_point != MeterCustom) {
188                         set_meter_point (MeterInput, this);
189                 }
190         } else {
191                 set_meter_point (_saved_meter_point, this);
192         }
193
194         _rec_enable_control->Changed ();
195 }
196
197
198 bool
199 Track::set_name (const string& str)
200 {
201         bool ret;
202
203         if (record_enabled() && _session.actively_recording()) {
204                 /* this messes things up if done while recording */
205                 return false;
206         }
207
208         if (_diskstream->set_name (str)) {
209                 return false;
210         }
211
212         /* save state so that the statefile fully reflects any filename changes */
213
214         if ((ret = Route::set_name (str)) == 0) {
215                 _session.save_state ("");
216         }
217
218         return ret;
219 }
220
221 void
222 Track::set_latency_delay (nframes_t longest_session_latency)
223 {
224         Route::set_latency_delay (longest_session_latency);
225         _diskstream->set_roll_delay (_roll_delay);
226 }
227
228 void
229 Track::zero_diskstream_id_in_xml (XMLNode& node)
230 {
231         if (node.property ("diskstream-id")) {
232                 node.add_property ("diskstream-id", "0");
233         }
234 }
235
236 int
237 Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
238                 bool session_state_changing, bool can_record, bool /*rec_monitors_input*/)
239 {
240         if (n_outputs().n_total() == 0) {
241                 return 0;
242         }
243
244         if (!_active) {
245                 silence (nframes);
246                 return 0;
247         }
248
249         if (session_state_changing) {
250
251                 /* XXX is this safe to do against transport state changes? */
252
253                 passthru_silence (start_frame, end_frame, nframes, 0);
254                 return 0;
255         }
256
257         diskstream()->check_record_status (start_frame, nframes, can_record);
258
259         bool send_silence;
260
261         if (_have_internal_generator) {
262                 /* since the instrument has no input streams,
263                    there is no reason to send any signal
264                    into the route.
265                 */
266                 send_silence = true;
267         } else {
268                 if (!Config->get_tape_machine_mode()) {
269                         /*
270                            ADATs work in a strange way..
271                            they monitor input always when stopped.and auto-input is engaged.
272                         */
273                         if ((Config->get_monitoring_model() == SoftwareMonitoring)
274                                         && (_session.config.get_auto_input () || _diskstream->record_enabled())) {
275                                 send_silence = false;
276                         } else {
277                                 send_silence = true;
278                         }
279                 } else {
280                         /*
281                            Other machines switch to input on stop if the track is record enabled,
282                            regardless of the auto input setting (auto input only changes the
283                            monitoring state when the transport is rolling)
284                         */
285                         if ((Config->get_monitoring_model() == SoftwareMonitoring)
286                                         && _diskstream->record_enabled()) {
287                                 send_silence = false;
288                         } else {
289                                 send_silence = true;
290                         }
291                 }
292         }
293
294         _amp->apply_gain_automation(false);
295
296         if (send_silence) {
297
298                 /* if we're sending silence, but we want the meters to show levels for the signal,
299                    meter right here.
300                 */
301
302                 if (_have_internal_generator) {
303                         passthru_silence (start_frame, end_frame, nframes, 0);
304                 } else {
305                         if (_meter_point == MeterInput) {
306                                 _input->process_input (_meter, start_frame, end_frame, nframes);
307                         }
308                         passthru_silence (start_frame, end_frame, nframes, 0);
309                 }
310
311         } else {
312
313                 /* we're sending signal, but we may still want to meter the input.
314                  */
315
316                 passthru (start_frame, end_frame, nframes, false);
317         }
318
319         _main_outs->flush (nframes, end_frame - start_frame - 1);
320
321         return 0;
322 }
323
324 int
325 Track::silent_roll (nframes_t nframes, sframes_t /*start_frame*/, sframes_t /*end_frame*/,
326                     bool can_record, bool rec_monitors_input)
327 {
328         if (n_outputs().n_total() == 0 && _processors.empty()) {
329                 return 0;
330         }
331
332         if (!_active) {
333                 silence (nframes);
334                 return 0;
335         }
336
337         _silent = true;
338         _amp->apply_gain_automation(false);
339
340         silence (nframes);
341
342         return diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input);
343 }