| @@ -119,39 +119,6 @@ ifneq ($(shell pkg-config --exists QtXml && echo true),true) | |||
| $(error QtXml missing, cannot continue) | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # Check for optional libs (required by backend or bridges) | |||
| HAVE_FFMPEG = $(shell pkg-config --exists libavcodec libavformat libavutil && pkg-config --max-version=1.9 libavcodec && echo true) | |||
| HAVE_GTK2 = $(shell pkg-config --exists gtk+-2.0 && echo true) | |||
| HAVE_GTK3 = $(shell pkg-config --exists gtk+-3.0 && echo true) | |||
| HAVE_QT4 = $(shell pkg-config --exists QtCore QtGui && echo true) | |||
| HAVE_QT5 = $(shell pkg-config --exists Qt5Core Qt5Gui Qt5Widgets && echo true) | |||
| HAVE_X11 = $(shell pkg-config --exists x11 && echo true) | |||
| ifeq ($(LINUX),true) | |||
| HAVE_ALSA = $(shell pkg-config --exists alsa && echo true) | |||
| HAVE_PULSEAUDIO = $(shell pkg-config --exists libpulse-simple && echo true) | |||
| endif | |||
| ifeq ($(CARLA_CSOUND_SUPPORT),true) | |||
| # FIXME ? | |||
| HAVE_CSOUND = $(shell pkg-config --exists sndfile && echo true) | |||
| endif | |||
| ifeq ($(CARLA_SAMPLERS_SUPPORT),true) | |||
| HAVE_FLUIDSYNTH = $(shell pkg-config --exists fluidsynth && echo true) | |||
| HAVE_LINUXSAMPLER = $(shell pkg-config --exists linuxsampler && echo true) | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # Check for optional libs (needed by internal plugins) | |||
| HAVE_AF_DEPS = $(shell pkg-config --exists sndfile && echo true) | |||
| HAVE_MF_DEPS = $(shell pkg-config --exists smf && echo true) | |||
| HAVE_ZYN_DEPS = $(shell pkg-config --exists fftw3 mxml zlib && echo true) | |||
| HAVE_ZYN_UI_DEPS = $(shell pkg-config --exists ntk_images ntk && echo true) | |||
| # -------------------------------------------------------------- | |||
| # Check for dgl support | |||
| @@ -190,6 +157,40 @@ ifeq ($(WIN32),true) | |||
| HAVE_JUCE = true | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # Check for optional libs (required by backend or bridges) | |||
| HAVE_FFMPEG = $(shell pkg-config --exists libavcodec libavformat libavutil && pkg-config --max-version=1.9 libavcodec && echo true) | |||
| HAVE_GTK2 = $(shell pkg-config --exists gtk+-2.0 && echo true) | |||
| HAVE_GTK3 = $(shell pkg-config --exists gtk+-3.0 && echo true) | |||
| HAVE_QT4 = $(shell pkg-config --exists QtCore QtGui && echo true) | |||
| HAVE_QT5 = $(shell pkg-config --exists Qt5Core Qt5Gui Qt5Widgets && echo true) | |||
| HAVE_X11 = $(shell pkg-config --exists x11 && echo true) | |||
| ifeq ($(LINUX),true) | |||
| HAVE_ALSA = $(shell pkg-config --exists alsa && echo true) | |||
| HAVE_PULSEAUDIO = $(shell pkg-config --exists libpulse-simple && echo true) | |||
| endif | |||
| ifeq ($(CARLA_CSOUND_SUPPORT),true) | |||
| ifeq ($(HAVE_JUCE),true) | |||
| HAVE_CSOUND = $(shell pkg-config --exists sndfile && echo true) | |||
| endif | |||
| endif | |||
| ifeq ($(CARLA_SAMPLERS_SUPPORT),true) | |||
| HAVE_FLUIDSYNTH = $(shell pkg-config --exists fluidsynth && echo true) | |||
| HAVE_LINUXSAMPLER = $(shell pkg-config --exists linuxsampler && echo true) | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # Check for optional libs (needed by internal plugins) | |||
| HAVE_AF_DEPS = $(shell pkg-config --exists sndfile && echo true) | |||
| HAVE_MF_DEPS = $(shell pkg-config --exists smf && echo true) | |||
| HAVE_ZYN_DEPS = $(shell pkg-config --exists fftw3 mxml zlib && echo true) | |||
| HAVE_ZYN_UI_DEPS = $(shell pkg-config --exists ntk_images ntk && echo true) | |||
| # -------------------------------------------------------------- | |||
| # Set base stuff | |||
| @@ -1613,6 +1613,10 @@ const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const unsigned int, | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| #ifdef WANT_DSSI | |||
| # include "CarlaDssiUtils.cpp" | |||
| #endif | |||
| #include "CarlaStateUtils.cpp" | |||
| #endif | |||
| @@ -1732,7 +1732,7 @@ void CarlaPlugin::sendMidiAllNotesOffToCallback() | |||
| postEvent.value2 = 0; | |||
| postEvent.value3 = 0.0f; | |||
| for (unsigned short i=0; i < MAX_MIDI_NOTE; ++i) | |||
| for (int32_t i=0; i < MAX_MIDI_NOTE; ++i) | |||
| { | |||
| postEvent.value2 = i; | |||
| pData->postRtEvents.appendRT(postEvent); | |||
| @@ -23,45 +23,7 @@ | |||
| #include "CarlaDssiUtils.hpp" | |||
| #include "CarlaMathUtils.hpp" | |||
| // TODO - put this in a cpp file | |||
| #include <QtCore/QDir> | |||
| #include <QtCore/QFileInfo> | |||
| #include <QtCore/QStringList> | |||
| const char* find_dssi_ui(const char* const filename, const char* const label) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0', nullptr); | |||
| carla_debug("find_dssi_ui(\"%s\", \"%s\")", filename, label); | |||
| QString guiFilename; | |||
| QString pluginDir(filename); | |||
| pluginDir.resize(pluginDir.lastIndexOf(".")); | |||
| QString checkLabel(label); | |||
| QString checkSName(QFileInfo(pluginDir).baseName()); | |||
| if (! checkLabel.endsWith("_")) checkLabel += "_"; | |||
| if (! checkSName.endsWith("_")) checkSName += "_"; | |||
| QStringList guiFiles(QDir(pluginDir).entryList()); | |||
| foreach (const QString& gui, guiFiles) | |||
| { | |||
| if (gui.startsWith(checkLabel) || gui.startsWith(checkSName)) | |||
| { | |||
| QFileInfo finalname(pluginDir + QDir::separator() + gui); | |||
| guiFilename = finalname.absoluteFilePath(); | |||
| break; | |||
| } | |||
| } | |||
| if (guiFilename.isEmpty()) | |||
| return nullptr; | |||
| return carla_strdup(guiFilename.toUtf8().constData()); | |||
| } | |||
| #include <QtCore/QByteArray> | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -79,7 +41,7 @@ public: | |||
| fDescriptor(nullptr), | |||
| fDssiDescriptor(nullptr), | |||
| fUsesCustomData(false), | |||
| fGuiFilename(nullptr), | |||
| fUiFilename(nullptr), | |||
| fAudioInBuffers(nullptr), | |||
| fAudioOutBuffers(nullptr), | |||
| fParamBuffers(nullptr) | |||
| @@ -132,10 +94,10 @@ public: | |||
| fDssiDescriptor = nullptr; | |||
| } | |||
| if (fGuiFilename != nullptr) | |||
| if (fUiFilename != nullptr) | |||
| { | |||
| delete[] fGuiFilename; | |||
| fGuiFilename = nullptr; | |||
| delete[] fUiFilename; | |||
| fUiFilename = nullptr; | |||
| } | |||
| clearBuffers(); | |||
| @@ -589,12 +551,12 @@ public: | |||
| else if (LADSPA_IS_PORT_CONTROL(portType)) | |||
| { | |||
| uint32_t j = iCtrl++; | |||
| pData->param.data[j].type = PARAMETER_UNKNOWN; | |||
| pData->param.data[j].hints = 0x0; | |||
| pData->param.data[j].index = static_cast<int32_t>(j); | |||
| pData->param.data[j].rindex = static_cast<int32_t>(i); | |||
| pData->param.data[j].midiCC = -1; | |||
| pData->param.data[j].midiChannel = 0; | |||
| pData->param.special[j] = PARAMETER_SPECIAL_NULL; | |||
| float min, max, def, step, stepSmall, stepLarge; | |||
| @@ -689,18 +651,8 @@ public: | |||
| stepSmall = 1.0f; | |||
| stepLarge = 1.0f; | |||
| pData->param.data[j].type = PARAMETER_SPECIAL; | |||
| pData->param.data[j].hints = 0; // TODO PARAMETER_LATENCY | |||
| } | |||
| else if (std::strcmp(fDescriptor->PortNames[i], "_sample-rate") == 0) | |||
| { | |||
| def = sampleRate; | |||
| step = 1.0f; | |||
| stepSmall = 1.0f; | |||
| stepLarge = 1.0f; | |||
| pData->param.data[j].type = PARAMETER_SPECIAL; | |||
| pData->param.data[j].hints = 0; // TODO PARAMETER_SAMPLE_RATE | |||
| pData->param.data[j].type = PARAMETER_SPECIAL; | |||
| pData->param.special[j] = PARAMETER_SPECIAL_LATENCY; | |||
| } | |||
| else | |||
| { | |||
| @@ -790,7 +742,7 @@ public: | |||
| if (LADSPA_IS_HARD_RT_CAPABLE(fDescriptor->Properties)) | |||
| pData->hints |= PLUGIN_IS_RTSAFE; | |||
| if (fGuiFilename != nullptr) | |||
| if (fUiFilename != nullptr) | |||
| pData->hints |= PLUGIN_HAS_CUSTOM_UI; | |||
| if (aOuts > 0 && (aIns == aOuts || aIns == 1)) | |||
| @@ -816,8 +768,8 @@ public: | |||
| { | |||
| for (uint32_t i=0; i < pData->param.count; ++i) | |||
| { | |||
| //if (pData->param.data[i].type != PARAMETER_LATENCY) | |||
| // continue; | |||
| if (pData->param.special[i] != PARAMETER_SPECIAL_LATENCY) | |||
| continue; | |||
| // we need to pre-run the plugin so it can update its latency control-port | |||
| @@ -883,8 +835,8 @@ public: | |||
| uint32_t newCount = 0; | |||
| if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr) | |||
| { | |||
| while (fDssiDescriptor->get_program(fHandle, newCount)) | |||
| newCount++; | |||
| for (; fDssiDescriptor->get_program(fHandle, newCount) != nullptr;) | |||
| ++newCount; | |||
| } | |||
| if (newCount > 0) | |||
| @@ -1061,8 +1013,6 @@ public: | |||
| } | |||
| pData->needsReset = false; | |||
| CARLA_PROCESS_CONTINUE_CHECK; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| @@ -1075,7 +1025,7 @@ public: | |||
| if (pData->extNotes.mutex.tryLock()) | |||
| { | |||
| while (midiEventCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty()) | |||
| for (; midiEventCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();) | |||
| { | |||
| const ExternalMidiNote& note(pData->extNotes.data.getFirst(true)); | |||
| @@ -1100,33 +1050,31 @@ public: | |||
| bool allNotesOffSent = false; | |||
| bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
| uint32_t time, numEvents = pData->event.portIn->getEventCount(); | |||
| uint32_t numEvents = pData->event.portIn->getEventCount(); | |||
| uint32_t startTime = 0; | |||
| uint32_t timeOffset = 0; | |||
| uint32_t nextBankId = 0; | |||
| uint32_t nextBankId; | |||
| if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | |||
| nextBankId = pData->midiprog.data[pData->midiprog.current].bank; | |||
| else | |||
| nextBankId = 0; | |||
| for (uint32_t i=0; i < numEvents; ++i) | |||
| { | |||
| const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
| time = event.time; | |||
| CARLA_ASSERT_INT2(time < frames, time, frames); | |||
| if (time >= frames) | |||
| if (event.time >= frames) | |||
| continue; | |||
| CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset); | |||
| CARLA_ASSERT_INT2(event.time >= timeOffset, event.time, timeOffset); | |||
| if (time > timeOffset && isSampleAccurate) | |||
| if (isSampleAccurate && event.time > timeOffset) | |||
| { | |||
| if (processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset, midiEventCount)) | |||
| if (processSingle(inBuffer, outBuffer, event.time - timeOffset, timeOffset, midiEventCount)) | |||
| { | |||
| startTime = 0; | |||
| timeOffset = time; | |||
| timeOffset = event.time; | |||
| midiEventCount = 0; | |||
| if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | |||
| @@ -1143,8 +1091,7 @@ public: | |||
| case kEngineEventTypeNull: | |||
| break; | |||
| case kEngineEventTypeControl: | |||
| { | |||
| case kEngineEventTypeControl: { | |||
| const EngineControlEvent& ctrlEvent(event.ctrl); | |||
| switch (ctrlEvent.type) | |||
| @@ -1152,8 +1099,7 @@ public: | |||
| case kEngineControlEventTypeNull: | |||
| break; | |||
| case kEngineControlEventTypeParameter: | |||
| { | |||
| case kEngineControlEventTypeParameter: { | |||
| #ifndef BUILD_BRIDGE | |||
| // Control backend stuff | |||
| if (event.channel == pData->ctrlChannel) | |||
| @@ -1165,6 +1111,7 @@ public: | |||
| value = ctrlEvent.value; | |||
| setDryWet(value, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value); | |||
| break; | |||
| } | |||
| if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) | |||
| @@ -1172,6 +1119,7 @@ public: | |||
| value = ctrlEvent.value*127.0f/100.0f; | |||
| setVolume(value, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value); | |||
| break; | |||
| } | |||
| if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) | |||
| @@ -1199,12 +1147,14 @@ public: | |||
| setBalanceRight(right, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right); | |||
| break; | |||
| } | |||
| } | |||
| #endif | |||
| // Control plugin parameters | |||
| for (uint32_t k=0; k < pData->param.count; ++k) | |||
| uint32_t k; | |||
| for (k=0; k < pData->param.count; ++k) | |||
| { | |||
| if (pData->param.data[k].midiChannel != event.channel) | |||
| continue; | |||
| @@ -1231,8 +1181,13 @@ public: | |||
| setParameterValue(k, value, false, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value); | |||
| break; | |||
| } | |||
| // check if event is already handled | |||
| if (k == pData->param.count) | |||
| break; | |||
| if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F) | |||
| { | |||
| if (midiEventCount >= kPluginMaxMidiEvents) | |||
| @@ -1241,7 +1196,7 @@ public: | |||
| snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]); | |||
| carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : time; | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
| midiEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
| midiEvent.data.control.channel = event.channel; | |||
| @@ -1250,7 +1205,7 @@ public: | |||
| } | |||
| break; | |||
| } | |||
| } // case kEngineControlEventTypeParameter | |||
| case kEngineControlEventTypeMidiBank: | |||
| if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0) | |||
| @@ -1284,7 +1239,7 @@ public: | |||
| snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]); | |||
| carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : time; | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
| midiEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
| midiEvent.data.control.channel = event.channel; | |||
| @@ -1307,7 +1262,7 @@ public: | |||
| snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]); | |||
| carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : time; | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
| midiEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
| midiEvent.data.control.channel = event.channel; | |||
| @@ -1316,13 +1271,11 @@ public: | |||
| midiEventCount += 1; | |||
| } | |||
| break; | |||
| } | |||
| } // switch (ctrlEvent.type) | |||
| break; | |||
| } | |||
| } // case kEngineEventTypeControl | |||
| case kEngineEventTypeMidi: | |||
| { | |||
| case kEngineEventTypeMidi: { | |||
| if (midiEventCount >= kPluginMaxMidiEvents) | |||
| continue; | |||
| @@ -1338,12 +1291,11 @@ public: | |||
| snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount]); | |||
| carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : time; | |||
| midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
| switch (status) | |||
| { | |||
| case MIDI_STATUS_NOTE_OFF: | |||
| { | |||
| case MIDI_STATUS_NOTE_OFF: { | |||
| const uint8_t note = engineEvent.data[1]; | |||
| midiEvent.type = SND_SEQ_EVENT_NOTEOFF; | |||
| @@ -1353,8 +1305,8 @@ public: | |||
| pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, note, 0.0f); | |||
| break; | |||
| } | |||
| case MIDI_STATUS_NOTE_ON: | |||
| { | |||
| case MIDI_STATUS_NOTE_ON: { | |||
| const uint8_t note = engineEvent.data[1]; | |||
| const uint8_t velo = engineEvent.data[2]; | |||
| @@ -1366,8 +1318,8 @@ public: | |||
| pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, note, velo); | |||
| break; | |||
| } | |||
| case MIDI_STATUS_POLYPHONIC_AFTERTOUCH: | |||
| { | |||
| if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) | |||
| { | |||
| const uint8_t note = engineEvent.data[1]; | |||
| @@ -1379,9 +1331,8 @@ public: | |||
| midiEvent.data.note.velocity = pressure; | |||
| } | |||
| break; | |||
| } | |||
| case MIDI_STATUS_CONTROL_CHANGE: | |||
| { | |||
| if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) | |||
| { | |||
| const uint8_t control = engineEvent.data[1]; | |||
| @@ -1393,9 +1344,8 @@ public: | |||
| midiEvent.data.control.value = value; | |||
| } | |||
| break; | |||
| } | |||
| case MIDI_STATUS_CHANNEL_PRESSURE: | |||
| { | |||
| if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) | |||
| { | |||
| const uint8_t pressure = engineEvent.data[1]; | |||
| @@ -1405,9 +1355,8 @@ public: | |||
| midiEvent.data.control.value = pressure; | |||
| } | |||
| break; | |||
| } | |||
| case MIDI_STATUS_PITCH_WHEEL_CONTROL: | |||
| { | |||
| if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) | |||
| { | |||
| const uint8_t lsb = engineEvent.data[1]; | |||
| @@ -1418,16 +1367,16 @@ public: | |||
| midiEvent.data.control.value = ((msb << 7) | lsb) - 8192; | |||
| } | |||
| break; | |||
| } | |||
| default: | |||
| continue; | |||
| break; | |||
| } | |||
| } // switch (status) | |||
| midiEventCount += 1; | |||
| break; | |||
| } | |||
| } | |||
| } // case kEngineEventTypeMidi | |||
| } // switch (event.type) | |||
| } | |||
| pData->postRtEvents.trySplice(); | |||
| @@ -1814,7 +1763,7 @@ public: | |||
| const void* getExtraStuff() const noexcept override | |||
| { | |||
| return fGuiFilename; | |||
| return fUiFilename; | |||
| } | |||
| bool init(const char* const filename, const char* const name, const char* const label) | |||
| @@ -1945,7 +1894,7 @@ public: | |||
| if (const char* const guiFilename = find_dssi_ui(filename, fDescriptor->Label)) | |||
| { | |||
| pData->osc.thread.setOscData(guiFilename, fDescriptor->Label); | |||
| fGuiFilename = guiFilename; | |||
| fUiFilename = guiFilename; | |||
| } | |||
| // --------------------------------------------------------------- | |||
| @@ -2015,7 +1964,7 @@ private: | |||
| const DSSI_Descriptor* fDssiDescriptor; | |||
| bool fUsesCustomData; | |||
| const char* fGuiFilename; | |||
| const char* fUiFilename; | |||
| float** fAudioInBuffers; | |||
| float** fAudioOutBuffers; | |||
| @@ -550,7 +550,6 @@ public: | |||
| else if (LADSPA_IS_PORT_CONTROL(portType)) | |||
| { | |||
| uint32_t j = iCtrl++; | |||
| pData->param.data[j].type = PARAMETER_UNKNOWN; | |||
| pData->param.data[j].hints = 0x0; | |||
| pData->param.data[j].index = static_cast<int32_t>(j); | |||
| pData->param.data[j].rindex = static_cast<int32_t>(i); | |||
| @@ -645,16 +644,6 @@ public: | |||
| pData->param.data[j].type = PARAMETER_SPECIAL; | |||
| pData->param.special[j] = PARAMETER_SPECIAL_LATENCY; | |||
| } | |||
| else if (std::strcmp(fDescriptor->PortNames[i], "_sample-rate") == 0) | |||
| { | |||
| def = sampleRate; | |||
| step = 1.0f; | |||
| stepSmall = 1.0f; | |||
| stepLarge = 1.0f; | |||
| pData->param.data[j].type = PARAMETER_SPECIAL; | |||
| pData->param.special[j] = PARAMETER_SPECIAL_SAMPLE_RATE; | |||
| } | |||
| else | |||
| { | |||
| pData->param.data[j].type = PARAMETER_OUTPUT; | |||
| @@ -665,6 +654,7 @@ public: | |||
| } | |||
| else | |||
| { | |||
| pData->param.data[j].type = PARAMETER_UNKNOWN; | |||
| carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)"); | |||
| } | |||
| @@ -872,7 +862,6 @@ public: | |||
| // disable any output sound | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| FLOAT_CLEAR(outBuffer[i], frames); | |||
| return; | |||
| } | |||
| @@ -900,34 +889,30 @@ public: | |||
| bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
| uint32_t time, numEvents = pData->event.portIn->getEventCount(); | |||
| uint32_t numEvents = pData->event.portIn->getEventCount(); | |||
| uint32_t timeOffset = 0; | |||
| for (uint32_t i=0; i < numEvents; ++i) | |||
| { | |||
| const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
| time = event.time; | |||
| if (time >= frames) | |||
| if (event.time >= frames) | |||
| continue; | |||
| CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset); | |||
| CARLA_ASSERT_INT2(event.time >= timeOffset, event.time, timeOffset); | |||
| if (time > timeOffset && isSampleAccurate) | |||
| if (isSampleAccurate && event.time > timeOffset) | |||
| { | |||
| if (processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset)) | |||
| timeOffset = time; | |||
| if (processSingle(inBuffer, outBuffer, event.time - timeOffset, timeOffset)) | |||
| timeOffset = event.time; | |||
| } | |||
| // Control change | |||
| switch (event.type) | |||
| { | |||
| case kEngineEventTypeNull: | |||
| break; | |||
| case kEngineEventTypeControl: | |||
| { | |||
| case kEngineEventTypeControl: { | |||
| const EngineControlEvent& ctrlEvent(event.ctrl); | |||
| switch (ctrlEvent.type) | |||
| @@ -935,8 +920,7 @@ public: | |||
| case kEngineControlEventTypeNull: | |||
| break; | |||
| case kEngineControlEventTypeParameter: | |||
| { | |||
| case kEngineControlEventTypeParameter: { | |||
| #ifndef BUILD_BRIDGE | |||
| // Control backend stuff | |||
| if (event.channel == pData->ctrlChannel) | |||
| @@ -948,6 +932,7 @@ public: | |||
| value = ctrlEvent.value; | |||
| setDryWet(value, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value); | |||
| break; | |||
| } | |||
| if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0) | |||
| @@ -955,6 +940,7 @@ public: | |||
| value = ctrlEvent.value*127.0f/100.0f; | |||
| setVolume(value, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value); | |||
| break; | |||
| } | |||
| if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0) | |||
| @@ -982,6 +968,7 @@ public: | |||
| setBalanceRight(right, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right); | |||
| break; | |||
| } | |||
| } | |||
| #endif | |||
| @@ -1014,25 +1001,24 @@ public: | |||
| setParameterValue(k, value, false, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value); | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| } // case kEngineControlEventTypeParameter | |||
| case kEngineControlEventTypeMidiBank: | |||
| case kEngineControlEventTypeMidiProgram: | |||
| case kEngineControlEventTypeAllSoundOff: | |||
| case kEngineControlEventTypeAllNotesOff: | |||
| break; | |||
| } | |||
| } // switch (ctrlEvent.type) | |||
| break; | |||
| } | |||
| } // case kEngineEventTypeControl | |||
| case kEngineEventTypeMidi: | |||
| // ignored in LADSPA | |||
| break; | |||
| } | |||
| } // switch (event.type) | |||
| } | |||
| pData->postRtEvents.trySplice(); | |||
| @@ -71,10 +71,10 @@ LadspaPlugin.cpp.o: LadspaPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| DssiPlugin.cpp.o: DssiPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_DSSI_UTILS_HPP) $(CARLA_MATH_UTILS_HPP) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ # FIXME | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||
| Lv2Plugin.cpp.o: Lv2Plugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_LV2_UTILS_HPP) $(CARLA_MATH_UTILS_HPP) $(LV2_ATOM_QUEUE_HPP) $(CARLA_ENGINE_OSC_HPP) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ # FIXME | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ # FIXME - remove qtcore? | |||
| VstPlugin.cpp.o: VstPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_VST_UTILS_HPP) $(CARLA_MATH_UTILS_HPP) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| @@ -1924,6 +1924,10 @@ const char* carla_get_host_osc_url_udp() | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| #ifdef WANT_DSSI | |||
| # include "CarlaDssiUtils.cpp" | |||
| #endif | |||
| #include "CarlaStateUtils.cpp" | |||
| #if 0 | |||
| @@ -1376,7 +1376,7 @@ class PluginEdit(QDialog): | |||
| self.fTabIconTimers.append(ICON_STATE_NULL) | |||
| def _updateCtrlMidiProgram(self): | |||
| if self.fPluginInfo['type'] not in (PLUGIN_INTERNAL, PLUGIN_SF2): | |||
| if self.fPluginInfo['type'] not in (PLUGIN_INTERNAL, PLUGIN_FILE_SF2): | |||
| return | |||
| elif self.fPluginInfo['category'] != PLUGIN_CATEGORY_SYNTH: | |||
| return | |||
| @@ -10,6 +10,10 @@ include ../Makefile.mk | |||
| BUILD_CXX_FLAGS += -I../backend -I../includes -I../utils -isystem ../modules -Wno-multichar | |||
| ifeq ($(MACOS),true) | |||
| BUILD_CXX_FLAGS += -ObjC++ | |||
| endif | |||
| BUILD_CXX_FLAGS += $(QTCORE_FLAGS) | |||
| LINK_FLAGS += $(QTCORE_LIBS) | |||
| @@ -18,7 +22,8 @@ LINK_FLAGS += $(QTCORE_LIBS) | |||
| BUILD_CXX_FLAGS += -DWANT_NATIVE | |||
| ifeq ($(CARLA_PLUGIN_SUPPORT),true) | |||
| BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 | |||
| BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI | |||
| # -DWANT_LV2 | |||
| # -DWANT_VST | |||
| # ifeq ($(CARLA_VESTIGE_HEADER),true) | |||
| # BUILD_CXX_FLAGS += -DVESTIGE_HEADER | |||
| @@ -78,11 +83,8 @@ WIN_32BIT_FLAGS = $(32BIT_FLAGS) | |||
| WIN_64BIT_FLAGS = $(64BIT_FLAGS) | |||
| WIN_LINK_FLAGS = $(LINK_FLAGS) $(EXTRA_LIBS) | |||
| ifeq ($(MACOS),true) | |||
| OBJS = carla-discovery.mm.o | |||
| else | |||
| OBJS = carla-discovery.cpp | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| @@ -66,14 +66,14 @@ CARLA_BACKEND_USE_NAMESPACE | |||
| // -------------------------------------------------------------------------- | |||
| // Dummy values to test plugins with | |||
| const uint32_t kBufferSize = 512; | |||
| const double kSampleRate = 44100.0; | |||
| const float kSampleRatef = 44100.0f; | |||
| static const uint32_t kBufferSize = 512; | |||
| static const double kSampleRate = 44100.0; | |||
| static const float kSampleRatef = 44100.0f; | |||
| // -------------------------------------------------------------------------- | |||
| // Don't print ELF/EXE related errors since discovery can find multi-architecture binaries | |||
| void print_lib_error(const char* const filename) | |||
| static void print_lib_error(const char* const filename) | |||
| { | |||
| const char* const error(lib_error(filename)); | |||
| @@ -86,22 +86,22 @@ void print_lib_error(const char* const filename) | |||
| // VST stuff | |||
| // Check if plugin is currently processing | |||
| bool gVstIsProcessing = false; | |||
| static bool gVstIsProcessing = false; | |||
| // Check if plugin needs idle | |||
| bool gVstNeedsIdle = false; | |||
| static bool gVstNeedsIdle = false; | |||
| // Check if plugin wants midi | |||
| bool gVstWantsMidi = false; | |||
| static bool gVstWantsMidi = false; | |||
| // Check if plugin wants time | |||
| bool gVstWantsTime = false; | |||
| static bool gVstWantsTime = false; | |||
| // Current uniqueId for VST shell plugins | |||
| intptr_t gVstCurrentUniqueId = 0; | |||
| static intptr_t gVstCurrentUniqueId = 0; | |||
| // Supported Carla features | |||
| intptr_t vstHostCanDo(const char* const feature) | |||
| static intptr_t vstHostCanDo(const char* const feature) | |||
| { | |||
| carla_debug("vstHostCanDo(\"%s\")", feature); | |||
| @@ -153,7 +153,7 @@ intptr_t vstHostCanDo(const char* const feature) | |||
| } | |||
| // Host-side callback | |||
| intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) | |||
| static intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) | |||
| { | |||
| carla_debug("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)", effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, opt); | |||
| @@ -431,7 +431,7 @@ private: | |||
| // ------------------------------ Plugin Checks ----------------------------- | |||
| void do_ladspa_check(void*& libHandle, const char* const filename, const bool init) | |||
| static void do_ladspa_check(void*& libHandle, const char* const filename, const bool init) | |||
| { | |||
| #ifdef WANT_LADSPA | |||
| LADSPA_Descriptor_Function descFn = (LADSPA_Descriptor_Function)lib_symbol(libHandle, "ladspa_descriptor"); | |||
| @@ -508,7 +508,7 @@ void do_ladspa_check(void*& libHandle, const char* const filename, const bool in | |||
| DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable"); | |||
| } | |||
| int hints = 0x0; | |||
| uint hints = 0x0; | |||
| int audioIns = 0; | |||
| int audioOuts = 0; | |||
| int audioTotal = 0; | |||
| @@ -675,7 +675,7 @@ void do_ladspa_check(void*& libHandle, const char* const filename, const bool in | |||
| #endif | |||
| } | |||
| void do_dssi_check(void*& libHandle, const char* const filename, const bool init) | |||
| static void do_dssi_check(void*& libHandle, const char* const filename, const bool init) | |||
| { | |||
| #ifdef WANT_DSSI | |||
| DSSI_Descriptor_Function descFn = (DSSI_Descriptor_Function)lib_symbol(libHandle, "dssi_descriptor"); | |||
| @@ -726,7 +726,7 @@ void do_dssi_check(void*& libHandle, const char* const filename, const bool init | |||
| return; | |||
| } | |||
| DSSI_Descriptor_Function descFn = (DSSI_Descriptor_Function)lib_symbol(libHandle, "dssi_descriptor"); | |||
| descFn = (DSSI_Descriptor_Function)lib_symbol(libHandle, "dssi_descriptor"); | |||
| if (descFn == nullptr) | |||
| { | |||
| @@ -772,7 +772,7 @@ void do_dssi_check(void*& libHandle, const char* const filename, const bool init | |||
| DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable"); | |||
| } | |||
| int hints = 0x0; | |||
| uint hints = 0x0; | |||
| int audioIns = 0; | |||
| int audioOuts = 0; | |||
| int audioTotal = 0; | |||
| @@ -780,7 +780,7 @@ void do_dssi_check(void*& libHandle, const char* const filename, const bool init | |||
| int parametersIns = 0; | |||
| int parametersOuts = 0; | |||
| int parametersTotal = 0; | |||
| int programs = 0; | |||
| ulong programs = 0; | |||
| if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties)) | |||
| hints |= PLUGIN_IS_RTSAFE; | |||
| @@ -816,13 +816,11 @@ void do_dssi_check(void*& libHandle, const char* const filename, const bool init | |||
| if (midiIns > 0 && audioIns == 0 && audioOuts > 0) | |||
| hints |= PLUGIN_IS_SYNTH; | |||
| #if 0 // FIXME | |||
| if (const char* const ui = find_dssi_ui(filename, ldescriptor->Label)) | |||
| { | |||
| hints |= PLUGIN_HAS_CUSTOM_UI; | |||
| delete[] ui; | |||
| } | |||
| #endif | |||
| if (init) | |||
| { | |||
| @@ -850,8 +848,8 @@ void do_dssi_check(void*& libHandle, const char* const filename, const bool init | |||
| if (descriptor->get_program != nullptr && descriptor->select_program != nullptr) | |||
| { | |||
| while (descriptor->get_program(handle, programs++) != nullptr) | |||
| continue; | |||
| for (; descriptor->get_program(handle, programs) != nullptr;) | |||
| ++programs; | |||
| } | |||
| LADSPA_Data bufferAudio[kBufferSize][audioTotal]; | |||
| @@ -997,7 +995,7 @@ void do_dssi_check(void*& libHandle, const char* const filename, const bool init | |||
| #endif | |||
| } | |||
| void do_lv2_check(const char* const bundle, const bool init) | |||
| static void do_lv2_check(const char* const bundle, const bool init) | |||
| { | |||
| #ifdef WANT_LV2 | |||
| Lv2WorldClass& lv2World(Lv2WorldClass::getInstance()); | |||
| @@ -1212,7 +1210,7 @@ void do_lv2_check(const char* const bundle, const bool init) | |||
| #endif | |||
| } | |||
| void do_vst_check(void*& libHandle, const bool init) | |||
| static void do_vst_check(void*& libHandle, const bool init) | |||
| { | |||
| #ifdef WANT_VST | |||
| VST_Function vstFn = (VST_Function)lib_symbol(libHandle, "VSTPluginMain"); | |||
| @@ -1456,7 +1454,7 @@ void do_vst_check(void*& libHandle, const bool init) | |||
| #endif | |||
| } | |||
| void do_au_check(void*& libHandle, const bool init) | |||
| static void do_au_check(void*& libHandle, const bool init) | |||
| { | |||
| #if 0 //def WANT_AU | |||
| #else | |||
| @@ -1470,7 +1468,7 @@ void do_au_check(void*& libHandle, const bool init) | |||
| }; | |||
| #ifdef HAVE_JUCE | |||
| void do_juce_check(const char* const filename, const char* const stype, const bool init) | |||
| static void do_juce_check(const char* const filename, const char* const stype, const bool init) | |||
| { | |||
| using namespace juce; | |||
| @@ -1556,7 +1554,7 @@ void do_juce_check(const char* const filename, const char* const stype, const bo | |||
| } | |||
| #endif | |||
| void do_csound_check(const char* const filename, const bool init) | |||
| static void do_csound_check(const char* const filename, const bool init) | |||
| { | |||
| #ifdef WANT_CSOUND | |||
| Csound csound; | |||
| @@ -1659,7 +1657,7 @@ void do_csound_check(const char* const filename, const bool init) | |||
| #endif | |||
| } | |||
| void do_fluidsynth_check(const char* const filename, const bool init) | |||
| static void do_fluidsynth_check(const char* const filename, const bool init) | |||
| { | |||
| #ifdef WANT_FLUIDSYNTH | |||
| if (! fluid_is_soundfont(filename)) | |||
| @@ -1685,7 +1683,7 @@ void do_fluidsynth_check(const char* const filename, const bool init) | |||
| fluid_sfont_t* f_sfont; | |||
| fluid_preset_t f_preset; | |||
| f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id); | |||
| f_sfont = fluid_synth_get_sfont_by_id(f_synth, static_cast<uint>(f_id)); | |||
| f_sfont->iteration_start(f_sfont); | |||
| while (f_sfont->iteration_next(f_sfont, &f_preset)) | |||
| @@ -1745,7 +1743,7 @@ void do_fluidsynth_check(const char* const filename, const bool init) | |||
| #endif | |||
| } | |||
| void do_linuxsampler_check(const char* const filename, const char* const stype, const bool init) | |||
| static void do_linuxsampler_check(const char* const filename, const char* const stype, const bool init) | |||
| { | |||
| #ifdef WANT_LINUXSAMPLER | |||
| const QFileInfo file(filename); | |||
| @@ -1932,6 +1930,13 @@ int main(int argc, char* argv[]) | |||
| return 0; | |||
| } | |||
| // -------------------------------------------------------------------------- | |||
| // Extras | |||
| #ifdef WANT_DSSI | |||
| # include "CarlaDssiUtils.cpp" | |||
| #endif | |||
| #ifdef HAVE_JUCE | |||
| // -------------------------------------------------------------------------- | |||
| // we want juce_audio_processors but without UI code | |||
| @@ -1,18 +0,0 @@ | |||
| /* | |||
| * Carla Plugin discovery, MacOS objc++ file | |||
| * Copyright (C) 2014 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "carla-discovery.cpp" | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Carla DSSI utils | |||
| * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaDssiUtils.hpp" | |||
| #include <QtCore/QDir> | |||
| #include <QtCore/QFileInfo> | |||
| #include <QtCore/QStringList> | |||
| // ----------------------------------------------------------------------- | |||
| const char* find_dssi_ui(const char* const filename, const char* const label) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0', nullptr); | |||
| carla_debug("find_dssi_ui(\"%s\", \"%s\")", filename, label); | |||
| QString guiFilename; | |||
| QString pluginDir(filename); | |||
| pluginDir.resize(pluginDir.lastIndexOf(".")); | |||
| QString checkLabel(label); | |||
| QString checkSName(QFileInfo(pluginDir).baseName()); | |||
| if (! checkLabel.endsWith("_")) checkLabel += "_"; | |||
| if (! checkSName.endsWith("_")) checkSName += "_"; | |||
| QStringList guiFiles(QDir(pluginDir).entryList()); | |||
| foreach (const QString& gui, guiFiles) | |||
| { | |||
| if (gui.startsWith(checkLabel) || gui.startsWith(checkSName)) | |||
| { | |||
| QFileInfo finalname(pluginDir + QDir::separator() + gui); | |||
| guiFilename = finalname.absoluteFilePath(); | |||
| break; | |||
| } | |||
| } | |||
| if (guiFilename.isEmpty()) | |||
| return nullptr; | |||
| return carla_strdup(guiFilename.toUtf8().constData()); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla DSSI utils | |||
| * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -21,50 +21,10 @@ | |||
| #include "CarlaLadspaUtils.hpp" | |||
| #include "dssi/dssi.h" | |||
| // TODO - put this in a cpp file | |||
| //#include <QtCore/QDir> | |||
| //#include <QtCore/QFileInfo> | |||
| //#include <QtCore/QStringList> | |||
| // ----------------------------------------------------------------------- | |||
| // Find UI binary for a plugin (returned value must be deleted) | |||
| //static inline | |||
| const char* find_dssi_ui(const char* const filename, const char* const label); | |||
| #if 0 | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0', nullptr); | |||
| carla_debug("find_dssi_ui(\"%s\", \"%s\")", filename, label); | |||
| QString guiFilename; | |||
| QString pluginDir(filename); | |||
| pluginDir.resize(pluginDir.lastIndexOf(".")); | |||
| QString checkLabel(label); | |||
| QString checkSName(QFileInfo(pluginDir).baseName()); | |||
| if (! checkLabel.endsWith("_")) checkLabel += "_"; | |||
| if (! checkSName.endsWith("_")) checkSName += "_"; | |||
| QStringList guiFiles(QDir(pluginDir).entryList()); | |||
| foreach (const QString& gui, guiFiles) | |||
| { | |||
| if (gui.startsWith(checkLabel) || gui.startsWith(checkSName)) | |||
| { | |||
| QFileInfo finalname(pluginDir + QDir::separator() + gui); | |||
| guiFilename = finalname.absoluteFilePath(); | |||
| break; | |||
| } | |||
| } | |||
| if (guiFilename.isEmpty()) | |||
| return nullptr; | |||
| return carla_strdup(guiFilename.toUtf8().constData()); | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||