fix for most (all? we can dream ...) issues involved in #4399 (editing multiply-appli...
[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 <glibmm/thread.h>
36
37 #include "pbd/error.h"
38 #include "pbd/basename.h"
39 #include "pbd/memento_command.h"
40 #include "pbd/xml++.h"
41 #include "pbd/stacktrace.h"
42
43 #include "ardour/ardour.h"
44 #include "ardour/audioengine.h"
45 #include "ardour/debug.h"
46 #include "ardour/diskstream.h"
47 #include "ardour/utils.h"
48 #include "ardour/configuration.h"
49 #include "ardour/audiofilesource.h"
50 #include "ardour/send.h"
51 #include "ardour/pannable.h"
52 #include "ardour/panner_shell.h"
53 #include "ardour/playlist.h"
54 #include "ardour/cycle_timer.h"
55 #include "ardour/region.h"
56 #include "ardour/panner.h"
57 #include "ardour/session.h"
58 #include "ardour/io.h"
59 #include "ardour/track.h"
60
61 #include "i18n.h"
62 #include <locale.h>
63
64 using namespace std;
65 using namespace ARDOUR;
66 using namespace PBD;
67
68 /* XXX This goes uninitialized when there is no ~/.config/ardour3 directory.
69  * I can't figure out why, so this will do for now (just stole the
70  * default from configuration_vars.h).  0 is not a good value for
71  * allocating buffer sizes..
72  */
73 ARDOUR::framecnt_t Diskstream::disk_io_chunk_frames = 1024 * 256 / sizeof (Sample);
74
75 PBD::Signal0<void>                Diskstream::DiskOverrun;
76 PBD::Signal0<void>                Diskstream::DiskUnderrun;
77
78 Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
79         : SessionObject(sess, name)
80         , i_am_the_modifier (0)
81         , _track (0)
82         , _record_enabled (0)
83         , _visible_speed (1.0f)
84         , _actual_speed (1.0f)
85         , _buffer_reallocation_required (false)
86         , _seek_required (false)
87         , capture_start_frame (0)
88         , capture_captured (0)
89         , was_recording (false)
90         , adjust_capture_position (0)
91         , _capture_offset (0)
92         , _roll_delay (0)
93         , first_recordable_frame (max_framepos)
94         , last_recordable_frame (max_framepos)
95         , last_possibly_recording (0)
96         , _alignment_style (ExistingMaterial)
97         , _alignment_choice (Automatic)
98         , _slaved (false)
99         , loop_location (0)
100         , overwrite_frame (0)
101         , overwrite_offset (0)
102         , _pending_overwrite (false)
103         , overwrite_queued (false)
104         , wrap_buffer_size (0)
105         , speed_buffer_size (0)
106         , _speed (1.0)
107         , _target_speed (_speed)
108         , file_frame (0)
109         , playback_sample (0)
110         , in_set_state (false)
111         , _flags (flag)
112         , deprecated_io_node (0)
113 {
114 }
115
116 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
117         : SessionObject(sess, "unnamed diskstream")
118         , i_am_the_modifier (0)
119         , _track (0)
120         , _record_enabled (0)
121         , _visible_speed (1.0f)
122         , _actual_speed (1.0f)
123         , _buffer_reallocation_required (false)
124         , _seek_required (false)
125         , capture_start_frame (0)
126         , capture_captured (0)
127         , was_recording (false)
128         , adjust_capture_position (0)
129         , _capture_offset (0)
130         , _roll_delay (0)
131         , first_recordable_frame (max_framepos)
132         , last_recordable_frame (max_framepos)
133         , last_possibly_recording (0)
134         , _alignment_style (ExistingMaterial)
135         , _alignment_choice (Automatic)
136         , _slaved (false)
137         , loop_location (0)
138         , overwrite_frame (0)
139         , overwrite_offset (0)
140         , _pending_overwrite (false)
141         , overwrite_queued (false)
142         , wrap_buffer_size (0)
143         , speed_buffer_size (0)
144         , _speed (1.0)
145         , _target_speed (_speed)
146         , file_frame (0)
147         , playback_sample (0)
148         , in_set_state (false)
149         , _flags (Recordable)
150         , deprecated_io_node (0)
151 {
152 }
153
154 Diskstream::~Diskstream ()
155 {
156         DEBUG_TRACE (DEBUG::Destruction, string_compose ("Diskstream %1 deleted\n", _name));
157
158         if (_playlist) {
159                 _playlist->release ();
160         }
161
162         delete deprecated_io_node;
163 }
164
165 void
166 Diskstream::set_track (Track* t)
167 {
168         _track = t;
169         _io = _track->input();
170
171         ic_connection.disconnect();
172         _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2));
173
174         if (_io->n_ports() != ChanCount::ZERO) {
175                 input_change_pending.type = IOChange::Type (IOChange::ConfigurationChanged|IOChange::ConnectionsChanged);
176                 non_realtime_input_change ();
177         }
178
179         _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this));
180 }
181
182 void
183 Diskstream::handle_input_change (IOChange change, void * /*src*/)
184 {
185         Glib::Mutex::Lock lm (state_lock);
186
187         if (change.type & (IOChange::ConfigurationChanged|IOChange::ConnectionsChanged)) {
188
189                 /* rather than handle this here on a DS-by-DS basis we defer to the
190                    session transport/butler thread, and let it tackle
191                    as many diskstreams as need it in one shot. this avoids many repeated
192                    takings of the audioengine process lock.
193                 */
194
195                 if (!(input_change_pending.type & change.type)) {
196                         input_change_pending.type = IOChange::Type (input_change_pending.type | change.type);
197                         _session.request_input_change_handling ();
198                 }
199         }
200 }
201
202 void
203 Diskstream::non_realtime_set_speed ()
204 {
205         if (_buffer_reallocation_required)
206         {
207                 Glib::Mutex::Lock lm (state_lock);
208                 allocate_temporary_buffers ();
209
210                 _buffer_reallocation_required = false;
211         }
212
213         if (_seek_required) {
214                 if (speed() != 1.0f || speed() != -1.0f) {
215                         seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
216                 }
217                 else {
218                         seek (_session.transport_frame(), true);
219                 }
220
221                 _seek_required = false;
222         }
223 }
224
225 bool
226 Diskstream::realtime_set_speed (double sp, bool global)
227 {
228         bool changed = false;
229         double new_speed = sp * _session.transport_speed();
230
231         if (_visible_speed != sp) {
232                 _visible_speed = sp;
233                 changed = true;
234         }
235
236         if (new_speed != _actual_speed) {
237
238                 framecnt_t required_wrap_size = (framecnt_t) floor (_session.get_block_size() *
239                                                                   fabs (new_speed)) + 1;
240
241                 if (required_wrap_size > wrap_buffer_size) {
242                         _buffer_reallocation_required = true;
243                 }
244
245                 _actual_speed = new_speed;
246                 _target_speed = fabs(_actual_speed);
247         }
248
249         if (changed) {
250                 if (!global) {
251                         _seek_required = true;
252                 }
253                 SpeedChanged (); /* EMIT SIGNAL */
254         }
255
256         return _buffer_reallocation_required || _seek_required;
257 }
258
259 void
260 Diskstream::set_capture_offset ()
261 {
262         if (_io == 0) {
263                 /* can't capture, so forget it */
264                 return;
265         }
266
267         _capture_offset = _io->latency();
268         DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: using IO latency, capture offset set to %2\n", name(), _capture_offset));
269 }
270
271
272 void
273 Diskstream::set_align_style (AlignStyle a, bool force)
274 {
275         if (record_enabled() && _session.actively_recording()) {
276                 return;
277         }
278
279         if ((a != _alignment_style) || force) {
280                 _alignment_style = a;
281                 AlignmentStyleChanged ();
282         }
283 }
284
285 void
286 Diskstream::set_align_choice (AlignChoice a, bool force)
287 {
288         if (record_enabled() && _session.actively_recording()) {
289                 return;
290         }
291
292         if ((a != _alignment_choice) || force) {
293                 _alignment_choice = a;
294
295                 switch (_alignment_choice) {
296                 case Automatic:
297                         set_align_style_from_io ();
298                         break;
299                 case UseExistingMaterial:
300                         set_align_style (ExistingMaterial);
301                         break;
302                 case UseCaptureTime:
303                         set_align_style (CaptureTime);
304                         break;
305                 }
306         }
307 }
308
309 int
310 Diskstream::set_loop (Location *location)
311 {
312         if (location) {
313                 if (location->start() >= location->end()) {
314                         error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
315                         return -1;
316                 }
317         }
318
319         loop_location = location;
320
321         LoopSet (location); /* EMIT SIGNAL */
322         return 0;
323 }
324
325 /** Get the start position (in session frames) of the nth capture in the current pass */
326 ARDOUR::framepos_t
327 Diskstream::get_capture_start_frame (uint32_t n) const
328 {
329         Glib::Mutex::Lock lm (capture_info_lock);
330
331         if (capture_info.size() > n) {
332                 /* this is a completed capture */
333                 return capture_info[n]->start;
334         } else {
335                 /* this is the currently in-progress capture */
336                 return capture_start_frame;
337         }
338 }
339
340 ARDOUR::framecnt_t
341 Diskstream::get_captured_frames (uint32_t n) const
342 {
343         Glib::Mutex::Lock lm (capture_info_lock);
344
345         if (capture_info.size() > n) {
346                 /* this is a completed capture */
347                 return capture_info[n]->frames;
348         } else {
349                 /* this is the currently in-progress capture */
350                 return capture_captured;
351         }
352 }
353
354 void
355 Diskstream::set_roll_delay (ARDOUR::framecnt_t nframes)
356 {
357         _roll_delay = nframes;
358 }
359
360 int
361 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
362 {
363         if (!playlist) {
364                 return 0;
365         }
366
367         bool prior_playlist = false;
368
369         {
370                 Glib::Mutex::Lock lm (state_lock);
371
372                 if (playlist == _playlist) {
373                         return 0;
374                 }
375
376                 playlist_connections.drop_connections ();
377
378                 if (_playlist) {
379                         _playlist->release();
380                         prior_playlist = true;
381                 }
382
383                 _playlist = playlist;
384                 _playlist->use();
385
386                 if (!in_set_state && recordable()) {
387                         reset_write_sources (false);
388                 }
389
390                 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
391                 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
392                 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1, _2));
393         }
394
395         /* don't do this if we've already asked for it *or* if we are setting up
396            the diskstream for the very first time - the input changed handling will
397            take care of the buffer refill.
398         */
399
400         if (!overwrite_queued && prior_playlist) {
401                 _session.request_overwrite_buffer (_track);
402                 overwrite_queued = true;
403         }
404
405         PlaylistChanged (); /* EMIT SIGNAL */
406         _session.set_dirty ();
407
408         return 0;
409 }
410
411 void
412 Diskstream::playlist_changed (const PropertyChange&)
413 {
414         playlist_modified ();
415 }
416
417 void
418 Diskstream::playlist_modified ()
419 {
420         if (!i_am_the_modifier && !overwrite_queued) {
421                 _session.request_overwrite_buffer (_track);
422                 overwrite_queued = true;
423         }
424 }
425
426 void
427 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
428 {
429         boost::shared_ptr<Playlist> pl (wpl.lock());
430
431         if (pl == _playlist) {
432
433                 /* this catches an ordering issue with session destruction. playlists
434                    are destroyed before diskstreams. we have to invalidate any handles
435                    we have to the playlist.
436                 */
437
438                 if (_playlist) {
439                         _playlist.reset ();
440                 }
441         }
442 }
443
444 bool
445 Diskstream::set_name (const string& str)
446 {
447         if (_name != str) {
448                 assert(playlist());
449                 playlist()->set_name (str);
450                 SessionObject::set_name(str);
451         }
452         return true;
453 }
454
455 XMLNode&
456 Diskstream::get_state ()
457 {
458         XMLNode* node = new XMLNode ("Diskstream");
459         char buf[64];
460         LocaleGuard lg (X_("POSIX"));
461
462         node->add_property ("flags", enum_2_string (_flags));
463         node->add_property ("playlist", _playlist->name());
464         node->add_property("name", _name);
465         id().print (buf, sizeof (buf));
466         node->add_property("id", buf);
467         snprintf (buf, sizeof(buf), "%f", _visible_speed);
468         node->add_property ("speed", buf);
469         node->add_property ("capture-alignment", enum_2_string (_alignment_choice));
470
471         if (_extra_xml) {
472                 node->add_child_copy (*_extra_xml);
473         }
474
475         return *node;
476 }
477
478 int
479 Diskstream::set_state (const XMLNode& node, int /*version*/)
480 {
481         const XMLProperty* prop;
482
483         if ((prop = node.property ("name")) != 0) {
484                 _name = prop->value();
485         }
486
487         if (deprecated_io_node) {
488                 set_id (*deprecated_io_node);
489         } else {
490                 set_id (node);
491         }
492
493         if ((prop = node.property ("flags")) != 0) {
494                 _flags = Flag (string_2_enum (prop->value(), _flags));
495         }
496
497         if ((prop = node.property (X_("capture-alignment"))) != 0) {
498                 set_align_choice (AlignChoice (string_2_enum (prop->value(), _alignment_choice)), true);
499         } else {
500                 set_align_choice (Automatic, true);
501         }
502
503         if ((prop = node.property ("playlist")) == 0) {
504                 return -1;
505         }
506
507         if (find_and_use_playlist (prop->value())) {
508                 return -1;
509         }
510
511         if ((prop = node.property ("speed")) != 0) {
512                 double sp = atof (prop->value().c_str());
513
514                 if (realtime_set_speed (sp, false)) {
515                         non_realtime_set_speed ();
516                 }
517         }
518
519         return 0;
520 }
521
522 void
523 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
524 {
525         /* If we're coming from an undo, it will have handled
526            automation undo (it must, since automation-follows-regions
527            can lose automation data).  Hence we can do nothing here.
528         */
529
530         if (from_undo) {
531                 return;
532         }
533
534         if (!_track || Config->get_automation_follows_regions () == false) {
535                 return;
536         }
537
538         list< Evoral::RangeMove<double> > movements;
539
540         for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
541              i != movements_frames.end();
542              ++i) {
543
544                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
545         }
546
547         /* move panner automation */
548         boost::shared_ptr<Pannable> pannable = _track->pannable();
549         Evoral::ControlSet::Controls& c (pannable->controls());
550
551         for (Evoral::ControlSet::Controls::iterator ci = c.begin(); ci != c.end(); ++ci) {
552                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl>(ci->second);
553                 if (!ac) {
554                         continue;
555                 }
556                 boost::shared_ptr<AutomationList> alist = ac->alist();
557
558                 XMLNode & before = alist->get_state ();
559                 bool const things_moved = alist->move_ranges (movements);
560                 if (things_moved) {
561                         _session.add_command (new MementoCommand<AutomationList> (
562                                                       *alist.get(), &before, &alist->get_state ()));
563                 }
564         }
565
566         /* move processor automation */
567         _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
568 }
569
570 void
571 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
572 {
573         boost::shared_ptr<Processor> processor (p.lock ());
574         if (!processor) {
575                 return;
576         }
577
578         list< Evoral::RangeMove<double> > movements;
579         for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
580                 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
581         }
582
583         set<Evoral::Parameter> const a = processor->what_can_be_automated ();
584
585         for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
586                 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
587                 XMLNode & before = al->get_state ();
588                 bool const things_moved = al->move_ranges (movements);
589                 if (things_moved) {
590                         _session.add_command (
591                                 new MementoCommand<AutomationList> (
592                                         *al.get(), &before, &al->get_state ()
593                                         )
594                                 );
595                 }
596         }
597 }
598
599 void
600 Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
601 {
602         int possibly_recording;
603         int rolling;
604         int change;
605         const int transport_rolling = 0x4;
606         const int track_rec_enabled = 0x2;
607         const int global_rec_enabled = 0x1;
608         const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
609
610         /* merge together the 3 factors that affect record status, and compute
611            what has changed.
612         */
613
614         rolling = _session.transport_speed() != 0.0f;
615         possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
616         change = possibly_recording ^ last_possibly_recording;
617
618         if (possibly_recording == last_possibly_recording) {
619                 return;
620         }
621
622         framecnt_t existing_material_offset = _session.worst_playback_latency();
623
624         if (possibly_recording == fully_rec_enabled) {
625
626                 if (last_possibly_recording == fully_rec_enabled) {
627                         return;
628                 }
629
630                 capture_start_frame = _session.transport_frame();
631                 first_recordable_frame = capture_start_frame + _capture_offset;
632                 last_recordable_frame = max_framepos;
633
634                 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %7 (%9) FRF = %2 CSF = %4 CO = %5, EMO = %6 RD = %8 WOL %10 WTL %11\n",
635                                                                       name(), first_recordable_frame, last_recordable_frame, capture_start_frame,
636                                                                       _capture_offset,
637                                                                       existing_material_offset,
638                                                                       transport_frame,
639                                                                       _roll_delay,
640                                                                       _session.transport_frame(),
641                                                                       _session.worst_output_latency(),
642                                                                       _session.worst_track_latency()));
643
644
645                 if (_alignment_style == ExistingMaterial) {
646                         first_recordable_frame += existing_material_offset;
647                         DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tshift FRF by EMO %1\n",
648                                                                               first_recordable_frame));
649                 }
650
651                 prepare_record_status (capture_start_frame);
652
653         } else {
654
655                 if (last_possibly_recording == fully_rec_enabled) {
656
657                         /* we were recording last time */
658
659                         if (change & transport_rolling) {
660
661                                 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop(). We
662                                    had to set it there because we likely rolled past the stopping point to declick out,
663                                    and then backed up.
664                                  */
665
666                         } else {
667                                 /* punch out */
668
669                                 last_recordable_frame = _session.transport_frame() + _capture_offset;
670
671                                 if (_alignment_style == ExistingMaterial) {
672                                         last_recordable_frame += existing_material_offset;
673                                 }
674                         }
675                 }
676         }
677
678         last_possibly_recording = possibly_recording;
679 }
680
681 void
682 Diskstream::route_going_away ()
683 {
684         _io.reset ();
685 }
686
687 void
688 Diskstream::calculate_record_range(OverlapType ot, framepos_t transport_frame, framecnt_t nframes,
689                                    framecnt_t & rec_nframes, framecnt_t & rec_offset)
690 {
691         switch (ot) {
692         case OverlapNone:
693                 rec_nframes = 0;
694                 break;
695
696         case OverlapInternal:
697                 /*     ----------    recrange
698                          |---|       transrange
699                 */
700                 rec_nframes = nframes;
701                 rec_offset = 0;
702                 break;
703
704         case OverlapStart:
705                 /*    |--------|    recrange
706                 -----|          transrange
707                 */
708                 rec_nframes = transport_frame + nframes - first_recordable_frame;
709                 if (rec_nframes) {
710                         rec_offset = first_recordable_frame - transport_frame;
711                 }
712                 break;
713
714         case OverlapEnd:
715                 /*    |--------|    recrange
716                          |--------  transrange
717                 */
718                 rec_nframes = last_recordable_frame - transport_frame;
719                 rec_offset = 0;
720                 break;
721
722         case OverlapExternal:
723                 /*    |--------|    recrange
724                     --------------  transrange
725                 */
726                 rec_nframes = last_recordable_frame - first_recordable_frame;
727                 rec_offset = first_recordable_frame - transport_frame;
728                 break;
729         }
730
731         DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 rec? %2 @ %3 (for %4) FRF %5 LRF %6 : rf %7 @ %8\n",
732                                                               _name, enum_2_string (ot), transport_frame, nframes,
733                                                               first_recordable_frame, last_recordable_frame, rec_nframes, rec_offset));
734 }
735
736 void
737 Diskstream::prepare_to_stop (framepos_t pos)
738 {
739         last_recordable_frame = pos + _capture_offset;
740 }