tracing and small fixes to improve object destruction pathways
[ardour.git] / libs / ardour / diskstream.cc
1 /*
2     Copyright (C) 2000-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 */
19
20 #include <fstream>
21 #include <cassert>
22 #include <cstdio>
23 #include <unistd.h>
24 #include <cmath>
25 #include <cerrno>
26 #include <string>
27 #include <climits>
28 #include <fcntl.h>
29 #include <cstdlib>
30 #include <ctime>
31 #include <sys/stat.h>
32 #include <sys/mman.h>
33
34 #include <sigc++/bind.h>
35
36 #include "pbd/error.h"
37 #include "pbd/basename.h"
38 #include <glibmm/thread.h>
39 #include "pbd/xml++.h"
40 #include "pbd/memento_command.h"
41
42 #include "ardour/ardour.h"
43 #include "ardour/audioengine.h"
44 #include "ardour/debug.h"
45 #include "ardour/diskstream.h"
46 #include "ardour/utils.h"
47 #include "ardour/configuration.h"
48 #include "ardour/audiofilesource.h"
49 #include "ardour/send.h"
50 #include "ardour/playlist.h"
51 #include "ardour/cycle_timer.h"
52 #include "ardour/region.h"
53 #include "ardour/panner.h"
54 #include "ardour/session.h"
55 #include "ardour/io.h"
56 #include "ardour/route.h"
57
58 #include "i18n.h"
59 #include <locale.h>
60
61 using namespace std;
62 using namespace ARDOUR;
63 using namespace PBD;
64
65 /* XXX This goes uninitialized when there is no ~/.ardour3 directory.
66  * I can't figure out why, so this will do for now (just stole the
67  * default from configuration_vars.h).  0 is not a good value for
68  * allocating buffer sizes..
69  */
70 ARDOUR::nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256;
71
72 sigc::signal<void>                Diskstream::DiskOverrun;
73 sigc::signal<void>                Diskstream::DiskUnderrun;
74
75 Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
76         : SessionObject(sess, name)
77 {
78         init (flag);
79 }
80
81 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
82         : SessionObject(sess, "unnamed diskstream")
83 {
84         init (Recordable);
85 }
86
87 void
88 Diskstream::init (Flag f)
89 {
90         _flags = f;
91         _route = 0;
92         _alignment_style = ExistingMaterial;
93         _persistent_alignment_style = ExistingMaterial;
94         first_input_change = true;
95         i_am_the_modifier = 0;
96         g_atomic_int_set (&_record_enabled, 0);
97         was_recording = false;
98         capture_start_frame = 0;
99         capture_captured = 0;
100         _visible_speed = 1.0f;
101         _actual_speed = 1.0f;
102         _buffer_reallocation_required = false;
103         _seek_required = false;
104         first_recordable_frame = max_frames;
105         last_recordable_frame = max_frames;
106         _roll_delay = 0;
107         _capture_offset = 0;
108         _processed = false;
109         _slaved = false;
110         adjust_capture_position = 0;
111         last_possibly_recording = 0;
112         loop_location = 0;
113         wrap_buffer_size = 0;
114         speed_buffer_size = 0;
115         _speed = 1.0;
116         _target_speed = _speed;
117         file_frame = 0;
118         playback_sample = 0;
119         playback_distance = 0;
120         _read_data_count = 0;
121         _write_data_count = 0;
122         commit_should_unlock = false;
123
124         pending_overwrite = false;
125         overwrite_frame = 0;
126         overwrite_queued = false;
127         input_change_pending = NoChange;
128 }
129
130 Diskstream::~Diskstream ()
131 {
132         DEBUG_TRACE (DEBUG::Destruction, string_compose ("Diskstream %1 deleted\n", _name));
133
134         if (_playlist) {
135                 _playlist->release ();
136         }
137 }
138
139 void
140 Diskstream::set_route (Route& r)
141 {
142         _route = &r;
143         _io = _route->input();
144         input_change_pending = ConfigurationChanged;
145         non_realtime_input_change ();
146         set_align_style_from_io ();
147
148         _route->GoingAway.connect (mem_fun (*this, &Diskstream::route_going_away));
149 }
150
151 void
152 Diskstream::handle_input_change (IOChange change, void * /*src*/)
153 {
154         Glib::Mutex::Lock lm (state_lock);
155
156         if (!(input_change_pending & change)) {
157                 input_change_pending = IOChange (input_change_pending|change);
158                 _session.request_input_change_handling ();
159         }
160 }
161
162 void
163 Diskstream::non_realtime_set_speed ()
164 {
165         if (_buffer_reallocation_required)
166         {
167                 Glib::Mutex::Lock lm (state_lock);
168                 allocate_temporary_buffers ();
169
170                 _buffer_reallocation_required = false;
171         }
172
173         if (_seek_required) {
174                 if (speed() != 1.0f || speed() != -1.0f) {
175                         seek ((nframes_t) (_session.transport_frame() * (double) speed()), true);
176                 }
177                 else {
178                         seek (_session.transport_frame(), true);
179                 }
180
181                 _seek_required = false;
182         }
183 }
184
185 bool
186 Diskstream::realtime_set_speed (double sp, bool global)
187 {
188         bool changed = false;
189         double new_speed = sp * _session.transport_speed();
190
191         if (_visible_speed != sp) {
192                 _visible_speed = sp;
193                 changed = true;
194         }
195
196         if (new_speed != _actual_speed) {
197
198                 nframes_t required_wrap_size = (nframes_t) floor (_session.get_block_size() *
199                                                                             fabs (new_speed)) + 1;
200
201                 if (required_wrap_size > wrap_buffer_size) {
202                         _buffer_reallocation_required = true;
203                 }
204
205                 _actual_speed = new_speed;
206                 _target_speed = fabs(_actual_speed);
207         }
208
209         if (changed) {
210                 if (!global) {
211                         _seek_required = true;
212                 }
213                 SpeedChanged (); /* EMIT SIGNAL */
214         }
215
216         return _buffer_reallocation_required || _seek_required;
217 }
218
219 void
220 Diskstream::prepare ()
221 {
222         _processed = false;
223         playback_distance = 0;
224 }
225
226 void
227 Diskstream::recover ()
228 {
229         if (commit_should_unlock) {
230                 state_lock.unlock();
231         }
232         _processed = false;
233 }
234
235 void
236 Diskstream::set_capture_offset ()
237 {
238         if (_io == 0) {
239                 /* can't capture, so forget it */
240                 return;
241         }
242
243         _capture_offset = _io->latency();
244 }
245
246 void
247 Diskstream::set_align_style (AlignStyle a)
248 {
249         if (record_enabled() && _session.actively_recording()) {
250                 return;
251         }
252
253         if (a != _alignment_style) {
254                 _alignment_style = a;
255                 AlignmentStyleChanged ();
256         }
257 }
258
259 int
260 Diskstream::set_loop (Location *location)
261 {
262         if (location) {
263                 if (location->start() >= location->end()) {
264                         error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
265                         return -1;
266                 }
267         }
268
269         loop_location = location;
270
271          LoopSet (location); /* EMIT SIGNAL */
272         return 0;
273 }
274
275 ARDOUR::nframes_t
276 Diskstream::get_capture_start_frame (uint32_t n)
277 {
278         Glib::Mutex::Lock lm (capture_info_lock);
279
280         if (capture_info.size() > n) {
281                 return capture_info[n]->start;
282         }
283         else {
284                 return capture_start_frame;
285         }
286 }
287
288 ARDOUR::nframes_t
289 Diskstream::get_captured_frames (uint32_t n)
290 {
291         Glib::Mutex::Lock lm (capture_info_lock);
292
293         if (capture_info.size() > n) {
294                 return capture_info[n]->frames;
295         }
296         else {
297                 return capture_captured;
298         }
299 }
300
301 void
302 Diskstream::set_roll_delay (ARDOUR::nframes_t nframes)
303 {
304         _roll_delay = nframes;
305 }
306
307 void
308 Diskstream::set_speed (double sp)
309 {
310         _session.request_diskstream_speed (*this, sp);
311
312         /* to force a rebuffering at the right place */
313         playlist_modified();
314 }
315
316 int
317 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
318 {
319         {
320                 Glib::Mutex::Lock lm (state_lock);
321
322                 if (playlist == _playlist) {
323                         return 0;
324                 }
325
326                 plmod_connection.disconnect ();
327                 plgone_connection.disconnect ();
328                 plregion_connection.disconnect ();
329
330                 if (_playlist) {
331                         _playlist->release();
332                 }
333
334                 _playlist = playlist;
335                 _playlist->use();
336
337                 if (!in_set_state && recordable()) {
338                         reset_write_sources (false);
339                 }
340
341                 plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified));
342                 plgone_connection = _playlist->GoingAway.connect (bind (mem_fun (*this, &Diskstream::playlist_deleted), boost::weak_ptr<Playlist>(_playlist)));
343                 plregion_connection = _playlist->RangesMoved.connect (mem_fun (*this, &Diskstream::playlist_ranges_moved));
344         }
345
346         /* don't do this if we've already asked for it *or* if we are setting up
347            the diskstream for the very first time - the input changed handling will
348            take care of the buffer refill.
349         */
350
351         if (!overwrite_queued && !(_session.state_of_the_state() & Session::CannotSave)) {
352                 _session.request_overwrite_buffer (this);
353                 overwrite_queued = true;
354         }
355
356         PlaylistChanged (); /* EMIT SIGNAL */
357         _session.set_dirty ();
358
359         return 0;
360 }
361
362 void
363 Diskstream::playlist_changed (Change)
364 {
365         playlist_modified ();
366 }
367
368 void
369 Diskstream::playlist_modified ()
370 {
371         if (!i_am_the_modifier && !overwrite_queued) {
372                 _session.request_overwrite_buffer (this);
373                 overwrite_queued = true;
374         }
375 }
376
377 void
378 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
379 {
380         boost::shared_ptr<Playlist> pl (wpl.lock());
381
382         if (pl == _playlist) {
383
384                 /* this catches an ordering issue with session destruction. playlists
385                    are destroyed before diskstreams. we have to invalidate any handles
386                    we have to the playlist.
387                 */
388
389                 if (_playlist) {
390                         _playlist.reset ();
391                 }
392         }
393 }
394
395 bool
396 Diskstream::set_name (const string& str)
397 {
398         if (str != _name) {
399                 assert(playlist());
400                 playlist()->set_name (str);
401
402                 SessionObject::set_name(str);
403
404                 if (!in_set_state && recordable()) {
405                         /* rename existing capture files so that they have the correct name */
406                         return rename_write_sources ();
407                 } else {
408                         return false;
409                 }
410         }
411
412         return true;
413 }
414
415 void
416 Diskstream::remove_region_from_last_capture (boost::weak_ptr<Region> wregion)
417 {
418         boost::shared_ptr<Region> region (wregion.lock());
419
420         if (!region) {
421                 return;
422         }
423
424         _last_capture_regions.remove (region);
425 }
426
427 void
428 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const & movements_frames)
429 {
430         if (!_route || Config->get_automation_follows_regions () == false) {
431                 return;
432         }
433
434         list< Evoral::RangeMove<double> > movements;
435
436         for (list< Evoral::RangeMove<nframes_t> >::const_iterator i = movements_frames.begin();
437              i != movements_frames.end();
438              ++i) {
439
440                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
441         }
442
443         /* move panner automation */
444         boost::shared_ptr<Panner> p = _route->main_outs()->panner ();
445         if (p) {
446                 for (uint32_t i = 0; i < p->npanners (); ++i) {
447                         boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
448                         XMLNode & before = pan_alist->get_state ();
449                         pan_alist->move_ranges (movements);
450                         _session.add_command (new MementoCommand<AutomationList> (
451                                                       *pan_alist.get(), &before, &pan_alist->get_state ()));
452                 }
453         }
454
455         /* move processor automation */
456         _route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &Diskstream::move_processor_automation), movements_frames));
457 }
458
459 void
460 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p,
461                                        list< Evoral::RangeMove<nframes_t> > const & movements_frames)
462 {
463         boost::shared_ptr<Processor> processor (p.lock ());
464         if (!processor) {
465                 return;
466         }
467
468         list< Evoral::RangeMove<double> > movements;
469         for (list< Evoral::RangeMove<nframes_t> >::const_iterator i = movements_frames.begin();
470                    i != movements_frames.end(); ++i) {
471                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
472         }
473
474         set<Evoral::Parameter> const a = processor->what_can_be_automated ();
475
476         for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
477                 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
478                 XMLNode & before = al->get_state ();
479                 al->move_ranges (movements);
480                 _session.add_command (
481                         new MementoCommand<AutomationList> (
482                                 *al.get(), &before, &al->get_state ()
483                                 )
484                         );
485         }
486 }
487
488 void
489 Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*/, bool can_record)
490 {
491         int possibly_recording;
492         int rolling;
493         int change;
494         const int transport_rolling = 0x4;
495         const int track_rec_enabled = 0x2;
496         const int global_rec_enabled = 0x1;
497
498         /* merge together the 3 factors that affect record status, and compute
499            what has changed.
500         */
501
502         rolling = _session.transport_speed() != 0.0f;
503         possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
504         change = possibly_recording ^ last_possibly_recording;
505
506         if (possibly_recording == last_possibly_recording) {
507                 return;
508         }
509
510         /* change state */
511
512         /* if per-track or global rec-enable turned on while the other was already on, we've started recording */
513
514         if (((change & track_rec_enabled) && record_enabled() && (!(change & global_rec_enabled) && can_record)) ||
515             ((change & global_rec_enabled) && can_record && (!(change & track_rec_enabled) && record_enabled()))) {
516
517                 /* starting to record: compute first+last frames */
518
519                 first_recordable_frame = transport_frame + _capture_offset;
520                 last_recordable_frame = max_frames;
521                 capture_start_frame = transport_frame;
522
523                 if (!(last_possibly_recording & transport_rolling) && (possibly_recording & transport_rolling)) {
524
525                         /* was stopped, now rolling (and recording) */
526
527                         if (_alignment_style == ExistingMaterial) {
528                                 first_recordable_frame += _session.worst_output_latency();
529                         } else {
530                                 first_recordable_frame += _roll_delay;
531                         }
532
533                 } else {
534
535                         /* was rolling, but record state changed */
536
537                         if (_alignment_style == ExistingMaterial) {
538
539
540                                 if (!_session.config.get_punch_in()) {
541
542                                         /* manual punch in happens at the correct transport frame
543                                            because the user hit a button. but to get alignment correct
544                                            we have to back up the position of the new region to the
545                                            appropriate spot given the roll delay.
546                                         */
547
548                                         capture_start_frame -= _roll_delay;
549
550                                         /* XXX paul notes (august 2005): i don't know why
551                                            this is needed.
552                                         */
553
554                                         first_recordable_frame += _capture_offset;
555
556                                 } else {
557
558                                         /* autopunch toggles recording at the precise
559                                            transport frame, and then the DS waits
560                                            to start recording for a time that depends
561                                            on the output latency.
562                                         */
563
564                                         first_recordable_frame += _session.worst_output_latency();
565                                 }
566
567                         } else {
568
569                                 if (_session.config.get_punch_in()) {
570                                         first_recordable_frame += _roll_delay;
571                                 } else {
572                                         capture_start_frame -= _roll_delay;
573                                 }
574                         }
575
576                 }
577
578                 prepare_record_status(capture_start_frame);
579
580         } else if (!record_enabled() || !can_record) {
581
582                 /* stop recording */
583
584                 last_recordable_frame = transport_frame + _capture_offset;
585
586                 if (_alignment_style == ExistingMaterial) {
587                         last_recordable_frame += _session.worst_output_latency();
588                 } else {
589                         last_recordable_frame += _roll_delay;
590                 }
591                 
592                 first_recordable_frame = max_frames;
593         }
594
595         last_possibly_recording = possibly_recording;
596 }
597
598 void
599 Diskstream::route_going_away ()
600 {
601         _io.reset ();
602 }
603
604 void
605 Diskstream::calculate_record_range(OverlapType ot, sframes_t transport_frame, nframes_t nframes,
606                                    nframes_t& rec_nframes, nframes_t& rec_offset)
607 {
608         switch (ot) {
609         case OverlapNone:
610                 rec_nframes = 0;
611                 break;
612
613         case OverlapInternal:
614                 /*     ----------    recrange
615                          |---|       transrange
616                 */
617                 rec_nframes = nframes;
618                 rec_offset = 0;
619                 break;
620
621         case OverlapStart:
622                 /*    |--------|    recrange
623                 -----|          transrange
624                 */
625                 rec_nframes = transport_frame + nframes - first_recordable_frame;
626                 if (rec_nframes) {
627                         rec_offset = first_recordable_frame - transport_frame;
628                 }
629                 break;
630
631         case OverlapEnd:
632                 /*    |--------|    recrange
633                          |--------  transrange
634                 */
635                 rec_nframes = last_recordable_frame - transport_frame;
636                 rec_offset = 0;
637                 break;
638
639         case OverlapExternal:
640                 /*    |--------|    recrange
641                     --------------  transrange
642                 */
643                 rec_nframes = last_recordable_frame - first_recordable_frame;
644                 rec_offset = first_recordable_frame - transport_frame;
645                 break;
646         }
647 }