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
This commit is contained in:
parent
32766ce215
commit
2ed2b61224
@ -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;
|
||||
}
|
||||
|
@ -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 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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -20,7 +20,7 @@ class Fader : public Control
|
||||
MidiByteArray update_message ();
|
||||
|
||||
static Control* factory (Surface&, int id, const char*, Group&);
|
||||
|
||||
|
||||
private:
|
||||
float position;
|
||||
};
|
||||
|
36
libs/surfaces/mackie/jog.cc
Normal file
36
libs/surfaces/mackie/jog.cc
Normal file
@ -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;
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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 ()
|
||||
{
|
||||
boost::shared_ptr<Surface> surface = surfaces.front();
|
||||
|
||||
/* rec is a tristate */
|
||||
|
||||
|
||||
Button * rec = reinterpret_cast<Button*> (surfaces.front()->controls_by_name["record"]);
|
||||
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;
|
||||
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()) {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
using namespace Mackie;
|
||||
|
||||
int const Pot::External = 0x2e;
|
||||
|
||||
Control*
|
||||
Pot::factory (Surface& surface, int id, const char* name, Group& group)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
Button* button;
|
||||
|
||||
Group::add (control);
|
||||
|
||||
Fader* fader;
|
||||
Pot* pot;
|
||||
Button* button;
|
||||
Meter* meter;
|
||||
/* fader, vpot, meter were all set explicitly */
|
||||
|
||||
if ((fader = dynamic_cast<Fader*>(&control)) != 0) {
|
||||
|
||||
_fader = fader;
|
||||
|
||||
} else if ((pot = dynamic_cast<Pot*>(&control)) != 0) {
|
||||
|
||||
_vpot = pot;
|
||||
|
||||
} else if ((button = dynamic_cast<Button*>(&control)) != 0) {
|
||||
|
||||
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)));
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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, }
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user