X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession.cc;h=043d72d1283bed0edb34d445094a579f4ce5d25f;hb=2afaa517170fe18c3448ba7378621d80ee5667cf;hp=6caa41e9ed917de6e039215d8c72fb4ee912293c;hpb=7f4880ad12222b113e305fa2f690bc6b113ab975;p=ardour.git diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 6caa41e9ed..043d72d128 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -90,6 +90,7 @@ #include "ardour/recent_sessions.h" #include "ardour/region.h" #include "ardour/region_factory.h" +#include "ardour/revision.h" #include "ardour/route_graph.h" #include "ardour/route_group.h" #include "ardour/send.h" @@ -212,6 +213,7 @@ Session::Session (AudioEngine &eng, , _exporting (false) , _export_rolling (false) , _export_preroll (0) + , _export_latency (0) , _pre_export_mmc_enabled (false) , _name (snapshot_name) , _is_new (true) @@ -236,7 +238,7 @@ Session::Session (AudioEngine &eng, , pending_locate_flush (false) , pending_abort (false) , pending_auto_loop (false) - , _mempool ("Session", 1048576) + , _mempool ("Session", 2097152) , lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool)) , _n_lua_scripts (0) , _butler (new Butler (*this)) @@ -248,6 +250,7 @@ Session::Session (AudioEngine &eng, , _rt_thread_active (false) , _rt_emit_pending (false) , _ac_thread_active (false) + , _latency_recompute_pending (0) , step_speed (0) , outbound_mtc_timecode_frame (0) , next_quarter_frame_to_send (-1) @@ -316,6 +319,8 @@ Session::Session (AudioEngine &eng, { uint32_t sr = 0; + created_with = string_compose ("%1 %2", PROGRAM_NAME, revision); + pthread_mutex_init (&_rt_emit_mutex, 0); pthread_cond_init (&_rt_emit_cond, 0); @@ -1311,8 +1316,12 @@ Session::reset_monitor_section () _master_out->output()->disconnect (this); _monitor_out->output()->disconnect (this); - _monitor_out->input()->ensure_io (_master_out->output()->n_ports(), false, this); - _monitor_out->output()->ensure_io (_master_out->output()->n_ports(), false, this); + // monitor section follow master bus - except midi + ChanCount mon_chn (_master_out->output()->n_ports()); + mon_chn.set_midi (0); + + _monitor_out->input()->ensure_io (mon_chn, false, this); + _monitor_out->output()->ensure_io (mon_chn, false, this); for (uint32_t n = 0; n < limit; ++n) { boost::shared_ptr p = _monitor_out->input()->ports().nth_audio_port (n); @@ -1942,7 +1951,7 @@ void Session::set_all_tracks_record_enabled (bool enable ) { boost::shared_ptr rl = routes.reader(); - set_controls (route_list_to_control_list (rl, &Track::rec_enable_control), enable, Controllable::NoGroup); + set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), enable, Controllable::NoGroup); } void @@ -2305,7 +2314,7 @@ Session::resort_routes_using (boost::shared_ptr r) #ifndef NDEBUG DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n"); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 presentation order %2\n", (*i)->name(), (*i)->presentation_info().global_order())); + DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 presentation order %2\n", (*i)->name(), (*i)->presentation_info().order())); } #endif @@ -2573,6 +2582,7 @@ Session::new_midi_route (RouteGroup* route_group, uint32_t how_many, string name route_group->add (bus); } + bus->add_internal_return (); ret.push_back (bus); } @@ -2921,24 +2931,28 @@ Session::reconnect_mmc_ports(bool inputs) #endif void -Session::ensure_presentation_info_gap (PresentationInfo::order_t first_new_order, uint32_t how_many) +Session::ensure_route_presentation_info_gap (PresentationInfo::order_t first_new_order, uint32_t how_many) { if (first_new_order == PresentationInfo::max_order) { /* adding at end, no worries */ return; } - /* create a gap in the existing route order keys to accomodate new routes.*/ - boost::shared_ptr rd = routes.reader(); - for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) { - boost::shared_ptr rt (*ri); + /* create a gap in the presentation info to accomodate @param how_many + * new objects. + */ + StripableList sl; + get_stripables (sl); + + for (StripableList::iterator si = sl.begin(); si != sl.end(); ++si) { + boost::shared_ptr s (*si); - if (rt->presentation_info().special()) { + if (s->is_monitor() || s->is_auditioner()) { continue; } - if (rt->presentation_info().group_order () >= first_new_order) { - rt->set_presentation_group_order (rt->presentation_info().group_order () + how_many); + if (s->presentation_info().order () >= first_new_order) { + s->set_presentation_order (s->presentation_info().order () + how_many); } } } @@ -3071,8 +3085,6 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Bus"); - ensure_presentation_info_gap (order, how_many); - while (how_many) { if (!find_route_name (name_template.empty () ? _("Bus") : name_template, ++bus_id, bus_name, use_number)) { error << "cannot find name for new audio bus" << endmsg; @@ -3257,6 +3269,10 @@ Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::s (*i)->add_property ("bitslot", buf); (*i)->add_property ("name", name); } + else if (type && type->value() == X_("intreturn")) { + (*i)->remove_property (X_("bitslot")); + (*i)->add_property ("ignore-bitslot", "1"); + } else if (type && type->value() == X_("return")) { // Return::set_state() generates a new one (*i)->remove_property (X_("bitslot")); @@ -3391,7 +3407,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool } DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("ensure order gap starting at %1 for %2\n", order, new_routes.size())); - ensure_presentation_info_gap (order, new_routes.size()); + ensure_route_presentation_info_gap (order, new_routes.size()); for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x, ++added) { @@ -3404,6 +3420,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2)); r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1)); + r->processor_latency_changed.connect_same_thread (*this, boost::bind (&Session::queue_latency_recompute, this)); if (r->is_master()) { _master_out = r; @@ -3432,27 +3449,31 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool /* presentation info order may already have been set from XML */ - if (r->presentation_info().unordered()) { + if (!r->presentation_info().order_set()) { if (order == PresentationInfo::max_order) { /* just add to the end */ - r->set_presentation_group_order_explicit (n_routes + added); + r->set_presentation_order (n_routes + added, false); DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order not set, set to NR %1 + %2 = %3\n", n_routes, added, n_routes + added)); } else { - r->set_presentation_group_order_explicit (order + added); + r->set_presentation_order (order + added); DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order not set, set to %1 + %2 = %3\n", order, added, order + added)); } } else { - DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order already set to %1\n", r->presentation_info().group_order())); + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order already set to %1\n", r->presentation_info().order())); } } - DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("added route %1, group order %2 global order %3 type %4 (summary: %5)\n", +#if !defined(__APPLE__) && !defined(__FreeBSD__) + /* clang complains: 'operator<<' should be declared prior to the call site or in an associated namespace of one of its + * arguments std::ostream& operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid)" + */ + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("added route %1, group order %2 type %3 (summary: %4)\n", r->name(), - r->presentation_info().group_order(), - r->presentation_info().global_order(), + r->presentation_info().order(), enum_2_string (r->presentation_info().flags()), - r->presentation_info().to_string())); + r->presentation_info())); +#endif if (input_auto_connect || output_auto_connect) { @@ -3672,7 +3693,7 @@ Session::remove_routes (boost::shared_ptr routes_to_remove) return; } - Stripable::PresentationInfoChange(); /* EMIT SIGNAL */ + PresentationInfo::Change(); /* EMIT SIGNAL */ /* save the new state of the world */ @@ -4213,27 +4234,14 @@ Session::get_remote_nth_route (PresentationInfo::order_t n) const return boost::dynamic_pointer_cast (get_remote_nth_stripable (n, PresentationInfo::Route)); } -struct GlobalPresentationOrderSorter { - bool operator() (boost::shared_ptr a, boost::shared_ptr b) { - return a->presentation_info() < b->presentation_info(); - } -}; - boost::shared_ptr Session::get_remote_nth_stripable (PresentationInfo::order_t n, PresentationInfo::Flag flags) const { StripableList sl; PresentationInfo::order_t match_cnt = 0; - /* API is one-based, so adjust n */ - - if (n) { - --n; - } - get_stripables (sl); - GlobalPresentationOrderSorter cmp; - sl.sort (cmp); + sl.sort (Stripable::PresentationOrderSorter()); for (StripableList::const_iterator s = sl.begin(); s != sl.end(); ++s) { if ((*s)->presentation_info().flag_match (flags)) { @@ -4264,11 +4272,11 @@ struct PresentationOrderSorter { if (a->presentation_info().special() && !b->presentation_info().special()) { /* a is not ordered, b is; b comes before a */ return false; - } else if (b->presentation_info().unordered() && !a->presentation_info().unordered()) { + } else if (!b->presentation_info().order_set() && a->presentation_info().order_set()) { /* b is not ordered, a is; a comes before b */ return true; } else { - return a->presentation_info().global_order() < b->presentation_info().global_order(); + return a->presentation_info().order() < b->presentation_info().order(); } } }; @@ -5165,6 +5173,7 @@ Session::try_run_lua (pframes_t nframes) Glib::Threads::Mutex::Lock tm (lua_lock, Glib::Threads::TRY_LOCK); if (tm.locked ()) { try { (*_lua_run)(nframes); } catch (luabridge::LuaException const& e) { } + lua.collect_garbage_step (); } } @@ -5174,6 +5183,7 @@ Session::setup_lua () #ifndef NDEBUG lua.Print.connect (&_lua_print); #endif + lua.tweak_rt_gc (); lua.do_command ( "function ArdourSession ()" " local self = { scripts = {}, instances = {} }" @@ -5365,7 +5375,7 @@ Session::RoutePublicOrderSorter::operator() (boost::shared_ptr a, boost:: if (b->is_monitor()) { return false; } - return a->presentation_info() < b->presentation_info(); + return a->presentation_info().order() < b->presentation_info().order(); } bool @@ -6182,7 +6192,7 @@ Session::solo_control_mode_changed () the session's saved solo state). So just explicitly turn them all off. */ - set_controls (route_list_to_control_list (get_routes(), &Route::solo_control), 0.0, Controllable::NoGroup); + set_controls (route_list_to_control_list (get_routes(), &Stripable::solo_control), 0.0, Controllable::NoGroup); } } @@ -6712,7 +6722,7 @@ Session::notify_presentation_info_change () return; } - Stripable::PresentationInfoChange (); /* EMIT SIGNAL */ + PresentationInfo::Change (); /* EMIT SIGNAL */ reassign_track_numbers(); #ifdef USE_TRACKS_CODE_FEATURES @@ -6831,6 +6841,16 @@ Session::auto_connect_route (boost::shared_ptr route, bool connect_inputs } } +void +Session::queue_latency_recompute () +{ + g_atomic_int_inc (&_latency_recompute_pending); + if (pthread_mutex_trylock (&_auto_connect_mutex) == 0) { + pthread_cond_signal (&_auto_connect_cond); + pthread_mutex_unlock (&_auto_connect_mutex); + } +} + void Session::auto_connect (const AutoConnectRequest& ar) { @@ -6996,6 +7016,20 @@ Session::auto_connect_thread_run () } } + if (!actively_recording ()) { // might not be needed, + /* this is only used for updating plugin latencies, the + * graph does not change. so it's safe in general. + * BUT.. + * .. update_latency_compensation () entails set_capture_offset() + * which calls Diskstream::set_capture_offset () which + * modifies the capture offset... which can be a proplem + * in "prepare_to_stop" + */ + while (g_atomic_int_and (&_latency_recompute_pending, 0)) { + update_latency_compensation (); + } + } + pthread_cond_wait (&_auto_connect_cond, &_auto_connect_mutex); } pthread_mutex_unlock (&_auto_connect_mutex);