c1: Add GUI for plugin mappings

This commit is contained in:
Hoger Dehnhardt 2023-11-13 21:56:57 +01:00
parent 361d0374dc
commit 5db598fb0a
5 changed files with 340 additions and 32 deletions

View file

@ -22,6 +22,7 @@
#include <ytkmm/label.h> #include <ytkmm/label.h>
#include <ytkmm/liststore.h> #include <ytkmm/liststore.h>
#include <gtkmm/alignment.h>
#include "pbd/file_utils.h" #include "pbd/file_utils.h"
#include "pbd/i18n.h" #include "pbd/i18n.h"
#include "pbd/strsplit.h" #include "pbd/strsplit.h"
@ -32,6 +33,7 @@
#include "ardour/filesystem_paths.h" #include "ardour/filesystem_paths.h"
#include "ardour/parameter_descriptor.h" #include "ardour/parameter_descriptor.h"
#include "console1.h" #include "console1.h"
#include "gtkmm2ext/action_model.h"
#include "gtkmm2ext/bindings.h" #include "gtkmm2ext/bindings.h"
#include "gtkmm2ext/gui_thread.h" #include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h" #include "gtkmm2ext/utils.h"
@ -49,7 +51,7 @@ Console1::get_gui () const
if (!gui) { if (!gui) {
const_cast<Console1*> (this)->build_gui (); const_cast<Console1*> (this)->build_gui ();
} }
static_cast<Gtk::VBox*> (gui)->show_all (); static_cast<Gtk::Notebook*> (gui)->show_all ();
return gui; return gui;
} }
@ -57,7 +59,7 @@ void
Console1::tear_down_gui () Console1::tear_down_gui ()
{ {
if (gui) { if (gui) {
Gtk::Widget* w = static_cast<Gtk::VBox*> (gui)->get_parent (); Gtk::Widget* w = static_cast<Gtk::Widget*> (gui)->get_parent ();
if (w) { if (w) {
w->hide (); w->hide ();
delete w; delete w;
@ -167,10 +169,44 @@ C1GUI::C1GUI (Console1& p)
row++; row++;
hpacker.pack_start (table, true, true); 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 = manage (new VBox);
HBox* plugselect_packer = manage (new HBox);
l = manage (new Gtk::Label (_("Select Plugin")));
plugselect_packer->pack_start (*l, false, false);
plugconfig_packer->pack_start (*plugselect_packer, false, false);
Glib::RefPtr<Gtk::ListStore> plugin_store_model = ListStore::create (plugin_columns);
TreeModel::Row plugin_combo_row;
for( const auto &pm : c1.getPluginMappingMap() ){
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);
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 ();
append_page (*plugconfig_packer, _ ("Plugin Mappings"));
plugconfig_packer->show_all ();
/* update the port connection combos */ /* update the port connection combos */
@ -186,7 +222,9 @@ C1GUI::C1GUI (Console1& p)
_port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ()); _port_connections, invalidator (*this), std::bind (&C1GUI::connection_handler, this), gui_context ());
} }
C1GUI::~C1GUI () {} C1GUI::~C1GUI () {
write_plugin_assignment();
}
void void
C1GUI::set_swap_solo_mute () C1GUI::set_swap_solo_mute ()
@ -287,7 +325,7 @@ C1GUI::build_midi_port_list (vector<string> const& ports, bool for_input)
row = *store->append (); row = *store->append ();
row[midi_port_columns.full_name] = string (); row[midi_port_columns.full_name] = string ();
row[midi_port_columns.short_name] = _ ("Disconnected"); row[midi_port_columns.short_name] = _("Disconnected");
for (vector<string>::const_iterator p = ports.begin (); p != ports.end (); ++p) { for (vector<string>::const_iterator p = ports.begin (); p != ports.end (); ++p) {
row = *store->append (); row = *store->append ();
@ -334,3 +372,119 @@ C1GUI::active_port_changed (Gtk::ComboBox* combo, bool for_input)
} }
} }
} }
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];
pc.parameters[index].controllerId = ArdourSurface::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));
assignement_changed = true;
}
}
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 = !pc.parameters[index].shift;
pc.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));
assignement_changed = true;
}
}
CellRendererCombo*
C1GUI::make_action_renderer (Glib::RefPtr<ListStore> 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::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* renderer;
CellRendererToggle* boolRenderer = manage (new CellRendererToggle);
boolRenderer->set_active ();
boolRenderer->property_activatable() = true;
col = manage (new TreeViewColumn (_ ("Shift"), *boolRenderer));
col->add_attribute (boolRenderer->property_active (), plugin_assignment_editor_columns.shift);
boolRenderer->signal_toggled().connect (sigc::mem_fun(*this, &C1GUI::toggle_shift));
plugin_assignment_editor.append_column (*col);
renderer = make_action_renderer (c1.getPluginControllerModel(), plugin_assignment_editor_columns.controllerName);
col = manage (new TreeViewColumn (_("Control"), *renderer));
col->add_attribute (renderer->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<TreeModel>());
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));
pc = c1.getPluginMappingMap ()[new_plugin_id];
for( auto &parm : pc.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);
}
void C1GUI::write_plugin_assignment(){
DEBUG_TRACE (DEBUG::Console1, "write_plugin_assignment\n");
if( !assignement_changed )
return;
c1.write_plugin_mapping (pc);
assignement_changed = false;
}

