13
0

avoid crash when switching devices in mackie control code, add locks to protect surfaces list (hopefully done without adding any deadlocks - can't test this at present)

git-svn-id: svn://localhost/ardour2/branches/3.0@13750 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2012-12-31 16:04:46 +00:00
parent 104da317ff
commit 99b94fad77
2 changed files with 63 additions and 11 deletions

View File

@ -434,8 +434,12 @@ MackieControlProtocol::periodic ()
now_usecs = (now.tv_sec * 1000000) + now.tv_usec; now_usecs = (now.tv_sec * 1000000) + now.tv_usec;
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { {
(*s)->periodic (now_usecs); Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
(*s)->periodic (now_usecs);
}
} }
update_timecode_display (); update_timecode_display ();
@ -470,6 +474,8 @@ MackieControlProtocol::update_timecode_beats_led()
void void
MackieControlProtocol::update_global_button (int id, LedState ls) MackieControlProtocol::update_global_button (int id, LedState ls)
{ {
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (!_device_info.has_global_controls()) { if (!_device_info.has_global_controls()) {
return; return;
} }
@ -488,6 +494,8 @@ MackieControlProtocol::update_global_button (int id, LedState ls)
void void
MackieControlProtocol::update_global_led (int id, LedState ls) MackieControlProtocol::update_global_led (int id, LedState ls)
{ {
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (!_device_info.has_global_controls()) { if (!_device_info.has_global_controls()) {
return; return;
} }
@ -524,6 +532,8 @@ MackieControlProtocol::update_surfaces()
void void
MackieControlProtocol::initialize() MackieControlProtocol::initialize()
{ {
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) { if (surfaces.empty()) {
return; return;
} }
@ -593,13 +603,16 @@ MackieControlProtocol::set_device (const string& device_name, bool allow_activat
{ {
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",
device_name, allow_activation));
if (d == DeviceInfo::device_info.end()) { if (d == DeviceInfo::device_info.end()) {
return; return;
} }
if (_active) { if (_active) {
clear_ports (); clear_ports ();
surfaces.clear (); clear_surfaces ();
} }
_device_info = d->second; _device_info = d->second;
@ -632,7 +645,11 @@ MackieControlProtocol::create_surfaces ()
for (uint32_t n = 0; n < 1 + _device_info.extenders(); ++n) { for (uint32_t n = 0; n < 1 + _device_info.extenders(); ++n) {
boost::shared_ptr<Surface> surface (new Surface (*this, device_name, n, stype)); boost::shared_ptr<Surface> surface (new Surface (*this, device_name, n, stype));
surfaces.push_back (surface);
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
surfaces.push_back (surface);
}
/* next device will be an extender */ /* next device will be an extender */
@ -685,7 +702,7 @@ MackieControlProtocol::close()
route_connections.drop_connections (); route_connections.drop_connections ();
periodic_connection.disconnect (); periodic_connection.disconnect ();
surfaces.clear (); clear_surfaces();
} }
XMLNode& XMLNode&
@ -806,6 +823,8 @@ MackieControlProtocol::format_timecode_timecode (framepos_t now_frame)
void void
MackieControlProtocol::update_timecode_display() MackieControlProtocol::update_timecode_display()
{ {
Glib::Threads::Mutex::Lock lm (surfaces_lock);
if (surfaces.empty()) { if (surfaces.empty()) {
return; return;
} }
@ -878,7 +897,12 @@ MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
void void
MackieControlProtocol::notify_solo_active_changed (bool active) MackieControlProtocol::notify_solo_active_changed (bool active)
{ {
boost::shared_ptr<Surface> surface = surfaces.front(); boost::shared_ptr<Surface> surface;
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
surface = surfaces.front ();
}
map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Led::RudeSolo); map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Led::RudeSolo);
if (x != surface->controls_by_device_independent_id.end()) { if (x != surface->controls_by_device_independent_id.end()) {
@ -937,6 +961,8 @@ MackieControlProtocol::notify_transport_state_changed()
void void
MackieControlProtocol::notify_metering_state_changed() MackieControlProtocol::notify_metering_state_changed()
{ {
Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
(*s)->notify_metering_state_changed (); (*s)->notify_metering_state_changed ();
} }
@ -948,8 +974,14 @@ MackieControlProtocol::notify_record_state_changed ()
if (!_device_info.has_global_controls()) { if (!_device_info.has_global_controls()) {
return; return;
} }
boost::shared_ptr<Surface> surface = surfaces.front();
boost::shared_ptr<Surface> surface;
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
surface = surfaces.front();
}
/* rec is a tristate */ /* rec is a tristate */
map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Button::Record); map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Button::Record);
@ -1220,6 +1252,8 @@ MackieControlProtocol::clear_ports ()
void void
MackieControlProtocol::set_view_mode (ViewMode m) MackieControlProtocol::set_view_mode (ViewMode m)
{ {
Glib::Threads::Mutex::Lock lm (surfaces_lock);
_view_mode = m; _view_mode = m;
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
@ -1231,6 +1265,8 @@ MackieControlProtocol::set_view_mode (ViewMode m)
void void
MackieControlProtocol::set_flip_mode (bool yn) MackieControlProtocol::set_flip_mode (bool yn)
{ {
Glib::Threads::Mutex::Lock lm (surfaces_lock);
_flip_mode = yn; _flip_mode = yn;
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
@ -1257,6 +1293,8 @@ MackieControlProtocol::force_special_route_to_strip (boost::shared_ptr<Route> r,
return; return;
} }
Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
if ((*s)->number() == surface) { if ((*s)->number() == surface) {
Strip* strip = (*s)->nth_strip (strip_number); Strip* strip = (*s)->nth_strip (strip_number);
@ -1277,7 +1315,6 @@ MackieControlProtocol::gui_track_selection_changed (ARDOUR::RouteNotificationLis
void void
MackieControlProtocol::_gui_track_selection_changed (ARDOUR::RouteNotificationList* rl, bool save_list) MackieControlProtocol::_gui_track_selection_changed (ARDOUR::RouteNotificationList* rl, bool save_list)
{ {
/* We need to keep a list of the most recently selected routes around, /* We need to keep a list of the most recently selected routes around,
but we are not allowed to keep shared_ptr<Route> unless we want to but we are not allowed to keep shared_ptr<Route> unless we want to
handle the complexities of route deletion. So instead, the GUI sends handle the complexities of route deletion. So instead, the GUI sends
@ -1296,8 +1333,12 @@ MackieControlProtocol::_gui_track_selection_changed (ARDOUR::RouteNotificationLi
} }
} }
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { {
(*s)->gui_selection_changed (srl); Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
(*s)->gui_selection_changed (srl);
}
} }
if (save_list) { if (save_list) {
@ -1471,6 +1512,8 @@ MackieControlProtocol::pull_route_range (DownButtonList& down, RouteList& select
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("PRR %5 in list %1.%2 - %3.%4\n", first_surface, first_strip, last_surface, last_strip, DEBUG_TRACE (DEBUG::MackieControl, string_compose ("PRR %5 in list %1.%2 - %3.%4\n", first_surface, first_strip, last_surface, last_strip,
down.size())); down.size()));
Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) { for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
if ((*s)->number() >= first_surface && (*s)->number() <= last_surface) { if ((*s)->number() >= first_surface && (*s)->number() <= last_surface) {
@ -1526,8 +1569,15 @@ void
MackieControlProtocol::ipmidi_restart () MackieControlProtocol::ipmidi_restart ()
{ {
clear_ports (); clear_ports ();
surfaces.clear (); clear_surfaces ();
create_surfaces (); create_surfaces ();
switch_banks (_current_initial_bank, true); switch_banks (_current_initial_bank, true);
needs_ipmidi_restart = false; needs_ipmidi_restart = false;
} }
void
MackieControlProtocol::clear_surfaces ()
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
surfaces.clear ();
}

View File

@ -136,6 +136,7 @@ class MackieControlProtocol
static bool probe(); static bool probe();
Glib::Threads::Mutex surfaces_lock;
typedef std::list<boost::shared_ptr<Mackie::Surface> > Surfaces; typedef std::list<boost::shared_ptr<Mackie::Surface> > Surfaces;
Surfaces surfaces; Surfaces surfaces;
@ -295,6 +296,7 @@ class MackieControlProtocol
void build_gui (); void build_gui ();
bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port); bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
void clear_ports (); void clear_ports ();
void clear_surfaces ();
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, bool save_list); void gui_track_selection_changed (ARDOUR::RouteNotificationListPtr, bool save_list);