numerous changes to Mackie support, generally offering better robustness

This commit is contained in:
Paul Davis 2015-10-10 17:13:04 -04:00
parent 7c58b4de5f
commit 965b135842
8 changed files with 157 additions and 107 deletions

View file

@ -118,6 +118,7 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
_surface_combo.signal_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::surface_combo_changed));
_cp.DeviceChanged.connect (device_change_connection, invalidator (*this), boost::bind (&MackieControlProtocolGUI::device_changed, this), gui_context());
_cp.ConnectionChange.connect (connection_change_connection, invalidator (*this), boost::bind (&MackieControlProtocolGUI::connection_handler, this), gui_context());
ipmidi_base_port_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::ipmidi_spinner_changed));
@ -239,6 +240,29 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
fkey_packer->show_all();
}
void
MackieControlProtocolGUI::connection_handler ()
{
vector<Gtk::ComboBoxText*>::iterator ic;
vector<Gtk::ComboBoxText*>::iterator oc;
vector<string> midi_inputs;
vector<string> midi_outputs;
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsPhysical), midi_inputs);
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsPhysical), midi_outputs);
for (ic = input_combos.begin(), oc = output_combos.begin(); ic != input_combos.end() && oc != output_combos.end(); ++ic, ++oc) {
boost::shared_ptr<Surface> surface = _cp.get_surface_by_raw_pointer ((*ic)->get_data ("surface"));
if (surface) {
update_port_combos (midi_inputs, midi_outputs, *ic, *oc, surface);
}
}
}
void
MackieControlProtocolGUI::update_port_combos (vector<string> const& midi_inputs, vector<string> const& midi_outputs,
Gtk::ComboBoxText* input_combo,
@ -827,47 +851,3 @@ MackieControlProtocolGUI::touch_sensitive_change ()
int sensitivity = (int) touch_sensitivity_adjustment.get_value ();
_cp.set_touch_sensitivity (sensitivity);
}
void
MackieControlProtocolGUI::surface_connectivity_change (Surface* raw_surface)
{
boost::shared_ptr<Surface> surface;
for (MackieControlProtocol::Surfaces::iterator s = _cp.surfaces.begin(); s != _cp.surfaces.end(); ++s) {
if ((*s).get() == raw_surface) {
surface = *s;
break;
}
}
if (!surface) {
return;
}
Gtk::ComboBoxText* input_combo = 0;
Gtk::ComboBoxText* output_combo = 0;
for (vector<Gtk::ComboBoxText*>::iterator c = input_combos.begin(); c != input_combos.end(); ++c) {
if ((*c)->get_data ("surface") == raw_surface) {
input_combo = *c;
}
}
for (vector<Gtk::ComboBoxText*>::iterator c = output_combos.begin(); c != output_combos.end(); ++c) {
if ((*c)->get_data ("surface") == raw_surface) {
output_combo = *c;
}
}
if (!input_combo || !output_combo) {
return;
}
vector<string> midi_inputs;
vector<string> midi_outputs;
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsPhysical), midi_inputs);
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsPhysical), midi_outputs);
update_port_combos (midi_inputs, midi_outputs, input_combo, output_combo, surface);
}

View file

@ -135,11 +135,8 @@ class MackieControlProtocolGUI : public Gtk::Notebook
Gtk::ComboBoxText* output_combo,
boost::shared_ptr<Mackie::Surface> surface);
/* this takes a raw pointer to Surface, because it connects to a signal
emitted by a Surface and we don't want to use
boost::shared_from_this.
*/
void surface_connectivity_change (Mackie::Surface* raw_surface);
PBD::ScopedConnection connection_change_connection;
void connection_handler ();
};
}

View file

