@@ -354,7 +354,7 @@ void ControllerManager::slotPollDevices() {
354354 // we are cooperative a skip the next cycle to free at least some
355355 // CPU time
356356 //
357- // Some random test data form a i5-3317U CPU @ 1.70GHz Running
357+ // Some random test data from a i5-3317U CPU @ 1.70GHz Running
358358 // Ubuntu Trusty:
359359 // * Idle poll: ~5 µs.
360360 // * 5 messages burst (full midi bandwidth): ~872 µs.
@@ -412,6 +412,8 @@ void ControllerManager::closeController(Controller* pController) {
412412 ConfigKey (" [Controller]" , sanitizeDeviceName (pController->getName ())), 0 );
413413}
414414
415+ // This needs to be called in a Qt::BlockingQueuedConnection so that the
416+ // signaling thread can't alter the LegacyControllerMapping during applying
415417void ControllerManager::slotApplyMapping (Controller* pController,
416418 std::shared_ptr<LegacyControllerMapping> pMapping,
417419 bool bEnabled) {
@@ -434,19 +436,26 @@ void ControllerManager::slotApplyMapping(Controller* pController,
434436 qWarning () << " Mapping is dirty, changes might be lost on restart!" ;
435437 }
436438
437-
438439 // Save the file path/name in the config so it can be auto-loaded at
439440 // startup next time
440441 m_pConfig->set (key, pMapping->filePath ());
441442
442443 pController->setMapping (std::move (pMapping));
443444
444445 if (bEnabled) {
445- openController (pController);
446446 emit mappingApplied (pController->isMappable ());
447447 } else {
448448 emit mappingApplied (false );
449+ return ;
449450 }
451+
452+ // Note: openController() may call ControllerRenderingEngine::setup()
453+ // Which has a blocking invokeMethod() call for QOffscreenSurface::create()
454+ // That why we need to return from this blocking call first.
455+ QMetaObject::invokeMethod (
456+ this ,
457+ [this , pController]() { openController (pController); },
458+ Qt::QueuedConnection);
450459}
451460
452461// static
0 commit comments