add and use Source::empty() since it can be done more efficiently than length(pos...
[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));
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)
440 {
441         if (!_track || Config->get_automation_follows_regions () == false) {
442                 return;
443         }
444
445         list< Evoral::RangeMove<double> > movements;
446
447         for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
448              i != movements_frames.end();
449              ++i) {
450
451                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
452         }
453
454         /* move panner automation */
455         boost::shared_ptr<Panner> p = _track->main_outs()->panner ();
456         if (p) {
457                 for (uint32_t i = 0; i < p->npanners (); ++i) {
458                         boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
459                         XMLNode & before = pan_alist->get_state ();
460                         pan_alist->move_ranges (movements);
461                         _session.add_command (new MementoCommand<AutomationList> (
462                                                       *pan_alist.get(), &before, &pan_alist->get_state ()));
463                 }
464         }
465
466         /* move processor automation */
467         _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
468 }
469
470 void
471 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
472 {
473         boost::shared_ptr<Processor> processor (p.lock ());
474         if (!processor) {
475                 return;
476         }
477
478         list< Evoral::RangeMove<double> > movements;
479         for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
480                    i != movements_frames.end(); ++i) {
481                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
482         }
483
484         set<Evoral::Parameter> const a = processor->what_can_be_automated ();
485
486         for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
487                 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
488                 XMLNode & before = al->get_state ();
489                 al->move_ranges (movements);
490                 _session.add_command (
491                         new MementoCommand<AutomationList> (
492                                 *al.get(), &before, &al->get_state ()
493                                 )
494                         );
495         }
496 }
497
498 void
499 Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*/, bool can_record)
500 {
501         int possibly_recording;
502         int rolling;
503         int change;
504         const int transport_rolling = 0x4;
505         const int track_rec_enabled = 0x2;
506         const int global_rec_enabled = 0x1;
507         const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
508
509         /* merge together the 3 factors that affect record status, and compute
510            what has changed.
511         */
512
513         rolling = _session.transport_speed() != 0.0f;
514         possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
515         change = possibly_recording ^ last_possibly_recording;
516
517         if (possibly_recording == last_possibly_recording) {
518                 return;
519         }
520         if (possibly_recording == fully_rec_enabled) {
521
522                 if (last_possibly_recording == fully_rec_enabled) {
523                         return;
524                 }
525
526                 /* we transitioned to recording. lets see if its transport based or a punch */
527                 
528                 first_recordable_frame = transport_frame + _capture_offset;
529                 last_recordable_frame = max_frames;
530                 capture_start_frame = transport_frame;
531
532                 if (change & transport_rolling) {
533
534                         /* transport-change (started rolling) */
535                         
536                         if (_alignment_style == ExistingMaterial) {
537                                 
538                                 /* there are two delays happening:
539                                    
540                                    1) inbound, represented by _capture_offset
541                                    2) outbound, represented by _session.worst_output_latency()
542
543                                    the first sample to record occurs when the larger of these
544                                    two has elapsed, since they occur in parallel.
545
546                                    since we've already added _capture_offset, just add the
547                                    difference if _session.worst_output_latency() is larger.
548                                 */
549
550                                 if (_capture_offset < _session.worst_output_latency()) {
551                                         first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
552                                 } 
553                         } else {
554                                 first_recordable_frame += _roll_delay;
555                         }
556                         
557                 } else {
558
559                         /* punch in */
560
561                         if (_alignment_style == ExistingMaterial) {
562
563                                 /* There are two kinds of punch:
564                                    
565                                    manual punch in happens at the correct transport frame
566                                    because the user hit a button. but to get alignment correct 
567                                    we have to back up the position of the new region to the 
568                                    appropriate spot given the roll delay.
569
570                                    autopunch toggles recording at the precise
571                                    transport frame, and then the DS waits
572                                    to start recording for a time that depends
573                                    on the output latency.
574
575                                    XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
576
577                                 */
578
579                                 if (_capture_offset < _session.worst_output_latency()) {
580                                         /* see comment in ExistingMaterial block above */
581                                         first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
582                                 }
583
584                         } else {
585                                 capture_start_frame -= _roll_delay;
586                         }
587                 }
588                 
589                 prepare_record_status (capture_start_frame);
590
591         } else {
592
593                 if (last_possibly_recording == fully_rec_enabled) {
594
595                         /* we were recording last time */
596                         
597                         if (change & transport_rolling) {
598                                 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
599                                 
600                         } else {
601                                 /* punch out */
602                                 
603                                 last_recordable_frame = transport_frame + _capture_offset;
604                                 
605                                 if (_alignment_style == ExistingMaterial) {
606                                         if (_session.worst_output_latency() > _capture_offset) {
607                                                 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
608                                         }
609                                 } else {
610                                         last_recordable_frame += _roll_delay;
611                                 }
612                         }
613                 }
614         }
615
616         last_possibly_recording = possibly_recording;
617 }
618
619 void
620 Diskstream::route_going_away ()
621 {
622         _io.reset ();
623 }
624
625 void
626 Diskstream::calculate_record_range(OverlapType ot, sframes_t transport_frame, nframes_t nframes,
627                                    nframes_t& rec_nframes, nframes_t& rec_offset)
628 {
629         switch (ot) {
630         case OverlapNone:
631                 rec_nframes = 0;
632                 break;
633
634         case OverlapInternal:
635                 /*     ----------    recrange
636                          |---|       transrange
637                 */
638                 rec_nframes = nframes;
639                 rec_offset = 0;
640                 break;
641
642         case OverlapStart:
643                 /*    |--------|    recrange
644                 -----|          transrange
645                 */
646                 rec_nframes = transport_frame + nframes - first_recordable_frame;
647                 if (rec_nframes) {
648                         rec_offset = first_recordable_frame - transport_frame;
649                 }
650                 break;
651
652         case OverlapEnd:
653                 /*    |--------|    recrange
654                          |--------  transrange
655                 */
656                 rec_nframes = last_recordable_frame - transport_frame;
657                 rec_offset = 0;
658                 break;
659
660         case OverlapExternal:
661                 /*    |--------|    recrange
662                     --------------  transrange
663                 */
664                 rec_nframes = last_recordable_frame - first_recordable_frame;
665                 rec_offset = first_recordable_frame - transport_frame;
666                 break;
667         }
668 }
669
670 void
671 Diskstream::prepare_to_stop (framepos_t pos)
672 {
673         last_recordable_frame = pos + _capture_offset;
674 }