| @@ -719,7 +719,7 @@ public: | |||||
| * Initialize/start the engine, using @a clientName. | * Initialize/start the engine, using @a clientName. | ||||
| * When the engine is intialized, you need to call idle() at regular intervals. | * When the engine is intialized, you need to call idle() at regular intervals. | ||||
| */ | */ | ||||
| virtual bool init(const char* const clientName); | |||||
| virtual bool init(const char* const clientName) = 0; | |||||
| /*! | /*! | ||||
| * Close engine. | * Close engine. | ||||
| @@ -259,17 +259,6 @@ uint CarlaEngine::getMaxPluginNumber() const noexcept | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // Virtual, per-engine type calls | // Virtual, per-engine type calls | ||||
| bool CarlaEngine::init(const char* const clientName) | |||||
| { | |||||
| carla_debug("CarlaEngine::init(\"%s\")", clientName); | |||||
| if (! pData->init(clientName)) | |||||
| return false; | |||||
| callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName()); | |||||
| return true; | |||||
| } | |||||
| bool CarlaEngine::close() | bool CarlaEngine::close() | ||||
| { | { | ||||
| carla_debug("CarlaEngine::close()"); | carla_debug("CarlaEngine::close()"); | ||||
| @@ -749,6 +749,11 @@ public: | |||||
| return false; | return false; | ||||
| } | } | ||||
| const char* const jackClientName(jackbridge_get_client_name(fClient)); | |||||
| if (! pData->init(jackClientName)) | |||||
| return false; | |||||
| pData->bufferSize = jackbridge_get_buffer_size(fClient); | pData->bufferSize = jackbridge_get_buffer_size(fClient); | ||||
| pData->sampleRate = jackbridge_get_sample_rate(fClient); | pData->sampleRate = jackbridge_get_sample_rate(fClient); | ||||
| @@ -760,8 +765,6 @@ public: | |||||
| jackbridge_set_process_callback(fClient, carla_jack_process_callback, this); | jackbridge_set_process_callback(fClient, carla_jack_process_callback, this); | ||||
| jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback, this); | jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback, this); | ||||
| const char* const jackClientName(jackbridge_get_client_name(fClient)); | |||||
| if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY) | if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY) | ||||
| initJackPatchbay(jackClientName); | initJackPatchbay(jackClientName); | ||||
| @@ -793,10 +796,17 @@ public: | |||||
| if (jackbridge_activate(fClient)) | if (jackbridge_activate(fClient)) | ||||
| { | { | ||||
| CarlaEngine::init(jackClientName); | |||||
| callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName()); | |||||
| return true; | return true; | ||||
| } | } | ||||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||||
| { | |||||
| pData->graph.destroy(); | |||||
| } | |||||
| pData->close(); | |||||
| jackbridge_client_close(fClient); | jackbridge_client_close(fClient); | ||||
| fClient = nullptr; | fClient = nullptr; | ||||
| @@ -809,51 +819,47 @@ public: | |||||
| { | { | ||||
| carla_debug("CarlaEngineJack::close()"); | carla_debug("CarlaEngineJack::close()"); | ||||
| CarlaEngine::close(); | |||||
| #ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
| CarlaEngine::close(); | |||||
| fClient = nullptr; | fClient = nullptr; | ||||
| fIsRunning = false; | fIsRunning = false; | ||||
| return true; | return true; | ||||
| #else | #else | ||||
| if (jackbridge_deactivate(fClient)) | |||||
| { | |||||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||||
| { | |||||
| if (fRackPorts[0] != nullptr) | |||||
| { | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioIn1]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioIn2]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioOut1]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioOut2]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortEventIn]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortEventOut]); | |||||
| carla_fill<jack_port_t*>(fRackPorts, nullptr, kRackPortCount); | |||||
| } | |||||
| pData->graph.destroy(); | |||||
| } | |||||
| // deactivate first | |||||
| const bool deactivated(jackbridge_deactivate(fClient)); | |||||
| if (jackbridge_client_close(fClient)) | |||||
| { | |||||
| fClient = nullptr; | |||||
| return true; | |||||
| } | |||||
| else | |||||
| setLastError("Failed to close the JACK client"); | |||||
| } | |||||
| else | |||||
| setLastError("Failed to deactivate the JACK client"); | |||||
| fClient = nullptr; | |||||
| // clear engine data | |||||
| CarlaEngine::close(); | |||||
| fUsedGroups.clear(); | fUsedGroups.clear(); | ||||
| fUsedPorts.clear(); | fUsedPorts.clear(); | ||||
| fUsedConnections.clear(); | fUsedConnections.clear(); | ||||
| fNewGroups.clear(); | fNewGroups.clear(); | ||||
| return false; | |||||
| // clear rack/patchbay stuff | |||||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||||
| { | |||||
| if (deactivated) | |||||
| { | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioIn1]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioIn2]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioOut1]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioOut2]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortEventIn]); | |||||
| jackbridge_port_unregister(fClient, fRackPorts[kRackPortEventOut]); | |||||
| } | |||||
| carla_fill<jack_port_t*>(fRackPorts, nullptr, kRackPortCount); | |||||
| pData->graph.destroy(); | |||||
| } | |||||
| // close client | |||||
| if (deactivated) | |||||
| jackbridge_client_close(fClient); | |||||
| fClient = nullptr; | |||||
| return true; | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -1354,6 +1360,9 @@ protected: | |||||
| else if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | else if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | ||||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->events.in != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(pData->events.out != nullptr,); | |||||
| // get buffers from jack | // get buffers from jack | ||||
| float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn1], nframes); | float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn1], nframes); | ||||
| float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn2], nframes); | float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn2], nframes); | ||||
| @@ -1362,7 +1371,7 @@ protected: | |||||
| void* const eventIn = jackbridge_port_get_buffer(fRackPorts[kRackPortEventIn], nframes); | void* const eventIn = jackbridge_port_get_buffer(fRackPorts[kRackPortEventIn], nframes); | ||||
| void* const eventOut = jackbridge_port_get_buffer(fRackPorts[kRackPortEventOut], nframes); | void* const eventOut = jackbridge_port_get_buffer(fRackPorts[kRackPortEventOut], nframes); | ||||
| #if 0 | |||||
| #if 1 | |||||
| // assert buffers | // assert buffers | ||||
| CARLA_SAFE_ASSERT(audioIn1 != nullptr); | CARLA_SAFE_ASSERT(audioIn1 != nullptr); | ||||
| CARLA_SAFE_ASSERT(audioIn2 != nullptr); | CARLA_SAFE_ASSERT(audioIn2 != nullptr); | ||||
| @@ -165,6 +165,13 @@ public: | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (! pData->init(clientName)) | |||||
| { | |||||
| close(); | |||||
| setLastError("Failed to init internal data"); | |||||
| return false; | |||||
| } | |||||
| pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); | pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); | ||||
| pData->sampleRate = fDevice->getCurrentSampleRate(); | pData->sampleRate = fDevice->getCurrentSampleRate(); | ||||
| @@ -172,9 +179,9 @@ public: | |||||
| fDevice->start(this); | fDevice->start(this); | ||||
| CarlaEngine::init(clientName); | |||||
| patchbayRefresh(false); | patchbayRefresh(false); | ||||
| callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName()); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -182,18 +189,14 @@ public: | |||||
| { | { | ||||
| carla_debug("CarlaEngineJuce::close()"); | carla_debug("CarlaEngineJuce::close()"); | ||||
| bool hasError = !CarlaEngine::close(); | |||||
| bool hasError = false; | |||||
| if (fDevice != nullptr) | |||||
| { | |||||
| if (fDevice->isPlaying()) | |||||
| fDevice->stop(); | |||||
| // stop stream first | |||||
| if (fDevice != nullptr && fDevice->isPlaying()) | |||||
| fDevice->stop(); | |||||
| if (fDevice->isOpen()) | |||||
| fDevice->close(); | |||||
| fDevice = nullptr; | |||||
| } | |||||
| // clear engine data | |||||
| CarlaEngine::close(); | |||||
| pData->graph.destroy(); | pData->graph.destroy(); | ||||
| @@ -223,6 +226,15 @@ public: | |||||
| fMidiOuts.clear(); | fMidiOuts.clear(); | ||||
| fMidiOutMutex.unlock(); | fMidiOutMutex.unlock(); | ||||
| // close stream | |||||
| if (fDevice != nullptr) | |||||
| { | |||||
| if (fDevice->isOpen()) | |||||
| fDevice->close(); | |||||
| fDevice = nullptr; | |||||
| } | |||||
| return !hasError; | return !hasError; | ||||
| } | } | ||||
| @@ -621,11 +621,17 @@ protected: | |||||
| { | { | ||||
| carla_debug("CarlaEngineNative::init(\"%s\")", clientName); | carla_debug("CarlaEngineNative::init(\"%s\")", clientName); | ||||
| if (! pData->init(clientName)) | |||||
| { | |||||
| close(); | |||||
| setLastError("Failed to init internal data"); | |||||
| return false; | |||||
| } | |||||
| pData->bufferSize = pHost->get_buffer_size(pHost->handle); | pData->bufferSize = pHost->get_buffer_size(pHost->handle); | ||||
| pData->sampleRate = pHost->get_sample_rate(pHost->handle); | pData->sampleRate = pHost->get_sample_rate(pHost->handle); | ||||
| fIsRunning = true; | fIsRunning = true; | ||||
| CarlaEngine::init(clientName); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -267,6 +267,13 @@ public: | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (! pData->init(clientName)) | |||||
| { | |||||
| close(); | |||||
| setLastError("Failed to init internal data"); | |||||
| return false; | |||||
| } | |||||
| pData->bufferSize = bufferFrames; | pData->bufferSize = bufferFrames; | ||||
| pData->sampleRate = fAudio.getStreamSampleRate(); | pData->sampleRate = fAudio.getStreamSampleRate(); | ||||
| @@ -286,9 +293,9 @@ public: | |||||
| return false; | return false; | ||||
| } | } | ||||
| CarlaEngine::init(clientName); | |||||
| patchbayRefresh(false); | patchbayRefresh(false); | ||||
| callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName()); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -297,28 +304,24 @@ public: | |||||
| CARLA_SAFE_ASSERT(fAudioOutCount != 0); | CARLA_SAFE_ASSERT(fAudioOutCount != 0); | ||||
| carla_debug("CarlaEngineRtAudio::close()"); | carla_debug("CarlaEngineRtAudio::close()"); | ||||
| bool hasError = !CarlaEngine::close(); | |||||
| bool hasError = false; | |||||
| if (fAudio.isStreamOpen()) | |||||
| // stop stream first | |||||
| if (fAudio.isStreamOpen() && fAudio.isStreamRunning()) | |||||
| { | { | ||||
| if (fAudio.isStreamRunning()) | |||||
| try { | |||||
| fAudio.stopStream(); | |||||
| } | |||||
| catch (const RtAudioError& e) | |||||
| { | { | ||||
| try { | |||||
| fAudio.stopStream(); | |||||
| } | |||||
| catch (const RtAudioError& e) | |||||
| { | |||||
| if (! hasError) | |||||
| { | |||||
| setLastError(e.what()); | |||||
| hasError = true; | |||||
| } | |||||
| } | |||||
| setLastError(e.what()); | |||||
| hasError = true; | |||||
| } | } | ||||
| fAudio.closeStream(); | |||||
| } | } | ||||
| // clear engine data | |||||
| CarlaEngine::close(); | |||||
| pData->graph.destroy(); | pData->graph.destroy(); | ||||
| for (LinkedList<MidiInPort>::Itenerator it = fMidiIns.begin(); it.valid(); it.next()) | for (LinkedList<MidiInPort>::Itenerator it = fMidiIns.begin(); it.valid(); it.next()) | ||||
| @@ -353,6 +356,10 @@ public: | |||||
| fLastEventTime = 0; | fLastEventTime = 0; | ||||
| fDeviceName.clear(); | fDeviceName.clear(); | ||||
| // close stream | |||||
| if (fAudio.isStreamOpen()) | |||||
| fAudio.closeStream(); | |||||
| return !hasError; | return !hasError; | ||||
| } | } | ||||
| @@ -249,9 +249,6 @@ class CarlaHostW(HostWindow): | |||||
| self.ui.dockWidget.installEventFilter(self) | self.ui.dockWidget.installEventFilter(self) | ||||
| self.ui.dockWidgetTitleBar = QWidget(self) | |||||
| self.ui.dockWidget.setTitleBarWidget(self.ui.dockWidgetTitleBar) | |||||
| QTimer.singleShot(0, self.slot_initWidgets) | QTimer.singleShot(0, self.slot_initWidgets) | ||||
| # ----------------------------------------------------------------- | # ----------------------------------------------------------------- | ||||
| @@ -65,7 +65,7 @@ if __name__ == '__main__': | |||||
| gCarla.isControl = False | gCarla.isControl = False | ||||
| gCarla.isLocal = True | gCarla.isLocal = True | ||||
| gCarla.isPlugin = False | gCarla.isPlugin = False | ||||
| gCarla.processMode = ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS | |||||
| gCarla.processMode = ENGINE_PROCESS_MODE_PATCHBAY | |||||
| gCarla.processModeForced = True | gCarla.processModeForced = True | ||||
| initHost(initName, libPrefix) | initHost(initName, libPrefix) | ||||
| @@ -254,6 +254,9 @@ class HostWindow(QMainWindow): | |||||
| self.ui.menu_PluginMacros.setEnabled(False) | self.ui.menu_PluginMacros.setEnabled(False) | ||||
| self.ui.menu_Canvas.setEnabled(False) | self.ui.menu_Canvas.setEnabled(False) | ||||
| self.ui.dockWidgetTitleBar = QWidget(self) | |||||
| self.ui.dockWidget.setTitleBarWidget(self.ui.dockWidgetTitleBar) | |||||
| self.setTransportMenuEnabled(False) | self.setTransportMenuEnabled(False) | ||||
| # ------------------------------------------------------------- | # ------------------------------------------------------------- | ||||
| @@ -127,7 +127,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| elif msg.startswith("PARAMVAL_"): | elif msg.startswith("PARAMVAL_"): | ||||
| pluginId, paramId = [int(i) for i in msg.replace("PARAMVAL_", "").split(":")] | pluginId, paramId = [int(i) for i in msg.replace("PARAMVAL_", "").split(":")] | ||||
| paramValue = float(self.readlineblock()) | paramValue = float(self.readlineblock()) | ||||
| gCarla.host._set_parameterValueS(pluginId, paramId, paramValue) | |||||
| gCarla.host._set_parameterValue(pluginId, paramId, paramValue) | |||||
| elif msg.startswith("ENGINE_CALLBACK_"): | elif msg.startswith("ENGINE_CALLBACK_"): | ||||
| action = int(msg.replace("ENGINE_CALLBACK_", "")) | action = int(msg.replace("ENGINE_CALLBACK_", "")) | ||||
| @@ -141,9 +141,9 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| gCarla.host._set_pluginName(pluginId, valueStr) | gCarla.host._set_pluginName(pluginId, valueStr) | ||||
| elif action == ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: | elif action == ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: | ||||
| if value1 < 0: | if value1 < 0: | ||||
| gCarla.host._set_parameterValueInt(pluginId, value1, value3) | |||||
| gCarla.host._set_internalValue(pluginId, value1, value3) | |||||
| else: | else: | ||||
| gCarla.host._set_parameterValueS(pluginId, value1, value3) | |||||
| gCarla.host._set_parameterValue(pluginId, value1, value3) | |||||
| elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | ||||
| gCarla.host._set_parameterDefault(pluginId, value1, value3) | gCarla.host._set_parameterDefault(pluginId, value1, value3) | ||||
| elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED: | elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED: | ||||
| @@ -212,7 +212,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| 'unit': paramUnit, | 'unit': paramUnit, | ||||
| 'scalePointCount': 0, | 'scalePointCount': 0, | ||||
| } | } | ||||
| gCarla.host._set_parameterInfoS(pluginId, paramId, paramInfo) | |||||
| gCarla.host._set_parameterInfo(pluginId, paramId, paramInfo) | |||||
| paramData = { | paramData = { | ||||
| 'type': paramType, | 'type': paramType, | ||||
| @@ -222,7 +222,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| 'midiCC': midiCC, | 'midiCC': midiCC, | ||||
| 'midiChannel': midiChannel | 'midiChannel': midiChannel | ||||
| } | } | ||||
| gCarla.host._set_parameterDataS(pluginId, paramId, paramData) | |||||
| gCarla.host._set_parameterData(pluginId, paramId, paramData) | |||||
| elif msg.startswith("PARAMETER_RANGES_"): | elif msg.startswith("PARAMETER_RANGES_"): | ||||
| pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_RANGES_", "").split(":")] | pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_RANGES_", "").split(":")] | ||||
| @@ -236,7 +236,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| 'stepSmall': stepSmall, | 'stepSmall': stepSmall, | ||||
| 'stepLarge': stepLarge | 'stepLarge': stepLarge | ||||
| } | } | ||||
| gCarla.host._set_parameterRangeS(pluginId, paramId, paramRanges) | |||||
| gCarla.host._set_parameterRanges(pluginId, paramId, paramRanges) | |||||
| elif msg.startswith("PROGRAM_COUNT_"): | elif msg.startswith("PROGRAM_COUNT_"): | ||||
| pluginId, count, current = [int(i) for i in msg.replace("PROGRAM_COUNT_", "").split(":")] | pluginId, count, current = [int(i) for i in msg.replace("PROGRAM_COUNT_", "").split(":")] | ||||
| @@ -246,7 +246,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| elif msg.startswith("PROGRAM_NAME_"): | elif msg.startswith("PROGRAM_NAME_"): | ||||
| pluginId, progId = [int(i) for i in msg.replace("PROGRAM_NAME_", "").split(":")] | pluginId, progId = [int(i) for i in msg.replace("PROGRAM_NAME_", "").split(":")] | ||||
| progName = self.readlineblock().replace("\r", "\n") | progName = self.readlineblock().replace("\r", "\n") | ||||
| gCarla.host._set_programNameS(pluginId, progId, progName) | |||||
| gCarla.host._set_programName(pluginId, progId, progName) | |||||
| elif msg.startswith("MIDI_PROGRAM_COUNT_"): | elif msg.startswith("MIDI_PROGRAM_COUNT_"): | ||||
| pluginId, count, current = [int(i) for i in msg.replace("MIDI_PROGRAM_COUNT_", "").split(":")] | pluginId, count, current = [int(i) for i in msg.replace("MIDI_PROGRAM_COUNT_", "").split(":")] | ||||
| @@ -257,7 +257,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| pluginId, midiProgId = [int(i) for i in msg.replace("MIDI_PROGRAM_DATA_", "").split(":")] | pluginId, midiProgId = [int(i) for i in msg.replace("MIDI_PROGRAM_DATA_", "").split(":")] | ||||
| bank, program = [int(i) for i in self.readlineblock().split(":")] | bank, program = [int(i) for i in self.readlineblock().split(":")] | ||||
| name = self.readlineblock().replace("\r", "\n") | name = self.readlineblock().replace("\r", "\n") | ||||
| gCarla.host._set_midiProgramDataS(pluginId, midiProgId, {'bank': bank, 'program': program, 'name': name}) | |||||
| gCarla.host._set_midiProgramData(pluginId, midiProgId, {'bank': bank, 'program': program, 'name': name}) | |||||
| elif msg == "error": | elif msg == "error": | ||||
| error = self.readlineblock().replace("\r", "\n") | error = self.readlineblock().replace("\r", "\n") | ||||