@ -400,11 +400,11 @@ MackieControlProtocol::set_active (bool yn)
BaseUI::run ();
if (create_surfaces ()) {
return -1;
}
connect_session_signals ();
update_surfaces ();
if (!_device_info.name().empty()) {
set_device (_device_info.name(), true);
}
/* set up periodic task for metering and automation
*/
@ -534,6 +534,10 @@ MackieControlProtocol::update_global_button (int id, LedState ls)
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) {
return;
}
if (!_device_info.has_global_controls()) {
return;
}
@ -554,6 +558,10 @@ MackieControlProtocol::update_global_led (int id, LedState ls)
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) {
return;
}
if (!_device_info.has_global_controls()) {
return;
}
@ -688,6 +696,8 @@ MackieControlProtocol::set_device_info (const string& device_name)
int
MackieControlProtocol::set_device (const string& device_name, bool force)
{
cerr << "Set Device\n\n\n\n\n\n";
if (device_name == device_info().name() && !force) {
/* already using that device, nothing to do */
return 0;
@ -708,15 +718,17 @@ MackieControlProtocol::set_device (const string& device_name, bool force)
hui_timeout->attach (main_loop()->get_context());
}
if (create_surfaces ()) {
return -1;
}
if (!_device_info.uses_ipmidi()) {
/* notice that the handler for this will execute in our event
loop, not in the thread where the
PortConnectedOrDisconnected signal is emitted.
*/
ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::connection_handler, this, _1, _2, _3, _4, _5), this);
}
switch_banks (0, true);
if (create_surfaces ()) {
return -1;
}
DeviceChanged ();
@ -735,18 +747,17 @@ MackieControlProtocol::create_surfaces ()
{
string device_name;
surface_type_t stype = mcu; // type not yet determined
char buf[128];
if (_device_info.extenders() == 0) {
device_name = X_("mackie control");
} else {
device_name = X_("mackie control #1");
}
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Create %1 surfaces\n", 1 + _device_info.extenders()));
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Create %1 surfaces for %2\n", 1 + _device_info.extenders(), _device_info.name()));
for (uint32_t n = 0; n < 1 + _device_info.extenders(); ++n) {
if (n == 0) {
device_name = _device_info.name();
} else {
device_name = string_compose ("%1 #%2", _device_info.name(), n+1);
}
boost::shared_ptr<Surface> surface;
if (n == _device_info.master_position()) {
@ -765,6 +776,7 @@ MackieControlProtocol::create_surfaces ()
}
if (_surfaces_state) {
cerr << "Resetting surface state\n";
surface->set_state (*_surfaces_state, _surfaces_version);
}
@ -773,13 +785,6 @@ MackieControlProtocol::create_surfaces ()
surfaces.push_back (surface);
}
if (_device_info.extenders() < 2) {
device_name = X_("mackie control #2");
} else {
snprintf (buf, sizeof (buf), X_("mackie control #%d"), n+2);
device_name = buf;
}
if (!_device_info.uses_ipmidi()) {
_input_bundle.reset (new ARDOUR::Bundle (_("Mackie Control In"), true));
@ -857,6 +862,7 @@ MackieControlProtocol::create_surfaces ()
void
MackieControlProtocol::close()
{
port_connection.disconnect ();
session_connections.drop_connections ();
route_connections.drop_connections ();
periodic_connection.disconnect ();
@ -1050,6 +1056,14 @@ void MackieControlProtocol::notify_parameter_changed (std::string const & p)
void
MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
{
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) {
return;
}
}
// currently assigned banks are less than the full set of
// strips, so activate the new strip now.
@ -1072,6 +1086,11 @@ MackieControlProtocol::notify_solo_active_changed (bool active)
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) {
return;
}
surface = _master_surface;
}
@ -1087,6 +1106,14 @@ MackieControlProtocol::notify_solo_active_changed (bool active)
void
MackieControlProtocol::notify_remote_id_changed()
{
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) {
return;
}
}
Sorted sorted = get_sorted_routes();
uint32_t sz = n_strips();
@ -1150,6 +1177,9 @@ MackieControlProtocol::notify_record_state_changed ()
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) {
return;
}
surface = _master_surface;
}
@ -1771,7 +1801,6 @@ MackieControlProtocol::ipmidi_restart ()
void
MackieControlProtocol::clear_surfaces ()
{
port_connection.disconnect ();
clear_ports ();
{
@ -1814,6 +1843,20 @@ MackieControlProtocol::toggle_backlight ()
}
}
boost::shared_ptr<Surface>
MackieControlProtocol::get_surface_by_raw_pointer (void* ptr) const
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
if ((*s).get() == (Surface*) ptr) {
return *s;
}
}
return boost::shared_ptr<Surface> ();
}
boost::shared_ptr<Surface>
MackieControlProtocol::nth_surface (uint32_t n) const
{
@ -1831,11 +1874,14 @@ MackieControlProtocol::nth_surface (uint32_t n) const
void
MackieControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port> wp1, std::string name1, boost::weak_ptr<ARDOUR::Port> wp2, std::string name2, bool yn)
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
Surfaces scopy;
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
scopy = surfaces;
}
for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
for (Surfaces::const_iterator s = scopy.begin(); s != scopy.end(); ++s) {
if ((*s)->connection_handler (wp1, name1, wp2, name2, yn)) {
cerr << (*s)->name() << " Connected, or disconnected\n";
ConnectionChange (*s);
break;
}

View file

@ -166,6 +166,7 @@ class MackieControlProtocol
typedef std::list<boost::shared_ptr<Mackie::Surface> > Surfaces;
Surfaces surfaces;
boost::shared_ptr<Mackie::Surface> get_surface_by_raw_pointer (void*) const;
boost::shared_ptr<Mackie::Surface> nth_surface (uint32_t) const;
std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();

View file

@ -200,7 +200,6 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
_pan_mode = PanAzimuthAutomation;
potmode_changed (true);
_route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
_route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
@ -368,7 +367,14 @@ Strip::notify_trim_changed (bool force_update)
_surface->write (_vpot->zero());
return;
}
Control* control = control_by_parameter[TrimAutomation];
Control* control = 0;
ControlParameterMap::iterator i = control_by_parameter.find (TrimAutomation);
if (i == control_by_parameter.end()) {
return;
}
control = i->second;
boost::shared_ptr<AutomationControl> ac = _route->trim_control();
@ -432,12 +438,15 @@ Strip::notify_panner_azi_changed (bool force_update)
return;
}
Control* control = control_by_parameter[PanAzimuthAutomation];
Control* control = 0;
ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
if (!control) {
if (i == control_by_parameter.end()) {
return;
}
control = i->second;
double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value());
if (force_update || pos != _last_pan_azi_position_written) {
@ -472,13 +481,15 @@ Strip::notify_panner_width_changed (bool force_update)
return;
}
Control* control = 0;
ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
Control* control = control_by_parameter[PanWidthAutomation];
if (!control) {
if (i == control_by_parameter.end()) {
return;
}
control = i->second;
double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
if (force_update || pos != _last_pan_azi_position_written) {
@ -1007,22 +1018,23 @@ Strip::potmode_changed (bool notify)
// WIP
int pm = _surface->mcp().pot_mode();
switch (pm) {
case MackieControlProtocol::Pan:
// This needs to set current pan mode (azimuth or width... or whatever)
set_vpot_parameter (_pan_mode);
DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Pan mode.\n");
break;
case MackieControlProtocol::Tracks: // should change the Tracks to Trim
DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
case MackieControlProtocol::Pan:
// This needs to set current pan mode (azimuth or width... or whatever)
set_vpot_parameter (_pan_mode);
DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Pan mode.\n");
break;
case MackieControlProtocol::Tracks: // should change the Tracks to Trim
DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
set_vpot_parameter (TrimAutomation);
break;
case MackieControlProtocol::Send:
DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
// set to current send
break;
default:
break;
}
case MackieControlProtocol::Send:
DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
// set to current send
break;
default:
cerr << "Pot mode " << pm << " not yet handled\n";
break;
}
if (notify) {
notify_all ();
@ -1133,9 +1145,13 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
reset_saved_values ();
for (int i = 0; i <= TrimAutomation; ++i) {
if (control_by_parameter[i] == _vpot) {
control_by_parameter[i] = 0;
/* unset any mapping between the vpot and any existing parameters */
for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
if (i != control_by_parameter.end() && i->second == _vpot) {
i->second = 0;
}
}

View file

@ -155,7 +155,8 @@ private:
void reset_saved_values ();
std::map<Evoral::Parameter,Control*> control_by_parameter;
typedef std::map<Evoral::Parameter,Control*> ControlParameterMap;
ControlParameterMap control_by_parameter;
};
}

View file

@ -37,6 +37,8 @@
#include "ardour/session.h"
#include "ardour/utils.h"
#include <gtkmm2ext/gui_thread.h>
#include "control_group.h"
#include "surface_port.h"
#include "surface.h"
@ -221,6 +223,13 @@ Surface::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, b
to queue it with the MCP event loop.
*/
/* XXX this is a horrible hack. Without a short sleep here,
something prevents the device wakeup messages from being
sent and/or the responses from being received.
*/
g_usleep (100000);
connected ();
} else {
@ -662,9 +671,7 @@ Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count
write_sysex (host_connection_query (bytes));
} else {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Mackie Control Device ready, current status = %1\n", _active));
if (!_active) {
turn_it_on ();
}
turn_it_on ();
}
break;
@ -672,7 +679,7 @@ Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count
DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device confirms connection, ardour replies\n");
if (bytes[4] == 0x10 || bytes[4] == 0x11) {
write_sysex (host_connection_confirmation (bytes));
_active = true;
turn_it_on ();
}
break;

View file

@ -3,6 +3,8 @@
#include <stdint.h>
#include <sigc++/trackable.h>
#include "pbd/signals.h"
#include "pbd/xml++.h"
#include "midi++/types.h"
@ -43,7 +45,7 @@ class Jog;
class Pot;
class Led;
class Surface : public PBD::ScopedConnectionList
class Surface : public PBD::ScopedConnectionList, public sigc::trackable
{
public:
Surface (MackieControlProtocol&, const std::string& name, uint32_t number, surface_type_t stype);