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