View file

@ -30,19 +30,32 @@
#include <ytkmm/treestore.h> #include <ytkmm/treestore.h>
#include <ytkmm/spinbutton.h> #include <ytkmm/spinbutton.h>
#include <ytkmm/notebook.h> #include <ytkmm/notebook.h>
#include <gtkmm/box.h>
#include <gtkmm/combobox.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/image.h>
#include <gtkmm/notebook.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/table.h>
#include <gtkmm/treestore.h>
#include <gtkmm/spinbutton.h>
namespace Gtk { namespace Gtk {
class CellRendererCombo; class CellRendererCombo;
class ListStore; class ListStore;
} }
namespace ActionManager {
class ActionModel;
}
#include "ardour/mode.h" #include "ardour/mode.h"
#include "console1.h" #include "console1.h"
namespace ArdourSurface { namespace ArdourSurface {
class C1GUI : public Gtk::VBox class C1GUI : public Gtk::Notebook
{ {
public: public:
C1GUI (Console1&); C1GUI (Console1&);
@ -55,11 +68,19 @@ private:
Gtk::Table table; Gtk::Table table;
Gtk::ComboBox input_combo; Gtk::ComboBox input_combo;
Gtk::ComboBox output_combo; Gtk::ComboBox output_combo;
Gtk::ComboBox plugins_combo;
Gtk::ScrolledWindow plugin_mapping_scroller;
Gtk::Image image; Gtk::Image image;
Gtk::CheckButton swap_solo_mute_cb; Gtk::CheckButton swap_solo_mute_cb;
Gtk::CheckButton band_q_as_send_cb; Gtk::CheckButton band_q_as_send_cb;
Gtk::CheckButton create_plugin_stubs_btn; Gtk::CheckButton create_plugin_stubs_btn;
Gtk::TreeView plugin_assignment_editor;
Gtk::VBox plugin_packer;
bool assignement_changed = false;
void update_port_combos (); void update_port_combos ();
PBD::ScopedConnection connection_change_connection; PBD::ScopedConnection connection_change_connection;
void connection_handler (); void connection_handler ();
@ -74,17 +95,54 @@ private:
Gtk::TreeModelColumn<std::string> full_name; Gtk::TreeModelColumn<std::string> full_name;
}; };
struct PluginColumns : public Gtk::TreeModel::ColumnRecord {
PluginColumns() {
add (plugin_name);
add (plugin_id);
}
Gtk::TreeModelColumn<std::string> plugin_name;
Gtk::TreeModelColumn<std::string> plugin_id;
};
struct PluginAssignamentEditorColumns : public Gtk::TreeModel::ColumnRecord {
PluginAssignamentEditorColumns() {
add (index);
add (name);
add (is_switch);
add (controllerName);
add (shift);
};
Gtk::TreeModelColumn<int> index; // parameter index
Gtk::TreeModelColumn<std::string> name; // readable name of the parameter
Gtk::TreeModelColumn<bool> is_switch;
Gtk::TreeModelColumn<std::string> controllerName; // enum Button::ID
Gtk::TreeModelColumn<bool> shift;
};
MidiPortColumns midi_port_columns; MidiPortColumns midi_port_columns;
PluginColumns plugin_columns;
PluginAssignamentEditorColumns plugin_assignment_editor_columns;
Glib::RefPtr<Gtk::ListStore> plugin_assignment_store;
bool ignore_active_change; bool ignore_active_change;
Glib::RefPtr<Gtk::ListStore> build_midi_port_list (std::vector<std::string> const & ports, bool for_input); Glib::RefPtr<Gtk::ListStore> build_midi_port_list (std::vector<std::string> const & ports, bool for_input);
void active_port_changed (Gtk::ComboBox*,bool for_input);
ArdourSurface::Console1::PluginMapping pc;
Gtk::CellRendererCombo* make_action_renderer (Glib::RefPtr<Gtk::ListStore> model, Gtk::TreeModelColumnBase column);
void build_plugin_assignment_editor ();
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_swap_solo_mute ();
void set_band_q_as_send(); void set_band_q_as_send();
void set_create_mapping_stubs(); void set_create_mapping_stubs ();
void active_plugin_changed (Gtk::ComboBox* combo);
void write_plugin_assignment ();
}; };
} }
#endif /* __ardour_console1_gui_h__ */ #endif /* __ardour_console1_gui_h__ */

