X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fdiskstream.cc;h=7f4214037d6a2bbe1b12450cedd1cd3eaee4d7b2;hb=424cacfbc83516d9e935bd93135e58b34dcfc002;hp=3c79d31f98a4f032a178ee99ce96394f023e03cb;hpb=75e6adcf03078c24d13ddc7c9c714582a6cf7891;p=ardour.git diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 3c79d31f98..7f4214037d 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -17,7 +17,6 @@ */ -#include #include #include #include @@ -29,10 +28,8 @@ #include #include #include -#include - -#include +#include #include "pbd/error.h" #include "pbd/basename.h" @@ -40,22 +37,13 @@ #include "pbd/xml++.h" #include "pbd/stacktrace.h" -#include "ardour/ardour.h" -#include "ardour/audioengine.h" #include "ardour/debug.h" #include "ardour/diskstream.h" -#include "ardour/utils.h" -#include "ardour/configuration.h" -#include "ardour/audiofilesource.h" -#include "ardour/send.h" +#include "ardour/io.h" #include "ardour/pannable.h" -#include "ardour/panner_shell.h" +#include "ardour/profile.h" #include "ardour/playlist.h" -#include "ardour/cycle_timer.h" -#include "ardour/region.h" -#include "ardour/panner.h" #include "ardour/session.h" -#include "ardour/io.h" #include "ardour/track.h" #include "i18n.h" @@ -65,12 +53,8 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -/* 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.. - */ -ARDOUR::framecnt_t Diskstream::disk_io_chunk_frames = 1024 * 256 / sizeof (Sample); +ARDOUR::framecnt_t Diskstream::disk_read_chunk_frames = default_disk_read_chunk_frames (); +ARDOUR::framecnt_t Diskstream::disk_write_chunk_frames = default_disk_write_chunk_frames (); PBD::Signal0 Diskstream::DiskOverrun; PBD::Signal0 Diskstream::DiskUnderrun; @@ -80,11 +64,11 @@ Diskstream::Diskstream (Session &sess, const string &name, Flag flag) , i_am_the_modifier (0) , _track (0) , _record_enabled (0) + , _record_safe (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) @@ -96,7 +80,6 @@ Diskstream::Diskstream (Session &sess, const string &name, Flag flag) , last_possibly_recording (0) , _alignment_style (ExistingMaterial) , _alignment_choice (Automatic) - , _scrubbing (false) , _slaved (false) , loop_location (0) , overwrite_frame (0) @@ -109,7 +92,6 @@ Diskstream::Diskstream (Session &sess, const string &name, Flag flag) , _target_speed (_speed) , file_frame (0) , playback_sample (0) - , playback_distance (0) , in_set_state (false) , _flags (flag) , deprecated_io_node (0) @@ -121,11 +103,11 @@ Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/) , i_am_the_modifier (0) , _track (0) , _record_enabled (0) + , _record_safe (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) @@ -137,7 +119,6 @@ Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/) , last_possibly_recording (0) , _alignment_style (ExistingMaterial) , _alignment_choice (Automatic) - , _scrubbing (false) , _slaved (false) , loop_location (0) , overwrite_frame (0) @@ -150,7 +131,6 @@ Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/) , _target_speed (_speed) , file_frame (0) , playback_sample (0) - , playback_distance (0) , in_set_state (false) , _flags (Recordable) , deprecated_io_node (0) @@ -188,7 +168,7 @@ Diskstream::set_track (Track* t) void Diskstream::handle_input_change (IOChange change, void * /*src*/) { - Glib::Mutex::Lock lm (state_lock); + Glib::Threads::Mutex::Lock lm (state_lock); if (change.type & (IOChange::ConfigurationChanged|IOChange::ConnectionsChanged)) { @@ -210,7 +190,7 @@ Diskstream::non_realtime_set_speed () { if (_buffer_reallocation_required) { - Glib::Mutex::Lock lm (state_lock); + Glib::Threads::Mutex::Lock lm (state_lock); allocate_temporary_buffers (); _buffer_reallocation_required = false; @@ -241,8 +221,8 @@ Diskstream::realtime_set_speed (double sp, bool global) if (new_speed != _actual_speed) { - framecnt_t required_wrap_size = (framecnt_t) floor (_session.get_block_size() * - fabs (new_speed)) + 1; + framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() * + fabs (new_speed)) + 2; if (required_wrap_size > wrap_buffer_size) { _buffer_reallocation_required = true; @@ -270,8 +250,18 @@ Diskstream::set_capture_offset () return; } - _capture_offset = _io->latency(); - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: using IO latency, capture offset set to %2\n", name(), _capture_offset)); + switch (_alignment_style) { + case ExistingMaterial: + _capture_offset = _io->latency(); + break; + + case CaptureTime: + default: + _capture_offset = 0; + break; + } + + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: using IO latency, capture offset set to %2 with style = %3\n", name(), _capture_offset, enum_2_string (_alignment_style))); } @@ -284,6 +274,7 @@ Diskstream::set_align_style (AlignStyle a, bool force) if ((a != _alignment_style) || force) { _alignment_style = a; + set_capture_offset (); AlignmentStyleChanged (); } } @@ -298,17 +289,17 @@ Diskstream::set_align_choice (AlignChoice a, bool force) if ((a != _alignment_choice) || force) { _alignment_choice = a; - switch (_alignment_choice) { - case Automatic: - set_align_style_from_io (); - break; - case UseExistingMaterial: - set_align_style (ExistingMaterial); - break; - case UseCaptureTime: - set_align_style (CaptureTime); - break; - } + switch (_alignment_choice) { + case Automatic: + set_align_style_from_io (); + break; + case UseExistingMaterial: + set_align_style (ExistingMaterial); + break; + case UseCaptureTime: + set_align_style (CaptureTime); + break; + } } } @@ -332,7 +323,7 @@ Diskstream::set_loop (Location *location) ARDOUR::framepos_t Diskstream::get_capture_start_frame (uint32_t n) const { - Glib::Mutex::Lock lm (capture_info_lock); + Glib::Threads::Mutex::Lock lm (capture_info_lock); if (capture_info.size() > n) { /* this is a completed capture */ @@ -346,7 +337,7 @@ Diskstream::get_capture_start_frame (uint32_t n) const ARDOUR::framecnt_t Diskstream::get_captured_frames (uint32_t n) const { - Glib::Mutex::Lock lm (capture_info_lock); + Glib::Threads::Mutex::Lock lm (capture_info_lock); if (capture_info.size() > n) { /* this is a completed capture */ @@ -373,7 +364,7 @@ Diskstream::use_playlist (boost::shared_ptr playlist) bool prior_playlist = false; { - Glib::Mutex::Lock lm (state_lock); + Glib::Threads::Mutex::Lock lm (state_lock); if (playlist == _playlist) { return 0; @@ -394,6 +385,7 @@ Diskstream::use_playlist (boost::shared_ptr playlist) } _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this)); + _playlist->LayeringChanged.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, _2)); } @@ -455,7 +447,13 @@ Diskstream::set_name (const string& str) playlist()->set_name (str); SessionObject::set_name(str); } - return true; + return true; +} + +bool +Diskstream::set_write_source_name (const std::string& str) { + _write_source_name = str; + return true; } XMLNode& @@ -463,7 +461,7 @@ Diskstream::get_state () { XMLNode* node = new XMLNode ("Diskstream"); char buf[64]; - LocaleGuard lg (X_("POSIX")); + LocaleGuard lg (X_("C")); node->add_property ("flags", enum_2_string (_flags)); node->add_property ("playlist", _playlist->name()); @@ -473,6 +471,7 @@ Diskstream::get_state () snprintf (buf, sizeof(buf), "%f", _visible_speed); node->add_property ("speed", buf); node->add_property ("capture-alignment", enum_2_string (_alignment_choice)); + node->add_property ("record-safe", _record_safe ? "yes" : "no"); if (_extra_xml) { node->add_child_copy (*_extra_xml); @@ -500,6 +499,11 @@ Diskstream::set_state (const XMLNode& node, int /*version*/) _flags = Flag (string_2_enum (prop->value(), _flags)); } + if (Profile->get_trx() && (_flags & Destructive)) { + error << string_compose (_("%1: this session uses destructive tracks, which are not supported"), PROGRAM_NAME) << endmsg; + return -1; + } + if ((prop = node.property (X_("capture-alignment"))) != 0) { set_align_choice (AlignChoice (string_2_enum (prop->value(), _alignment_choice)), true); } else { @@ -510,16 +514,8 @@ Diskstream::set_state (const XMLNode& node, int /*version*/) return -1; } - { - bool had_playlist = (_playlist != 0); - - if (find_and_use_playlist (prop->value())) { - return -1; - } - - if (!had_playlist) { - _playlist->set_orig_diskstream_id (id()); - } + if (find_and_use_playlist (prop->value())) { + return -1; } if ((prop = node.property ("speed")) != 0) { @@ -530,7 +526,11 @@ Diskstream::set_state (const XMLNode& node, int /*version*/) } } - return 0; + if ((prop = node.property ("record-safe")) != 0) { + _record_safe = PBD::string_is_affirmative (prop->value()) ? 1 : 0; + } + + return 0; } void @@ -596,7 +596,7 @@ Diskstream::move_processor_automation (boost::weak_ptr p, list< Evora set const a = processor->what_can_be_automated (); - for (set::iterator i = a.begin (); i != a.end (); ++i) { + for (set::const_iterator i = a.begin (); i != a.end (); ++i) { boost::shared_ptr al = processor->automation_control(*i)->alist(); XMLNode & before = al->get_state (); bool const things_moved = al->move_ranges (movements); @@ -619,27 +619,27 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record) 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); + 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. - */ + * what has changed. + */ rolling = _session.transport_speed() != 0.0f; - possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record; + possibly_recording = (rolling << 2) | ((int)record_enabled() << 1) | (int)can_record; change = possibly_recording ^ last_possibly_recording; if (possibly_recording == last_possibly_recording) { return; } - framecnt_t existing_material_offset = _session.worst_playback_latency(); + const framecnt_t existing_material_offset = _session.worst_playback_latency(); - if (possibly_recording == fully_rec_enabled) { + if (possibly_recording == fully_rec_enabled) { - if (last_possibly_recording == fully_rec_enabled) { - return; - } + if (last_possibly_recording == fully_rec_enabled) { + return; + } capture_start_frame = _session.transport_frame(); first_recordable_frame = capture_start_frame + _capture_offset; @@ -662,32 +662,32 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record) first_recordable_frame)); } - prepare_record_status (capture_start_frame); + prepare_record_status (capture_start_frame); - } else { + } else { - if (last_possibly_recording == fully_rec_enabled) { + if (last_possibly_recording == fully_rec_enabled) { - /* we were recording last time */ + /* we were recording last time */ - if (change & transport_rolling) { + if (change & transport_rolling) { - /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop(). We - had to set it there because we likely rolled past the stopping point to declick out, - and then backed up. - */ + /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop(). We + * had to set it there because we likely rolled past the stopping point to declick out, + * and then backed up. + */ - } else { - /* punch out */ + } else { + /* punch out */ - last_recordable_frame = _session.transport_frame() + _capture_offset; + last_recordable_frame = _session.transport_frame() + _capture_offset; - if (_alignment_style == ExistingMaterial) { - last_recordable_frame += existing_material_offset; - } - } - } - } + if (_alignment_style == ExistingMaterial) { + last_recordable_frame += existing_material_offset; + } + } + } + } last_possibly_recording = possibly_recording; } @@ -699,44 +699,44 @@ Diskstream::route_going_away () } void -Diskstream::calculate_record_range(OverlapType ot, framepos_t transport_frame, framecnt_t nframes, - framecnt_t & rec_nframes, framecnt_t & rec_offset) +Diskstream::calculate_record_range (Evoral::OverlapType ot, framepos_t transport_frame, framecnt_t nframes, + framecnt_t & rec_nframes, framecnt_t & rec_offset) { switch (ot) { - case OverlapNone: + case Evoral::OverlapNone: rec_nframes = 0; break; - case OverlapInternal: + case Evoral::OverlapInternal: /* ---------- recrange - |---| transrange - */ + * |---| transrange + */ rec_nframes = nframes; rec_offset = 0; break; - case OverlapStart: + case Evoral::OverlapStart: /* |--------| recrange - -----| transrange - */ + * -----| transrange + */ rec_nframes = transport_frame + nframes - first_recordable_frame; if (rec_nframes) { rec_offset = first_recordable_frame - transport_frame; } break; - case OverlapEnd: + case Evoral::OverlapEnd: /* |--------| recrange - |-------- transrange - */ + * |-------- transrange + */ rec_nframes = last_recordable_frame - transport_frame; rec_offset = 0; break; - case OverlapExternal: + case Evoral::OverlapExternal: /* |--------| recrange - -------------- transrange - */ + * -------------- transrange + */ rec_nframes = last_recordable_frame - first_recordable_frame; rec_offset = first_recordable_frame - transport_frame; break; @@ -748,7 +748,119 @@ Diskstream::calculate_record_range(OverlapType ot, framepos_t transport_frame, f } void -Diskstream::prepare_to_stop (framepos_t pos) +Diskstream::prepare_to_stop (framepos_t transport_frame, framepos_t audible_frame) { - last_recordable_frame = pos + _capture_offset; + switch (_alignment_style) { + case ExistingMaterial: + last_recordable_frame = transport_frame + _capture_offset; + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose("%1: prepare to stop sets last recordable frame to %2 + %3 = %4\n", _name, transport_frame, _capture_offset, last_recordable_frame)); + break; + + case CaptureTime: + last_recordable_frame = audible_frame; // note that capture_offset is zero + /* we may already have captured audio before the last_recordable_frame (audible frame), + so deal with this. + */ + if (last_recordable_frame > capture_start_frame) { + capture_captured = min (capture_captured, last_recordable_frame - capture_start_frame); + } + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose("%1: prepare to stop sets last recordable frame to audible frame @ %2\n", _name, audible_frame)); + break; + } + +} + +void +Diskstream::engage_record_enable () +{ + g_atomic_int_set (&_record_enabled, 1); +} + +void +Diskstream::disengage_record_enable () +{ + g_atomic_int_set (&_record_enabled, 0); +} + +void +Diskstream::engage_record_safe () +{ + g_atomic_int_set (&_record_safe, 1); +} + +void +Diskstream::disengage_record_safe () +{ + g_atomic_int_set (&_record_safe, 0); +} + +framecnt_t +Diskstream::default_disk_read_chunk_frames() +{ + return 65536; +} + +framecnt_t +Diskstream::default_disk_write_chunk_frames () +{ + return 65536; +} + +void +Diskstream::set_buffering_parameters (BufferingPreset bp) +{ + framecnt_t read_chunk_size; + framecnt_t read_buffer_size; + framecnt_t write_chunk_size; + framecnt_t write_buffer_size; + + if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) { + return; + } + + disk_read_chunk_frames = read_chunk_size; + disk_write_chunk_frames = write_chunk_size; + Config->set_audio_capture_buffer_seconds (write_buffer_size); + Config->set_audio_playback_buffer_seconds (read_buffer_size); + + cerr << "Set buffering params to " << disk_read_chunk_frames << '|' << disk_write_chunk_frames << '|' + << Config->get_audio_playback_buffer_seconds() << '|' + << Config->get_audio_capture_buffer_seconds () + << endl; +} + +bool +Diskstream::get_buffering_presets (BufferingPreset bp, + framecnt_t& read_chunk_size, + framecnt_t& read_buffer_size, + framecnt_t& write_chunk_size, + framecnt_t& write_buffer_size) +{ + switch (bp) { + case Small: + read_chunk_size = 65536; /* samples */ + write_chunk_size = 65536; /* samples */ + read_buffer_size = 5; /* seconds */ + write_buffer_size = 5; /* seconds */ + break; + + case Medium: + read_chunk_size = 262144; /* samples */ + write_chunk_size = 131072; /* samples */ + read_buffer_size = 10; /* seconds */ + write_buffer_size = 10; /* seconds */ + break; + + case Large: + read_chunk_size = 524288; /* samples */ + write_chunk_size = 131072; /* samples */ + read_buffer_size = 20; /* seconds */ + write_buffer_size = 20; /* seconds */ + break; + + default: + return false; + } + + return true; }