diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp index 1de0a8db2..50d4f52a1 100644 --- a/source/backend/engine/CarlaEngineNative.cpp +++ b/source/backend/engine/CarlaEngineNative.cpp @@ -20,18 +20,18 @@ #endif #include "CarlaEngineInternal.hpp" +#include "CarlaPipeUtils.hpp" #include "CarlaStateUtils.hpp" #include "CarlaNative.hpp" -#include #include CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- -class CarlaEngineNativeThread : public CarlaThread +class CarlaEngineNativeUI : public CarlaPipeServer { public: enum UiState { @@ -41,107 +41,110 @@ public: UiCrashed }; - CarlaEngineNativeThread(CarlaEngine* const engine) + CarlaEngineNativeUI(CarlaEngine* const engine) : fEngine(engine), - fProcess(nullptr)/*,*/ - //fUiState(UiNone) + fUiState(UiNone) { - carla_debug("CarlaEngineNativeThread::CarlaEngineNativeThread(%p)", engine); + carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine); } - ~CarlaEngineNativeThread() override + ~CarlaEngineNativeUI() override { - //CARLA_ASSERT_INT(fUiState == UiNone, fUiState); - carla_debug("CarlaEngineNativeThread::~CarlaEngineNativeThread()"); - - if (fProcess != nullptr) - { - delete fProcess; - fProcess = nullptr; - } + CARLA_ASSERT_INT(fUiState == UiNone, fUiState); + carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()"); } -#if 0 - void setOscData(const char* const binary) + void setData(const char* const filename, const double sampleRate, const char* const uiTitle) { - fBinary = binary; + fFilename = filename; + fSampleRate = CarlaString(sampleRate); + fUiTitle = uiTitle; } - UiState getUiState() + UiState getAndResetUiState() noexcept { - const UiState state(fUiState); + const UiState uiState(fUiState); fUiState = UiNone; - - return state; + return uiState; } - void stop() + void start() { - if (fProcess == nullptr) - return; - - fUiState = UiNone; - fProcess->kill(); - //fProcess->close(); + CarlaPipeServer::start(fFilename, fSampleRate, fUiTitle); + writeMsg("show\n", 5); } -#endif protected: - void run() override - { - carla_debug("CarlaEngineNativeThread::run() - binary:\"%s\"", (const char*)fBinary); - -#if 0 - if (fProcess == nullptr) + void msgReceived(const char* const msg) override + { + /* + * TODO: + * load_file load_project save_project patchbay_connect patchbay_disconnect patchbay_refresh + * transport_play transport_pause transport_relocate + * *add_plugin* remove_plugin remove_all_plugins rename_plugin clone_plugin replace_plugin switch_plugins + * load_plugin_state save_plugin_state + * set_option *set_active* set_drywet set_volume set_balance_left set_balance_right set_panning set_ctrl_channel + * set_parameter_value set_parameter_midi_channel set_parameter_midi_cc set_program set_midi_program set_custom_data set_chunk_data + * prepare_for_save send_midi_note show_custom_ui + */ + + if (std::strcmp(msg, "exiting") == 0) { - fProcess = new QProcess(nullptr); - fProcess->setProcessChannelMode(QProcess::ForwardedChannels); + waitChildClose(); + fUiState = UiHide; } - else if (fProcess->state() == QProcess::Running) + else if (std::strcmp(msg, "set_engine_option") == 0) { - carla_stderr("CarlaEngineNativeThread::run() - already running, giving up..."); - - fUiState = UiCrashed; - fProcess->terminate(); - //kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), -1, 0, 0.0f, nullptr); - // TODO: tell master to hide UI - return; - } + int option, value; + const char* valueStr; - QStringList arguments; - arguments << kEngine->getOscServerPathTCP(); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(option),); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(value),); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(valueStr),); - fProcess->start((const char*)fBinary, arguments); - fProcess->waitForStarted(); - - fUiState = UiShow; + fEngine->setOption((EngineOption)option, value, valueStr); + } + else if (std::strcmp(msg, "add_plugin") == 0) + { + int btype, ptype; + const char* filename; + const char* name; + const char* label; + + CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(btype),); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(ptype),); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(name),); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(label),); + + fEngine->addPlugin((BinaryType)btype, (PluginType)ptype, filename, name, label); + } + else if (std::strcmp(msg, "set_active") == 0) + { + int pluginId; + bool onOff; - fProcess->waitForFinished(-1); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff),); - if (fProcess->exitCode() == 0) - { - // Hide - fUiState = UiHide; - carla_stdout("CarlaEngineNativeThread::run() - GUI closed"); + if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) + plugin->setActive(onOff, true, false); } else { - // Kill - fUiState = UiCrashed; - carla_stderr("CarlaEngineNativeThread::run() - GUI crashed while running"); + carla_stderr("msgReceived : %s", msg); } -#endif } private: CarlaEngine* const fEngine; - CarlaString fBinary; - QProcess* fProcess; + CarlaString fFilename; + CarlaString fSampleRate; + CarlaString fUiTitle; + UiState fUiState; -// UiState fUiState; - - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeThread) + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeUI) }; // ----------------------------------------------------------------------- @@ -155,7 +158,7 @@ public: fIsPatchbay(isPatchbay), fIsActive(false), fIsRunning(false), - fThread(this) + fUiServer(this) { carla_debug("CarlaEngineNative::CarlaEngineNative()"); @@ -179,25 +182,7 @@ public: init("Carla-Rack"); } - // TESTING - //if (! addPlugin(PLUGIN_INTERNAL, nullptr, "Ping Pong Pan", "PingPongPan")) - // carla_stdout("TESTING PLUG3 ERROR:\n%s", getLastError()); - -#if 0 - // set control thread binary - CarlaString threadBinary(getResourceDir()); - threadBinary += "/../"; - threadBinary += "carla_control.py"; - - fThread.setOscData(threadBinary); - -// if (! addPlugin(PLUGIN_INTERNAL, nullptr, "MIDI Transpose", "midiTranspose")) -// carla_stdout("TESTING PLUG1 ERROR:\n%s", getLastError()); -// if (! addPlugin(PLUGIN_INTERNAL, nullptr, "ZynAddSubFX", "zynaddsubfx")) -// carla_stdout("TESTING PLUG2 ERROR:\n%s", getLastError()); -// if (! addPlugin(PLUGIN_INTERNAL, nullptr, "Ping Pong Pan", "PingPongPan")) -// carla_stdout("TESTING PLUG3 ERROR:\n%s", getLastError()); -#endif + setCallback(_ui_server_callback, this); } ~CarlaEngineNative() override @@ -263,6 +248,32 @@ protected: CarlaEngine::sampleRateChanged(newSampleRate); } + // ------------------------------------------------------------------- + + void uiServerCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr) + { + if (! fIsRunning) + return; + + char strBuf[STR_MAX+1]; + std::sprintf(strBuf, "ENGINE_CALLBACK_%i\n", int(action)); + fUiServer.writeMsg(strBuf); + + std::sprintf(strBuf, "%u\n", pluginId); + fUiServer.writeMsg(strBuf); + + std::sprintf(strBuf, "%i\n", value1); + fUiServer.writeMsg(strBuf); + + std::sprintf(strBuf, "%i\n", value2); + fUiServer.writeMsg(strBuf); + + std::sprintf(strBuf, "%f\n", value3); + fUiServer.writeMsg(strBuf); + + fUiServer.writeAndFixMsg(valueStr); + } + // ------------------------------------------------------------------- // Plugin parameter calls @@ -590,79 +601,40 @@ protected: runPendingRtEvents(); } -#if 0 // ------------------------------------------------------------------- // Plugin UI calls - void uiShow(const bool show) override + void uiShow(const bool show) { if (show) { - fThread.start(); + fUiServer.setData("/home/falktx/FOSS/GIT-mine/Carla/source/carla-plugin", pData->sampleRate, pHost->uiName); + fUiServer.start(); } else { -#if 0 - for (uint32_t i=0; i < pData->curPluginCount; ++i) - { - CarlaPlugin* const plugin(pData->plugins[i].plugin); - - if (plugin == nullptr || ! plugin->enabled()) - continue; - - plugin->showGui(false); - } -#endif - - fThread.stop(); + fUiServer.stop(); } } - void uiIdle() override + void uiIdle() { CarlaEngine::idle(); + fUiServer.idle(); - switch(fThread.getUiState()) + switch (fUiServer.getAndResetUiState()) { - case CarlaEngineNativeThread::UiNone: - case CarlaEngineNativeThread::UiShow: + case CarlaEngineNativeUI::UiNone: + case CarlaEngineNativeUI::UiShow: break; - case CarlaEngineNativeThread::UiCrashed: - hostUiUnavailable(); + case CarlaEngineNativeUI::UiCrashed: + pHost->dispatcher(pHost->handle, HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f); break; - case CarlaEngineNativeThread::UiHide: - uiClosed(); + case CarlaEngineNativeUI::UiHide: + pHost->ui_closed(pHost->handle); break; } } -#endif - -#if 0 - void uiSetParameterValue(const uint32_t index, const float value) override - { - if (index >= getParameterCount()) - return; - - CarlaPlugin* const plugin(pData->plugins[0].plugin); - - if (plugin == nullptr || ! plugin->isEnabled()) - return; - - plugin->uiParameterChange(index, value); - } - - void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override - { - return; - - // TODO - - // unused - (void)channel; - (void)bank; - (void)program; - } -#endif // ------------------------------------------------------------------- // Plugin state calls @@ -823,6 +795,16 @@ public: handlePtr->setMidiProgram(channel, bank, program); } + static void _ui_show(NativePluginHandle handle, bool show) + { + handlePtr->uiShow(show); + } + + static void _ui_idle(NativePluginHandle handle) + { + handlePtr->uiIdle(); + } + static void _activate(NativePluginHandle handle) { handlePtr->activate(); @@ -876,6 +858,15 @@ public: (void)ptr; } + // ------------------------------------------------------------------- + + static void _ui_server_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, float value3, const char* valueStr) + { + handlePtr->uiServerCallback(action, pluginId, value1, value2, value3, valueStr); + } + + // ------------------------------------------------------------------- + #undef handlePtr private: @@ -883,7 +874,7 @@ private: const bool fIsPatchbay; // rack if false bool fIsActive, fIsRunning; - CarlaEngineNativeThread fThread; + CarlaEngineNativeUI fUiServer; CarlaPlugin* _getFirstPlugin() const noexcept { @@ -928,8 +919,8 @@ static const NativePluginDescriptor carlaRackDesc = { CarlaEngineNative::_set_parameter_value, CarlaEngineNative::_set_midi_program, /* _set_custom_data */ nullptr, - /* _ui_show */ nullptr, - /* _ui_idle */ nullptr, + CarlaEngineNative::_ui_show, + CarlaEngineNative::_ui_idle, /* _ui_set_parameter_value */ nullptr, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, @@ -967,8 +958,8 @@ static const NativePluginDescriptor carlaPatchbayDesc = { CarlaEngineNative::_set_parameter_value, CarlaEngineNative::_set_midi_program, /* _set_custom_data */ nullptr, - /* _ui_show */ nullptr, - /* _ui_idle */ nullptr, + CarlaEngineNative::_ui_show, + CarlaEngineNative::_ui_idle, /* _ui_set_parameter_value */ nullptr, /* _ui_set_midi_program */ nullptr, /* _ui_set_custom_data */ nullptr, diff --git a/source/backend/plugin/CarlaPluginThread.cpp b/source/backend/plugin/CarlaPluginThread.cpp index 2d35138ce..eed466418 100644 --- a/source/backend/plugin/CarlaPluginThread.cpp +++ b/source/backend/plugin/CarlaPluginThread.cpp @@ -115,11 +115,12 @@ void CarlaPluginThread::run() } QString name(fPlugin->getName()); - QStringList arguments; if (name.isEmpty()) name = "(none)"; + QStringList arguments; + switch (fMode) { case PLUGIN_THREAD_NULL: diff --git a/source/carla-plugin b/source/carla-plugin index e909b9522..f85853dc8 100755 --- a/source/carla-plugin +++ b/source/carla-plugin @@ -16,6 +16,11 @@ # # For a full copy of the GNU General Public License see the GPL.txt file +# ------------------------------------------------------------------------------------------------------------ +# Imports (Global) + +from time import sleep + # ------------------------------------------------------------------------------------------------------------ # Imports (Custom Stuff) @@ -26,23 +31,46 @@ from externalui import ExternalUI # Host Plugin object class PluginHost(object): - def __init__(self): + def __init__(self, sampleRate): object.__init__(self) - self.fParent = None - + self.fSupportedFileExts = "" self.fBufferSize = 0 - self.fSampleRate = 0.0 + self.fSampleRate = sampleRate self.fLastError = "" - self.fSupportedFileTypes = "" + self.fIsRunning = True + + # ------------------------------------------------------------------- + + def get_complete_license_text(self): + return "" + + def get_supported_file_extensions(self): + return self.fSupportedFileExts # ------------------------------------------------------------------- def get_engine_driver_count(self): - return 0 + return 1 - def get_supported_file_types(self): - return self.fSupportedFileTypes + def get_engine_driver_name(self, index): + return "Plugin" + + def get_engine_driver_device_names(self, index): + return [] + + def get_engine_driver_device_info(self, index, name): + return PyEngineDriverDeviceInfo + + # ------------------------------------------------------------------- + + def get_internal_plugin_count(self): + return int(self.lib.carla_get_internal_plugin_count()) + + def get_internal_plugin_info(self, index): + return None + + # ------------------------------------------------------------------- def engine_init(self, driverName, clientName): return True @@ -50,8 +78,15 @@ class PluginHost(object): def engine_close(self): return True + def engine_idle(self): + if Carla.gui.idleExternalUI(): + return + + self.fIsRunning = False + Carla.gui.d_uiQuit() + def is_engine_running(self): - return True + return self.fIsRunning def set_engine_about_to_close(self): pass @@ -59,197 +94,243 @@ class PluginHost(object): def set_engine_callback(self, func): pass - def load_filename(self, filename): - self.fParent.send(["load_filename", filename]) + def set_engine_option(self, option, value, valueStr): + Carla.gui.send(["set_engine_option", option, value, valueStr]) + + # ------------------------------------------------------------------- + + def set_file_callback(self, func): + pass + + def load_file(self, filename): + Carla.gui.send(["load_file", filename]) return True def load_project(self, filename): - self.fParent.send(["load_project", filename]) + Carla.gui.send(["load_project", filename]) return True def save_project(self, filename): - self.fParent.send(["save_project", filename]) + Carla.gui.send(["save_project", filename]) return True + # ------------------------------------------------------------------- + def patchbay_connect(self, portIdA, portIdB): - self.fParent.send(["patchbay_connect", portIdA, portIdB]) + Carla.gui.send(["patchbay_connect", portIdA, portIdB]) return True def patchbay_disconnect(self, connectionId): - self.fParent.send(["patchbay_disconnect", connectionId]) + Carla.gui.send(["patchbay_disconnect", connectionId]) return True def patchbay_refresh(self): - self.fParent.send(["patchbay_refresh"]) + Carla.gui.send(["patchbay_refresh"]) return True - def add_plugin(self, btype, ptype, filename, name, label, extraStuff): - self.fParent.send(["add_plugin", btype, ptype, filename, name, label]) + # ------------------------------------------------------------------- + + def transport_play(self): + Carla.gui.send(["transport_play"]) + + def transport_pause(self): + Carla.gui.send(["transport_pause"]) + + def transport_relocate(self, frame): + Carla.gui.send(["transport_relocate"]) + + def get_current_transport_frame(self): + return 0 + + def get_transport_info(self): + return PyCarlaTransportInfo + + # ------------------------------------------------------------------- + + def add_plugin(self, btype, ptype, filename, name, label, extraPtr): + Carla.gui.send(["add_plugin", btype, ptype, filename, name, label]) return True def remove_plugin(self, pluginId): - self.fParent.send(["remove_plugin", pluginId]) + Carla.gui.send(["remove_plugin", pluginId]) return True def remove_all_plugins(self): - self.fParent.send(["remove_all_plugins"]) + Carla.gui.send(["remove_all_plugins"]) return True def rename_plugin(self, pluginId, newName): - self.fParent.send(["rename_plugin", pluginId, newName]) - return True + Carla.gui.send(["rename_plugin", pluginId, newName]) + return newName def clone_plugin(self, pluginId): - self.fParent.send(["clone_plugin", pluginId]) + Carla.gui.send(["clone_plugin", pluginId]) return True def replace_plugin(self, pluginId): - self.fParent.send(["replace_plugin", pluginId]) + Carla.gui.send(["replace_plugin", pluginId]) return True def switch_plugins(self, pluginIdA, pluginIdB): - self.fParent.send(["switch_plugins", pluginIdA, pluginIdB]) + Carla.gui.send(["switch_plugins", pluginIdA, pluginIdB]) return True + # ------------------------------------------------------------------- + def load_plugin_state(self, pluginId, filename): - self.fParent.send(["load_plugin_state", pluginId, filename]) + Carla.gui.send(["load_plugin_state", pluginId, filename]) return True def save_plugin_state(self, pluginId, filename): - self.fParent.send(["save_plugin_state", pluginId, filename]) + Carla.gui.send(["save_plugin_state", pluginId, filename]) return True - #def get_plugin_info(self, pluginId): - #return structToDict(self.lib.carla_get_plugin_info(pluginId).contents) + # ------------------------------------------------------------------- + + def get_plugin_info(self, pluginId): + return PyCarlaPluginInfo - #def get_audio_port_count_info(self, pluginId): - #return structToDict(self.lib.carla_get_audio_port_count_info(pluginId).contents) + def get_audio_port_count_info(self, pluginId): + return PyCarlaPortCountInfo + + def get_midi_port_count_info(self, pluginId): + return PyCarlaPortCountInfo + + def get_parameter_count_info(self, pluginId): + return PyCarlaPortCountInfo + + def get_parameter_info(self, pluginId, parameterId): + return PyCarlaParameterInfo + + def get_parameter_scalepoint_info(self, pluginId, parameterId, scalePointId): + return PyCarlaScalePointInfo + + # ------------------------------------------------------------------- - #def get_midi_port_count_info(self, pluginId): - #return structToDict(self.lib.carla_get_midi_port_count_info(pluginId).contents) + def get_parameter_data(self, pluginId, parameterId): + return PyParameterData - #def get_parameter_count_info(self, pluginId): - #return structToDict(self.lib.carla_get_parameter_count_info(pluginId).contents) + def get_parameter_ranges(self, pluginId, parameterId): + return PyParameterRanges - #def get_parameter_info(self, pluginId, parameterId): - #return structToDict(self.lib.carla_get_parameter_info(pluginId, parameterId).contents) + def get_midi_program_data(self, pluginId, midiProgramId): + return PyMidiProgramData - #def get_parameter_scalepoint_info(self, pluginId, parameterId, scalePointId): - #return structToDict(self.lib.carla_get_parameter_scalepoint_info(pluginId, parameterId, scalePointId).contents) + def get_custom_data(self, pluginId, customDataId): + return PyCustomData - #def get_parameter_data(self, pluginId, parameterId): - #return structToDict(self.lib.carla_get_parameter_data(pluginId, parameterId).contents) + def get_chunk_data(self, pluginId): + return "" - #def get_parameter_ranges(self, pluginId, parameterId): - #return structToDict(self.lib.carla_get_parameter_ranges(pluginId, parameterId).contents) + # ------------------------------------------------------------------- - #def get_midi_program_data(self, pluginId, midiProgramId): - #return structToDict(self.lib.carla_get_midi_program_data(pluginId, midiProgramId).contents) + def get_parameter_count(self, pluginId): + return 0 - #def get_custom_data(self, pluginId, customDataId): - #return structToDict(self.lib.carla_get_custom_data(pluginId, customDataId).contents) + def get_program_count(self, pluginId): + return 0 - #def get_chunk_data(self, pluginId): - #return self.lib.carla_get_chunk_data(pluginId) + def get_midi_program_count(self, pluginId): + return 0 - #def get_parameter_count(self, pluginId): - #return self.lib.carla_get_parameter_count(pluginId) + def get_custom_data_count(self, pluginId): + return 0 - #def get_program_count(self, pluginId): - #return self.lib.carla_get_program_count(pluginId) + # ------------------------------------------------------------------- - #def get_midi_program_count(self, pluginId): - #return self.lib.carla_get_midi_program_count(pluginId) + def get_parameter_text(self, pluginId, parameterId, value): + return "" - #def get_custom_data_count(self, pluginId): - #return self.lib.carla_get_custom_data_count(pluginId) + def get_program_name(self, pluginId, programId): + return "" - #def get_parameter_text(self, pluginId, parameterId): - #return self.lib.carla_get_parameter_text(pluginId, parameterId) + def get_midi_program_name(self, pluginId, midiProgramId): + return "" - #def get_program_name(self, pluginId, programId): - #return self.lib.carla_get_program_name(pluginId, programId) + def get_real_plugin_name(self, pluginId): + return "" - #def get_midi_program_name(self, pluginId, midiProgramId): - #return self.lib.carla_get_midi_program_name(pluginId, midiProgramId) + # ------------------------------------------------------------------- - #def get_real_plugin_name(self, pluginId): - #return self.lib.carla_get_real_plugin_name(pluginId) + def get_current_program_index(self, pluginId): + return 0 - #def get_current_program_index(self, pluginId): - #return self.lib.carla_get_current_program_index(pluginId) + def get_current_midi_program_index(self, pluginId): + return 0 - #def get_current_midi_program_index(self, pluginId): - #return self.lib.carla_get_current_midi_program_index(pluginId) + def get_default_parameter_value(self, pluginId, parameterId): + return 0.0 - #def get_default_parameter_value(self, pluginId, parameterId): - #return self.lib.carla_get_default_parameter_value(pluginId, parameterId) + def get_current_parameter_value(self, pluginId, parameterId): + return 0.0 - #def get_current_parameter_value(self, pluginId, parameterId): - #return self.lib.carla_get_current_parameter_value(pluginId, parameterId) + def get_input_peak_value(self, pluginId, isLeft): + return 0.0 - #def get_input_peak_value(self, pluginId, portId): - #return self.lib.carla_get_input_peak_value(pluginId, portId) + def get_output_peak_value(self, pluginId, isLeft): + return 0.0 - #def get_output_peak_value(self, pluginId, portId): - #return self.lib.carla_get_output_peak_value(pluginId, portId) + # ------------------------------------------------------------------- def set_option(self, pluginId, option, yesNo): - self.fParent.send(["set_option", pluginId, option, yesNo]) + Carla.gui.send(["set_option", pluginId, option, yesNo]) def set_active(self, pluginId, onOff): - self.fParent.send(["set_active", pluginId, onOff]) + Carla.gui.send(["set_active", pluginId, onOff]) def set_drywet(self, pluginId, value): - self.fParent.send(["set_drywet", pluginId, value]) + Carla.gui.send(["set_drywet", pluginId, value]) def set_volume(self, pluginId, value): - self.fParent.send(["set_volume", pluginId, value]) + Carla.gui.send(["set_volume", pluginId, value]) def set_balance_left(self, pluginId, value): - self.fParent.send(["set_balance_left", pluginId, value]) + Carla.gui.send(["set_balance_left", pluginId, value]) def set_balance_right(self, pluginId, value): - self.fParent.send(["set_balance_right", pluginId, value]) + Carla.gui.send(["set_balance_right", pluginId, value]) def set_panning(self, pluginId, value): - self.fParent.send(["set_panning", pluginId, value]) + Carla.gui.send(["set_panning", pluginId, value]) def set_ctrl_channel(self, pluginId, channel): - self.fParent.send(["set_ctrl_channel", pluginId, channel]) + Carla.gui.send(["set_ctrl_channel", pluginId, channel]) - def set_parameter_value(self, pluginId, parameterId, value): - self.fParent.send(["set_parameter_value", pluginId, parameterId, value]) + # ------------------------------------------------------------------- - def set_parameter_midi_cc(self, pluginId, parameterId, cc): - self.fParent.send(["set_parameter_midi_cc", pluginId, parameterId, cc]) + def set_parameter_value(self, pluginId, parameterId, value): + Carla.gui.send(["set_parameter_value", pluginId, parameterId, value]) def set_parameter_midi_channel(self, pluginId, parameterId, channel): - self.fParent.send(["set_parameter_midi_channel", pluginId, parameterId, channel]) + Carla.gui.send(["set_parameter_midi_channel", pluginId, parameterId, channel]) + + def set_parameter_midi_cc(self, pluginId, parameterId, cc): + Carla.gui.send(["set_parameter_midi_cc", pluginId, parameterId, cc]) def set_program(self, pluginId, programId): - self.fParent.send(["set_program", pluginId, programId]) + Carla.gui.send(["set_program", pluginId, programId]) def set_midi_program(self, pluginId, midiProgramId): - self.fParent.send(["set_midi_program", pluginId, midiProgramId]) + Carla.gui.send(["set_midi_program", pluginId, midiProgramId]) def set_custom_data(self, pluginId, type_, key, value): - self.fParent.send(["set_custom_data", pluginId, type_, key, value]) + Carla.gui.send(["set_custom_data", pluginId, type_, key, value]) def set_chunk_data(self, pluginId, chunkData): - self.fParent.send(["set_chunk_data", pluginId, chunkData]) + Carla.gui.send(["set_chunk_data", pluginId, chunkData]) + + # ------------------------------------------------------------------- def prepare_for_save(self, pluginId): - self.fParent.send(["prepare_for_save", pluginId]) + Carla.gui.send(["prepare_for_save", pluginId]) def send_midi_note(self, pluginId, channel, note, velocity): - self.fParent.send(["send_midi_note", pluginId, channel, note, velocity]) + Carla.gui.send(["send_midi_note", pluginId, channel, note, velocity]) - def show_gui(self, pluginId, yesNo): - self.fParent.send(["show_gui", pluginId, yesNo]) + def show_custom_ui(self, pluginId, yesNo): + Carla.gui.send(["show_custom_ui", pluginId, yesNo]) - def get_last_error(self): - return self.fLastError + # ------------------------------------------------------------------- def get_buffer_size(self): return self.fBufferSize @@ -257,11 +338,14 @@ class PluginHost(object): def get_sample_rate(self): return self.fSampleRate -# ------------------------------------------------------------------------------------------------------------ -# Init plugin + def get_last_error(self): + return self.fLastError + + def get_host_osc_url_tcp(self): + return "" -def initPlugin(): - Carla.host = PluginHost() + def get_host_osc_url_udp(self): + return "" # ------------------------------------------------------------------------------------------------------------ # Main Window @@ -271,10 +355,6 @@ class CarlaMiniW(HostWindow, ExternalUI): HostWindow.__init__(self, None) ExternalUI.__init__(self) - if Carla.host is not None: - Carla.host.fParent = None - Carla.host.fSampleRate = self.d_getSampleRate() - if False: from carla_patchbay import CarlaPatchbayW self.fContainer = CarlaPatchbayW(self) @@ -282,11 +362,9 @@ class CarlaMiniW(HostWindow, ExternalUI): from carla_rack import CarlaRackW self.fContainer = CarlaRackW(self) - self.setCentralWidget(self.fContainer) + self.setupContainer(False) self.setWindowTitle(self.fUiName) - self.fIdleTimer = self.startTimer(50) - self.showUiIfTesting() # ------------------------------------------------------------------- @@ -308,17 +386,54 @@ class CarlaMiniW(HostWindow, ExternalUI): # ------------------------------------------------------------------- # Qt events - def timerEvent(self, event): - if event.timerId() == self.fIdleTimer: - if not self.idleExternalUI(): - self.d_uiQuit() - - HostWindow.timerEvent(self, event) - def closeEvent(self, event): self.closeExternalUI() HostWindow.closeEvent(self, event) + # ------------------------------------------------------------------- + # Custom idler + + def idleExternalUI(self): + while True: + if self.fPipeRecv is None: + return True + + try: + msg = self.fPipeRecv.readline().strip() + except IOError: + return False + + if not msg: + return True + + elif msg == "show": + self.d_uiShow() + + elif msg == "hide": + self.d_uiHide() + + elif msg == "quit": + self.fQuitReceived = True + self.d_uiQuit() + + elif msg == "uiTitle": + uiTitle = self.fPipeRecv.readline().strip().replace("\r", "\n") + self.d_uiTitleChanged(uiTitle) + + elif msg.startswith("ENGINE_CALLBACK_"): + action = int(msg.replace("ENGINE_CALLBACK_", "")) + pluginId = int(self.fPipeRecv.readline()) + value1 = int(self.fPipeRecv.readline()) + value2 = int(self.fPipeRecv.readline()) + value3 = float(self.fPipeRecv.readline()) + valueStr = self.fPipeRecv.readline().strip().replace("\r", "\n") + engineCallback(None, action, pluginId, value1, value2, value3, valueStr) + + else: + print("unknown message: \"" + msg + "\"") + + return True + # ------------------------------------------------------------------------------------------------------------ # Main @@ -334,30 +449,25 @@ if __name__ == '__main__': setUpSignals() # ------------------------------------------------------------- - # Setup + # Init plugin host data Carla.isControl = False - Carla.isLocal = False + Carla.isLocal = True Carla.isPlugin = True # ------------------------------------------------------------- - # Read CLI args - - argv = app.arguments() - argc = len(argv) + # Create GUI first - if argc > 1: - pass + Carla.gui = CarlaMiniW() # ------------------------------------------------------------- - # Init plugin backend + # Init plugin host now - initPlugin() + Carla.host = PluginHost(Carla.gui.d_getSampleRate()) - # ------------------------------------------------------------- - # Create GUI + initHost("Carla-Plugin") - Carla.gui = CarlaMiniW() + engineCallback(None, ENGINE_CALLBACK_ENGINE_STARTED, 0, ENGINE_PROCESS_MODE_CONTINUOUS_RACK, ENGINE_TRANSPORT_MODE_PLUGIN, 0.0, "Plugin") # ------------------------------------------------------------- # App-Loop diff --git a/source/carla_host.py b/source/carla_host.py index 77239cc04..8bce9b2c7 100644 --- a/source/carla_host.py +++ b/source/carla_host.py @@ -154,7 +154,8 @@ class HostWindow(QMainWindow): # ------------------------------------------------------------- # Set callback, TODO put somewhere else - Carla.host.set_engine_callback(engineCallback) + if Carla.host is not None: + Carla.host.set_engine_callback(engineCallback) # ------------------------------------------------------------- # Internal stuff @@ -220,9 +221,11 @@ class HostWindow(QMainWindow): # Set up GUI (right panel) self.fDirModel = QFileSystemModel(self) - self.fDirModel.setNameFilters(Carla.host.get_supported_file_extensions().split(";")) self.fDirModel.setRootPath(HOME) + if Carla.host is not None: + self.fDirModel.setNameFilters(Carla.host.get_supported_file_extensions().split(";")) + self.ui.fileTreeView.setModel(self.fDirModel) self.ui.fileTreeView.setRootIndex(self.fDirModel.index(HOME)) self.ui.fileTreeView.setColumnHidden(1, True) @@ -508,9 +511,9 @@ class HostWindow(QMainWindow): if rdfItem.UniqueID == uniqueId: return pointer(rdfItem) - elif ptype in (PLUGIN_GIG, PLUGIN_SF2): + elif ptype in (PLUGIN_FILE_GIG, PLUGIN_FILE_SF2): if plugin['name'].lower().endswith(" (16 outputs)"): - return c_char_p("true") + return c_char_p("true".encode("utf-8")) return None @@ -1061,9 +1064,9 @@ class HostWindow(QMainWindow): def timerEvent(self, event): if event.timerId() == self.fIdleTimerFast: - if not Carla.isPlugin: - Carla.host.engine_idle() - self.refreshTransport() + #if not Carla.isPlugin: + Carla.host.engine_idle() + self.refreshTransport() self.fContainer.idleFast() diff --git a/source/carla_shared.py b/source/carla_shared.py index 526351c26..ae3a8ada5 100644 --- a/source/carla_shared.py +++ b/source/carla_shared.py @@ -524,7 +524,9 @@ def initHost(appName, libPrefix = None, failError = True): Carla.discovery_posix32 = findTool("discovery", "carla-discovery-posix32") Carla.discovery_posix64 = findTool("discovery", "carla-discovery-posix64") - if not libfilename: + # ------------------------------------------------------------- + + if not (libfilename or Carla.isPlugin): if failError: QMessageBox.critical(None, "Error", "Failed to find the carla library, cannot continue") sys.exit(1) @@ -533,7 +535,8 @@ def initHost(appName, libPrefix = None, failError = True): # ------------------------------------------------------------- # Init host - Carla.host = Host(libfilename) + if Carla.host is None: + Carla.host = Host(libfilename) # ------------------------------------------------------------- # Set binary path diff --git a/source/carla_widgets.py b/source/carla_widgets.py index 3c85b72e5..6c3b2d76e 100755 --- a/source/carla_widgets.py +++ b/source/carla_widgets.py @@ -560,13 +560,13 @@ class PluginEdit(QDialog): self.ui.le_type.setText("VST") elif pluginType == PLUGIN_AU: self.ui.le_type.setText("AU") - elif pluginType == PLUGIN_CSOUND: - self.ui.le_type.setText("CSOUND") - elif pluginType == PLUGIN_GIG: + elif pluginType == PLUGIN_FILE_CSD: + self.ui.le_type.setText("CSD") + elif pluginType == PLUGIN_FILE_GIG: self.ui.le_type.setText("GIG") - elif pluginType == PLUGIN_SF2: + elif pluginType == PLUGIN_FILE_SF2: self.ui.le_type.setText("SF2") - elif pluginType == PLUGIN_SFZ: + elif pluginType == PLUGIN_FILE_SFZ: self.ui.le_type.setText("SFZ") else: self.ui.le_type.setText(self.tr("Unknown")) diff --git a/source/externalui.py b/source/externalui.py index ce11b41b4..b4cc24c84 100755 --- a/source/externalui.py +++ b/source/externalui.py @@ -192,7 +192,11 @@ class ExternalUI(object): elif isinstance(line, float): line2 = "%.10f" % line else: - return + try: + line2 = str(line) + except: + print("unknown data type to send:", type(line2)) + return self.fPipeSend.write(line2 + "\n") self.fPipeSend.flush() diff --git a/source/plugin/carla-native-base.cpp b/source/plugin/carla-native-base.cpp index 5a5ca791b..de5e4ecd6 100644 --- a/source/plugin/carla-native-base.cpp +++ b/source/plugin/carla-native-base.cpp @@ -52,9 +52,7 @@ struct PluginListManager { { const NativePluginDescriptor* const desc(CarlaBackend::CarlaPlugin::getNativePluginDescriptor(i)); - carla_stderr2("PLM: %i/%i : %s", i+1, count, desc->name); - -#ifdef CARLA_NATIVE_PLUGIN_LV2 +#if 0 //def CARLA_NATIVE_PLUGIN_LV2 // TESTING!!! // LV2 MIDI Out and Open/Save are not implemented yet if (desc->midiOuts > 0 || (desc->hints & PLUGIN_NEEDS_UI_OPEN_SAVE) != 0) continue;