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