/* * Copyright (C) 2020 Luciano Iam * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "ardour/dB.h" #include "ardour/meter.h" #include "ardour/plugin_insert.h" #include "ardour/session.h" #include "pbd/controllable.h" #include "mixer.h" using namespace ARDOUR; ArdourMixerPlugin::ArdourMixerPlugin (boost::shared_ptr insert) : _insert (insert) , _connections (boost::shared_ptr (new PBD::ScopedConnectionList())) {} boost::shared_ptr ArdourMixerPlugin::insert () const { return _insert; } boost::shared_ptr ArdourMixerPlugin::connections () const { return _connections; } bool ArdourMixerPlugin::enabled () const { return insert ()->enabled (); } void ArdourMixerPlugin::set_enabled (bool enabled) { insert ()->enable (enabled); } TypedValue ArdourMixerPlugin::param_value (uint32_t param_n) { boost::shared_ptr control = param_control (param_n); ParameterDescriptor pd = control->desc (); TypedValue value = TypedValue (); if (pd.toggled) { value = TypedValue (static_cast (control->get_value ())); } else if (pd.enumeration || pd.integer_step) { value = TypedValue (static_cast (control->get_value ())); } else { value = TypedValue (control->get_value ()); } return value; } void ArdourMixerPlugin::set_param_value (uint32_t param_n, TypedValue value) { boost::shared_ptr control = param_control (param_n); ParameterDescriptor pd = control->desc (); double dbl_val; if (pd.toggled) { dbl_val = static_cast (static_cast (value)); } else if (pd.enumeration || pd.integer_step) { dbl_val = static_cast (static_cast (value)); } else { dbl_val = static_cast (value); } control->set_value (dbl_val, PBD::Controllable::NoGroup); } boost::shared_ptr ArdourMixerPlugin::param_control (uint32_t param_n) const { bool ok = false; boost::shared_ptr 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 for param id = " + boost::lexical_cast(param_n)); } return _insert->automation_control (Evoral::Parameter (PluginAutomation, 0, control_id)); } ArdourMixerStrip::ArdourMixerStrip (boost::shared_ptr stripable) : _stripable (stripable) , _connections (boost::shared_ptr (new PBD::ScopedConnectionList())) { if (_stripable->presentation_info ().flags () & ARDOUR::PresentationInfo::VCA) { /* no plugins to handle */ return; } boost::shared_ptr route = boost::dynamic_pointer_cast (_stripable); if (!route) { return; } for (uint32_t plugin_n = 0;; ++plugin_n) { boost::shared_ptr processor = route->nth_plugin (plugin_n); if (!processor) { break; } boost::shared_ptr insert = boost::static_pointer_cast (processor); if (insert) { ArdourMixerPlugin plugin (insert); _plugins.emplace (plugin_n, plugin); } } } boost::shared_ptr ArdourMixerStrip::stripable () const { return _stripable; } boost::shared_ptr ArdourMixerStrip::connections () const { return _connections; } ArdourMixerPlugin& ArdourMixerStrip::plugin (uint32_t plugin_n) { if (_plugins.find (plugin_n) == _plugins.end ()) { throw ArdourMixerNotFoundException ("plugin id = " + boost::lexical_cast(plugin_n) + " not found"); } return _plugins.at (plugin_n); } ArdourMixerStrip::PluginMap& ArdourMixerStrip::plugins () { return _plugins; } 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 ac = _stripable->pan_azimuth_control (); if (!ac) { throw ArdourMixerNotFoundException ("strip has no panner"); } return ac->internal_to_interface (ac->get_value ()); } void ArdourMixerStrip::set_pan (double value) { boost::shared_ptr 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 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::infinity (); } float db = accurate_coefficient_to_dB (static_cast (k)); return static_cast (db); } double ArdourMixerStrip::from_db (double db) { if (db < -192) { return 0; } float k = dB_to_coefficient (static_cast (db)); return static_cast (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.emplace (strip_n++, strip); } return 0; } int ArdourMixer::stop () { _strips.clear (); return 0; } ArdourMixer::StripMap& ArdourMixer::strips () { return _strips; } ArdourMixerStrip& ArdourMixer::strip (uint32_t strip_n) { if (_strips.find (strip_n) == _strips.end ()) { throw ArdourMixerNotFoundException ("strip id = " + boost::lexical_cast(strip_n) + " not found"); } return _strips.at (strip_n); } void ArdourMixer::on_drop_strip (uint32_t strip_n) { /*for (uint32_t plugin_n = 0;; ++plugin_n) { boost::shared_ptr 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); }