MCP: dynamic ipMIDI ports, more default key bindings, various minor fixes

git-svn-id: svn://localhost/ardour2/branches/3.0@12092 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2012-04-25 21:21:36 +00:00
parent 40d57d1c1e
commit 2bae75fa0b
13 changed files with 148 additions and 74 deletions

View file

@ -50,8 +50,6 @@ CONFIG_VARIABLE (bool, first_midi_bank_is_zero, "diplay-first-midi-bank-as-zero"
CONFIG_VARIABLE (uint32_t, feedback_interval_ms, "feedback-interval-ms", 100) CONFIG_VARIABLE (uint32_t, feedback_interval_ms, "feedback-interval-ms", 100)
CONFIG_VARIABLE (bool, use_tranzport, "use-tranzport", false) CONFIG_VARIABLE (bool, use_tranzport, "use-tranzport", false)
CONFIG_VARIABLE (std::string, mackie_device_name, "mackie-device-name", "Mackie Control Universal Pro")
CONFIG_VARIABLE (std::string, mackie_device_profile, "mackie-device-profile", "default")
CONFIG_VARIABLE (RemoteModel, remote_model, "remote-model", MixerOrdered) CONFIG_VARIABLE (RemoteModel, remote_model, "remote-model", MixerOrdered)
/* disk operations */ /* disk operations */

View file

@ -75,8 +75,16 @@ ControlProtocolManager::set_session (Session* s)
instantiate (**i); instantiate (**i);
(*i)->requested = false; (*i)->requested = false;
if ((*i)->protocol && (*i)->state) { if ((*i)->protocol) {
(*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version); if ((*i)->state) {
(*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
} else {
/* guarantee a call to
set_state() whether we have
existing state or not
*/
(*i)->protocol->set_state (XMLNode(""), Stateful::loading_state_version);
}
} }
} }
} }

View file

