summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-04-14 19:02:54 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-04-14 19:02:54 +0000
commit2ed2b6122410fcd3e08c9bf8f753de512aa5c6b0 (patch)
tree2c3792dd3eced9a3008fedefdaf9b3816bed53e7
parent32766ce215fc2c668c65a54dc1d9436cd11ca413 (diff)
MCP: redesign to allow device-specific button IDs, since we know that at least one device (nucleus) does not honor mackie's specification document
git-svn-id: svn://localhost/ardour2/branches/3.0@11972 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/surfaces/mackie/button.cc85
-rw-r--r--libs/surfaces/mackie/button.h169
-rw-r--r--libs/surfaces/mackie/controls.cc10
-rw-r--r--libs/surfaces/mackie/controls.h2
-rw-r--r--libs/surfaces/mackie/device_info.cc123
-rw-r--r--libs/surfaces/mackie/device_info.h27
-rw-r--r--libs/surfaces/mackie/fader.h2
-rw-r--r--libs/surfaces/mackie/jog.cc36
-rw-r--r--libs/surfaces/mackie/jog.h4
-rw-r--r--libs/surfaces/mackie/led.cc6
-rw-r--r--libs/surfaces/mackie/led.h6
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc106
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h6
-rw-r--r--libs/surfaces/mackie/pot.cc2
-rw-r--r--libs/surfaces/mackie/pot.h4
-rw-r--r--libs/surfaces/mackie/strip.cc86
-rw-r--r--libs/surfaces/mackie/strip.h3
-rw-r--r--libs/surfaces/mackie/surface.cc138
-rw-r--r--libs/surfaces/mackie/surface.h7
-rw-r--r--libs/surfaces/mackie/wscript1
-rw-r--r--mcp_devices/nucleus.xml12
21 files changed, 517 insertions, 318 deletions
diff --git a/libs/surfaces/mackie/button.cc b/libs/surfaces/mackie/button.cc
index 714294ed7d..588c11d984 100644
--- a/libs/surfaces/mackie/button.cc
+++ b/libs/surfaces/mackie/button.cc
@@ -24,11 +24,92 @@
using namespace Mackie;
Control*
-Button::factory (Surface& surface, int id, const char* name, Group& group)
+Button::factory (Surface& surface, Button::ID bid, int id, const std::string& name, Group& group)
{
- Button* b = new Button (id, name, group);
+ Button* b = new Button (bid, id, name, group);
+ /* store button with the device-specific ID */
surface.buttons[id] = b;
surface.controls.push_back (b);
group.add (*b);
return b;
}
+
+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; }
+
+ /* 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; }
+
+ return -1;
+}
diff --git a/libs/surfaces/mackie/button.h b/libs/surfaces/mackie/button.h
index 2702452750..48ea9c5919 100644
--- a/libs/surfaces/mackie/button.h
+++ b/libs/surfaces/mackie/button.h
@@ -30,92 +30,105 @@ class Surface;
class Button : public Control
{
public:
- enum base_id_t {
- recenable_base_id = 0x0,
- solo_base_id = 0x08,
- mute_base_id = 0x10,
- select_base_id = 0x18,
- vselect_base_id = 0x20,
- fader_touch_base_id = 0x68, // 0xe0,
- };
+/* These values uniquely identify each possible button that an MCP device may
+ send. Each DeviceInfo object contains its own set of button definitions that
+ define what device ID will be sent for each button, and there is no reason
+ for them to be the same. */
- enum ButtonID {
- Io = 0x28,
- Sends = 0x29,
- Pan = 0x2a,
- Plugin = 0x2b,
- Eq = 0x2c,
- Dyn = 0x2d,
- Left = 0x2e,
- Right = 0x2f,
- ChannelLeft = 0x30,
- ChannelRight = 0x31,
- Flip = 0x32,
- Edit = 0x33,
- NameValue = 0x34,
- TimecodeBeats = 0x35,
- F1 = 0x36,
- F2 = 0x37,
- F3 = 0x38,
- F4 = 0x39,
- F5 = 0x3a,
- F6 = 0x3b,
- F7 = 0x3c,
- F8 = 0x3d,
- F9 = 0x3e,
- F10 = 0x3f,
- F11 = 0x40,
- F12 = 0x41,
- F13 = 0x42,
- F14 = 0x43,
- F15 = 0x44,
- F16 = 0x45,
- Shift = 0x46,
- Option = 0x47,
- Ctrl = 0x48,
- CmdAlt = 0x49,
- On = 0x4a,
- RecReady = 0x4b,
- Undo = 0x4c,
- Save = 0x4d,
- Touch = 0x4e,
- Redo = 0x4f,
- Marker = 0x50,
- Enter = 0x51,
- Cancel = 0x52,
- Mixer = 0x53,
- FrmLeft = 0x54,
- FrmRight = 0x55,
- Loop = 0x56,
- PunchIn = 0x57,
- PunchOut = 0x58,
- Home = 0x59,
- End = 0x5a,
- Rewind = 0x5b,
- Ffwd = 0x5c,
- Stop = 0x5d,
- Play = 0x5e,
- Record = 0x5f,
- CursorUp = 0x60,
- CursorDown = 0x61,
- CursorLeft = 0x62,
- CursorRight = 0x63,
- Zoom = 0x64,
- Scrub = 0x65,
- UserA = 0x66,
- UserB = 0x67,
+ enum ID {
+ /* Global Buttons */
+
+ IO,
+ Sends,
+ Pan,
+ Plugin,
+ Eq,
+ Dyn,
+ Left,
+ Right,
+ ChannelLeft,
+ ChannelRight,
+ Flip,
+ Edit,
+ NameValue,
+ TimecodeBeats,
+ F1,
+ F2,
+ F3,
+ F4,
+ F5,
+ F6,
+ F7,
+ F8,
+ F9,
+ F10,
+ F11,
+ F12,
+ F13,
+ F14,
+ F15,
+ F16,
+ Shift,
+ Option,
+ Ctrl,
+ CmdAlt,
+ On,
+ RecReady,
+ Undo,
+ Save,
+ Touch,
+ Redo,
+ Marker,
+ Enter,
+ Cancel,
+ Mixer,
+ FrmLeft,
+ FrmRight,
+ Loop,
+ PunchIn,
+ PunchOut,
+ Home,
+ End,
+ Rewind,
+ Ffwd,
+ Stop,
+ Play,
+ Record,
+ CursorUp,
+ CursorDown,
+ CursorLeft,
+ CursorRight,
+ Zoom,
+ Scrub,
+ UserA,
+ UserB,
+
+ /* Strip buttons */
+
+ RecEnable,
+ Solo,
+ Mute,
+ Select,
+ VSelect,
+ FaderTouch,
};
- Button (int id, std::string name, Group & group)
- : Control (id, name, group)
- , _led (id, name + "_led", group) {}
+
+ Button (ID bid, int did, std::string name, Group & group)
+ : Control (did, name, group)
+ , _bid (bid)
+ , _led (did, name + "_led", group) {}
MidiByteArray zero() { return _led.zero (); }
MidiByteArray set_state (LedState ls) { return _led.set_state (ls); }
-
- static Control* factory (Surface&, int id, const char*, Group&);
+ ID bid() const { return _bid; }
+
+ static Control* factory (Surface& surface, Button::ID bid, int id, const std::string&, Group& group);
+ static int name_to_id (const std::string& name);
+
private:
+ ID _bid; /* device independent button ID */
Led _led;
};
diff --git a/libs/surfaces/mackie/controls.cc b/libs/surfaces/mackie/controls.cc
index 0e95d6ee95..24b59fd744 100644
--- a/libs/surfaces/mackie/controls.cc
+++ b/libs/surfaces/mackie/controls.cc
@@ -83,16 +83,6 @@ ostream & Mackie::operator << (ostream & os, const Mackie::Control & control)
return os;
}
-Control*
-Jog::factory (Surface& surface, int id, const char* name, Group& group)
-{
- Jog* j = new Jog (id, name, group);
- surface.controls.push_back (j);
- surface.controls_by_name["jog"] = j;
- group.add (*j);
- return j;
-}
-
void
Control::set_normal_control (boost::shared_ptr<AutomationControl> ac)
{
diff --git a/libs/surfaces/mackie/controls.h b/libs/surfaces/mackie/controls.h
index 8538cace88..eb9a691972 100644
--- a/libs/surfaces/mackie/controls.h
+++ b/libs/surfaces/mackie/controls.h
@@ -85,7 +85,7 @@ public:
boost::shared_ptr<ARDOUR::AutomationControl> modified_ac;
private:
- int _id;
+ int _id; /* possibly device-dependent ID */
std::string _name;
Group& _group;
bool _in_use;
diff --git a/libs/surfaces/mackie/device_info.cc b/libs/surfaces/mackie/device_info.cc
index 9b15baf208..1ec9c2e788 100644
--- a/libs/surfaces/mackie/device_info.cc
+++ b/libs/surfaces/mackie/device_info.cc
@@ -17,6 +17,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <cstdlib>
#include <cstring>
#include <glibmm/miscutils.h>
@@ -50,7 +51,83 @@ DeviceInfo::DeviceInfo()
, _has_touch_sense_faders (true)
, _name (X_("Mackie Control Universal Pro"))
{
-
+ /* these definitions are based on Mackie's specification for Mackie
+ * Control Protocol.
+ *
+ * Any given device info file can override any or all of these for any reason.
+ */
+
+ _global_buttons[Button::IO] = GlobalButtonInfo ("io", "assignment", 0x28);
+ _global_buttons[Button::Sends] = GlobalButtonInfo ("sends", "assignment", 0x29);
+ _global_buttons[Button::Pan] = GlobalButtonInfo ("pan", "assignment", 0x2a);
+ _global_buttons[Button::Plugin] = GlobalButtonInfo ("plugin", "assignment", 0x2b);
+ _global_buttons[Button::Eq] = GlobalButtonInfo ("eq", "assignment", 0x2c);
+ _global_buttons[Button::Dyn] = GlobalButtonInfo ("dyn", "assignment", 0x2d);
+ _global_buttons[Button::Left] = GlobalButtonInfo ("left", "bank", 0x2e);
+ _global_buttons[Button::Right] = GlobalButtonInfo ("right", "bank", 0x2f);
+ _global_buttons[Button::ChannelLeft] = GlobalButtonInfo ("channel left", "bank", 0x30);
+ _global_buttons[Button::ChannelRight] = GlobalButtonInfo ("channelright", "bank", 0x31);
+ _global_buttons[Button::Flip] = GlobalButtonInfo ("flip", "none", 0x32);
+ _global_buttons[Button::Edit] = GlobalButtonInfo ("edit", "none", 0x33);
+ _global_buttons[Button::NameValue] = GlobalButtonInfo ("name/value", "display", 0x34);
+ _global_buttons[Button::TimecodeBeats] = GlobalButtonInfo ("timecode/beats", "display", 0x35);
+ _global_buttons[Button::F1] = GlobalButtonInfo ("F1", "none", 0x36);
+ _global_buttons[Button::F2] = GlobalButtonInfo ("F2", "none", 0x37);
+ _global_buttons[Button::F3] = GlobalButtonInfo ("F3", "none", 0x38);
+ _global_buttons[Button::F4] = GlobalButtonInfo ("F4", "none", 0x39);
+ _global_buttons[Button::F5] = GlobalButtonInfo ("F5", "none", 0x3a);
+ _global_buttons[Button::F6] = GlobalButtonInfo ("F6", "none", 0x3b);
+ _global_buttons[Button::F7] = GlobalButtonInfo ("F7", "none", 0x3c);
+ _global_buttons[Button::F8] = GlobalButtonInfo ("F8", "none", 0x3d);
+ _global_buttons[Button::F9] = GlobalButtonInfo ("F9", "none", 0x3e);
+ _global_buttons[Button::F10] = GlobalButtonInfo ("F10", "none", 0x3f);
+ _global_buttons[Button::F11] = GlobalButtonInfo ("F11", "none", 0x40);
+ _global_buttons[Button::F12] = GlobalButtonInfo ("F12", "none", 0x41);
+ _global_buttons[Button::F13] = GlobalButtonInfo ("F13", "none", 0x42);
+ _global_buttons[Button::F14] = GlobalButtonInfo ("F14", "none", 0x43);
+ _global_buttons[Button::F15] = GlobalButtonInfo ("F15", "none", 0x44);
+ _global_buttons[Button::F16] = GlobalButtonInfo ("F16", "none", 0x45);
+ _global_buttons[Button::Shift] = GlobalButtonInfo ("shift", "modifiers", 0x46);
+ _global_buttons[Button::Option] = GlobalButtonInfo ("option", "modifiers", 0x47);
+ _global_buttons[Button::Ctrl] = GlobalButtonInfo ("control", "modifiers", 0x48);
+ _global_buttons[Button::CmdAlt] = GlobalButtonInfo ("cmd_alt", "modifiers", 0x49);
+ _global_buttons[Button::On] = GlobalButtonInfo ("on", "automation", 0x4a);
+ _global_buttons[Button::RecReady] = GlobalButtonInfo ("rec_ready", "automation", 0x4b);
+ _global_buttons[Button::Undo] = GlobalButtonInfo ("undo", "functions", 0x4c);
+ _global_buttons[Button::Save] = GlobalButtonInfo ("save", "automation", 0x4d);
+ _global_buttons[Button::Touch] = GlobalButtonInfo ("touch", "automation", 0x4e);
+ _global_buttons[Button::Redo] = GlobalButtonInfo ("redo", "functions", 0x4f);
+ _global_buttons[Button::Marker] = GlobalButtonInfo ("marker", "functions", 0x50);
+ _global_buttons[Button::Enter] = GlobalButtonInfo ("enter", "functions", 0x51);
+ _global_buttons[Button::Cancel] = GlobalButtonInfo ("cancel", "functions", 0x52);
+ _global_buttons[Button::Mixer] = GlobalButtonInfo ("mixer", "functions", 0x53);
+ _global_buttons[Button::FrmLeft] = GlobalButtonInfo ("frm left", "transport", 0x54);
+ _global_buttons[Button::FrmRight] = GlobalButtonInfo ("frm right", "transport", 0x55);
+ _global_buttons[Button::Loop] = GlobalButtonInfo ("loop", "transport", 0x56);
+ _global_buttons[Button::PunchIn] = GlobalButtonInfo ("punch in", "transport", 0x57);
+ _global_buttons[Button::PunchOut] = GlobalButtonInfo ("punch out", "transport", 0x58);
+ _global_buttons[Button::Home] = GlobalButtonInfo ("home", "transport", 0x59);
+ _global_buttons[Button::End] = GlobalButtonInfo ("end", "transport", 0x5a);
+ _global_buttons[Button::Rewind] = GlobalButtonInfo ("rewind", "transport", 0x5b);
+ _global_buttons[Button::Ffwd] = GlobalButtonInfo ("ffwd", "transport", 0x5c);
+ _global_buttons[Button::Stop] = GlobalButtonInfo ("stop", "transport", 0x5d);
+ _global_buttons[Button::Play] = GlobalButtonInfo ("play", "transport", 0x5e);
+ _global_buttons[Button::Record] = GlobalButtonInfo ("record", "transport", 0x5f);
+ _global_buttons[Button::CursorUp] = GlobalButtonInfo ("cursor up", "cursor", 0x60);
+ _global_buttons[Button::CursorDown] = GlobalButtonInfo ("cursor down", "cursor", 0x61);
+ _global_buttons[Button::CursorLeft] = GlobalButtonInfo ("cursor left", "cursor", 0x62);
+ _global_buttons[Button::CursorRight] = GlobalButtonInfo ("cursor right", "cursor", 0x63);
+ _global_buttons[Button::Zoom] = GlobalButtonInfo ("zoom", "none", 0x64);
+ _global_buttons[Button::Scrub] = GlobalButtonInfo ("scrub", "none", 0x65);
+ _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::Solo] = StripButtonInfo (0x08, "solo");
+ _strip_buttons[Button::Mute] = StripButtonInfo (0x10, "mute");
+ _strip_buttons[Button::Select] = StripButtonInfo (0x18, "select");
+ _strip_buttons[Button::VSelect] = StripButtonInfo (0x20, "vselect");
+ _strip_buttons[Button::FaderTouch] = StripButtonInfo (0x68, "fader touch");
}
DeviceInfo::~DeviceInfo()
@@ -134,6 +211,50 @@ DeviceInfo::set_state (const XMLNode& node, int /* version */)
_has_touch_sense_faders = string_is_affirmative (prop->value());
}
}
+ if ((child = node.child ("Buttons")) != 0) {
+ XMLNodeConstIterator i;
+ const XMLNodeList& nlist (child->children());
+
+ for (i = nlist.begin(); i != nlist.end(); ++i) {
+ if ((*i)->name() == "GlobalButton") {
+ if ((prop = (*i)->property ("name")) != 0) {
+ int id = Button::name_to_id (prop->value());
+ if (id >= 0) {
+ Button::ID bid = (Button::ID) id;
+ if ((prop = (*i)->property ("id")) != 0) {
+ int val = strtol (prop->value().c_str(), 0, 0);
+ std::map<Button::ID,GlobalButtonInfo>::iterator b = _global_buttons.find (bid);
+ if (b != _global_buttons.end()) {
+ b->second.id = val;
+
+ if ((prop = (*i)->property ("label")) != 0) {
+ b->second.label = prop->value();
+ }
+ }
+ }
+ }
+
+ }
+
+ } else if ((*i)->name() == "StripButton") {
+ if ((prop = (*i)->property ("name")) != 0) {
+ int id = Button::name_to_id (prop->value());
+ if (id >= 0) {
+ Button::ID bid = (Button::ID) id;
+ if ((prop = (*i)->property ("baseid")) != 0) {
+ int val = strtol (prop->value().c_str(), 0, 0);
+ std::map<Button::ID,StripButtonInfo>::iterator b = _strip_buttons.find (bid);
+ if (b != _strip_buttons.end()) {
+ b->second.base_id = val;
+ }
+ }
+ }
+
+ }
+
+ }
+ }
+ }
return 0;
}
diff --git a/libs/surfaces/mackie/device_info.h b/libs/surfaces/mackie/device_info.h
index 191ccfc4ce..9ca51cae71 100644
--- a/libs/surfaces/mackie/device_info.h
+++ b/libs/surfaces/mackie/device_info.h
@@ -25,10 +25,31 @@
#include <string>
#include <map>
+#include "button.h"
+
class XMLNode;
namespace Mackie {
+struct GlobalButtonInfo {
+ std::string label; // visible to user
+ std::string group; // in case we want to present in a GUI
+ int32_t id; // value sent by device
+
+ GlobalButtonInfo () : id (-1) {}
+ GlobalButtonInfo (const std::string& l, const std::string& g, uint32_t i)
+ : label (l), group (g), id (i) {}
+};
+
+struct StripButtonInfo {
+ int32_t base_id;
+ std::string name;
+
+ StripButtonInfo () : base_id (-1) {}
+ StripButtonInfo (uint32_t i, const std::string& n)
+ : base_id (i), name (n) {}
+};
+
class DeviceInfo
{
public:
@@ -51,6 +72,9 @@ class DeviceInfo
static std::map<std::string,DeviceInfo> device_info;
static void reload_device_info();
+ const std::map<Button::ID,GlobalButtonInfo>& global_buttons() const { return _global_buttons; }
+ const std::map<Button::ID,StripButtonInfo>& strip_buttons() const { return _strip_buttons; }
+
private:
uint32_t _strip_cnt;
uint32_t _extenders;
@@ -62,6 +86,9 @@ class DeviceInfo
bool _has_jog_wheel;
bool _has_touch_sense_faders;
std::string _name;
+
+ std::map<Button::ID,GlobalButtonInfo> _global_buttons;
+ std::map<Button::ID,StripButtonInfo> _strip_buttons;
};
class DeviceProfile
diff --git a/libs/surfaces/mackie/fader.h b/libs/surfaces/mackie/fader.h
index 3520699e98..ed8e72eb50 100644
--- a/libs/surfaces/mackie/fader.h
+++ b/libs/surfaces/mackie/fader.h
@@ -20,7 +20,7 @@ class Fader : public Control
MidiByteArray update_message ();
static Control* factory (Surface&, int id, const char*, Group&);
-
+
private:
float position;
};
diff --git a/libs/surfaces/mackie/jog.cc b/libs/surfaces/mackie/jog.cc
new file mode 100644
index 0000000000..dc832868ed
--- /dev/null
+++ b/libs/surfaces/mackie/jog.cc
@@ -0,0 +1,36 @@
+/*
+ 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 "jog.h"
+#include "surface.h"
+#include "control_group.h"
+
+using namespace Mackie;
+
+const int Jog::ID = 0x3c;
+
+Control*
+Jog::factory (Surface& surface, int id, const char* name, Group& group)
+{
+ Jog* j = new Jog (id, name, group);
+ surface.pots[id] = j;
+ surface.controls.push_back (j);
+ group.add (*j);
+ return j;
+}
diff --git a/libs/surfaces/mackie/jog.h b/libs/surfaces/mackie/jog.h
index a4a6b739de..23451f92b2 100644
--- a/libs/surfaces/mackie/jog.h
+++ b/libs/surfaces/mackie/jog.h
@@ -28,9 +28,7 @@ namespace Mackie {
class Jog : public Pot
{
public:
- enum base_id_t {
- base_id = 0x3c
- };
+ static const int ID;
Jog (int id, std::string name, Group & group)
: Pot (id, name, group)
diff --git a/libs/surfaces/mackie/led.cc b/libs/surfaces/mackie/led.cc
index 342db049a5..38aa5c7f3b 100644
--- a/libs/surfaces/mackie/led.cc
+++ b/libs/surfaces/mackie/led.cc
@@ -23,6 +23,12 @@
using namespace Mackie;
+const int Led::FaderTouch = 0x70;
+const int Led::Timecode = 0x71;
+const int Led::Beats = 0x72;
+const int Led::RudeSolo = 0x73;
+const int Led::RelayClick = 0x74;
+
Control*
Led::factory (Surface& surface, int id, const char* name, Group& group)
{
diff --git a/libs/surfaces/mackie/led.h b/libs/surfaces/mackie/led.h
index fca9b78a43..fdbeb8cd9c 100644
--- a/libs/surfaces/mackie/led.h
+++ b/libs/surfaces/mackie/led.h
@@ -29,6 +29,12 @@ namespace Mackie {
class Led : public Control
{
public:
+ static const int FaderTouch;
+ static const int Timecode;
+ static const int Beats;
+ static const int RudeSolo;
+ static const int RelayClick;
+
Led (int id, std::string name, Group & group)
: Control (id, name, group)
, state (off)
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index 7aa78d8c02..3f98e98ac9 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -409,12 +409,12 @@ MackieControlProtocol::update_timecode_beats_led()
{
switch (_timecode_type) {
case ARDOUR::AnyTime::BBT:
- update_global_led ("beats", on);
- update_global_led ("timecode", off);
+ update_global_led (Led::Beats, on);
+ update_global_led (Led::Timecode, off);
break;
case ARDOUR::AnyTime::Timecode:
- update_global_led ("timecode", on);
- update_global_led ("beats", off);
+ update_global_led (Led::Timecode, on);
+ update_global_led (Led::Beats, off);
break;
default:
ostringstream os;
@@ -424,7 +424,7 @@ MackieControlProtocol::update_timecode_beats_led()
}
void
-MackieControlProtocol::update_global_button (const string & name, LedState ls)
+MackieControlProtocol::update_global_button (int id, LedState ls)
{
boost::shared_ptr<Surface> surface = surfaces.front();
@@ -432,16 +432,17 @@ MackieControlProtocol::update_global_button (const string & name, LedState ls)
return;
}
- if (surface->controls_by_name.find (name) != surface->controls_by_name.end()) {
- Button * button = dynamic_cast<Button*> (surface->controls_by_name[name]);
+ map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (id);
+ if (x != surface->controls_by_device_independent_id.end()) {
+ Button * button = dynamic_cast<Button*> (x->second);
surface->write (button->set_state (ls));
} else {
- DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", name));
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", id));
}
}
void
-MackieControlProtocol::update_global_led (const string & name, LedState ls)
+MackieControlProtocol::update_global_led (int id, LedState ls)
{
boost::shared_ptr<Surface> surface = surfaces.front();
@@ -449,11 +450,12 @@ MackieControlProtocol::update_global_led (const string & name, LedState ls)
return;
}
- if (surface->controls_by_name.find (name) != surface->controls_by_name.end()) {
- Led * led = dynamic_cast<Led*> (surface->controls_by_name[name]);
+ map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (id);
+ if (x != surface->controls_by_device_independent_id.end()) {
+ Led * led = dynamic_cast<Led*> (x->second);
surface->write (led->set_state (ls));
} else {
- DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", name));
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", id));
}
}
@@ -755,11 +757,11 @@ MackieControlProtocol::update_timecode_display()
void MackieControlProtocol::notify_parameter_changed (std::string const & p)
{
if (p == "punch-in") {
- update_global_button ("punch_in", session->config.get_punch_in());
+ update_global_button (Button::PunchIn, session->config.get_punch_in());
} else if (p == "punch-out") {
- update_global_button ("punch_out", session->config.get_punch_out());
+ update_global_button (Button::PunchOut, session->config.get_punch_out());
} else if (p == "clicking") {
- update_global_button ("clicking", Config->get_clicking());
+ // update_global_button (Button::RelayClick, Config->get_clicking());
} else {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("parameter changed: %1\n", p));
}
@@ -789,10 +791,12 @@ MackieControlProtocol::notify_solo_active_changed (bool active)
{
boost::shared_ptr<Surface> surface = surfaces.front();
- Led* rude_solo = dynamic_cast<Led*> (surface->controls_by_name["solo"]);
-
- if (rude_solo) {
- surface->write (rude_solo->set_state (active ? flashing : off));
+ map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Led::RudeSolo);
+ if (x != surface->controls_by_device_independent_id.end()) {
+ Led* rude_solo = dynamic_cast<Led*> (x->second);
+ if (rude_solo) {
+ surface->write (rude_solo->set_state (active ? flashing : off));
+ }
}
}
@@ -821,17 +825,17 @@ MackieControlProtocol::notify_remote_id_changed()
void
MackieControlProtocol::notify_loop_state_changed()
{
- update_global_button ("loop", session->get_play_loop());
+ update_global_button (Button::Loop, session->get_play_loop());
}
void
MackieControlProtocol::notify_transport_state_changed()
{
// switch various play and stop buttons on / off
- update_global_button ("play", session->transport_speed() == 1.0);
- update_global_button ("stop", !session->transport_rolling());
- update_global_button ("rewind", session->transport_speed() < 0.0);
- update_global_button ("ffwd", session->transport_speed() > 1.0);
+ update_global_button (Button::Play, session->transport_speed() == 1.0);
+ update_global_button (Button::Stop, !session->transport_rolling());
+ update_global_button (Button::Rewind, session->transport_speed() < 0.0);
+ update_global_button (Button::Ffwd, session->transport_speed() > 1.0);
_transport_previously_rolling = session->transport_rolling();
}
@@ -839,31 +843,33 @@ MackieControlProtocol::notify_transport_state_changed()
void
MackieControlProtocol::notify_record_state_changed ()
{
- /* rec is a tristate */
-
+ boost::shared_ptr<Surface> surface = surfaces.front();
- Button * rec = reinterpret_cast<Button*> (surfaces.front()->controls_by_name["record"]);
- if (rec) {
- LedState ls;
+ /* rec is a tristate */
- switch (session->record_status()) {
- case Session::Disabled:
- DEBUG_TRACE (DEBUG::MackieControl, "record state changed to disabled, LED off\n");
- ls = off;
- break;
- case Session::Recording:
- DEBUG_TRACE (DEBUG::MackieControl, "record state changed to recording, LED on\n");
- ls = on;
- break;
- case Session::Enabled:
- DEBUG_TRACE (DEBUG::MackieControl, "record state changed to enabled, LED flashing\n");
- ls = flashing;
- break;
+ map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Button::Record);
+ if (x != surface->controls_by_device_independent_id.end()) {
+ Button * rec = dynamic_cast<Button*> (x->second);
+ if (rec) {
+ LedState ls;
+
+ switch (session->record_status()) {
+ case Session::Disabled:
+ DEBUG_TRACE (DEBUG::MackieControl, "record state changed to disabled, LED off\n");
+ ls = off;
+ break;
+ case Session::Recording:
+ DEBUG_TRACE (DEBUG::MackieControl, "record state changed to recording, LED on\n");
+ ls = on;
+ break;
+ case Session::Enabled:
+ DEBUG_TRACE (DEBUG::MackieControl, "record state changed to enabled, LED flashing\n");
+ ls = flashing;
+ break;
+ }
+
+ surface->write (rec->set_state (ls));
}
-
- surfaces.front()->write (rec->set_state (ls));
- } else {
- DEBUG_TRACE (DEBUG::MackieControl, "record button control not found\n");
}
}
@@ -969,9 +975,9 @@ MackieControlProtocol::update_led (Surface& surface, Button& button, Mackie::Led
void
MackieControlProtocol::build_button_map ()
{
-#define DEFINE_BUTTON_HANDLER(b,p,r) button_map.insert (pair<int,ButtonHandlers> ((b), ButtonHandlers ((p),(r))));
+#define DEFINE_BUTTON_HANDLER(b,p,r) button_map.insert (pair<Button::ID,ButtonHandlers> ((b), ButtonHandlers ((p),(r))));
- DEFINE_BUTTON_HANDLER (Button::Io, &MackieControlProtocol::io_press, &MackieControlProtocol::io_release);
+ DEFINE_BUTTON_HANDLER (Button::IO, &MackieControlProtocol::io_press, &MackieControlProtocol::io_release);
DEFINE_BUTTON_HANDLER (Button::Sends, &MackieControlProtocol::sends_press, &MackieControlProtocol::sends_release);
DEFINE_BUTTON_HANDLER (Button::Pan, &MackieControlProtocol::pan_press, &MackieControlProtocol::pan_release);
DEFINE_BUTTON_HANDLER (Button::Plugin, &MackieControlProtocol::plugin_press, &MackieControlProtocol::plugin_release);
@@ -1047,7 +1053,9 @@ 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()));
- ButtonMap::iterator b = button_map.find (button.id());
+ /* lookup using the device-INDEPENDENT button ID */
+
+ ButtonMap::iterator b = button_map.find (button.bid());
if (b != button_map.end()) {
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index 83b77bd7f2..c4cda58c26 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -171,8 +171,8 @@ class MackieControlProtocol
/// this is called to generate the midi to send in response to a button press.
void update_led(Mackie::Surface&, Mackie::Button & button, Mackie::LedState);
- void update_global_button(const std::string & name, Mackie::LedState);
- void update_global_led(const std::string & name, Mackie::LedState);
+ void update_global_button (int id, Mackie::LedState);
+ void update_global_led (int id, Mackie::LedState);
ARDOUR::Session & get_session() { return *session; }
framepos_t transport_frame() const;
@@ -247,7 +247,7 @@ class MackieControlProtocol
, release (r) {}
};
- typedef std::map<int,ButtonHandlers> ButtonMap;
+ typedef std::map<Mackie::Button::ID,ButtonHandlers> ButtonMap;
typedef std::list<GSource*> PortSources;
static MackieControlProtocol* _instance;
diff --git a/libs/surfaces/mackie/pot.cc b/libs/surfaces/mackie/pot.cc
index 1320512e92..0b3062be8c 100644
--- a/libs/surfaces/mackie/pot.cc
+++ b/libs/surfaces/mackie/pot.cc
@@ -24,6 +24,8 @@
using namespace Mackie;
+int const Pot::External = 0x2e;
+
Control*
Pot::factory (Surface& surface, int id, const char* name, Group& group)
{
diff --git a/libs/surfaces/mackie/pot.h b/libs/surfaces/mackie/pot.h
index e8a6b0dc43..5aa4f297d1 100644
--- a/libs/surfaces/mackie/pot.h
+++ b/libs/surfaces/mackie/pot.h
@@ -27,9 +27,7 @@ namespace Mackie {
class Pot : public Control
{
public:
- enum base_id_t {
- base_id = 0x10,
- };
+ static int const External;
enum Mode {
dot = 0,
diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc
index dc7a15fe6a..2d65b663ca 100644
--- a/libs/surfaces/mackie/strip.cc
+++ b/libs/surfaces/mackie/strip.cc
@@ -59,7 +59,7 @@ using namespace PBD;
extern PBD::EventLoop::InvalidationRecord* __invalidator (sigc::trackable& trackable, const char*, int);
#define invalidator() __invalidator (*(MackieControlProtocol::instance()), __FILE__, __LINE__)
-Strip::Strip (Surface& s, const std::string& name, int index, StripControlDefinition* ctls)
+Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
: Group (name)
, _solo (0)
, _recenable (0)
@@ -76,75 +76,51 @@ Strip::Strip (Surface& s, const std::string& name, int index, StripControlDefini
, _last_gain_position_written (-1.0)
, _last_pan_position_written (-1.0)
{
- /* build the controls for this track, which will automatically add them
- to the Group
- */
+ _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
+ _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, index, "vpot", *this));
+ _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
- for (uint32_t i = 0; ctls[i].name[0]; ++i) {
- ctls[i].factory (*_surface, ctls[i].base_id + index, ctls[i].name, *this);
+ for (map<Button::ID,StripButtonInfo>::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);
}
}
Strip::~Strip ()
{
+ /* surface is responsible for deleting all controls */
}
-/**
- TODO could optimise this to use enum, but it's only
- called during the protocol class instantiation.
-*/
-void Strip::add (Control & control)
+void
+Strip::add (Control & control)
{
- Group::add (control);
-
- Fader* fader;
- Pot* pot;
Button* button;
- Meter* meter;
-
- if ((fader = dynamic_cast<Fader*>(&control)) != 0) {
- _fader = fader;
-
- } else if ((pot = dynamic_cast<Pot*>(&control)) != 0) {
-
- _vpot = pot;
+ Group::add (control);
- } else if ((button = dynamic_cast<Button*>(&control)) != 0) {
+ /* fader, vpot, meter were all set explicitly */
- if (control.id() >= Button::recenable_base_id &&
- control.id() < Button::recenable_base_id + 8) {
-
+ if ((button = dynamic_cast<Button*>(&control)) != 0) {
+ switch (button->bid()) {
+ case Button::RecEnable:
_recenable = button;
-
- } else if (control.id() >= Button::mute_base_id &&
- control.id() < Button::mute_base_id + 8) {
-
+ break;
+ case Button::Mute:
_mute = button;
-
- } else if (control.id() >= Button::solo_base_id &&
- control.id() < Button::solo_base_id + 8) {
-
+ break;
+ case Button::Solo:
_solo = button;
-
- } else if (control.id() >= Button::select_base_id &&
- control.id() < Button::select_base_id + 8) {
-
+ break;
+ case Button::Select:
_select = button;
-
- } else if (control.id() >= Button::vselect_base_id &&
- control.id() < Button::vselect_base_id + 8) {
-
+ break;
+ case Button::VSelect:
_vselect = button;
-
- } else if (control.id() >= Button::fader_touch_base_id &&
- control.id() < Button::fader_touch_base_id + 8) {
-
+ break;
+ case Button::FaderTouch:
_fader_touch = button;
+ default:
+ break;
}
-
- } else if ((meter = dynamic_cast<Meter*>(&control)) != 0) {
- _meter = meter;
}
}
@@ -385,14 +361,13 @@ Strip::handle_button (Button& button, ButtonState bs)
button.set_in_use (false);
}
- DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.id(), (bs == press)));
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
int lock_mod = (MackieControlProtocol::MODIFIER_CONTROL|MackieControlProtocol::MODIFIER_SHIFT);
int ms = _surface->mcp().modifier_state();
bool modified = (ms & MackieControlProtocol::MODIFIER_CONTROL);
- if (button.id() >= Button::select_base_id &&
- button.id() < Button::select_base_id + 8) {
+ if (button.bid() == Button::Select) {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("select touch, lock ? %1\n", ((ms & lock_mod) == lock_mod) ? 1 : 0));
@@ -415,9 +390,8 @@ Strip::handle_button (Button& button, ButtonState bs)
return;
}
-
- if ((button.id() >= Button::fader_touch_base_id &&
- button.id() < Button::fader_touch_base_id + 8)) {
+
+ if (button.bid() == Button::FaderTouch) {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
diff --git a/libs/surfaces/mackie/strip.h b/libs/surfaces/mackie/strip.h
index 2324f84447..56c6a2f720 100644
--- a/libs/surfaces/mackie/strip.h
+++ b/libs/surfaces/mackie/strip.h
@@ -13,6 +13,7 @@
#include "control_group.h"
#include "types.h"
#include "midi_byte_array.h"
+#include "device_info.h"
namespace ARDOUR {
class Route;
@@ -47,7 +48,7 @@ struct GlobalControlDefinition {
class Strip : public Group
{
public:
- Strip (Surface&, const std::string & name, int index, StripControlDefinition* ctls);
+ Strip (Surface&, const std::string & name, int index, const std::map<Button::ID,StripButtonInfo>&);
~Strip();
boost::shared_ptr<ARDOUR::Route> route() const { return _route; }
diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc
index 2f87b844f0..6d47393f60 100644
--- a/libs/surfaces/mackie/surface.cc
+++ b/libs/surfaces/mackie/surface.cc
@@ -50,81 +50,6 @@ static MidiByteArray mackie_sysex_hdr_xt (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x15)
static MidiByteArray empty_midi_byte_array;
-static GlobalControlDefinition mackie_global_controls[] = {
- { "jog", 0x3c, Jog::factory, "none" },
- { "external", 0x2e, Pot::factory, "none" },
- { "io", 0x28, Button::factory, "assignment" },
- { "sends", 0x29, Button::factory, "assignment" },
- { "pan", 0x2a, Button::factory, "assignment" },
- { "plugin", 0x2b, Button::factory, "assignment" },
- { "eq", 0x2c, Button::factory, "assignment" },
- { "dyn", 0x2d, Button::factory, "assignment" },
- { "left", 0x2e, Button::factory, "bank" },
- { "right", 0x2f, Button::factory, "bank" },
- { "channel_left", 0x30, Button::factory, "bank" },
- { "channel_right", 0x31, Button::factory, "bank" },
- { "flip", 0x32, Button::factory, "none" },
- { "edit", 0x33, Button::factory, "none" },
- { "name_value", 0x34, Button::factory, "display" },
- { "timecode_beats", 0x35, Button::factory, "display" },
- { "F1", Button::F1, Button::factory, "none" },
- { "F2", Button::F2, Button::factory, "none" },
- { "F3", Button::F3, Button::factory, "none" },
- { "F4", Button::F4, Button::factory, "none" },
- { "F5", Button::F5, Button::factory, "none" },
- { "F6", Button::F6, Button::factory, "none" },
- { "F7", Button::F7, Button::factory, "none" },
- { "F8", Button::F8, Button::factory, "none" },
- { "F9", Button::F9, Button::factory, "none" },
- { "F10", Button::F10, Button::factory, "none" },
- { "F11", Button::F11, Button::factory, "none" },
- { "F12", Button::F12, Button::factory, "none" },
- { "F13", Button::F13, Button::factory, "none" },
- { "F14", Button::F14, Button::factory, "none" },
- { "F15", Button::F15, Button::factory, "none" },
- { "F16", Button::F16, Button::factory, "none" },
- { "shift", 0x46, Button::factory, "modifiers" },
- { "option", 0x47, Button::factory, "modifiers" },
- { "control", 0x48, Button::factory, "modifiers" },
- { "cmd_alt", 0x49, Button::factory, "modifiers" },
- { "on", 0x4a, Button::factory, "automation" },
- { "rec_ready", 0x4b, Button::factory, "automation" },
- { "undo", 0x4c, Button::factory, "functions" },
- { "save", Button::Save, Button::factory, "automation" },
- { "touch", Button::Touch, Button::factory, "automation" },
- { "redo", Button::Redo, Button::factory, "functions" },
- { "marker", Button::Marker, Button::factory, "functions" },
- { "enter", Button::Enter, Button::factory, "functions" },
- { "cancel", Button::Cancel, Button::factory, "functions" },
- { "mixer", Button::Mixer, Button::factory, "functions" },
- { "frm_left", 0x54, Button::factory, "transport" },
- { "frm_right", 0x55, Button::factory, "transport" },
- { "loop", Button::Loop, Button::factory, "transport" },
- { "punch_in", 0x57, Button::factory, "transport" },
- { "punch_out", 0x58, Button::factory, "transport" },
- { "home", Button::Home, Button::factory, "transport" },
- { "end", Button::End, Button::factory, "transport" },
- { "rewind", Button::Rewind, Button::factory, "transport" },
- { "ffwd", Button::Ffwd, Button::factory, "transport" },
- { "stop", Button::Stop, Button::factory, "transport" },
- { "play", Button::Play, Button::factory, "transport" },
- { "record", Button::Record, Button::factory, "transport" },
- { "cursor_up", Button::CursorUp, Button::factory, "cursor" },
- { "cursor_down", Button::CursorDown, Button::factory, "cursor" },
- { "cursor_left", Button::CursorLeft, Button::factory, "cursor" },
- { "cursor_right", Button::CursorRight, Button::factory, "cursor" },
- { "zoom", Button::Zoom, Button::factory, "none" },
- { "scrub", Button::Scrub, Button::factory, "none" },
- { "user_a", Button::UserA, Button::factory, "user" },
- { "user_b", Button::UserB, Button::factory, "user" },
- { "fader_touch", 0x70, Led::factory, "master" },
- { "timecode", 0x71, Led::factory, "none" },
- { "beats", 0x72, Led::factory, "none" },
- { "solo", 0x73, Led::factory, "none" },
- { "relay_click", 0x73, Led::factory, "none" },
- { "", 0, Button::factory, "" }
-};
-
Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, uint32_t number, surface_type_t stype)
: _mcp (mcp)
, _stype (stype)
@@ -138,12 +63,12 @@ Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, ui
_port = new SurfacePort (*this);
- if (_mcp.device_info().has_global_controls()) {
- init_controls ();
- }
+ /* only the first Surface object has global controls */
- if (_mcp.device_info().has_jog_wheel()) {
- _jog_wheel = new Mackie::JogWheel (_mcp);
+ if (_number == 0) {
+ if (_mcp.device_info().has_global_controls()) {
+ init_controls ();
+ }
}
uint32_t n = _mcp.device_info().strip_cnt();
@@ -204,6 +129,16 @@ Surface::sysex_hdr() const
return mackie_sysex_hdr;
}
+static GlobalControlDefinition mackie_global_controls[] = {
+ { "external", Pot::External, Pot::factory, "none" },
+ { "fader_touch", Led::FaderTouch, Led::factory, "master" },
+ { "timecode", Led::Timecode, Led::factory, "none" },
+ { "beats", Led::Beats, Led::factory, "none" },
+ { "solo", Led::RudeSolo, Led::factory, "none" },
+ { "relay_click", Led::RelayClick, Led::factory, "none" },
+ { "", 0, Led::factory, "" }
+};
+
void
Surface::init_controls()
{
@@ -220,38 +155,39 @@ Surface::init_controls()
groups["transport"] = new Group ("transport");
groups["user"] = new Group ("user");
groups["master"] = new Group ("master");
+
+ if (_mcp.device_info().has_jog_wheel()) {
+ _jog_wheel = new Mackie::JogWheel (_mcp);
+ }
for (uint32_t n = 0; mackie_global_controls[n].name[0]; ++n) {
group = groups[mackie_global_controls[n].group_name];
Control* control = mackie_global_controls[n].factory (*this, mackie_global_controls[n].id, mackie_global_controls[n].name, *group);
- controls_by_name[mackie_global_controls[n].name] = control;
- group->add (*control);
- }
-}
-
-static StripControlDefinition mackie_strip_controls[] = {
- { "gain", 0, Fader::factory, },
- { "vpot", Pot::base_id, Pot::factory, },
- { "recenable", Button::recenable_base_id, Button::factory, },
- { "solo", Button::solo_base_id, Button::factory, },
- { "mute", Button::mute_base_id, Button::factory, },
- { "select", Button::select_base_id, Button::factory, },
- { "vselect", Button::vselect_base_id, Button::factory, },
- { "fader_touch", Button::fader_touch_base_id, Button::factory, },
- { "meter", 0, Meter::factory, },
- { "", 0, Button::factory, }
-};
+ controls_by_device_independent_id[mackie_global_controls[n].id] = control;
+ }
+
+ /* add global buttons */
+
+ const map<Button::ID,GlobalButtonInfo>& global_buttons (_mcp.device_info().global_buttons());
+
+ for (map<Button::ID,GlobalButtonInfo>::const_iterator b = global_buttons.begin(); b != global_buttons.end(); ++b){
+ group = groups[b->second.group];
+ controls_by_device_independent_id[b->first] = Button::factory (*this, b->first, b->second.id, b->second.label, *group);
+ }
+}
void
Surface::init_strips (uint32_t n)
{
+ const map<Button::ID,StripButtonInfo>& strip_buttons (_mcp.device_info().strip_buttons());
+
for (uint32_t i = 0; i < n; ++i) {
char name[32];
snprintf (name, sizeof (name), "strip_%d", (8* _number) + i);
- Strip* strip = new Strip (*this, name, i, mackie_strip_controls);
+ Strip* strip = new Strip (*this, name, i, strip_buttons);
groups[name] = strip;
strips.push_back (strip);
@@ -280,7 +216,7 @@ Surface::display_bank_start (uint32_t current_bank)
void
Surface::blank_jog_ring ()
{
- Control* control = controls_by_name["jog"];
+ Control* control = controls_by_device_independent_id[Jog::ID];
if (control) {
Pot* pot = dynamic_cast<Pot*> (control);
@@ -395,10 +331,6 @@ Surface::handle_midi_controller_message (MIDI::Parser &, MIDI::EventTwoBytes* ev
Pot* pot = pots[ev->controller_number];
- if (!pot && ev->controller_number == Jog::base_id) {
- pot = dynamic_cast<Pot*> (controls_by_name["jog"]);
- }
-
if (pot) {
ControlState state;
diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h
index 6bdb575847..5bcd9ebde9 100644
--- a/libs/surfaces/mackie/surface.h
+++ b/libs/surfaces/mackie/surface.h
@@ -53,13 +53,10 @@ public:
std::map<int,Fader*> faders;
std::map<int,Pot*> pots;
- std::map<int,Button*> buttons;
+ std::map<int,Button*> buttons; // index is device-DEPENDENT
std::map<int,Led*> leds;
std::map<int,Meter*> meters;
-
- /// no strip controls in here because they usually
- /// have the same names.
- std::map<std::string,Control*> controls_by_name;
+ std::map<int,Control*> controls_by_device_independent_id;
Mackie::JogWheel* jog_wheel() const { return _jog_wheel; }
diff --git a/libs/surfaces/mackie/wscript b/libs/surfaces/mackie/wscript
index d21c9d9aef..ed573ab798 100644
--- a/libs/surfaces/mackie/wscript
+++ b/libs/surfaces/mackie/wscript
@@ -27,6 +27,7 @@ def build(bld):
fader.cc
gui.cc
interface.cc
+ jog.cc
led.cc
mackie_control_protocol.cc
mackie_jog_wheel.cc
diff --git a/mcp_devices/nucleus.xml b/mcp_devices/nucleus.xml
index 5d38ddfec9..d03ad558fc 100644
--- a/mcp_devices/nucleus.xml
+++ b/mcp_devices/nucleus.xml
@@ -2,12 +2,20 @@
<MackieProtocolDevice>
<Name value="SSL Nucleus"/>
<Strips value="8"/>
+ <Extenders value="1"/>
<MasterFader value="no"/>
<SegmentedDisplay value="yes"/>
<TimecodeDisplay value="no"/>
<TwoCharacterDisplay value="yes"/>
- <Extenders value="1"/>
<GlobalControls value="yes"/>
- <JogWheel value="no"/>
+ <JogWheel value="yes"/>
<TouchSenseFaders value="yes"/>
+ <SendsModifiers value="0x3"/>
+ <Quirks>
+ <ButtonOffNonZero/>
+ </Quirks>
+ <Buttons>
+ <GlobalButton name="Marker" id="0x48" label="instrument"/>
+ <StripButton name="FaderTouch" baseid="0x68"/>
+ </Buttons>
</MackieProtocolDevice>