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)
{
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 ();
strip_addr.push_back (strip_n);
ValueVector strip_desc = ValueVector ();
strip_desc.push_back (strip->name ());
strip_desc.push_back (strip.name ());
strip_desc.push_back (is_vca);
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_mute, strip_n, mixer ().strip_mute (strip_n));
update (client, Node::strip_gain, strip_n, strip.gain ());
update (client, Node::strip_mute, strip_n, strip.mute ());
// Pan and plugins not available in VCAs
if (is_vca) {
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) {
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) {
boost::shared_ptr<PluginInsert> insert = mixer ()
.strip_plugin_insert (strip_n, plugin_n);
boost::shared_ptr<PluginInsert> insert = strip.nth_plugin (plugin_n).insert ();
if (!insert) {
break;
}
@ -95,11 +94,11 @@ WebsocketsDispatcher::update_all_nodes (Client client)
static_cast<std::string> (plugin->name ()));
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) {
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) {
continue;
}
@ -130,7 +129,7 @@ WebsocketsDispatcher::update_all_nodes (Client client)
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);
}
}
@ -190,9 +189,9 @@ WebsocketsDispatcher::strip_gain_handler (Client client, const NodeStateMessage&
uint32_t strip_id = state.nth_addr (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 {
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);
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 {
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);
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 {
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);
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 {
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);
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));
} 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);
}
}

View file