@ -134,8 +134,6 @@ MidiControlUI::reset_ports ()
for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) { for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) {
cerr << "MIDI UI looking at port " << (*i)->name() << endl;
if (!(*i)->centrally_parsed()) { if (!(*i)->centrally_parsed()) {
continue; continue;
} }

View file

@ -51,8 +51,8 @@ Button::name_to_id (const std::string& name)
if (!g_strcasecmp (name.c_str(), "ChannelRight")) { return ChannelRight; } if (!g_strcasecmp (name.c_str(), "ChannelRight")) { return ChannelRight; }
if (!g_strcasecmp (name.c_str(), "Flip")) { return Flip; } if (!g_strcasecmp (name.c_str(), "Flip")) { return Flip; }
if (!g_strcasecmp (name.c_str(), "Edit")) { return Edit; } if (!g_strcasecmp (name.c_str(), "Edit")) { return Edit; }
if (!g_strcasecmp (name.c_str(), "NameValue")) { return NameValue; } if (!g_strcasecmp (name.c_str(), "Name/Value")) { return NameValue; }
if (!g_strcasecmp (name.c_str(), "TimecodeBeats")) { return TimecodeBeats; } if (!g_strcasecmp (name.c_str(), "Timecode/Beats")) { return TimecodeBeats; }
if (!g_strcasecmp (name.c_str(), "F1")) { return F1; } if (!g_strcasecmp (name.c_str(), "F1")) { return F1; }
if (!g_strcasecmp (name.c_str(), "F2")) { return F2; } if (!g_strcasecmp (name.c_str(), "F2")) { return F2; }
if (!g_strcasecmp (name.c_str(), "F3")) { return F3; } if (!g_strcasecmp (name.c_str(), "F3")) { return F3; }

View file

@ -209,12 +209,16 @@ DeviceInfo::set_state (const XMLNode& node, int /* version */)
} }
} }
/* strip count is mandatory */
if ((child = node.child ("Strips")) != 0) { if ((child = node.child ("Strips")) != 0) {
if ((prop = child->property ("value")) != 0) { if ((prop = child->property ("value")) != 0) {
if ((_strip_cnt = atoi (prop->value())) == 0) { if ((_strip_cnt = atoi (prop->value())) == 0) {
_strip_cnt = 8; _strip_cnt = 8;
} }
} }
} else {
return -1;
} }
if ((child = node.child ("Extenders")) != 0) { if ((child = node.child ("Extenders")) != 0) {

View file

@ -107,13 +107,11 @@ DeviceProfile::reload_device_profiles ()
if (!devprofiles) { if (!devprofiles) {
error << "No MCP device info files found using " << spath.to_string() << endmsg; error << "No MCP device info files found using " << spath.to_string() << endmsg;
std::cerr << "No MCP device info files found using " << spath.to_string() << std::endl;
return; return;
} }
if (devprofiles->empty()) { if (devprofiles->empty()) {
error << "No MCP device info files found using " << spath.to_string() << endmsg; error << "No MCP device info files found using " << spath.to_string() << endmsg;
std::cerr << "No MCP device info files found using " << spath.to_string() << std::endl;
return; return;
} }
@ -288,7 +286,7 @@ DeviceProfile::set_button_action (Button::ID id, int modifier_state, const strin
ButtonActionMap::iterator i = _button_map.find (id); ButtonActionMap::iterator i = _button_map.find (id);
if (i == _button_map.end()) { if (i == _button_map.end()) {
return; i = _button_map.insert (std::make_pair (id, ButtonActions())).first;
} }
string action (act); string action (act);
@ -360,6 +358,7 @@ DeviceProfile::save ()
XMLTree tree; XMLTree tree;
tree.set_root (&get_state()); tree.set_root (&get_state());
if (!tree.write (fullpath.to_string())) { if (!tree.write (fullpath.to_string())) {
error << string_compose ("MCP profile not saved to %1", fullpath.to_string()) << endmsg; error << string_compose ("MCP profile not saved to %1", fullpath.to_string()) << endmsg;
} }

View file

@ -72,7 +72,7 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
, touch_sensitivity_adjustment (0, 0, 9, 1, 4) , touch_sensitivity_adjustment (0, 0, 9, 1, 4)
, touch_sensitivity_scale (touch_sensitivity_adjustment) , touch_sensitivity_scale (touch_sensitivity_adjustment)
, recalibrate_fader_button (_("Recalibrate Faders")) , recalibrate_fader_button (_("Recalibrate Faders"))
, ipmidi_base_port_adjustment (21928, 0, 32767, 1, 1000) , ipmidi_base_port_adjustment (_cp.ipmidi_base(), 0, 32767, 1, 1000)
, ipmidi_base_port_spinner (ipmidi_base_port_adjustment) , ipmidi_base_port_spinner (ipmidi_base_port_adjustment)
{ {
Gtk::Label* l; Gtk::Label* l;
@ -141,6 +141,7 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
table->attach (ipmidi_base_port_spinner, 1, 2, 7, 8, AttachOptions(FILL|EXPAND), AttachOptions (0)); table->attach (ipmidi_base_port_spinner, 1, 2, 7, 8, AttachOptions(FILL|EXPAND), AttachOptions (0));
ipmidi_base_port_spinner.set_sensitive (_cp.device_info().uses_ipmidi()); ipmidi_base_port_spinner.set_sensitive (_cp.device_info().uses_ipmidi());
ipmidi_base_port_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::ipmidi_spinner_changed));
vector<string> profiles; vector<string> profiles;
@ -344,7 +345,7 @@ MackieControlProtocolGUI::refresh_function_key_editor ()
Glib::RefPtr<Gtk::Action> act; Glib::RefPtr<Gtk::Action> act;
string action; string action;
const string defstring = "def"; const string defstring = "\u2022";
action = dp.get_button_action (bid, 0); action = dp.get_button_action (bid, 0);
if (action.empty()) { if (action.empty()) {
@ -432,12 +433,12 @@ MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const Glib
std::map<std::string,std::string>::iterator i = action_map.find (text); std::map<std::string,std::string>::iterator i = action_map.find (text);
cerr << "Changed to " << text << endl;
if (i == action_map.end()) { if (i == action_map.end()) {
return; return;
} }
cerr << "Changed to " << i->first << " aka " << i->second << endl;
Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (i->second.c_str()); Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (i->second.c_str());
if (act) { if (act) {
@ -474,8 +475,9 @@ MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const Glib
} }
_cp.device_profile().set_button_action ((*row)[function_key_columns.id], modifier, i->second); _cp.device_profile().set_button_action ((*row)[function_key_columns.id], modifier, i->second);
} else {
std::cerr << "no such action\n";
} }
} }
} }
@ -497,7 +499,13 @@ MackieControlProtocolGUI::profile_combo_changed ()
string profile = _profile_combo.get_active_text(); string profile = _profile_combo.get_active_text();
_cp.set_profile (profile); _cp.set_profile (profile);
ARDOUR::Config->set_mackie_device_profile (profile);
refresh_function_key_editor (); refresh_function_key_editor ();
} }
void
MackieControlProtocolGUI::ipmidi_spinner_changed ()
{
cerr << "Set IP MIDI base to " << ipmidi_base_port_spinner.get_value() << endl;
_cp.set_ipmidi_base ((int16_t) lrintf (ipmidi_base_port_spinner.get_value()));
}

