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_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)
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_framepos)
138 , last_recordable_frame (max_framepos)
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 (change.type & IOChange::ConfigurationChanged) {
198 if (!(input_change_pending.type & change.type)) {
199 input_change_pending.type = IOChange::Type (input_change_pending.type | change.type);
200 _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 ((framepos_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 */
302 /** Get the start position (in session frames) of the nth capture in the current pass */
304 Diskstream::get_capture_start_frame (uint32_t n) const
306 Glib::Mutex::Lock lm (capture_info_lock);
308 if (capture_info.size() > n) {
309 /* this is a completed capture */
310 return capture_info[n]->start;
312 /* this is the currently in-progress capture */
313 return capture_start_frame;
318 Diskstream::get_captured_frames (uint32_t n) const
320 Glib::Mutex::Lock lm (capture_info_lock);
322 if (capture_info.size() > n) {
323 /* this is a completed capture */
324 return capture_info[n]->frames;
326 /* this is the currently in-progress capture */
327 return capture_captured;
332 Diskstream::set_roll_delay (ARDOUR::nframes_t nframes)
334 _roll_delay = nframes;
338 Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
344 bool prior_playlist = false;
347 Glib::Mutex::Lock lm (state_lock);
349 if (playlist == _playlist) {
353 playlist_connections.drop_connections ();
356 _playlist->release();
357 prior_playlist = true;
360 _playlist = playlist;
363 if (!in_set_state && recordable()) {
364 reset_write_sources (false);
367 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
368 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
369 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1, _2));
372 /* don't do this if we've already asked for it *or* if we are setting up
373 the diskstream for the very first time - the input changed handling will
374 take care of the buffer refill.
377 if (!overwrite_queued && prior_playlist) {
378 _session.request_overwrite_buffer (_track);
379 overwrite_queued = true;
382 PlaylistChanged (); /* EMIT SIGNAL */
383 _session.set_dirty ();
389 Diskstream::playlist_changed (const PropertyChange&)
391 playlist_modified ();
395 Diskstream::playlist_modified ()
397 if (!i_am_the_modifier && !overwrite_queued) {
398 _session.request_overwrite_buffer (_track);
399 overwrite_queued = true;
404 Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
406 boost::shared_ptr<Playlist> pl (wpl.lock());
408 if (pl == _playlist) {
410 /* this catches an ordering issue with session destruction. playlists
411 are destroyed before diskstreams. we have to invalidate any handles
412 we have to the playlist.
422 Diskstream::set_name (const string& str)
426 playlist()->set_name (str);
428 SessionObject::set_name(str);
430 if (!in_set_state && recordable()) {
431 /* rename existing capture files so that they have the correct name */
432 return rename_write_sources ();
442 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
444 /* If we're coming from an undo, it will have handled
445 automation undo (it must, since automation-follows-regions
446 can lose automation data). Hence we can do nothing here.
453 if (!_track || Config->get_automation_follows_regions () == false) {
457 list< Evoral::RangeMove<double> > movements;
459 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
460 i != movements_frames.end();
463 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
466 /* move panner automation */
467 boost::shared_ptr<Panner> p = _track->main_outs()->panner ();
469 for (uint32_t i = 0; i < p->npanners (); ++i) {
470 boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
471 XMLNode & before = pan_alist->get_state ();
472 bool const things_moved = pan_alist->move_ranges (movements);
474 _session.add_command (new MementoCommand<AutomationList> (
475 *pan_alist.get(), &before, &pan_alist->get_state ()));
480 /* move processor automation */
481 _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
485 Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
487 boost::shared_ptr<Processor> processor (p.lock ());
492 list< Evoral::RangeMove<double> > movements;
493 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
494 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
497 set<Evoral::Parameter> const a = processor->what_can_be_automated ();
499 for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
500 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
501 XMLNode & before = al->get_state ();
502 bool const things_moved = al->move_ranges (movements);
504 _session.add_command (
505 new MementoCommand<AutomationList> (
506 *al.get(), &before, &al->get_state ()
514 Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
516 int possibly_recording;
519 const int transport_rolling = 0x4;
520 const int track_rec_enabled = 0x2;
521 const int global_rec_enabled = 0x1;
522 const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
524 /* merge together the 3 factors that affect record status, and compute
528 rolling = _session.transport_speed() != 0.0f;
529 possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
530 change = possibly_recording ^ last_possibly_recording;
532 if (possibly_recording == last_possibly_recording) {
535 if (possibly_recording == fully_rec_enabled) {
537 if (last_possibly_recording == fully_rec_enabled) {
541 /* we transitioned to recording. lets see if its transport based or a punch */
543 first_recordable_frame = transport_frame + _capture_offset;
544 last_recordable_frame = max_framepos;
545 capture_start_frame = transport_frame;
547 if (change & transport_rolling) {
549 /* transport-change (started rolling) */
551 if (_alignment_style == ExistingMaterial) {
553 /* there are two delays happening:
555 1) inbound, represented by _capture_offset
556 2) outbound, represented by _session.worst_output_latency()
558 the first sample to record occurs when the larger of these
559 two has elapsed, since they occur in parallel.
561 since we've already added _capture_offset, just add the
562 difference if _session.worst_output_latency() is larger.
565 if (_capture_offset < _session.worst_output_latency()) {
566 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
569 first_recordable_frame += _roll_delay;
576 if (_alignment_style == ExistingMaterial) {
578 /* There are two kinds of punch:
580 manual punch in happens at the correct transport frame
581 because the user hit a button. but to get alignment correct
582 we have to back up the position of the new region to the
583 appropriate spot given the roll delay.
585 autopunch toggles recording at the precise
586 transport frame, and then the DS waits
587 to start recording for a time that depends
588 on the output latency.
590 XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
594 if (_capture_offset < _session.worst_output_latency()) {
595 /* see comment in ExistingMaterial block above */
596 first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
600 capture_start_frame -= _roll_delay;
604 prepare_record_status (capture_start_frame);
608 if (last_possibly_recording == fully_rec_enabled) {
610 /* we were recording last time */
612 if (change & transport_rolling) {
613 /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
618 last_recordable_frame = transport_frame + _capture_offset;
620 if (_alignment_style == ExistingMaterial) {
621 if (_session.worst_output_latency() > _capture_offset) {
622 last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
625 last_recordable_frame += _roll_delay;
631 last_possibly_recording = possibly_recording;
635 Diskstream::route_going_away ()
641 Diskstream::calculate_record_range(OverlapType ot, framepos_t transport_frame, framecnt_t nframes,
642 nframes_t& rec_nframes, nframes_t& rec_offset)
649 case OverlapInternal:
650 /* ---------- recrange
653 rec_nframes = nframes;
658 /* |--------| recrange
661 rec_nframes = transport_frame + nframes - first_recordable_frame;
663 rec_offset = first_recordable_frame - transport_frame;
668 /* |--------| recrange
671 rec_nframes = last_recordable_frame - transport_frame;
675 case OverlapExternal:
676 /* |--------| recrange
677 -------------- transrange
679 rec_nframes = last_recordable_frame - first_recordable_frame;
680 rec_offset = first_recordable_frame - transport_frame;
686 Diskstream::prepare_to_stop (framepos_t pos)
688 last_recordable_frame = pos + _capture_offset;