/* * DISTRHO Plugin Toolkit (DPT) * Copyright (C) 2012-2013 Filipe Coelho * * 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 "CarlaNative.hpp" #include "CarlaString.hpp" #include "DistrhoPluginMain.cpp" #if DISTRHO_PLUGIN_HAS_UI # include "DistrhoUIMain.cpp" #endif // ----------------------------------------------------------------------- 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(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 // -----------------------------------------------------------------------