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 , playback_distance (0)
110 , _read_data_count (0)
111 , _write_data_count (0)
112 , in_set_state (false)
113 , _persistent_alignment_style (ExistingMaterial)
114 , first_input_change (true)
120 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
121 : SessionObject(sess, "unnamed diskstream")
122 , i_am_the_modifier (0)
124 , _record_enabled (0)
125 , _visible_speed (1.0f)
126 , _actual_speed (1.0f)
127 , _buffer_reallocation_required (false)
128 , _seek_required (false)
129 , force_refill (false)
130 , capture_start_frame (0)
131 , capture_captured (0)
132 , was_recording (false)
133 , adjust_capture_position (0)
134 , _capture_offset (0)
136 , first_recordable_frame (max_framepos)
137 , last_recordable_frame (max_framepos)
138 , last_possibly_recording (0)
139 , _alignment_style (ExistingMaterial)
143 , overwrite_frame (0)
144 , overwrite_offset (0)
145 , _pending_overwrite (false)
146 , overwrite_queued (false)
147 , wrap_buffer_size (0)
148 , speed_buffer_size (0)
150 , _target_speed (_speed)
152 , playback_sample (0)
153 , playback_distance (0)
154 , _read_data_count (0)
155 , _write_data_count (0)
156 , in_set_state (false)
157 , _persistent_alignment_style (ExistingMaterial)
158 , first_input_change (true)
159 , _flags (Recordable)
163 Diskstream::~Diskstream ()
165 DEBUG_TRACE (DEBUG::Destruction, string_compose ("Diskstream %1 deleted\n", _name));
168 _playlist->release ();
173 Diskstream::set_track (Track* t)
176 _io = _track->input();
178 ic_connection.disconnect();
179 _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2));
181 input_change_pending = IOChange::ConfigurationChanged;
182 non_realtime_input_change ();
183 set_align_style_from_io ();
185 _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this));
189 Diskstream::handle_input_change (IOChange change, void * /*src*/)
191 Glib::Mutex::Lock lm (state_lock);
193 if (change.type & IOChange::ConfigurationChanged) {
194 if (!(input_change_pending.type & change.type)) {
195 input_change_pending.type = IOChange::Type (input_change_pending.type | change.type);
196 _session.request_input_change_handling ();
202 Diskstream::non_realtime_set_speed ()
204 if (_buffer_reallocation_required)
206 Glib::Mutex::Lock lm (state_lock);
207 allocate_temporary_buffers ();
209 _buffer_reallocation_required = false;
212 if (_seek_required) {
213 if (speed() != 1.0f || speed() != -1.0f) {
214 seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
217 seek (_session.transport_frame(), true);
220 _seek_required = false;
225 Diskstream::realtime_set_speed (double sp, bool global)
227 bool changed = false;
228 double new_speed = sp * _session.transport_speed();
230 if (_visible_speed != sp) {
235 if (new_speed != _actual_speed) {
237 framecnt_t required_wrap_size = (framecnt_t) floor (_session.get_block_size() *
238 fabs (new_speed)) + 1;
240 if (required_wrap_size > wrap_buffer_size) {
241 _buffer_reallocation_required = true;
244 _actual_speed = new_speed;
245 _target_speed = fabs(_actual_speed);
250 _seek_required = true;
252 SpeedChanged (); /* EMIT SIGNAL */
255 return _buffer_reallocation_required || _seek_required;
259 Diskstream::set_capture_offset ()
262 /* can't capture, so forget it */
266 _capture_offset = _io->latency();
270 Diskstream::set_align_style (AlignStyle a)
272 if (record_enabled() && _session.actively_recording()) {
276 if (a != _alignment_style) {
277 _alignment_style = a;
278 AlignmentStyleChanged ();
283 Diskstream::set_loop (Location *location)
286 if (location->start() >= location->end()) {
287 error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
292 loop_location = location;
294 LoopSet (location); /* EMIT SIGNAL */
298 /** Get the start position (in session frames) of the nth capture in the current pass */
300 Diskstream::get_capture_start_frame (uint32_t n) const
302 Glib::Mutex::Lock lm (capture_info_lock);
304 if (capture_info.size() > n) {
305 /* this is a completed capture */
306 return capture_info[n]->start;
308 /* this is the currently in-progress capture */
309 return capture_start_frame;
314 Diskstream::get_captured_frames (uint32_t n) const
316 Glib::Mutex::Lock lm (capture_info_lock);
318 if (capture_info.size() > n) {
319 /* this is a completed capture */
320 return capture_info[n]->frames;
322 /* this is the currently in-progress capture */
323 return capture_captured;
328 Diskstream::set_roll_delay (ARDOUR::framecnt_t nframes)
330 _roll_delay = nframes;
334 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
340 bool prior_playlist = false;
343 Glib::Mutex::Lock lm (state_lock);
345 if (playlist == _playlist) {
349 playlist_connections.drop_connections ();
352 _playlist->release();
353 prior_playlist = true;
356 _playlist = playlist;
359 if (!in_set_state && recordable()) {
360 reset_write_sources (false);
363 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
364 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
365 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1, _2));
368 /* don't do this if we've already asked for it *or* if we are setting up
369 the diskstream for the very first time - the input changed handling will
370 take care of the buffer refill.
373 if (!overwrite_queued && prior_playlist) {
374 _session.request_overwrite_buffer (_track);
375 overwrite_queued = true;
378 PlaylistChanged (); /* EMIT SIGNAL */
379 _session.set_dirty ();
385 Diskstream::playlist_changed (const PropertyChange&)
387 playlist_modified ();
391 Diskstream::playlist_modified ()
393 if (!i_am_the_modifier && !overwrite_queued) {
394 _session.request_overwrite_buffer (_track);
395 overwrite_queued = true;
400 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
402 boost::shared_ptr<Playlist> pl (wpl.lock());
404 if (pl == _playlist) {
406 /* this catches an ordering issue with session destruction. playlists
407 are destroyed before diskstreams. we have to invalidate any handles
408 we have to the playlist.
418 Diskstream::set_name (const string& str)
422 playlist()->set_name (str);
424 SessionObject::set_name(str);
426 if (!in_set_state && recordable()) {
427 /* rename existing capture files so that they have the correct name */
428 return rename_write_sources ();
438 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
440 /* If we're coming from an undo, it will have handled
441 automation undo (it must, since automation-follows-regions
442 can lose automation data). Hence we can do nothing here.
449 if (!_track || Config->get_automation_follows_regions () == false) {
453 list< Evoral::RangeMove<double> > movements;
455 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
456 i != movements_frames.end();
459 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
462 /* move panner automation */
463 boost::shared_ptr<Pannable> pannable = _track->pannable();
464 Evoral::ControlSet::Controls& c (pannable->controls());
466 for (Evoral::ControlSet::Controls::iterator ci = c.begin(); ci != c.end(); ++ci) {
467 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl>(ci->second);
471 boost::shared_ptr<AutomationList> alist = ac->alist();
473 XMLNode & before = alist->get_state ();
474 bool const things_moved = alist->move_ranges (movements);
476 _session.add_command (new MementoCommand<AutomationList> (
477 *alist.get(), &before, &alist->get_state ()));
481 /* move processor automation */
482 _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
486 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
488 boost::shared_ptr<Processor> processor (p.lock ());
493 list< Evoral::RangeMove<double> > movements;
494 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
495 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
498 set<Evoral::Parameter> const a = processor->what_can_be_automated ();
500 for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
501 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
502 XMLNode & before = al->get_state ();
503 bool const things_moved = al->move_ranges (movements);
505 _session.add_command (
506 new MementoCommand<AutomationList> (
507 *al.get(), &before, &al->get_state ()
515 Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
517 int possibly_recording;
520 const int transport_rolling = 0x4;
521 const int track_rec_enabled = 0x2;
522 const int global_rec_enabled = 0x1;
523 const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
525 /* merge together the 3 factors that affect record status, and compute
529 rolling = _session.transport_speed() != 0.0f;
530 possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
531 change = possibly_recording ^ last_possibly_recording;
533 if (possibly_recording == last_possibly_recording) {
536 if (possibly_recording == fully_rec_enabled) {
538 if (last_possibly_recording == fully_rec_enabled) {
542 /* we transitioned to recording. lets see if its transport based or a punch */
544 first_recordable_frame = transport_frame + _capture_offset;
545 last_recordable_frame = max_framepos;
546 capture_start_frame = transport_frame;
548 if (change & transport_rolling) {
550 /* transport-change (started rolling) */
552 if (_alignment_style == ExistingMaterial) {
554 /* there are two delays happening:
556 1) inbound, represented by _capture_offset
557 2) outbound, represented by _session.worst_output_latency()
559 the first sample to record occurs when the larger of these
560 two has elapsed, since they occur in parallel.
562 since we've already added _capture_offset, just add the
563 difference if _session.worst_output_latency() is larger.
566 if (_capture_offset < _session.worst_output_latency()) {
567 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
570 first_recordable_frame += _roll_delay;
577 if (_alignment_style == ExistingMaterial) {
579 /* There are two kinds of punch:
581 manual punch in happens at the correct transport frame
582 because the user hit a button. but to get alignment correct
583 we have to back up the position of the new region to the
584 appropriate spot given the roll delay.
586 autopunch toggles recording at the precise
587 transport frame, and then the DS waits
588 to start recording for a time that depends
589 on the output latency.
591 XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
595 if (_capture_offset < _session.worst_output_latency()) {
596 /* see comment in ExistingMaterial block above */
597 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
601 capture_start_frame -= _roll_delay;
605 prepare_record_status (capture_start_frame);
609 if (last_possibly_recording == fully_rec_enabled) {
611 /* we were recording last time */
613 if (change & transport_rolling) {
614 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
619 last_recordable_frame = transport_frame + _capture_offset;
621 if (_alignment_style == ExistingMaterial) {
622 if (_session.worst_output_latency() > _capture_offset) {
623 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
626 last_recordable_frame += _roll_delay;
632 last_possibly_recording = possibly_recording;
636 Diskstream::route_going_away ()
642 Diskstream::calculate_record_range(OverlapType ot, framepos_t transport_frame, framecnt_t nframes,
643 framecnt_t & rec_nframes, framecnt_t & rec_offset)
650 case OverlapInternal:
651 /* ---------- recrange
654 rec_nframes = nframes;
659 /* |--------| recrange
662 rec_nframes = transport_frame + nframes - first_recordable_frame;
664 rec_offset = first_recordable_frame - transport_frame;
669 /* |--------| recrange
672 rec_nframes = last_recordable_frame - transport_frame;
676 case OverlapExternal:
677 /* |--------| recrange
678 -------------- transrange
680 rec_nframes = last_recordable_frame - first_recordable_frame;
681 rec_offset = first_recordable_frame - transport_frame;
687 Diskstream::prepare_to_stop (framepos_t pos)
689 last_recordable_frame = pos + _capture_offset;