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