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