| @@ -2471,7 +2471,6 @@ void CarlaEngine::oscSend_bridge_set_chunk_data(const char* const chunkFile) con | |||
| std::strcat(targetPath, "/bridge_set_chunk_data"); | |||
| try_lo_send(pData->oscData->target, targetPath, "s", chunkFile); | |||
| } | |||
| #else | |||
| 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()); | |||
| @@ -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; | |||
| @@ -749,6 +749,7 @@ public: | |||
| //jackbridge_set_latency_callback(client, carla_jack_latency_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 | |||
| return new CarlaEngineJackClient(*this, client); | |||
| @@ -810,6 +811,7 @@ public: | |||
| jackbridge_set_process_callback(jclient, carla_jack_process_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; | |||
| } | |||
| @@ -2058,6 +2060,19 @@ private: | |||
| } | |||
| } | |||
| # 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 | |||
| 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); | |||
| if (std::strcmp(bmethod, "set_chunk_data") == 0) | |||
| 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) | |||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeError, argc, argv, types); | |||
| } | |||
| @@ -204,13 +204,13 @@ struct BridgeControl : public RingBufferControl<StackPackedRingBuffer> { | |||
| setRingBuffer(nullptr, false); | |||
| } | |||
| bool waitForServer() | |||
| bool waitForServer(const int secs) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | |||
| 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 | |||
| @@ -243,6 +243,7 @@ public: | |||
| fInitError(false), | |||
| fSaved(false), | |||
| fNeedsSemDestroy(false), | |||
| fTimedOut(false), | |||
| fParams(nullptr) | |||
| { | |||
| carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype)); | |||
| @@ -268,11 +269,11 @@ public: | |||
| pData->active = false; | |||
| } | |||
| if (pData->osc.thread.isRunning()) | |||
| if (pData->osc.thread.isRunning() && ! fTimedOut) | |||
| { | |||
| fShmControl.writeOpcode(kPluginBridgeOpcodeQuit); | |||
| fShmControl.commitWrite(); | |||
| fShmControl.waitForServer(); | |||
| fShmControl.waitForServer(3); | |||
| } | |||
| if (pData->osc.data.target != nullptr) | |||
| @@ -282,7 +283,7 @@ public: | |||
| } | |||
| pData->osc.data.free(); | |||
| pData->osc.thread.stop(6000); | |||
| pData->osc.thread.stop(3000); | |||
| if (fNeedsSemDestroy) | |||
| { | |||
| @@ -708,9 +709,14 @@ public: | |||
| fShmControl.writeFloat(1.0f); | |||
| fShmControl.commitWrite(); | |||
| bool timedOut = true; | |||
| try { | |||
| waitForServer(); | |||
| timedOut = waitForServer(); | |||
| } catch(...) {} | |||
| if (! timedOut) | |||
| fTimedOut = false; | |||
| } | |||
| void deactivate() noexcept override | |||
| @@ -721,9 +727,14 @@ public: | |||
| fShmControl.writeFloat(0.0f); | |||
| fShmControl.commitWrite(); | |||
| bool timedOut = true; | |||
| try { | |||
| waitForServer(); | |||
| timedOut = waitForServer(); | |||
| } catch(...) {} | |||
| if (! timedOut) | |||
| fTimedOut = false; | |||
| } | |||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override | |||
| @@ -731,7 +742,7 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Check if active | |||
| if (! pData->active) | |||
| if (fTimedOut || ! pData->active) | |||
| { | |||
| // disable any output sound | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| @@ -1045,6 +1056,8 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Reset audio buffers | |||
| //std::memset(fShmAudioPool.data, 0, fShmAudioPool.size); | |||
| for (uint32_t i=0; i < fInfo.aIns; ++i) | |||
| FLOAT_COPY(fShmAudioPool.data + (i * frames), inBuffer[i], frames); | |||
| @@ -1054,7 +1067,7 @@ public: | |||
| fShmControl.writeOpcode(kPluginBridgeOpcodeProcess); | |||
| fShmControl.commitWrite(); | |||
| if (! waitForServer()) | |||
| if (! waitForServer(2)) | |||
| { | |||
| pData->singleMutex.unlock(); | |||
| return true; | |||
| @@ -1597,7 +1610,7 @@ public: | |||
| break; | |||
| } | |||
| case kPluginBridgeUpdate: | |||
| case kPluginBridgeUpdateNow: | |||
| fInitiated = true; | |||
| break; | |||
| @@ -1796,6 +1809,7 @@ private: | |||
| bool fInitError; | |||
| bool fSaved; | |||
| bool fNeedsSemDestroy; | |||
| bool fTimedOut; | |||
| CarlaString fBridgeBinary; | |||
| @@ -1835,12 +1849,14 @@ private: | |||
| 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; | |||
| } | |||
| @@ -35,7 +35,7 @@ public: | |||
| JucePlugin(CarlaEngine* const engine, const uint id) | |||
| : CarlaPlugin(engine, id), | |||
| fInstance(nullptr), | |||
| fAudioBuffer(0, 0) | |||
| fAudioBuffer(1, 0) | |||
| { | |||
| carla_debug("JucePlugin::JucePlugin(%p, %i)", engine, id); | |||
| @@ -457,7 +457,7 @@ public: | |||
| // plugin hints | |||
| pData->hints = 0x0; | |||
| if (fDesc.category.compareIgnoreCase("synth")) | |||
| if (fDesc.isInstrument) | |||
| pData->hints |= PLUGIN_IS_SYNTH; | |||
| if (fInstance->hasEditor()) | |||
| @@ -668,24 +668,38 @@ public: | |||
| return false; | |||
| } | |||
| #if 0 | |||
| if (label == nullptr || label[0] == '\0') | |||
| { | |||
| pData->engine->setLastError("null label"); | |||
| 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 | |||
| //fDesc.name = fDesc.descriptiveName = label; | |||
| //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); | |||
| // --------------------------------------------------------------- | |||
| @@ -443,7 +443,9 @@ endif | |||
| ifeq ($(HAVE_JUCE),true) | |||
| LIBS_NATIVE += \ | |||
| ../modules/juce_audio_basics.a \ | |||
| ../modules/juce_audio_processors.a \ | |||
| ../modules/juce_core.a \ | |||
| ../modules/juce_data_structures.a \ | |||
| ../modules/juce_events.a \ | |||
| ../modules/juce_data_structures.a \ | |||
| ../modules/juce_graphics.a \ | |||
| @@ -503,6 +505,17 @@ LIBS_POSIX32 = \ | |||
| ../modules/lilv.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) | |||
| $(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/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) | |||
| $(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/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 | |||
| $(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 | |||
| $(CXX) $< $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) -c -o $@ | |||
| @@ -46,7 +46,7 @@ enum PluginBridgeInfoType { | |||
| kPluginBridgeConfigure, // ss => key, value | |||
| kPluginBridgeSetCustomData, // sss => type, key, value | |||
| kPluginBridgeSetChunkData, // s => chunkFile | |||
| kPluginBridgeUpdate, // | |||
| kPluginBridgeUpdateNow, // | |||
| kPluginBridgeError // | |||
| }; | |||
| @@ -138,8 +138,8 @@ const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type) noexcept | |||
| return "kPluginBridgeSetCustomData"; | |||
| case kPluginBridgeSetChunkData: | |||
| return "kPluginBridgeSetChunkData"; | |||
| case kPluginBridgeUpdate: | |||
| return "kPluginBridgeUpdate"; | |||
| case kPluginBridgeUpdateNow: | |||
| return "kPluginBridgeUpdateNow"; | |||
| case 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_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::strcat(targetPath, "/bridge_update"); | |||
| std::strcat(targetPath, "/bridge_update_now"); | |||
| try_lo_send(oscData.target, targetPath, "s", url); | |||
| } | |||