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