View file

@ -92,6 +92,7 @@ class MackieControlProtocolGUI : public Gtk::Notebook
void surface_combo_changed (); void surface_combo_changed ();
void profile_combo_changed (); void profile_combo_changed ();
void ipmidi_spinner_changed ();
std::map<std::string,std::string> action_map; // map from action names to paths std::map<std::string,std::string> action_map; // map from action names to paths

View file

@ -36,7 +36,7 @@ new_mackie_protocol (ControlProtocolDescriptor*, Session* s)
try { try {
mcp = new MackieControlProtocol (*s); mcp = new MackieControlProtocol (*s);
mcp->set_active (true); /* do not set active here - wait for set_state() */
} }
catch (exception & e) { catch (exception & e) {
error << "Error instantiating MackieControlProtocol: " << e.what() << endmsg; error << "Error instantiating MackieControlProtocol: " << e.what() << endmsg;

View file

@ -35,6 +35,7 @@
#include "midi++/types.h" #include "midi++/types.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/ipmidi_port.h"
#include "pbd/pthread_utils.h" #include "pbd/pthread_utils.h"
#include "pbd/error.h" #include "pbd/error.h"
#include "pbd/memento_command.h" #include "pbd/memento_command.h"
@ -104,15 +105,14 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
, _view_mode (Mixer) , _view_mode (Mixer)
, _current_selected_track (-1) , _current_selected_track (-1)
, _modifier_state (0) , _modifier_state (0)
, _ipmidi_base (MIDI::IPMIDIPort::lowest_ipmidi_port_default)
, needs_ipmidi_restart (false)
{ {
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n"); DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
DeviceInfo::reload_device_info (); DeviceInfo::reload_device_info ();
DeviceProfile::reload_device_profiles (); DeviceProfile::reload_device_profiles ();
set_device (Config->get_mackie_device_name());
set_profile (Config->get_mackie_device_profile());
TrackSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::gui_track_selection_changed, this, _1), this); TrackSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::gui_track_selection_changed, this, _1), this);
_instance = this; _instance = this;
@ -353,37 +353,30 @@ MackieControlProtocol::set_active (bool yn)
return 0; return 0;
} }
try if (yn) {
{
if (yn) { /* start event loop */
BaseUI::run ();
create_surfaces ();
connect_session_signals ();
_active = true;
update_surfaces ();
/* set up periodic task for metering and automation
*/
Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
periodic_timeout->attach (main_loop()->get_context());
} else {
/* start event loop */ BaseUI::quit ();
close ();
BaseUI::run ();
create_surfaces ();
connect_session_signals ();
_active = true;
update_surfaces ();
/* set up periodic task for metering and automation
*/
Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
periodic_timeout->attach (main_loop()->get_context());
} else {
BaseUI::quit ();
close();
_active = false;
}
}
catch (exception & e) {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set_active to false because exception caught: %1\n", e.what()));
_active = false; _active = false;
throw;
} }
return 0; return 0;
@ -396,6 +389,11 @@ MackieControlProtocol::periodic ()
return false; return false;
} }
if (needs_ipmidi_restart) {
ipmidi_restart ();
return true;
}
struct timeval now; struct timeval now;
uint64_t now_usecs; uint64_t now_usecs;
gettimeofday (&now, 0); gettimeofday (&now, 0);
@ -475,8 +473,6 @@ MackieControlProtocol::update_surfaces()
return; return;
} }
// do the initial bank switch to connect signals // do the initial bank switch to connect signals
// _current_initial_bank is initialised by set_state // _current_initial_bank is initialised by set_state
switch_banks (_current_initial_bank, true); switch_banks (_current_initial_bank, true);
@ -549,10 +545,6 @@ MackieControlProtocol::set_device (const string& device_name)
_device_info = d->second; _device_info = d->second;
/* store it away in a global location */
Config->set_mackie_device_name (device_name);
if (_active) { if (_active) {
create_surfaces (); create_surfaces ();
switch_banks (0, true); switch_banks (0, true);
@ -637,15 +629,22 @@ XMLNode&
MackieControlProtocol::get_state() MackieControlProtocol::get_state()
{ {
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state\n"); DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state\n");
char buf[16];
// add name of protocol // add name of protocol
XMLNode* node = new XMLNode (X_("Protocol")); XMLNode* node = new XMLNode (X_("Protocol"));
node->add_property (X_("name"), ARDOUR::ControlProtocol::_name); node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
// add current bank // add current bank
ostringstream os; snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
os << _current_initial_bank; node->add_property (X_("bank"), buf);
node->add_property (X_("bank"), os.str());
// ipMIDI base port (possibly not used)
snprintf (buf, sizeof (buf), "%d", _ipmidi_base);
node->add_property (X_("ipmidi-base"), buf);
node->add_property (X_("device-profile"), _device_profile.name());
node->add_property (X_("device-name"), _device_info.name());
return *node; return *node;
} }
@ -657,15 +656,34 @@ MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
int retval = 0; int retval = 0;
const XMLProperty* prop; const XMLProperty* prop;
uint32_t bank;
bool active = _active;
if ((prop = node.property (X_("ipmidi-base"))) != 0) {
set_ipmidi_base (atoi (prop->value()));
}
// fetch current bank // fetch current bank
if ((prop = node.property (X_("bank"))) != 0) { if ((prop = node.property (X_("bank"))) != 0) {
string bank = prop->value(); bank = atoi (prop->value());
set_active (true); }
uint32_t new_bank = atoi (bank.c_str());
if (_current_initial_bank != new_bank) { if ((prop = node.property (X_("active"))) != 0) {
switch_banks (new_bank); active = string_is_affirmative (prop->value());
} }
if ((prop = node.property (X_("device-name"))) != 0) {
set_device (prop->value());
}
if ((prop = node.property (X_("device-profile"))) != 0) {
set_profile (prop->value());
}
set_active (active);
if (_active) {
switch_banks (bank, true);
} }
return retval; return retval;
@ -1166,8 +1184,6 @@ MackieControlProtocol::force_special_route_to_strip (boost::shared_ptr<Route> r,
void void
MackieControlProtocol::gui_track_selection_changed (ARDOUR::RouteNotificationListPtr rl) MackieControlProtocol::gui_track_selection_changed (ARDOUR::RouteNotificationListPtr rl)
{ {
cerr << "GUI Selection changed, " << rl->size() << " routes\n";
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
(*s)->gui_selection_changed (rl); (*s)->gui_selection_changed (rl);
} }
@ -1366,3 +1382,31 @@ MackieControlProtocol::pull_route_range (DownButtonList& down, RouteList& select
} }
} }
} }
void
MackieControlProtocol::set_ipmidi_base (int16_t portnum)
{
/* this will not be saved without a session save, so .. */
session->set_dirty ();
_ipmidi_base = portnum;
/* if the current device uses ipMIDI we need
to restart.
*/
if (_active && _device_info.uses_ipmidi()) {
needs_ipmidi_restart = true;
}
}
void
MackieControlProtocol::ipmidi_restart ()
{
clear_ports ();
surfaces.clear ();
create_surfaces ();
switch_banks (_current_initial_bank, true);
needs_ipmidi_restart = false;
}

