initial work on livetrax all-mono, direct outs and send-to-(master/monitor?)

This commit is contained in:
Paul Davis 2024-03-25 10:31:57 -06:00
parent 3aaa066652
commit 3f81b73f36
5 changed files with 123 additions and 46 deletions

View File

@ -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<PeakMeter> _meter;
std::shared_ptr<PolarityProcessor> _polarity;
std::shared_ptr<TriggerBox> _triggerbox;
std::shared_ptr<InternalSend> _master_send;
bool _volume_applies_to_output;

View File

@ -1804,6 +1804,7 @@ private:
MidiPortFlags exclude = MidiPortFlags (0));
void auto_connect (const AutoConnectRequest&);
void livetrax_auto_connect (std::shared_ptr<Route>);
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<Route>, bool, bool, const ChanCount&, const ChanCount&, const ChanCount& io = ChanCount(), const ChanCount& oo = ChanCount());
void livetrax_auto_connect_route (std::shared_ptr<Route>);
void midi_output_change_handler (IOChange change, void* /*src*/, std::weak_ptr<Route> midi_track);
/* track numbering */

View File

@ -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<Route> (shared_from_this()), std::shared_ptr<Route>(), 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<Delivery> (*p)
&& std::dynamic_pointer_cast<Delivery> (*p)->role() == Delivery::Main
&& !is_auditioner()
&& (is_monitor() || _strict_io || Profile->get_mixbus ())) {
if (!Profile->get_livetrax()
&& std::dynamic_pointer_cast<Delivery> (*p)
&& std::dynamic_pointer_cast<Delivery> (*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<Processor> 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<PluginInsert> pi;
if ((pi = std::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
pi->set_strict_io (_strict_io);
}
}
list<pair<ChanCount, ChanCount> > 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<PluginInsert> pi;
if ((pi = std::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
pi->set_strict_io (_strict_io);
}
}
list<pair<ChanCount, ChanCount> > 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<PluginInsert> pi;
if ((pi = std::dynamic_pointer_cast<PluginInsert>(*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);

View File

@ -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) {

View File

@ -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<Track> (*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<Track> (route)) {
route->set_track_number(++tn);
} else if (!route->is_main_bus ()) {
route->set_track_number(--bn);
}
std::shared_ptr<TriggerBox> tb = (*i)->triggerbox();
if (Profile->get_livetrax() && !route->is_auditioner() && route->is_track()) {
livetrax_auto_connect_route (route);
}
std::shared_ptr<TriggerBox> 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<Track> t = std::dynamic_pointer_cast<Track> (*i);
for (auto & route : r) {
std::shared_ptr<Track> t = std::dynamic_pointer_cast<Track> (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> route)
{
ChanCount ignored;
auto_connect_route (route, true, true, ignored, ignored, ignored, ignored);
}
void
Session::auto_connect_route (std::shared_ptr<Route> 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> route)
{
vector<string> physinputs;
vector<string> physoutputs;
get_physical_ports (physinputs, physoutputs, DataType::AUDIO);
const vector<string>::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<string> physinputs;
vector<string> 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) ();
}
}