From 3f81b73f3643393fb9b166d0ad0c1cc83913afbc Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 25 Mar 2024 10:31:57 -0600 Subject: [PATCH] initial work on livetrax all-mono, direct outs and send-to-(master/monitor?) --- libs/ardour/ardour/route.h | 2 + libs/ardour/ardour/session.h | 2 + libs/ardour/route.cc | 78 ++++++++++++++++++++++-------------- libs/ardour/send.cc | 15 ++++++- libs/ardour/session.cc | 72 +++++++++++++++++++++++++-------- 5 files changed, 123 insertions(+), 46 deletions(-) diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index c157c46439..2b8758aa0b 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -99,6 +99,7 @@ class MonitorControl; class TriggerBox; class SurroundReturn; class SurroundSend; +class Send; class LIBARDOUR_API Route : public Stripable, public GraphNode, @@ -695,6 +696,7 @@ protected: std::shared_ptr _meter; std::shared_ptr _polarity; std::shared_ptr _triggerbox; + std::shared_ptr _master_send; bool _volume_applies_to_output; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 09ef6f25d9..665cb9debc 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1804,6 +1804,7 @@ private: MidiPortFlags exclude = MidiPortFlags (0)); void auto_connect (const AutoConnectRequest&); + void livetrax_auto_connect (std::shared_ptr); void queue_latency_recompute (); /* SessionEventManager interface */ @@ -1984,6 +1985,7 @@ private: bool find_route_name (std::string const &, uint32_t& id, std::string& name, bool); void count_existing_track_channels (ChanCount& in, ChanCount& out); void auto_connect_route (std::shared_ptr, bool, bool, const ChanCount&, const ChanCount&, const ChanCount& io = ChanCount(), const ChanCount& oo = ChanCount()); + void livetrax_auto_connect_route (std::shared_ptr); void midi_output_change_handler (IOChange change, void* /*src*/, std::weak_ptr midi_track); /* track numbering */ diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index afe660c5ed..c4e55db093 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -316,6 +316,11 @@ Route::init () panner_shell()->select_panner_by_uri ("http://ardour.org/plugin/panner_balance"); } + if (Profile->get_livetrax() && is_track()) { + _master_send.reset (new InternalSend (_session, _pannable, _mute_master, std::dynamic_pointer_cast (shared_from_this()), std::shared_ptr(), Delivery::Aux, false)); + _master_send->set_display_to_user (false); + } + /* now set up processor chain and invisible processors */ { Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ()); @@ -1847,10 +1852,11 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err) if ((*p)->can_support_io_configuration(in, out)) { - if (std::dynamic_pointer_cast (*p) - && std::dynamic_pointer_cast (*p)->role() == Delivery::Main - && !is_auditioner() - && (is_monitor() || _strict_io || Profile->get_mixbus ())) { + if (!Profile->get_livetrax() + && std::dynamic_pointer_cast (*p) + && std::dynamic_pointer_cast (*p)->role() == Delivery::Main + && !is_auditioner() + && (is_monitor() || _strict_io || Profile->get_mixbus ())) { /* with strict I/O the panner + output are forced to * follow the last processor's output. * @@ -2522,41 +2528,49 @@ Route::customize_plugin_insert (std::shared_ptr proc, uint32_t count, } bool -Route::set_strict_io (const bool enable) +Route::set_strict_io (bool enable) { Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ()); - if (_strict_io != enable) { - _strict_io = enable; - Glib::Threads::RWLock::ReaderLock lm (_processor_lock); + if (Profile->get_livetrax()) { + /* cannot be disabled, and is set to true by default */ + // enable = true; + } + + if (_strict_io == enable) { + return true; + } + + _strict_io = enable; + Glib::Threads::RWLock::ReaderLock lm (_processor_lock); + for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) { + std::shared_ptr pi; + if ((pi = std::dynamic_pointer_cast(*p)) != 0) { + pi->set_strict_io (_strict_io); + } + } + + list > c = try_configure_processors_unlocked (n_inputs (), 0); + + if (c.empty()) { + // not possible + _strict_io = !enable; // restore old value for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) { std::shared_ptr pi; if ((pi = std::dynamic_pointer_cast(*p)) != 0) { pi->set_strict_io (_strict_io); } } - - list > c = try_configure_processors_unlocked (n_inputs (), 0); - - if (c.empty()) { - // not possible - _strict_io = !enable; // restore old value - for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) { - std::shared_ptr pi; - if ((pi = std::dynamic_pointer_cast(*p)) != 0) { - pi->set_strict_io (_strict_io); - } - } - return false; - } - lm.release (); - - configure_processors (0); - lx.release (); - - processors_changed (RouteProcessorChange (RouteProcessorChange::CustomPinChange, false)); /* EMIT SIGNAL */ - _session.set_dirty (); + return false; } + lm.release (); + + configure_processors (0); + lx.release (); + + processors_changed (RouteProcessorChange (RouteProcessorChange::CustomPinChange, false)); /* EMIT SIGNAL */ + _session.set_dirty (); + return true; } @@ -5284,6 +5298,12 @@ Route::setup_invisible_processors () new_processors.push_back (_surround_send); } + if (Profile->get_livetrax() && is_track()) { + assert (_master_send); + assert (!_master_send->display_to_user()); + new_processors.push_back (_master_send); + } + /* MAIN OUTS */ assert (_main_outs); diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc index f6a20590d1..bfd3d9a6b9 100644 --- a/libs/ardour/send.cc +++ b/libs/ardour/send.cc @@ -36,6 +36,7 @@ #include "ardour/io.h" #include "ardour/meter.h" #include "ardour/panner_shell.h" +#include "ardour/profile.h" #include "ardour/send.h" #include "ardour/session.h" @@ -72,9 +73,17 @@ Send::name_and_id_new_send (Session& s, Role r, uint32_t& bitslot, bool ignore_b return string (); } + + + switch (r) { case Delivery::Aux: - return string_compose (_("aux %1"), (bitslot = s.next_aux_send_id ())); + if (Profile->get_livetrax()) { + /* The only type of aux send possible with livetrax */ + return _("master"); + } else { + return string_compose (_("aux %1"), (bitslot = s.next_aux_send_id ())); + } case Delivery::Listen: bitslot = 0; /* unused */ return _("listen"); // no ports, no need for numbering @@ -551,6 +560,10 @@ Send::set_name (const string& new_name) bool Send::display_to_user () const { + if (_role == Aux && Profile->get_livetrax()) { + return false; + } + /* we ignore Deliver::_display_to_user */ if (_role == Listen || _role == Foldback) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index b2bab19796..eadf641789 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -3021,6 +3021,8 @@ Session::new_audio_track (int input_channels, int output_channels, RouteGroup* r goto failed; } + std::cerr << "new track with " << output_channels << " channels\n"; + if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) { error << string_compose ( _("cannot configure %1 in/%2 out configuration for new audio track"), @@ -3104,7 +3106,7 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r << endmsg; goto failure; } - + if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) { error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"), @@ -3524,6 +3526,8 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool { PresentationInfo::ChangeSuspender cs; ensure_route_presentation_info_gap (order, new_routes.size()); + ensure_stripable_sort_order (); + reassign_track_numbers (); for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x, ++added) { @@ -3603,7 +3607,6 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool ARDOUR::GUIIdle (); } - ensure_stripable_sort_order (); } if (_monitor_out && !loading()) { @@ -3622,8 +3625,6 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool r->enable_surround_send (); } } - - reassign_track_numbers (); } void @@ -4580,15 +4581,19 @@ Session::reassign_track_numbers () StateProtector sp (this); - for (RouteList::iterator i = r.begin(); i != r.end(); ++i) { - assert (!(*i)->is_auditioner()); - if (std::dynamic_pointer_cast (*i)) { - (*i)->set_track_number(++tn); - } else if (!(*i)->is_main_bus ()) { - (*i)->set_track_number(--bn); + for (auto & route : r) { + assert (!route->is_auditioner()); + if (std::dynamic_pointer_cast (route)) { + route->set_track_number(++tn); + } else if (!route->is_main_bus ()) { + route->set_track_number(--bn); } - std::shared_ptr tb = (*i)->triggerbox(); + if (Profile->get_livetrax() && !route->is_auditioner() && route->is_track()) { + livetrax_auto_connect_route (route); + } + + std::shared_ptr tb = (route)->triggerbox(); if (tb) { tb->set_order (trigger_order); trigger_order++; @@ -4599,8 +4604,8 @@ Session::reassign_track_numbers () _track_number_decimals = decimals; if (decimals_changed && config.get_track_name_number ()) { - for (RouteList::iterator i = r.begin(); i != r.end(); ++i) { - std::shared_ptr t = std::dynamic_pointer_cast (*i); + for (auto & route : r) { + std::shared_ptr t = std::dynamic_pointer_cast (route); if (t) { t->resync_take_name (); } @@ -6462,7 +6467,7 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end, plist.add (Properties::whole_file, true); plist.add (Properties::length, len); //ToDo: in nutempo, if the Range is snapped to bbt, this should be in bbt (?) - plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true)); // TODO: allow custom region-name when consolidating + plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true)); // TODO: allow custom region-name when consolidating plist.add (Properties::tags, "(bounce)"); result = RegionFactory::create (srcs, plist, true); @@ -7669,6 +7674,13 @@ Session::cut_copy_section (timepos_t const& start_, timepos_t const& end_, timep commit_reversible_command (); } +void +Session::livetrax_auto_connect_route (std::shared_ptr route) +{ + ChanCount ignored; + auto_connect_route (route, true, true, ignored, ignored, ignored, ignored); +} + void Session::auto_connect_route (std::shared_ptr route, bool connect_inputs, @@ -7710,6 +7722,27 @@ Session::queue_latency_recompute () auto_connect_thread_wakeup (); } +void +Session::livetrax_auto_connect (std::shared_ptr route) +{ + vector physinputs; + vector physoutputs; + + get_physical_ports (physinputs, physoutputs, DataType::AUDIO); + + const vector::size_type n = route->track_number() - 1; + + route->input()->disconnect (this); + route->output()->disconnect (this); + + route->input()->connect (route->input()->ports().port (DataType::AUDIO, 0), physinputs[n % physinputs.size()], this); + route->output()->connect (route->output()->ports().port (DataType::AUDIO, 0), physoutputs[n % physoutputs.size()], this); + + DEBUG_TRACE (DEBUG::PortConnectAuto, string_compose ("livetrax auto connect %1 [%2] to %3 and %4\n", route->name(), route->track_number(), + physinputs[n % physinputs.size()], + physoutputs[n % physoutputs.size()])); +} + void Session::auto_connect (const AutoConnectRequest& ar) { @@ -7721,6 +7754,11 @@ Session::auto_connect (const AutoConnectRequest& ar) return; } + if (Profile->get_livetrax() && !route->is_auditioner() && route->is_track()) { + livetrax_auto_connect (route); + return; + } + /* If both inputs and outputs are auto-connected to physical ports, * use the max of input and output offsets to ensure auto-connected * port numbers always match up (e.g. the first audio input and the @@ -7750,7 +7788,6 @@ Session::auto_connect (const AutoConnectRequest& ar) vector physinputs; vector physoutputs; - /* for connecting track inputs we only want MIDI ports marked * for "music". */ @@ -7775,6 +7812,8 @@ Session::auto_connect (const AutoConnectRequest& ar) DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect input."); break; } + + DEBUG_TRACE (DEBUG::PortConnectAuto, string_compose ("autoconnected input %1/%2 [%4]to %3\n", route->name(), i, port, route->track_number())); } } @@ -7801,6 +7840,8 @@ Session::auto_connect (const AutoConnectRequest& ar) DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect output."); break; } + + DEBUG_TRACE (DEBUG::PortConnectAuto, string_compose ("autoconnected output %1/%2 [%4]to %3\n", route->name(), i, port, route->track_number())); } } } @@ -8132,4 +8173,3 @@ Session::foreach_route (void (Route::*method)()) ((r.get())->*method) (); } } -