View file

@ -192,6 +192,9 @@ class MackieControlProtocol
void add_down_select_button (int surface, int strip); void add_down_select_button (int surface, int strip);
void remove_down_select_button (int surface, int strip); void remove_down_select_button (int surface, int strip);
void select_range (); void select_range ();
int16_t ipmidi_base() const { return _ipmidi_base; }
void set_ipmidi_base (int16_t);
protected: protected:
// shut down the surface // shut down the surface
@ -278,6 +281,8 @@ class MackieControlProtocol
int _modifier_state; int _modifier_state;
PortSources port_sources; PortSources port_sources;
ButtonMap button_map; ButtonMap button_map;
int16_t _ipmidi_base;
bool needs_ipmidi_restart;
void create_surfaces (); void create_surfaces ();
bool periodic(); bool periodic();
@ -286,10 +291,9 @@ class MackieControlProtocol
void clear_ports (); void clear_ports ();
void force_special_route_to_strip (boost::shared_ptr<ARDOUR::Route> r, uint32_t surface, uint32_t strip_number); void force_special_route_to_strip (boost::shared_ptr<ARDOUR::Route> r, uint32_t surface, uint32_t strip_number);
void build_button_map (); void build_button_map ();
void gui_track_selection_changed (ARDOUR::RouteNotificationListPtr); void gui_track_selection_changed (ARDOUR::RouteNotificationListPtr);
void ipmidi_restart ();
/* BUTTON HANDLING */ /* BUTTON HANDLING */
typedef std::set<uint32_t> DownButtonList; typedef std::set<uint32_t> DownButtonList;

