Don't write undo records for automation that moves with regions when nothing changes...
[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/track.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         , _track (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         , _track (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_track (Track* t)
180 {
181         _track = t;
182         _io = _track->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         _track->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 int
335 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
336 {
337         if (!playlist) {
338                 return 0;
339         }
340
341         bool prior_playlist = false;
342
343         {
344                 Glib::Mutex::Lock lm (state_lock);
345
346                 if (playlist == _playlist) {
347                         return 0;
348                 }
349
350                 playlist_connections.drop_connections ();
351
352                 if (_playlist) {
353                         _playlist->release();
354                         prior_playlist = true;
355                 }
356
357                 _playlist = playlist;
358                 _playlist->use();
359
360                 if (!in_set_state && recordable()) {
361                         reset_write_sources (false);
362                 }
363
364                 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
365                 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
366                 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1, _2));
367         }
368
369         /* don't do this if we've already asked for it *or* if we are setting up
370            the diskstream for the very first time - the input changed handling will
371            take care of the buffer refill.
372         */
373
374         if (!overwrite_queued && prior_playlist) {
375                 _session.request_overwrite_buffer (_track);
376                 overwrite_queued = true;
377         }
378
379         PlaylistChanged (); /* EMIT SIGNAL */
380         _session.set_dirty ();
381
382         return 0;
383 }
384
385 void
386 Diskstream::playlist_changed (const PropertyChange&)
387 {
388         playlist_modified ();
389 }
390
391 void
392 Diskstream::playlist_modified ()
393 {
394         if (!i_am_the_modifier && !overwrite_queued) {
395                 _session.request_overwrite_buffer (_track);
396                 overwrite_queued = true;
397         }
398 }
399
400 void
401 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
402 {
403         boost::shared_ptr<Playlist> pl (wpl.lock());
404
405         if (pl == _playlist) {
406
407                 /* this catches an ordering issue with session destruction. playlists
408                    are destroyed before diskstreams. we have to invalidate any handles
409                    we have to the playlist.
410                 */
411
412                 if (_playlist) {
413                         _playlist.reset ();
414                 }
415         }
416 }
417
418 bool
419 Diskstream::set_name (const string& str)
420 {
421         if (_name != str) {
422                 assert(playlist());
423                 playlist()->set_name (str);
424
425                 SessionObject::set_name(str);
426
427                 if (!in_set_state && recordable()) {
428                         /* rename existing capture files so that they have the correct name */
429                         return rename_write_sources ();
430                 } else {
431                         return false;
432                 }
433         }
434
435         return true;
436 }
437
438 void
439 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
440 {
441         /* If we're coming from an undo, it will have handled
442            automation undo (it must, since automation-follows-regions
443            can lose automation data).  Hence we can do nothing here.
444         */
445         
446         if (from_undo) {
447                 return;
448         }
449         
450         if (!_track || Config->get_automation_follows_regions () == false) {
451                 return;
452         }
453
454         list< Evoral::RangeMove<double> > movements;
455
456         for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
457              i != movements_frames.end();
458              ++i) {
459
460                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
461         }
462
463         /* move panner automation */
464         boost::shared_ptr<Panner> p = _track->main_outs()->panner ();
465         if (p) {
466                 for (uint32_t i = 0; i < p->npanners (); ++i) {
467                         boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
468                         XMLNode & before = pan_alist->get_state ();
469                         bool const things_moved = pan_alist->move_ranges (movements);
470                         if (things_moved) {
471                                 _session.add_command (new MementoCommand<AutomationList> (
472                                                               *pan_alist.get(), &before, &pan_alist->get_state ()));
473                         }
474                 }
475         }
476
477         /* move processor automation */
478         _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
479 }
480
481 void
482 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
483 {
484         boost::shared_ptr<Processor> processor (p.lock ());
485         if (!processor) {
486                 return;
487         }
488
489         list< Evoral::RangeMove<double> > movements;
490         for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
491                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
492         }
493
494         set<Evoral::Parameter> const a = processor->what_can_be_automated ();
495
496         for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
497                 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
498                 XMLNode & before = al->get_state ();
499                 bool const things_moved = al->move_ranges (movements);
500                 if (things_moved) {
501                         _session.add_command (
502                                 new MementoCommand<AutomationList> (
503                                         *al.get(), &before, &al->get_state ()
504                                         )
505                                 );
506                 }
507         }
508 }
509
510 void
511 Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*/, bool can_record)
512 {
513         int possibly_recording;
514         int rolling;
515         int change;
516         const int transport_rolling = 0x4;
517         const int track_rec_enabled = 0x2;
518         const int global_rec_enabled = 0x1;
519         const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
520
521         /* merge together the 3 factors that affect record status, and compute
522            what has changed.
523         */
524
525         rolling = _session.transport_speed() != 0.0f;
526         possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
527         change = possibly_recording ^ last_possibly_recording;
528
529         if (possibly_recording == last_possibly_recording) {
530                 return;
531         }
532         if (possibly_recording == fully_rec_enabled) {
533
534                 if (last_possibly_recording == fully_rec_enabled) {
535                         return;
536                 }
537
538                 /* we transitioned to recording. lets see if its transport based or a punch */
539                 
540                 first_recordable_frame = transport_frame + _capture_offset;
541                 last_recordable_frame = max_frames;
542                 capture_start_frame = transport_frame;
543
544                 if (change & transport_rolling) {
545
546                         /* transport-change (started rolling) */
547                         
548                         if (_alignment_style == ExistingMaterial) {
549                                 
550                                 /* there are two delays happening:
551                                    
552                                    1) inbound, represented by _capture_offset
553                                    2) outbound, represented by _session.worst_output_latency()
554
555                                    the first sample to record occurs when the larger of these
556                                    two has elapsed, since they occur in parallel.
557
558                                    since we've already added _capture_offset, just add the
559                                    difference if _session.worst_output_latency() is larger.
560                                 */
561
562                                 if (_capture_offset < _session.worst_output_latency()) {
563                                         first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
564                                 } 
565                         } else {
566                                 first_recordable_frame += _roll_delay;
567                         }
568                         
569                 } else {
570
571                         /* punch in */
572
573                         if (_alignment_style == ExistingMaterial) {
574
575                                 /* There are two kinds of punch:
576                                    
577                                    manual punch in happens at the correct transport frame
578                                    because the user hit a button. but to get alignment correct 
579                                    we have to back up the position of the new region to the 
580                                    appropriate spot given the roll delay.
581
582                                    autopunch toggles recording at the precise
583                                    transport frame, and then the DS waits
584                                    to start recording for a time that depends
585                                    on the output latency.
586
587                                    XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
588
589                                 */
590
591                                 if (_capture_offset < _session.worst_output_latency()) {
592                                         /* see comment in ExistingMaterial block above */
593                                         first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
594                                 }
595
596                         } else {
597                                 capture_start_frame -= _roll_delay;
598                         }
599                 }
600                 
601                 prepare_record_status (capture_start_frame);
602
603         } else {
604
605                 if (last_possibly_recording == fully_rec_enabled) {
606
607                         /* we were recording last time */
608                         
609                         if (change & transport_rolling) {
610                                 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
611                                 
612                         } else {
613                                 /* punch out */
614                                 
615                                 last_recordable_frame = transport_frame + _capture_offset;
616                                 
617                                 if (_alignment_style == ExistingMaterial) {
618                                         if (_session.worst_output_latency() > _capture_offset) {
619                                                 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
620                                         }
621                                 } else {
622                                         last_recordable_frame += _roll_delay;
623                                 }
624                         }
625                 }
626         }
627
628         last_possibly_recording = possibly_recording;
629 }
630
631 void
632 Diskstream::route_going_away ()
633 {
634         _io.reset ();
635 }
636
637 void
638 Diskstream::calculate_record_range(OverlapType ot, sframes_t transport_frame, nframes_t nframes,
639                                    nframes_t& rec_nframes, nframes_t& rec_offset)
640 {
641         switch (ot) {
642         case OverlapNone:
643                 rec_nframes = 0;
644                 break;
645
646         case OverlapInternal:
647                 /*     ----------    recrange
648                          |---|       transrange
649                 */
650                 rec_nframes = nframes;
651                 rec_offset = 0;
652                 break;
653
654         case OverlapStart:
655                 /*    |--------|    recrange
656                 -----|          transrange
657                 */
658                 rec_nframes = transport_frame + nframes - first_recordable_frame;
659                 if (rec_nframes) {
660                         rec_offset = first_recordable_frame - transport_frame;
661                 }
662                 break;
663
664         case OverlapEnd:
665                 /*    |--------|    recrange
666                          |--------  transrange
667                 */
668                 rec_nframes = last_recordable_frame - transport_frame;
669                 rec_offset = 0;
670                 break;
671
672         case OverlapExternal:
673                 /*    |--------|    recrange
674                     --------------  transrange
675                 */
676                 rec_nframes = last_recordable_frame - first_recordable_frame;
677                 rec_offset = first_recordable_frame - transport_frame;
678                 break;
679         }
680 }
681
682 void
683 Diskstream::prepare_to_stop (framepos_t pos)
684 {
685         last_recordable_frame = pos + _capture_offset;
686 }