View file

@ -57,6 +57,9 @@ Console1::ensure_config_dir ()
uint32_t uint32_t
Console1::load_mappings () Console1::load_mappings ()
{ {
if( mappings_loaded )
return pluginMappingMap.size ();
uint32_t i = 0; uint32_t i = 0;
if (!ensure_config_dir ()) if (!ensure_config_dir ())
return 1; return 1;
@ -89,7 +92,9 @@ Console1::load_mappings ()
++i; ++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 - found %1 mapping files\n", i));
DEBUG_TRACE (DEBUG::Console1, string_compose ("Console1::load_mappings - loaded %1 mapping files\n", pluginMappingMap.size()));
g_dir_close (gdir); g_dir_close (gdir);
mappings_loaded = true;
return i; return i;
} }
@ -118,26 +123,32 @@ Console1::load_mapping (XMLNode* mapping_xml)
const XMLNodeList& plist = (*i)->children (); const XMLNodeList& plist = (*i)->children ();
XMLNodeConstIterator j; XMLNodeConstIterator j;
PluginParameterMapping parmap;
for (j = plist.begin (); j != plist.end (); ++j) { for (j = plist.begin (); j != plist.end (); ++j) {
if ((*j)->name () == "name") { if ((*j)->name () == "name") {
param_name = (*j)->child_content (); param_name = (*j)->child_content ();
} else if ((*j)->name () == "mapping") { } else if ((*j)->name () == "mapping") {
param_mapping = (*j)->child_content (); param_mapping = (*j)->child_content ();
(*j)->get_property ("shift", parmap.shift);
} }
} }
parmap.paramIndex = index;
parmap.name = param_name;
parmap.is_switch = (param_type == "switch");
if (!param_mapping.empty ()) { if (!param_mapping.empty ()) {
PluginParameterMapping parmap;
parmap.paramIndex = index;
parmap.name = param_name;
ControllerMap::const_iterator m = controllerMap.find (param_mapping); ControllerMap::const_iterator m = controllerMap.find (param_mapping);
if (m == controllerMap.end ()) if (m != controllerMap.end ())
continue; {
parmap.controllerId = m->second; parmap.controllerId = m->second;
parmap.is_switch = (param_type == "switch"); }
pm.parameters[index] = std::move (parmap);
pluginMappingMap[pm.id] = pm;
} }
else{
pm.configured = false;
parmap.controllerId = CONTROLLER_NONE;
}
pm.parameters[index] = std::move (parmap);
} }
pluginMappingMap[pm.id] = pm;
return true; return true;
} }
@ -182,6 +193,44 @@ Console1::create_mapping (const std::shared_ptr<Processor> proc, const std::shar
tree->write (); tree->write ();
} }
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 ("Plugin parameter %1: %2\n",plugin_param.first ,plugin_param.second.name));
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);
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 bool
Console1::select_plugin (const int32_t plugin_index) Console1::select_plugin (const int32_t plugin_index)
{ {
@ -444,4 +493,16 @@ Console1::spill_plugins (const int32_t plugin_index)
return true; return true;
} }
Glib::RefPtr<Gtk::ListStore> Console1::getPluginControllerModel()
{
plugin_controller_model = Gtk::ListStore::create (plugin_controller_columns);
Gtk::TreeModel::Row plugin_controller_combo_row;
for( const auto &controller : controllerMap ){
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;
}
} }

View file