View file

@ -56,7 +56,7 @@ SurfacePort::SurfacePort (Surface& s)
, _output_port (0) , _output_port (0)
{ {
if (_surface->mcp().device_info().uses_ipmidi()) { if (_surface->mcp().device_info().uses_ipmidi()) {
_input_port = new MIDI::IPMIDIPort (MIDI::IPMIDIPort::lowest_ipmidi_port_default+_surface->number()); _input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
_output_port = _input_port; _output_port = _input_port;
} else { } else {
jack_client_t* jack = MackieControlProtocol::instance()->get_session().engine().jack(); jack_client_t* jack = MackieControlProtocol::instance()->get_session().engine().jack();

View file

@ -1,9 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MackieDeviceProfile> <MackieDeviceProfile>
<Name value="Basic SSL Nucleus"/> <Name value="Basic SSL Nucleus"/>
<MasterOn value="14"/>
<MonitorOn value="15"/>
<Buttons> <Buttons>
<Button name="f1" plain="Editor/goto-visual-state-1"/> <Button name="Name/Value" shift="Transport/ToggleExternalSync"/>
<Button name="F1" plain="MouseMode/set-mouse-mode-object" shift="Transport/GotoStart" cmdalt="options/SendMidiClock"/>
<Button name="F2" plain="MouseMode/set-mouse-mode-range" shift="Transport/ToggleExternalSync"/>
<Button name="F3" plain="Transport/ToggleClick" control="Transport/ToggleAutoReturn" shift="Transport/ToggleAutoPlay"/>
<Button name="F4" plain="Transport/TogglePunch" control="Transport/TogglePunchOut" shift="Transport/TogglePunchIn" option="Transport/ToggleExternalSync"/>
<Button name="F5" plain="Zoom/zoom-focus-center" control="Zoom/zoom-focus-mouse" shift="Zoom/zoom-focus-left" option="Zoom/zoom-focus-playhead" cmdalt="Zoom/zoom-focus-right" shiftcontrol="Zoom/zoom-focus-edit"/>
<Button name="F6" plain="Common/toggle-audio-connection-manager" control="Common/ToggleBigClock" shift="Common/toggle-midi-connection-manager" option="Common/toggle-mixer-on-top"/>
<Button name="F7" plain="Transport/ToggleExternalSync"/>
<Button name="F8" plain="Editor/cycle-snap-mode" control="Editor/prev-snap-choice" shift="Editor/next-snap-choice" option="Editor/prev-snap-choice"/>
<Button name="Marker" plain="Editor/jump-forward-to-mark"/>
<Button name="Loop" shift="Region/loop-region"/>
<Button name="Nudge" plain="Region/nudge-forward" control="Region/naturalize-region" shift="Region/nudge-backward" option="Transport/ToggleExternalSync"/>
<Button name="Drop" plain="Editor/jump-backward-to-mark"/>
</Buttons> </Buttons>
</MackieDeviceProfile> </MackieDeviceProfile>