2 Copyright (C) 2000-2006 Paul Davis
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.
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.
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.
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"
41 #include "ardour/ardour.h"
42 #include "ardour/audioengine.h"
43 #include "ardour/debug.h"
44 #include "ardour/diskstream.h"
45 #include "ardour/utils.h"
46 #include "ardour/configuration.h"
47 #include "ardour/audiofilesource.h"
48 #include "ardour/send.h"
49 #include "ardour/playlist.h"
50 #include "ardour/cycle_timer.h"
51 #include "ardour/region.h"
52 #include "ardour/panner.h"
53 #include "ardour/session.h"
54 #include "ardour/io.h"
55 #include "ardour/track.h"
61 using namespace ARDOUR;
64 /* XXX This goes uninitialized when there is no ~/.config/ardour3 directory.
65 * I can't figure out why, so this will do for now (just stole the
66 * default from configuration_vars.h). 0 is not a good value for
67 * allocating buffer sizes..
69 ARDOUR::nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256;
71 PBD::Signal0<void> Diskstream::DiskOverrun;
72 PBD::Signal0<void> Diskstream::DiskUnderrun;
74 Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
75 : SessionObject(sess, name)
76 , i_am_the_modifier (0)
79 , _visible_speed (1.0f)
80 , _actual_speed (1.0f)
81 , _buffer_reallocation_required (false)
82 , _seek_required (false)
83 , force_refill (false)
84 , capture_start_frame (0)
85 , capture_captured (0)
86 , was_recording (false)
87 , adjust_capture_position (0)
90 , first_recordable_frame (max_frames)
91 , last_recordable_frame (max_frames)
92 , last_possibly_recording (0)
93 , _alignment_style (ExistingMaterial)
98 , overwrite_offset (0)
99 , _pending_overwrite (false)
100 , overwrite_queued (false)
101 , wrap_buffer_size (0)
102 , speed_buffer_size (0)
104 , _target_speed (_speed)
106 , playback_sample (0)
107 , playback_distance (0)
108 , _read_data_count (0)
109 , _write_data_count (0)
110 , in_set_state (false)
111 , _persistent_alignment_style (ExistingMaterial)
112 , first_input_change (true)
114 , scrub_buffer_size (0)
121 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
122 : SessionObject(sess, "unnamed diskstream")
123 , i_am_the_modifier (0)
125 , _record_enabled (0)
126 , _visible_speed (1.0f)
127 , _actual_speed (1.0f)
128 , _buffer_reallocation_required (false)
129 , _seek_required (false)
130 , force_refill (false)
131 , capture_start_frame (0)
132 , capture_captured (0)
133 , was_recording (false)
134 , adjust_capture_position (0)
135 , _capture_offset (0)
137 , first_recordable_frame (max_frames)
138 , last_recordable_frame (max_frames)
139 , last_possibly_recording (0)
140 , _alignment_style (ExistingMaterial)
144 , overwrite_frame (0)
145 , overwrite_offset (0)
146 , _pending_overwrite (false)
147 , overwrite_queued (false)
148 , wrap_buffer_size (0)
149 , speed_buffer_size (0)
151 , _target_speed (_speed)
153 , playback_sample (0)
154 , playback_distance (0)
155 , _read_data_count (0)
156 , _write_data_count (0)
157 , in_set_state (false)
158 , _persistent_alignment_style (ExistingMaterial)
159 , first_input_change (true)
161 , scrub_buffer_size (0)
163 , _flags (Recordable)
167 Diskstream::~Diskstream ()
169 DEBUG_TRACE (DEBUG::Destruction, string_compose ("Diskstream %1 deleted\n", _name));
172 _playlist->release ();
177 Diskstream::set_track (Track* t)
180 _io = _track->input();
182 ic_connection.disconnect();
183 _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2));
185 input_change_pending = IOChange::ConfigurationChanged;
186 non_realtime_input_change ();
187 set_align_style_from_io ();
189 _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this));
193 Diskstream::handle_input_change (IOChange change, void * /*src*/)
195 Glib::Mutex::Lock lm (state_lock);
197 if (!(input_change_pending.type & change.type)) {
198 input_change_pending.type = IOChange::Type (input_change_pending.type | change.type);
199 _session.request_input_change_handling ();
204 Diskstream::non_realtime_set_speed ()
206 if (_buffer_reallocation_required)
208 Glib::Mutex::Lock lm (state_lock);
209 allocate_temporary_buffers ();
211 _buffer_reallocation_required = false;
214 if (_seek_required) {
215 if (speed() != 1.0f || speed() != -1.0f) {
216 seek ((nframes_t) (_session.transport_frame() * (double) speed()), true);
219 seek (_session.transport_frame(), true);
222 _seek_required = false;
227 Diskstream::realtime_set_speed (double sp, bool global)
229 bool changed = false;
230 double new_speed = sp * _session.transport_speed();
232 if (_visible_speed != sp) {
237 if (new_speed != _actual_speed) {
239 nframes_t required_wrap_size = (nframes_t) floor (_session.get_block_size() *
240 fabs (new_speed)) + 1;
242 if (required_wrap_size > wrap_buffer_size) {
243 _buffer_reallocation_required = true;
246 _actual_speed = new_speed;
247 _target_speed = fabs(_actual_speed);
252 _seek_required = true;
254 SpeedChanged (); /* EMIT SIGNAL */
257 return _buffer_reallocation_required || _seek_required;
261 Diskstream::set_capture_offset ()
264 /* can't capture, so forget it */
268 _capture_offset = _io->latency();
272 Diskstream::set_align_style (AlignStyle a)
274 if (record_enabled() && _session.actively_recording()) {
278 if (a != _alignment_style) {
279 _alignment_style = a;
280 AlignmentStyleChanged ();
285 Diskstream::set_loop (Location *location)
288 if (location->start() >= location->end()) {
289 error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
294 loop_location = location;
296 LoopSet (location); /* EMIT SIGNAL */
301 Diskstream::get_capture_start_frame (uint32_t n)
303 Glib::Mutex::Lock lm (capture_info_lock);
305 if (capture_info.size() > n) {
306 return capture_info[n]->start;
309 return capture_start_frame;
314 Diskstream::get_captured_frames (uint32_t n)
316 Glib::Mutex::Lock lm (capture_info_lock);
318 if (capture_info.size() > n) {
319 return capture_info[n]->frames;
322 return capture_captured;
327 Diskstream::set_roll_delay (ARDOUR::nframes_t nframes)
329 _roll_delay = nframes;
333 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
339 bool prior_playlist = false;
342 Glib::Mutex::Lock lm (state_lock);
344 if (playlist == _playlist) {
348 playlist_connections.drop_connections ();
351 _playlist->release();
352 prior_playlist = true;
355 _playlist = playlist;
358 if (!in_set_state && recordable()) {
359 reset_write_sources (false);
362 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
363 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
364 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1, _2));
367 /* don't do this if we've already asked for it *or* if we are setting up
368 the diskstream for the very first time - the input changed handling will
369 take care of the buffer refill.
372 if (!overwrite_queued && prior_playlist) {
373 _session.request_overwrite_buffer (_track);
374 overwrite_queued = true;
377 PlaylistChanged (); /* EMIT SIGNAL */
378 _session.set_dirty ();
384 Diskstream::playlist_changed (const PropertyChange&)
386 playlist_modified ();
390 Diskstream::playlist_modified ()
392 if (!i_am_the_modifier && !overwrite_queued) {
393 _session.request_overwrite_buffer (_track);
394 overwrite_queued = true;
399 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
401 boost::shared_ptr<Playlist> pl (wpl.lock());
403 if (pl == _playlist) {
405 /* this catches an ordering issue with session destruction. playlists
406 are destroyed before diskstreams. we have to invalidate any handles
407 we have to the playlist.
417 Diskstream::set_name (const string& str)
421 playlist()->set_name (str);
423 SessionObject::set_name(str);
425 if (!in_set_state && recordable()) {
426 /* rename existing capture files so that they have the correct name */
427 return rename_write_sources ();
437 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
439 /* If we're coming from an undo, it will have handled
440 automation undo (it must, since automation-follows-regions
441 can lose automation data). Hence we can do nothing here.
448 if (!_track || Config->get_automation_follows_regions () == false) {
452 list< Evoral::RangeMove<double> > movements;
454 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
455 i != movements_frames.end();
458 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
461 /* move panner automation */
462 boost::shared_ptr<Panner> p = _track->main_outs()->panner ();
464 for (uint32_t i = 0; i < p->npanners (); ++i) {
465 boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
466 XMLNode & before = pan_alist->get_state ();
467 bool const things_moved = pan_alist->move_ranges (movements);
469 _session.add_command (new MementoCommand<AutomationList> (
470 *pan_alist.get(), &before, &pan_alist->get_state ()));
475 /* move processor automation */
476 _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
480 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
482 boost::shared_ptr<Processor> processor (p.lock ());
487 list< Evoral::RangeMove<double> > movements;
488 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
489 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
492 set<Evoral::Parameter> const a = processor->what_can_be_automated ();
494 for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
495 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
496 XMLNode & before = al->get_state ();
497 bool const things_moved = al->move_ranges (movements);
499 _session.add_command (
500 new MementoCommand<AutomationList> (
501 *al.get(), &before, &al->get_state ()
509 Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*/, bool can_record)
511 int possibly_recording;
514 const int transport_rolling = 0x4;
515 const int track_rec_enabled = 0x2;
516 const int global_rec_enabled = 0x1;
517 const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
519 /* merge together the 3 factors that affect record status, and compute
523 rolling = _session.transport_speed() != 0.0f;
524 possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
525 change = possibly_recording ^ last_possibly_recording;
527 if (possibly_recording == last_possibly_recording) {
530 if (possibly_recording == fully_rec_enabled) {
532 if (last_possibly_recording == fully_rec_enabled) {
536 /* we transitioned to recording. lets see if its transport based or a punch */
538 first_recordable_frame = transport_frame + _capture_offset;
539 last_recordable_frame = max_frames;
540 capture_start_frame = transport_frame;
542 if (change & transport_rolling) {
544 /* transport-change (started rolling) */
546 if (_alignment_style == ExistingMaterial) {
548 /* there are two delays happening:
550 1) inbound, represented by _capture_offset
551 2) outbound, represented by _session.worst_output_latency()
553 the first sample to record occurs when the larger of these
554 two has elapsed, since they occur in parallel.
556 since we've already added _capture_offset, just add the
557 difference if _session.worst_output_latency() is larger.
560 if (_capture_offset < _session.worst_output_latency()) {
561 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
564 first_recordable_frame += _roll_delay;
571 if (_alignment_style == ExistingMaterial) {
573 /* There are two kinds of punch:
575 manual punch in happens at the correct transport frame
576 because the user hit a button. but to get alignment correct
577 we have to back up the position of the new region to the
578 appropriate spot given the roll delay.
580 autopunch toggles recording at the precise
581 transport frame, and then the DS waits
582 to start recording for a time that depends
583 on the output latency.
585 XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
589 if (_capture_offset < _session.worst_output_latency()) {
590 /* see comment in ExistingMaterial block above */
591 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
595 capture_start_frame -= _roll_delay;
599 prepare_record_status (capture_start_frame);
603 if (last_possibly_recording == fully_rec_enabled) {
605 /* we were recording last time */
607 if (change & transport_rolling) {
608 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
613 last_recordable_frame = transport_frame + _capture_offset;
615 if (_alignment_style == ExistingMaterial) {
616 if (_session.worst_output_latency() > _capture_offset) {
617 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
620 last_recordable_frame += _roll_delay;
626 last_possibly_recording = possibly_recording;
630 Diskstream::route_going_away ()
636 Diskstream::calculate_record_range(OverlapType ot, sframes_t transport_frame, nframes_t nframes,
637 nframes_t& rec_nframes, nframes_t& rec_offset)
644 case OverlapInternal:
645 /* ---------- recrange
648 rec_nframes = nframes;
653 /* |--------| recrange
656 rec_nframes = transport_frame + nframes - first_recordable_frame;
658 rec_offset = first_recordable_frame - transport_frame;
663 /* |--------| recrange
666 rec_nframes = last_recordable_frame - transport_frame;
670 case OverlapExternal:
671 /* |--------| recrange
672 -------------- transrange
674 rec_nframes = last_recordable_frame - first_recordable_frame;
675 rec_offset = first_recordable_frame - transport_frame;
681 Diskstream::prepare_to_stop (framepos_t pos)
683 last_recordable_frame = pos + _capture_offset;