Browse Source

Wait for pending events to stop before quitting carla

tags/1.9.7
falkTX 9 years ago
parent
commit
67c4521df1
8 changed files with 101 additions and 25 deletions
  1. +7
    -1
      source/backend/CarlaEngine.hpp
  2. +2
    -1
      source/backend/CarlaHost.h
  3. +3
    -3
      source/backend/CarlaStandalone.cpp
  4. +29
    -1
      source/backend/engine/CarlaEngine.cpp
  5. +2
    -0
      source/backend/plugin/CarlaPluginBridge.cpp
  6. +3
    -3
      source/carla_backend.py
  7. +54
    -15
      source/carla_host.py
  8. +1
    -1
      source/native-plugins/resources/carla-plugin

+ 7
- 1
source/backend/CarlaEngine.hpp View File

@@ -1002,11 +1002,17 @@ public:
// -------------------------------------------------------------------
// Misc

/*!
* Check if the engine is about to close.
*/
bool isAboutToClose() const noexcept;

/*!
* Tell the engine it's about to close.
* This is used to prevent the engine thread(s) from reactivating.
* Returns true if there's no pending engine events.
*/
void setAboutToClose() noexcept;
bool setAboutToClose() noexcept;

// -------------------------------------------------------------------
// Options


+ 2
- 1
source/backend/CarlaHost.h View File

@@ -340,8 +340,9 @@ CARLA_EXPORT bool carla_is_engine_running();
/*!
* Tell the engine it's about to close.
* This is used to prevent the engine thread(s) from reactivating.
* Returns true if there's no pending engine events.
*/
CARLA_EXPORT void carla_set_engine_about_to_close();
CARLA_EXPORT bool carla_set_engine_about_to_close();

