| @@ -719,7 +719,7 @@ public: | |||
| * Initialize/start the engine, using @a clientName. | |||
| * 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. | |||
| @@ -259,17 +259,6 @@ uint CarlaEngine::getMaxPluginNumber() const noexcept | |||
| // ----------------------------------------------------------------------- | |||
| // 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() | |||
| { | |||
| carla_debug("CarlaEngine::close()"); | |||
| @@ -749,6 +749,11 @@ public: | |||
| 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->sampleRate = jackbridge_get_sample_rate(fClient); | |||
| @@ -760,8 +765,6 @@ public: | |||
| jackbridge_set_process_callback(fClient, carla_jack_process_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) | |||
| initJackPatchbay(jackClientName); | |||
| @@ -793,10 +796,17 @@ public: | |||
| if (jackbridge_activate(fClient)) | |||
| { | |||
| CarlaEngine::init(jackClientName); | |||
| callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName()); | |||
| 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); | |||
| fClient = nullptr; | |||
| @@ -809,51 +819,47 @@ public: | |||
| { | |||
| carla_debug("CarlaEngineJack::close()"); | |||
| CarlaEngine::close(); | |||
| #ifdef BUILD_BRIDGE | |||
| CarlaEngine::close(); | |||
| fClient = nullptr; | |||
| fIsRunning = false; | |||
| return true; | |||
| #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(); | |||
| fUsedPorts.clear(); | |||
| fUsedConnections.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 | |||
| } | |||
| @@ -1354,6 +1360,9 @@ protected: | |||
| else if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||
| 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 | |||
| float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn1], 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 eventOut = jackbridge_port_get_buffer(fRackPorts[kRackPortEventOut], nframes); | |||
| #if 0 | |||
| #if 1 | |||
| // assert buffers | |||
| CARLA_SAFE_ASSERT(audioIn1 != nullptr); | |||
| CARLA_SAFE_ASSERT(audioIn2 != nullptr); | |||
| @@ -165,6 +165,13 @@ public: | |||
| return false; | |||
| } | |||
| if (! pData->init(clientName)) | |||
| { | |||
| close(); | |||
| setLastError("Failed to init internal data"); | |||
| return false; | |||
| } | |||
| pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); | |||
| pData->sampleRate = fDevice->getCurrentSampleRate(); | |||
| @@ -172,9 +179,9 @@ public: | |||
| fDevice->start(this); | |||
| CarlaEngine::init(clientName); | |||
| patchbayRefresh(false); | |||
| callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName()); | |||
| return true; | |||
| } | |||
| @@ -182,18 +189,14 @@ public: | |||
| { | |||
| 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(); | |||
| @@ -223,6 +226,15 @@ public: | |||
| fMidiOuts.clear(); | |||
| fMidiOutMutex.unlock(); | |||
| // close stream | |||
| if (fDevice != nullptr) | |||
| { | |||
| if (fDevice->isOpen()) | |||
| fDevice->close(); | |||
| fDevice = nullptr; | |||
| } | |||
| return !hasError; | |||
| } | |||
| @@ -621,11 +621,17 @@ protected: | |||
| { | |||
| 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->sampleRate = pHost->get_sample_rate(pHost->handle); | |||
| fIsRunning = true; | |||
| CarlaEngine::init(clientName); | |||
| return true; | |||
| } | |||
| @@ -267,6 +267,13 @@ public: | |||
| return false; | |||
| } | |||
| if (! pData->init(clientName)) | |||
| { | |||
| close(); | |||
| setLastError("Failed to init internal data"); | |||
| return false; | |||
| } | |||
| pData->bufferSize = bufferFrames; | |||
| pData->sampleRate = fAudio.getStreamSampleRate(); | |||
| @@ -286,9 +293,9 @@ public: | |||
| return false; | |||
| } | |||
| CarlaEngine::init(clientName); | |||
| patchbayRefresh(false); | |||
| callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName()); | |||
| return true; | |||
| } | |||
| @@ -297,28 +304,24 @@ public: | |||
| CARLA_SAFE_ASSERT(fAudioOutCount != 0); | |||
| 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(); | |||
| for (LinkedList<MidiInPort>::Itenerator it = fMidiIns.begin(); it.valid(); it.next()) | |||
| @@ -353,6 +356,10 @@ public: | |||
| fLastEventTime = 0; | |||
| fDeviceName.clear(); | |||
| // close stream | |||
| if (fAudio.isStreamOpen()) | |||
| fAudio.closeStream(); | |||
| return !hasError; | |||
| } | |||
| @@ -249,9 +249,6 @@ class CarlaHostW(HostWindow): | |||
| self.ui.dockWidget.installEventFilter(self) | |||
| self.ui.dockWidgetTitleBar = QWidget(self) | |||
| self.ui.dockWidget.setTitleBarWidget(self.ui.dockWidgetTitleBar) | |||
| QTimer.singleShot(0, self.slot_initWidgets) | |||
| # ----------------------------------------------------------------- | |||
| @@ -65,7 +65,7 @@ if __name__ == '__main__': | |||
| gCarla.isControl = False | |||
| gCarla.isLocal = True | |||
| gCarla.isPlugin = False | |||
| gCarla.processMode = ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS | |||
| gCarla.processMode = ENGINE_PROCESS_MODE_PATCHBAY | |||
| gCarla.processModeForced = True | |||
| initHost(initName, libPrefix) | |||
| @@ -254,6 +254,9 @@ class HostWindow(QMainWindow): | |||
| self.ui.menu_PluginMacros.setEnabled(False) | |||
| self.ui.menu_Canvas.setEnabled(False) | |||
| self.ui.dockWidgetTitleBar = QWidget(self) | |||
| self.ui.dockWidget.setTitleBarWidget(self.ui.dockWidgetTitleBar) | |||
| self.setTransportMenuEnabled(False) | |||
| # ------------------------------------------------------------- | |||
| @@ -127,7 +127,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||
| elif msg.startswith("PARAMVAL_"): | |||
| pluginId, paramId = [int(i) for i in msg.replace("PARAMVAL_", "").split(":")] | |||
| paramValue = float(self.readlineblock()) | |||
| gCarla.host._set_parameterValueS(pluginId, paramId, paramValue) | |||
| gCarla.host._set_parameterValue(pluginId, paramId, paramValue) | |||
| elif msg.startswith("ENGINE_CALLBACK_"): | |||
| action = int(msg.replace("ENGINE_CALLBACK_", "")) | |||
| @@ -141,9 +141,9 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||
| gCarla.host._set_pluginName(pluginId, valueStr) | |||
| elif action == ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: | |||
| if value1 < 0: | |||
| gCarla.host._set_parameterValueInt(pluginId, value1, value3) | |||
| gCarla.host._set_internalValue(pluginId, value1, value3) | |||
| else: | |||
| gCarla.host._set_parameterValueS(pluginId, value1, value3) | |||
| gCarla.host._set_parameterValue(pluginId, value1, value3) | |||
| elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | |||
| gCarla.host._set_parameterDefault(pluginId, value1, value3) | |||
| elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED: | |||
| @@ -212,7 +212,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||
| 'unit': paramUnit, | |||
| 'scalePointCount': 0, | |||
| } | |||
| gCarla.host._set_parameterInfoS(pluginId, paramId, paramInfo) | |||
| gCarla.host._set_parameterInfo(pluginId, paramId, paramInfo) | |||
| paramData = { | |||
| 'type': paramType, | |||
| @@ -222,7 +222,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||
| 'midiCC': midiCC, | |||
| 'midiChannel': midiChannel | |||
| } | |||
| gCarla.host._set_parameterDataS(pluginId, paramId, paramData) | |||
| gCarla.host._set_parameterData(pluginId, paramId, paramData) | |||
| elif msg.startswith("PARAMETER_RANGES_"): | |||
| pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_RANGES_", "").split(":")] | |||
| @@ -236,7 +236,7 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||
| 'stepSmall': stepSmall, | |||
| 'stepLarge': stepLarge | |||
| } | |||
| gCarla.host._set_parameterRangeS(pluginId, paramId, paramRanges) | |||
| gCarla.host._set_parameterRanges(pluginId, paramId, paramRanges) | |||
| elif msg.startswith("PROGRAM_COUNT_"): | |||
| 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_"): | |||
| pluginId, progId = [int(i) for i in msg.replace("PROGRAM_NAME_", "").split(":")] | |||
| 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_"): | |||
| 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(":")] | |||
| bank, program = [int(i) for i in self.readlineblock().split(":")] | |||
| 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": | |||
| error = self.readlineblock().replace("\r", "\n") | |||