diff --git a/libs/surfaces/console1/c1_control.h b/libs/surfaces/console1/c1_control.h index 2629c03e92..e1f377ecf1 100644 --- a/libs/surfaces/console1/c1_control.h +++ b/libs/surfaces/console1/c1_control.h @@ -4,66 +4,146 @@ #include "ardour/debug.h" #include "console1.h" -namespace ArdourSurface { +namespace Console1 +{ using ControllerID = Console1::ControllerID; class Controller { - public: - enum ControllerType - { - CONTROLLER, - CONTROLLER_BUTTON, - MULTISTATE_BUTTON, - ENCODER, - METER - }; +public: Controller (Console1* console1, ControllerID id) - : console1 (console1) - , _id (id) + : console1 (console1) + , _id (id) { } - virtual ~Controller () {} + Controller (Console1* console1, + ControllerID id, + std::function action, + std::function shift_action = 0, + std::function plugin_action = 0, + std::function plugin_shift_action = 0) + : console1 (console1) + , _id (id) + , action (action) + , shift_action (shift_action) + , plugin_action (plugin_action) + , plugin_shift_action (plugin_shift_action) + { + } - Console1* console1; - ControllerID id () const { return _id; } + virtual ~Controller () + { + } - virtual ControllerType get_type () { return CONTROLLER; } + Console1* console1; + ControllerID id () const + { + return _id; + } - protected: - ControllerID _id; + virtual void clear_value() {} + + virtual ControllerType get_type () + { + return CONTROLLER; + } + + void set_action (std::function new_action) + { + action = new_action; + } + + void set_plugin_action (std::function new_action) + { + plugin_action = new_action; + } + + void set_plugin_shift_action (std::function new_action) + { + plugin_shift_action = new_action; + } + std::function get_action (){ + return action; + } + std::function get_shift_action () + { + return shift_action; + } + + std::function get_plugin_action () + { + return plugin_action; + } + + std::function get_plugin_shift_action () + { + return plugin_shift_action; + } + +protected: + ControllerID _id; + std::function action; + std::function shift_action; + std::function plugin_action; + std::function plugin_shift_action; +}; + +class Encoder : public Controller +{ +public: + Encoder (Console1* console1, + ControllerID id, + std::function action, + std::function shift_action = 0, + std::function plugin_action = 0, + std::function plugin_shift_action = 0) + : Controller (console1, id, action, shift_action, plugin_action, plugin_shift_action) + { + console1->controllerMap.insert (std::make_pair (id, this)); + } + + ControllerType get_type () + { + return ENCODER; + } + + virtual void set_value (uint32_t value) + { + MIDI::byte buf[3]; + buf[0] = 0xB0; + buf[1] = _id; + buf[2] = value; + + console1->write (buf, 3); + } + + PBD::Signal* plugin_signal; }; class ControllerButton : public Controller { - public: - ControllerButton (Console1* console1, - ControllerID id, +public: + ControllerButton (Console1* console1, + ControllerID id, std::function action, - std::function shift_action = 0, - std::function plugin_action = 0, - std::function plugin_shift_action = 0 ) - : Controller (console1, id) - , action (action) - , shift_action (shift_action) - , plugin_action (plugin_action) - , plugin_shift_action (plugin_shift_action) + std::function shift_action = 0, + std::function plugin_action = 0, + std::function plugin_shift_action = 0) + : Controller (console1, id, action, shift_action, plugin_action, plugin_shift_action) { - console1->buttons.insert (std::make_pair (id, this)); + console1->controllerMap.insert (std::make_pair (id, this)); } - ControllerType get_type () { return CONTROLLER_BUTTON; } - - void set_action (std::function new_action) { action = new_action; } - void set_plugin_action (std::function new_action) { plugin_action = new_action; } - void set_plugin_shift_action (std::function new_action) { plugin_shift_action = new_action; } + ControllerType get_type () + { + return CONTROLLER_BUTTON; + } virtual void set_led_state (bool onoff) { - // DEBUG_TRACE(DEBUG::Console1, "ControllerButton::set_led_state ...\n"); MIDI::byte buf[3]; buf[0] = 0xB0; buf[1] = _id; @@ -74,7 +154,6 @@ class ControllerButton : public Controller virtual void set_led_value (uint32_t val) { - // DEBUG_TRACE(DEBUG::Console1, "ControllerButton::set_led_state ...\n"); MIDI::byte buf[3]; buf[0] = 0xB0; buf[1] = _id; @@ -82,34 +161,28 @@ class ControllerButton : public Controller console1->write (buf, 3); } - std::function action; - std::function shift_action; - std::function plugin_action; - std::function plugin_shift_action; }; class MultiStateButton : public Controller { - public: - MultiStateButton (Console1* console1, - ControllerID id, - std::vector state_values, +public: + MultiStateButton (Console1* console1, + ControllerID id, + std::vector state_values, std::function action, - std::function shift_action = 0, - std::function plugin_action = 0, - std::function plugin_shift_action = 0 - ) - : Controller (console1, id) - , action (action) - , shift_action (shift_action) - , plugin_action (action) - , plugin_shift_action (shift_action) - , state_values (state_values) + std::function shift_action = 0, + std::function plugin_action = 0, + std::function plugin_shift_action = 0) + : Controller (console1, id, action, shift_action, plugin_action, plugin_shift_action) + , state_values (state_values) { - console1->multi_buttons.insert (std::make_pair (id, this)); + console1->controllerMap.insert (std::make_pair (id, this)); } - ControllerType get_type () { return MULTISTATE_BUTTON; } + ControllerType get_type () + { + return MULTISTATE_BUTTON; + } virtual void set_led_state (uint32_t state) { @@ -123,36 +196,33 @@ class MultiStateButton : public Controller console1->write (buf, 3); } - void set_action (std::function new_action) { action = new_action; } - void set_plugin_action (std::function new_action) { plugin_action = new_action; } - void set_plugin_shift_action (std::function new_action) { plugin_shift_action = new_action; } + uint32_t state_count () + { + return state_values.size (); + } - uint32_t state_count () { return state_values.size (); } - - std::function action; - std::function shift_action; - std::function plugin_action; - std::function plugin_shift_action; - - private: +private: std::vector state_values; }; class Meter : public Controller { - public: - Meter (Console1* console1, - ControllerID id, +public: + Meter (Console1* console1, + ControllerID id, std::function action, std::function shift_action = 0) - : Controller (console1, id) - , action (action) - , shift_action (shift_action) + : Controller (console1, id) + , action (action) + , shift_action (shift_action) { console1->meters.insert (std::make_pair (id, this)); } - ControllerType get_type () { return METER; } + ControllerType get_type () + { + return METER; + } virtual void set_value (uint32_t value) { @@ -167,46 +237,6 @@ class Meter : public Controller std::function shift_action; }; -class Encoder : public Controller -{ - public: - Encoder (Console1* console1, - ControllerID id, - std::function action, - std::function shift_action = 0, - std::function plugin_action = 0, - std::function plugin_shift_action = 0) - : Controller (console1, id) - , action (action) - , shift_action (shift_action) - , plugin_action (plugin_action) - , plugin_shift_action (plugin_action) - { - console1->encoders.insert (std::make_pair (id, this)); - } +} // namespace Console1 - ControllerType get_type () { return ENCODER; } - - void set_action (std::function new_action) { action = new_action; } - void set_plugin_action (std::function new_action) { plugin_action = new_action; } - void set_plugin_shift_action (std::function new_action) { plugin_shift_action = new_action; } - - virtual void set_value (uint32_t value) - { - MIDI::byte buf[3]; - buf[0] = 0xB0; - buf[1] = _id; - buf[2] = value; - - console1->write (buf, 3); - } - std::function action; - std::function shift_action; - std::function plugin_action; - std::function plugin_shift_action; - - PBD::Signal* plugin_signal; -}; - -} #endif // ardour_surface_console1_button_h diff --git a/libs/surfaces/console1/c1_gui.cc b/libs/surfaces/console1/c1_gui.cc index ae37d3e0ac..61d85f0198 100644 --- a/libs/surfaces/console1/c1_gui.cc +++ b/libs/surfaces/console1/c1_gui.cc @@ -19,6 +19,7 @@ #include "c1_gui.h" #include +#include #include #include @@ -32,24 +33,27 @@ #include "ardour/filesystem_paths.h" #include "ardour/parameter_descriptor.h" #include "console1.h" +#include "gtkmm2ext/action_model.h" #include "gtkmm2ext/bindings.h" #include "gtkmm2ext/gui_thread.h" #include "gtkmm2ext/utils.h" using namespace PBD; using namespace ARDOUR; -using namespace ArdourSurface; using namespace std; using namespace Gtk; using namespace Gtkmm2ext; +namespace Console1 +{ + void* Console1::get_gui () const { if (!gui) { const_cast (this)->build_gui (); } - static_cast (gui)->show_all (); + static_cast (gui)->show_all (); return gui; } @@ -57,7 +61,7 @@ void Console1::tear_down_gui () { if (gui) { - Gtk::Widget* w = static_cast (gui)->get_parent (); + Gtk::Widget* w = static_cast (gui)->get_parent (); if (w) { w->hide (); delete w; @@ -113,19 +117,18 @@ C1GUI::C1GUI (Console1& p) // swap_solo_mute (_ ("Swap Solo and Mute")); swap_solo_mute_cb.set_tooltip_text ( - _ ("If checked Ardour the mute and solo buttons are swept so they have the same order as in the GUI.")); + _("If checked Ardour the mute and solo buttons are swept so they have the same order as in the GUI.")); swap_solo_mute_cb.set_active (p.swap_solo_mute); swap_solo_mute_cb.signal_toggled ().connect (sigc::mem_fun (*this, &C1GUI::set_swap_solo_mute)); #ifdef MIXBUS - // before the ssl strips, the q knobs for low- and high mids where alwas used as sends, now this can be toggled - band_q_as_send_cb.set_tooltip_text ( - _ ("If checked Ardour the Q-Factor knobs for Low and High are used as sends for Send 11 and send 12.")); + // before the ssl strips, the q knobs for low- and high mids where always used as sends, now this can be toggled + band_q_as_send_cb.set_tooltip_text ( + _("If checked Ardour the Q-Factor knobs for Low and High are used as sends for Send 11 and send 12.")); band_q_as_send_cb.set_active (p.band_q_as_send); band_q_as_send_cb.signal_toggled ().connect (sigc::mem_fun (*this, &C1GUI::set_band_q_as_send)); #endif - // create_plugin_stubs (_ ("Create Plugin Mapping Stubs")); - create_plugin_stubs_btn.set_tooltip_text (_ ("If checked a mapping stub is created for every unknown plugin.")); + create_plugin_stubs_btn.set_tooltip_text (_("If checked a mapping stub is created for every unknown plugin.")); create_plugin_stubs_btn.set_active (p.create_mapping_stubs); create_plugin_stubs_btn.signal_toggled ().connect (sigc::mem_fun (*this, &C1GUI::set_create_mapping_stubs)); @@ -137,14 +140,14 @@ C1GUI::C1GUI (Console1& p) row++; l = manage (new Gtk::Label); - l->set_markup (string_compose ("%1", _ ("Outgoing MIDI on:"))); + l->set_markup (string_compose ("%1", _("Outgoing MIDI on:"))); l->set_alignment (1.0, 0.5); table.attach (*l, 0, 1, row, row + 1, AttachOptions (FILL | EXPAND), AttachOptions (0)); table.attach (output_combo, 1, 2, row, row + 1, AttachOptions (FILL | EXPAND), AttachOptions (0), 0, 0); row++; l = manage (new Gtk::Label); - l->set_markup (string_compose ("%1", _ ("Swap Solo and Mute:"))); + l->set_markup (string_compose ("%1", _("Swap Solo and Mute:"))); l->set_alignment (1.0, 0.5); table.attach (*l, 0, 1, row, row + 1, AttachOptions (FILL | EXPAND), AttachOptions (0)); table.attach (swap_solo_mute_cb, 1, 2, row, row + 1); @@ -152,7 +155,7 @@ C1GUI::C1GUI (Console1& p) #ifdef MIXBUS l = manage (new Gtk::Label); - l->set_markup (string_compose ("%1", _ ("Use Mid-Q Buttons as send 11/12:"))); + l->set_markup (string_compose ("%1", _("Use Mid-Q Buttons as send 11/12:"))); l->set_alignment (1.0, 0.5); table.attach (*l, 0, 1, row, row + 1, AttachOptions (FILL | EXPAND), AttachOptions (0)); table.attach (band_q_as_send_cb, 1, 2, row, row + 1); @@ -160,33 +163,45 @@ C1GUI::C1GUI (Console1& p) #endif l = manage (new Gtk::Label); - l->set_markup (string_compose ("%1", _ ("Create Plugin Mapping Stubs:"))); + l->set_markup (string_compose ("%1", _("Create Plugin Mapping Stubs:"))); l->set_alignment (1.0, 0.5); table.attach (*l, 0, 1, row, row + 1, AttachOptions (FILL | EXPAND), AttachOptions (0)); table.attach (create_plugin_stubs_btn, 1, 2, row, row + 1); row++; hpacker.pack_start (table, true, true); + append_page (hpacker, _("Device Setup")); + hpacker.show_all(); - set_spacing (12); + // Create the page for plugin mappings + p.load_mappings (); - pack_start (hpacker, false, false); + VBox* plugconfig_packer = build_plugin_assignment_page(); - /* update the port connection combos */ + append_page (*plugconfig_packer, _("Plugin Mappings")); + plugconfig_packer->show_all (); - update_port_combos (); + /* update the port connection combos */ - /* catch future changes to connection state */ + update_port_combos (); - ARDOUR::AudioEngine::instance ()->PortRegisteredOrUnregistered.connect ( - _port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ()); - ARDOUR::AudioEngine::instance ()->PortPrettyNameChanged.connect ( - _port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ()); - c1.ConnectionChange.connect ( - _port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ()); + /* catch future changes to connection state */ + + ARDOUR::AudioEngine::instance ()->PortRegisteredOrUnregistered.connect ( + port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ()); + ARDOUR::AudioEngine::instance ()->PortPrettyNameChanged.connect ( + port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ()); + c1.ConnectionChange.connect ( + port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ()); + + c1.PluginStubAdded.connect ( + plugin_connections, invalidator (*this), std::bind (&C1GUI::load_plugin_combo_rows, this), gui_context ()); } -C1GUI::~C1GUI () {} +C1GUI::~C1GUI () { + DEBUG_TRACE (DEBUG::Console1, "1GUI::~C1GUI ()\n"); + c1.midi_assign_mode = false; +} void C1GUI::set_swap_solo_mute () @@ -287,7 +302,7 @@ C1GUI::build_midi_port_list (vector const& ports, bool for_input) row = *store->append (); row[midi_port_columns.full_name] = string (); - row[midi_port_columns.short_name] = _ ("Disconnected"); + row[midi_port_columns.short_name] = _("Disconnected"); for (vector::const_iterator p = ports.begin (); p != ports.end (); ++p) { row = *store->append (); @@ -334,3 +349,6 @@ C1GUI::active_port_changed (Gtk::ComboBox* combo, bool for_input) } } } + + +} // namespace Console1 \ No newline at end of file diff --git a/libs/surfaces/console1/c1_gui.h b/libs/surfaces/console1/c1_gui.h index e5408f82c1..9b1eb18239 100644 --- a/libs/surfaces/console1/c1_gui.h +++ b/libs/surfaces/console1/c1_gui.h @@ -23,47 +23,62 @@ #include #include -#include #include +#include +#include #include #include #include +#include #include #include namespace Gtk { - class CellRendererCombo; - class ListStore; + class ListStore; +} + +namespace ActionManager { + class ActionModel; } #include "ardour/mode.h" #include "console1.h" -namespace ArdourSurface { +namespace Console1 { -class C1GUI : public Gtk::VBox +class C1GUI : public Gtk::Notebook { public: C1GUI (Console1&); ~C1GUI (); private: - Console1& c1; + Console1& c1; PBD::ScopedConnectionList lcxl_connections; - Gtk::VBox hpacker; - Gtk::Table table; - Gtk::ComboBox input_combo; - Gtk::ComboBox output_combo; - Gtk::Image image; + Gtk::VBox hpacker; + Gtk::Table table; + Gtk::ComboBox input_combo; + Gtk::ComboBox output_combo; + + Gtk::Image image; Gtk::CheckButton swap_solo_mute_cb; Gtk::CheckButton band_q_as_send_cb; Gtk::CheckButton create_plugin_stubs_btn; + Gtk::ScrolledWindow plugin_mapping_scroller; + Gtk::ComboBox plugins_combo; + Gtk::TreeView plugin_assignment_editor; + Gtk::ToggleButton* midi_assign_button; + Gtk::VBox plugin_packer; + + sigc::signal plugin_assignment_changed; + void update_port_combos (); PBD::ScopedConnection connection_change_connection; void connection_handler (); - PBD::ScopedConnectionList _port_connections; + PBD::ScopedConnectionList port_connections; + PBD::ScopedConnectionList plugin_connections; struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord { MidiPortColumns() { @@ -74,17 +89,58 @@ private: Gtk::TreeModelColumn full_name; }; + struct PluginColumns : public Gtk::TreeModel::ColumnRecord { + PluginColumns() { + add (plugin_name); + add (plugin_id); + } + Gtk::TreeModelColumn plugin_name; + Gtk::TreeModelColumn plugin_id; + }; + + struct PluginAssignamentEditorColumns : public Gtk::TreeModel::ColumnRecord { + PluginAssignamentEditorColumns() { + add (index); + add (name); + add (is_switch); + add (controllerName); + add (shift); + }; + Gtk::TreeModelColumn index; // parameter index + Gtk::TreeModelColumn name; // readable name of the parameter + Gtk::TreeModelColumn is_switch; + Gtk::TreeModelColumn controllerName; // enum Button::ID + Gtk::TreeModelColumn shift; + }; + MidiPortColumns midi_port_columns; + PluginColumns plugin_columns; + PluginAssignamentEditorColumns plugin_assignment_editor_columns; + Glib::RefPtr plugin_assignment_store; + bool ignore_active_change; Glib::RefPtr build_midi_port_list (std::vector const & ports, bool for_input); - void active_port_changed (Gtk::ComboBox*,bool for_input); + + + Console1::PluginMapping plugin_mapping; + Gtk::VBox* build_plugin_assignment_page (); + Gtk::CellRendererCombo* make_action_renderer (Glib::RefPtr model, Gtk::TreeModelColumnBase column); + void load_plugin_combo_rows (); + void build_plugin_assignment_editor (); + void plugin_assignment_editor_selection_changed (); + void change_controller_number (int controllerNumber, bool shiftState); + void midi_assign_button_toggled (Gtk::ToggleButton* b); + void change_controller (const Glib::ustring&, const Gtk::TreeIter&); + void toggle_shift (const Glib::ustring&); + void active_port_changed (Gtk::ComboBox*, bool for_input); void set_swap_solo_mute (); - void set_band_q_as_send(); - void set_create_mapping_stubs(); + void set_band_q_as_send (); + void set_create_mapping_stubs (); + void active_plugin_changed (Gtk::ComboBox* combo); + void write_plugin_assignment (); }; - -} +} // namespace Console1 #endif /* __ardour_console1_gui_h__ */ diff --git a/libs/surfaces/console1/c1_operations.cc b/libs/surfaces/console1/c1_operations.cc index 571d281a5f..58cf93030b 100644 --- a/libs/surfaces/console1/c1_operations.cc +++ b/libs/surfaces/console1/c1_operations.cc @@ -27,13 +27,15 @@ #include "console1.h" using namespace ARDOUR; -using namespace ArdourSurface; using namespace PBD; using namespace Glib; using namespace std; /* Operations */ +namespace Console1 +{ + void Console1::bank (bool up) { @@ -145,7 +147,7 @@ Console1::select (const uint32_t i) void Console1::shift (const uint32_t val) { - DEBUG_TRACE (DEBUG::Console1, "shift()\n"); + DEBUG_TRACE (DEBUG::Console1, string_compose( "shift (%1)\n", val )); shift_state = !shift_state; ShiftChange (val); } @@ -674,11 +676,14 @@ Console1::map_select () void Console1::map_shift (bool shift) { - DEBUG_TRACE (DEBUG::Console1, "map_shift()\n"); + DEBUG_TRACE (DEBUG::Console1, string_compose ("map_shift(%1)\n", shift)); try { ControllerButton* controllerButton = get_button (PRESET); controllerButton->set_led_state (shift); - map_stripable_state (); + if( in_plugin_state ) + remap_plugin_parameter (current_plugin_index); + else + map_stripable_state (); } catch (ControlNotFoundException const&) { DEBUG_TRACE (DEBUG::Console1, "Button not found\n"); } @@ -687,7 +692,7 @@ Console1::map_shift (bool shift) void Console1::map_plugin_state (bool plugin_state) { - DEBUG_TRACE (DEBUG::Console1, "map_plugin_state()\n"); + DEBUG_TRACE (DEBUG::Console1, string_compose ("map_plugin_state(%1)\n", plugin_state) ); try { ControllerButton* controllerButton = get_button (TRACK_GROUP); controllerButton->set_led_state (in_plugin_state); @@ -699,10 +704,6 @@ Console1::map_plugin_state (bool plugin_state) stop_blinking (ControllerID (FOCUS1 + i)); } map_stripable_state (); - } else { - // I don't plan shift functionality with plugins... - shift (0); - // map all plugin related operations } } @@ -1034,6 +1035,7 @@ Console1::map_drive () } } +// Sends // Sends void Console1::map_mb_send_level (const uint32_t n) @@ -1045,15 +1047,22 @@ Console1::map_mb_send_level (const uint32_t n) } #endif // Theese two sends are available in non-shift state - if (n_offset > 9 && shift_state) { + if (n_offset > 9 && shift_state) + { return; + } else if (n_offset < 10 && !shift_state) // while the rest needs the shift state + { + return; + } + else if( !shift_state && !switch_eq_q_dials ) + { } else if (n_offset < 10 && !shift_state) { // while the rest needs the shift state return; } else if(!shift_state && !switch_eq_q_dials) { return; - } + } ControllerID controllerID = get_send_controllerid (n_offset); if (map_encoder (controllerID)) { std::shared_ptr control = _current_stripable->send_level_controllable (n); @@ -1153,6 +1162,7 @@ Console1::map_comp_emph () } } + void Console1::eqBandQChangeMapping (bool mapValues) { DEBUG_TRACE(DEBUG::Console1, string_compose("eqBandQChangeMapping(): band_q_as_send = %1, strip_eq_mode = %2, mapValues = %3 \n", band_q_as_send, strip_eq_mode, mapValues)); @@ -1228,3 +1238,5 @@ Console1::map_encoder (ControllerID controllerID, std::shared_ptr + * + * 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 "c1_gui.h" + +#include "ardour/debug.h" +#include "console1.h" + +#include "pbd/i18n.h" + +using namespace PBD; +using namespace Gtk; +using namespace std; + + +namespace Console1 +{ + +VBox* +C1GUI::build_plugin_assignment_page () +{ + VBox* plugconfig_packer = manage (new VBox); + HBox* plugselect_packer = manage (new HBox); + + Gtk::Label* l; + l = manage (new Gtk::Label (_ ("Select Plugin"))); + plugselect_packer->pack_start (*l, false, false); + + plugconfig_packer->pack_start (*plugselect_packer, false, false); + + load_plugin_combo_rows (); + plugselect_packer->pack_start (plugins_combo, true, true); + plugin_mapping_scroller.property_shadow_type () = Gtk::SHADOW_NONE; + plugin_mapping_scroller.set_policy (Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC); + + plugin_mapping_scroller.add (plugin_assignment_editor); + plugconfig_packer->pack_start (plugin_mapping_scroller, true, true, 20); + + build_plugin_assignment_editor (); + + midi_assign_button = manage (new ToggleButton (_ ("assign Control per MIDI"))); + midi_assign_button->set_sensitive (false); + midi_assign_button->set_active (false); + midi_assign_button->signal_toggled ().connect (sigc::bind (sigc::mem_fun (*this, &C1GUI::midi_assign_button_toggled), midi_assign_button)); + plugconfig_packer->pack_start (*midi_assign_button, false, false); + plugin_assignment_changed.connect (sigc::mem_fun (*this, &C1GUI::write_plugin_assignment)); + return plugconfig_packer; +} + +void C1GUI::load_plugin_combo_rows() +{ + Glib::RefPtr plugin_store_model = ListStore::create (plugin_columns); + TreeModel::Row plugin_combo_row; + + for (const auto& pm : c1.plugin_mapping_map) { + plugin_combo_row = *(plugin_store_model->append ()); + plugin_combo_row[plugin_columns.plugin_name] = pm.second.name; + plugin_combo_row[plugin_columns.plugin_id] = pm.first; + DEBUG_TRACE (DEBUG::Console1, string_compose ("Add Plugin: name %1 / %2\n", pm.second.name, pm.first)); + } + plugins_combo.pack_start (plugin_columns.plugin_name); + plugins_combo.signal_changed ().connect ( + sigc::bind (sigc::mem_fun (*this, &C1GUI::active_plugin_changed), &plugins_combo)); + plugins_combo.set_model (plugin_store_model); +} + +void +C1GUI::build_plugin_assignment_editor () +{ + plugin_assignment_editor.append_column (_ ("Key"), plugin_assignment_editor_columns.index); + plugin_assignment_editor.append_column (_ ("Name"), plugin_assignment_editor_columns.name); + plugin_assignment_editor.append_column (_ ("Switch"), plugin_assignment_editor_columns.is_switch); + + TreeViewColumn* col; + CellRendererCombo* controlRenderer; + + CellRendererToggle* boolRendererShift = manage (new CellRendererToggle); + boolRendererShift->set_active (); + boolRendererShift->property_activatable () = true; + col = manage (new TreeViewColumn (_ ("Shift"), *boolRendererShift)); + col->add_attribute (boolRendererShift->property_active (), plugin_assignment_editor_columns.shift); + boolRendererShift->signal_toggled ().connect (sigc::mem_fun (*this, &C1GUI::toggle_shift)); + plugin_assignment_editor.append_column (*col); + + controlRenderer = make_action_renderer (c1.getPluginControllerModel (), plugin_assignment_editor_columns.controllerName); + col = manage (new TreeViewColumn (_ ("Control"), *controlRenderer)); + col->add_attribute (controlRenderer->property_text (), plugin_assignment_editor_columns.controllerName); + plugin_assignment_editor.append_column (*col); + + plugin_assignment_store = ListStore::create (plugin_assignment_editor_columns); + plugin_assignment_editor.set_model (plugin_assignment_store); +} + +void +C1GUI::active_plugin_changed (Gtk::ComboBox* combo) +{ + DEBUG_TRACE (DEBUG::Console1, "C1GUI active_plugin_changed\n"); + + write_plugin_assignment (); + + plugin_assignment_editor.set_model (Glib::RefPtr ()); + plugin_assignment_store->clear (); + + TreeModel::iterator active = combo->get_active (); + TreeModel::Row plugin_assignment_row; + + string new_plugin_name = (*active)[plugin_columns.plugin_name]; + string new_plugin_id = (*active)[plugin_columns.plugin_id]; + DEBUG_TRACE (DEBUG::Console1, string_compose ("Plugin: selected %1 / %2\n", new_plugin_name, new_plugin_id)); + plugin_mapping = c1.plugin_mapping_map[new_plugin_id]; + + for (auto& parm : plugin_mapping.parameters) { + plugin_assignment_row = *(plugin_assignment_store->append ()); + plugin_assignment_row[plugin_assignment_editor_columns.index] = parm.first; + plugin_assignment_row[plugin_assignment_editor_columns.name] = parm.second.name; + plugin_assignment_row[plugin_assignment_editor_columns.controllerName] = c1.findControllerNameById (parm.second.controllerId); + plugin_assignment_row[plugin_assignment_editor_columns.is_switch] = parm.second.is_switch; + plugin_assignment_row[plugin_assignment_editor_columns.shift] = parm.second.shift; + + DEBUG_TRACE (DEBUG::Console1, string_compose ("Parameter Name %1 \n", parm.second.name)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Parameter Index: %1 - index %2 \n", parm.first, parm.second.paramIndex)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("ControllerId: %1 \n", parm.second.controllerId)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("is switch? %1 \n", parm.second.is_switch)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("is shift? %1 \n", parm.second.shift)); + } + plugin_assignment_editor.set_model (plugin_assignment_store); + plugin_assignment_editor.get_selection ()->set_mode (SELECTION_SINGLE); + plugin_assignment_editor.get_selection ()->signal_changed ().connect (sigc::mem_fun (*this, &C1GUI::plugin_assignment_editor_selection_changed)); + midi_assign_button->set_sensitive (false); + midi_assign_button->set_active (false); +} + +CellRendererCombo* +C1GUI::make_action_renderer (Glib::RefPtr model, Gtk::TreeModelColumnBase column) +{ + CellRendererCombo* renderer = manage (new CellRendererCombo); + renderer->property_model () = model; + renderer->property_editable () = true; + renderer->property_text_column () = 0; + renderer->property_has_entry () = false; + renderer->signal_changed ().connect (sigc::mem_fun (*this, &C1GUI::change_controller)); + + return renderer; +} + +void +C1GUI::change_controller (const Glib::ustring& sPath, const TreeModel::iterator& iter) +{ + Gtk::TreePath path (sPath); + Gtk::TreeModel::iterator row = plugin_assignment_store->get_iter (path); + int index = *path.begin (); + if (row) { + string controllerName = (*iter)[c1.plugin_controller_columns.controllerName]; + int controllerId = (*iter)[c1.plugin_controller_columns.controllerId]; + plugin_mapping.parameters[index].controllerId = Console1::ControllerID (controllerId); + (*row).set_value (plugin_assignment_editor_columns.controllerName, controllerName); + DEBUG_TRACE (DEBUG::Console1, + string_compose ("Column Name: Controller, index %1, name %2 \n", index, controllerName)); + plugin_assignment_changed (); + } +} + +void +C1GUI::plugin_assignment_editor_selection_changed () +{ + if (plugin_assignment_editor.get_selection ()->count_selected_rows () != 1) { + midi_assign_button->set_sensitive (false); + } + midi_assign_button->set_sensitive (true); +} + +void +C1GUI::write_plugin_assignment () +{ + DEBUG_TRACE (DEBUG::Console1, "write_plugin_assignment\n"); + c1.plugin_mapping_map[plugin_mapping.id] = plugin_mapping; + c1.write_plugin_mapping (plugin_mapping); +} + +void +C1GUI::change_controller_number( int controllerNumber, bool shiftState ){ + DEBUG_TRACE (DEBUG::Console1, string_compose ("C1GUI::change_controller_number: received %1\n", controllerNumber)); + Gtk::TreeModel::iterator row = plugin_assignment_editor.get_selection ()->get_selected (); + + if (row) { + string name = c1.findControllerNameById (Console1::ControllerID(controllerNumber)); + (*row).set_value (plugin_assignment_editor_columns.controllerName, name); + (*row).set_value (plugin_assignment_editor_columns.shift, shiftState); + int index = (*row).get_value (plugin_assignment_editor_columns.index); + plugin_mapping.parameters[index].controllerId = Console1::ControllerID (controllerNumber); + plugin_mapping.parameters[index].shift = shiftState ? 1 : 0; + plugin_assignment_changed (); + } + midi_assign_button->set_active (false); +} + +void +C1GUI::midi_assign_button_toggled (Gtk::ToggleButton* b) +{ + DEBUG_TRACE (DEBUG::Console1, "C1GUI::midi_assign_button_changed() \n"); + bool en = b->get_active (); + c1.midi_assign_mode = en; + if( en ) + { + c1.SendControllerNumber.connect (std::bind ( &C1GUI::change_controller_number, this, _1, _2)); + } +} + +void +C1GUI::toggle_shift (const Glib::ustring& s) +{ + int index = atoi (s.c_str ()); + Gtk::TreeModel::iterator row = plugin_assignment_store->get_iter (s); + if (row) { + bool value = !plugin_mapping.parameters[index].shift; + plugin_mapping.parameters[index].shift = value; + (*row).set_value (plugin_assignment_editor_columns.shift, value); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Column Name: Shift, value %1\n", value)); + plugin_assignment_changed (); + } +} + +} \ No newline at end of file diff --git a/libs/surfaces/console1/c1_plugin_operations.cc b/libs/surfaces/console1/c1_plugin_operations.cc index 6fd1d5ef48..f4d67d41f3 100644 --- a/libs/surfaces/console1/c1_plugin_operations.cc +++ b/libs/surfaces/console1/c1_plugin_operations.cc @@ -35,12 +35,12 @@ #include "console1.h" using namespace ARDOUR; -using namespace ArdourSurface; using namespace PBD; using namespace Glib; using namespace std; -namespace ArdourSurface { +namespace Console1 +{ bool Console1::ensure_config_dir () @@ -57,6 +57,9 @@ Console1::ensure_config_dir () uint32_t Console1::load_mappings () { + if( mappings_loaded ) + return plugin_mapping_map.size (); + uint32_t i = 0; if (!ensure_config_dir ()) return 1; @@ -89,7 +92,9 @@ Console1::load_mappings () ++i; } DEBUG_TRACE (DEBUG::Console1, string_compose ("Console1::load_mappings - found %1 mapping files\n", i)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Console1::load_mappings - loaded %1 mapping files\n", plugin_mapping_map.size())); g_dir_close (gdir); + mappings_loaded = true; return i; } @@ -118,56 +123,68 @@ Console1::load_mapping (XMLNode* mapping_xml) const XMLNodeList& plist = (*i)->children (); XMLNodeConstIterator j; + PluginParameterMapping parmap; for (j = plist.begin (); j != plist.end (); ++j) { if ((*j)->name () == "name") { param_name = (*j)->child_content (); } else if ((*j)->name () == "mapping") { param_mapping = (*j)->child_content (); + (*j)->get_property ("shift", parmap.shift); + (*j)->get_property ("is_switch", parmap.is_switch); } } + parmap.paramIndex = index; + parmap.name = param_name; if (!param_mapping.empty ()) { - PluginParameterMapping parmap; - parmap.paramIndex = index; - parmap.name = param_name; - ControllerMap::const_iterator m = controllerMap.find (param_mapping); - if (m == controllerMap.end ()) - continue; - parmap.controllerId = m->second; - parmap.is_switch = (param_type == "switch"); - pm.parameters[index] = std::move (parmap); - pluginMappingMap[pm.id] = pm; + ControllerNameIdMap::const_iterator m = controllerNameIdMap.find (param_mapping); + if (m != controllerNameIdMap.end ()) + { + parmap.controllerId = m->second; + } } + else{ + pm.configured = false; + parmap.controllerId = CONTROLLER_NONE; + } + pm.parameters[index] = std::move (parmap); } + plugin_mapping_map[pm.id] = pm; return true; } void -Console1::create_mapping (const std::shared_ptr proc, const std::shared_ptr plugin) +Console1::create_plugin_mapping_stubs (const std::shared_ptr proc, const std::shared_ptr plugin) { + DEBUG_TRACE (DEBUG::Console1, "create_plugin_mapping_stubs \n"); XMLTree* tree = new XMLTree (); XMLNode node = XMLNode ("c1plugin-mapping"); - node.set_property ("ID", plugin->unique_id ()); - node.set_property ("NAME", plugin->name ()); - int32_t n_controls = -1; + if( plugin->unique_id() == "" ) + return; + node.set_property ("ID", plugin->unique_id ()); + node.set_property ("NAME", plugin->name ()); + int32_t n_controls = -1; - set p = proc->what_can_be_automated (); - for (set::iterator j = p.begin (); j != p.end (); ++j) { - ++n_controls; - std::string n = proc->describe_parameter (*j); - DEBUG_TRACE (DEBUG::Console1, string_compose ("Plugin parameter %1: %2\n", n_controls, n)); - if (n == "hidden") { - continue; - } - XMLNode param = XMLNode ("param-mapping"); - param.set_property ("id", n_controls); - XMLNode name = XMLNode ("name"); - XMLNode c = XMLNode ("c", plugin->parameter_label (n_controls).c_str ()); - name.add_child_copy (c); - XMLNode mapping = XMLNode ("mapping"); - mapping.set_property ("shift", "false"); - param.add_child_copy (name); - param.add_child_copy (mapping); - node.add_child_copy (param); + set p = proc->what_can_be_automated (); + for (set::iterator j = p.begin (); j != p.end (); ++j) { + ++n_controls; + std::string n = proc->describe_parameter (*j); + DEBUG_TRACE (DEBUG::Console1, string_compose ("create_plugin_mapping_stubs: Plugin parameter %1: %2\n", n_controls, n)); + if (n == "hidden") { + continue; + } + ParameterDescriptor parameterDescriptor; + plugin->get_parameter_descriptor (n_controls, parameterDescriptor); + XMLNode param = XMLNode ("param-mapping"); + param.set_property ("id", n_controls); + XMLNode name = XMLNode ("name"); + XMLNode c = XMLNode ("c", plugin->parameter_label (n_controls).c_str ()); + name.add_child_copy (c); + XMLNode mapping = XMLNode ("mapping"); + mapping.set_property ("shift", "false"); + mapping.set_property ("is_switch", parameterDescriptor.toggled ? 1 : 0); + param.add_child_copy (name); + param.add_child_copy (mapping); + node.add_child_copy (param); } tree->set_root (&node); @@ -180,12 +197,54 @@ Console1::create_mapping (const std::shared_ptr proc, const std::shar tree->set_filename (filename); tree->write (); + load_mapping (&node); + PluginStubAdded (); +} + +void +Console1::write_plugin_mapping (PluginMapping &mapping) +{ + DEBUG_TRACE (DEBUG::Console1, "write_plugin_mapping \n"); + XMLTree* tree = new XMLTree (); + XMLNode node = XMLNode ("c1plugin-mapping"); + node.set_property ("ID", mapping.id); + node.set_property ("NAME", mapping.name); + + for (const auto& plugin_param : mapping.parameters ) { + DEBUG_TRACE (DEBUG::Console1, string_compose ("write_plugin_mapping: Plugin parameter %1: %2 - shift: %3\n", plugin_param.first, plugin_param.second.name, plugin_param.second.shift)); + XMLNode param = XMLNode ("param-mapping"); + param.set_property ("id", plugin_param.second.paramIndex); + XMLNode name = XMLNode ("name"); + XMLNode c = XMLNode ("c", plugin_param.second.name ); + name.add_child_copy (c); + XMLNode mapping = XMLNode ("mapping"); + mapping.set_property ("shift", plugin_param.second.shift); + mapping.set_property ("is_switch", plugin_param.second.is_switch); + XMLNode controller = XMLNode ("c", findControllerNameById (plugin_param.second.controllerId)); + mapping.add_child_copy (controller); + param.add_child_copy (name); + param.add_child_copy (mapping); + node.add_child_copy (param); + } + + tree->set_root (&node); + + if (!ensure_config_dir ()) + return; + + std::string filename = Glib::build_filename ( + user_config_directory (), config_dir_name, string_compose ("%1.%2", mapping.id, "xml")); + + tree->set_filename (filename); + tree->write (); + load_mapping (&node); } bool Console1::select_plugin (const int32_t plugin_index) { DEBUG_TRACE (DEBUG::Console1, "Console1::select_plugin\n"); + midi_assign_mode = false; if (current_plugin_index == plugin_index) { std::shared_ptr r = std::dynamic_pointer_cast (_current_stripable); if (!r) { @@ -239,24 +298,23 @@ Console1::remove_plugin_operations () { plugin_connections.drop_connections (); - for (auto& e : encoders) { - e.second->set_plugin_action (0); - e.second->set_plugin_shift_action (0); - e.second->set_value (0); - } - for (auto& b : buttons) { - if (b.first == ControllerID::TRACK_GROUP) + for (auto& c : controllerMap) { + if (c.first == ControllerID::TRACK_GROUP) continue; - if (b.first >= ControllerID::FOCUS1 && b.first <= ControllerID::FOCUS20) + if (c.first >= ControllerID::FOCUS1 && c.first <= ControllerID::FOCUS20) continue; - b.second->set_plugin_action (0); - b.second->set_plugin_shift_action (0); - b.second->set_led_state (false); - } - for (auto& m : multi_buttons) { - m.second->set_plugin_action (0); - m.second->set_plugin_shift_action (0); - m.second->set_led_state (false); + c.second->set_plugin_action (0); + c.second->set_plugin_shift_action (0); + c.second->clear_value (); + if( c.second->get_type() == ControllerType::CONTROLLER_BUTTON && c.first != ControllerID::PRESET ) + { + ControllerButton* b = dynamic_cast (c.second); + b->set_led_state (false); + } else if (c.second->get_type () == ControllerType::MULTISTATE_BUTTON ) + { + MultiStateButton* b = dynamic_cast (c.second); + b->set_led_state (false); + } } } @@ -271,17 +329,19 @@ Console1::find_plugin (const int32_t plugin_index) if (!r) { return proc; } - remove_plugin_operations (); while ((ext_plugin_index < plugin_index) && (int_plugin_index < (int)bank_size)) { ++int_plugin_index; + DEBUG_TRACE (DEBUG::Console1, string_compose ("find_plugin: int index %1, ext index %2\n", int_plugin_index, ext_plugin_index)); proc = r->nth_plugin (int_plugin_index); if (!proc) { + DEBUG_TRACE (DEBUG::Console1, "find_plugin: plugin not found\n"); continue; - ; } + DEBUG_TRACE (DEBUG::Console1, "find_plugin: plugin found\n"); if (!proc->display_to_user ()) { + DEBUG_TRACE (DEBUG::Console1, "find_plugin: display to user failed\n"); continue; } @@ -301,19 +361,161 @@ Console1::find_plugin (const int32_t plugin_index) } bool -Console1::spill_plugins (const int32_t plugin_index) +Console1::setup_plugin_mute_button(const std::shared_ptr& plugin_insert) { - bool mapping_found = false; + int32_t n_controls = -1; + try { + ControllerButton* cb = get_button (ControllerID::MUTE); + std::function plugin_mapping = [=] () -> void { cb->set_led_state (!plugin_insert->enabled ()); }; + cb->set_plugin_action ([=] (uint32_t val) { + plugin_insert->enable (val == 0); + DEBUG_TRACE (DEBUG::Console1, + string_compose ("ControllerButton Plugin parameter %1: %2 \n", n_controls, val)); + }); - remove_plugin_operations (); + plugin_insert->ActiveChanged.connect ( + plugin_connections, MISSING_INVALIDATOR, std::bind (plugin_mapping), this); + plugin_insert->ActiveChanged (); + return true; + } catch (ControlNotFoundException const&) { + DEBUG_TRACE (DEBUG::Console1, string_compose ("No ControllerButton found %1\n", n_controls)); + return false; + } +} - std::shared_ptr proc = find_plugin (plugin_index); - if (!proc) +bool +Console1::setup_plugin_controller (const PluginParameterMapping& ppm, int32_t n_controls, + const ParameterDescriptor& parameterDescriptor, + const std::shared_ptr& ac) +{ + DEBUG_TRACE (DEBUG::Console1, "Console1::setup_plugin_controller"); + try { + Controller* controller = get_controller (ppm.controllerId); + if (!ppm.shift) + controller->set_plugin_action ([=] (uint32_t val) { + double v = val / 127.f; + double translated = parameterDescriptor.from_interface (v, true); + ac->set_value (translated, + PBD::Controllable::GroupControlDisposition::UseGroup); + DEBUG_TRACE ( + DEBUG::Console1, + string_compose ("from: ->Encoder Plugin parameter %1: origin %2 calculated %3 translated %4\n", n_controls, val, v, translated)); + }); + else + controller->set_plugin_shift_action ([=] (uint32_t val) { + double v = val / 127.f; + double translated = parameterDescriptor.from_interface (v, true); + ac->set_value (translated, + PBD::Controllable::GroupControlDisposition::UseGroup); + DEBUG_TRACE ( + DEBUG::Console1, + string_compose ("from: ->Encoder Plugin shift-parameter %1: origin %2 calculated %3 translated %4\n", n_controls, val, v, translated)); + }); + return set_plugin_receive_connection (controller, ac, parameterDescriptor, ppm); + } catch (ControlNotFoundException const&) { + DEBUG_TRACE (DEBUG::Console1, string_compose ("No Encoder found %1\n", n_controls)); + return false; + } +} + +bool +Console1::set_plugin_receive_connection (Controller* controller, const std::shared_ptr& ac, const ParameterDescriptor& parameterDescriptor, const PluginParameterMapping& ppm) +{ + DEBUG_TRACE (DEBUG::Console1, "Console1::set_plugin_receive_connection \n"); + + if (ppm.shift != shift_state) return false; - int32_t n_controls = -1; - DEBUG_TRACE (DEBUG::Console1, string_compose ("Found plugin %1\n", proc->name ())); - std::shared_ptr plugin_insert = std::dynamic_pointer_cast (proc); + std::function plugin_mapping; + + switch (controller->get_type ()) { + case ControllerType::ENCODER: { + Encoder* e = dynamic_cast (controller); + if (e) { + DEBUG_TRACE (DEBUG::Console1, "Console1::set_plugin_receive_connection ENCODER\n"); + + plugin_mapping = + [=] (bool b, PBD::Controllable::GroupControlDisposition d) -> void { + double origin = ac->get_value (); + double v = parameterDescriptor.to_interface (origin, true); + e->set_value (v * 127); + DEBUG_TRACE ( + DEBUG::Console1, + string_compose ("to: <-Encoder Plugin parameter %1: origin %2 translated %3 - %4\n", ppm.paramIndex, origin, v, v * 127)); + }; + DEBUG_TRACE (DEBUG::Console1, string_compose ("ENCODER has plugin_action %1, has shitft_plugin_action %2\n", e->get_plugin_action () ? "Yes" : "No", e->get_plugin_shift_action () ? "Yes" : "No")); + } + }; + break; + case ControllerType::CONTROLLER_BUTTON: { + ControllerButton* button = dynamic_cast (controller); + if (button) { + DEBUG_TRACE (DEBUG::Console1, "Console1::set_plugin_receive_connection CONTROLLER_BUTTON \n"); + + plugin_mapping = [=] (bool b, PBD::Controllable::GroupControlDisposition d) -> void { + button->set_led_state (ac->get_value ()); + DEBUG_TRACE (DEBUG::Console1, + string_compose ("<-ControllerButton Plugin parameter %1: %2 \n", + ppm.paramIndex, + ac->get_value ())); + }; + } + }; + break; + default: + return false; + break; + } + + ac->Changed.connect ( + plugin_connections, MISSING_INVALIDATOR, std::bind (plugin_mapping, _1, _2), this); + ac->Changed (true, PBD::Controllable::GroupControlDisposition::UseGroup); + return true; +} + +bool +Console1::handle_plugin_parameter(const PluginParameterMapping& ppm, int32_t n_controls, + const ParameterDescriptor& parameterDescriptor, + const std::shared_ptr& ac) +{ + bool swtch = false; + DEBUG_TRACE (DEBUG::Console1, string_compose ("\nName: %1 \n", parameterDescriptor.label)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Normal: %1 \n", parameterDescriptor.normal)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Lower: %1 \n", parameterDescriptor.lower)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Upper: %1 \n", parameterDescriptor.upper)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Toggled: %1 \n", parameterDescriptor.toggled)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Logarithmic: %1 \n", parameterDescriptor.logarithmic)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Rangesteps: %1 \n", parameterDescriptor.rangesteps)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Unit: %1 \n", parameterDescriptor.unit)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Step: %1 \n", parameterDescriptor.step)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Smallstep: %1 \n", parameterDescriptor.smallstep)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Largestep: %1 \n", parameterDescriptor.largestep)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Int-step: %1 \n", parameterDescriptor.integer_step)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Sr_dependent: %1 \n", parameterDescriptor.sr_dependent)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Enumeration: %1 \n", parameterDescriptor.enumeration)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Inlinectrl: %1 \n", parameterDescriptor.inline_ctrl)); + + if (parameterDescriptor.toggled) + swtch = true; + else if (parameterDescriptor.integer_step && parameterDescriptor.upper == 1) + swtch = true; + else if (ppm.is_switch) + swtch = true; + + return setup_plugin_controller(ppm, n_controls, parameterDescriptor, ac); +} + +bool +Console1::remap_plugin_parameter (int plugin_index) +{ + DEBUG_TRACE (DEBUG::Console1, string_compose ("Console1::remap_plugin_parameter index = %1 \n", plugin_index)); + //plugin_connections.drop_connections (); + + int32_t n_controls = -1; + std::shared_ptr proc = find_plugin (plugin_index); + set p = proc->what_can_be_automated (); + + std::shared_ptr plugin_insert = std::dynamic_pointer_cast (proc); if (!plugin_insert) return false; @@ -321,127 +523,117 @@ Console1::spill_plugins (const int32_t plugin_index) if (!plugin) return false; - DEBUG_TRACE (DEBUG::Console1, string_compose ("Found plugin id %1\n", plugin->unique_id ())); - - try { - ControllerButton* cb = get_button (ControllerID::MUTE); - std::function plugin_mapping = [=] () -> void { cb->set_led_state (!plugin_insert->enabled ()); }; - cb->set_plugin_action ([=] (uint32_t val) { - plugin_insert->enable (val == 0); - DEBUG_TRACE (DEBUG::Console1, - string_compose ("ControllerButton Plugin parameter %1: %2 \n", n_controls, val)); - }); - - plugin_insert->ActiveChanged.connect ( - plugin_connections, MISSING_INVALIDATOR, std::bind (plugin_mapping), this); - plugin_insert->ActiveChanged (); - } catch (ControlNotFoundException const&) { - DEBUG_TRACE (DEBUG::Console1, string_compose ("No ControllerButton found %1\n", n_controls)); - } - PluginMappingMap::iterator pmmit = pluginMappingMap.find (plugin->unique_id ()); - mapping_found = (pmmit != pluginMappingMap.end ()); - - if (!mapping_found) { - if (create_mapping_stubs) { - create_mapping (proc, plugin); - } - return true; - } + setup_plugin_mute_button (plugin_insert); + PluginMappingMap::iterator pmmit = plugin_mapping_map.find (plugin->unique_id ()); + if (pmmit == plugin_mapping_map.end ()) + return false; PluginMapping pluginMapping = pmmit->second; - DEBUG_TRACE (DEBUG::Console1, - string_compose ("Plugin mapping found for id %1, name %2\n", pluginMapping.id, pluginMapping.name)); - - set p = proc->what_can_be_automated (); - for (set::iterator j = p.begin (); j != p.end (); ++j) { ++n_controls; std::string n = proc->describe_parameter (*j); - DEBUG_TRACE (DEBUG::Console1, string_compose ("Plugin parameter %1: %2\n", n_controls, n)); + DEBUG_TRACE (DEBUG::Console1, string_compose ("Console1::remap_plugin_parameter: Plugin parameter %1: %2\n", n_controls, n)); if (n == "hidden") { continue; } ParameterDescriptor parameterDescriptor; plugin->get_parameter_descriptor (n_controls, parameterDescriptor); - if (plugin->parameter_is_control (n_controls)) { - DEBUG_TRACE (DEBUG::Console1, "parameter is control\n"); - } - if (plugin->parameter_is_output (n_controls)) { - DEBUG_TRACE (DEBUG::Console1, "parameter is output\n"); - } - if (plugin->parameter_is_audio (n_controls)) { - DEBUG_TRACE (DEBUG::Console1, "parameter is audio\n"); - } - if (plugin->parameter_is_input (n_controls)) { - std::shared_ptr c = - plugin_insert->automation_control (Evoral::Parameter (PluginAutomation, 0, n_controls)); - if (c) { - PluginParameterMapping ppm = pluginMapping.parameters[n_controls]; - bool swtch = false; - if (parameterDescriptor.integer_step && parameterDescriptor.upper == 1) { - swtch = true; - } else if (ppm.is_switch) { - swtch = true; - } - if (!swtch) { - try { - Encoder* e = get_encoder (ppm.controllerId); - std::function plugin_mapping = - [=] (bool b, PBD::Controllable::GroupControlDisposition d) -> void { - double v = parameterDescriptor.to_interface (c->get_value (), true); - e->set_value (v * 127); - DEBUG_TRACE ( - DEBUG::Console1, - string_compose ("<-Encoder Plugin parameter %1: %2 - %3\n", n_controls, v * 127, v)); - }; - e->set_plugin_action ([=] (uint32_t val) { - double v = val / 127.f; - c->set_value (parameterDescriptor.from_interface (v, true), - PBD::Controllable::GroupControlDisposition::UseGroup); - DEBUG_TRACE ( - DEBUG::Console1, - string_compose ("->Encoder Plugin parameter %1: %2 - %3\n", n_controls, val, v)); - }); - c->Changed.connect ( - plugin_connections, MISSING_INVALIDATOR, std::bind (plugin_mapping, _1, _2), this); - c->Changed (true, PBD::Controllable::GroupControlDisposition::UseGroup); - continue; - } catch (ControlNotFoundException const&) { - DEBUG_TRACE (DEBUG::Console1, string_compose ("No Encoder found %1\n", n_controls)); - } - } else { - try { - ControllerButton* cb = get_button (ppm.controllerId); - std::function plugin_mapping = - [=] (bool b, PBD::Controllable::GroupControlDisposition d) -> void { - cb->set_led_state (c->get_value ()); - DEBUG_TRACE (DEBUG::Console1, - string_compose ("<-ControllerButton Plugin parameter %1: %2 \n", - n_controls, - c->get_value ())); - }; - cb->set_plugin_action ([=] (uint32_t val) { - double v = val / 127.f; - c->set_value (parameterDescriptor.from_interface (v, true), - PBD::Controllable::GroupControlDisposition::UseGroup); - DEBUG_TRACE ( - DEBUG::Console1, - string_compose ("->ControllerButton Plugin parameter %1: %2 - %3\n", n_controls, val, v)); - }); - - c->Changed.connect ( - plugin_connections, MISSING_INVALIDATOR, std::bind (plugin_mapping, _1, _2), this); - c->Changed (true, PBD::Controllable::GroupControlDisposition::UseGroup); - continue; - } catch (ControlNotFoundException const&) { - DEBUG_TRACE (DEBUG::Console1, string_compose ("No ControllerButton found %1\n", n_controls)); - } - } - } - } - } + PluginParameterMapping ppm = pluginMapping.parameters[n_controls]; + Controller *controller = get_controller (ppm.controllerId); + std::shared_ptr ac = plugin_insert->automation_control (Evoral::Parameter (PluginAutomation, 0, n_controls)); + if (controller && ac) { + DEBUG_TRACE (DEBUG::Console1, string_compose ("CONTROLLER has plugin_action %1, has shitft_plugin_action %2\n", controller->get_plugin_action () ? "Yes" : "No", controller->get_plugin_shift_action () ? "Yes" : "No")); + set_plugin_receive_connection (controller, ac, parameterDescriptor, ppm); + } + } return true; } +bool +Console1::spill_plugins (const int32_t plugin_index) +{ + bool mapping_found = false; + + remove_plugin_operations (); + + std::shared_ptr proc = find_plugin (plugin_index); + if (!proc) + return false; + + int32_t n_controls = -1; + DEBUG_TRACE (DEBUG::Console1, string_compose ("spill_plugins: Found plugin %1\n", proc->name ())); + std::shared_ptr plugin_insert = std::dynamic_pointer_cast (proc); + if (!plugin_insert) + return false; + + std::shared_ptr plugin = plugin_insert->plugin (); + if (!plugin) + return false; + + DEBUG_TRACE (DEBUG::Console1, string_compose ("spill_plugins: Found plugin id %1\n", plugin->unique_id ())); + + // Setup mute button + setup_plugin_mute_button(plugin_insert); + + PluginMappingMap::iterator pmmit = plugin_mapping_map.find (plugin->unique_id ()); + mapping_found = (pmmit != plugin_mapping_map.end ()); + + if (!mapping_found) { + if (create_mapping_stubs) { + create_plugin_mapping_stubs (proc, plugin); + } + return true; + } + + PluginMapping pluginMapping = pmmit->second; + + DEBUG_TRACE (DEBUG::Console1, + string_compose ("spill_plugins: Plugin mapping found for id %1, name %2\n", pluginMapping.id, pluginMapping.name)); + + set p = proc->what_can_be_automated (); + + for (set::iterator j = p.begin (); j != p.end (); ++j) { + ++n_controls; + std::string n = proc->describe_parameter (*j); + DEBUG_TRACE (DEBUG::Console1, string_compose ("spill_plugins: Plugin parameter %1: %2\n", n_controls, n)); + if (n == "hidden") { + continue; + } + ParameterDescriptor parameterDescriptor; + plugin->get_parameter_descriptor (n_controls, parameterDescriptor); + if (plugin->parameter_is_control (n_controls)) { + DEBUG_TRACE (DEBUG::Console1, "parameter is control\n"); + } + if (plugin->parameter_is_output (n_controls)) { + DEBUG_TRACE (DEBUG::Console1, "parameter is output\n"); + } + if (plugin->parameter_is_audio (n_controls)) { + DEBUG_TRACE (DEBUG::Console1, "parameter is audio\n"); + } + if (plugin->parameter_is_input (n_controls)) { + std::shared_ptr c = + plugin_insert->automation_control (Evoral::Parameter (PluginAutomation, 0, n_controls)); + if (c) { + PluginParameterMapping ppm = pluginMapping.parameters[n_controls]; + handle_plugin_parameter(ppm, n_controls, parameterDescriptor, c); + } + } + } + return true; } + +Glib::RefPtr Console1::getPluginControllerModel() +{ + plugin_controller_model = Gtk::ListStore::create (plugin_controller_columns); + Gtk::TreeModel::Row plugin_controller_combo_row; + for( const auto &controller : controllerNameIdMap ) + { + plugin_controller_combo_row = *(plugin_controller_model->append ()); + plugin_controller_combo_row[plugin_controller_columns.controllerId] = controller.second; + plugin_controller_combo_row[plugin_controller_columns.controllerName] = X_ (controller.first); + } + return plugin_controller_model; +} + +} // namespace Console1 diff --git a/libs/surfaces/console1/console1.cc b/libs/surfaces/console1/console1.cc index a5c3666583..7684af9fdc 100644 --- a/libs/surfaces/console1/console1.cc +++ b/libs/surfaces/console1/console1.cc @@ -41,12 +41,16 @@ #include "c1_control.h" #include "c1_gui.h" + + using namespace ARDOUR; -using namespace ArdourSurface; using namespace PBD; using namespace Glib; using namespace std; +namespace Console1 +{ + Console1::Console1 (Session& s) : MIDISurface (s, X_ ("Softube Console1"), X_ ("Console1"), false) , gui (0) @@ -66,25 +70,17 @@ Console1::~Console1 () stop_event_loop (); MIDISurface::drop (); - for (const auto& b : buttons) { - delete b.second; - } - for (const auto& e : encoders) { - delete e.second; - } - for (const auto& m : meters) { - delete m.second; - } - for (const auto& mb : multi_buttons) { - delete mb.second; + for (const auto& c : controllerMap) { + delete c.second; } } void Console1::all_lights_out () { - for (ButtonMap::iterator b = buttons.begin (); b != buttons.end (); ++b) { - b->second->set_led_state (false); + for (ControllerMap::iterator b = controllerMap.begin (); b != controllerMap.end (); ++b) { + if( b->second->get_type() == ControllerType::CONTROLLER_BUTTON ) + (dynamic_cast(b->second))->set_led_state (false); } } @@ -181,7 +177,7 @@ Console1::begin_using_device () f0 7d 20 00 00 00 01 00 7f 49 6f 6c 73 00 f7 */ - load_mappings (); + load_mappings (); setup_controls (); /* Connection to the blink-timer */ @@ -277,18 +273,22 @@ Console1::setup_controls () for (uint32_t i = 0; i < 20; ++i) { new ControllerButton (this, - ControllerID (FOCUS1 + i), - std::function (std::bind (&Console1::select, this, i)), - 0, - std::function (std::bind (&Console1::select_plugin, this, i))); + ControllerID (FOCUS1 + i), + std::function (std::bind (&Console1::select, this, i)), + std::function (std::bind (&Console1::select, this, i)), + std::function (std::bind (&Console1::select_plugin, this, i)), + std::function (std::bind (&Console1::select_plugin, this, i))); } new ControllerButton ( this, ControllerID::PRESET, std::function (std::bind (&Console1::shift, this, _1))); new ControllerButton (this, - ControllerID::TRACK_GROUP, - std::function (std::bind (&Console1::plugin_state, this, _1))); + ControllerID::TRACK_GROUP, + std::function (std::bind (&Console1::plugin_state, this, _1)), + std::function (std::bind (&Console1::plugin_state, this, _1)), + std::function (std::bind (&Console1::plugin_state, this, _1)), + std::function (std::bind (&Console1::plugin_state, this, _1))); new ControllerButton ( this, ControllerID::DISPLAY_ON, std::function (std::bind (&Console1::rude_solo, this, _1))); @@ -438,64 +438,48 @@ void Console1::handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes* tb) { uint32_t controller_number = static_cast (tb->controller_number); - uint32_t value = static_cast (tb->value); -DEBUG_TRACE (DEBUG::Console1, + uint32_t value = static_cast (tb->value); + + DEBUG_TRACE (DEBUG::Console1, string_compose ("handle_midi_controller_message cn: '%1' val: '%2'\n", controller_number, value)); - try { - Encoder* e = get_encoder (ControllerID (controller_number)); - if (in_plugin_state && e->plugin_action) { - e->plugin_action (value); - } else if (shift_state && e->shift_action) { - e->shift_action (value); - } else { - e->action (value); - } + DEBUG_TRACE (DEBUG::Console1, + string_compose ("handle_midi_controller_message shift state: '%1' plugin state: '%2'\n", shift_state, in_plugin_state)); + + if (midi_assign_mode && (controller_number != ControllerID::PRESET)) { + SendControllerNumber (controller_number, shift_state); return; - } catch (ControlNotFoundException const&) { + } + + try { + Controller* controller = controllerMap[ControllerID (controller_number)]; + if (controller ) { + DEBUG_TRACE (DEBUG::Console1, "handle_midi_controller_message; Controller Found'\n"); + if (shift_state && in_plugin_state && controller->get_plugin_shift_action ()) { + controller->get_plugin_shift_action () (value); + DEBUG_TRACE (DEBUG::Console1, "handle_midi_controller_message: plugin_shift_action'\n" ); + } else if (in_plugin_state && controller->get_plugin_action ()) { + controller->get_plugin_action () (value); + DEBUG_TRACE (DEBUG::Console1, "handle_midi_controller_message: plugin_action'\n"); + } else if (shift_state && controller->get_shift_action ()) { + controller->get_shift_action () (value); + DEBUG_TRACE (DEBUG::Console1, "handle_midi_controller_message: shift_action'\n"); + } else { + controller->get_action () (value); + DEBUG_TRACE (DEBUG::Console1, "handle_midi_controller_message: action'\n"); + } + return; + } + else { + DEBUG_TRACE (DEBUG::Console1, "handle_midi_controller_message: Controller not found'\n"); + } + } + catch (ControlNotFoundException const&) { DEBUG_TRACE (DEBUG::Console1, string_compose ("handle_midi_controller_message: encoder not found cn: " "'%1' val: '%2'\n", controller_number, value)); } - - try { - ControllerButton* b = get_button (ControllerID (controller_number)); - if (in_plugin_state && b->plugin_action) { - DEBUG_TRACE (DEBUG::Console1, "Executing plugin_action\n"); - b->plugin_action (value); - } else if (shift_state && b->shift_action) { - DEBUG_TRACE (DEBUG::Console1, "Executing shift_action\n"); - b->shift_action (value); - } else { - DEBUG_TRACE (DEBUG::Console1, "Executing action\n"); - b->action (value); - } - return; - } catch (ControlNotFoundException const&) { - DEBUG_TRACE (DEBUG::Console1, - string_compose ("handle_midi_controller_message: button not found cn: " - "'%1' val: '%2'\n", - controller_number, - value)); - } - - try { - MultiStateButton* mb = get_mbutton (ControllerID (controller_number)); - if (shift_state && mb->shift_action) { - mb->shift_action (value); - } else { - mb->action (value); - } - - return; - } catch (ControlNotFoundException const&) { - DEBUG_TRACE (DEBUG::Console1, - string_compose ("handle_midi_controller_message: mbutton not found cn: " - "'%1' val: '%2'\n", - controller_number, - value)); - } } void @@ -532,7 +516,7 @@ Console1::notify_transport_state_changed () void Console1::stripable_selection_changed () { - DEBUG_TRACE (DEBUG::Console1, "stripable_selection_changed \n"); + DEBUG_TRACE (DEBUG::Console1, "stripable_selection_changed \n"); if (!_in_use) return; @@ -953,15 +937,6 @@ Console1::blinker () return true; } -ControllerButton* -Console1::get_button (ControllerID id) const -{ - ButtonMap::const_iterator b = buttons.find (id); - if (b == buttons.end ()) - throw (ControlNotFoundException ()); - return const_cast (b->second); -} - Meter* Console1::get_meter (ControllerID id) const { @@ -971,22 +946,42 @@ Console1::get_meter (ControllerID id) const return const_cast (m->second); } +Controller* +Console1::get_controller (ControllerID id) const +{ + ControllerMap::const_iterator c = controllerMap.find (id); + if (c == controllerMap.end ()) + throw (ControlNotFoundException ()); + return (c->second); +} + +Controller* +Console1::get_controller (ControllerID id, ControllerType controllerType) const +{ + ControllerMap::const_iterator c = controllerMap.find (id); + if ((c == controllerMap.end ()) || (c->second->get_type () != controllerType)) + throw (ControlNotFoundException ()); + return (c->second); +} + Encoder* Console1::get_encoder (ControllerID id) const { - EncoderMap::const_iterator m = encoders.find (id); - if (m == encoders.end ()) - throw (ControlNotFoundException ()); - return const_cast (m->second); + return dynamic_cast (get_controller (id, ControllerType::ENCODER)); } +ControllerButton* +Console1::get_button (ControllerID id) const +{ + return dynamic_cast (get_controller (id, ControllerType::CONTROLLER_BUTTON)); +} + + + MultiStateButton* Console1::get_mbutton (ControllerID id) const { - MultiStateButtonMap::const_iterator m = multi_buttons.find (id); - if (m == multi_buttons.end ()) - throw (ControlNotFoundException ()); - return const_cast (m->second); + return dynamic_cast (get_controller (id, ControllerType::MULTISTATE_BUTTON)); } ControllerID @@ -1259,3 +1254,21 @@ Console1::master_monitor_has_changed () DEBUG_TRACE (DEBUG::Console1, string_compose ("master_monitor_has_changed - monitor active %1\n", monitor_active)); create_strip_inventory (); } + +const std::string Console1::findControllerNameById (const ControllerID id){ + for( const auto &controller : controllerNameIdMap ){ + if( controller.second == id ){ + return controller.first; + } + } + return std::string(); +} + +void +Console1::reset_midi_assign_mode () +{ + DEBUG_TRACE (DEBUG::Console1, "console1::reset_midi_assign_mode()\n"); + midi_assign_mode = false; +} + +} // namespace Console1 \ No newline at end of file diff --git a/libs/surfaces/console1/console1.h b/libs/surfaces/console1/console1.h index 58cd9b3b94..d2702da281 100644 --- a/libs/surfaces/console1/console1.h +++ b/libs/surfaces/console1/console1.h @@ -23,9 +23,17 @@ #include #include +#include + +#include +#include + +#include + #define ABSTRACT_UI_EXPORTS #include "pbd/abstract_ui.h" +#include "ardour/parameter_descriptor.h" #include "ardour/presentation_info.h" #include "control_protocol/control_protocol.h" @@ -55,20 +63,15 @@ namespace PBD { class Controllable; } +namespace Console1 +{ + class MIDIControllable; class MIDIFunction; class MIDIAction; -namespace ArdourSurface { - class C1GUI; -// XXX TODO: these classes should not be in the ArdourSurface namespace -// which is shared with all other ctrl surfaces. -// -// ArdourSurface::Meter etc may cause conflicts. -// best add a C1 prefix, or additional namespace - class Controller; class ControllerButton; class MultiStateButton; @@ -86,6 +89,14 @@ public: ControlNotFoundException () {} }; +enum ControllerType { + CONTROLLER, + CONTROLLER_BUTTON, + MULTISTATE_BUTTON, + ENCODER, + METER +}; + class Console1 : public MIDISurface { @@ -109,6 +120,7 @@ public: std::string input_port_name () const override; std::string output_port_name () const override; + uint32_t load_mappings (); XMLNode& get_state () const override; int set_state (const XMLNode&, int version) override; @@ -118,109 +130,113 @@ public: bool create_mapping_stubs; bool switch_eq_q_dials = true; + bool midi_assign_mode = false; + + void reset_midi_assign_mode (); + bool in_use(){ return _in_use; } - PBD::Signal ConnectionChange; + PBD::Signal ConnectionChange; /* Timer Events */ - PBD::Signal BlinkIt; - PBD::Signal Periodic; + PBD::Signal BlinkIt; + PBD::Signal Periodic; - /* Local Signals */ - PBD::Signal BankChange; - PBD::Signal ShiftChange; - PBD::Signal PluginStateChange; - PBD::Signal EQBandQBindingChange; + /* Local Signals */ + PBD::Signal PluginStubAdded; + PBD::Signal BankChange; + PBD::Signal ShiftChange; + PBD::Signal PluginStateChange; + PBD::Signal EQBandQBindingChange; + sigc::signal2 SendControllerNumber; - enum ControllerID - { - CONTROLLER_NONE = 0, - VOLUME = 7, - PAN = 10, - MUTE = 12, - SOLO = 13, - ORDER = 14, - DRIVE = 15, - EXTERNAL_SIDECHAIN = 17, - CHARACTER = 18, - FOCUS1 = 21, - FOCUS2, - FOCUS3, - FOCUS4, - FOCUS5, - FOCUS6, - FOCUS7, - FOCUS8, - FOCUS9, - FOCUS10, - FOCUS11, - FOCUS12, - FOCUS13, - FOCUS14, - FOCUS15, - FOCUS16, - FOCUS17, - FOCUS18, - FOCUS19, - FOCUS20 = 40, - COMP = 46, - COMP_THRESH = 47, - COMP_RELEASE = 48, - COMP_RATIO = 49, - COMP_PAR = 50, - COMP_ATTACK = 51, - SHAPE = 53, - SHAPE_GATE = 54, - SHAPE_SUSTAIN = 55, - SHAPE_RELEASE = 56, - SHAPE_PUNCH = 57, - PRESET = 58, - HARD_GATE = 59, - FILTER_TO_COMPRESSORS = 61, - HIGH_SHAPE = 65, - EQ = 80, - HIGH_GAIN = 82, - HIGH_FREQ = 83, - HIGH_MID_GAIN = 85, - HIGH_MID_FREQ = 86, - HIGH_MID_SHAPE = 87, - LOW_MID_GAIN = 88, - LOW_MID_FREQ = 89, - LOW_MID_SHAPE = 90, - LOW_GAIN = 91, - LOW_FREQ = 92, - LOW_SHAPE = 93, - PAGE_UP = 96, - PAGE_DOWN = 97, - DISPLAY_ON = 102, - LOW_CUT = 103, - MODE = 104, - HIGH_CUT = 105, - GAIN = 107, - PHASE_INV = 108, - INPUT_METER_L = 110, - INPUT_METER_R = 111, - OUTPUT_METER_L = 112, - OUTPUT_METER_R = 113, - SHAPE_METER = 114, - COMP_METER = 115, - TRACK_COPY = 120, - TRACK_GROUP = 123, + enum ControllerID { + CONTROLLER_NONE = 0, + VOLUME = 7, + PAN = 10, + MUTE = 12, + SOLO = 13, + ORDER = 14, + DRIVE = 15, + EXTERNAL_SIDECHAIN = 17, + CHARACTER = 18, + FOCUS1 = 21, + FOCUS2, + FOCUS3, + FOCUS4, + FOCUS5, + FOCUS6, + FOCUS7, + FOCUS8, + FOCUS9, + FOCUS10, + FOCUS11, + FOCUS12, + FOCUS13, + FOCUS14, + FOCUS15, + FOCUS16, + FOCUS17, + FOCUS18, + FOCUS19, + FOCUS20 = 40, + COMP = 46, + COMP_THRESH = 47, + COMP_RELEASE = 48, + COMP_RATIO = 49, + COMP_PAR = 50, + COMP_ATTACK = 51, + SHAPE = 53, + SHAPE_GATE = 54, + SHAPE_SUSTAIN = 55, + SHAPE_RELEASE = 56, + SHAPE_PUNCH = 57, + PRESET = 58, + HARD_GATE = 59, + FILTER_TO_COMPRESSORS = 61, + HIGH_SHAPE = 65, + EQ = 80, + HIGH_GAIN = 82, + HIGH_FREQ = 83, + HIGH_MID_GAIN = 85, + HIGH_MID_FREQ = 86, + HIGH_MID_SHAPE = 87, + LOW_MID_GAIN = 88, + LOW_MID_FREQ = 89, + LOW_MID_SHAPE = 90, + LOW_GAIN = 91, + LOW_FREQ = 92, + LOW_SHAPE = 93, + PAGE_UP = 96, + PAGE_DOWN = 97, + DISPLAY_ON = 102, + LOW_CUT = 103, + MODE = 104, + HIGH_CUT = 105, + GAIN = 107, + PHASE_INV = 108, + INPUT_METER_L = 110, + INPUT_METER_R = 111, + OUTPUT_METER_L = 112, + OUTPUT_METER_R = 113, + SHAPE_METER = 114, + COMP_METER = 115, + TRACK_COPY = 120, + TRACK_GROUP = 123, - }; + }; - enum EQ_MODE - { - EQM_UNDEFINED = -1, - EQM_HARRISON = 0, - EQM_SSL = 1 - }; + enum EQ_MODE { + EQM_UNDEFINED = -1, + EQM_HARRISON = 0, + EQM_SSL = 1 + }; - using ControllerMap = std::map; + using ControllerNameIdMap = std::map; - ControllerMap controllerMap{ { "CONTROLLER_NONE", ControllerID::CONTROLLER_NONE }, + ControllerNameIdMap controllerNameIdMap{ { "CONTROLLER_NONE", ControllerID::CONTROLLER_NONE }, { "VOLUME", ControllerID::VOLUME }, { "PAN", ControllerID::PAN }, { "MUTE", ControllerID::MUTE }, @@ -293,12 +309,27 @@ public: { "TRACK_COPY", ControllerID::TRACK_COPY }, { "TRACK_GROUP", ControllerID::TRACK_GROUP } }; -private: + struct PluginControllerColumns : public Gtk::TreeModel::ColumnRecord { + PluginControllerColumns () { + add (controllerName); + add (controllerId); + } + Gtk::TreeModelColumn controllerName; + Gtk::TreeModelColumn controllerId; + }; + PluginControllerColumns plugin_controller_columns; + Glib::RefPtr plugin_controller_model; + const std::string findControllerNameById (const ControllerID id); + + private: std::string config_dir_name = "c1mappings"; /* GUI */ mutable C1GUI* gui; void build_gui (); + bool mappings_loaded = false; + bool controls_model_loaded = false; + /* Configuration */ const uint32_t bank_size = 20; @@ -311,7 +342,7 @@ private: // Selected EQ EQ_MODE strip_eq_mode = EQM_UNDEFINED; - bool rolling = false; + bool rolling = false; uint32_t current_bank = 0; uint32_t current_strippable_index = 0; @@ -372,76 +403,74 @@ private: void select_rid_by_index (const uint32_t index); /* Controller Maps*/ - typedef std::map ButtonMap; - typedef std::map MultiStateButtonMap; - typedef std::map MeterMap; - typedef std::map EncoderMap; + typedef std::map MeterMap; - ButtonMap buttons; - ControllerButton* get_button (ControllerID) const; + typedef std::map ControllerMap; - MultiStateButtonMap multi_buttons; - MultiStateButton* get_mbutton (ControllerID id) const; + MeterMap meters; + Meter* get_meter (ControllerID) const; + ControllerButton* get_button (ControllerID) const; - MeterMap meters; - Meter* get_meter (ControllerID) const; + MultiStateButton* get_mbutton (ControllerID id) const; - EncoderMap encoders; - Encoder* get_encoder (ControllerID) const; + Encoder* get_encoder (ControllerID) const; - typedef std::map SendControllerMap; - SendControllerMap send_controllers{ { 0, LOW_FREQ }, { 1, LOW_MID_FREQ }, { 2, HIGH_MID_FREQ }, - { 3, HIGH_FREQ }, { 4, LOW_GAIN }, { 5, LOW_MID_GAIN }, - { 6, HIGH_MID_GAIN }, { 7, HIGH_GAIN }, { 8, LOW_MID_SHAPE }, - { 9, HIGH_MID_SHAPE }, { 10, LOW_MID_SHAPE }, { 11, HIGH_MID_SHAPE } }; + ControllerMap controllerMap; + Controller* get_controller (ControllerID id) const; + Controller* get_controller (ControllerID id, ControllerType controllerType) const; - ControllerID get_send_controllerid (uint32_t); + typedef std::map SendControllerMap; + SendControllerMap send_controllers{ { 0, LOW_FREQ }, { 1, LOW_MID_FREQ }, { 2, HIGH_MID_FREQ }, { 3, HIGH_FREQ }, + { 4, LOW_GAIN }, { 5, LOW_MID_GAIN }, { 6, HIGH_MID_GAIN }, { 7, HIGH_GAIN }, + { 8, LOW_MID_SHAPE }, { 9, HIGH_MID_SHAPE }, { 10, LOW_MID_SHAPE }, { 11, HIGH_MID_SHAPE } }; - /* */ - void all_lights_out (); + ControllerID get_send_controllerid (uint32_t); - void notify_transport_state_changed () override; - void notify_solo_active_changed (bool) override; + /* */ + void all_lights_out (); - sigc::connection periodic_connection; + void notify_transport_state_changed () override; + void notify_solo_active_changed (bool) override; - bool periodic (); - void periodic_update_meter (); + sigc::connection periodic_connection; - // Meter Handlig - uint32_t last_output_meter_l = 0; - uint32_t last_output_meter_r = 0; + bool periodic (); + void periodic_update_meter (); - std::shared_ptr gate_redux_meter = 0; - uint32_t last_gate_meter = 0; + // Meter Handlig + uint32_t last_output_meter_l = 0; + uint32_t last_output_meter_r = 0; - std::shared_ptr comp_redux_meter = 0; - uint32_t last_comp_redux = 0; + std::shared_ptr gate_redux_meter = 0; + uint32_t last_gate_meter = 0; - sigc::connection blink_connection; - typedef std::list Blinkers; - Blinkers blinkers; - bool blink_state; - bool blinker (); - void start_blinking (ControllerID); - void stop_blinking (ControllerID); + std::shared_ptr comp_redux_meter = 0; + uint32_t last_comp_redux = 0; - void set_current_stripable (std::shared_ptr); - void drop_current_stripable (); - /*void use_master (); - void use_monitor ();*/ - void stripable_selection_changed () override; - /*PBD::ScopedConnection selection_connection;*/ - PBD::ScopedConnectionList stripable_connections; - PBD::ScopedConnectionList console1_connections; - PBD::ScopedConnectionList plugin_connections; + sigc::connection blink_connection; + typedef std::list Blinkers; + Blinkers blinkers; + bool blink_state; + bool blinker (); + void start_blinking (ControllerID); + void stop_blinking (ControllerID); - void map_stripable_state (); + void set_current_stripable (std::shared_ptr); + void drop_current_stripable (); + /*void use_master (); + void use_monitor ();*/ + void stripable_selection_changed () override; + /*PBD::ScopedConnection selection_connection;*/ + PBD::ScopedConnectionList stripable_connections; + PBD::ScopedConnectionList console1_connections; + PBD::ScopedConnectionList plugin_connections; - void notify_parameter_changed (std::string) override; - void band_q_usage_changed (); + void map_stripable_state (); - /* operations (defined in c1_operations.cc) */ + void notify_parameter_changed (std::string) override; + void band_q_usage_changed (); + + /* operations (defined in c1_operations.cc) */ void bank (bool up); void drive (uint32_t value); @@ -630,32 +659,59 @@ private: using ParameterMap = std::map; + /* plugin handling */ + bool ensure_config_dir (); + bool load_mapping (XMLNode* fin); + + /** + * @brief Creates mapping stubs for a given plugin processor. + * + * This function sets up the necessary mapping stubs to associate the specified + * plugin with its processor, enabling control surface integration or automation. + * + * @param proc Shared pointer to the ARDOUR::Processor instance to be mapped. + * @param plugin Shared pointer to the ARDOUR::Plugin instance for which mapping stubs are created. + */ + void create_plugin_mapping_stubs (const std::shared_ptr proc, const std::shared_ptr plugin); + + bool spill_plugins (const int32_t plugin_index); + + bool setup_plugin_mute_button (const std::shared_ptr& plugin_insert); + + bool setup_plugin_controller (const PluginParameterMapping& ppm, int32_t n_controls, + const ARDOUR::ParameterDescriptor& parameterDescriptor, + const std::shared_ptr& ac); + + bool handle_plugin_parameter (const PluginParameterMapping& ppm, int32_t n_controls, + const ARDOUR::ParameterDescriptor& parameterDescriptor, + const std::shared_ptr& c); + + bool set_plugin_receive_connection (Controller* controller, const std::shared_ptr& ac, const ARDOUR::ParameterDescriptor& parameterDescriptor, const PluginParameterMapping& ppm); + + bool remap_plugin_parameter (int plugin_index); + + /* plugin operations */ + void remove_plugin_operations (); + std::shared_ptr find_plugin (const int32_t plugin_index); + bool select_plugin (const int32_t plugin_index); + + bool map_select_plugin (const int32_t plugin_index); + + void eqBandQChangeMapping (bool mapValues); + +public: struct PluginMapping { std::string id; std::string name; + bool configured; ParameterMap parameters; }; + using PluginMappingMap = std::map; + PluginMappingMap plugin_mapping_map; - /* plugin handling */ - bool ensure_config_dir (); - uint32_t load_mappings (); - bool load_mapping (XMLNode* fin); - void create_mapping (const std::shared_ptr proc, const std::shared_ptr plugin); - - bool spill_plugins (const int32_t plugin_index); - - /* plugin operations */ - void remove_plugin_operations (); - std::shared_ptr find_plugin (const int32_t plugin_index); - bool select_plugin (const int32_t plugin_index); - - bool map_select_plugin (const int32_t plugin_index); - - void eqBandQChangeMapping (bool mapValues); - - using PluginMappingMap = std::map; - PluginMappingMap pluginMappingMap; + Glib::RefPtr getPluginControllerModel(); + void write_plugin_mapping (PluginMapping &mapping); }; -} +} // namespace Console1 #endif /* ardour_surface_console1_h */ diff --git a/libs/surfaces/console1/console1_interface.cc b/libs/surfaces/console1/console1_interface.cc index 0b04edc0bd..636ec2c6f3 100644 --- a/libs/surfaces/console1/console1_interface.cc +++ b/libs/surfaces/console1/console1_interface.cc @@ -22,15 +22,14 @@ #include "console1.h" using namespace ARDOUR; -using namespace ArdourSurface; static ControlProtocol* new_console1 (Session* s) { - Console1* console1 = 0; + Console1::Console1* console1 = 0; try { - console1 = new Console1 (*s); + console1 = new Console1::Console1 (*s); } catch (failed_constructor& err) { delete console1; console1 = 0; diff --git a/libs/surfaces/console1/wscript b/libs/surfaces/console1/wscript index 5668b9cee5..b9af2156ca 100644 --- a/libs/surfaces/console1/wscript +++ b/libs/surfaces/console1/wscript @@ -15,6 +15,7 @@ def build(bld): console1.cc c1_operations.cc c1_plugin_operations.cc + c1_plugin_control_assignment.cc c1_gui.cc ''' obj.defines = [ 'PACKAGE="ardour_console1"' ] @@ -22,6 +23,11 @@ def build(bld): obj.includes = [ '.', './console1'] obj.name = 'libardour_console1' obj.target = 'ardour_console1' - obj.uselib = 'SIGCPP XML OSX GLIBMM GIOMM PANGOMM' - obj.use = 'libardour libardour_cp libardour_midisurface libgtkmm2ext libpbd libevoral libtemporal libytkmm' + obj.uselib = 'SIGCPP XML OSX' + obj.use = 'libardour libardour_cp libardour_midisurface libgtkmm2ext libpbd libevoral libtemporal' obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces') + if bld.is_defined('YTK'): + obj.use += ' libytkmm' + obj.uselib += ' GLIBMM GIOMM PANGOMM' + else: + obj.uselib += ' GTKMM'