From b9ff443085b0513d95c867cce81595b9509b2dff Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 17 Apr 2012 20:41:31 +0000 Subject: [PATCH] MCP: various work on the button binding GUI git-svn-id: svn://localhost/ardour2/branches/3.0@11997 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardev_common.sh.in | 2 +- libs/ardour/ardour/rc_configuration_vars.h | 1 + libs/gtkmm2ext/actions.cc | 44 ++- libs/gtkmm2ext/gtkmm2ext/actions.h | 1 + libs/surfaces/mackie/button.cc | 289 +++++++++++----- libs/surfaces/mackie/button.h | 5 +- libs/surfaces/mackie/device_info.cc | 8 +- libs/surfaces/mackie/device_info.h | 21 -- libs/surfaces/mackie/device_profile.cc | 323 ++++++++++++++++++ libs/surfaces/mackie/device_profile.h | 68 ++++ libs/surfaces/mackie/gui.cc | 159 +++++++-- libs/surfaces/mackie/gui.h | 52 +-- .../mackie/mackie_control_protocol.cc | 37 ++ .../surfaces/mackie/mackie_control_protocol.h | 4 + libs/surfaces/mackie/strip.cc | 5 +- libs/surfaces/mackie/surface.cc | 2 + libs/surfaces/mackie/wscript | 1 + mcp_devices/mcpro.xml => mcp/mcpro.device | 0 mcp_devices/mcproxt.xml => mcp/mcproxt.device | 0 mcp_devices/nucleus.xml => mcp/nucleus.device | 0 20 files changed, 857 insertions(+), 165 deletions(-) create mode 100644 libs/surfaces/mackie/device_profile.cc create mode 100644 libs/surfaces/mackie/device_profile.h rename mcp_devices/mcpro.xml => mcp/mcpro.device (100%) rename mcp_devices/mcproxt.xml => mcp/mcproxt.device (100%) rename mcp_devices/nucleus.xml => mcp/nucleus.device (100%) diff --git a/gtk2_ardour/ardev_common.sh.in b/gtk2_ardour/ardev_common.sh.in index 897e7168df..58e6c4e0ba 100644 --- a/gtk2_ardour/ardev_common.sh.in +++ b/gtk2_ardour/ardev_common.sh.in @@ -8,7 +8,7 @@ export ARDOUR_PATH=$TOP/gtk2_ardour/icons:$TOP/gtk2_ardour/pixmaps:$TOP/build/gt export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie export ARDOUR_PANNER_PATH=$libs/panners/2in2out:$libs/panners/1in2out:$libs/panners/vbap export ARDOUR_DATA_PATH=$TOP/gtk2_ardour:build/gtk2_ardour:. -export ARDOUR_MCP_DEVINFO_PATH=$TOP/mcp_devices:. +export ARDOUR_MCP_PATH=$TOP/mcp:. if test -d $HOME/gtk/inst ; then export GTK_PATH=~/.ardour3:$libs/clearlooks-newer diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h index fd92f57d1b..cd093d1d80 100644 --- a/libs/ardour/ardour/rc_configuration_vars.h +++ b/libs/ardour/ardour/rc_configuration_vars.h @@ -51,6 +51,7 @@ CONFIG_VARIABLE (bool, first_midi_bank_is_zero, "diplay-first-midi-bank-as-zero" CONFIG_VARIABLE (uint32_t, feedback_interval_ms, "feedback-interval-ms", 100) CONFIG_VARIABLE (bool, use_tranzport, "use-tranzport", false) CONFIG_VARIABLE (std::string, mackie_device_name, "mackie-device-name", "Mackie Control Universal Pro") +CONFIG_VARIABLE (std::string, mackie_device_profile, "mackie-device-profile", "default") CONFIG_VARIABLE (RemoteModel, remote_model, "remote-model", MixerOrdered) /* disk operations */ diff --git a/libs/gtkmm2ext/actions.cc b/libs/gtkmm2ext/actions.cc index 774991038e..3fc9def399 100644 --- a/libs/gtkmm2ext/actions.cc +++ b/libs/gtkmm2ext/actions.cc @@ -246,9 +246,23 @@ ActionManager::get_widget (const char * name) RefPtr ActionManager::get_action (const char* path) { + if (!path) { + return RefPtr(); + } + char copy[strlen(path)+1]; - strcpy (copy, path); - char *slash = strchr (copy, '/'); + + if (*path == '/') { + const char* cslash = strchr (path, '/'); + if (!cslash) { + return RefPtr (); + } + strcpy (copy, cslash+1); + } else { + strcpy (copy, path); + } + + char* slash = strchr (copy, '/'); if (!slash) { return RefPtr (); } @@ -290,6 +304,32 @@ ActionManager::get_action (const char* group_name, const char* action_name) return act; } +RefPtr +ActionManager::get_action_from_name (const char* name) +{ + /* the C++ API for functions used here appears to be broken in + gtkmm2.6, so we fall back to the C level. + */ + + GList* list = gtk_ui_manager_get_action_groups (ui_manager->gobj()); + GList* node; + GList* acts; + + for (node = list; node; node = g_list_next (node)) { + + GtkActionGroup* group = (GtkActionGroup*) node->data; + + for (acts = gtk_action_group_list_actions (group); acts; acts = g_list_next (acts)) { + GtkAction* action = (GtkAction*) acts->data; + if (!strcmp (gtk_action_get_name (action), name)) { + return Glib::wrap (action, true); + } + } + } + + return RefPtr(); +} + void ActionManager::set_sensitive (vector >& actions, bool state) { diff --git a/libs/gtkmm2ext/gtkmm2ext/actions.h b/libs/gtkmm2ext/gtkmm2ext/actions.h index 0c53e9c10d..e35ee1f442 100644 --- a/libs/gtkmm2ext/gtkmm2ext/actions.h +++ b/libs/gtkmm2ext/gtkmm2ext/actions.h @@ -43,6 +43,7 @@ namespace ActionManager { extern Gtk::Widget* get_widget (const char * name); extern Glib::RefPtr get_action (const char* group, const char* name); extern Glib::RefPtr get_action (const char* path); + extern Glib::RefPtr get_action_from_name (const char* name); extern void do_action (const char* group, const char* name); extern void set_toggle_action (const char* group, const char* name, bool); diff --git a/libs/surfaces/mackie/button.cc b/libs/surfaces/mackie/button.cc index 33521c2a87..11fc391930 100644 --- a/libs/surfaces/mackie/button.cc +++ b/libs/surfaces/mackie/button.cc @@ -17,6 +17,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include "button.h" #include "surface.h" #include "control_group.h" @@ -37,102 +39,203 @@ Button::factory (Surface& surface, Button::ID bid, int id, const std::string& na int Button::name_to_id (const std::string& name) { - if (name == "IO") { return IO; } - if (name == "Sends") { return Sends; } - if (name == "Pan") { return Pan; } - if (name == "Plugin") { return Plugin; } - if (name == "Eq") { return Eq; } - if (name == "Dyn") { return Dyn; } - if (name == "Left") { return Left; } - if (name == "Right") { return Right; } - if (name == "ChannelLeft") { return ChannelLeft; } - if (name == "ChannelRight") { return ChannelRight; } - if (name == "Flip") { return Flip; } - if (name == "Edit") { return Edit; } - if (name == "NameValue") { return NameValue; } - if (name == "TimecodeBeats") { return TimecodeBeats; } - if (name == "F1") { return F1; } - if (name == "F2") { return F2; } - if (name == "F3") { return F3; } - if (name == "F4") { return F4; } - if (name == "F5") { return F5; } - if (name == "F6") { return F6; } - if (name == "F7") { return F7; } - if (name == "F8") { return F8; } - if (name == "F9") { return F9; } - if (name == "F10") { return F10; } - if (name == "F11") { return F11; } - if (name == "F12") { return F12; } - if (name == "F13") { return F13; } - if (name == "F14") { return F14; } - if (name == "F15") { return F15; } - if (name == "F16") { return F16; } - if (name == "Shift") { return Shift; } - if (name == "Option") { return Option; } - if (name == "Ctrl") { return Ctrl; } - if (name == "CmdAlt") { return CmdAlt; } - if (name == "On") { return On; } - if (name == "RecReady") { return RecReady; } - if (name == "Undo") { return Undo; } - if (name == "Save") { return Save; } - if (name == "Touch") { return Touch; } - if (name == "Redo") { return Redo; } - if (name == "Marker") { return Marker; } - if (name == "Enter") { return Enter; } - if (name == "Cancel") { return Cancel; } - if (name == "Mixer") { return Mixer; } - if (name == "FrmLeft") { return FrmLeft; } - if (name == "FrmRight") { return FrmRight; } - if (name == "Loop") { return Loop; } - if (name == "PunchIn") { return PunchIn; } - if (name == "PunchOut") { return PunchOut; } - if (name == "Home") { return Home; } - if (name == "End") { return End; } - if (name == "Rewind") { return Rewind; } - if (name == "Ffwd") { return Ffwd; } - if (name == "Stop") { return Stop; } - if (name == "Play") { return Play; } - if (name == "Record") { return Record; } - if (name == "CursorUp") { return CursorUp; } - if (name == "CursorDown") { return CursorDown; } - if (name == "CursorLeft") { return CursorLeft; } - if (name == "CursorRight") { return CursorRight; } - if (name == "Zoom") { return Zoom; } - if (name == "Scrub") { return Scrub; } - if (name == "UserA") { return UserA; } - if (name == "UserB") { return UserB; } - if (name == "Snapshot") { return Snapshot; } - if (name == "Read") { return Read; } - if (name == "Write") { return Write; } - if (name == "FdrGroup") { return FdrGroup; } - if (name == "ClearSolo") { return ClearSolo; } - if (name == "Track") { return Track; } - if (name == "Send") { return Send; } - if (name == "MidiTracks") { return MidiTracks; } - if (name == "Inputs") { return Inputs; } - if (name == "AudioTracks") { return AudioTracks; } - if (name == "AudioInstruments") { return AudioInstruments; } - if (name == "Aux") { return Aux; } - if (name == "Busses") { return Busses; } - if (name == "Outputs") { return Outputs; } - if (name == "User") { return User; } - if (name == "Trim") { return Trim; } - if (name == "Latch") { return Latch; } - if (name == "Grp") { return Grp; } - if (name == "Nudge") { return Nudge; } - if (name == "Drop") { return Drop; } - if (name == "Replace") { return Replace; } - if (name == "Click") { return Click; } - if (name == "View") { return View; } + if (!g_strcasecmp (name.c_str(), "IO")) { return IO; } + if (!g_strcasecmp (name.c_str(), "Sends")) { return Sends; } + if (!g_strcasecmp (name.c_str(), "Pan")) { return Pan; } + if (!g_strcasecmp (name.c_str(), "Plugin")) { return Plugin; } + if (!g_strcasecmp (name.c_str(), "Eq")) { return Eq; } + if (!g_strcasecmp (name.c_str(), "Dyn")) { return Dyn; } + if (!g_strcasecmp (name.c_str(), "Left")) { return Left; } + if (!g_strcasecmp (name.c_str(), "Right")) { return Right; } + if (!g_strcasecmp (name.c_str(), "ChannelLeft")) { return ChannelLeft; } + if (!g_strcasecmp (name.c_str(), "ChannelRight")) { return ChannelRight; } + if (!g_strcasecmp (name.c_str(), "Flip")) { return Flip; } + if (!g_strcasecmp (name.c_str(), "Edit")) { return Edit; } + if (!g_strcasecmp (name.c_str(), "NameValue")) { return NameValue; } + if (!g_strcasecmp (name.c_str(), "TimecodeBeats")) { return TimecodeBeats; } + if (!g_strcasecmp (name.c_str(), "F1")) { return F1; } + if (!g_strcasecmp (name.c_str(), "F2")) { return F2; } + if (!g_strcasecmp (name.c_str(), "F3")) { return F3; } + if (!g_strcasecmp (name.c_str(), "F4")) { return F4; } + if (!g_strcasecmp (name.c_str(), "F5")) { return F5; } + if (!g_strcasecmp (name.c_str(), "F6")) { return F6; } + if (!g_strcasecmp (name.c_str(), "F7")) { return F7; } + if (!g_strcasecmp (name.c_str(), "F8")) { return F8; } + if (!g_strcasecmp (name.c_str(), "F9")) { return F9; } + if (!g_strcasecmp (name.c_str(), "F10")) { return F10; } + if (!g_strcasecmp (name.c_str(), "F11")) { return F11; } + if (!g_strcasecmp (name.c_str(), "F12")) { return F12; } + if (!g_strcasecmp (name.c_str(), "F13")) { return F13; } + if (!g_strcasecmp (name.c_str(), "F14")) { return F14; } + if (!g_strcasecmp (name.c_str(), "F15")) { return F15; } + if (!g_strcasecmp (name.c_str(), "F16")) { return F16; } + if (!g_strcasecmp (name.c_str(), "Shift")) { return Shift; } + if (!g_strcasecmp (name.c_str(), "Option")) { return Option; } + if (!g_strcasecmp (name.c_str(), "Ctrl")) { return Ctrl; } + if (!g_strcasecmp (name.c_str(), "CmdAlt")) { return CmdAlt; } + if (!g_strcasecmp (name.c_str(), "On")) { return On; } + if (!g_strcasecmp (name.c_str(), "RecReady")) { return RecReady; } + if (!g_strcasecmp (name.c_str(), "Undo")) { return Undo; } + if (!g_strcasecmp (name.c_str(), "Save")) { return Save; } + if (!g_strcasecmp (name.c_str(), "Touch")) { return Touch; } + if (!g_strcasecmp (name.c_str(), "Redo")) { return Redo; } + if (!g_strcasecmp (name.c_str(), "Marker")) { return Marker; } + if (!g_strcasecmp (name.c_str(), "Enter")) { return Enter; } + if (!g_strcasecmp (name.c_str(), "Cancel")) { return Cancel; } + if (!g_strcasecmp (name.c_str(), "Mixer")) { return Mixer; } + if (!g_strcasecmp (name.c_str(), "FrmLeft")) { return FrmLeft; } + if (!g_strcasecmp (name.c_str(), "FrmRight")) { return FrmRight; } + if (!g_strcasecmp (name.c_str(), "Loop")) { return Loop; } + if (!g_strcasecmp (name.c_str(), "PunchIn")) { return PunchIn; } + if (!g_strcasecmp (name.c_str(), "PunchOut")) { return PunchOut; } + if (!g_strcasecmp (name.c_str(), "Home")) { return Home; } + if (!g_strcasecmp (name.c_str(), "End")) { return End; } + if (!g_strcasecmp (name.c_str(), "Rewind")) { return Rewind; } + if (!g_strcasecmp (name.c_str(), "Ffwd")) { return Ffwd; } + if (!g_strcasecmp (name.c_str(), "Stop")) { return Stop; } + if (!g_strcasecmp (name.c_str(), "Play")) { return Play; } + if (!g_strcasecmp (name.c_str(), "Record")) { return Record; } + if (!g_strcasecmp (name.c_str(), "CursorUp")) { return CursorUp; } + if (!g_strcasecmp (name.c_str(), "CursorDown")) { return CursorDown; } + if (!g_strcasecmp (name.c_str(), "CursorLeft")) { return CursorLeft; } + if (!g_strcasecmp (name.c_str(), "CursorRight")) { return CursorRight; } + if (!g_strcasecmp (name.c_str(), "Zoom")) { return Zoom; } + if (!g_strcasecmp (name.c_str(), "Scrub")) { return Scrub; } + if (!g_strcasecmp (name.c_str(), "UserA")) { return UserA; } + if (!g_strcasecmp (name.c_str(), "UserB")) { return UserB; } + if (!g_strcasecmp (name.c_str(), "Snapshot")) { return Snapshot; } + if (!g_strcasecmp (name.c_str(), "Read")) { return Read; } + if (!g_strcasecmp (name.c_str(), "Write")) { return Write; } + if (!g_strcasecmp (name.c_str(), "FdrGroup")) { return FdrGroup; } + if (!g_strcasecmp (name.c_str(), "ClearSolo")) { return ClearSolo; } + if (!g_strcasecmp (name.c_str(), "Track")) { return Track; } + if (!g_strcasecmp (name.c_str(), "Send")) { return Send; } + if (!g_strcasecmp (name.c_str(), "MidiTracks")) { return MidiTracks; } + if (!g_strcasecmp (name.c_str(), "Inputs")) { return Inputs; } + if (!g_strcasecmp (name.c_str(), "AudioTracks")) { return AudioTracks; } + if (!g_strcasecmp (name.c_str(), "AudioInstruments")) { return AudioInstruments; } + if (!g_strcasecmp (name.c_str(), "Aux")) { return Aux; } + if (!g_strcasecmp (name.c_str(), "Busses")) { return Busses; } + if (!g_strcasecmp (name.c_str(), "Outputs")) { return Outputs; } + if (!g_strcasecmp (name.c_str(), "User")) { return User; } + if (!g_strcasecmp (name.c_str(), "Trim")) { return Trim; } + if (!g_strcasecmp (name.c_str(), "Latch")) { return Latch; } + if (!g_strcasecmp (name.c_str(), "Grp")) { return Grp; } + if (!g_strcasecmp (name.c_str(), "Nudge")) { return Nudge; } + if (!g_strcasecmp (name.c_str(), "Drop")) { return Drop; } + if (!g_strcasecmp (name.c_str(), "Replace")) { return Replace; } + if (!g_strcasecmp (name.c_str(), "Click")) { return Click; } + if (!g_strcasecmp (name.c_str(), "View")) { return View; } /* Strip buttons */ - if (name == "RecEnable") { return RecEnable; } - if (name == "Solo") { return Solo; } - if (name == "Mute") { return Mute; } - if (name == "Select") { return Select; } - if (name == "VSelect") { return VSelect; } - if (name == "FaderTouch") { return FaderTouch; } + if (!g_strcasecmp (name.c_str(), "RecEnable")) { return RecEnable; } + if (!g_strcasecmp (name.c_str(), "Solo")) { return Solo; } + if (!g_strcasecmp (name.c_str(), "Mute")) { return Mute; } + if (!g_strcasecmp (name.c_str(), "Select")) { return Select; } + if (!g_strcasecmp (name.c_str(), "VSelect")) { return VSelect; } + if (!g_strcasecmp (name.c_str(), "FaderTouch")) { return FaderTouch; } return -1; } + +std::string +Button::id_to_name (Button::ID id) +{ + if (id == IO) { return "IO"; } + if (id == Sends) { return "Sends"; } + if (id == Pan) { return "Pan"; } + if (id == Plugin) { return "Plugin"; } + if (id == Eq) { return "Eq"; } + if (id == Dyn) { return "Dyn"; } + if (id == Left) { return "Bank Left"; } + if (id == Right) { return "Bank Right"; } + if (id == ChannelLeft) { return "Channel Left"; } + if (id == ChannelRight) { return "Channel Right"; } + if (id == Flip) { return "Flip"; } + if (id == Edit) { return "Edit"; } + if (id == NameValue) { return "Name/Value"; } + if (id == TimecodeBeats) { return "Timecode/Beats"; } + if (id == F1) { return "F1"; } + if (id == F2) { return "F2"; } + if (id == F3) { return "F3"; } + if (id == F4) { return "F4"; } + if (id == F5) { return "F5"; } + if (id == F6) { return "F6"; } + if (id == F7) { return "F7"; } + if (id == F8) { return "F8"; } + if (id == F9) { return "F9"; } + if (id == F10) { return "F10"; } + if (id == F11) { return "F11"; } + if (id == F12) { return "F12"; } + if (id == F13) { return "F13"; } + if (id == F14) { return "F14"; } + if (id == F15) { return "F15"; } + if (id == F16) { return "F16"; } + if (id == Shift) { return "Shift"; } + if (id == Option) { return "Option"; } + if (id == Ctrl) { return "Ctrl"; } + if (id == CmdAlt) { return "CmdAlt"; } + if (id == On) { return "On"; } + if (id == RecReady) { return "Record"; } + if (id == Undo) { return "Undo"; } + if (id == Save) { return "Save"; } + if (id == Touch) { return "Touch"; } + if (id == Redo) { return "Redo"; } + if (id == Marker) { return "Marker"; } + if (id == Enter) { return "Enter"; } + if (id == Cancel) { return "Cancel"; } + if (id == Mixer) { return "Mixer"; } + if (id == FrmLeft) { return "Frm Left"; } + if (id == FrmRight) { return "Frm Right"; } + if (id == Loop) { return "Loop"; } + if (id == PunchIn) { return "Punch In"; } + if (id == PunchOut) { return "Punch Out"; } + if (id == Home) { return "Home"; } + if (id == End) { return "End"; } + if (id == Rewind) { return "Rewind"; } + if (id == Ffwd) { return "FFwd"; } + if (id == Stop) { return "Stop"; } + if (id == Play) { return "Play"; } + if (id == Record) { return "Record"; } + if (id == CursorUp) { return "Cursor Up"; } + if (id == CursorDown) { return "Cursor Down"; } + if (id == CursorLeft) { return "Cursor Left"; } + if (id == CursorRight) { return "Cursor Right"; } + if (id == Zoom) { return "Zoom"; } + if (id == Scrub) { return "Scrub"; } + if (id == UserA) { return "User A"; } + if (id == UserB) { return "User B"; } + if (id == Snapshot) { return "Snapshot"; } + if (id == Read) { return "Read"; } + if (id == Write) { return "Write"; } + if (id == FdrGroup) { return "Fader Group"; } + if (id == ClearSolo) { return "Clear Solo"; } + if (id == Track) { return "Track"; } + if (id == Send) { return "Send"; } + if (id == MidiTracks) { return "Midi Tracks"; } + if (id == Inputs) { return "Inputs"; } + if (id == AudioTracks) { return "Audio Tracks"; } + if (id == AudioInstruments) { return "Audio Instruments"; } + if (id == Aux) { return "Aux"; } + if (id == Busses) { return "Busses"; } + if (id == Outputs) { return "Outputs"; } + if (id == User) { return "User"; } + if (id == Trim) { return "Trim"; } + if (id == Latch) { return "Latch"; } + if (id == Grp) { return "Group"; } + if (id == Nudge) { return "Nudge"; } + if (id == Drop) { return "Drop"; } + if (id == Replace) { return "Replace"; } + if (id == Click) { return "Click"; } + if (id == View) { return "View"; } + + if (id == RecEnable) { return "Record Enable"; } + if (id == Solo) { return "Solo"; } + if (id == Mute) { return "Mute"; } + if (id == Select) { return "Select"; } + if (id == VSelect) { return "V-Pot"; } + if (id == FaderTouch) { return "Fader Touch"; } + + return "???"; +} diff --git a/libs/surfaces/mackie/button.h b/libs/surfaces/mackie/button.h index d6d6fd17e8..b90f4b21a3 100644 --- a/libs/surfaces/mackie/button.h +++ b/libs/surfaces/mackie/button.h @@ -120,12 +120,14 @@ public: Trim, Latch, Grp, - Nudge, + Nudge, Drop, Replace, Click, View, + FinalGlobalButton, + /* Strip buttons */ RecEnable, @@ -149,6 +151,7 @@ public: static Control* factory (Surface& surface, Button::ID bid, int id, const std::string&, Group& group); static int name_to_id (const std::string& name); + static std::string id_to_name (Button::ID); private: ID _bid; /* device independent button ID */ diff --git a/libs/surfaces/mackie/device_info.cc b/libs/surfaces/mackie/device_info.cc index 6e1d0274d3..72512f3139 100644 --- a/libs/surfaces/mackie/device_info.cc +++ b/libs/surfaces/mackie/device_info.cc @@ -182,7 +182,7 @@ DeviceInfo::shared_buttons () _global_buttons[Button::UserA] = GlobalButtonInfo ("user a", "user", 0x66); _global_buttons[Button::UserB] = GlobalButtonInfo ("user b", "user", 0x67); - _strip_buttons[Button::RecEnable], StripButtonInfo (0x0, "recenable"); + _strip_buttons[Button::RecEnable] = StripButtonInfo (0x0, "recenable"); _strip_buttons[Button::Solo] = StripButtonInfo (0x08, "solo"); _strip_buttons[Button::Mute] = StripButtonInfo (0x10, "mute"); _strip_buttons[Button::Select] = StripButtonInfo (0x18, "select"); @@ -387,9 +387,9 @@ DeviceInfo::has_touch_sense_faders () const return _has_touch_sense_faders; } -static const char * const devinfo_env_variable_name = "ARDOUR_MCP_DEVINFO_PATH"; -static const char* const devinfo_dir_name = "mcp_devices"; -static const char* const devinfo_suffix = ".xml"; +static const char * const devinfo_env_variable_name = "ARDOUR_MCP_PATH"; +static const char* const devinfo_dir_name = "mcp"; +static const char* const devinfo_suffix = ".device"; static sys::path system_devinfo_search_path () diff --git a/libs/surfaces/mackie/device_info.h b/libs/surfaces/mackie/device_info.h index 287bed5c0e..b08616db45 100644 --- a/libs/surfaces/mackie/device_info.h +++ b/libs/surfaces/mackie/device_info.h @@ -96,27 +96,6 @@ class DeviceInfo void shared_buttons (); }; -class DeviceProfile -{ - public: - DeviceProfile (DeviceInfo& info); - ~DeviceProfile(); - - const std::string& get_f_action (uint32_t fn, int modifier_state); - void set_f_action (uint32_t fn, int modifier_state, const std::string&); - - private: - struct KeyActions { - std::string plain; - std::string control; - std::string shift; - std::string option; - std::string cmdalt; - std::string shiftcontrol; - }; - - typedef std::map KeyActionMap; -}; } diff --git a/libs/surfaces/mackie/device_profile.cc b/libs/surfaces/mackie/device_profile.cc new file mode 100644 index 0000000000..860da3ca2a --- /dev/null +++ b/libs/surfaces/mackie/device_profile.cc @@ -0,0 +1,323 @@ +/* + Copyright (C) 2006,2007 John Anderson + Copyright (C) 2012 Paul Davis + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "pbd/xml++.h" +#include "pbd/error.h" +#include "pbd/pathscanner.h" + +#include "ardour/filesystem_paths.h" + +#include "mackie_control_protocol.h" +#include "device_profile.h" + +#include "i18n.h" + +using namespace Mackie; +using namespace PBD; +using namespace ARDOUR; +using std::string; +using std::vector; + +std::map DeviceProfile::device_profiles; + +DeviceProfile::DeviceProfile (const string& n) + : _name (n) +{ +} + +DeviceProfile::~DeviceProfile() +{ +} + +static const char * const devprofile_env_variable_name = "ARDOUR_MCP_PATH"; +static const char* const devprofile_dir_name = "mcp"; +static const char* const devprofile_suffix = ".profile"; + +static sys::path +system_devprofile_search_path () +{ + bool devprofile_path_defined = false; + sys::path spath_env (Glib::getenv (devprofile_env_variable_name, devprofile_path_defined)); + + if (devprofile_path_defined) { + return spath_env; + } + + SearchPath spath (system_data_search_path()); + spath.add_subdirectory_to_paths(devprofile_dir_name); + + // just return the first directory in the search path that exists + SearchPath::const_iterator i = std::find_if(spath.begin(), spath.end(), sys::exists); + + if (i == spath.end()) return sys::path(); + + return *i; +} + +static sys::path +user_devprofile_directory () +{ + sys::path p(user_config_directory()); + p /= devprofile_dir_name; + + return p; +} + +static bool +devprofile_filter (const string &str, void */*arg*/) +{ + return (str.length() > strlen(devprofile_suffix) && + str.find (devprofile_suffix) == (str.length() - strlen (devprofile_suffix))); +} + +void +DeviceProfile::reload_device_profiles () +{ + DeviceProfile dp; + vector s; + vector *devprofiles; + PathScanner scanner; + SearchPath spath (system_devprofile_search_path()); + spath += user_devprofile_directory (); + + devprofiles = scanner (spath.to_string(), devprofile_filter, 0, false, true); + device_profiles.clear (); + + if (!devprofiles) { + error << "No MCP device info files found using " << spath.to_string() << endmsg; + std::cerr << "No MCP device info files found using " << spath.to_string() << std::endl; + return; + } + + if (devprofiles->empty()) { + error << "No MCP device info files found using " << spath.to_string() << endmsg; + std::cerr << "No MCP device info files found using " << spath.to_string() << std::endl; + return; + } + + for (vector::iterator i = devprofiles->begin(); i != devprofiles->end(); ++i) { + string fullpath = *(*i); + + XMLTree tree; + + std::cerr << "Loading " << fullpath << std::endl; + + if (!tree.read (fullpath.c_str())) { + std::cerr << "XML read failed\n"; + continue; + } + + XMLNode* root = tree.root (); + if (!root) { + std::cerr << "no root\n"; + continue; + } + + if (dp.set_state (*root, 3000) == 0) { /* version is ignored for now */ + std::cerr << "saved profile " << dp.name() << std::endl; + device_profiles[dp.name()] = dp; + } + } + + delete devprofiles; +} + +int +DeviceProfile::set_state (const XMLNode& node, int /* version */) +{ + const XMLProperty* prop; + const XMLNode* child; + + if (node.name() != "MackieDeviceProfile") { + std::cerr << "wrong root\n"; + return -1; + } + + /* name is mandatory */ + + if ((child = node.child ("Name")) == 0 || (prop = child->property ("value")) == 0) { + std::cerr << "no name\n"; + return -1; + } else { + _name = prop->value(); + std::cerr << "got name " << _name << std::endl; + } + + if ((child = node.child ("Buttons")) != 0) { + XMLNodeConstIterator i; + const XMLNodeList& nlist (child->children()); + + for (i = nlist.begin(); i != nlist.end(); ++i) { + + if ((*i)->name() == "Button") { + + std::cerr << "foudn a button\n"; + + if ((prop = (*i)->property ("name")) == 0) { + error << string_compose ("Button without name in device profile \"%1\" - ignored", _name) << endmsg; + continue; + } + + int id = Button::name_to_id (prop->value()); + if (id < 0) { + error << string_compose ("Unknow button ID \"%1\"", prop->value()) << endmsg; + continue; + } + + Button::ID bid = (Button::ID) id; + + ButtonActionMap::iterator b = _button_map.find (bid); + + if (b == _button_map.end()) { + b = _button_map.insert (_button_map.end(), std::pair (bid, ButtonActions())); + } + + std::cerr << "checking bindings for button " << bid << std::endl; + + if ((prop = (*i)->property ("plain")) != 0) { + std::cerr << "Loaded binding between " << bid << " and " << prop->value() << std::endl; + b->second.plain = prop->value (); + } + if ((prop = (*i)->property ("control")) != 0) { + b->second.control = prop->value (); + } + if ((prop = (*i)->property ("shift")) != 0) { + b->second.shift = prop->value (); + } + if ((prop = (*i)->property ("option")) != 0) { + b->second.option = prop->value (); + } + if ((prop = (*i)->property ("cmdalt")) != 0) { + b->second.cmdalt = prop->value (); + } + if ((prop = (*i)->property ("shiftcontrol")) != 0) { + b->second.shiftcontrol = prop->value (); + } + } + } + } else { + std::cerr << " no buttons\n"; + } + + return 0; +} + +XMLNode& +DeviceProfile::get_state () const +{ + XMLNode* node = new XMLNode ("MackieDeviceProfile"); + + node->add_property ("name", _name); + + if (_button_map.empty()) { + return *node; + } + + XMLNode* buttons = new XMLNode ("Buttons"); + node->add_child_nocopy (*buttons); + + for (ButtonActionMap::const_iterator b = _button_map.begin(); b != _button_map.end(); ++b) { + XMLNode* n = new XMLNode ("Button"); + + n->add_property ("name", b->first); + + if (!b->second.plain.empty()) { + n->add_property ("plain", b->second.plain); + } + if (!b->second.control.empty()) { + n->add_property ("control", b->second.control); + } + if (!b->second.shift.empty()) { + n->add_property ("shift", b->second.shift); + } + if (!b->second.option.empty()) { + n->add_property ("option", b->second.option); + } + if (!b->second.cmdalt.empty()) { + n->add_property ("cmdalt", b->second.cmdalt); + } + if (!b->second.shiftcontrol.empty()) { + n->add_property ("shiftcontrol", b->second.shiftcontrol); + } + + buttons->add_child_nocopy (*n); + } + + return *node; +} + +string +DeviceProfile::get_button_action (Button::ID id, int modifier_state) const +{ + ButtonActionMap::const_iterator i = _button_map.find (id); + + if (i == _button_map.end()) { + return string(); + } + + if (modifier_state == MackieControlProtocol::MODIFIER_CONTROL) { + return i->second.control; + } else if (modifier_state == MackieControlProtocol::MODIFIER_SHIFT) { + return i->second.shift; + } else if (modifier_state == MackieControlProtocol::MODIFIER_OPTION) { + return i->second.option; + } else if (modifier_state == MackieControlProtocol::MODIFIER_CMDALT) { + return i->second.cmdalt; + } else if (modifier_state == (MackieControlProtocol::MODIFIER_CONTROL|MackieControlProtocol::MODIFIER_SHIFT)) { + return i->second.shiftcontrol; + } + + return i->second.plain; +} + +void +DeviceProfile::set_button_action (Button::ID id, int modifier_state, const string& action) +{ + ButtonActionMap::iterator i = _button_map.find (id); + + if (i == _button_map.end()) { + return; + } + + if (modifier_state == MackieControlProtocol::MODIFIER_CONTROL) { + i->second.control = action; + } else if (modifier_state == MackieControlProtocol::MODIFIER_SHIFT) { + i->second.shift = action; + } else if (modifier_state == MackieControlProtocol::MODIFIER_OPTION) { + i->second.option = action; + } else if (modifier_state == MackieControlProtocol::MODIFIER_CMDALT) { + i->second.cmdalt = action; + } else if (modifier_state == (MackieControlProtocol::MODIFIER_CONTROL|MackieControlProtocol::MODIFIER_SHIFT)) { + i->second.shiftcontrol = action; + } + + if (modifier_state == 0) { + i->second.plain = action; + } +} + +const string& +DeviceProfile::name() const +{ + return _name; +} diff --git a/libs/surfaces/mackie/device_profile.h b/libs/surfaces/mackie/device_profile.h new file mode 100644 index 0000000000..da63d97f48 --- /dev/null +++ b/libs/surfaces/mackie/device_profile.h @@ -0,0 +1,68 @@ +/* + Copyright (C) 2012 Paul Davis + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_mackie_control_protocol_device_profile_h__ +#define __ardour_mackie_control_protocol_device_profile_h__ + +#include +#include +#include +#include + +#include "button.h" + +class XMLNode; + +namespace Mackie { + +class DeviceProfile +{ + public: + DeviceProfile (const std::string& name = ""); + ~DeviceProfile(); + + std::string get_button_action (Button::ID, int modifier_state) const; + void set_button_action (Button::ID, int modifier_state, const std::string&); + + const std::string& name() const; + + static void reload_device_profiles (); + static std::map device_profiles; + + private: + struct ButtonActions { + std::string plain; + std::string control; + std::string shift; + std::string option; + std::string cmdalt; + std::string shiftcontrol; + }; + + typedef std::map ButtonActionMap; + + std::string _name; + ButtonActionMap _button_map; + + int set_state (const XMLNode&, int version); + XMLNode& get_state () const; +}; + +} + +#endif /* __ardour_mackie_control_protocol_device_profile_h__ */ diff --git a/libs/surfaces/mackie/gui.cc b/libs/surfaces/mackie/gui.cc index 1086e44bfb..0ed07276a6 100644 --- a/libs/surfaces/mackie/gui.cc +++ b/libs/surfaces/mackie/gui.cc @@ -71,19 +71,32 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p) Gtk::Table* table = Gtk::manage (new Gtk::Table (2, 2)); table->set_spacings (4); - table->attach (*manage (new Gtk::Label (_("Surface type:"))), 0, 1, 0, 1, AttachOptions(FILL|EXPAND), AttachOptions(0)); + table->attach (*manage (new Gtk::Label (_("Device Type:"))), 0, 1, 0, 1, AttachOptions(FILL|EXPAND), AttachOptions(0)); table->attach (_surface_combo, 1, 2, 0, 1, AttachOptions(FILL|EXPAND), AttachOptions(0)); + table->attach (*manage (new Gtk::Label (_("Profile/Settings:"))), 0, 1, 1, 2, AttachOptions(FILL|EXPAND), AttachOptions(0)); + table->attach (_profile_combo, 1, 2, 1, 2, AttachOptions(FILL|EXPAND), AttachOptions(0)); + vector surfaces; for (std::map::iterator i = DeviceInfo::device_info.begin(); i != DeviceInfo::device_info.end(); ++i) { - std::cerr << "Dveice known: " << i->first << endl; surfaces.push_back (i->first); } Gtkmm2ext::set_popdown_strings (_surface_combo, surfaces); _surface_combo.set_active_text (p.device_info().name()); _surface_combo.signal_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::surface_combo_changed)); + vector profiles; + + profiles.push_back ("default"); + + for (std::map::iterator i = DeviceProfile::device_profiles.begin(); i != DeviceProfile::device_profiles.end(); ++i) { + profiles.push_back (i->first); + } + Gtkmm2ext::set_popdown_strings (_profile_combo, profiles); + _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 Selection")); table->show_all(); @@ -92,7 +105,9 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p) append_page (function_key_scroller, _("Function Keys")); function_key_scroller.add (function_key_editor); - rebuild_function_key_editor (); + build_available_action_menu (); + build_function_key_editor (); + refresh_function_key_editor (); function_key_scroller.show_all(); } @@ -110,7 +125,7 @@ MackieControlProtocolGUI::make_action_renderer (Glib::RefPtr model, G } void -MackieControlProtocolGUI::rebuild_function_key_editor () +MackieControlProtocolGUI::build_available_action_menu () { /* build a model of all available actions (needs to be tree structured * more) @@ -186,16 +201,21 @@ MackieControlProtocolGUI::rebuild_function_key_editor () if (l->empty ()) { row[available_action_columns.name] = *t; + action_map[*t] = *p; } else { row[available_action_columns.name] = *l; + action_map[*l] = *p; } row[available_action_columns.path] = (*p); } +} +void +MackieControlProtocolGUI::build_function_key_editor () +{ function_key_editor.append_column (_("Key"), function_key_columns.name); - TreeViewColumn* col; CellRendererCombo* renderer; @@ -229,23 +249,106 @@ MackieControlProtocolGUI::rebuild_function_key_editor () 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()); + function_key_model->clear (); + /* now fill with data */ - function_key_model = ListStore::create (function_key_columns); - TreeModel::Row row; - - for (uint32_t n = 0; n < 16; ++n) { + DeviceProfile dp (_cp.device_profile()); + + for (int n = 0; n < Mackie::Button::FinalGlobalButton; ++n) { + + Mackie::Button::ID bid = (Mackie::Button::ID) n; row = *(function_key_model->append()); - row[function_key_columns.name] = string_compose ("F%1", n+1); - row[function_key_columns.number] = n; - row[function_key_columns.plain] = ""; // _cp.f_action (n, 0); - row[function_key_columns.control] = "c"; - row[function_key_columns.option] = "o"; - row[function_key_columns.shift] = "s"; - row[function_key_columns.cmdalt] = "ca"; - row[function_key_columns.shiftcontrol] = "sc"; + row[function_key_columns.name] = Mackie::Button::id_to_name (bid); + row[function_key_columns.id] = bid; + + Glib::RefPtr act; + string action; + const string defstring = "def"; + + action = dp.get_button_action (bid, 0); + if (action.empty()) { + row[function_key_columns.plain] = defstring; + } else { + std::cerr << "action = " << action << '\n'; + act = ActionManager::get_action (action.c_str()); + std::cerr << " action = " << act << endl; + if (act) { + row[function_key_columns.plain] = act->get_label(); + } else { + row[function_key_columns.plain] = defstring; + } + } + + action = dp.get_button_action (bid, MackieControlProtocol::MODIFIER_CONTROL); + if (action.empty()) { + row[function_key_columns.control] = defstring; + } else { + act = ActionManager::get_action (action.c_str()); + 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_SHIFT); + if (action.empty()) { + row[function_key_columns.shift] = defstring; + } else { + act = ActionManager::get_action (action.c_str()); + 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_OPTION); + if (action.empty()) { + row[function_key_columns.option] = defstring; + } else { + act = ActionManager::get_action (action.c_str()); + 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 { + act = ActionManager::get_action (action.c_str()); + 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.c_str()); + 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); @@ -257,10 +360,19 @@ MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const Glib Gtk::TreePath path(sPath); Gtk::TreeModel::iterator row = function_key_model->get_iter(path); - cerr << sPath << '-' << col.index() << " changed to " << text << endl; - if (row) { - (*row).set_value (col.index(), text); + + std::map::iterator i = action_map.find (text); + + if (i == action_map.end()) { + return; + } + + Glib::RefPtr act = ActionManager::get_action (i->second.c_str()); + + if (act) { + (*row).set_value (col.index(), text); + } } } @@ -270,4 +382,11 @@ MackieControlProtocolGUI::surface_combo_changed () _cp.set_device (_surface_combo.get_active_text()); } +void +MackieControlProtocolGUI::profile_combo_changed () +{ + _cp.set_profile (_profile_combo.get_active_text()); + refresh_function_key_editor (); +} + diff --git a/libs/surfaces/mackie/gui.h b/libs/surfaces/mackie/gui.h index 16a4c426ff..1c248fcbfb 100644 --- a/libs/surfaces/mackie/gui.h +++ b/libs/surfaces/mackie/gui.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2010 Paul Davis - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. + Copyright (C) 2010-2012 Paul Davis + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -32,18 +32,19 @@ namespace Gtk { class MackieControlProtocol; +#include "button.h" + #include "i18n.h" class MackieControlProtocolGUI : public Gtk::Notebook { public: - MackieControlProtocolGUI (MackieControlProtocol &); - + MackieControlProtocolGUI (MackieControlProtocol &); + private: - void surface_combo_changed (); - MackieControlProtocol& _cp; Gtk::ComboBoxText _surface_combo; + Gtk::ComboBoxText _profile_combo; struct AvailableActionColumns : public Gtk::TreeModel::ColumnRecord { AvailableActionColumns() { @@ -57,7 +58,7 @@ class MackieControlProtocolGUI : public Gtk::Notebook struct FunctionKeyColumns : public Gtk::TreeModel::ColumnRecord { FunctionKeyColumns() { add (name); - add (number); + add (id); add (plain); add (shift); add (control); @@ -66,7 +67,7 @@ class MackieControlProtocolGUI : public Gtk::Notebook add (shiftcontrol); }; Gtk::TreeModelColumn name; - Gtk::TreeModelColumn number; + Gtk::TreeModelColumn id; Gtk::TreeModelColumn plain; Gtk::TreeModelColumn shift; Gtk::TreeModelColumn control; @@ -83,8 +84,15 @@ class MackieControlProtocolGUI : public Gtk::Notebook Glib::RefPtr function_key_model; Glib::RefPtr available_action_model; - void rebuild_function_key_editor (); + void build_available_action_menu (); + void refresh_function_key_editor (); + void build_function_key_editor (); void action_changed (const Glib::ustring &sPath, const Glib::ustring &text, Gtk::TreeModelColumnBase); Gtk::CellRendererCombo* make_action_renderer (Glib::RefPtr model, Gtk::TreeModelColumnBase); + + void surface_combo_changed (); + void profile_combo_changed (); + + std::map action_map; // map from action names to paths }; diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index 40ad239696..8698391646 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -57,6 +57,7 @@ #include "midi_byte_array.h" #include "mackie_control_exception.h" +#include "device_profile.h" #include "surface_port.h" #include "surface.h" #include "strip.h" @@ -108,7 +109,10 @@ MackieControlProtocol::MackieControlProtocol (Session& session) DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n"); DeviceInfo::reload_device_info (); + DeviceProfile::reload_device_profiles (); + set_device (Config->get_mackie_device_name()); + set_profile (Config->get_mackie_device_profile()); AudioEngine::instance()->PortConnectedOrDisconnected.connect ( audio_engine_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5), @@ -506,6 +510,23 @@ MackieControlProtocol::connect_session_signals() } } +void +MackieControlProtocol::set_profile (const string& profile_name) +{ + if (profile_name == "default") { + /* reset to default */ + _device_profile = DeviceProfile (profile_name); + } + + map::iterator d = DeviceProfile::device_profiles.find (profile_name); + + if (d == DeviceProfile::device_profiles.end()) { + return; + } + + _device_profile = d->second; +} + void MackieControlProtocol::set_device (const string& device_name) { @@ -1016,6 +1037,22 @@ MackieControlProtocol::handle_button_event (Surface& surface, Button& button, Bu DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2\n", (bs == press ? "press" : "release"), button.id())); + /* check profile first */ + + string action = _device_profile.get_button_action (button.bid(), _modifier_state); + + if (!action.empty()) { + /* if there is a bound action for this button, and this is a press event, + carry out the action. If its a release event, do nothing since we + don't bind to them at all but don't want any other handling to + occur either. + */ + if (bs == press) { + access_action (action); + } + return; + } + /* lookup using the device-INDEPENDENT button ID */ ButtonMap::iterator b = button_map.find (button.bid()); diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index a2050fbeec..238c9c4aa5 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -41,6 +41,7 @@ #include "mackie_jog_wheel.h" #include "timer.h" #include "device_info.h" +#include "device_profile.h" namespace ARDOUR { class AutomationControl; @@ -118,9 +119,11 @@ class MackieControlProtocol static MackieControlProtocol* instance() { return _instance; } const Mackie::DeviceInfo& device_info() const { return _device_info; } + const Mackie::DeviceProfile& device_profile() const { return _device_profile; } int set_active (bool yn); void set_device (const std::string&); + void set_profile (const std::string&); bool flip_mode () const { return _flip_mode; } ViewMode view_mode () const { return _view_mode; } @@ -249,6 +252,7 @@ class MackieControlProtocol static MackieControlProtocol* _instance; Mackie::DeviceInfo _device_info; + Mackie::DeviceProfile _device_profile; sigc::connection periodic_connection; uint32_t _current_initial_bank; PBD::ScopedConnectionList audio_engine_connections; diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc index cbb0a9d6ca..24aeb92340 100644 --- a/libs/surfaces/mackie/strip.cc +++ b/libs/surfaces/mackie/strip.cc @@ -88,7 +88,10 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map (Meter::factory (*_surface, index, "meter", *this)); for (map::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) { - (void) Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this); + Button* bb = dynamic_cast (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this)); + DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n", + _surface->number(), index, Button::id_to_name (bb->bid()), + bb->id(), b->second.base_id)); } } diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc index f1f308209c..52323ee8a6 100644 --- a/libs/surfaces/mackie/surface.cc +++ b/libs/surfaces/mackie/surface.cc @@ -199,6 +199,8 @@ Surface::init_strips (uint32_t n) snprintf (name, sizeof (name), "strip_%d", (8* _number) + i); + std::cerr << "*** Surface " << _number << " Setup strips for index " << i << endl; + Strip* strip = new Strip (*this, name, i, strip_buttons); groups[name] = strip; diff --git a/libs/surfaces/mackie/wscript b/libs/surfaces/mackie/wscript index ed573ab798..5f0bb1aa2d 100644 --- a/libs/surfaces/mackie/wscript +++ b/libs/surfaces/mackie/wscript @@ -24,6 +24,7 @@ def build(bld): button.cc controls.cc device_info.cc + device_profile.cc fader.cc gui.cc interface.cc diff --git a/mcp_devices/mcpro.xml b/mcp/mcpro.device similarity index 100% rename from mcp_devices/mcpro.xml rename to mcp/mcpro.device diff --git a/mcp_devices/mcproxt.xml b/mcp/mcproxt.device similarity index 100% rename from mcp_devices/mcproxt.xml rename to mcp/mcproxt.device diff --git a/mcp_devices/nucleus.xml b/mcp/nucleus.device similarity index 100% rename from mcp_devices/nucleus.xml rename to mcp/nucleus.device