| @@ -0,0 +1,471 @@ | |||||
| /* | |||||
| * DISTRHO Plugin Framework (DPF) | |||||
| * Copyright (C) 2012-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 Lesser General Public | |||||
| * License as published by the Free Software Foundation. | |||||
| * | |||||
| * 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 Lesser General Public License for more details. | |||||
| * | |||||
| * For a full copy of the license see the LGPL.txt file | |||||
| */ | |||||
| #include "DistrhoPluginInternal.hpp" | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| # include "DistrhoUIInternal.hpp" | |||||
| #endif | |||||
| #include "CarlaNative.hpp" | |||||
| // ----------------------------------------------------------------------- | |||||
| START_NAMESPACE_DISTRHO | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| // ----------------------------------------------------------------------- | |||||
| // Carla UI | |||||
| #if ! DISTRHO_PLUGIN_WANT_STATE | |||||
| static const setStateFunc setStateCallback = nullptr; | |||||
| #endif | |||||
| #if ! DISTRHO_PLUGIN_IS_SYNTH | |||||
| static const sendNoteFunc sendNoteCallback = nullptr; | |||||
| #endif | |||||
| class UICarla | |||||
| { | |||||
| public: | |||||
| UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin) | |||||
| : fHost(host), | |||||
| fPlugin(plugin), | |||||
| fUI(this, 0, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback) | |||||
| { | |||||
| fUI.setTitle(host->uiName); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| void carla_show(const bool yesNo) | |||||
| { | |||||
| fUI.setVisible(yesNo); | |||||
| } | |||||
| void carla_idle() | |||||
| { | |||||
| fUI.idle(); | |||||
| } | |||||
| void carla_setParameterValue(const uint32_t index, const float value) | |||||
| { | |||||
| fUI.parameterChanged(index, value); | |||||
| } | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| void carla_setMidiProgram(const uint32_t realProgram) | |||||
| { | |||||
| fUI.programChanged(realProgram); | |||||
| } | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_WANT_STATE | |||||
| void carla_setCustomData(const char* const key, const char* const value) | |||||
| { | |||||
| fUI.stateChanged(key, value); | |||||
| } | |||||
| #endif | |||||
| void carla_setUiTitle(const char* const uiTitle) | |||||
| { | |||||
| fUI.setTitle(uiTitle); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| protected: | |||||
| void handleEditParameter(const uint32_t, const bool) | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| void handleSetParameterValue(const uint32_t rindex, const float value) | |||||
| { | |||||
| fHost->ui_parameter_changed(fHost->handle, rindex, value); | |||||
| } | |||||
| void handleSetState(const char* const key, const char* const value) | |||||
| { | |||||
| fHost->ui_custom_data_changed(fHost->handle, key, value); | |||||
| } | |||||
| void handleSendNote(const uint8_t, const uint8_t, const uint8_t) | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| void handleUiResize(const unsigned int width, const unsigned int height) | |||||
| { | |||||
| fUI.setSize(width, height); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| private: | |||||
| // Plugin stuff | |||||
| const NativeHostDescriptor* const fHost; | |||||
| PluginExporter* const fPlugin; | |||||
| // UI | |||||
| UIExporter fUI; | |||||
| // --------------------------------------------- | |||||
| // Callbacks | |||||
| #define handlePtr ((UICarla*)ptr) | |||||
| static void editParameterCallback(void* ptr, uint32_t index, bool started) | |||||
| { | |||||
| handlePtr->handleEditParameter(index, started); | |||||
| } | |||||
| static void setParameterCallback(void* ptr, uint32_t rindex, float value) | |||||
| { | |||||
| handlePtr->handleSetParameterValue(rindex, value); | |||||
| } | |||||
| #if DISTRHO_PLUGIN_WANT_STATE | |||||
| static void setStateCallback(void* ptr, const char* key, const char* value) | |||||
| { | |||||
| handlePtr->handleSetState(key, value); | |||||
| } | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity) | |||||
| { | |||||
| handlePtr->handleSendNote(channel, note, velocity); | |||||
| } | |||||
| #endif | |||||
| static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height) | |||||
| { | |||||
| handlePtr->handleUiResize(width, height); | |||||
| } | |||||
| #undef handlePtr | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UICarla) | |||||
| }; | |||||
| #endif // DISTRHO_PLUGIN_HAS_UI | |||||
| // ----------------------------------------------------------------------- | |||||
| // Carla Plugin | |||||
| class PluginCarla : public NativePluginClass | |||||
| { | |||||
| public: | |||||
| PluginCarla(const NativeHostDescriptor* const host) | |||||
| : NativePluginClass(host) | |||||
| { | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| fUiPtr = nullptr; | |||||
| #endif | |||||
| } | |||||
| ~PluginCarla() override | |||||
| { | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| if (fUiPtr != nullptr) | |||||
| { | |||||
| delete fUiPtr; | |||||
| fUiPtr = nullptr; | |||||
| } | |||||
| #endif | |||||
| } | |||||
| protected: | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin parameter calls | |||||
| uint32_t getParameterCount() const override | |||||
| { | |||||
| return fPlugin.getParameterCount(); | |||||
| } | |||||
| const NativeParameter* getParameterInfo(const uint32_t index) const override | |||||
| { | |||||
| CARLA_ASSERT(index < getParameterCount()); | |||||
| static NativeParameter param; | |||||
| // reset | |||||
| param.hints = ::PARAMETER_IS_ENABLED; | |||||
| param.scalePointCount = 0; | |||||
| param.scalePoints = nullptr; | |||||
| { | |||||
| int nativeParamHints = ::PARAMETER_IS_ENABLED; | |||||
| const uint32_t paramHints = fPlugin.getParameterHints(index); | |||||
| if (paramHints & PARAMETER_IS_AUTOMABLE) | |||||
| nativeParamHints |= ::PARAMETER_IS_AUTOMABLE; | |||||
| if (paramHints & PARAMETER_IS_BOOLEAN) | |||||
| nativeParamHints |= ::PARAMETER_IS_BOOLEAN; | |||||
| if (paramHints & PARAMETER_IS_INTEGER) | |||||
| nativeParamHints |= ::PARAMETER_IS_INTEGER; | |||||
| if (paramHints & PARAMETER_IS_LOGARITHMIC) | |||||
| nativeParamHints |= ::PARAMETER_IS_LOGARITHMIC; | |||||
| if (paramHints & PARAMETER_IS_OUTPUT) | |||||
| nativeParamHints |= ::PARAMETER_IS_OUTPUT; | |||||
| param.hints = static_cast<NativeParameterHints>(nativeParamHints); | |||||
| } | |||||
| param.name = fPlugin.getParameterName(index); | |||||
| param.unit = fPlugin.getParameterUnit(index); | |||||
| { | |||||
| const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); | |||||
| param.ranges.def = ranges.def; | |||||
| param.ranges.min = ranges.min; | |||||
| param.ranges.max = ranges.max; | |||||
| //param.ranges.step = ranges.step; | |||||
| //param.ranges.stepSmall = ranges.stepSmall; | |||||
| //param.ranges.stepLarge = ranges.stepLarge; | |||||
| } | |||||
| return ¶m; | |||||
| } | |||||
| float getParameterValue(const uint32_t index) const override | |||||
| { | |||||
| CARLA_ASSERT(index < getParameterCount()); | |||||
| return fPlugin.getParameterValue(index); | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin midi-program calls | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| uint32_t getMidiProgramCount() const override | |||||
| { | |||||
| return fPlugin.getProgramCount(); | |||||
| } | |||||
| const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const override | |||||
| { | |||||
| CARLA_ASSERT(index < getMidiProgramCount()); | |||||
| if (index >= fPlugin.getProgramCount()) | |||||
| return nullptr; | |||||
| static NativeMidiProgram midiProgram; | |||||
| midiProgram.bank = index / 128; | |||||
| midiProgram.program = index % 128; | |||||
| midiProgram.name = fPlugin.getProgramName(index); | |||||
| return &midiProgram; | |||||
| } | |||||
| #endif | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin state calls | |||||
| void setParameterValue(const uint32_t index, const float value) override | |||||
| { | |||||
| CARLA_ASSERT(index < getParameterCount()); | |||||
| fPlugin.setParameterValue(index, value); | |||||
| } | |||||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override | |||||
| { | |||||
| const uint32_t realProgram(bank * 128 + program); | |||||
| if (realProgram >= fPlugin.getProgramCount()) | |||||
| return; | |||||
| fPlugin.setProgram(realProgram); | |||||
| } | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_WANT_STATE | |||||
| void setCustomData(const char* const key, const char* const value) override | |||||
| { | |||||
| CARLA_ASSERT(key != nullptr); | |||||
| CARLA_ASSERT(value != nullptr); | |||||
| fPlugin.setState(key, value); | |||||
| } | |||||
| #endif | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin process calls | |||||
| void activate() override | |||||
| { | |||||
| fPlugin.activate(); | |||||
| } | |||||
| void deactivate() override | |||||
| { | |||||
| fPlugin.deactivate(); | |||||
| } | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override | |||||
| { | |||||
| uint32_t i; | |||||
| for (i=0; i < midiEventCount && i < kMaxMidiEvents; ++i) | |||||
| { | |||||
| const NativeMidiEvent* const midiEvent(&midiEvents[i]); | |||||
| MidiEvent* const realMidiEvent(&fRealMidiEvents[i]); | |||||
| realMidiEvent->frame = midiEvent->time; | |||||
| realMidiEvent->size = midiEvent->size; | |||||
| for (uint8_t j=0; j < midiEvent->size; ++j) | |||||
| realMidiEvent->buf[j] = midiEvent->data[j]; | |||||
| } | |||||
| fPlugin.run(inBuffer, outBuffer, frames, fRealMidiEvents, i); | |||||
| } | |||||
| #else | |||||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override | |||||
| { | |||||
| fPlugin.run(inBuffer, outBuffer, frames); | |||||
| } | |||||
| #endif | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin UI calls | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| void uiShow(const bool show) override | |||||
| { | |||||
| if (show) | |||||
| createUiIfNeeded(); | |||||
| if (fUiPtr != nullptr) | |||||
| fUiPtr->carla_show(show); | |||||
| } | |||||
| void uiIdle() override | |||||
| { | |||||
| CARLA_ASSERT(fUiPtr != nullptr); | |||||
| if (fUiPtr != nullptr) | |||||
| fUiPtr->carla_idle(); | |||||
| } | |||||
| void uiSetParameterValue(const uint32_t index, const float value) override | |||||
| { | |||||
| CARLA_ASSERT(fUiPtr != nullptr); | |||||
| CARLA_ASSERT(index < getParameterCount()); | |||||
| if (fUiPtr != nullptr) | |||||
| fUiPtr->carla_setParameterValue(index, value); | |||||
| } | |||||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||||
| void uiSetMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override | |||||
| { | |||||
| CARLA_ASSERT(fUiPtr != nullptr); | |||||
| const uint32_t realProgram(bank * 128 + program); | |||||
| if (realProgram >= fPlugin.getProgramCount()) | |||||
| return; | |||||
| if (fUiPtr != nullptr) | |||||
| fUiPtr->carla_setMidiProgram(realProgram); | |||||
| } | |||||
| # endif | |||||
| # if DISTRHO_PLUGIN_WANT_STATE | |||||
| void uiSetCustomData(const char* const key, const char* const value) override | |||||
| { | |||||
| CARLA_ASSERT(fUiPtr != nullptr); | |||||
| CARLA_ASSERT(key != nullptr); | |||||
| CARLA_ASSERT(value != nullptr); | |||||
| if (fUiPtr != nullptr) | |||||
| fUiPtr->carla_setCustomData(key, value); | |||||
| } | |||||
| # endif | |||||
| #endif | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin dispatcher calls | |||||
| void bufferSizeChanged(const uint32_t bufferSize) override | |||||
| { | |||||
| fPlugin.setBufferSize(bufferSize, true); | |||||
| } | |||||
| void sampleRateChanged(const double sampleRate) override | |||||
| { | |||||
| fPlugin.setSampleRate(sampleRate, true); | |||||
| } | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| void uiNameChanged(const char* const uiName) override | |||||
| { | |||||
| if (fUiPtr != nullptr) | |||||
| fUiPtr->carla_setUiTitle(uiName); | |||||
| } | |||||
| #endif | |||||
| // ------------------------------------------------------------------- | |||||
| private: | |||||
| PluginExporter fPlugin; | |||||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||||
| MidiEvent fRealMidiEvents[kMaxMidiEvents]; | |||||
| #endif | |||||
| #if DISTRHO_PLUGIN_HAS_UI | |||||
| // UI | |||||
| UICarla* fUiPtr; | |||||
| void createUiIfNeeded() | |||||
| { | |||||
| if (fUiPtr == nullptr) | |||||
| { | |||||
| d_lastUiSampleRate = getSampleRate(); | |||||
| fUiPtr = new UICarla(getHostHandle(), &fPlugin); | |||||
| } | |||||
| } | |||||
| #endif | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla) | |||||
| // ------------------------------------------------------------------- | |||||
| public: | |||||
| static NativePluginHandle _instantiate(const NativeHostDescriptor* host) | |||||
| { | |||||
| d_lastBufferSize = host->get_buffer_size(host->handle); | |||||
| d_lastSampleRate = host->get_sample_rate(host->handle); | |||||
| return new PluginCarla(host); | |||||
| } | |||||
| static void _cleanup(NativePluginHandle handle) | |||||
| { | |||||
| delete (PluginCarla*)handle; | |||||
| } | |||||
| }; | |||||
| END_NAMESPACE_DISTRHO | |||||
| // ----------------------------------------------------------------------- | |||||