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::framecnt_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_framepos)
91 , last_recordable_frame (max_framepos)
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)
118 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
119 : SessionObject(sess, "unnamed diskstream")
120 , i_am_the_modifier (0)
122 , _record_enabled (0)
123 , _visible_speed (1.0f)
124 , _actual_speed (1.0f)
125 , _buffer_reallocation_required (false)
126 , _seek_required (false)
127 , force_refill (false)
128 , capture_start_frame (0)
129 , capture_captured (0)
130 , was_recording (false)
131 , adjust_capture_position (0)
132 , _capture_offset (0)
134 , first_recordable_frame (max_framepos)
135 , last_recordable_frame (max_framepos)
136 , last_possibly_recording (0)
137 , _alignment_style (ExistingMaterial)
141 , overwrite_frame (0)
142 , overwrite_offset (0)
143 , _pending_overwrite (false)
144 , overwrite_queued (false)
145 , wrap_buffer_size (0)
146 , speed_buffer_size (0)
148 , _target_speed (_speed)
150 , playback_sample (0)
151 , playback_distance (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<Panner> p = _track->main_outs()->panner ();
463 for (uint32_t i = 0; i < p->npanners (); ++i) {
464 boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
465 XMLNode & before = pan_alist->get_state ();
466 bool const things_moved = pan_alist->move_ranges (movements);
468 _session.add_command (new MementoCommand<AutomationList> (
469 *pan_alist.get(), &before, &pan_alist->get_state ()));
474 /* move processor automation */
475 _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
479 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
481 boost::shared_ptr<Processor> processor (p.lock ());
486 list< Evoral::RangeMove<double> > movements;
487 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
488 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
491 set<Evoral::Parameter> const a = processor->what_can_be_automated ();
493 for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
494 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
495 XMLNode & before = al->get_state ();
496 bool const things_moved = al->move_ranges (movements);
498 _session.add_command (
499 new MementoCommand<AutomationList> (
500 *al.get(), &before, &al->get_state ()
508 Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
510 int possibly_recording;
513 const int transport_rolling = 0x4;
514 const int track_rec_enabled = 0x2;
515 const int global_rec_enabled = 0x1;
516 const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
518 /* merge together the 3 factors that affect record status, and compute
522 rolling = _session.transport_speed() != 0.0f;
523 possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
524 change = possibly_recording ^ last_possibly_recording;
526 if (possibly_recording == last_possibly_recording) {
529 if (possibly_recording == fully_rec_enabled) {
531 if (last_possibly_recording == fully_rec_enabled) {
535 /* we transitioned to recording. lets see if its transport based or a punch */
537 first_recordable_frame = transport_frame + _capture_offset;
538 last_recordable_frame = max_framepos;
539 capture_start_frame = transport_frame;
541 if (change & transport_rolling) {
543 /* transport-change (started rolling) */
545 if (_alignment_style == ExistingMaterial) {
547 /* there are two delays happening:
549 1) inbound, represented by _capture_offset
550 2) outbound, represented by _session.worst_output_latency()
552 the first sample to record occurs when the larger of these
553 two has elapsed, since they occur in parallel.
555 since we've already added _capture_offset, just add the
556 difference if _session.worst_output_latency() is larger.
559 if (_capture_offset < _session.worst_output_latency()) {
560 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
563 first_recordable_frame += _roll_delay;
570 if (_alignment_style == ExistingMaterial) {
572 /* There are two kinds of punch:
574 manual punch in happens at the correct transport frame
575 because the user hit a button. but to get alignment correct
576 we have to back up the position of the new region to the
577 appropriate spot given the roll delay.
579 autopunch toggles recording at the precise
580 transport frame, and then the DS waits
581 to start recording for a time that depends
582 on the output latency.
584 XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
588 if (_capture_offset < _session.worst_output_latency()) {
589 /* see comment in ExistingMaterial block above */
590 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
594 capture_start_frame -= _roll_delay;
598 prepare_record_status (capture_start_frame);
602 if (last_possibly_recording == fully_rec_enabled) {
604 /* we were recording last time */
606 if (change & transport_rolling) {
607 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
612 last_recordable_frame = transport_frame + _capture_offset;
614 if (_alignment_style == ExistingMaterial) {
615 if (_session.worst_output_latency() > _capture_offset) {
616 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
619 last_recordable_frame += _roll_delay;
625 last_possibly_recording = possibly_recording;
629 Diskstream::route_going_away ()
635 Diskstream::calculate_record_range(OverlapType ot, framepos_t transport_frame, framecnt_t nframes,
636 framecnt_t & rec_nframes, framecnt_t & rec_offset)
643 case OverlapInternal:
644 /* ---------- recrange
647 rec_nframes = nframes;
652 /* |--------| recrange
655 rec_nframes = transport_frame + nframes - first_recordable_frame;
657 rec_offset = first_recordable_frame - transport_frame;
662 /* |--------| recrange
665 rec_nframes = last_recordable_frame - transport_frame;
669 case OverlapExternal:
670 /* |--------| recrange
671 -------------- transrange
673 rec_nframes = last_recordable_frame - first_recordable_frame;
674 rec_offset = first_recordable_frame - transport_frame;
680 Diskstream::prepare_to_stop (framepos_t pos)
682 last_recordable_frame = pos + _capture_offset;