WS: use an object-oriented internal API for the mixer

- This allows to better handle strips & plugins connection lifecycles
- Coherent with the JS client design
This commit is contained in:
Luciano Iam 2020-08-29 17:01:35 +02:00 committed by Robin Gareus
parent 4a4734fbb1
commit 3509fe1589
No known key found for this signature in database
GPG key ID: A090BCE02CF57F04
5 changed files with 351 additions and 286 deletions

View file

@ -56,36 +56,35 @@ void
WebsocketsDispatcher::update_all_nodes (Client client) WebsocketsDispatcher::update_all_nodes (Client client)
{ {
for (uint32_t strip_n = 0; strip_n < mixer ().strip_count (); ++strip_n) { for (uint32_t strip_n = 0; strip_n < mixer ().strip_count (); ++strip_n) {
boost::shared_ptr<Stripable> strip = mixer ().nth_strip (strip_n); ArdourMixerStrip &strip = mixer ().nth_strip (strip_n);
bool is_vca = strip->presentation_info ().flags () & ARDOUR::PresentationInfo::VCA; bool is_vca = strip.stripable ()->presentation_info ().flags () & ARDOUR::PresentationInfo::VCA;
AddressVector strip_addr = AddressVector (); AddressVector strip_addr = AddressVector ();
strip_addr.push_back (strip_n); strip_addr.push_back (strip_n);
ValueVector strip_desc = ValueVector (); ValueVector strip_desc = ValueVector ();
strip_desc.push_back (strip->name ()); strip_desc.push_back (strip.name ());
strip_desc.push_back (is_vca); strip_desc.push_back (is_vca);
update (client, Node::strip_description, strip_addr, strip_desc); update (client, Node::strip_description, strip_addr, strip_desc);
update (client, Node::strip_gain, strip_n, mixer ().strip_gain (strip_n)); update (client, Node::strip_gain, strip_n, strip.gain ());
update (client, Node::strip_mute, strip_n, mixer ().strip_mute (strip_n)); update (client, Node::strip_mute, strip_n, strip.mute ());
// Pan and plugins not available in VCAs // Pan and plugins not available in VCAs
if (is_vca) { if (is_vca) {
continue; continue;
} }
boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route> (strip); boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route> (strip.stripable ());
if (!route) { if (!route) {
continue; continue;
} }
update (client, Node::strip_pan, strip_n, mixer ().strip_pan (strip_n)); update (client, Node::strip_pan, strip_n, strip.pan ());
for (uint32_t plugin_n = 0;; ++plugin_n) { for (uint32_t plugin_n = 0;; ++plugin_n) {
boost::shared_ptr<PluginInsert> insert = mixer () boost::shared_ptr<PluginInsert> insert = strip.nth_plugin (plugin_n).insert ();
.strip_plugin_insert (strip_n, plugin_n);
if (!insert) { if (!insert) {
break; break;
} }
@ -95,11 +94,11 @@ WebsocketsDispatcher::update_all_nodes (Client client)
static_cast<std::string> (plugin->name ())); static_cast<std::string> (plugin->name ()));
update (client, Node::strip_plugin_enable, strip_n, plugin_n, update (client, Node::strip_plugin_enable, strip_n, plugin_n,
mixer ().strip_plugin_enabled (strip_n, plugin_n)); strip.nth_plugin (plugin_n).enabled ());
for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) { for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) {
boost::shared_ptr<AutomationControl> a_ctrl = boost::shared_ptr<AutomationControl> a_ctrl =
mixer ().strip_plugin_param_control (strip_n, plugin_n, param_n); strip.nth_plugin (plugin_n).param_control (param_n);
if (!a_ctrl) { if (!a_ctrl) {
continue; continue;
} }
@ -130,7 +129,7 @@ WebsocketsDispatcher::update_all_nodes (Client client)
update (client, Node::strip_plugin_param_description, addr, val); update (client, Node::strip_plugin_param_description, addr, val);
TypedValue value = mixer ().strip_plugin_param_value (strip_n, plugin_n, param_n); TypedValue value = strip.nth_plugin (plugin_n).param_value (param_n);
update (client, Node::strip_plugin_param_value, strip_n, plugin_n, param_n, value); update (client, Node::strip_plugin_param_value, strip_n, plugin_n, param_n, value);
} }
} }
@ -190,9 +189,9 @@ WebsocketsDispatcher::strip_gain_handler (Client client, const NodeStateMessage&
uint32_t strip_id = state.nth_addr (0); uint32_t strip_id = state.nth_addr (0);
if (msg.is_write () && (state.n_val () > 0)) { if (msg.is_write () && (state.n_val () > 0)) {
mixer ().set_strip_gain (strip_id, state.nth_val (0)); mixer ().nth_strip (strip_id).set_gain (state.nth_val (0));
} else { } else {
update (client, Node::strip_gain, strip_id, mixer ().strip_gain (strip_id)); update (client, Node::strip_gain, strip_id, mixer ().nth_strip (strip_id).gain ());
} }
} }
@ -208,9 +207,9 @@ WebsocketsDispatcher::strip_pan_handler (Client client, const NodeStateMessage&
uint32_t strip_id = state.nth_addr (0); uint32_t strip_id = state.nth_addr (0);
if (msg.is_write () && (state.n_val () > 0)) { if (msg.is_write () && (state.n_val () > 0)) {
mixer ().set_strip_pan (strip_id, state.nth_val (0)); mixer ().nth_strip (strip_id).set_pan (state.nth_val (0));
} else { } else {
update (client, Node::strip_pan, strip_id, mixer ().strip_pan (strip_id)); update (client, Node::strip_pan, strip_id, mixer ().nth_strip (strip_id).pan ());
} }
} }
@ -226,9 +225,9 @@ WebsocketsDispatcher::strip_mute_handler (Client client, const NodeStateMessage&
uint32_t strip_id = state.nth_addr (0); uint32_t strip_id = state.nth_addr (0);
if (msg.is_write () && (state.n_val () > 0)) { if (msg.is_write () && (state.n_val () > 0)) {
mixer ().set_strip_mute (strip_id, state.nth_val (0)); mixer ().nth_strip (strip_id).set_mute (state.nth_val (0));
} else { } else {
update (client, Node::strip_mute, strip_id, mixer ().strip_mute (strip_id)); update (client, Node::strip_mute, strip_id, mixer ().nth_strip (strip_id).mute ());
} }
} }
@ -245,10 +244,10 @@ WebsocketsDispatcher::strip_plugin_enable_handler (Client client, const NodeStat
uint32_t plugin_id = state.nth_addr (1); uint32_t plugin_id = state.nth_addr (1);
if (msg.is_write () && (state.n_val () > 0)) { if (msg.is_write () && (state.n_val () > 0)) {
mixer ().set_strip_plugin_enabled (strip_id, plugin_id, state.nth_val (0)); mixer ().nth_strip (strip_id).nth_plugin (plugin_id).set_enabled (state.nth_val (0));
} else { } else {
update (client, Node::strip_plugin_enable, strip_id, plugin_id, update (client, Node::strip_plugin_enable, strip_id, plugin_id,
mixer ().strip_plugin_enabled (strip_id, plugin_id)); mixer ().nth_strip (strip_id).nth_plugin (plugin_id).enabled ());
} }
} }
@ -266,10 +265,10 @@ WebsocketsDispatcher::strip_plugin_param_value_handler (Client client, const Nod
uint32_t param_id = state.nth_addr (2); uint32_t param_id = state.nth_addr (2);
if (msg.is_write () && (state.n_val () > 0)) { if (msg.is_write () && (state.n_val () > 0)) {
mixer ().set_strip_plugin_param_value (strip_id, plugin_id, param_id, mixer ().nth_strip (strip_id).nth_plugin (plugin_id).set_param_value (param_id,
state.nth_val (0)); state.nth_val (0));
} else { } else {
TypedValue value = mixer ().strip_plugin_param_value (strip_id, plugin_id, param_id); TypedValue value = mixer ().nth_strip (strip_id).nth_plugin (plugin_id).param_value (param_id);
update (client, Node::strip_plugin_param_value, strip_id, plugin_id, param_id, value); update (client, Node::strip_plugin_param_value, strip_id, plugin_id, param_id, value);
} }
} }

View file

@ -16,7 +16,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "ardour/meter.h"
#include "ardour/plugin_insert.h" #include "ardour/plugin_insert.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/tempo.h" #include "ardour/tempo.h"
@ -57,21 +56,21 @@ struct StripGainObserver {
void operator() (ArdourFeedback* p, uint32_t strip_n) void operator() (ArdourFeedback* p, uint32_t strip_n)
{ {
// fires multiple times (4x as of ardour 6.0) // fires multiple times (4x as of ardour 6.0)
p->update_all (Node::strip_gain, strip_n, p->mixer ().strip_gain (strip_n)); p->update_all (Node::strip_gain, strip_n, p->mixer ().nth_strip (strip_n).gain ());
} }
}; };
struct StripPanObserver { struct StripPanObserver {
void operator() (ArdourFeedback* p, uint32_t strip_n) void operator() (ArdourFeedback* p, uint32_t strip_n)
{ {
p->update_all (Node::strip_pan, strip_n, p->mixer ().strip_pan (strip_n)); p->update_all (Node::strip_pan, strip_n, p->mixer ().nth_strip (strip_n).pan ());
} }
}; };
struct StripMuteObserver { struct StripMuteObserver {
void operator() (ArdourFeedback* p, uint32_t strip_n) void operator() (ArdourFeedback* p, uint32_t strip_n)
{ {
p->update_all (Node::strip_mute, strip_n, p->mixer ().strip_mute (strip_n)); p->update_all (Node::strip_mute, strip_n, p->mixer ().nth_strip (strip_n).mute ());
} }
}; };
@ -79,7 +78,7 @@ struct PluginBypassObserver {
void operator() (ArdourFeedback* p, uint32_t strip_n, uint32_t plugin_n) void operator() (ArdourFeedback* p, uint32_t strip_n, uint32_t plugin_n)
{ {
p->update_all (Node::strip_plugin_enable, strip_n, plugin_n, p->update_all (Node::strip_plugin_enable, strip_n, plugin_n,
p->mixer ().strip_plugin_enabled (strip_n, plugin_n)); p->mixer ().nth_strip (strip_n).nth_plugin (plugin_n).enabled ());
} }
}; };
@ -92,7 +91,7 @@ struct PluginParamValueObserver {
return; return;
} }
p->update_all (Node::strip_plugin_param_value, strip_n, plugin_n, param_n, p->update_all (Node::strip_plugin_param_value, strip_n, plugin_n, param_n,
ArdourMixer::plugin_param_value (control)); ArdourMixerPlugin::param_value (control));
} }
}; };
@ -117,17 +116,17 @@ ArdourFeedback::stop ()
_periodic_connection.disconnect (); _periodic_connection.disconnect ();
_transport_connections.drop_connections (); _transport_connections.drop_connections ();
for (StripConnectionMap::iterator it = _strip_connections.begin (); it != _strip_connections.end(); ++it) { /*for (StripConnectionMap::iterator it = _strip_connections.begin (); it != _strip_connections.end(); ++it) {
it->second->drop_connections (); it->second->drop_connections ();
} }
_strip_connections.clear(); _strip_connections.clear();
*/
for (PluginConnectionMap::iterator it = _plugin_connections.begin (); it != _plugin_connections.end(); ++it) { /*for (PluginConnectionMap::iterator it = _plugin_connections.begin (); it != _plugin_connections.end(); ++it) {
it->second->drop_connections (); it->second->drop_connections ();
} }
_plugin_connections.clear(); _plugin_connections.clear();*/
return 0; return 0;
} }
@ -181,10 +180,7 @@ ArdourFeedback::poll () const
update_all (Node::transport_time, transport ().time ()); update_all (Node::transport_time, transport ().time ());
for (uint32_t strip_n = 0; strip_n < mixer ().strip_count (); ++strip_n) { for (uint32_t strip_n = 0; strip_n < mixer ().strip_count (); ++strip_n) {
// meters float db = mixer ().nth_strip (strip_n).meter_level_db ();
boost::shared_ptr<Stripable> strip = mixer ().nth_strip (strip_n);
boost::shared_ptr<PeakMeter> meter = strip->peak_meter ();
float db = meter ? meter->meter_level (0, MeterMCP) : -193;
update_all (Node::strip_meter, strip_n, static_cast<double> (db)); update_all (Node::strip_meter, strip_n, static_cast<double> (db));
} }
@ -207,27 +203,21 @@ void
ArdourFeedback::observe_mixer () ArdourFeedback::observe_mixer ()
{ {
for (uint32_t strip_n = 0; strip_n < mixer ().strip_count (); ++strip_n) { for (uint32_t strip_n = 0; strip_n < mixer ().strip_count (); ++strip_n) {
boost::shared_ptr<Stripable> strip = mixer ().nth_strip (strip_n); boost::shared_ptr<Stripable> stripable = mixer ().nth_strip (strip_n).stripable ();
boost::shared_ptr<PBD::ScopedConnectionList> connections = mixer().nth_strip (strip_n).connections ();
std::unique_ptr<PBD::ScopedConnectionList> connections (new PBD::ScopedConnectionList()); stripable->gain_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
strip->gain_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
boost::bind<void> (StripGainObserver (), this, strip_n), event_loop ()); boost::bind<void> (StripGainObserver (), this, strip_n), event_loop ());
if (strip->pan_azimuth_control ()) { if (stripable->pan_azimuth_control ()) {
strip->pan_azimuth_control ()->Changed.connect (*connections, MISSING_INVALIDATOR, stripable->pan_azimuth_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
boost::bind<void> (StripPanObserver (), this, strip_n), event_loop ()); boost::bind<void> (StripPanObserver (), this, strip_n), event_loop ());
} }
strip->mute_control ()->Changed.connect (*connections, MISSING_INVALIDATOR, stripable->mute_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
boost::bind<void> (StripMuteObserver (), this, strip_n), event_loop ()); boost::bind<void> (StripMuteObserver (), this, strip_n), event_loop ());
strip->DropReferences.connect (*connections, MISSING_INVALIDATOR, observe_strip_plugins (strip_n, stripable);
boost::bind (&ArdourFeedback::on_drop_strip, this, strip_n), event_loop ());
_strip_connections[strip_n] = std::move (connections);
observe_strip_plugins (strip_n, strip);
} }
} }
@ -235,7 +225,7 @@ void
ArdourFeedback::observe_strip_plugins (uint32_t strip_n, boost::shared_ptr<ARDOUR::Stripable> strip) ArdourFeedback::observe_strip_plugins (uint32_t strip_n, boost::shared_ptr<ARDOUR::Stripable> strip)
{ {
for (uint32_t plugin_n = 0;; ++plugin_n) { for (uint32_t plugin_n = 0;; ++plugin_n) {
boost::shared_ptr<PluginInsert> insert = mixer ().strip_plugin_insert (strip_n, plugin_n); boost::shared_ptr<PluginInsert> insert = mixer ().nth_strip (strip_n).nth_plugin (plugin_n).insert ();
if (!insert) { if (!insert) {
break; break;
} }
@ -250,11 +240,11 @@ ArdourFeedback::observe_strip_plugins (uint32_t strip_n, boost::shared_ptr<ARDOU
boost::bind<void> (PluginBypassObserver (), this, strip_n, plugin_n), event_loop ()); boost::bind<void> (PluginBypassObserver (), this, strip_n, plugin_n), event_loop ());
} }
insert->DropReferences.connect (*connections, MISSING_INVALIDATOR, //insert->DropReferences.connect (*connections, MISSING_INVALIDATOR,
boost::bind (&ArdourFeedback::on_drop_plugin, this, strip_n, plugin_n), event_loop ()); // boost::bind (&ArdourFeedback::on_drop_plugin, this, strip_n, plugin_n), event_loop ());
// assume each strip can hold up to 65535 plugins // assume each strip can hold up to 65535 plugins
_plugin_connections[(strip_n << 16) | plugin_n] = std::move (connections); //_plugin_connections[(strip_n << 16) | plugin_n] = std::move (connections);
observe_strip_plugin_param_values (strip_n, plugin_n, insert); observe_strip_plugin_param_values (strip_n, plugin_n, insert);
} }
@ -267,42 +257,17 @@ ArdourFeedback::observe_strip_plugin_param_values (uint32_t strip_n,
boost::shared_ptr<Plugin> plugin = insert->plugin (); boost::shared_ptr<Plugin> plugin = insert->plugin ();
for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) { for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) {
boost::shared_ptr<AutomationControl> control = mixer ().strip_plugin_param_control ( boost::shared_ptr<AutomationControl> control = mixer ().nth_strip (strip_n).nth_plugin (plugin_n).param_control (param_n);
strip_n, plugin_n, param_n);
if (!control) { if (!control) {
continue; continue;
} }
PBD::ScopedConnectionList *connections = _plugin_connections[(strip_n << 16) | plugin_n].get(); /*PBD::ScopedConnectionList *connections = _plugin_connections[(strip_n << 16) | plugin_n].get();
control->Changed.connect (*connections, MISSING_INVALIDATOR, control->Changed.connect (*connections, MISSING_INVALIDATOR,
boost::bind<void> (PluginParamValueObserver (), this, strip_n, plugin_n, param_n, boost::bind<void> (PluginParamValueObserver (), this, strip_n, plugin_n, param_n,
boost::weak_ptr<AutomationControl>(control)), boost::weak_ptr<AutomationControl>(control)),
event_loop ()); event_loop ());*/
} }
} }
void
ArdourFeedback::on_drop_strip (uint32_t strip_n)
{
for (uint32_t plugin_n = 0;; ++plugin_n) {
boost::shared_ptr<PluginInsert> insert = mixer ().strip_plugin_insert (strip_n, plugin_n);
if (!insert) {
break;
}
on_drop_plugin (strip_n, plugin_n);
}
_strip_connections[strip_n]->drop_connections ();
_strip_connections.erase (strip_n);
}
void
ArdourFeedback::on_drop_plugin (uint32_t strip_n, uint32_t plugin_n)
{
uint32_t key = (strip_n << 16) | plugin_n;
_plugin_connections[key]->drop_connections ();
_plugin_connections.erase (key);
}