@ -16,7 +16,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/meter.h"
#include "ardour/plugin_insert.h"
#include "ardour/session.h"
#include "ardour/tempo.h"
@ -57,21 +56,21 @@ struct StripGainObserver {
void operator() (ArdourFeedback* p, uint32_t strip_n)
{
// 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 {
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 {
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)
{
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;
}
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 ();
_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 ();
}
_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 ();
}
_plugin_connections.clear();
_plugin_connections.clear();*/
return 0;
}
@ -181,10 +180,7 @@ ArdourFeedback::poll () const
update_all (Node::transport_time, transport ().time ());
for (uint32_t strip_n = 0; strip_n < mixer ().strip_count (); ++strip_n) {
// meters
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;
float db = mixer ().nth_strip (strip_n).meter_level_db ();
update_all (Node::strip_meter, strip_n, static_cast<double> (db));
}
@ -207,27 +203,21 @@ void
ArdourFeedback::observe_mixer ()
{
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());
strip->gain_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
stripable->gain_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
boost::bind<void> (StripGainObserver (), this, strip_n), event_loop ());
if (strip->pan_azimuth_control ()) {
strip->pan_azimuth_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
if (stripable->pan_azimuth_control ()) {
stripable->pan_azimuth_control ()->Changed.connect (*connections, MISSING_INVALIDATOR,
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 ());
strip->DropReferences.connect (*connections, MISSING_INVALIDATOR,
boost::bind (&ArdourFeedback::on_drop_strip, this, strip_n), event_loop ());
_strip_connections[strip_n] = std::move (connections);
observe_strip_plugins (strip_n, strip);
observe_strip_plugins (strip_n, stripable);
}
}
@ -235,7 +225,7 @@ void
ArdourFeedback::observe_strip_plugins (uint32_t strip_n, boost::shared_ptr<ARDOUR::Stripable> strip)
{
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) {
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 ());
}
insert->DropReferences.connect (*connections, MISSING_INVALIDATOR,
boost::bind (&ArdourFeedback::on_drop_plugin, this, strip_n, plugin_n), event_loop ());
//insert->DropReferences.connect (*connections, MISSING_INVALIDATOR,
// boost::bind (&ArdourFeedback::on_drop_plugin, this, strip_n, plugin_n), event_loop ());
// 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);
}
@ -267,42 +257,17 @@ ArdourFeedback::observe_strip_plugin_param_values (uint32_t strip_n,
boost::shared_ptr<Plugin> plugin = insert->plugin ();
for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) {
boost::shared_ptr<AutomationControl> control = mixer ().strip_plugin_param_control (
strip_n, plugin_n, param_n);
boost::shared_ptr<AutomationControl> control = mixer ().nth_strip (strip_n).nth_plugin (plugin_n).param_control (param_n);
if (!control) {
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,
boost::bind<void> (PluginParamValueObserver (), this, strip_n, plugin_n, param_n,
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;
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;
void observe_transport ();
@ -59,9 +53,6 @@ private:
void observe_strip_plugins (uint32_t, boost::shared_ptr<ARDOUR::Stripable>);
void observe_strip_plugin_param_values (uint32_t, uint32_t,
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_

View file

@ -17,6 +17,7 @@
*/
#include "ardour/dB.h"
#include "ardour/meter.h"
#include "ardour/plugin_insert.h"
#include "ardour/session.h"
#include "pbd/controllable.h"
@ -25,157 +26,33 @@
using namespace ARDOUR;
int
ArdourMixer::start ()
ArdourMixerPlugin::ArdourMixerPlugin (boost::shared_ptr<ARDOUR::PluginInsert> insert)
: _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 */
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);
return _insert;
}
bool
ArdourMixer::strip_mute (uint32_t strip_n) const
ArdourMixerPlugin::enabled () const
{
return nth_strip (strip_n)->mute_control ()->muted ();
insert ()->enabled ();
}
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);
}
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);
insert ()->enable (enabled);
}
TypedValue
ArdourMixer::strip_plugin_param_value (uint32_t strip_n, uint32_t plugin_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)
ArdourMixerPlugin::param_value (uint32_t param_n)
{
boost::shared_ptr<ARDOUR::AutomationControl> control = param_control (param_n);
TypedValue value = TypedValue ();
if (control) {
@ -193,48 +70,241 @@ ArdourMixer::plugin_param_value (boost::shared_ptr<ARDOUR::AutomationControl> co
return value;
}
boost::shared_ptr<PluginInsert>
ArdourMixer::strip_plugin_insert (uint32_t strip_n, uint32_t plugin_n) const
void
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) {
boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route> (strip);
if (control) {
ParameterDescriptor pd = control->desc ();
double dbl_val;
if (route) {
boost::shared_ptr<Processor> processor = route->nth_plugin (plugin_n);
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);
}
if (processor) {
boost::shared_ptr<PluginInsert> insert =
boost::static_pointer_cast<PluginInsert> (processor);
control->set_value (dbl_val, PBD::Controllable::NoGroup);
}
}
if (insert) {
return insert;
}
boost::shared_ptr<ARDOUR::AutomationControl>
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>
ArdourMixer::strip_plugin_param_control (uint32_t strip_n, uint32_t plugin_n,
uint32_t param_n) const
boost::shared_ptr<ARDOUR::Stripable>
ArdourMixerStrip::stripable () const
{
boost::shared_ptr<PluginInsert> insert = strip_plugin_insert (strip_n, plugin_n);
return _stripable;
}
if (insert) {
bool ok = false;
boost::shared_ptr<Plugin> plugin = insert->plugin ();
uint32_t control_id = plugin->nth_parameter (param_n, ok);
boost::shared_ptr<PBD::ScopedConnectionList>
ArdourMixerStrip::connections () const
{
return _connections;
}
if (ok && plugin->parameter_is_input (control_id)) {
boost::shared_ptr<AutomationControl> control =
insert->automation_control (Evoral::Parameter (PluginAutomation, 0, control_id));
return control;
}
int
ArdourMixerStrip::plugin_count () const
{
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 "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
{
public:
@ -32,37 +96,13 @@ public:
int start ();
int stop ();
static double to_db (double);
static double from_db (double);
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>);
uint32_t strip_count () const;
ArdourMixerStrip& nth_strip (uint32_t);
void on_drop_strip (uint32_t);
private:
typedef std::vector<boost::shared_ptr<ARDOUR::Stripable> > StripableVector;
StripableVector _strips;
typedef std::vector<ArdourMixerStrip> StripsVector;
StripsVector _strips;
};
#endif // _ardour_surface_websockets_mixer_h_