13
0
livetrax/libs/surfaces/mackie/gui.cc
Todd Naugle 8cf7204917 Mackie Control: Use selected device's info when building the Keys dialog
The device info file allows key names and values to be configured in each
device file. Use that information when building the Functions Keys tab in
the Mackie protocol setup dialog.
2021-08-06 12:18:24 -05:00

846 lines
27 KiB
C++

/*
* Copyright (C) 2006-2007 John Anderson
* Copyright (C) 2011 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2012-2019 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2014-2015 Robin Gareus <robin@gareus.org>
* Copyright (C) 2015-2017 Len Ovens <len@ovenwerks.net>
*
* 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 <gtkmm/comboboxtext.h>
#include <gtkmm/box.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/table.h>
#include <gtkmm/treeview.h>
#include <gtkmm/liststore.h>
#include <gtkmm/treestore.h>
#include <gtkmm/notebook.h>
#include <gtkmm/cellrenderercombo.h>
#include <gtkmm/scale.h>
#include <gtkmm/alignment.h>
#include "pbd/error.h"
#include "pbd/unwind.h"
#include "pbd/strsplit.h"
#include "gtkmm2ext/actions.h"
#include "gtkmm2ext/action_model.h"
#include "gtkmm2ext/bindings.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h"
#include "ardour/audioengine.h"
#include "ardour/port.h"
#include "ardour/rc_configuration.h"
#include "mackie_control_protocol.h"
#include "device_info.h"
#include "gui.h"
#include "surface.h"
#include "surface_port.h"
#include "pbd/i18n.h"
using namespace std;
using namespace Gtk;
using namespace ArdourSurface;
using namespace Mackie;
void*
MackieControlProtocol::get_gui () const
{
if (!_gui) {
const_cast<MackieControlProtocol*>(this)->build_gui ();
}
static_cast<Gtk::Notebook*>(_gui)->show_all();
return _gui;
}
void
MackieControlProtocol::tear_down_gui ()
{
if (_gui) {
Gtk::Widget *w = static_cast<Gtk::Widget*>(_gui)->get_parent();
if (w) {
w->hide();
delete w;
}
}
delete (MackieControlProtocolGUI*) _gui;
_gui = 0;
}
void
MackieControlProtocol::build_gui ()
{
_gui = (void *) new MackieControlProtocolGUI (*this);
}
MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
: _cp (p)
, table (2, 9)
, action_model (ActionManager::ActionModel::instance ())
, touch_sensitivity_adjustment (0, 0, 9, 1, 4)
, touch_sensitivity_scale (touch_sensitivity_adjustment)
, recalibrate_fader_button (_("Recalibrate Faders"))
, ipmidi_base_port_adjustment (_cp.ipmidi_base(), 0, 32767, 1, 1000)
, discover_button (_("Discover Mackie Devices"))
, _device_dependent_widget (0)
, _ignore_profile_changed (false)
, ignore_active_change (false)
{
Gtk::Label* l;
Gtk::Alignment* align;
int row = 0;
set_border_width (12);
table.set_row_spacings (4);
table.set_col_spacings (6);
table.set_border_width (12);
table.set_homogeneous (false);
l = manage (new Gtk::Label (_("Device Type:")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
table.attach (_surface_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
vector<string> surfaces;
for (std::map<std::string,DeviceInfo>::iterator i = DeviceInfo::device_info.begin(); i != DeviceInfo::device_info.end(); ++i) {
surfaces.push_back (i->first);
}
Gtkmm2ext::set_popdown_strings (_surface_combo, surfaces);
_surface_combo.signal_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::surface_combo_changed));
_cp.DeviceChanged.connect (device_change_connection, invalidator (*this), boost::bind (&MackieControlProtocolGUI::device_changed, this), gui_context());
/* catch future changes to connection state */
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (_port_connections, invalidator (*this), boost::bind (&MackieControlProtocolGUI::connection_handler, this), gui_context());
ARDOUR::AudioEngine::instance()->PortPrettyNameChanged.connect (_port_connections, invalidator (*this), boost::bind (&MackieControlProtocolGUI::connection_handler, this), gui_context());
_cp.ConnectionChange.connect (_port_connections, invalidator (*this), boost::bind (&MackieControlProtocolGUI::connection_handler, this), gui_context());
ipmidi_base_port_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::ipmidi_spinner_changed));
/* device-dependent part */
device_dependent_row = row;
if (_device_dependent_widget) {
table.remove (*_device_dependent_widget);
_device_dependent_widget = 0;
}
_device_dependent_widget = device_dependent_widget ();
table.attach (*_device_dependent_widget, 0, 12, row, row+1, AttachOptions(0), AttachOptions(0), 0, 0);
row++;
/* back to the boilerplate */
RadioButtonGroup rb_group = absolute_touch_mode_button.get_group();
touch_move_mode_button.set_group (rb_group);
recalibrate_fader_button.signal_clicked().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::recalibrate_faders));
backlight_button.signal_clicked().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::toggle_backlight));
touch_sensitivity_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::touch_sensitive_change));
touch_sensitivity_scale.set_update_policy (Gtk::UPDATE_DISCONTINUOUS);
l = manage (new Gtk::Label (_("Button click")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align = manage (new Alignment);
align->set (0.0, 0.5);
align->add (relay_click_button);
table.attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
l = manage (new Gtk::Label (_("Backlight")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align = manage (new Alignment);
align->set (0.0, 0.5);
align->add (backlight_button);
table.attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
l = manage (new Gtk::Label (_("Send Fader Position Only When Touched")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align = manage (new Alignment);
align->set (0.0, 0.5);
align->add (absolute_touch_mode_button);
table.attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
l = manage (new Gtk::Label (_("Send Fader Position When Moved")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align = manage (new Alignment);
align->set (0.0, 0.5);
align->add (touch_move_mode_button);
table.attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
l = manage (new Gtk::Label (_("Fader Touch Sense Sensitivity")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
touch_sensitivity_scale.property_digits() = 0;
touch_sensitivity_scale.property_draw_value() = false;
table.attach (touch_sensitivity_scale, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
table.attach (recalibrate_fader_button, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
table.attach (discover_button, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
discover_button.signal_clicked().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::discover_clicked));
row++;
vector<string> profiles;
for (std::map<std::string,DeviceProfile>::iterator i = DeviceProfile::device_profiles.begin(); i != DeviceProfile::device_profiles.end(); ++i) {
cerr << "add discovered profile " << i->first << endl;
profiles.push_back (i->first);
}
Gtkmm2ext::set_popdown_strings (_profile_combo, profiles);
cerr << "set active profile from " << p.device_profile().name() << endl;
_profile_combo.set_active_text (p.device_profile().name());
_profile_combo.signal_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::profile_combo_changed));
append_page (table, _("Device Setup"));
table.show_all();
/* function key editor */
VBox* fkey_packer = manage (new VBox);
HBox* profile_packer = manage (new HBox);
HBox* observation_packer = manage (new HBox);
l = manage (new Gtk::Label (_("Profile/Settings:")));
profile_packer->pack_start (*l, false, false);
profile_packer->pack_start (_profile_combo, true, true);
profile_packer->set_spacing (12);
profile_packer->set_border_width (12);
l = manage (new Gtk::Label (_("* Button available at the original Mackie MCU PRO or current device if enabled (NOT implemented yet). Device specific name presented.")));
observation_packer->pack_start (*l, false, false);
fkey_packer->pack_start (*profile_packer, false, false);
fkey_packer->pack_start (function_key_scroller, true, true);
fkey_packer->pack_start (*observation_packer, false, false);
fkey_packer->set_spacing (12);
function_key_scroller.property_shadow_type() = Gtk::SHADOW_NONE;
function_key_scroller.add (function_key_editor);
append_page (*fkey_packer, _("Function Keys"));
build_function_key_editor ();
refresh_function_key_editor ();
fkey_packer->show_all();
}
void
MackieControlProtocolGUI::connection_handler ()
{
/* ignore all changes to combobox active strings here, because we're
updating them to match a new ("external") reality - we were called
because port connections have changed.
*/
PBD::Unwinder<bool> ici (ignore_active_change, true);
vector<Gtk::ComboBox*>::iterator ic;
vector<Gtk::ComboBox*>::iterator oc;
vector<string> midi_inputs;
vector<string> midi_outputs;
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsTerminal), midi_inputs);
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsTerminal), midi_outputs);
for (ic = input_combos.begin(), oc = output_combos.begin(); ic != input_combos.end() && oc != output_combos.end(); ++ic, ++oc) {
boost::shared_ptr<Surface> surface = _cp.get_surface_by_raw_pointer ((*ic)->get_data ("surface"));
if (surface) {
update_port_combos (midi_inputs, midi_outputs, *ic, *oc, surface);
}
}
}
void
MackieControlProtocolGUI::update_port_combos (vector<string> const& midi_inputs, vector<string> const& midi_outputs,
Gtk::ComboBox* input_combo,
Gtk::ComboBox* output_combo,
boost::shared_ptr<Surface> surface)
{
Glib::RefPtr<Gtk::ListStore> input = build_midi_port_list (midi_inputs, true);
Glib::RefPtr<Gtk::ListStore> output = build_midi_port_list (midi_outputs, false);
bool input_found = false;
bool output_found = false;
int n;
input_combo->set_model (input);
output_combo->set_model (output);
Gtk::TreeModel::Children children = input->children();
Gtk::TreeModel::Children::iterator i;
i = children.begin();
++i; /* skip "Disconnected" */
for (n = 1; i != children.end(); ++i, ++n) {
string port_name = (*i)[midi_port_columns.full_name];
if (surface->port().input().connected_to (port_name)) {
input_combo->set_active (n);
input_found = true;
break;
}
}
if (!input_found) {
input_combo->set_active (0); /* disconnected */
}
children = output->children();
i = children.begin();
++i; /* skip "Disconnected" */
for (n = 1; i != children.end(); ++i, ++n) {
string port_name = (*i)[midi_port_columns.full_name];
if (surface->port().output().connected_to (port_name)) {
output_combo->set_active (n);
output_found = true;
break;
}
}
if (!output_found) {
output_combo->set_active (0); /* disconnected */
}
}
Gtk::Widget*
MackieControlProtocolGUI::device_dependent_widget ()
{
Gtk::Table* dd_table;
Gtk::Label* l;
int row = 0;
uint32_t n_surfaces = 1 + _cp.device_info().extenders();
uint32_t main_pos = _cp.device_info().master_position();
if (!_cp.device_info().uses_ipmidi()) {
dd_table = Gtk::manage (new Gtk::Table (n_surfaces, 2));
} else {
dd_table = Gtk::manage (new Gtk::Table (1, 2));
}
dd_table = Gtk::manage (new Gtk::Table (2, n_surfaces));
dd_table->set_row_spacings (4);
dd_table->set_col_spacings (6);
dd_table->set_border_width (12);
_surface_combo.set_active_text (_cp.device_info().name());
vector<string> midi_inputs;
vector<string> midi_outputs;
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsPhysical), midi_inputs);
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsPhysical), midi_outputs);
input_combos.clear ();
output_combos.clear ();
if (!_cp.device_info().uses_ipmidi()) {
for (uint32_t n = 0; n < n_surfaces; ++n) {
boost::shared_ptr<Surface> surface = _cp.nth_surface (n);
if (!surface) {
PBD::fatal << string_compose (_("programming error: %1\n"), string_compose ("n=%1 surface not found!", n)) << endmsg;
abort (); /*NOTREACHED*/
}
Gtk::ComboBox* input_combo = manage (new Gtk::ComboBox);
Gtk::ComboBox* output_combo = manage (new Gtk::ComboBox);
update_port_combos (midi_inputs, midi_outputs, input_combo, output_combo, surface);
input_combo->pack_start (midi_port_columns.short_name);
input_combo->set_data ("surface", surface.get());
input_combos.push_back (input_combo);
output_combo->pack_start (midi_port_columns.short_name);
output_combo->set_data ("surface", surface.get());
output_combos.push_back (output_combo);
boost::weak_ptr<Surface> ws (surface);
input_combo->signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &MackieControlProtocolGUI::active_port_changed), input_combo, ws, true));
output_combo->signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &MackieControlProtocolGUI::active_port_changed), output_combo, ws, false));
string send_string;
string receive_string;
if (n_surfaces > 1) {
if (n == main_pos) {
send_string = string_compose(_("Main surface at position %1 sends via:"), n + 1);
receive_string = string_compose(_("Main surface at position %1 receives via:"), n + 1);
} else {
send_string = string_compose (_("Extender at position %1 sends via:"), n + 1);
receive_string = string_compose (_("Extender at position %1 receives via:"), n + 1);
}
} else {
send_string = _("Surface sends via:");
receive_string = _("Surface receives via:");
}
l = manage (new Gtk::Label (send_string));
l->set_alignment (1.0, 0.5);
dd_table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
dd_table->attach (*input_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
l = manage (new Gtk::Label (receive_string));
l->set_alignment (1.0, 0.5);
dd_table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
dd_table->attach (*output_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
}
} else {
l = manage (new Gtk::Label (_("ipMIDI Port (lowest)")));
l->set_alignment (1.0, 0.5);
Gtk::SpinButton* ipmidi_base_port_spinner = manage (new Gtk::SpinButton (ipmidi_base_port_adjustment));
dd_table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
dd_table->attach (*ipmidi_base_port_spinner, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
}
return dd_table;
}
CellRendererCombo*
MackieControlProtocolGUI::make_action_renderer (Glib::RefPtr<TreeStore> 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::bind (sigc::mem_fun(*this, &MackieControlProtocolGUI::action_changed), column));
return renderer;
}
void
MackieControlProtocolGUI::build_function_key_editor ()
{
function_key_editor.append_column (_("Key"), function_key_columns.name);
TreeViewColumn* col;
CellRendererCombo* renderer;
renderer = make_action_renderer (action_model.model(), function_key_columns.plain);
col = manage (new TreeViewColumn (_("Plain"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.plain);
function_key_editor.append_column (*col);
renderer = make_action_renderer (action_model.model(), function_key_columns.shift);
col = manage (new TreeViewColumn (_("Shift"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.shift);
function_key_editor.append_column (*col);
renderer = make_action_renderer (action_model.model(), function_key_columns.control);
col = manage (new TreeViewColumn (_("Control"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.control);
function_key_editor.append_column (*col);
renderer = make_action_renderer (action_model.model(), function_key_columns.option);
col = manage (new TreeViewColumn (_("Option"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.option);
function_key_editor.append_column (*col);
renderer = make_action_renderer (action_model.model(), function_key_columns.cmdalt);
col = manage (new TreeViewColumn (_("Cmd/Alt"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.cmdalt);
function_key_editor.append_column (*col);
renderer = make_action_renderer (action_model.model(), function_key_columns.shiftcontrol);
col = manage (new TreeViewColumn (_("Shift+Control"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.shiftcontrol);
function_key_editor.append_column (*col);
function_key_model = ListStore::create (function_key_columns);
function_key_editor.set_model (function_key_model);
}
void
MackieControlProtocolGUI::refresh_function_key_editor ()
{
function_key_editor.set_model (Glib::RefPtr<TreeModel>());
function_key_model->clear ();
/* now fill with data */
TreeModel::Row row;
DeviceProfile dp (_cp.device_profile());
DeviceInfo di (_cp.device_info());
for (int n = 0; n < Mackie::Button::FinalGlobalButton; ++n) {
Mackie::Button::ID bid = (Mackie::Button::ID) n;
row = *(function_key_model->append());
if (di.global_buttons().find (bid) == di.global_buttons().end()) {
row[function_key_columns.name] = Mackie::Button::id_to_name (bid);
} else {
row[function_key_columns.name] = di.get_global_button_name (bid) + "*";
}
row[function_key_columns.id] = bid;
Glib::RefPtr<Gtk::Action> act;
string action;
const string defstring = "\u2022";
/* We only allow plain bindings for Fn keys. All others are
* reserved for hard-coded actions.
*/
if (bid >= Mackie::Button::F1 && bid <= Mackie::Button::F8) {
action = dp.get_button_action (bid, 0);
if (action.empty()) {
row[function_key_columns.plain] = defstring;
} else {
if (action.find ('/') == string::npos) {
/* Probably a key alias */
row[function_key_columns.plain] = action;
} else {
act = ActionManager::get_action (action, false);
if (act) {
row[function_key_columns.plain] = act->get_label();
} else {
row[function_key_columns.plain] = defstring;
}
}
}
}
/* We only allow plain bindings for Fn keys. All others are
* reserved for hard-coded actions.
*/
if (bid >= Mackie::Button::F1 && bid <= Mackie::Button::F8) {
action = dp.get_button_action (bid, MackieControlProtocol::MODIFIER_SHIFT);
if (action.empty()) {
row[function_key_columns.shift] = defstring;
} else {
if (action.find ('/') == string::npos) {
/* Probably a key alias */
row[function_key_columns.shift] = action;
} else {
act = ActionManager::get_action (action, false);
if (act) {
row[function_key_columns.shift] = act->get_label();
} else {
row[function_key_columns.shift] = defstring;
}
}
}
}
action = dp.get_button_action (bid, MackieControlProtocol::MODIFIER_CONTROL);
if (action.empty()) {
row[function_key_columns.control] = defstring;
} else {
if (action.find ('/') == string::npos) {
/* Probably a key alias */
row[function_key_columns.control] = action;
} else {
act = ActionManager::get_action (action, false);
if (act) {
row[function_key_columns.control] = act->get_label();
} else {
row[function_key_columns.control] = defstring;
}
}
}
action = dp.get_button_action (bid, MackieControlProtocol::MODIFIER_OPTION);
if (action.empty()) {
row[function_key_columns.option] = defstring;
} else {
if (action.find ('/') == string::npos) {
/* Probably a key alias */
row[function_key_columns.option] = action;
} else {
act = ActionManager::get_action (action, false);
if (act) {
row[function_key_columns.option] = act->get_label();
} else {
row[function_key_columns.option] = defstring;
}
}
}
action = dp.get_button_action (bid, MackieControlProtocol::MODIFIER_CMDALT);
if (action.empty()) {
row[function_key_columns.cmdalt] = defstring;
} else {
if (action.find ('/') == string::npos) {
/* Probably a key alias */
row[function_key_columns.cmdalt] = action;
} else {
act = ActionManager::get_action (action, false);
if (act) {
row[function_key_columns.cmdalt] = act->get_label();
} else {
row[function_key_columns.cmdalt] = defstring;
}
}
}
action = dp.get_button_action (bid, (MackieControlProtocol::MODIFIER_SHIFT|MackieControlProtocol::MODIFIER_CONTROL));
if (action.empty()) {
row[function_key_columns.shiftcontrol] = defstring;
} else {
act = ActionManager::get_action (action, false);
if (act) {
row[function_key_columns.shiftcontrol] = act->get_label();
} else {
row[function_key_columns.shiftcontrol] = defstring;
}
}
}
function_key_editor.set_model (function_key_model);
}
void
MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const TreeModel::iterator & iter, TreeModelColumnBase col)
{
string action_path = (*iter)[action_model.columns().path];
// Remove Binding is not in the action map but still valid
bool remove = false;
if (action_path == "Remove Binding") {
remove = true;
}
Gtk::TreePath path(sPath);
Gtk::TreeModel::iterator row = function_key_model->get_iter(path);
if (row) {
Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (action_path, false);
if (!act) {
cerr << action_path << " not found in action map\n";
if (!remove) {
return;
}
}
if (act || remove) {
/* update visible text, using string supplied by
available action model so that it matches and is found
within the model.
*/
if (remove) {
Glib::ustring dot = "\u2022";
(*row).set_value (col.index(), dot);
} else {
(*row).set_value (col.index(), act->get_label());
}
/* update the current DeviceProfile, using the full
* path
*/
int modifier;
switch (col.index()) {
case 3:
modifier = MackieControlProtocol::MODIFIER_SHIFT;
break;
case 4:
modifier = MackieControlProtocol::MODIFIER_CONTROL;
break;
case 5:
modifier = MackieControlProtocol::MODIFIER_OPTION;
break;
case 6:
modifier = MackieControlProtocol::MODIFIER_CMDALT;
break;
case 7:
modifier = (MackieControlProtocol::MODIFIER_SHIFT|MackieControlProtocol::MODIFIER_CONTROL);
break;
default:
modifier = 0;
}
if (remove) {
_cp.device_profile().set_button_action ((*row)[function_key_columns.id], modifier, "");
} else {
_cp.device_profile().set_button_action ((*row)[function_key_columns.id], modifier, action_path);
}
_ignore_profile_changed = true;
_profile_combo.set_active_text ( _cp.device_profile().name() );
_ignore_profile_changed = false;
} else {
std::cerr << "no such action\n";
}
}
}
void
MackieControlProtocolGUI::surface_combo_changed ()
{
_cp.set_device (_surface_combo.get_active_text(), false);
}
void
MackieControlProtocolGUI::device_changed ()
{
if (_device_dependent_widget) {
table.remove (*_device_dependent_widget);
_device_dependent_widget = 0;
}
_device_dependent_widget = device_dependent_widget ();
_device_dependent_widget->show_all ();
table.attach (*_device_dependent_widget, 0, 12, device_dependent_row, device_dependent_row+1, AttachOptions(0), AttachOptions(0), 0, 0);
refresh_function_key_editor ();
}
void
MackieControlProtocolGUI::profile_combo_changed ()
{
if (!_ignore_profile_changed) {
string profile = _profile_combo.get_active_text();
_cp.set_profile (profile);
refresh_function_key_editor ();
}
}
void
MackieControlProtocolGUI::ipmidi_spinner_changed ()
{
_cp.set_ipmidi_base ((int16_t) lrintf (ipmidi_base_port_adjustment.get_value()));
}
void
MackieControlProtocolGUI::discover_clicked ()
{
/* this should help to get things started */
_cp.ping_devices ();
}
void
MackieControlProtocolGUI::recalibrate_faders ()
{
_cp.recalibrate_faders ();
}
void
MackieControlProtocolGUI::toggle_backlight ()
{
_cp.toggle_backlight ();
}
void
MackieControlProtocolGUI::touch_sensitive_change ()
{
int sensitivity = (int) touch_sensitivity_adjustment.get_value ();
_cp.set_touch_sensitivity (sensitivity);
}
Glib::RefPtr<Gtk::ListStore>
MackieControlProtocolGUI::build_midi_port_list (vector<string> const & ports, bool for_input)
{
Glib::RefPtr<Gtk::ListStore> store = ListStore::create (midi_port_columns);
TreeModel::Row row;
row = *store->append ();
row[midi_port_columns.full_name] = string();
row[midi_port_columns.short_name] = _("Disconnected");
for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
row = *store->append ();
row[midi_port_columns.full_name] = *p;
std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
if (pn.empty ()) {
pn = (*p).substr ((*p).find (':') + 1);
}
row[midi_port_columns.short_name] = pn;
}
return store;
}
void
MackieControlProtocolGUI::active_port_changed (Gtk::ComboBox* combo, boost::weak_ptr<Surface> ws, bool for_input)
{
if (ignore_active_change) {
return;
}
boost::shared_ptr<Surface> surface = ws.lock();
if (!surface) {
return;
}
TreeModel::iterator active = combo->get_active ();
string new_port = (*active)[midi_port_columns.full_name];
if (new_port.empty()) {
if (for_input) {
surface->port().input().disconnect_all ();
} else {
surface->port().output().disconnect_all ();
}
return;
}
if (for_input) {
if (!surface->port().input().connected_to (new_port)) {
surface->port().input().disconnect_all ();
surface->port().input().connect (new_port);
}
} else {
if (!surface->port().output().connected_to (new_port)) {
surface->port().output().disconnect_all ();
surface->port().output().connect (new_port);
}
}
}