mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-06 13:45:43 +01:00
make monitor section an optional feature than can be added/removed as needed. this is a big commit, and breakage is possible. it has been moderately tested. this commit also locks the remote control ID of the master bus to 318 and the monitor section (if any) to 319. the numbers are based on MIDI Machine Control limits
git-svn-id: svn://localhost/ardour2/branches/3.0@11256 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
4b95a7912a
commit
508c5eb5bd
16 changed files with 409 additions and 218 deletions
|
|
@ -45,6 +45,8 @@
|
|||
#include "pbd/file_utils.h"
|
||||
#include "pbd/convert.h"
|
||||
#include "pbd/strsplit.h"
|
||||
#include "pbd/strsplit.h"
|
||||
#include "pbd/unwind.h"
|
||||
|
||||
#include "ardour/amp.h"
|
||||
#include "ardour/analyser.h"
|
||||
|
|
@ -539,110 +541,8 @@ Session::when_engine_running ()
|
|||
hookup_io ();
|
||||
|
||||
if (_is_new && !no_auto_connect()) {
|
||||
|
||||
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
|
||||
|
||||
/* don't connect the master bus outputs if there is a monitor bus */
|
||||
|
||||
if (_master_out && Config->get_auto_connect_standard_busses() && !_monitor_out) {
|
||||
|
||||
/* if requested auto-connect the outputs to the first N physical ports.
|
||||
*/
|
||||
|
||||
uint32_t limit = _master_out->n_outputs().n_total();
|
||||
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
boost::shared_ptr<Port> p = _master_out->output()->nth (n);
|
||||
string connect_to;
|
||||
if (outputs[p->type()].size() > n) {
|
||||
connect_to = outputs[p->type()][n];
|
||||
}
|
||||
|
||||
if (!connect_to.empty() && p->connected_to (connect_to) == false) {
|
||||
if (_master_out->output()->connect (p, connect_to, this)) {
|
||||
error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
|
||||
<< endmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_monitor_out) {
|
||||
|
||||
/* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
|
||||
are undefined, at best.
|
||||
*/
|
||||
|
||||
/* control out listens to master bus (but ignores it
|
||||
under some conditions)
|
||||
*/
|
||||
|
||||
uint32_t limit = _monitor_out->n_inputs().n_audio();
|
||||
|
||||
if (_master_out) {
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
boost::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
|
||||
boost::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
|
||||
|
||||
if (o) {
|
||||
string connect_to = o->name();
|
||||
if (_monitor_out->input()->connect (p, connect_to, this)) {
|
||||
error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
|
||||
<< endmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if control out is not connected, connect control out to physical outs
|
||||
*/
|
||||
|
||||
if (!_monitor_out->output()->connected ()) {
|
||||
|
||||
if (!Config->get_monitor_bus_preferred_bundle().empty()) {
|
||||
|
||||
boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
|
||||
|
||||
if (b) {
|
||||
_monitor_out->output()->connect_ports_to_bundle (b, this);
|
||||
} else {
|
||||
warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
|
||||
Config->get_monitor_bus_preferred_bundle())
|
||||
<< endmsg;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Monitor bus is audio only */
|
||||
uint32_t mod = n_physical_outputs.get (DataType::AUDIO);
|
||||
uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
|
||||
|
||||
if (mod != 0) {
|
||||
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
|
||||
boost::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
|
||||
string connect_to;
|
||||
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
||||
connect_to = outputs[DataType::AUDIO][n % mod];
|
||||
}
|
||||
|
||||
if (!connect_to.empty()) {
|
||||
if (_monitor_out->output()->connect (p, connect_to, this)) {
|
||||
error << string_compose (
|
||||
_("cannot connect control output %1 to %2"),
|
||||
n, connect_to)
|
||||
<< endmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto_connect_master_bus ();
|
||||
}
|
||||
|
||||
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
|
||||
|
|
@ -657,6 +557,226 @@ Session::when_engine_running ()
|
|||
_engine.set_session (this);
|
||||
}
|
||||
|
||||
void
|
||||
Session::auto_connect_master_bus ()
|
||||
{
|
||||
if (!_master_out || !Config->get_auto_connect_standard_busses() || _monitor_out) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* if requested auto-connect the outputs to the first N physical ports.
|
||||
*/
|
||||
|
||||
uint32_t limit = _master_out->n_outputs().n_total();
|
||||
vector<string> outputs[DataType::num_types];
|
||||
|
||||
for (uint32_t i = 0; i < DataType::num_types; ++i) {
|
||||
_engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
|
||||
}
|
||||
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
boost::shared_ptr<Port> p = _master_out->output()->nth (n);
|
||||
string connect_to;
|
||||
if (outputs[p->type()].size() > n) {
|
||||
connect_to = outputs[p->type()][n];
|
||||
}
|
||||
|
||||
if (!connect_to.empty() && p->connected_to (connect_to) == false) {
|
||||
if (_master_out->output()->connect (p, connect_to, this)) {
|
||||
error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
|
||||
<< endmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::remove_monitor_section ()
|
||||
{
|
||||
if (!_monitor_out) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* force reversion to Solo-In-Pace */
|
||||
Config->set_solo_control_is_listen_control (false);
|
||||
|
||||
{
|
||||
/* Hold process lock while doing this so that we don't hear bits and
|
||||
* pieces of audio as we work on each route.
|
||||
*/
|
||||
|
||||
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
|
||||
|
||||
/* Connect tracks to monitor section. Note that in an
|
||||
existing session, the internal sends will already exist, but we want the
|
||||
routes to notice that they connect to the control out specifically.
|
||||
*/
|
||||
|
||||
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
|
||||
|
||||
for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
|
||||
|
||||
if ((*x)->is_monitor()) {
|
||||
/* relax */
|
||||
} else if ((*x)->is_master()) {
|
||||
/* relax */
|
||||
} else {
|
||||
(*x)->drop_listen (_monitor_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove_route (_monitor_out);
|
||||
auto_connect_master_bus ();
|
||||
}
|
||||
|
||||
void
|
||||
Session::add_monitor_section ()
|
||||
{
|
||||
RouteList rl;
|
||||
|
||||
if (_monitor_out || !_master_out) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
|
||||
|
||||
if (r->init ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
|
||||
// boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
|
||||
#endif
|
||||
{
|
||||
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
|
||||
r->input()->ensure_io (_master_out->output()->n_ports(), false, this);
|
||||
r->output()->ensure_io (_master_out->output()->n_ports(), false, this);
|
||||
}
|
||||
|
||||
rl.push_back (r);
|
||||
add_routes (rl, false, false);
|
||||
|
||||
assert (_monitor_out);
|
||||
|
||||
/* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
|
||||
are undefined, at best.
|
||||
*/
|
||||
|
||||
uint32_t limit = _monitor_out->n_inputs().n_audio();
|
||||
|
||||
if (_master_out) {
|
||||
|
||||
/* connect the inputs to the master bus outputs. this
|
||||
* represents a separate data feed from the internal sends from
|
||||
* each route. as of jan 2011, it allows the monitor section to
|
||||
* conditionally ignore either the internal sends or the normal
|
||||
* input feed, but we should really find a better way to do
|
||||
* this, i think.
|
||||
*/
|
||||
|
||||
_master_out->output()->disconnect (this);
|
||||
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
boost::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
|
||||
boost::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
|
||||
|
||||
if (o) {
|
||||
string connect_to = o->name();
|
||||
if (_monitor_out->input()->connect (p, connect_to, this)) {
|
||||
error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
|
||||
<< endmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if monitor section is not connected, connect it to physical outs
|
||||
*/
|
||||
|
||||
if (Config->get_auto_connect_standard_busses() && !_monitor_out->output()->connected ()) {
|
||||
|
||||
if (!Config->get_monitor_bus_preferred_bundle().empty()) {
|
||||
|
||||
boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
|
||||
|
||||
if (b) {
|
||||
_monitor_out->output()->connect_ports_to_bundle (b, this);
|
||||
} else {
|
||||
warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
|
||||
Config->get_monitor_bus_preferred_bundle())
|
||||
<< endmsg;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Monitor bus is audio only */
|
||||
|
||||
uint32_t mod = n_physical_outputs.get (DataType::AUDIO);
|
||||
uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
|
||||
vector<string> outputs[DataType::num_types];
|
||||
|
||||
for (uint32_t i = 0; i < DataType::num_types; ++i) {
|
||||
_engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
|
||||
}
|
||||
|
||||
|
||||
if (mod != 0) {
|
||||
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
|
||||
boost::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
|
||||
string connect_to;
|
||||
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
||||
connect_to = outputs[DataType::AUDIO][n % mod];
|
||||
}
|
||||
|
||||
if (!connect_to.empty()) {
|
||||
if (_monitor_out->output()->connect (p, connect_to, this)) {
|
||||
error << string_compose (
|
||||
_("cannot connect control output %1 to %2"),
|
||||
n, connect_to)
|
||||
<< endmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Hold process lock while doing this so that we don't hear bits and
|
||||
* pieces of audio as we work on each route.
|
||||
*/
|
||||
|
||||
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
|
||||
|
||||
/* Connect tracks to monitor section. Note that in an
|
||||
existing session, the internal sends will already exist, but we want the
|
||||
routes to notice that they connect to the control out specifically.
|
||||
*/
|
||||
|
||||
|
||||
boost::shared_ptr<RouteList> rls = routes.reader ();
|
||||
|
||||
PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
|
||||
|
||||
for (RouteList::iterator x = rls->begin(); x != rls->end(); ++x) {
|
||||
|
||||
if ((*x)->is_monitor()) {
|
||||
/* relax */
|
||||
} else if ((*x)->is_master()) {
|
||||
/* relax */
|
||||
} else {
|
||||
(*x)->enable_monitor_send ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::hookup_io ()
|
||||
{
|
||||
|
|
@ -701,30 +821,6 @@ Session::hookup_io ()
|
|||
|
||||
Delivery::reset_panners ();
|
||||
|
||||
/* Connect tracks to monitor/listen bus if there is one. Note that in an
|
||||
existing session, the internal sends will already exist, but we want the
|
||||
routes to notice that they connect to the control out specifically.
|
||||
*/
|
||||
|
||||
if (_monitor_out) {
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
|
||||
|
||||
if ((*x)->is_monitor()) {
|
||||
|
||||
/* relax */
|
||||
|
||||
} else if ((*x)->is_master()) {
|
||||
|
||||
/* relax */
|
||||
|
||||
} else {
|
||||
|
||||
(*x)->listen_via_monitor ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Anyone who cares about input state, wake up and do something */
|
||||
|
||||
IOConnectionsComplete (); /* EMIT SIGNAL */
|
||||
|
|
@ -1467,7 +1563,7 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
|
|||
list<boost::shared_ptr<MidiTrack> > ret;
|
||||
uint32_t control_id;
|
||||
|
||||
control_id = ntracks() + nbusses();
|
||||
control_id = next_control_id ();
|
||||
|
||||
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("MIDI");
|
||||
|
||||
|
|
@ -1683,9 +1779,8 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
|
|||
* @param name_template string to use for the start of the name, or "" to use "Audio".
|
||||
*/
|
||||
list< boost::shared_ptr<AudioTrack> >
|
||||
Session::new_audio_track (
|
||||
int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template
|
||||
)
|
||||
Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group,
|
||||
uint32_t how_many, string name_template)
|
||||
{
|
||||
char track_name[32];
|
||||
uint32_t track_id = 0;
|
||||
|
|
@ -1694,7 +1789,7 @@ Session::new_audio_track (
|
|||
list<boost::shared_ptr<AudioTrack> > ret;
|
||||
uint32_t control_id;
|
||||
|
||||
control_id = ntracks() + nbusses() + 1;
|
||||
control_id = next_control_id ();
|
||||
|
||||
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Audio");
|
||||
|
||||
|
|
@ -1813,7 +1908,7 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
|
|||
RouteList ret;
|
||||
uint32_t control_id;
|
||||
|
||||
control_id = ntracks() + nbusses() + 1;
|
||||
control_id = next_control_id ();
|
||||
|
||||
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Bus");
|
||||
|
||||
|
|
@ -1901,7 +1996,7 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
|
|||
|
||||
XMLNode* node = tree.root();
|
||||
|
||||
control_id = ntracks() + nbusses() + 1;
|
||||
control_id = next_control_id ();
|
||||
|
||||
while (how_many) {
|
||||
|
||||
|
|
@ -2054,7 +2149,7 @@ Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
|
|||
} else if ((*x)->is_master()) {
|
||||
/* relax */
|
||||
} else {
|
||||
(*x)->listen_via_monitor ();
|
||||
(*x)->enable_monitor_send ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2153,7 +2248,7 @@ Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::
|
|||
void
|
||||
Session::remove_route (boost::shared_ptr<Route> route)
|
||||
{
|
||||
if (((route == _master_out) || (route == _monitor_out)) && !Config->get_allow_special_bus_removal()) {
|
||||
if (route == _master_out) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2175,13 +2270,6 @@ Session::remove_route (boost::shared_ptr<Route> route)
|
|||
}
|
||||
|
||||
if (route == _monitor_out) {
|
||||
|
||||
/* cancel control outs for all routes */
|
||||
|
||||
for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
|
||||
(*r)->drop_listen (_monitor_out);
|
||||
}
|
||||
|
||||
_monitor_out.reset ();
|
||||
}
|
||||
|
||||
|
|
@ -4564,3 +4652,9 @@ Session::session_name_is_legal (const string& path)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Session::next_control_id () const
|
||||
{
|
||||
return ntracks() + nbusses() + 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue