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 , input_change_pending (NoChange)
102 , wrap_buffer_size (0)
103 , speed_buffer_size (0)
105 , _target_speed (_speed)
107 , playback_sample (0)
108 , playback_distance (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)
115 , scrub_buffer_size (0)
122 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
123 : SessionObject(sess, "unnamed diskstream")
124 , i_am_the_modifier (0)
126 , _record_enabled (0)
127 , _visible_speed (1.0f)
128 , _actual_speed (1.0f)
129 , _buffer_reallocation_required (false)
130 , _seek_required (false)
131 , force_refill (false)
132 , capture_start_frame (0)
133 , capture_captured (0)
134 , was_recording (false)
135 , adjust_capture_position (0)
136 , _capture_offset (0)
138 , first_recordable_frame (max_frames)
139 , last_recordable_frame (max_frames)
140 , last_possibly_recording (0)
141 , _alignment_style (ExistingMaterial)
145 , overwrite_frame (0)
146 , overwrite_offset (0)
147 , _pending_overwrite (false)
148 , overwrite_queued (false)
149 , input_change_pending (NoChange)
150 , wrap_buffer_size (0)
151 , speed_buffer_size (0)
153 , _target_speed (_speed)
155 , playback_sample (0)
156 , playback_distance (0)
157 , _read_data_count (0)
158 , _write_data_count (0)
159 , in_set_state (false)
160 , _persistent_alignment_style (ExistingMaterial)
161 , first_input_change (true)
163 , scrub_buffer_size (0)
165 , _flags (Recordable)
169 Diskstream::~Diskstream ()
171 DEBUG_TRACE (DEBUG::Destruction, string_compose ("Diskstream %1 deleted\n", _name));
174 _playlist->release ();
179 Diskstream::set_track (Track* t)
182 _io = _track->input();
184 ic_connection.disconnect();
185 _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2));
187 input_change_pending = ConfigurationChanged;
188 non_realtime_input_change ();
189 set_align_style_from_io ();
191 _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this));
195 Diskstream::handle_input_change (IOChange change, void * /*src*/)
197 Glib::Mutex::Lock lm (state_lock);
199 if (!(input_change_pending & change)) {
200 input_change_pending = IOChange (input_change_pending|change);
201 _session.request_input_change_handling ();
206 Diskstream::non_realtime_set_speed ()
208 if (_buffer_reallocation_required)
210 Glib::Mutex::Lock lm (state_lock);
211 allocate_temporary_buffers ();
213 _buffer_reallocation_required = false;
216 if (_seek_required) {
217 if (speed() != 1.0f || speed() != -1.0f) {
218 seek ((nframes_t) (_session.transport_frame() * (double) speed()), true);
221 seek (_session.transport_frame(), true);
224 _seek_required = false;
229 Diskstream::realtime_set_speed (double sp, bool global)
231 bool changed = false;
232 double new_speed = sp * _session.transport_speed();
234 if (_visible_speed != sp) {
239 if (new_speed != _actual_speed) {
241 nframes_t required_wrap_size = (nframes_t) floor (_session.get_block_size() *
242 fabs (new_speed)) + 1;
244 if (required_wrap_size > wrap_buffer_size) {
245 _buffer_reallocation_required = true;
248 _actual_speed = new_speed;
249 _target_speed = fabs(_actual_speed);
254 _seek_required = true;
256 SpeedChanged (); /* EMIT SIGNAL */
259 return _buffer_reallocation_required || _seek_required;
263 Diskstream::set_capture_offset ()
266 /* can't capture, so forget it */
270 _capture_offset = _io->latency();
274 Diskstream::set_align_style (AlignStyle a)
276 if (record_enabled() && _session.actively_recording()) {
280 if (a != _alignment_style) {
281 _alignment_style = a;
282 AlignmentStyleChanged ();
287 Diskstream::set_loop (Location *location)
290 if (location->start() >= location->end()) {
291 error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
296 loop_location = location;
298 LoopSet (location); /* EMIT SIGNAL */
303 Diskstream::get_capture_start_frame (uint32_t n)
305 Glib::Mutex::Lock lm (capture_info_lock);
307 if (capture_info.size() > n) {
308 return capture_info[n]->start;
311 return capture_start_frame;
316 Diskstream::get_captured_frames (uint32_t n)
318 Glib::Mutex::Lock lm (capture_info_lock);
320 if (capture_info.size() > n) {
321 return capture_info[n]->frames;
324 return capture_captured;
329 Diskstream::set_roll_delay (ARDOUR::nframes_t nframes)
331 _roll_delay = nframes;
335 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
341 bool prior_playlist = false;
344 Glib::Mutex::Lock lm (state_lock);
346 if (playlist == _playlist) {
350 playlist_connections.drop_connections ();
353 _playlist->release();
354 prior_playlist = true;
357 _playlist = playlist;
360 if (!in_set_state && recordable()) {
361 reset_write_sources (false);
364 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
365 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
366 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1));
369 /* don't do this if we've already asked for it *or* if we are setting up
370 the diskstream for the very first time - the input changed handling will
371 take care of the buffer refill.
374 if (!overwrite_queued && prior_playlist) {
375 _session.request_overwrite_buffer (_track);
376 overwrite_queued = true;
379 PlaylistChanged (); /* EMIT SIGNAL */
380 _session.set_dirty ();
386 Diskstream::playlist_changed (const PropertyChange&)
388 playlist_modified ();
392 Diskstream::playlist_modified ()
394 if (!i_am_the_modifier && !overwrite_queued) {
395 _session.request_overwrite_buffer (_track);
396 overwrite_queued = true;
401 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
403 boost::shared_ptr<Playlist> pl (wpl.lock());
405 if (pl == _playlist) {
407 /* this catches an ordering issue with session destruction. playlists
408 are destroyed before diskstreams. we have to invalidate any handles
409 we have to the playlist.
419 Diskstream::set_name (const string& str)
423 playlist()->set_name (str);
425 SessionObject::set_name(str);
427 if (!in_set_state && recordable()) {
428 /* rename existing capture files so that they have the correct name */
429 return rename_write_sources ();
439 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames)
441 if (!_track || Config->get_automation_follows_regions () == false) {
445 list< Evoral::RangeMove<double> > movements;
447 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
448 i != movements_frames.end();
451 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
454 /* move panner automation */
455 boost::shared_ptr<Panner> p = _track->main_outs()->panner ();
457 for (uint32_t i = 0; i < p->npanners (); ++i) {
458 boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
459 XMLNode & before = pan_alist->get_state ();
460 pan_alist->move_ranges (movements);
461 _session.add_command (new MementoCommand<AutomationList> (
462 *pan_alist.get(), &before, &pan_alist->get_state ()));
466 /* move processor automation */
467 _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
471 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
473 boost::shared_ptr<Processor> processor (p.lock ());
478 list< Evoral::RangeMove<double> > movements;
479 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
480 i != movements_frames.end(); ++i) {
481 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
484 set<Evoral::Parameter> const a = processor->what_can_be_automated ();
486 for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
487 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
488 XMLNode & before = al->get_state ();
489 al->move_ranges (movements);
490 _session.add_command (
491 new MementoCommand<AutomationList> (
492 *al.get(), &before, &al->get_state ()
499 Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*/, bool can_record)
501 int possibly_recording;
504 const int transport_rolling = 0x4;
505 const int track_rec_enabled = 0x2;
506 const int global_rec_enabled = 0x1;
507 const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
509 /* merge together the 3 factors that affect record status, and compute
513 rolling = _session.transport_speed() != 0.0f;
514 possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
515 change = possibly_recording ^ last_possibly_recording;
517 if (possibly_recording == last_possibly_recording) {
520 if (possibly_recording == fully_rec_enabled) {
522 if (last_possibly_recording == fully_rec_enabled) {
526 /* we transitioned to recording. lets see if its transport based or a punch */
528 first_recordable_frame = transport_frame + _capture_offset;
529 last_recordable_frame = max_frames;
530 capture_start_frame = transport_frame;
532 if (change & transport_rolling) {
534 /* transport-change (started rolling) */
536 if (_alignment_style == ExistingMaterial) {
538 /* there are two delays happening:
540 1) inbound, represented by _capture_offset
541 2) outbound, represented by _session.worst_output_latency()
543 the first sample to record occurs when the larger of these
544 two has elapsed, since they occur in parallel.
546 since we've already added _capture_offset, just add the
547 difference if _session.worst_output_latency() is larger.
550 if (_capture_offset < _session.worst_output_latency()) {
551 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
554 first_recordable_frame += _roll_delay;
561 if (_alignment_style == ExistingMaterial) {
563 /* There are two kinds of punch:
565 manual punch in happens at the correct transport frame
566 because the user hit a button. but to get alignment correct
567 we have to back up the position of the new region to the
568 appropriate spot given the roll delay.
570 autopunch toggles recording at the precise
571 transport frame, and then the DS waits
572 to start recording for a time that depends
573 on the output latency.
575 XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
579 if (_capture_offset < _session.worst_output_latency()) {
580 /* see comment in ExistingMaterial block above */
581 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
585 capture_start_frame -= _roll_delay;
589 prepare_record_status (capture_start_frame);
593 if (last_possibly_recording == fully_rec_enabled) {
595 /* we were recording last time */
597 if (change & transport_rolling) {
598 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
603 last_recordable_frame = transport_frame + _capture_offset;
605 if (_alignment_style == ExistingMaterial) {
606 if (_session.worst_output_latency() > _capture_offset) {
607 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
610 last_recordable_frame += _roll_delay;
616 last_possibly_recording = possibly_recording;
620 Diskstream::route_going_away ()
626 Diskstream::calculate_record_range(OverlapType ot, sframes_t transport_frame, nframes_t nframes,
627 nframes_t& rec_nframes, nframes_t& rec_offset)
634 case OverlapInternal:
635 /* ---------- recrange
638 rec_nframes = nframes;
643 /* |--------| recrange
646 rec_nframes = transport_frame + nframes - first_recordable_frame;
648 rec_offset = first_recordable_frame - transport_frame;
653 /* |--------| recrange
656 rec_nframes = last_recordable_frame - transport_frame;
660 case OverlapExternal:
661 /* |--------| recrange
662 -------------- transrange
664 rec_nframes = last_recordable_frame - first_recordable_frame;
665 rec_offset = first_recordable_frame - transport_frame;
671 Diskstream::prepare_to_stop (framepos_t pos)
673 last_recordable_frame = pos + _capture_offset;