@ -181,7 +181,7 @@ Console1::begin_using_device ()
f0 7d 20 00 00 00 01 00 7f 49 6f 6c 73 00 f7 f0 7d 20 00 00 00 01 00 7f 49 6f 6c 73 00 f7
*/ */
load_mappings (); load_mappings ();
setup_controls (); setup_controls ();
/* Connection to the blink-timer */ /* Connection to the blink-timer */
@ -532,7 +532,7 @@ Console1::notify_transport_state_changed ()
void void
Console1::stripable_selection_changed () Console1::stripable_selection_changed ()
{ {
DEBUG_TRACE (DEBUG::Console1, "stripable_selection_changed \n"); DEBUG_TRACE (DEBUG::Console1, "stripable_selection_changed \n");
if (!_in_use) if (!_in_use)
return; return;
@ -1261,3 +1261,12 @@ Console1::master_monitor_has_changed ()
DEBUG_TRACE (DEBUG::Console1, string_compose ("master_monitor_has_changed - monitor active %1\n", monitor_active)); DEBUG_TRACE (DEBUG::Console1, string_compose ("master_monitor_has_changed - monitor active %1\n", monitor_active));
create_strip_inventory (); create_strip_inventory ();
} }
const std::string Console1::findControllerNameById (const ControllerID id){
for( const auto &controller : controllerMap ){
if( controller.second == id ){
return controller.first;
}
}
return std::string();
}

View file

@ -23,6 +23,11 @@
#include <map> #include <map>
#include <set> #include <set>
#include <gtkmm/treemodel.h>
#include <gtkmm/liststore.h>
#include <glibmm/threads.h>
#define ABSTRACT_UI_EXPORTS #define ABSTRACT_UI_EXPORTS
#include "pbd/abstract_ui.h" #include "pbd/abstract_ui.h"
@ -109,6 +114,7 @@ public:
std::string input_port_name () const override; std::string input_port_name () const override;
std::string output_port_name () const override; std::string output_port_name () const override;
uint32_t load_mappings ();
XMLNode& get_state () const override; XMLNode& get_state () const override;
int set_state (const XMLNode&, int version) override; int set_state (const XMLNode&, int version) override;
@ -293,12 +299,27 @@ public:
{ "TRACK_COPY", ControllerID::TRACK_COPY }, { "TRACK_COPY", ControllerID::TRACK_COPY },
{ "TRACK_GROUP", ControllerID::TRACK_GROUP } }; { "TRACK_GROUP", ControllerID::TRACK_GROUP } };
private: struct PluginControllerColumns : public Gtk::TreeModel::ColumnRecord {
PluginControllerColumns () {
add (controllerName);
add (controllerId);
}
Gtk::TreeModelColumn<std::string> controllerName;
Gtk::TreeModelColumn<int> controllerId;
};
PluginControllerColumns plugin_controller_columns;
Glib::RefPtr<Gtk::ListStore> plugin_controller_model;
const std::string findControllerNameById (const ControllerID id);
private:
std::string config_dir_name = "c1mappings"; std::string config_dir_name = "c1mappings";
/* GUI */ /* GUI */
mutable C1GUI* gui; mutable C1GUI* gui;
void build_gui (); void build_gui ();
bool mappings_loaded = false;
bool controls_model_loaded = false;
/* Configuration */ /* Configuration */
const uint32_t bank_size = 20; const uint32_t bank_size = 20;
@ -630,16 +651,8 @@ private:
using ParameterMap = std::map<uint32_t, PluginParameterMapping>; using ParameterMap = std::map<uint32_t, PluginParameterMapping>;
struct PluginMapping
{
std::string id;
std::string name;
ParameterMap parameters;
};
/* plugin handling */ /* plugin handling */
bool ensure_config_dir (); bool ensure_config_dir ();
uint32_t load_mappings ();
bool load_mapping (XMLNode* fin); bool load_mapping (XMLNode* fin);
void create_mapping (const std::shared_ptr<ARDOUR::Processor> proc, const std::shared_ptr<ARDOUR::Plugin> plugin); void create_mapping (const std::shared_ptr<ARDOUR::Processor> proc, const std::shared_ptr<ARDOUR::Plugin> plugin);
@ -654,8 +667,21 @@ private:
void eqBandQChangeMapping (bool mapValues); void eqBandQChangeMapping (bool mapValues);
using PluginMappingMap = std::map<std::string, PluginMapping>;
public:
struct PluginMapping
{
std::string id;
std::string name;
bool configured;
ParameterMap parameters;
};
using PluginMappingMap = std::map<std::string, PluginMapping>;
PluginMappingMap pluginMappingMap; PluginMappingMap pluginMappingMap;
PluginMappingMap getPluginMappingMap () { return pluginMappingMap; }
Glib::RefPtr<Gtk::ListStore> getPluginControllerModel();
void write_plugin_mapping (PluginMapping &mapping);
}; };
} }
#endif /* ardour_surface_console1_h */ #endif /* ardour_surface_console1_h */