|
|
@@ -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 |
|
|
|
|
|
|
|
// ----------------------------------------------------------------------- |