From 2a1dccabc9e66a1c3a6268f40f5bac345a1f89d1 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 17 Apr 2017 11:12:38 +0100 Subject: get diskreader working, and remove per-track varispeed API and mechanism --- libs/ardour/ardour/disk_io.h | 3 - libs/ardour/ardour/disk_writer.h | 1 + libs/ardour/ardour/midi_track.h | 1 - libs/ardour/ardour/route.h | 3 +- libs/ardour/ardour/track.h | 4 +- libs/ardour/disk_io.cc | 40 +++------ libs/ardour/disk_reader.cc | 47 +++++------ libs/ardour/disk_writer.cc | 10 ++- libs/ardour/midi_track.cc | 14 ---- libs/ardour/route.cc | 171 ++++++++++++++++++++------------------- libs/ardour/session_transport.cc | 6 +- libs/ardour/track.cc | 59 +++++++++++--- 12 files changed, 182 insertions(+), 177 deletions(-) diff --git a/libs/ardour/ardour/disk_io.h b/libs/ardour/ardour/disk_io.h index 54d4254a69..47b02582a1 100644 --- a/libs/ardour/ardour/disk_io.h +++ b/libs/ardour/ardour/disk_io.h @@ -78,7 +78,6 @@ class LIBARDOUR_API DiskIOProcessor : public Processor bool recordable() const { return _flags & Recordable; } bool non_layered() const { return _flags & NonLayered; } bool reversed() const { return _actual_speed < 0.0f; } - double speed() const { return _visible_speed; } virtual void non_realtime_locate (framepos_t); @@ -122,9 +121,7 @@ class LIBARDOUR_API DiskIOProcessor : public Processor protected: Flag _flags; uint32_t i_am_the_modifier; - double _visible_speed; double _actual_speed; - double _speed; double _target_speed; /* items needed for speed change logic */ bool _buffer_reallocation_required; diff --git a/libs/ardour/ardour/disk_writer.h b/libs/ardour/ardour/disk_writer.h index 4a5612fec9..62e18bff9d 100644 --- a/libs/ardour/ardour/disk_writer.h +++ b/libs/ardour/ardour/disk_writer.h @@ -48,6 +48,7 @@ class LIBARDOUR_API DiskWriter : public DiskIOProcessor void run (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framepos_t /*end_frame*/, double speed, pframes_t /*nframes*/, bool /*result_required*/); void non_realtime_locate (framepos_t); + void realtime_handle_transport_stopped (); virtual XMLNode& state (bool full); int set_state (const XMLNode&, int version); diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 0aff566b1c..f08af83aaa 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -44,7 +44,6 @@ public: int roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler); - void realtime_handle_transport_stopped (); void realtime_locate (); void non_realtime_locate (framepos_t); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 619e79fafc..d7f1ebe8a9 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -388,7 +388,8 @@ public: virtual XMLNode& get_template(); XMLNode& get_processor_state (); - virtual void set_processor_state (const XMLNode&); + void set_processor_state (const XMLNode&); + virtual bool set_processor_state (XMLNode const & node, XMLProperty const* prop, ProcessorList& new_order, bool& must_configure); boost::weak_ptr weakroute (); diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index d7b6324808..103def7041 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -67,6 +67,8 @@ class LIBARDOUR_API Track : public Route, public Recordable MonitorState monitoring_state () const; MeterState metering_state () const; + bool set_processor_state (XMLNode const & node, XMLProperty const* prop, ProcessorList& new_order, bool& must_configure); + virtual int no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing); @@ -155,6 +157,7 @@ class LIBARDOUR_API Track : public Route, public Recordable int can_internal_playback_seek (framecnt_t); int internal_playback_seek (framecnt_t); void non_realtime_locate (framepos_t); + void realtime_handle_transport_stopped (); void non_realtime_set_speed (); int overwrite_existing_buffers (); framecnt_t get_captured_frames (uint32_t n = 0) const; @@ -163,7 +166,6 @@ class LIBARDOUR_API Track : public Route, public Recordable bool realtime_set_speed (double, bool); void transport_stopped_wallclock (struct tm &, time_t, bool); bool pending_overwrite () const; - double speed () const; void prepare_to_stop (framepos_t, framepos_t); void set_slaved (bool); ChanCount n_channels (); diff --git a/libs/ardour/disk_io.cc b/libs/ardour/disk_io.cc index 4acbc49057..5b81e2a161 100644 --- a/libs/ardour/disk_io.cc +++ b/libs/ardour/disk_io.cc @@ -49,9 +49,7 @@ DiskIOProcessor::DiskIOProcessor (Session& s, string const & str, Flag f) : Processor (s, str) , _flags (f) , i_am_the_modifier (false) - , _visible_speed (0.0) , _actual_speed (0.0) - , _speed (0.0) , _target_speed (0.0) , _buffer_reallocation_required (false) , _seek_required (false) @@ -170,11 +168,7 @@ DiskIOProcessor::configure_io (ChanCount in, ChanCount out) midi_interpolation.add_channel_to (0,0); } - if (speed() != 1.0f || speed() != -1.0f) { - seek ((framepos_t) (_session.transport_frame() * (double) speed())); - } else { - seek (_session.transport_frame()); - } + seek (_session.transport_frame()); return Processor::configure_io (in, out); } @@ -206,11 +200,7 @@ DiskIOProcessor::non_realtime_locate (framepos_t location) { /* now refill channel buffers */ - if (speed() != 1.0f || speed() != -1.0f) { - seek ((framepos_t) (location * (double) speed()), true); - } else { - seek (location, true); - } + seek (location, true); } void @@ -221,39 +211,27 @@ DiskIOProcessor::non_realtime_set_speed () } if (_seek_required) { - if (speed() != 1.0f || speed() != -1.0f) { - seek ((framepos_t) (_session.transport_frame() * (double) speed()), true); - } - else { - seek (_session.transport_frame(), true); - } - + seek (_session.transport_frame(), true); _seek_required = false; } } bool -DiskIOProcessor::realtime_set_speed (double sp, bool global) +DiskIOProcessor::realtime_set_speed (double new_speed, bool global) { bool changed = false; - double new_speed = sp * _session.transport_speed(); - if (_visible_speed != sp) { - _visible_speed = sp; - changed = true; - } + DEBUG_TRACE (DEBUG::Transport, string_compose ("%1 will run at %2\n", name(), new_speed)); - if (new_speed != _actual_speed) { + if (_target_speed != new_speed) { + _target_speed = new_speed; + changed = true; - framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() * - fabs (new_speed)) + 2; + 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; } - - _actual_speed = new_speed; - _target_speed = fabs(_actual_speed); } if (changed) { diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index dd04d55138..fbc48c01c9 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -112,13 +112,11 @@ DiskReader::default_chunk_frames() bool DiskReader::set_name (string const & str) { - if (_name != str) { - for (uint32_t n = 0; n < DataType::num_types; ++n) { - if (_playlists[n]) { - _playlists[n]->set_name (str); - } - } - SessionObject::set_name(str); + string my_name = X_("reader:"); + my_name += str; + + if (_name != my_name) { + SessionObject::set_name (my_name); } return true; @@ -151,6 +149,7 @@ DiskReader::set_state (const XMLNode& node, int version) void DiskReader::realtime_handle_transport_stopped () { + realtime_set_speed (0.0f, true); } void @@ -244,14 +243,7 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, const bool need_disk_signal = result_required || _monitoring_choice == MonitorDisk || _monitoring_choice == MonitorCue; _need_butler = false; - - if (fabsf (_actual_speed) != 1.0f) { - midi_interpolation.set_speed (_target_speed); - interpolation.set_speed (_target_speed); - playback_distance = midi_interpolation.distance (nframes); - } else { - playback_distance = nframes; - } + playback_distance = calculate_playback_distance (nframes); if (!need_disk_signal) { @@ -339,7 +331,6 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, } chaninfo->buf->increment_read_ptr (playback_distance); - _speed = _target_speed; } /* MIDI data handling */ @@ -352,7 +343,7 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, get_playback (mbuf, playback_distance); /* vari-speed */ - if (_target_speed > 0 && _actual_speed != 1.0f) { + if (_actual_speed != 0.0 && fabsf (_actual_speed) != 1.0f) { MidiBuffer& mbuf (bufs.get_midi (0)); for (MidiBuffer::iterator i = mbuf.begin(); i != mbuf.end(); ++i) { MidiBuffer::TimeType *tme = i.timeptr(); @@ -428,6 +419,8 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, if (frames_read <= frames_written) { if ((frames_written - frames_read) + playback_distance < midi_readahead) { _need_butler = true; + } else { + cerr << name() << " fr " << frames_read << " > " << frames_written << endl; } } else { _need_butler = true; @@ -448,17 +441,14 @@ DiskReader::calculate_playback_distance (pframes_t nframes) { frameoffset_t playback_distance = nframes; - if (_actual_speed != 1.0f && _actual_speed != -1.0f) { + if (_target_speed != 1.0f && _target_speed != -1.0f) { interpolation.set_speed (_target_speed); - boost::shared_ptr c = channels.reader(); - int channel = 0; - for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++channel) { - playback_distance = interpolation.interpolate (channel, nframes, NULL, NULL); - } - } else { - playback_distance = nframes; + midi_interpolation.set_speed (_target_speed); + playback_distance = midi_interpolation.distance (nframes); } + _actual_speed = _target_speed; + if (_actual_speed < 0.0) { return -playback_distance; } else { @@ -496,7 +486,7 @@ DiskReader::overwrite_existing_buffers () /* AUDIO */ - bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f; + bool reversed = (_target_speed * _session.transport_speed()) < 0.0f; /* assume all are the same size */ framecnt_t size = c->front()->buf->bufsize(); @@ -839,7 +829,7 @@ DiskReader::refill_audio (Sample* mixdown_buffer, float* gain_buffer, framecnt_t int32_t ret = 0; framecnt_t to_read; RingBufferNPT::rw_vector vector; - bool const reversed = (_visible_speed * _session.transport_speed()) < 0.0f; + bool const reversed = (_target_speed * _session.transport_speed()) < 0.0f; framecnt_t total_space; framecnt_t zero_fill; uint32_t chan_n; @@ -1401,10 +1391,9 @@ DiskReader::refill_midi () } size_t write_space = _midi_buf->write_space(); - bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f; + bool reversed = (_target_speed * _session.transport_speed()) < 0.0f; DEBUG_TRACE (DEBUG::DiskIO, string_compose ("MIDI refill, write space = %1 file frame = %2\n", write_space, file_frame)); - //PBD::stacktrace (cerr, 20); /* no space to write */ if (write_space == 0) { diff --git a/libs/ardour/disk_writer.cc b/libs/ardour/disk_writer.cc index 4ca4c609a2..09b10696c0 100644 --- a/libs/ardour/disk_writer.cc +++ b/libs/ardour/disk_writer.cc @@ -417,13 +417,13 @@ DiskWriter::set_state (const XMLNode& node, int version) if (DiskIOProcessor::set_state (node, version)) { return -1; } - +#if 0 // XXX DISK if ((prop = node.property (X_("capture-alignment"))) != 0) { set_align_choice (AlignChoice (string_2_enum (prop->value(), _alignment_choice)), true); } else { set_align_choice (Automatic, true); } - +#endif if ((prop = node.property ("record-safe")) != 0) { _record_safe = PBD::string_is_affirmative (prop->value()) ? 1 : 0; @@ -1702,3 +1702,9 @@ DiskWriter::adjust_buffering () (*chan)->resize (_session.butler()->audio_diskstream_capture_buffer_size()); } } + +void +DiskWriter::realtime_handle_transport_stopped () +{ + realtime_set_speed (0.0f, true); +} diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index be85bc1d49..4e666b7c0a 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -397,20 +397,6 @@ MidiTrack::realtime_locate () _disk_reader->reset_tracker (); } -void -MidiTrack::realtime_handle_transport_stopped () -{ - Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); - - if (!lm.locked ()) { - return; - } - - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - (*i)->realtime_handle_transport_stopped (); - } -} - void MidiTrack::non_realtime_locate (framepos_t pos) { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 305af5beac..4ebc0cf82b 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -457,6 +457,7 @@ Route::process_output_buffers (BufferSet& bufs, _initial_delay + latency, longest_session_latency - latency); } + //cerr << name() << " run " << (*i)->name() << endl; (*i)->run (bufs, start_frame - latency, end_frame - latency, speed, nframes, *i != _processors.back()); bufs.set_count ((*i)->output_streams()); @@ -2825,88 +2826,7 @@ Route::set_processor_state (const XMLNode& node) /* CapturingProcessor should never be restored, it's always added explicitly when needed */ } else { - ProcessorList::iterator o; - - for (o = _processors.begin(); o != _processors.end(); ++o) { - XMLProperty const * id_prop = (*niter)->property(X_("id")); - if (id_prop && (*o)->id() == id_prop->value()) { - (*o)->set_state (**niter, Stateful::current_state_version); - new_order.push_back (*o); - break; - } - } - - // If the processor (*niter) is not on the route then create it - - if (o == _processors.end()) { - - boost::shared_ptr processor; - - if (prop->value() == "intsend") { - - processor.reset (new InternalSend (_session, _pannable, _mute_master, boost::dynamic_pointer_cast(shared_from_this()), boost::shared_ptr(), Delivery::Aux, true)); - - } else if (prop->value() == "ladspa" || prop->value() == "Ladspa" || - prop->value() == "lv2" || - prop->value() == "windows-vst" || - prop->value() == "mac-vst" || - prop->value() == "lxvst" || - prop->value() == "luaproc" || - prop->value() == "audiounit") { - - if (_session.get_disable_all_loaded_plugins ()) { - processor.reset (new UnknownProcessor (_session, **niter)); - } else { - processor.reset (new PluginInsert (_session)); - processor->set_owner (this); - if (_strict_io) { - boost::shared_ptr pi = boost::dynamic_pointer_cast(processor); - pi->set_strict_io (true); - } - - } - } else if (prop->value() == "port") { - - processor.reset (new PortInsert (_session, _pannable, _mute_master)); - - } else if (prop->value() == "send") { - - processor.reset (new Send (_session, _pannable, _mute_master, Delivery::Send, true)); - boost::shared_ptr send = boost::dynamic_pointer_cast (processor); - send->SelfDestruct.connect_same_thread (*this, - boost::bind (&Route::processor_selfdestruct, this, boost::weak_ptr (processor))); - - } else { - error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg; - continue; - } - - if (processor->set_state (**niter, Stateful::current_state_version) != 0) { - /* This processor could not be configured. Turn it into a UnknownProcessor */ - processor.reset (new UnknownProcessor (_session, **niter)); - } - - /* subscribe to Sidechain IO changes */ - boost::shared_ptr pi = boost::dynamic_pointer_cast (processor); - if (pi && pi->has_sidechain ()) { - pi->sidechain_input ()->changed.connect_same_thread (*this, boost::bind (&Route::sidechain_change_handler, this, _1, _2)); - } - - /* we have to note the monitor send here, otherwise a new one will be created - and the state of this one will be lost. - */ - boost::shared_ptr isend = boost::dynamic_pointer_cast (processor); - if (isend && isend->role() == Delivery::Listen) { - _monitor_send = isend; - } - - /* it doesn't matter if invisible processors are added here, as they - will be sorted out by setup_invisible_processors () shortly. - */ - - new_order.push_back (processor); - must_configure = true; - } + set_processor_state (**niter, prop, new_order, must_configure); } } @@ -2948,6 +2868,93 @@ Route::set_processor_state (const XMLNode& node) set_processor_positions (); } +bool +Route::set_processor_state (XMLNode const & node, XMLProperty const* prop, ProcessorList& new_order, bool& must_configure) +{ + ProcessorList::iterator o; + + for (o = _processors.begin(); o != _processors.end(); ++o) { + XMLProperty const * id_prop = node.property(X_("id")); + if (id_prop && (*o)->id() == id_prop->value()) { + (*o)->set_state (node, Stateful::current_state_version); + new_order.push_back (*o); + break; + } + } + + // If the processor (node) is not on the route then create it + + if (o == _processors.end()) { + + boost::shared_ptr processor; + + if (prop->value() == "intsend") { + + processor.reset (new InternalSend (_session, _pannable, _mute_master, boost::dynamic_pointer_cast(shared_from_this()), boost::shared_ptr(), Delivery::Aux, true)); + + } else if (prop->value() == "ladspa" || prop->value() == "Ladspa" || + prop->value() == "lv2" || + prop->value() == "windows-vst" || + prop->value() == "mac-vst" || + prop->value() == "lxvst" || + prop->value() == "luaproc" || + prop->value() == "audiounit") { + + if (_session.get_disable_all_loaded_plugins ()) { + processor.reset (new UnknownProcessor (_session, node)); + } else { + processor.reset (new PluginInsert (_session)); + processor->set_owner (this); + if (_strict_io) { + boost::shared_ptr pi = boost::dynamic_pointer_cast(processor); + pi->set_strict_io (true); + } + + } + } else if (prop->value() == "port") { + + processor.reset (new PortInsert (_session, _pannable, _mute_master)); + + } else if (prop->value() == "send") { + + processor.reset (new Send (_session, _pannable, _mute_master, Delivery::Send, true)); + boost::shared_ptr send = boost::dynamic_pointer_cast (processor); + send->SelfDestruct.connect_same_thread (*this, + boost::bind (&Route::processor_selfdestruct, this, boost::weak_ptr (processor))); + + } else { + return false; + } + + if (processor->set_state (node, Stateful::current_state_version) != 0) { + /* This processor could not be configured. Turn it into a UnknownProcessor */ + processor.reset (new UnknownProcessor (_session, node)); + } + + /* subscribe to Sidechain IO changes */ + boost::shared_ptr pi = boost::dynamic_pointer_cast (processor); + if (pi && pi->has_sidechain ()) { + pi->sidechain_input ()->changed.connect_same_thread (*this, boost::bind (&Route::sidechain_change_handler, this, _1, _2)); + } + + /* we have to note the monitor send here, otherwise a new one will be created + and the state of this one will be lost. + */ + boost::shared_ptr isend = boost::dynamic_pointer_cast (processor); + if (isend && isend->role() == Delivery::Listen) { + _monitor_send = isend; + } + + /* it doesn't matter if invisible processors are added here, as they + will be sorted out by setup_invisible_processors () shortly. + */ + + new_order.push_back (processor); + must_configure = true; + } + return true; +} + void Route::curve_reallocate () { diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 23d0c7ea42..3d3cea645c 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -1530,7 +1530,7 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a boost::shared_ptr rl = routes.reader(); for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { boost::shared_ptr tr = boost::dynamic_pointer_cast (*i); - if (tr && tr->realtime_set_speed (tr->speed(), true)) { + if (tr && tr->realtime_set_speed (_transport_speed, true)) { todo = PostTransportWork (todo | PostTransportSpeed); } } @@ -1694,7 +1694,7 @@ Session::start_transport () for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { boost::shared_ptr tr = boost::dynamic_pointer_cast (*i); if (tr) { - tr->realtime_set_speed (tr->speed(), true); + tr->realtime_set_speed (_transport_speed, true); } } @@ -1861,7 +1861,7 @@ Session::use_sync_source (Slave* new_slave) for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { boost::shared_ptr tr = boost::dynamic_pointer_cast (*i); if (tr && !tr->hidden()) { - if (tr->realtime_set_speed (tr->speed(), true)) { + if (tr->realtime_set_speed (_transport_speed, true)) { non_rt_required = true; } tr->set_slaved (_slave != 0); diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 41769ae471..d37fbb64c8 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -77,7 +77,6 @@ Track::init () } _disk_reader.reset (new DiskReader (_session, name(), dflags)); - _disk_reader->set_block_size (_session.get_block_size ()); _disk_reader->set_route (shared_from_this()); @@ -342,6 +341,7 @@ Track::set_name (const string& str) _disk_writer->set_write_source_name (diskstream_name); boost::shared_ptr me = boost::dynamic_pointer_cast (shared_from_this ()); + if (_playlists[data_type()]->all_regions_empty () && _session.playlists->playlists_for_track (me).size() == 1) { /* Only rename the diskstream (and therefore the playlist) if a) the playlist has never had a region added to it and @@ -358,6 +358,12 @@ Track::set_name (const string& str) _disk_writer->set_name (str); } + for (uint32_t n = 0; n < DataType::num_types; ++n) { + if (_playlists[n]) { + _playlists[n]->set_name (str); + } + } + /* save state so that the statefile fully reflects any filename changes */ if ((ret = Route::set_name (str)) == 0) { @@ -483,9 +489,9 @@ Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, if (no_meter) { BufferSet& bufs (_session.get_silent_buffers (n_process_buffers())); _meter->run (bufs, start_frame, end_frame, 1.0, nframes, true); - _input->process_input (boost::shared_ptr(), start_frame, end_frame, speed(), nframes); + _input->process_input (boost::shared_ptr(), start_frame, end_frame, _session.transport_speed(), nframes); } else { - _input->process_input (_meter, start_frame, end_frame, speed(), nframes); + _input->process_input (_meter, start_frame, end_frame, _session.transport_speed(), nframes); } } @@ -498,7 +504,7 @@ Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, fill_buffers_with_input (bufs, _input, nframes); if (_meter_point == MeterInput) { - _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true); + _meter->run (bufs, start_frame, end_frame, _session.transport_speed(), nframes, true); } passthru (bufs, start_frame, end_frame, nframes, false); @@ -707,6 +713,20 @@ Track::realtime_set_speed (double s, bool g) return _disk_writer->realtime_set_speed (s, g); } +void +Track::realtime_handle_transport_stopped () +{ + Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); + + if (!lm.locked ()) { + return; + } + + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + (*i)->realtime_handle_transport_stopped (); + } +} + void Track::transport_stopped_wallclock (struct tm & n, time_t t, bool g) { @@ -719,12 +739,6 @@ Track::pending_overwrite () const return _disk_reader->pending_overwrite (); } -double -Track::speed () const -{ - return _disk_reader->speed (); -} - void Track::prepare_to_stop (framepos_t t, framepos_t a) { @@ -1115,3 +1129,28 @@ Track::metering_state () const } return rv ? MeteringInput : MeteringRoute; } + +bool +Track::set_processor_state (XMLNode const & node, XMLProperty const* prop, ProcessorList& new_order, bool& must_configure) +{ + if (Route::set_processor_state (node, prop, new_order, must_configure)) { + return true; + } + + if (prop->value() == "diskreader") { + if (_disk_reader) { + _disk_reader->set_state (node, Stateful::current_state_version); + new_order.push_back (_disk_reader); + return true; + } + } else if (prop->value() == "diskwriter") { + if (_disk_writer) { + _disk_writer->set_state (node, Stateful::current_state_version); + new_order.push_back (_disk_writer); + return true; + } + } + + error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg; + return false; +} -- cgit v1.2.3