new CP API and fix several egregious bugs with port handling when switching devices, setting state etc.

This commit is contained in:
Paul Davis 2013-12-21 15:30:07 -05:00
parent 644ead06b4
commit 362769e967
3 changed files with 72 additions and 64 deletions

View file

@ -96,8 +96,6 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
, AbstractUI<MackieControlUIRequest> ("mackie") , AbstractUI<MackieControlUIRequest> ("mackie")
, _current_initial_bank (0) , _current_initial_bank (0)
, _timecode_type (ARDOUR::AnyTime::BBT) , _timecode_type (ARDOUR::AnyTime::BBT)
, _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
, _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
, _gui (0) , _gui (0)
, _zoom_mode (false) , _zoom_mode (false)
, _scrub_mode (false) , _scrub_mode (false)
@ -134,7 +132,6 @@ MackieControlProtocol::~MackieControlProtocol()
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol tear_down_gui ()\n"); DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol tear_down_gui ()\n");
tear_down_gui (); tear_down_gui ();
_active = false;
delete _surfaces_state; delete _surfaces_state;
/* stop event loop */ /* stop event loop */
@ -386,7 +383,7 @@ MackieControlProtocol::set_active (bool yn)
{ {
DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active init with yn: '%1'\n", yn)); DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active init with yn: '%1'\n", yn));
if (yn == _active) { if (yn == active()) {
return 0; return 0;
} }
@ -400,7 +397,6 @@ MackieControlProtocol::set_active (bool yn)
return -1; return -1;
} }
connect_session_signals (); connect_session_signals ();
_active = true;
update_surfaces (); update_surfaces ();
/* set up periodic task for metering and automation /* set up periodic task for metering and automation
@ -414,10 +410,11 @@ MackieControlProtocol::set_active (bool yn)
BaseUI::quit (); BaseUI::quit ();
close (); close ();
_active = false;
} }
ControlProtocol::set_active (yn);
DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active done with yn: '%1'\n", yn)); DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active done with yn: '%1'\n", yn));
return 0; return 0;
@ -426,7 +423,7 @@ MackieControlProtocol::set_active (bool yn)
bool bool
MackieControlProtocol::periodic () MackieControlProtocol::periodic ()
{ {
if (!_active) { if (!active()) {
return false; return false;
} }
@ -529,7 +526,7 @@ void
MackieControlProtocol::update_surfaces() MackieControlProtocol::update_surfaces()
{ {
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() init\n"); DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() init\n");
if (!_active) { if (!active()) {
return; return;
} }
@ -612,34 +609,36 @@ MackieControlProtocol::set_profile (const string& profile_name)
} }
int int
MackieControlProtocol::set_device (const string& device_name, bool allow_activation) MackieControlProtocol::set_device_info (const string& device_name)
{ {
map<string,DeviceInfo>::iterator d = DeviceInfo::device_info.find (device_name); map<string,DeviceInfo>::iterator d = DeviceInfo::device_info.find (device_name);
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1, activation allowed ? %2\n", DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1\n", device_name));
device_name, allow_activation));
if (d == DeviceInfo::device_info.end()) { if (d == DeviceInfo::device_info.end()) {
return -1; return -1;
} }
if (_active) {
clear_ports ();
clear_surfaces ();
}
_device_info = d->second; _device_info = d->second;
if (allow_activation) { return 0;
set_active (true); }
} else {
if (_active) { int
if (create_surfaces ()) { MackieControlProtocol::set_device (const string& device_name)
return -1; {
} if (set_device_info (device_name)) {
switch_banks (0, true); return -1;
}
} }
clear_surfaces ();
if (create_surfaces ()) {
return -1;
}
switch_banks (0, true);
return 0; return 0;
} }
@ -688,6 +687,10 @@ MackieControlProtocol::create_surfaces ()
stype = ext; stype = ext;
if (!_device_info.uses_ipmidi()) { if (!_device_info.uses_ipmidi()) {
_input_bundle.reset (new ARDOUR::Bundle (_("Mackie Control In"), true));
_output_bundle.reset (new ARDOUR::Bundle (_("Mackie Control Out"), false));
_input_bundle->add_channel ( _input_bundle->add_channel (
surface->port().input_port().name(), surface->port().input_port().name(),
ARDOUR::DataType::MIDI, ARDOUR::DataType::MIDI,
@ -699,6 +702,16 @@ MackieControlProtocol::create_surfaces ()
ARDOUR::DataType::MIDI, ARDOUR::DataType::MIDI,
session->engine().make_port_name_non_relative (surface->port().output_port().name()) session->engine().make_port_name_non_relative (surface->port().output_port().name())
); );
session->BundleAdded (_input_bundle);
session->BundleAdded (_output_bundle);
} else {
_input_bundle.reset ((ARDOUR::Bundle*) 0);
_output_bundle.reset ((ARDOUR::Bundle*) 0);
session->BundleRemoved (_input_bundle);
session->BundleRemoved (_output_bundle);
} }
int fd; int fd;
@ -723,8 +736,6 @@ MackieControlProtocol::create_surfaces ()
void void
MackieControlProtocol::close() MackieControlProtocol::close()
{ {
clear_ports ();
session_connections.drop_connections (); session_connections.drop_connections ();
route_connections.drop_connections (); route_connections.drop_connections ();
periodic_connection.disconnect (); periodic_connection.disconnect ();
@ -735,45 +746,42 @@ MackieControlProtocol::close()
XMLNode& XMLNode&
MackieControlProtocol::get_state() MackieControlProtocol::get_state()
{ {
XMLNode& node (ControlProtocol::get_state());
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state init\n"); DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state init\n");
char buf[16]; char buf[16];
// add name of protocol
XMLNode* node = new XMLNode (X_("Protocol"));
node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
// add current bank // add current bank
snprintf (buf, sizeof (buf), "%d", _current_initial_bank); snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
node->add_property (X_("bank"), buf); node.add_property (X_("bank"), buf);
// ipMIDI base port (possibly not used) // ipMIDI base port (possibly not used)
snprintf (buf, sizeof (buf), "%d", _ipmidi_base); snprintf (buf, sizeof (buf), "%d", _ipmidi_base);
node->add_property (X_("ipmidi-base"), buf); node.add_property (X_("ipmidi-base"), buf);
node->add_property (X_("device-profile"), _device_profile.name()); node.add_property (X_("device-profile"), _device_profile.name());
node->add_property (X_("device-name"), _device_info.name()); node.add_property (X_("device-name"), _device_info.name());
XMLNode* snode = new XMLNode (X_("Surfaces")); XMLNode* snode = new XMLNode (X_("Surfaces"));
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
snode->add_child_nocopy ((*s)->get_state()); snode->add_child_nocopy ((*s)->get_state());
} }
node->add_child_nocopy (*snode); node.add_child_nocopy (*snode);
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state done\n"); DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state done\n");
return *node; return node;
} }
int int
MackieControlProtocol::set_state (const XMLNode & node, int version) MackieControlProtocol::set_state (const XMLNode & node, int version)
{ {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active)); DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", active()));
int retval = 0; int retval = 0;
const XMLProperty* prop; const XMLProperty* prop;
uint32_t bank = 0; uint32_t bank = 0;
bool active = _active;
if ((prop = node.property (X_("ipmidi-base"))) != 0) { if ((prop = node.property (X_("ipmidi-base"))) != 0) {
set_ipmidi_base (atoi (prop->value())); set_ipmidi_base (atoi (prop->value()));
@ -784,12 +792,8 @@ MackieControlProtocol::set_state (const XMLNode & node, int version)
bank = atoi (prop->value()); bank = atoi (prop->value());
} }
if ((prop = node.property (X_("active"))) != 0) {
active = string_is_affirmative (prop->value());
}
if ((prop = node.property (X_("device-name"))) != 0) { if ((prop = node.property (X_("device-name"))) != 0) {
set_device (prop->value(), false); set_device_info (prop->value());
} }
if ((prop = node.property (X_("device-profile"))) != 0) { if ((prop = node.property (X_("device-profile"))) != 0) {
@ -806,12 +810,8 @@ MackieControlProtocol::set_state (const XMLNode & node, int version)
_surfaces_version = version; _surfaces_version = version;
} }
set_active (active); switch_banks (bank, true);
if (_active) {
switch_banks (bank, true);
}
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::set_state done\n"); DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::set_state done\n");
return retval; return retval;
@ -1058,8 +1058,12 @@ list<boost::shared_ptr<ARDOUR::Bundle> >
MackieControlProtocol::bundles () MackieControlProtocol::bundles ()
{ {
list<boost::shared_ptr<ARDOUR::Bundle> > b; list<boost::shared_ptr<ARDOUR::Bundle> > b;
b.push_back (_input_bundle);
b.push_back (_output_bundle); if (_input_bundle) {
b.push_back (_input_bundle);
b.push_back (_output_bundle);
}
return b; return b;
} }
@ -1282,8 +1286,10 @@ MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
void void
MackieControlProtocol::clear_ports () MackieControlProtocol::clear_ports ()
{ {
_input_bundle->remove_channels (); if (_input_bundle) {
_output_bundle->remove_channels (); _input_bundle->remove_channels ();
_output_bundle->remove_channels ();
}
for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) { for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
g_source_destroy (*i); g_source_destroy (*i);
@ -1604,7 +1610,7 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
to restart. to restart.
*/ */
if (_active && _device_info.uses_ipmidi()) { if (active() && _device_info.uses_ipmidi()) {
needs_ipmidi_restart = true; needs_ipmidi_restart = true;
} }
} }
@ -1612,7 +1618,6 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
int int
MackieControlProtocol::ipmidi_restart () MackieControlProtocol::ipmidi_restart ()
{ {
clear_ports ();
clear_surfaces (); clear_surfaces ();
if (create_surfaces ()) { if (create_surfaces ()) {
return -1; return -1;
@ -1625,6 +1630,7 @@ MackieControlProtocol::ipmidi_restart ()
void void
MackieControlProtocol::clear_surfaces () MackieControlProtocol::clear_surfaces ()
{ {
clear_ports ();
Glib::Threads::Mutex::Lock lm (surfaces_lock); Glib::Threads::Mutex::Lock lm (surfaces_lock);
surfaces.clear (); surfaces.clear ();
} }

View file

@ -120,7 +120,7 @@ class MackieControlProtocol
Mackie::DeviceProfile& device_profile() { return _device_profile; } Mackie::DeviceProfile& device_profile() { return _device_profile; }
int set_active (bool yn); int set_active (bool yn);
int set_device (const std::string&, bool allow_activation = true); int set_device (const std::string&);
void set_profile (const std::string&); void set_profile (const std::string&);
FlipMode flip_mode () const { return _flip_mode; } FlipMode flip_mode () const { return _flip_mode; }
@ -303,7 +303,8 @@ class MackieControlProtocol
void _gui_track_selection_changed (ARDOUR::RouteNotificationList*, bool save_list); void _gui_track_selection_changed (ARDOUR::RouteNotificationList*, bool save_list);
int ipmidi_restart (); int ipmidi_restart ();
void initialize (); void initialize ();
int set_device_info (const std::string& device_name);
/* BUTTON HANDLING */ /* BUTTON HANDLING */
typedef std::set<uint32_t> DownButtonList; typedef std::set<uint32_t> DownButtonList;

View file

@ -51,11 +51,12 @@ using namespace ARDOUR;
SurfacePort::SurfacePort (Surface& s) SurfacePort::SurfacePort (Surface& s)
: _surface (&s) : _surface (&s)
{ {
if (_surface->mcp().device_info().uses_ipmidi()) { if (_surface->mcp().device_info().uses_ipmidi()) {
_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number()); _input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
_output_port = _input_port; _output_port = _input_port;
} else { } else {
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true); _async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true);
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true); _async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true);
@ -70,19 +71,19 @@ SurfacePort::SurfacePort (Surface& s)
SurfacePort::~SurfacePort() SurfacePort::~SurfacePort()
{ {
if (_surface->mcp().device_info().uses_ipmidi()) { if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
delete _input_port; delete _input_port;
} else { } else {
if (_async_in) { if (_async_in) {
AudioEngine::instance()->unregister_port (_async_in); AudioEngine::instance()->unregister_port (_async_in);
_async_in.reset (); _async_in.reset ((ARDOUR::Port*) 0);
} }
if (_async_out) { if (_async_out) {
_output_port->drain (10000); _output_port->drain (10000);
AudioEngine::instance()->unregister_port (_async_out); AudioEngine::instance()->unregister_port (_async_out);
_async_out.reset (); _async_out.reset ((ARDOUR::Port*) 0);
} }
} }
} }
@ -92,7 +93,7 @@ SurfacePort::get_state ()
{ {
XMLNode* node = new XMLNode (X_("Port")); XMLNode* node = new XMLNode (X_("Port"));
if (_surface->mcp().device_info().uses_ipmidi()) { if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
/* no state required for IPMidi ports */ /* no state required for IPMidi ports */
return *node; return *node;
} }
@ -114,7 +115,7 @@ SurfacePort::get_state ()
int int
SurfacePort::set_state (const XMLNode& node, int version) SurfacePort::set_state (const XMLNode& node, int version)
{ {
if (_surface->mcp().device_info().uses_ipmidi()) { if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
return 0; return 0;
} }