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