X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession.cc;h=9bdf758a172148c8352d2b0b8890a0e56181210f;hb=1dc35d157eb45f2b28de954a7c98cc06a77c2802;hp=df8ae9fc51f355969c1b459e394141115fc930d8;hpb=24ec0b974d84df061cbbe645668dc62fa7120678;p=ardour.git diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index df8ae9fc51..9bdf758a17 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -93,19 +93,19 @@ #include "ardour/revision.h" #include "ardour/route_graph.h" #include "ardour/route_group.h" +#include "ardour/rt_tasklist.h" #include "ardour/send.h" #include "ardour/selection.h" #include "ardour/session.h" #include "ardour/session_directory.h" #include "ardour/session_playlists.h" -#include "ardour/slave.h" #include "ardour/smf_source.h" -#include "ardour/slave.h" #include "ardour/solo_isolate_control.h" #include "ardour/source_factory.h" #include "ardour/speakers.h" #include "ardour/tempo.h" #include "ardour/ticker.h" +#include "ardour/transport_master.h" #include "ardour/track.h" #include "ardour/types_convert.h" #include "ardour/user_bundle.h" @@ -184,23 +184,21 @@ Session::Session (AudioEngine &eng, , _seek_counter (0) , _session_range_location (0) , _session_range_end_is_free (true) - , _slave (0) , _silent (false) , _remaining_latency_preroll (0) + , _engine_speed (1.0) , _transport_speed (0) , _default_transport_speed (1.0) , _last_transport_speed (0) , _signalled_varispeed (0) , _target_transport_speed (0.0) , auto_play_legal (false) - , _last_slave_transport_sample (0) - , maximum_output_latency (0) , _requested_return_sample (-1) , current_block_size (0) , _worst_output_latency (0) , _worst_input_latency (0) - , _worst_track_latency (0) - , _worst_track_out_latency (0) + , _worst_route_latency (0) + , _send_latency_changes (0) , _have_captured (false) , _non_soloed_outs_muted (false) , _listening (false) @@ -210,13 +208,8 @@ Session::Session (AudioEngine &eng, , _was_seamless (Config->get_seamless_loop ()) , _under_nsm_control (false) , _xrun_count (0) - , delta_accumulator_cnt (0) - , average_slave_delta (1800) // !!! why 1800 ??? - , average_dir (0) - , have_first_delta_accumulator (false) - , _slave_state (Stopped) - , _mtc_active (false) - , _ltc_active (false) + , transport_master_tracking_state (Stopped) + , master_wait_end (0) , post_export_sync (false) , post_export_position (0) , _exporting (false) @@ -242,10 +235,6 @@ Session::Session (AudioEngine &eng, , _last_roll_location (0) , _last_roll_or_reversal_location (0) , _last_record_location (0) - , pending_locate_roll (false) - , pending_locate_sample (0) - , pending_locate_flush (false) - , pending_abort (false) , pending_auto_loop (false) , _mempool ("Session", 3145728) , lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool)) @@ -312,7 +301,6 @@ Session::Session (AudioEngine &eng, , _play_range (false) , _range_selection (-1,-1) , _object_selection (-1,-1) - , _preroll_record_punch_pos (-1) , _preroll_record_trim_len (0) , _count_in_once (false) , main_outs (0) @@ -463,6 +451,8 @@ Session::Session (AudioEngine &eng, StartTimeChanged.connect_same_thread (*this, boost::bind (&Session::start_time_changed, this, _1)); EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1)); + Send::ChangedLatency.connect_same_thread (*this, boost::bind (&Session::send_latency_compensation_change, this)); + emit_thread_start (); auto_connect_thread_start (); @@ -599,6 +589,8 @@ Session::immediately_post_engine () * session or set state for an existing one. */ + _rt_tasklist.reset (new RTTaskList ()); + if (how_many_dsp_threads () > 1) { /* For now, only create the graph if we are using >1 DSP threads, as it is a bit slower than the old code with 1 thread. @@ -656,8 +648,6 @@ Session::destroy () { Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); ltc_tx_cleanup(); - delete _slave; - _slave = 0; } /* disconnect from any and all signals that we are connected to */ @@ -671,7 +661,6 @@ Session::destroy () /* remove I/O objects before unsetting the engine session */ _click_io.reset (); - _ltc_input.reset (); _ltc_output.reset (); ControlProtocolManager::instance().drop_protocols (); @@ -687,12 +676,6 @@ Session::destroy () EngineStateController::instance()->remove_session(); #endif - /* drop slave, if any. We don't use use_sync_source (0) because - * there's no reason to do all the other stuff that may happen - * when calling that method. - */ - delete _slave; - /* deregister all ports - there will be no process or any other * callbacks from the engine any more. */ @@ -846,11 +829,9 @@ Session::destroy () bool del = true; switch (ev->type) { case SessionEvent::AutoLoop: - case SessionEvent::AutoLoopDeclick: case SessionEvent::Skip: case SessionEvent::PunchIn: case SessionEvent::PunchOut: - case SessionEvent::RecordStart: case SessionEvent::StopOnce: case SessionEvent::RangeStop: case SessionEvent::RangeLocate: @@ -893,21 +874,8 @@ Session::setup_ltc () { XMLNode* child = 0; - _ltc_input.reset (new IO (*this, X_("LTC In"), IO::Input)); _ltc_output.reset (new IO (*this, X_("LTC Out"), IO::Output)); - if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC In"))) != 0) { - _ltc_input->set_state (*(child->children().front()), Stateful::loading_state_version); - } else { - { - Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); - _ltc_input->ensure_io (ChanCount (DataType::AUDIO, 1), true, this); - // TODO use auto-connect thread somehow (needs a route currently) - // see note in Session::auto_connect_thread_run() why process lock is needed. - reconnect_ltc_input (); - } - } - if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC Out"))) != 0) { _ltc_output->set_state (*(child->children().front()), Stateful::loading_state_version); } else { @@ -923,7 +891,6 @@ Session::setup_ltc () * IO style of NAME/TYPE-{in,out}N */ - _ltc_input->nth (0)->set_name (X_("LTC-in")); _ltc_output->nth (0)->set_name (X_("LTC-out")); } @@ -1656,7 +1623,7 @@ Session::auto_punch_start_changed (Location* location) { replace_event (SessionEvent::PunchIn, location->start()); - if (get_record_enabled() && config.get_punch_in()) { + if (get_record_enabled() && config.get_punch_in() && !actively_recording ()) { /* capture start has been changed, so save new pending state */ save_state ("", true); } @@ -1665,19 +1632,14 @@ Session::auto_punch_start_changed (Location* location) void Session::auto_punch_end_changed (Location* location) { - samplepos_t when_to_stop = location->end(); - // when_to_stop += _worst_output_latency + _worst_input_latency; - replace_event (SessionEvent::PunchOut, when_to_stop); + replace_event (SessionEvent::PunchOut, location->end()); } void Session::auto_punch_changed (Location* location) { - samplepos_t when_to_stop = location->end(); - - replace_event (SessionEvent::PunchIn, location->start()); - //when_to_stop += _worst_output_latency + _worst_input_latency; - replace_event (SessionEvent::PunchOut, when_to_stop); + auto_punch_start_changed (location); + auto_punch_end_changed (location); } /** @param loc A loop location. @@ -1699,34 +1661,17 @@ Session::auto_loop_changed (Location* location) samplecnt_t dcl; auto_loop_declick_range (location, dcp, dcl); - if (transport_rolling() && play_loop) { - - replace_event (SessionEvent::AutoLoopDeclick, dcp, dcl); + bool rolling = transport_rolling (); - // if (_transport_sample > location->end()) { + if (rolling && play_loop) { if (_transport_sample < location->start() || _transport_sample > location->end()) { // relocate to beginning of loop clear_events (SessionEvent::LocateRoll); - request_locate (location->start(), true); } - else if (Config->get_seamless_loop() && !loop_changing) { - - // schedule a locate-roll to refill the disk readers at the - // previous loop end - loop_changing = true; - - if (location->end() > last_loopend) { - clear_events (SessionEvent::LocateRoll); - SessionEvent *ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, last_loopend, last_loopend, 0, true); - queue_event (ev); - } - - } } else { - clear_events (SessionEvent::AutoLoopDeclick); clear_events (SessionEvent::AutoLoop); } @@ -1736,13 +1681,12 @@ Session::auto_loop_changed (Location* location) samplepos_t pos; - if (!transport_rolling() && select_playhead_priority_target (pos)) { + if (!rolling && select_playhead_priority_target (pos)) { if (pos == location->start()) { request_locate (pos); } } - last_loopend = location->end(); set_dirty (); } @@ -1755,7 +1699,7 @@ Session::set_auto_punch_location (Location* location) if ((existing = _locations->auto_punch_location()) != 0 && existing != location) { punch_connections.drop_connections(); existing->set_auto_punch (false, this); - remove_event (existing->start(), SessionEvent::PunchIn); + clear_events (SessionEvent::PunchIn); clear_events (SessionEvent::PunchOut); auto_punch_location_changed (0); } @@ -1815,7 +1759,6 @@ Session::set_auto_loop_location (Location* location) samplepos_t dcp; samplecnt_t dcl; auto_loop_declick_range (existing, dcp, dcl); - remove_event (dcp, SessionEvent::AutoLoopDeclick); auto_loop_location_changed (0); } @@ -2119,7 +2062,6 @@ Session::disable_record (bool rt_context, bool force) if (!rt_context) { remove_pending_capture_state (); } - unset_preroll_record_punch (); } } @@ -2157,7 +2099,7 @@ Session::maybe_enable_record (bool rt_context) } if (_transport_speed) { - if (!config.get_punch_in() && !preroll_record_punch_enabled ()) { + if (!config.get_punch_in()) { enable_record (); } } else { @@ -3030,40 +2972,6 @@ Session::reconnect_midi_scene_ports(bool inputs) } } -void -Session::reconnect_mtc_ports () -{ - boost::shared_ptr mtc_in_ptr = _midi_ports->mtc_input_port(); - - if (!mtc_in_ptr) { - return; - } - - mtc_in_ptr->disconnect_all (); - - std::vector midi_port_states; - EngineStateController::instance()->get_physical_midi_input_states (midi_port_states); - - std::vector::iterator state_iter = midi_port_states.begin(); - - for (; state_iter != midi_port_states.end(); ++state_iter) { - if (state_iter->available && state_iter->mtc_in) { - mtc_in_ptr->connect (state_iter->name); - } - } - - if (!_midi_ports->mtc_input_port ()->connected () && - config.get_external_sync () && - (Config->get_sync_source () == MTC) ) { - config.set_external_sync (false); - } - - if ( ARDOUR::Profile->get_trx () ) { - // Tracks need this signal to update timecode_source_dropdown - MtcOrLtcInputPortChanged (); //emit signal - } -} - void Session::reconnect_mmc_ports(bool inputs) { @@ -3415,7 +3323,7 @@ Session::new_route_from_template (uint32_t how_many, PresentationInfo::order_t i } /* set this name in the XML description that we are about to use */ - +#warning fixme -- no more Diskstream if (pd == CopyPlaylist) { XMLNode* ds_node = find_named_node (node_copy, "Diskstream"); if (ds_node) { @@ -3483,9 +3391,7 @@ Session::new_route_from_template (uint32_t how_many, PresentationInfo::order_t i (*i)->remove_property (X_("bitslot")); } else if (type && type->value() == X_("port")) { - // PortInsert::set_state() handles the bitslot - (*i)->remove_property (X_("bitslot")); - (*i)->set_property ("ignore-name", "1"); + IOProcessor::prepare_for_reset (**i, name); } } } @@ -4342,6 +4248,16 @@ Session::get_stripables () const return rv; } +RouteList +Session::get_routelist (bool mixer_order) const +{ + boost::shared_ptr r = routes.reader (); + RouteList rv; + rv.insert (rv.end(), r->begin(), r->end()); + rv.sort (Stripable::Sorter (mixer_order)); + return rv; +} + boost::shared_ptr Session::get_routes_with_internal_returns() const { @@ -5499,7 +5415,6 @@ Session::setup_lua () #ifndef NDEBUG lua.Print.connect (&_lua_print); #endif - lua.tweak_rt_gc (); lua.sandbox (true); lua.do_command ( "function ArdourSession ()" @@ -5630,9 +5545,11 @@ Session::setup_lua () abort(); /*NOTREACHED*/ } + lua_mlock (L, 1); LuaBindings::stddef (L); LuaBindings::common (L); LuaBindings::dsp (L); + lua_mlock (L, 0); luabridge::push (L, this); lua_setglobal (L, "Session"); } @@ -5717,13 +5634,9 @@ Session::graph_reordered () resort_routes (); /* force all diskstreams to update their capture offset values to - reflect any changes in latencies within the graph. - */ - - boost::shared_ptr rl = routes.reader (); - for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { - (*i)->update_signal_latency (true); // XXX - } + * reflect any changes in latencies within the graph. + */ + update_route_latency (false, true); } /** @return Number of samples that there is disk space available to write, @@ -6833,9 +6746,76 @@ Session::unknown_processors () const } void -Session::update_latency (bool playback) +Session::set_worst_io_latencies_x (IOChange, void *) +{ + set_worst_io_latencies (); +} + +void +Session::send_latency_compensation_change () { + /* As a result of Send::set_output_latency() + * or InternalReturn::set_playback_offset () + * the send's own latency can change (source track + * is aligned with target bus). + * + * This can only happen be triggered by + * Route::update_signal_latency () + * when updating the processor latency. + * + * We need to walk the graph again to take those changes into account + * (we should probably recurse or process the graph in a 2 step process). + */ + ++_send_latency_changes; +} + +bool +Session::update_route_latency (bool playback, bool apply_to_delayline) +{ + /* Note: RouteList is process-graph sorted */ + boost::shared_ptr r = routes.reader (); + if (playback) { + /* reverse the list so that we work backwards from the last route to run to the first, + * this is not needed, but can help to reduce the iterations for aux-sends. + */ + RouteList* rl = routes.reader().get(); + r.reset (new RouteList (*rl)); + reverse (r->begin(), r->end()); + } + + bool changed = false; + int bailout = 0; +restart: + _send_latency_changes = 0; + _worst_route_latency = 0; + + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + // if (!(*i)->active()) { continue ; } // TODO + samplecnt_t l; + if ((*i)->signal_latency () != (l = (*i)->update_signal_latency (apply_to_delayline))) { + changed = true; + } + _worst_route_latency = std::max (l, _worst_route_latency); + } + + if (_send_latency_changes > 0) { + // only 1 extra iteration is needed (we allow only 1 level of aux-sends) + // BUT.. jack'n'sends'n'bugs + if (++bailout < 5) { + cerr << "restarting Session::update_latency. # of send changes: " << _send_latency_changes << " iteration: " << bailout << endl; + goto restart; + } + } + + DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_route_latency, (changed ? "yes" : "no"))); + + return changed; +} + +void +Session::update_latency (bool playback) +{ DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE"))); if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress || _route_deletion_in_progress) { @@ -6861,47 +6841,16 @@ Session::update_latency (bool playback) } if (playback) { - post_playback_latency (); + set_worst_output_latency (); + update_route_latency (true, true); } else { - post_capture_latency (); + set_worst_input_latency (); + update_route_latency (false, false); } DEBUG_TRACE (DEBUG::Latency, "JACK latency callback: DONE\n"); } -void -Session::post_playback_latency () -{ - set_worst_playback_latency (); - - boost::shared_ptr r = routes.reader (); - - _worst_track_out_latency = 0; // XXX remove me - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - assert (!(*i)->is_auditioner()); // XXX remove me - _worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ()); - } - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->active()) { continue ; } - (*i)->apply_latency_compensation (); - } -} - -void -Session::post_capture_latency () -{ - set_worst_capture_latency (); - - /* reflect any changes in capture latencies into capture offsets */ - - boost::shared_ptr rl = routes.reader(); - for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { - (*i)->update_signal_latency (); - } -} - void Session::initialize_latencies () { @@ -6917,12 +6866,12 @@ Session::initialize_latencies () void Session::set_worst_io_latencies () { - set_worst_playback_latency (); - set_worst_capture_latency (); + set_worst_output_latency (); + set_worst_input_latency (); } void -Session::set_worst_playback_latency () +Session::set_worst_output_latency () { if (_state_of_the_state & (InitialConnecting|Deletion)) { return; @@ -6946,7 +6895,7 @@ Session::set_worst_playback_latency () } void -Session::set_worst_capture_latency () +Session::set_worst_input_latency () { if (_state_of_the_state & (InitialConnecting|Deletion)) { return; @@ -6961,54 +6910,32 @@ Session::set_worst_capture_latency () boost::shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - boost::shared_ptr tr = boost::dynamic_pointer_cast (*i); - if (!tr) { - continue; - } _worst_input_latency = max (_worst_input_latency, (*i)->input()->latency()); } - DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst input latency: %1\n", _worst_input_latency)); + DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst input latency: %1\n", _worst_input_latency)); } void Session::update_latency_compensation (bool force_whole_graph) { - // TODO: consolidate - bool some_track_latency_changed = false; - if (_state_of_the_state & (InitialConnecting|Deletion)) { return; } - DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency compensation\n\n"); - - _worst_track_latency = 0; - - boost::shared_ptr r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - assert (!(*i)->is_auditioner()); // XXX remove me - if ((*i)->active()) { - samplecnt_t tl; - if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency () /* - (*i)->output()->user_latency()*/)) { - some_track_latency_changed = true; - } - _worst_track_latency = max (tl, _worst_track_latency); - } - } - - DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency, - (some_track_latency_changed ? "yes" : "no"))); - - DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n"); + bool some_track_latency_changed = update_route_latency (false, false); if (some_track_latency_changed || force_whole_graph) { _engine.update_latencies (); - } - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - (*i)->update_signal_latency (true); + /* above call will ask the backend up update its latencies, which + * eventually will trigger AudioEngine::latency_callback () and + * call Session::update_latency () + */ + } else { + boost::shared_ptr r = routes.reader (); + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + (*i)->apply_latency_compensation (); + } } } @@ -7050,39 +6977,12 @@ Session::operation_in_progress (GQuark op) const return (find (_current_trans_quarks.begin(), _current_trans_quarks.end(), op) != _current_trans_quarks.end()); } -boost::shared_ptr -Session::ltc_input_port () const -{ - assert (_ltc_input); - return _ltc_input->nth (0); -} - boost::shared_ptr Session::ltc_output_port () const { return _ltc_output ? _ltc_output->nth (0) : boost::shared_ptr (); } -void -Session::reconnect_ltc_input () -{ - if (_ltc_input) { - - string src = Config->get_ltc_source_port(); - - _ltc_input->disconnect (this); - - if (src != _("None") && !src.empty()) { - _ltc_input->nth (0)->connect (src); - } - - if ( ARDOUR::Profile->get_trx () ) { - // Tracks need this signal to update timecode_source_dropdown - MtcOrLtcInputPortChanged (); //emit signal - } - } -} - void Session::reconnect_ltc_output () { @@ -7346,6 +7246,7 @@ Session::auto_connect_thread_run () * modifies the capture-offset, which can be a problem. */ while (g_atomic_int_and (&_latency_recompute_pending, 0)) { + Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); update_latency_compensation (); } }