MCP: redesign to allow device-specific button IDs, since we know that at least one...
authorPaul Davis <paul@linuxaudiosystems.com>
Sat, 14 Apr 2012 19:02:54 +0000 (19:02 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sat, 14 Apr 2012 19:02:54 +0000 (19:02 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@11972 d708f5d6-7413-0410-9779-e7cbd77b26cf

21 files changed:
libs/surfaces/mackie/button.cc
libs/surfaces/mackie/button.h
libs/surfaces/mackie/controls.cc
libs/surfaces/mackie/controls.h
libs/surfaces/mackie/device_info.cc
libs/surfaces/mackie/device_info.h
libs/surfaces/mackie/fader.h
libs/surfaces/mackie/jog.cc [new file with mode: 0644]
libs/surfaces/mackie/jog.h
libs/surfaces/mackie/led.cc
libs/surfaces/mackie/led.h
libs/surfaces/mackie/mackie_control_protocol.cc
libs/surfaces/mackie/mackie_control_protocol.h
libs/surfaces/mackie/pot.cc
libs/surfaces/mackie/pot.h
libs/surfaces/mackie/strip.cc
libs/surfaces/mackie/strip.h
libs/surfaces/mackie/surface.cc
libs/surfaces/mackie/surface.h
libs/surfaces/mackie/wscript
mcp_devices/nucleus.xml

index 714294ed7d51ce7be8a7c188664358e0404dcc6a..588c11d984b8dfa2166e8c34b1e657f3c5ebdfa2 100644 (file)
 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;
+}
index 270245275076abac34f161586b91c7fc319272ef..48ea9c591935fa4d1cb94ad1705935d62ff5fadf 100644 (file)
@@ -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;
 };
 
index 0e95d6ee955c76f8db049f72800188243131583f..24b59fd744a58f4a7d8b086533e4b248104fdc2c 100644 (file)
@@ -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)
 {
index 8538cace8892f77e684467b65c1ffb2e2061ab32..eb9a69197291f21957c05019838573ba3b23bba0 100644 (file)
@@ -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;
index 9b15baf208db6930f2ff729a10f045c3114201ed..1ec9c2e78838dc0e3959ee72687916ff67800f7e 100644 (file)
@@ -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;
 }
index 191ccfc4ce2229f5bb387f16f5ffd5013bdf7e0c..9ca51cae719b5a466e11fc9e8ea6750dbcfac0f5 100644 (file)
 #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
index 3520699e985437a273db763b3ca8269edc988537..ed8e72eb50a5aa0beb59ee2c4e50177e819eae27 100644 (file)
@@ -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 (file)
index 0000000..dc83286
--- /dev/null
@@ -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;
+}
index a4a6b739dedef7e2b1615f641c66a1a647ea959f..23451f92b2ec0a32757be3ef67a95ab9abaff832 100644 (file)
@@ -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)
index 342db049a5605954c432b4cc5871d63a90b17629..38aa5c7f3b62ac470d88abf250d1828d51a7c988 100644 (file)
 
 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)
 {
index fca9b78a43f680f188fe15740a72784a39c7dac5..fdbeb8cd9cd061d1355455206eb588ff1ce4b679 100644 (file)
@@ -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)
index 7aa78d8c02247711f8769612704a78f2ef073985..3f98e98ac93fdee42f71bf87ed8c352a2eb48648 100644 (file)
@@ -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()) {
 
index 83b77bd7f2b3587171fa76012a2a1529c56abfd4..c4cda58c266446bb43867c0cb902ae9f54190bed 100644 (file)
@@ -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;
index 1320512e928e818c8a5554483a317355447339e0..0b3062be8c20700eb8e23cf2548fbee596665ed7 100644 (file)
@@ -24,6 +24,8 @@
 
 using namespace Mackie;
 
+int const Pot::External = 0x2e;
+
 Control*
 Pot::factory (Surface& surface, int id, const char* name, Group& group)
 {
index e8a6b0dc4324445a7b76be47626132ad1dad6134..5aa4f297d1a6a117847241a913141ddcb68afe8a 100644 (file)
@@ -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,
index dc7a15fe6a2a87f765697a97619ea4a1dbca69dd..2d65b663ca672cde35cbadb8286f3ef59081e35a 100644 (file)
@@ -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)));
 
index 2324f84447c2b7e62adb9c5f409451e48412fab1..56c6a2f720ab70516a97c0c9a22ff01662e6293b 100644 (file)
@@ -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; }
index 2f87b844f085aaeeef56b092ff0e86ef5527e474..6d47393f601685a14a1d11b93e8273f105a43448 100644 (file)
@@ -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;
                
index 6bdb5758477fba2794bc1e85b4058f1fdf8f437d..5bcd9ebde92eb1f9186ab52ae545e59dde5d0b31 100644 (file)
@@ -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; }
 
index d21c9d9aef8a15a41447945dd008b682b2fb2b2b..ed573ab79882ec8ced8ec28f797d84509b54b46a 100644 (file)
@@ -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
index 5d38ddfec90cbfb8008f4544b862530d95960f37..d03ad558fc861b7c5942717d16882a1c16b22d76 100644 (file)
@@ -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>