/*!
* Set the engine callback function.


+ 3
- 3
source/backend/CarlaStandalone.cpp View File

@@ -421,12 +421,12 @@ bool carla_is_engine_running()
return (gStandalone.engine != nullptr && gStandalone.engine->isRunning());
}

void carla_set_engine_about_to_close()
bool carla_set_engine_about_to_close()
{
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,);
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, true);
carla_debug("carla_set_engine_about_to_close()");

gStandalone.engine->setAboutToClose();
return gStandalone.engine->setAboutToClose();
}

void carla_set_engine_callback(EngineCallbackFunc func, void* ptr)


+ 29
- 1
source/backend/engine/CarlaEngine.cpp View File

@@ -1340,11 +1340,21 @@ void CarlaEngine::setLastError(const char* const error) const noexcept
pData->lastError = error;
}

void CarlaEngine::setAboutToClose() noexcept
// -----------------------------------------------------------------------
// Misc

bool CarlaEngine::isAboutToClose() const noexcept
{
return pData->aboutToClose;
}

bool CarlaEngine::setAboutToClose() noexcept
{
carla_debug("CarlaEngine::setAboutToClose()");

pData->aboutToClose = true;

return (pData->isIdling == 0);
}

// -----------------------------------------------------------------------
@@ -1856,6 +1866,9 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
xmlElement = xmlDoc.getDocumentElement(false);
CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to completely parse project file");

if (pData->aboutToClose)
return true;

const bool isPlugin(getType() == kEngineTypePlugin);

// engine settings
@@ -1968,6 +1981,9 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
break;
}

if (pData->aboutToClose)
return true;

// handle plugins first
for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
{
@@ -1980,6 +1996,9 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)

callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (pData->aboutToClose)
return true;

CARLA_SAFE_ASSERT_CONTINUE(stateSave.type != nullptr);

const void* extraStuff = nullptr;
@@ -2004,6 +2023,9 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
{
callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (pData->aboutToClose)
return true;

#ifndef BUILD_BRIDGE
// deactivate bridge client-side ping check, since some plugins block during load
if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && ! isPreset)
@@ -2034,6 +2056,9 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)

callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (pData->aboutToClose)
return true;

// handle connections (internal)
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
{
@@ -2076,6 +2101,9 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
}

callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (pData->aboutToClose)
return true;
}

// if we're running inside some session-manager (and using JACK), let them handle the external connections


+ 2
- 0
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -2567,6 +2567,8 @@ public:

if (fInitiated)
break;
if (pData->engine->isAboutToClose())
break;

carla_msleep(20);
}


+ 3
- 3
source/carla_backend.py View File

@@ -1852,7 +1852,7 @@ class CarlaHostNull(CarlaHostMeta):
return False

def set_engine_about_to_close(self):
return
return True

def set_engine_callback(self, func):
self.fEngineCallback = func
@@ -2119,7 +2119,7 @@ class CarlaHostDLL(CarlaHostMeta):
self.lib.carla_is_engine_running.restype = c_bool

self.lib.carla_set_engine_about_to_close.argtypes = None
self.lib.carla_set_engine_about_to_close.restype = None
self.lib.carla_set_engine_about_to_close.restype = c_bool

self.lib.carla_set_engine_callback.argtypes = [EngineCallbackFunc, c_void_p]
self.lib.carla_set_engine_callback.restype = None
@@ -2382,7 +2382,7 @@ class CarlaHostDLL(CarlaHostMeta):
return bool(self.lib.carla_is_engine_running())

def set_engine_about_to_close(self):
self.lib.carla_set_engine_about_to_close()
return bool(self.lib.carla_set_engine_about_to_close())

def set_engine_callback(self, func):
self._engineCallback = EngineCallbackFunc(func)


+ 54
- 15
source/carla_host.py View File

@@ -111,6 +111,10 @@ class HostWindow(QMainWindow):
self.fIsProjectLoading = False
self.fCurrentlyRemovingAllPlugins = False

# run a custom action after engine is properly closed
# 1 for close carla, 2 for load project
self.fCustomStopAction = 0

# first attempt of auto-start engine doesn't show an error
self.fFirstEngineInit = True

@@ -623,22 +627,44 @@ class HostWindow(QMainWindow):

@pyqtSlot()
def slot_engineStop(self, forced = False):
if self.fPluginCount > 0:
if not forced:
ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There are still some plugins loaded, you need to remove them to stop the engine.\n"
"Do you want to do this now?"),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if ask != QMessageBox.Yes:
return

self.killTimers()
self.removeAllPlugins()
self.host.set_engine_about_to_close()
self.host.remove_all_plugins()
if self.fPluginCount == 0:
self.engineStopFinal()
return True

if not forced:
ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There are still some plugins loaded, you need to remove them to stop the engine.\n"
"Do you want to do this now?"),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if ask != QMessageBox.Yes:
return

return self.slot_engineStopTryAgain()

@pyqtSlot()
def slot_engineStopTryAgain(self):
if self.host.is_engine_running() and not self.host.set_engine_about_to_close():
QTimer.singleShot(0, self.slot_engineStopTryAgain)
return False

self.engineStopFinal()
return True

def engineStopFinal(self):
self.killTimers()
self.removeAllPlugins()
self.host.remove_all_plugins()

if self.host.is_engine_running() and not self.host.engine_close():
print(self.host.get_last_error())

if self.fCustomStopAction == 1:
self.close()
elif self.fCustomStopAction == 2:
self.slot_engineStart()
self.loadProjectNow()

self.fCustomStopAction = 0

# --------------------------------------------------------------------------------------------------------
# Engine (host callbacks)

@@ -1683,7 +1709,11 @@ class HostWindow(QMainWindow):
self.fClientName = os.path.basename(valueStr)
self.fProjectFilename = QFileInfo(valueStr+".carxp").absoluteFilePath()
self.setProperWindowTitle()
self.slot_engineStop(True)

self.fCustomStopAction = 2
if not self.slot_engineStop(True):
return

self.slot_engineStart()
self.loadProjectNow()

@@ -1733,7 +1763,8 @@ class HostWindow(QMainWindow):
@pyqtSlot()
def slot_handleSIGTERM(self):
print("Got SIGTERM -> Closing now")
self.close()
self.fCustomStopAction = 1
self.slot_engineStop(True)

# --------------------------------------------------------------------------------------------------------
# Internal stuff
@@ -1817,6 +1848,11 @@ class HostWindow(QMainWindow):

return pitem.getWidget()

# --------------------------------------------------------------------------------------------------------

def waitForPendingEvents(self):
pass

# --------------------------------------------------------------------------------------------------------
# show/hide event

@@ -1927,7 +1963,10 @@ class HostWindow(QMainWindow):
self.saveSettings()

if self.host.is_engine_running() and not (self.host.isControl or self.host.isPlugin):
self.slot_engineStop(True)
if not self.slot_engineStop(True):
self.fCustomStopAction = 1
event.accept()
return

QMainWindow.closeEvent(self, event)



+ 1
- 1
source/native-plugins/resources/carla-plugin View File

@@ -64,7 +64,7 @@ class PluginHost(CarlaHostQtPlugin):
return self.fExternalUI.isRunning()

def set_engine_about_to_close(self):
return
return True

# ------------------------------------------------------------------------------------------------------------
# Main Window


Loading…
Cancel
Save