| @@ -2471,7 +2471,6 @@ void CarlaEngine::oscSend_bridge_set_chunk_data(const char* const chunkFile) con | |||||
| std::strcat(targetPath, "/bridge_set_chunk_data"); | std::strcat(targetPath, "/bridge_set_chunk_data"); | ||||
| try_lo_send(pData->oscData->target, targetPath, "s", chunkFile); | try_lo_send(pData->oscData->target, targetPath, "s", chunkFile); | ||||
| } | } | ||||
| #else | #else | ||||
| void CarlaEngine::oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept | void CarlaEngine::oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept | ||||
| { | { | ||||
| @@ -277,7 +277,7 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| while (fShmControl.isDataAvailable()) | |||||
| for (; fShmControl.isDataAvailable();) | |||||
| { | { | ||||
| const PluginBridgeOpcode opcode(fShmControl.readOpcode()); | const PluginBridgeOpcode opcode(fShmControl.readOpcode()); | ||||
| @@ -416,8 +416,8 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| if (jackbridge_sem_post(&fShmControl.data->runClient) != 0) | |||||
| pass(); //carla_stderr2("Could not post to semaphore"); | |||||
| if (! jackbridge_sem_post(&fShmControl.data->runClient)) | |||||
| carla_stderr2("Could not post to semaphore"); | |||||
| } | } | ||||
| fIsRunning = false; | fIsRunning = false; | ||||
| @@ -749,6 +749,7 @@ public: | |||||
| //jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin); | //jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin); | ||||
| jackbridge_set_process_callback(client, carla_jack_process_callback_plugin, plugin); | jackbridge_set_process_callback(client, carla_jack_process_callback_plugin, plugin); | ||||
| jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback_plugin, plugin); | |||||
| } | } | ||||
| #endif | #endif | ||||
| return new CarlaEngineJackClient(*this, client); | return new CarlaEngineJackClient(*this, client); | ||||
| @@ -810,6 +811,7 @@ public: | |||||
| jackbridge_set_process_callback(jclient, carla_jack_process_callback_plugin, plugin); | jackbridge_set_process_callback(jclient, carla_jack_process_callback_plugin, plugin); | ||||
| //jackbridge_set_latency_callback(jclient, carla_jack_latency_callback_plugin, plugin); | //jackbridge_set_latency_callback(jclient, carla_jack_latency_callback_plugin, plugin); | ||||
| jackbridge_on_shutdown(jclient, carla_jack_shutdown_callback_plugin, plugin); | |||||
| client->fClient = jclient; | client->fClient = jclient; | ||||
| } | } | ||||
| @@ -2058,6 +2060,19 @@ private: | |||||
| } | } | ||||
| } | } | ||||
| # endif | # endif | ||||
| static void carla_jack_shutdown_callback_plugin(void* arg) | |||||
| { | |||||
| CarlaPlugin* const plugin((CarlaPlugin*)arg); | |||||
| if (plugin != nullptr) | |||||
| { | |||||
| CarlaEngineJackClient* const engineClient((CarlaEngineJackClient*)plugin->getEngineClient()); | |||||
| CARLA_SAFE_ASSERT_RETURN(engineClient != nullptr,); | |||||
| engineClient->fClient = nullptr; | |||||
| } | |||||
| } | |||||
| #endif | #endif | ||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack) | ||||
| @@ -360,8 +360,8 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeSetCustomData, argc, argv, types); | return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeSetCustomData, argc, argv, types); | ||||
| if (std::strcmp(bmethod, "set_chunk_data") == 0) | if (std::strcmp(bmethod, "set_chunk_data") == 0) | ||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeSetChunkData, argc, argv, types); | return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeSetChunkData, argc, argv, types); | ||||
| if (std::strcmp(bmethod, "update") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeUpdate, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "update_now") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeUpdateNow, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "error") == 0) | if (std::strcmp(bmethod, "error") == 0) | ||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeError, argc, argv, types); | return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeError, argc, argv, types); | ||||
| } | } | ||||
| @@ -204,13 +204,13 @@ struct BridgeControl : public RingBufferControl<StackPackedRingBuffer> { | |||||
| setRingBuffer(nullptr, false); | setRingBuffer(nullptr, false); | ||||
| } | } | ||||
| bool waitForServer() | |||||
| bool waitForServer(const int secs) | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | ||||
| jackbridge_sem_post(&data->runServer); | jackbridge_sem_post(&data->runServer); | ||||
| return jackbridge_sem_timedwait(&data->runClient, 5); | |||||
| return jackbridge_sem_timedwait(&data->runClient, secs); | |||||
| } | } | ||||
| void writeOpcode(const PluginBridgeOpcode opcode) noexcept | void writeOpcode(const PluginBridgeOpcode opcode) noexcept | ||||
| @@ -243,6 +243,7 @@ public: | |||||
| fInitError(false), | fInitError(false), | ||||
| fSaved(false), | fSaved(false), | ||||
| fNeedsSemDestroy(false), | fNeedsSemDestroy(false), | ||||
| fTimedOut(false), | |||||
| fParams(nullptr) | fParams(nullptr) | ||||
| { | { | ||||
| carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype)); | carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype)); | ||||
| @@ -268,11 +269,11 @@ public: | |||||
| pData->active = false; | pData->active = false; | ||||
| } | } | ||||
| if (pData->osc.thread.isRunning()) | |||||
| if (pData->osc.thread.isRunning() && ! fTimedOut) | |||||
| { | { | ||||
| fShmControl.writeOpcode(kPluginBridgeOpcodeQuit); | fShmControl.writeOpcode(kPluginBridgeOpcodeQuit); | ||||
| fShmControl.commitWrite(); | fShmControl.commitWrite(); | ||||
| fShmControl.waitForServer(); | |||||
| fShmControl.waitForServer(3); | |||||
| } | } | ||||
| if (pData->osc.data.target != nullptr) | if (pData->osc.data.target != nullptr) | ||||
| @@ -282,7 +283,7 @@ public: | |||||
| } | } | ||||
| pData->osc.data.free(); | pData->osc.data.free(); | ||||
| pData->osc.thread.stop(6000); | |||||
| pData->osc.thread.stop(3000); | |||||
| if (fNeedsSemDestroy) | if (fNeedsSemDestroy) | ||||
| { | { | ||||
| @@ -708,9 +709,14 @@ public: | |||||
| fShmControl.writeFloat(1.0f); | fShmControl.writeFloat(1.0f); | ||||
| fShmControl.commitWrite(); | fShmControl.commitWrite(); | ||||
| bool timedOut = true; | |||||
| try { | try { | ||||
| waitForServer(); | |||||
| timedOut = waitForServer(); | |||||
| } catch(...) {} | } catch(...) {} | ||||
| if (! timedOut) | |||||
| fTimedOut = false; | |||||
| } | } | ||||
| void deactivate() noexcept override | void deactivate() noexcept override | ||||
| @@ -721,9 +727,14 @@ public: | |||||
| fShmControl.writeFloat(0.0f); | fShmControl.writeFloat(0.0f); | ||||
| fShmControl.commitWrite(); | fShmControl.commitWrite(); | ||||
| bool timedOut = true; | |||||
| try { | try { | ||||
| waitForServer(); | |||||
| timedOut = waitForServer(); | |||||
| } catch(...) {} | } catch(...) {} | ||||
| if (! timedOut) | |||||
| fTimedOut = false; | |||||
| } | } | ||||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override | void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override | ||||
| @@ -731,7 +742,7 @@ public: | |||||
| // -------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------- | ||||
| // Check if active | // Check if active | ||||
| if (! pData->active) | |||||
| if (fTimedOut || ! pData->active) | |||||
| { | { | ||||
| // disable any output sound | // disable any output sound | ||||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | for (uint32_t i=0; i < pData->audioOut.count; ++i) | ||||
| @@ -1045,6 +1056,8 @@ public: | |||||
| // -------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------- | ||||
| // Reset audio buffers | // Reset audio buffers | ||||
| //std::memset(fShmAudioPool.data, 0, fShmAudioPool.size); | |||||
| for (uint32_t i=0; i < fInfo.aIns; ++i) | for (uint32_t i=0; i < fInfo.aIns; ++i) | ||||
| FLOAT_COPY(fShmAudioPool.data + (i * frames), inBuffer[i], frames); | FLOAT_COPY(fShmAudioPool.data + (i * frames), inBuffer[i], frames); | ||||
| @@ -1054,7 +1067,7 @@ public: | |||||
| fShmControl.writeOpcode(kPluginBridgeOpcodeProcess); | fShmControl.writeOpcode(kPluginBridgeOpcodeProcess); | ||||
| fShmControl.commitWrite(); | fShmControl.commitWrite(); | ||||
| if (! waitForServer()) | |||||
| if (! waitForServer(2)) | |||||
| { | { | ||||
| pData->singleMutex.unlock(); | pData->singleMutex.unlock(); | ||||
| return true; | return true; | ||||
| @@ -1597,7 +1610,7 @@ public: | |||||
| break; | break; | ||||
| } | } | ||||
| case kPluginBridgeUpdate: | |||||
| case kPluginBridgeUpdateNow: | |||||
| fInitiated = true; | fInitiated = true; | ||||
| break; | break; | ||||
| @@ -1796,6 +1809,7 @@ private: | |||||
| bool fInitError; | bool fInitError; | ||||
| bool fSaved; | bool fSaved; | ||||
| bool fNeedsSemDestroy; | bool fNeedsSemDestroy; | ||||
| bool fTimedOut; | |||||
| CarlaString fBridgeBinary; | CarlaString fBridgeBinary; | ||||
| @@ -1835,12 +1849,14 @@ private: | |||||
| waitForServer(); | waitForServer(); | ||||
| } | } | ||||
| bool waitForServer() | |||||
| bool waitForServer(const int secs = 5) | |||||
| { | { | ||||
| if (! fShmControl.waitForServer()) | |||||
| CARLA_SAFE_ASSERT_RETURN(! fTimedOut, false); | |||||
| if (! fShmControl.waitForServer(secs)) | |||||
| { | { | ||||
| carla_stderr("waitForServer() timeout"); | |||||
| pData->active = false; // TODO | |||||
| carla_stderr("waitForServer() timeout here"); | |||||
| fTimedOut = true; | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -35,7 +35,7 @@ public: | |||||
| JucePlugin(CarlaEngine* const engine, const uint id) | JucePlugin(CarlaEngine* const engine, const uint id) | ||||
| : CarlaPlugin(engine, id), | : CarlaPlugin(engine, id), | ||||
| fInstance(nullptr), | fInstance(nullptr), | ||||
| fAudioBuffer(0, 0) | |||||
| fAudioBuffer(1, 0) | |||||
| { | { | ||||
| carla_debug("JucePlugin::JucePlugin(%p, %i)", engine, id); | carla_debug("JucePlugin::JucePlugin(%p, %i)", engine, id); | ||||
| @@ -457,7 +457,7 @@ public: | |||||
| // plugin hints | // plugin hints | ||||
| pData->hints = 0x0; | pData->hints = 0x0; | ||||
| if (fDesc.category.compareIgnoreCase("synth")) | |||||
| if (fDesc.isInstrument) | |||||
| pData->hints |= PLUGIN_IS_SYNTH; | pData->hints |= PLUGIN_IS_SYNTH; | ||||
| if (fInstance->hasEditor()) | if (fInstance->hasEditor()) | ||||
| @@ -668,24 +668,38 @@ public: | |||||
| return false; | return false; | ||||
| } | } | ||||
| #if 0 | |||||
| if (label == nullptr || label[0] == '\0') | if (label == nullptr || label[0] == '\0') | ||||
| { | { | ||||
| pData->engine->setLastError("null label"); | pData->engine->setLastError("null label"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| #else | |||||
| (void)label; | |||||
| // --------------------------------------------------------------- | |||||
| // fix path for wine usage | |||||
| String jfilename(filename); | |||||
| #ifdef CARLA_OS_WIN | |||||
| if (jfilename.startsWith("/")) | |||||
| { | |||||
| jfilename.replace("/", "\\"); | |||||
| jfilename = "Z:" + jfilename; | |||||
| } | |||||
| #endif | #endif | ||||
| //fDesc.name = fDesc.descriptiveName = label; | //fDesc.name = fDesc.descriptiveName = label; | ||||
| //fDesc.pluginFormatName = "VST"; | //fDesc.pluginFormatName = "VST"; | ||||
| fDesc.uid = 0; | |||||
| fDesc.fileOrIdentifier = filename; | |||||
| fDesc.uid = 0; // TODO - set uid for shell plugins | |||||
| fDesc.fileOrIdentifier = jfilename; | |||||
| fInstance = fFormat.createInstanceFromDescription(fDesc, 44100, 512); | |||||
| // TODO - set uid for shell plugins | |||||
| if (fInstance == nullptr) | |||||
| { | |||||
| pData->engine->setLastError("Plugin failed to initialize"); | |||||
| return false; | |||||
| } | |||||
| fInstance = fFormat.createInstanceFromDescription(fDesc, pData->engine->getSampleRate(), static_cast<int>(pData->engine->getBufferSize())); | |||||
| fInstance->fillInPluginDescription(fDesc); | fInstance->fillInPluginDescription(fDesc); | ||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| @@ -443,7 +443,9 @@ endif | |||||
| ifeq ($(HAVE_JUCE),true) | ifeq ($(HAVE_JUCE),true) | ||||
| LIBS_NATIVE += \ | LIBS_NATIVE += \ | ||||
| ../modules/juce_audio_basics.a \ | ../modules/juce_audio_basics.a \ | ||||
| ../modules/juce_audio_processors.a \ | |||||
| ../modules/juce_core.a \ | ../modules/juce_core.a \ | ||||
| ../modules/juce_data_structures.a \ | |||||
| ../modules/juce_events.a \ | ../modules/juce_events.a \ | ||||
| ../modules/juce_data_structures.a \ | ../modules/juce_data_structures.a \ | ||||
| ../modules/juce_graphics.a \ | ../modules/juce_graphics.a \ | ||||
| @@ -503,6 +505,17 @@ LIBS_POSIX32 = \ | |||||
| ../modules/lilv.posix32.a \ | ../modules/lilv.posix32.a \ | ||||
| ../modules/rtmempool.posix32.a | ../modules/rtmempool.posix32.a | ||||
| ifeq ($(HAVE_JUCE),true) | |||||
| LIBS_POSIX32 += \ | |||||
| ../modules/juce_audio_basics.posix32.a \ | |||||
| ../modules/juce_audio_processors.posix32.a \ | |||||
| ../modules/juce_core.posix32.a \ | |||||
| ../modules/juce_data_structures.posix32.a \ | |||||
| ../modules/juce_events.posix32.a \ | |||||
| ../modules/juce_graphics.posix32.a \ | |||||
| ../modules/juce_gui_basics.posix32.a | |||||
| endif | |||||
| carla-bridge-posix32: $(OBJS_POSIX32) $(LIBS_POSIX32) | carla-bridge-posix32: $(OBJS_POSIX32) $(LIBS_POSIX32) | ||||
| $(CXX) $(OBJS_POSIX32) -Wl,--start-group $(LIBS_POSIX32) -Wl,--end-group $(POSIX_LINK_FLAGS) $(POSIX_32BIT_FLAGS) -o $@ | $(CXX) $(OBJS_POSIX32) -Wl,--start-group $(LIBS_POSIX32) -Wl,--end-group $(POSIX_LINK_FLAGS) $(POSIX_32BIT_FLAGS) -o $@ | ||||
| @@ -551,6 +564,17 @@ LIBS_POSIX64 = \ | |||||
| ../modules/lilv.posix64.a \ | ../modules/lilv.posix64.a \ | ||||
| ../modules/rtmempool.posix64.a | ../modules/rtmempool.posix64.a | ||||
| ifeq ($(HAVE_JUCE),true) | |||||
| LIBS_POSIX64 += \ | |||||
| ../modules/juce_audio_basics.posix64.a \ | |||||
| ../modules/juce_audio_processors.posix64.a \ | |||||
| ../modules/juce_core.posix64.a \ | |||||
| ../modules/juce_data_structures.posix64.a \ | |||||
| ../modules/juce_events.posix64.a \ | |||||
| ../modules/juce_graphics.posix64.a \ | |||||
| ../modules/juce_gui_basics.posix64.a | |||||
| endif | |||||
| carla-bridge-posix64: $(OBJS_POSIX64) $(LIBS_POSIX64) | carla-bridge-posix64: $(OBJS_POSIX64) $(LIBS_POSIX64) | ||||
| $(CXX) $(OBJS_POSIX64) -Wl,--start-group $(LIBS_POSIX64) -Wl,--end-group $(POSIX_LINK_FLAGS) $(POSIX_64BIT_FLAGS) -o $@ | $(CXX) $(OBJS_POSIX64) -Wl,--start-group $(LIBS_POSIX64) -Wl,--end-group $(POSIX_LINK_FLAGS) $(POSIX_64BIT_FLAGS) -o $@ | ||||
| @@ -658,8 +682,19 @@ LIBS_WIN64 = \ | |||||
| ../modules/lilv.win64.a \ | ../modules/lilv.win64.a \ | ||||
| ../modules/rtmempool.win64.a | ../modules/rtmempool.win64.a | ||||
| ifeq ($(HAVE_JUCE),true) | |||||
| LIBS_WIN64 += \ | |||||
| ../modules/juce_audio_basics.win64.a \ | |||||
| ../modules/juce_audio_processors.win64.a \ | |||||
| ../modules/juce_core.win64.a \ | |||||
| ../modules/juce_data_structures.win64.a \ | |||||
| ../modules/juce_events.win64.a \ | |||||
| ../modules/juce_graphics.win64.a \ | |||||
| ../modules/juce_gui_basics.win64.a | |||||
| endif | |||||
| carla-bridge-win64.exe: $(OBJS_WIN64) $(LIBS_WIN64) ../modules/jackbridge-win64.dll | carla-bridge-win64.exe: $(OBJS_WIN64) $(LIBS_WIN64) ../modules/jackbridge-win64.dll | ||||
| $(CXX) $(OBJS_WIN64) -Wl,--start-group $(LIBS_WIN32) -Wl,--end-group $(WIN_LINK_FLAGS) $(WIN_64BIT_FLAGS) -ljackbridge-win64 -o $@ | |||||
| $(CXX) $(OBJS_WIN64) -Wl,--start-group $(LIBS_WIN64) -Wl,--end-group $(WIN_LINK_FLAGS) $(WIN_64BIT_FLAGS) -ljackbridge-win64 -o $@ | |||||
| %__win64.o: %.cpp | %__win64.o: %.cpp | ||||
| $(CXX) $< $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) -c -o $@ | $(CXX) $< $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) -c -o $@ | ||||
| @@ -46,7 +46,7 @@ enum PluginBridgeInfoType { | |||||
| kPluginBridgeConfigure, // ss => key, value | kPluginBridgeConfigure, // ss => key, value | ||||
| kPluginBridgeSetCustomData, // sss => type, key, value | kPluginBridgeSetCustomData, // sss => type, key, value | ||||
| kPluginBridgeSetChunkData, // s => chunkFile | kPluginBridgeSetChunkData, // s => chunkFile | ||||
| kPluginBridgeUpdate, // | |||||
| kPluginBridgeUpdateNow, // | |||||
| kPluginBridgeError // | kPluginBridgeError // | ||||
| }; | }; | ||||
| @@ -138,8 +138,8 @@ const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type) noexcept | |||||
| return "kPluginBridgeSetCustomData"; | return "kPluginBridgeSetCustomData"; | ||||
| case kPluginBridgeSetChunkData: | case kPluginBridgeSetChunkData: | ||||
| return "kPluginBridgeSetChunkData"; | return "kPluginBridgeSetChunkData"; | ||||
| case kPluginBridgeUpdate: | |||||
| return "kPluginBridgeUpdate"; | |||||
| case kPluginBridgeUpdateNow: | |||||
| return "kPluginBridgeUpdateNow"; | |||||
| case kPluginBridgeError: | case kPluginBridgeError: | ||||
| return "kPluginBridgeError"; | return "kPluginBridgeError"; | ||||
| } | } | ||||
| @@ -259,9 +259,9 @@ void osc_send_bridge_update(const CarlaOscData& oscData, const char* const url) | |||||
| CARLA_SAFE_ASSERT_RETURN(url != nullptr && url[0] != '\0',); | CARLA_SAFE_ASSERT_RETURN(url != nullptr && url[0] != '\0',); | ||||
| carla_debug("osc_send_bridge_update(path:\"%s\", \"%s\")", oscData.path, url); | carla_debug("osc_send_bridge_update(path:\"%s\", \"%s\")", oscData.path, url); | ||||
| char targetPath[std::strlen(oscData.path)+15]; | |||||
| char targetPath[std::strlen(oscData.path)+19]; | |||||
| std::strcpy(targetPath, oscData.path); | std::strcpy(targetPath, oscData.path); | ||||
| std::strcat(targetPath, "/bridge_update"); | |||||
| std::strcat(targetPath, "/bridge_update_now"); | |||||
| try_lo_send(oscData.target, targetPath, "s", url); | try_lo_send(oscData.target, targetPath, "s", url); | ||||
| } | } | ||||