View file

@ -46,12 +46,6 @@ private:
PBD::ScopedConnectionList _transport_connections; PBD::ScopedConnectionList _transport_connections;
sigc::connection _periodic_connection; sigc::connection _periodic_connection;
typedef boost::unordered_map<uint32_t, std::unique_ptr<PBD::ScopedConnectionList>> StripConnectionMap;
StripConnectionMap _strip_connections;
typedef boost::unordered_map<uint32_t, std::unique_ptr<PBD::ScopedConnectionList>> PluginConnectionMap;
StripConnectionMap _plugin_connections; // also holds connections to parameters
bool poll () const; bool poll () const;
void observe_transport (); void observe_transport ();
@ -59,9 +53,6 @@ private:
void observe_strip_plugins (uint32_t, boost::shared_ptr<ARDOUR::Stripable>); void observe_strip_plugins (uint32_t, boost::shared_ptr<ARDOUR::Stripable>);
void observe_strip_plugin_param_values (uint32_t, uint32_t, void observe_strip_plugin_param_values (uint32_t, uint32_t,
boost::shared_ptr<ARDOUR::PluginInsert>); boost::shared_ptr<ARDOUR::PluginInsert>);
void on_drop_strip (uint32_t);
void on_drop_plugin (uint32_t, uint32_t);
}; };
#endif // _ardour_surface_websockets_feedback_h_ #endif // _ardour_surface_websockets_feedback_h_

