X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fdiskstream.cc;h=40a2714dc0735e9ea865109d5bbf9797d41e236f;hb=56469c195640b561119852fd6d27a4b56e5af7e2;hp=7004ef1ed5036bda416584e255107cd7df4a7b35;hpb=c83389b8ec5fef9553a401e6123b7e55702af9e2;p=ardour.git diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 7004ef1ed5..40a2714dc0 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -52,7 +52,7 @@ #include "ardour/panner.h" #include "ardour/session.h" #include "ardour/io.h" -#include "ardour/route.h" +#include "ardour/track.h" #include "i18n.h" #include @@ -61,7 +61,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -/* XXX This goes uninitialized when there is no ~/.ardour3 directory. +/* XXX This goes uninitialized when there is no ~/.config/ardour3 directory. * I can't figure out why, so this will do for now (just stole the * default from configuration_vars.h). 0 is not a good value for * allocating buffer sizes.. @@ -73,57 +73,97 @@ PBD::Signal0 Diskstream::DiskUnderrun; Diskstream::Diskstream (Session &sess, const string &name, Flag flag) : SessionObject(sess, name) + , i_am_the_modifier (0) + , _track (0) + , _record_enabled (0) + , _visible_speed (1.0f) + , _actual_speed (1.0f) + , _buffer_reallocation_required (false) + , _seek_required (false) + , force_refill (false) + , capture_start_frame (0) + , capture_captured (0) + , was_recording (false) + , adjust_capture_position (0) + , _capture_offset (0) + , _roll_delay (0) + , first_recordable_frame (max_frames) + , last_recordable_frame (max_frames) + , last_possibly_recording (0) + , _alignment_style (ExistingMaterial) + , _scrubbing (false) + , _slaved (false) + , loop_location (0) + , overwrite_frame (0) + , overwrite_offset (0) + , _pending_overwrite (false) + , overwrite_queued (false) + , input_change_pending (NoChange) + , wrap_buffer_size (0) + , speed_buffer_size (0) + , _speed (1.0) + , _target_speed (_speed) + , file_frame (0) + , playback_sample (0) + , playback_distance (0) + , _read_data_count (0) + , _write_data_count (0) + , in_set_state (false) + , _persistent_alignment_style (ExistingMaterial) + , first_input_change (true) + , scrub_start (0) + , scrub_buffer_size (0) + , scrub_offset (0) + , _flags (flag) + { - init (flag); } Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/) : SessionObject(sess, "unnamed diskstream") + , i_am_the_modifier (0) + , _track (0) + , _record_enabled (0) + , _visible_speed (1.0f) + , _actual_speed (1.0f) + , _buffer_reallocation_required (false) + , _seek_required (false) + , force_refill (false) + , capture_start_frame (0) + , capture_captured (0) + , was_recording (false) + , adjust_capture_position (0) + , _capture_offset (0) + , _roll_delay (0) + , first_recordable_frame (max_frames) + , last_recordable_frame (max_frames) + , last_possibly_recording (0) + , _alignment_style (ExistingMaterial) + , _scrubbing (false) + , _slaved (false) + , loop_location (0) + , overwrite_frame (0) + , overwrite_offset (0) + , _pending_overwrite (false) + , overwrite_queued (false) + , input_change_pending (NoChange) + , wrap_buffer_size (0) + , speed_buffer_size (0) + , _speed (1.0) + , _target_speed (_speed) + , file_frame (0) + , playback_sample (0) + , playback_distance (0) + , _read_data_count (0) + , _write_data_count (0) + , in_set_state (false) + , _persistent_alignment_style (ExistingMaterial) + , first_input_change (true) + , scrub_start (0) + , scrub_buffer_size (0) + , scrub_offset (0) + , _flags (Recordable) { - init (Recordable); -} - -void -Diskstream::init (Flag f) -{ - _flags = f; - _route = 0; - _alignment_style = ExistingMaterial; - _persistent_alignment_style = ExistingMaterial; - first_input_change = true; - i_am_the_modifier = 0; - g_atomic_int_set (&_record_enabled, 0); - was_recording = false; - capture_start_frame = 0; - capture_captured = 0; - _visible_speed = 1.0f; - _actual_speed = 1.0f; - _buffer_reallocation_required = false; - _seek_required = false; - first_recordable_frame = max_frames; - last_recordable_frame = max_frames; - _roll_delay = 0; - _capture_offset = 0; - _processed = false; - _slaved = false; - adjust_capture_position = 0; - last_possibly_recording = 0; - loop_location = 0; - wrap_buffer_size = 0; - speed_buffer_size = 0; - _speed = 1.0; - _target_speed = _speed; - file_frame = 0; - playback_sample = 0; - playback_distance = 0; - _read_data_count = 0; - _write_data_count = 0; - commit_should_unlock = false; - - pending_overwrite = false; - overwrite_frame = 0; - overwrite_queued = false; - input_change_pending = NoChange; } Diskstream::~Diskstream () @@ -136,10 +176,10 @@ Diskstream::~Diskstream () } void -Diskstream::set_route (Route& r) +Diskstream::set_track (Track* t) { - _route = &r; - _io = _route->input(); + _track = t; + _io = _track->input(); ic_connection.disconnect(); _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2)); @@ -148,7 +188,7 @@ Diskstream::set_route (Route& r) non_realtime_input_change (); set_align_style_from_io (); - _route->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this)); + _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this)); } void @@ -219,22 +259,6 @@ Diskstream::realtime_set_speed (double sp, bool global) return _buffer_reallocation_required || _seek_required; } -void -Diskstream::prepare () -{ - _processed = false; - playback_distance = 0; -} - -void -Diskstream::recover () -{ - if (commit_should_unlock) { - state_lock.unlock(); - } - _processed = false; -} - void Diskstream::set_capture_offset () { @@ -296,7 +320,7 @@ Diskstream::get_captured_frames (uint32_t n) if (capture_info.size() > n) { return capture_info[n]->frames; } - else { + else { return capture_captured; } } @@ -307,18 +331,15 @@ Diskstream::set_roll_delay (ARDOUR::nframes_t nframes) _roll_delay = nframes; } -void -Diskstream::set_speed (double sp) -{ - _session.request_diskstream_speed (*this, sp); - - /* to force a rebuffering at the right place */ - playlist_modified(); -} - int Diskstream::use_playlist (boost::shared_ptr playlist) { + if (!playlist) { + return 0; + } + + bool prior_playlist = false; + { Glib::Mutex::Lock lm (state_lock); @@ -330,6 +351,7 @@ Diskstream::use_playlist (boost::shared_ptr playlist) if (_playlist) { _playlist->release(); + prior_playlist = true; } _playlist = playlist; @@ -339,7 +361,7 @@ Diskstream::use_playlist (boost::shared_ptr playlist) reset_write_sources (false); } - _playlist->Modified.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this)); + _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this)); _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_deleted, this, boost::weak_ptr(_playlist))); _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1)); } @@ -349,8 +371,8 @@ Diskstream::use_playlist (boost::shared_ptr playlist) take care of the buffer refill. */ - if (!overwrite_queued && !(_session.state_of_the_state() & Session::CannotSave)) { - _session.request_overwrite_buffer (this); + if (!overwrite_queued && prior_playlist) { + _session.request_overwrite_buffer (_track); overwrite_queued = true; } @@ -361,7 +383,7 @@ Diskstream::use_playlist (boost::shared_ptr playlist) } void -Diskstream::playlist_changed (Change) +Diskstream::playlist_changed (const PropertyChange&) { playlist_modified (); } @@ -370,7 +392,7 @@ void Diskstream::playlist_modified () { if (!i_am_the_modifier && !overwrite_queued) { - _session.request_overwrite_buffer (this); + _session.request_overwrite_buffer (_track); overwrite_queued = true; } } @@ -396,7 +418,7 @@ Diskstream::playlist_deleted (boost::weak_ptr wpl) bool Diskstream::set_name (const string& str) { - if (str != _name) { + if (_name != str) { assert(playlist()); playlist()->set_name (str); @@ -426,15 +448,15 @@ Diskstream::remove_region_from_last_capture (boost::weak_ptr wregion) } void -Diskstream::playlist_ranges_moved (list< Evoral::RangeMove > const & movements_frames) +Diskstream::playlist_ranges_moved (list< Evoral::RangeMove > const & movements_frames) { - if (!_route || Config->get_automation_follows_regions () == false) { + if (!_track || Config->get_automation_follows_regions () == false) { return; } list< Evoral::RangeMove > movements; - for (list< Evoral::RangeMove >::const_iterator i = movements_frames.begin(); + for (list< Evoral::RangeMove >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) { @@ -442,7 +464,7 @@ Diskstream::playlist_ranges_moved (list< Evoral::RangeMove > const & } /* move panner automation */ - boost::shared_ptr p = _route->main_outs()->panner (); + boost::shared_ptr p = _track->main_outs()->panner (); if (p) { for (uint32_t i = 0; i < p->npanners (); ++i) { boost::shared_ptr pan_alist = p->streampanner(i).pan_control()->alist(); @@ -454,11 +476,11 @@ Diskstream::playlist_ranges_moved (list< Evoral::RangeMove > const & } /* move processor automation */ - _route->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames)); + _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames)); } void -Diskstream::move_processor_automation (boost::weak_ptr p, list< Evoral::RangeMove > const & movements_frames) +Diskstream::move_processor_automation (boost::weak_ptr p, list< Evoral::RangeMove > const & movements_frames) { boost::shared_ptr processor (p.lock ()); if (!processor) { @@ -466,7 +488,7 @@ Diskstream::move_processor_automation (boost::weak_ptr p, list< Evora } list< Evoral::RangeMove > movements; - for (list< Evoral::RangeMove >::const_iterator i = movements_frames.begin(); + for (list< Evoral::RangeMove >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) { movements.push_back(Evoral::RangeMove(i->from, i->length, i->to)); } @@ -494,6 +516,7 @@ Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes* const int transport_rolling = 0x4; const int track_rec_enabled = 0x2; const int global_rec_enabled = 0x1; + const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled); /* merge together the 3 factors that affect record status, and compute what has changed. @@ -506,91 +529,101 @@ Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes* if (possibly_recording == last_possibly_recording) { return; } + if (possibly_recording == fully_rec_enabled) { - /* change state */ - - /* if per-track or global rec-enable turned on while the other was already on, we've started recording */ - - if (((change & track_rec_enabled) && record_enabled() && (!(change & global_rec_enabled) && can_record)) || - ((change & global_rec_enabled) && can_record && (!(change & track_rec_enabled) && record_enabled()))) { - - /* starting to record: compute first+last frames */ + if (last_possibly_recording == fully_rec_enabled) { + return; + } + /* we transitioned to recording. lets see if its transport based or a punch */ + first_recordable_frame = transport_frame + _capture_offset; last_recordable_frame = max_frames; capture_start_frame = transport_frame; - if (!(last_possibly_recording & transport_rolling) && (possibly_recording & transport_rolling)) { - - /* was stopped, now rolling (and recording) */ + if (change & transport_rolling) { + /* transport-change (started rolling) */ + if (_alignment_style == ExistingMaterial) { - first_recordable_frame += _session.worst_output_latency(); - } else { + + /* there are two delays happening: + + 1) inbound, represented by _capture_offset + 2) outbound, represented by _session.worst_output_latency() + + the first sample to record occurs when the larger of these + two has elapsed, since they occur in parallel. + + since we've already added _capture_offset, just add the + difference if _session.worst_output_latency() is larger. + */ + + if (_capture_offset < _session.worst_output_latency()) { + first_recordable_frame += (_session.worst_output_latency() - _capture_offset); + } + } else { first_recordable_frame += _roll_delay; - } + } + + } else { - } else { - - /* was rolling, but record state changed */ + /* punch in */ if (_alignment_style == ExistingMaterial) { + /* There are two kinds of punch: + + manual punch in happens at the correct transport frame + because the user hit a button. but to get alignment correct + we have to back up the position of the new region to the + appropriate spot given the roll delay. - if (!_session.config.get_punch_in()) { - - /* manual punch in happens at the correct transport frame - because the user hit a button. but to get alignment correct - we have to back up the position of the new region to the - appropriate spot given the roll delay. - */ + autopunch toggles recording at the precise + transport frame, and then the DS waits + to start recording for a time that depends + on the output latency. - capture_start_frame -= _roll_delay; + XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!! - /* XXX paul notes (august 2005): i don't know why - this is needed. - */ + */ - first_recordable_frame += _capture_offset; - - } else { - - /* autopunch toggles recording at the precise - transport frame, and then the DS waits - to start recording for a time that depends - on the output latency. - */ - - first_recordable_frame += _session.worst_output_latency(); - } + if (_capture_offset < _session.worst_output_latency()) { + /* see comment in ExistingMaterial block above */ + first_recordable_frame += (_session.worst_output_latency() - _capture_offset); + } } else { - - if (_session.config.get_punch_in()) { - first_recordable_frame += _roll_delay; - } else { - capture_start_frame -= _roll_delay; - } + capture_start_frame -= _roll_delay; } - - } - - prepare_record_status(capture_start_frame); - - } else if (!record_enabled() || !can_record) { - - /* stop recording */ - - last_recordable_frame = transport_frame + _capture_offset; - - if (_alignment_style == ExistingMaterial) { - last_recordable_frame += _session.worst_output_latency(); - } else { - last_recordable_frame += _roll_delay; - } - - first_recordable_frame = max_frames; - } + } + + prepare_record_status (capture_start_frame); + + } else { + + if (last_possibly_recording == fully_rec_enabled) { + + /* we were recording last time */ + + if (change & transport_rolling) { + /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */ + + } else { + /* punch out */ + + last_recordable_frame = transport_frame + _capture_offset; + + if (_alignment_style == ExistingMaterial) { + if (_session.worst_output_latency() > _capture_offset) { + last_recordable_frame += (_session.worst_output_latency() - _capture_offset); + } + } else { + last_recordable_frame += _roll_delay; + } + } + } + } last_possibly_recording = possibly_recording; } @@ -645,3 +678,9 @@ Diskstream::calculate_record_range(OverlapType ot, sframes_t transport_frame, nf break; } } + +void +Diskstream::prepare_to_stop (framepos_t pos) +{ + last_recordable_frame = pos + _capture_offset; +}