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/pannable.h"
50 #include "ardour/panner_shell.h"
51 #include "ardour/playlist.h"
52 #include "ardour/cycle_timer.h"
53 #include "ardour/region.h"
54 #include "ardour/panner.h"
55 #include "ardour/session.h"
56 #include "ardour/io.h"
57 #include "ardour/track.h"
63 using namespace ARDOUR;
66 /* XXX This goes uninitialized when there is no ~/.config/ardour3 directory.
67 * I can't figure out why, so this will do for now (just stole the
68 * default from configuration_vars.h). 0 is not a good value for
69 * allocating buffer sizes..
71 ARDOUR::framecnt_t Diskstream::disk_io_chunk_frames = 1024 * 256;
73 PBD::Signal0<void> Diskstream::DiskOverrun;
74 PBD::Signal0<void> Diskstream::DiskUnderrun;
76 Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
77 : SessionObject(sess, name)
78 , i_am_the_modifier (0)
81 , _visible_speed (1.0f)
82 , _actual_speed (1.0f)
83 , _buffer_reallocation_required (false)
84 , _seek_required (false)
85 , force_refill (false)
86 , capture_start_frame (0)
87 , capture_captured (0)
88 , was_recording (false)
89 , adjust_capture_position (0)
92 , first_recordable_frame (max_framepos)
93 , last_recordable_frame (max_framepos)
94 , last_possibly_recording (0)
95 , _alignment_style (ExistingMaterial)
100 , overwrite_offset (0)
101 , _pending_overwrite (false)
102 , overwrite_queued (false)
103 , wrap_buffer_size (0)
104 , speed_buffer_size (0)
106 , _target_speed (_speed)
108 , playback_sample (0)
109 , _read_data_count (0)
110 , _write_data_count (0)
111 , in_set_state (false)
112 , _persistent_alignment_style (ExistingMaterial)
113 , first_input_change (true)
119 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
120 : SessionObject(sess, "unnamed diskstream")
121 , i_am_the_modifier (0)
123 , _record_enabled (0)
124 , _visible_speed (1.0f)
125 , _actual_speed (1.0f)
126 , _buffer_reallocation_required (false)
127 , _seek_required (false)
128 , force_refill (false)
129 , capture_start_frame (0)
130 , capture_captured (0)
131 , was_recording (false)
132 , adjust_capture_position (0)
133 , _capture_offset (0)
135 , first_recordable_frame (max_framepos)
136 , last_recordable_frame (max_framepos)
137 , last_possibly_recording (0)
138 , _alignment_style (ExistingMaterial)
142 , overwrite_frame (0)
143 , overwrite_offset (0)
144 , _pending_overwrite (false)
145 , overwrite_queued (false)
146 , wrap_buffer_size (0)
147 , speed_buffer_size (0)
149 , _target_speed (_speed)
151 , playback_sample (0)
152 , _read_data_count (0)
153 , _write_data_count (0)
154 , in_set_state (false)
155 , _persistent_alignment_style (ExistingMaterial)
156 , first_input_change (true)
157 , _flags (Recordable)
161 Diskstream::~Diskstream ()
163 DEBUG_TRACE (DEBUG::Destruction, string_compose ("Diskstream %1 deleted\n", _name));
166 _playlist->release ();
171 Diskstream::set_track (Track* t)
174 _io = _track->input();
176 ic_connection.disconnect();
177 _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2));
179 input_change_pending = IOChange::ConfigurationChanged;
180 non_realtime_input_change ();
181 set_align_style_from_io ();
183 _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this));
187 Diskstream::handle_input_change (IOChange change, void * /*src*/)
189 Glib::Mutex::Lock lm (state_lock);
191 if (change.type & IOChange::ConfigurationChanged) {
192 if (!(input_change_pending.type & change.type)) {
193 input_change_pending.type = IOChange::Type (input_change_pending.type | change.type);
194 _session.request_input_change_handling ();
200 Diskstream::non_realtime_set_speed ()
202 if (_buffer_reallocation_required)
204 Glib::Mutex::Lock lm (state_lock);
205 allocate_temporary_buffers ();
207 _buffer_reallocation_required = false;
210 if (_seek_required) {
211 if (speed() != 1.0f || speed() != -1.0f) {
212 seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
215 seek (_session.transport_frame(), true);
218 _seek_required = false;
223 Diskstream::realtime_set_speed (double sp, bool global)
225 bool changed = false;
226 double new_speed = sp * _session.transport_speed();
228 if (_visible_speed != sp) {
233 if (new_speed != _actual_speed) {
235 framecnt_t required_wrap_size = (framecnt_t) floor (_session.get_block_size() *
236 fabs (new_speed)) + 1;
238 if (required_wrap_size > wrap_buffer_size) {
239 _buffer_reallocation_required = true;
242 _actual_speed = new_speed;
243 _target_speed = fabs(_actual_speed);
248 _seek_required = true;
250 SpeedChanged (); /* EMIT SIGNAL */
253 return _buffer_reallocation_required || _seek_required;
257 Diskstream::set_capture_offset ()
260 /* can't capture, so forget it */
264 _capture_offset = _io->latency();
268 Diskstream::set_align_style (AlignStyle a)
270 if (record_enabled() && _session.actively_recording()) {
274 if (a != _alignment_style) {
275 _alignment_style = a;
276 AlignmentStyleChanged ();
281 Diskstream::set_loop (Location *location)
284 if (location->start() >= location->end()) {
285 error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
290 loop_location = location;
292 LoopSet (location); /* EMIT SIGNAL */
296 /** Get the start position (in session frames) of the nth capture in the current pass */
298 Diskstream::get_capture_start_frame (uint32_t n) const
300 Glib::Mutex::Lock lm (capture_info_lock);
302 if (capture_info.size() > n) {
303 /* this is a completed capture */
304 return capture_info[n]->start;
306 /* this is the currently in-progress capture */
307 return capture_start_frame;
312 Diskstream::get_captured_frames (uint32_t n) const
314 Glib::Mutex::Lock lm (capture_info_lock);
316 if (capture_info.size() > n) {
317 /* this is a completed capture */
318 return capture_info[n]->frames;
320 /* this is the currently in-progress capture */
321 return capture_captured;
326 Diskstream::set_roll_delay (ARDOUR::framecnt_t nframes)
328 _roll_delay = nframes;
332 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
338 bool prior_playlist = false;
341 Glib::Mutex::Lock lm (state_lock);
343 if (playlist == _playlist) {
347 playlist_connections.drop_connections ();
350 _playlist->release();
351 prior_playlist = true;
354 _playlist = playlist;
357 if (!in_set_state && recordable()) {
358 reset_write_sources (false);
361 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
362 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
363 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1, _2));
366 /* don't do this if we've already asked for it *or* if we are setting up
367 the diskstream for the very first time - the input changed handling will
368 take care of the buffer refill.
371 if (!overwrite_queued && prior_playlist) {
372 _session.request_overwrite_buffer (_track);
373 overwrite_queued = true;
376 PlaylistChanged (); /* EMIT SIGNAL */
377 _session.set_dirty ();
383 Diskstream::playlist_changed (const PropertyChange&)
385 playlist_modified ();
389 Diskstream::playlist_modified ()
391 if (!i_am_the_modifier && !overwrite_queued) {
392 _session.request_overwrite_buffer (_track);
393 overwrite_queued = true;
398 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
400 boost::shared_ptr<Playlist> pl (wpl.lock());
402 if (pl == _playlist) {
404 /* this catches an ordering issue with session destruction. playlists
405 are destroyed before diskstreams. we have to invalidate any handles
406 we have to the playlist.
416 Diskstream::set_name (const string& str)
420 playlist()->set_name (str);
422 SessionObject::set_name(str);
424 if (!in_set_state && recordable()) {
425 /* rename existing capture files so that they have the correct name */
426 return rename_write_sources ();
436 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
438 /* If we're coming from an undo, it will have handled
439 automation undo (it must, since automation-follows-regions
440 can lose automation data). Hence we can do nothing here.
447 if (!_track || Config->get_automation_follows_regions () == false) {
451 list< Evoral::RangeMove<double> > movements;
453 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
454 i != movements_frames.end();
457 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
460 /* move panner automation */
461 boost::shared_ptr<Pannable> pannable = _track->pannable();
462 Evoral::ControlSet::Controls& c (pannable->controls());
464 for (Evoral::ControlSet::Controls::iterator ci = c.begin(); ci != c.end(); ++ci) {
465 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl>(ci->second);
469 boost::shared_ptr<AutomationList> alist = ac->alist();
471 XMLNode & before = alist->get_state ();
472 bool const things_moved = alist->move_ranges (movements);
474 _session.add_command (new MementoCommand<AutomationList> (
475 *alist.get(), &before, &alist->get_state ()));
479 /* move processor automation */
480 _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
484 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
486 boost::shared_ptr<Processor> processor (p.lock ());
491 list< Evoral::RangeMove<double> > movements;
492 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
493 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
496 set<Evoral::Parameter> const a = processor->what_can_be_automated ();
498 for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
499 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
500 XMLNode & before = al->get_state ();
501 bool const things_moved = al->move_ranges (movements);
503 _session.add_command (
504 new MementoCommand<AutomationList> (
505 *al.get(), &before, &al->get_state ()
513 Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
515 int possibly_recording;
518 const int transport_rolling = 0x4;
519 const int track_rec_enabled = 0x2;
520 const int global_rec_enabled = 0x1;
521 const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
523 /* merge together the 3 factors that affect record status, and compute
527 rolling = _session.transport_speed() != 0.0f;
528 possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
529 change = possibly_recording ^ last_possibly_recording;
531 if (possibly_recording == last_possibly_recording) {
534 if (possibly_recording == fully_rec_enabled) {
536 if (last_possibly_recording == fully_rec_enabled) {
540 /* we transitioned to recording. lets see if its transport based or a punch */
542 first_recordable_frame = transport_frame + _capture_offset;
543 last_recordable_frame = max_framepos;
544 capture_start_frame = transport_frame;
546 if (change & transport_rolling) {
548 /* transport-change (started rolling) */
550 if (_alignment_style == ExistingMaterial) {
552 /* there are two delays happening:
554 1) inbound, represented by _capture_offset
555 2) outbound, represented by _session.worst_output_latency()
557 the first sample to record occurs when the larger of these
558 two has elapsed, since they occur in parallel.
560 since we've already added _capture_offset, just add the
561 difference if _session.worst_output_latency() is larger.
564 if (_capture_offset < _session.worst_output_latency()) {
565 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
568 first_recordable_frame += _roll_delay;
575 if (_alignment_style == ExistingMaterial) {
577 /* There are two kinds of punch:
579 manual punch in happens at the correct transport frame
580 because the user hit a button. but to get alignment correct
581 we have to back up the position of the new region to the
582 appropriate spot given the roll delay.
584 autopunch toggles recording at the precise
585 transport frame, and then the DS waits
586 to start recording for a time that depends
587 on the output latency.
589 XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
593 if (_capture_offset < _session.worst_output_latency()) {
594 /* see comment in ExistingMaterial block above */
595 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
599 capture_start_frame -= _roll_delay;
603 prepare_record_status (capture_start_frame);
607 if (last_possibly_recording == fully_rec_enabled) {
609 /* we were recording last time */
611 if (change & transport_rolling) {
612 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
617 last_recordable_frame = transport_frame + _capture_offset;
619 if (_alignment_style == ExistingMaterial) {
620 if (_session.worst_output_latency() > _capture_offset) {
621 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
624 last_recordable_frame += _roll_delay;
630 last_possibly_recording = possibly_recording;
634 Diskstream::route_going_away ()
640 Diskstream::calculate_record_range(OverlapType ot, framepos_t transport_frame, framecnt_t nframes,
641 framecnt_t & rec_nframes, framecnt_t & rec_offset)
648 case OverlapInternal:
649 /* ---------- recrange
652 rec_nframes = nframes;
657 /* |--------| recrange
660 rec_nframes = transport_frame + nframes - first_recordable_frame;
662 rec_offset = first_recordable_frame - transport_frame;
667 /* |--------| recrange
670 rec_nframes = last_recordable_frame - transport_frame;
674 case OverlapExternal:
675 /* |--------| recrange
676 -------------- transrange
678 rec_nframes = last_recordable_frame - first_recordable_frame;
679 rec_offset = first_recordable_frame - transport_frame;
685 Diskstream::prepare_to_stop (framepos_t pos)
687 last_recordable_frame = pos + _capture_offset;