View file

@ -17,6 +17,7 @@
*/ */
#include "ardour/dB.h" #include "ardour/dB.h"
#include "ardour/meter.h"
#include "ardour/plugin_insert.h" #include "ardour/plugin_insert.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "pbd/controllable.h" #include "pbd/controllable.h"
@ -25,157 +26,33 @@
using namespace ARDOUR; using namespace ARDOUR;
int ArdourMixerPlugin::ArdourMixerPlugin (boost::shared_ptr<ARDOUR::PluginInsert> insert)
ArdourMixer::start () : _insert (insert)
, _connections (boost::shared_ptr<PBD::ScopedConnectionList> (new PBD::ScopedConnectionList()))
{}
boost::shared_ptr<ARDOUR::PluginInsert>
ArdourMixerPlugin::insert () const
{ {
/* take an indexed snapshot of current strips */ return _insert;
StripableList strips;
session ().get_stripables (strips, PresentationInfo::AllStripables);
for (StripableList::iterator strip = strips.begin (); strip != strips.end (); ++strip) {
_strips.push_back (*strip);
}
return 0;
}
int
ArdourMixer::stop ()
{
_strips.clear ();
return 0;
}
double
ArdourMixer::to_db (double k)
{
if (k == 0) {
return -std::numeric_limits<double>::infinity ();
}
float db = accurate_coefficient_to_dB (static_cast<float> (k));
return static_cast<double> (db);
}
double
ArdourMixer::from_db (double db)
{
if (db < -192) {
return 0;
}
float k = dB_to_coefficient (static_cast<float> (db));
return static_cast<double> (k);
}
double
ArdourMixer::strip_gain (uint32_t strip_n) const
{
return to_db (nth_strip (strip_n)->gain_control ()->get_value ());
}
void
ArdourMixer::set_strip_gain (uint32_t strip_n, double db)
{
nth_strip (strip_n)->gain_control ()->set_value (from_db (db), PBD::Controllable::NoGroup);
}
double
ArdourMixer::strip_pan (uint32_t strip_n) const
{
boost::shared_ptr<AutomationControl> ac = nth_strip (strip_n)->pan_azimuth_control ();
if (!ac) {
/* TODO: inform GUI that strip has no panner */
return 0;
}
return ac->internal_to_interface (ac->get_value ());
}
void
ArdourMixer::set_strip_pan (uint32_t strip_n, double value)
{
boost::shared_ptr<AutomationControl> ac = nth_strip (strip_n)->pan_azimuth_control ();
if (!ac) {
return;
}
ac->set_value (ac->interface_to_internal (value), PBD::Controllable::NoGroup);
} }
bool bool
ArdourMixer::strip_mute (uint32_t strip_n) const ArdourMixerPlugin::enabled () const
{ {
return nth_strip (strip_n)->mute_control ()->muted (); insert ()->enabled ();
} }
void void
ArdourMixer::set_strip_mute (uint32_t strip_n, bool mute) ArdourMixerPlugin::set_enabled (bool enabled)
{ {
nth_strip (strip_n)->mute_control ()->set_value (mute ? 1.0 : 0.0, PBD::Controllable::NoGroup); insert ()->enable (enabled);
}
bool
ArdourMixer::strip_plugin_enabled (uint32_t strip_n, uint32_t plugin_n) const
{
return strip_plugin_insert (strip_n, plugin_n)->enabled ();
}
void
ArdourMixer::set_strip_plugin_enabled (uint32_t strip_n, uint32_t plugin_n, bool enabled)
{
strip_plugin_insert (strip_n, plugin_n)->enable (enabled);
} }
TypedValue TypedValue
ArdourMixer::strip_plugin_param_value (uint32_t strip_n, uint32_t plugin_n, ArdourMixerPlugin::param_value (uint32_t param_n)
uint32_t param_n) const
{
return plugin_param_value (strip_plugin_param_control (strip_n, plugin_n, param_n));
}
void
ArdourMixer::set_strip_plugin_param_value (uint32_t strip_n, uint32_t plugin_n,
uint32_t param_n, TypedValue value)
{
boost::shared_ptr<AutomationControl> control = strip_plugin_param_control (
strip_n, plugin_n, param_n);
if (control) {
ParameterDescriptor pd = control->desc ();
double dbl_val;
if (pd.toggled) {
dbl_val = static_cast<double> (static_cast<bool> (value));
} else if (pd.enumeration || pd.integer_step) {
dbl_val = static_cast<double> (static_cast<int> (value));
} else {
dbl_val = static_cast<double> (value);
}
control->set_value (dbl_val, PBD::Controllable::NoGroup);
}
}
uint32_t
ArdourMixer::strip_count () const
{
return _strips.size ();
}
boost::shared_ptr<Stripable>
ArdourMixer::nth_strip (uint32_t strip_n) const
{
if (strip_n < _strips.size ()) {
return _strips[strip_n];
}
return boost::shared_ptr<Stripable> ();
}
TypedValue
ArdourMixer::plugin_param_value (boost::shared_ptr<ARDOUR::AutomationControl> control)
{ {
boost::shared_ptr<ARDOUR::AutomationControl> control = param_control (param_n);
TypedValue value = TypedValue (); TypedValue value = TypedValue ();
if (control) { if (control) {
@ -193,48 +70,241 @@ ArdourMixer::plugin_param_value (boost::shared_ptr<ARDOUR::AutomationControl> co
return value; return value;
} }
boost::shared_ptr<PluginInsert> void
ArdourMixer::strip_plugin_insert (uint32_t strip_n, uint32_t plugin_n) const ArdourMixerPlugin::set_param_value (uint32_t param_n, TypedValue value)
{ {
boost::shared_ptr<Stripable> strip = nth_strip (strip_n); boost::shared_ptr<AutomationControl> control = param_control (param_n);
if ((strip->presentation_info ().flags () & ARDOUR::PresentationInfo::VCA) == 0) { if (control) {
boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route> (strip); ParameterDescriptor pd = control->desc ();
double dbl_val;
if (route) { if (pd.toggled) {
boost::shared_ptr<Processor> processor = route->nth_plugin (plugin_n); dbl_val = static_cast<double> (static_cast<bool> (value));
} else if (pd.enumeration || pd.integer_step) {
dbl_val = static_cast<double> (static_cast<int> (value));
} else {
dbl_val = static_cast<double> (value);
}
if (processor) { control->set_value (dbl_val, PBD::Controllable::NoGroup);
boost::shared_ptr<PluginInsert> insert = }
boost::static_pointer_cast<PluginInsert> (processor); }
if (insert) { boost::shared_ptr<ARDOUR::AutomationControl>
return insert; ArdourMixerPlugin::param_control (uint32_t param_n) const
} {
bool ok = false;
boost::shared_ptr<Plugin> plugin = _insert->plugin ();
uint32_t control_id = plugin->nth_parameter (param_n, ok);
if (!ok || !plugin->parameter_is_input (control_id)) {
throw ArdourMixerNotFoundException("invalid automation control");
}
return _insert->automation_control (Evoral::Parameter (PluginAutomation, 0, control_id));
}
ArdourMixerStrip::ArdourMixerStrip (boost::shared_ptr<ARDOUR::Stripable> stripable)
: _stripable (stripable)
, _connections (boost::shared_ptr<PBD::ScopedConnectionList> (new PBD::ScopedConnectionList()))
{
if (_stripable->presentation_info ().flags () & ARDOUR::PresentationInfo::VCA) {
return;
}
boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route> (_stripable);
if (!route) {
return;
}
for (uint32_t plugin_n = 0;; ++plugin_n) {
boost::shared_ptr<Processor> processor = route->nth_plugin (plugin_n);
if (processor) {
boost::shared_ptr<PluginInsert> insert = boost::static_pointer_cast<PluginInsert> (processor);
if (insert) {
ArdourMixerPlugin plugin (insert);
_plugins.push_back (plugin);
} }
} }
} }
return boost::shared_ptr<PluginInsert> ();
} }
boost::shared_ptr<AutomationControl> boost::shared_ptr<ARDOUR::Stripable>
ArdourMixer::strip_plugin_param_control (uint32_t strip_n, uint32_t plugin_n, ArdourMixerStrip::stripable () const
uint32_t param_n) const
{ {
boost::shared_ptr<PluginInsert> insert = strip_plugin_insert (strip_n, plugin_n); return _stripable;
}
if (insert) { boost::shared_ptr<PBD::ScopedConnectionList>
bool ok = false; ArdourMixerStrip::connections () const
boost::shared_ptr<Plugin> plugin = insert->plugin (); {
uint32_t control_id = plugin->nth_parameter (param_n, ok); return _connections;
}
if (ok && plugin->parameter_is_input (control_id)) { int
boost::shared_ptr<AutomationControl> control = ArdourMixerStrip::plugin_count () const
insert->automation_control (Evoral::Parameter (PluginAutomation, 0, control_id)); {
return control; return _plugins.size ();
} }
ArdourMixerPlugin&
ArdourMixerStrip::nth_plugin (uint32_t plugin_n)
{
if (plugin_n < _plugins.size ()) {
return _plugins[plugin_n];
} }
return boost::shared_ptr<AutomationControl> (); throw ArdourMixerNotFoundException (""/*"Plugin with ID " + plugin_n + " not found"*/);
}
double
ArdourMixerStrip::gain () const
{
return to_db (_stripable->gain_control ()->get_value ());
}
void
ArdourMixerStrip::set_gain (double db)
{
_stripable->gain_control ()->set_value (from_db (db), PBD::Controllable::NoGroup);
}
double
ArdourMixerStrip::pan () const
{
boost::shared_ptr<AutomationControl> ac = _stripable->pan_azimuth_control ();
if (!ac) {
/* TODO: inform GUI that strip has no panner */
return 0;
}
return ac->internal_to_interface (ac->get_value ());
}
void
ArdourMixerStrip::set_pan (double value)
{
boost::shared_ptr<AutomationControl> ac = _stripable->pan_azimuth_control ();
if (!ac) {
return;
}
ac->set_value (ac->interface_to_internal (value), PBD::Controllable::NoGroup);
}
bool
ArdourMixerStrip::mute () const
{
return _stripable->mute_control ()->muted ();
}
void
ArdourMixerStrip::set_mute (bool mute)
{
_stripable->mute_control ()->set_value (mute ? 1.0 : 0.0, PBD::Controllable::NoGroup);
}
float
ArdourMixerStrip::meter_level_db () const
{
boost::shared_ptr<PeakMeter> meter = _stripable->peak_meter ();
return meter ? meter->meter_level (0, MeterMCP) : -193;
}
std::string
ArdourMixerStrip::name () const
{
return _stripable->name ();
}
void
ArdourMixerStrip::on_drop_plugin (uint32_t)
{
//uint32_t key = (strip_n << 16) | plugin_n;
//_plugin_connections[key]->drop_connections ();
//_plugin_connections.erase (key);
}
double
ArdourMixerStrip::to_db (double k)
{
if (k == 0) {
return -std::numeric_limits<double>::infinity ();
}
float db = accurate_coefficient_to_dB (static_cast<float> (k));
return static_cast<double> (db);
}
double
ArdourMixerStrip::from_db (double db)
{
if (db < -192) {
return 0;
}
float k = dB_to_coefficient (static_cast<float> (db));
return static_cast<double> (k);
}
int
ArdourMixer::start ()
{
/* take an indexed snapshot of current strips */
StripableList strips;
session ().get_stripables (strips, PresentationInfo::AllStripables);
uint32_t strip_n = 0;
for (StripableList::iterator it = strips.begin (); it != strips.end (); ++it) {
ArdourMixerStrip strip (*it);
//(*it)->DropReferences.connect (_connections, MISSING_INVALIDATOR,
// boost::bind (&ArdourMixer::on_drop_strip, this, strip_n), event_loop ());
_strips.push_back (strip);
strip_n++;
}
return 0;
}
int
ArdourMixer::stop ()
{
_strips.clear ();
return 0;
}
uint32_t
ArdourMixer::strip_count () const
{
return _strips.size ();
}
ArdourMixerStrip&
ArdourMixer::nth_strip (uint32_t strip_n)
{
if (strip_n < _strips.size ()) {
return _strips[strip_n];
}
throw ArdourMixerNotFoundException (""/*"Strip with ID " + strip_n + " not found"*/);
}
void
ArdourMixer::on_drop_strip (uint32_t strip_n)
{
/*for (uint32_t plugin_n = 0;; ++plugin_n) {
boost::shared_ptr<PluginInsert> insert = strip_plugin_insert (strip_n, plugin_n);
if (!insert) {
break;
}
on_drop_plugin (strip_n, plugin_n);
}*/
//_strip_connections[strip_n]->drop_connections ();
//_strip_connections.erase (strip_n);
} }

View file

@ -22,6 +22,70 @@
#include "component.h" #include "component.h"
#include "typed_value.h" #include "typed_value.h"
struct ArdourMixerNotFoundException : public virtual std::runtime_error
{
using std::runtime_error::runtime_error;
};
class ArdourMixerPlugin
{
public:
ArdourMixerPlugin (boost::shared_ptr<ARDOUR::PluginInsert>);
boost::shared_ptr<ARDOUR::PluginInsert> insert () const;
bool enabled () const;
void set_enabled (bool);
TypedValue param_value (uint32_t);
void set_param_value (uint32_t, TypedValue);
boost::shared_ptr<ARDOUR::AutomationControl> param_control (uint32_t) const;
static TypedValue param_value (boost::shared_ptr<ARDOUR::AutomationControl>);
private:
boost::shared_ptr<ARDOUR::PluginInsert> _insert;
boost::shared_ptr<PBD::ScopedConnectionList> _connections;
};
class ArdourMixerStrip
{
public:
ArdourMixerStrip (boost::shared_ptr<ARDOUR::Stripable>);
boost::shared_ptr<ARDOUR::Stripable> stripable () const;
boost::shared_ptr<PBD::ScopedConnectionList> connections () const;
int plugin_count () const;
ArdourMixerPlugin& nth_plugin (uint32_t);
double gain () const;
void set_gain (double);
double pan () const;
void set_pan (double);
bool mute () const;
void set_mute (bool);
std::string name () const;
float meter_level_db () const;
static double to_db (double);
static double from_db (double);
private:
boost::shared_ptr<ARDOUR::Stripable> _stripable;
boost::shared_ptr<PBD::ScopedConnectionList> _connections;
std::vector<ArdourMixerPlugin> _plugins;
void on_drop_plugin (uint32_t);
};
class ArdourMixer : public SurfaceComponent class ArdourMixer : public SurfaceComponent
{ {
public: public:
@ -32,37 +96,13 @@ public:
int start (); int start ();
int stop (); int stop ();
static double to_db (double); uint32_t strip_count () const;
static double from_db (double); ArdourMixerStrip& nth_strip (uint32_t);
void on_drop_strip (uint32_t);
double strip_gain (uint32_t) const;
void set_strip_gain (uint32_t, double);
double strip_pan (uint32_t) const;
void set_strip_pan (uint32_t, double);
bool strip_mute (uint32_t) const;
void set_strip_mute (uint32_t, bool);
bool strip_plugin_enabled (uint32_t, uint32_t) const;
void set_strip_plugin_enabled (uint32_t, uint32_t, bool);
TypedValue strip_plugin_param_value (uint32_t, uint32_t, uint32_t) const;
void set_strip_plugin_param_value (uint32_t, uint32_t, uint32_t, TypedValue);
uint32_t strip_count () const;
boost::shared_ptr<ARDOUR::Stripable> nth_strip (uint32_t) const;
boost::shared_ptr<ARDOUR::PluginInsert> strip_plugin_insert (uint32_t, uint32_t) const;
boost::shared_ptr<ARDOUR::AutomationControl> strip_plugin_param_control (
uint32_t, uint32_t, uint32_t) const;
static TypedValue plugin_param_value (boost::shared_ptr<ARDOUR::AutomationControl>);
private: private:
typedef std::vector<boost::shared_ptr<ARDOUR::Stripable> > StripableVector; typedef std::vector<ArdourMixerStrip> StripsVector;
StripableVector _strips; StripsVector _strips;
}; };
#endif // _ardour_surface_websockets_mixer_h_ #endif // _ardour_surface_websockets_mixer_h_