diff --git a/source/backend/CarlaNative.h b/source/backend/CarlaNative.h index 2835dd0a0..711f5db09 100644 --- a/source/backend/CarlaNative.h +++ b/source/backend/CarlaNative.h @@ -202,6 +202,7 @@ void carla_register_native_plugin_midiThrough(); void carla_register_native_plugin_3BandEQ(); void carla_register_native_plugin_3BandSplitter(); void carla_register_native_plugin_PingPongPan(); +void carla_register_native_plugin_Notes(); #ifdef WANT_AUDIOFILE void carla_register_native_plugin_audiofile(); diff --git a/source/backend/native/3bandeq/DistrhoPlugin3BandEQ.hpp b/source/backend/native/3bandeq/DistrhoPlugin3BandEQ.hpp index 62e08e7d3..be2ec7504 100644 --- a/source/backend/native/3bandeq/DistrhoPlugin3BandEQ.hpp +++ b/source/backend/native/3bandeq/DistrhoPlugin3BandEQ.hpp @@ -39,10 +39,10 @@ public: DistrhoPlugin3BandEQ(); ~DistrhoPlugin3BandEQ(); - // --------------------------------------------- - protected: + // --------------------------------------------- // Information + const char* d_label() const { return "3BandEQ"; @@ -68,27 +68,28 @@ protected: return d_cconst('D', '3', 'E', 'Q'); } + // --------------------------------------------- // Init + void d_initParameter(uint32_t index, Parameter& parameter); void d_initProgramName(uint32_t index, d_string& programName); + // --------------------------------------------- // Internal data + float d_parameterValue(uint32_t index); void d_setParameterValue(uint32_t index, float value); void d_setProgram(uint32_t index); + // --------------------------------------------- // Process + void d_activate(); void d_deactivate(); void d_run(float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents); // --------------------------------------------- -#ifdef QTCREATOR_TEST - void d_initStateKey(uint32_t, d_string&) {} - void d_setState(const char*, const char*) {} -#endif - private: float fLow, fMid, fHigh, fMaster, fLowMidFreq, fMidHighFreq; diff --git a/source/backend/native/3bandsplitter/DistrhoPlugin3BandSplitter.hpp b/source/backend/native/3bandsplitter/DistrhoPlugin3BandSplitter.hpp index 4d6198ace..946ecb5cb 100644 --- a/source/backend/native/3bandsplitter/DistrhoPlugin3BandSplitter.hpp +++ b/source/backend/native/3bandsplitter/DistrhoPlugin3BandSplitter.hpp @@ -39,10 +39,10 @@ public: DistrhoPlugin3BandSplitter(); ~DistrhoPlugin3BandSplitter(); - // --------------------------------------------- - protected: + // --------------------------------------------- // Information + const char* d_label() const { return "3BandSplitter"; @@ -68,16 +68,22 @@ protected: return d_cconst('D', '3', 'E', 'S'); } + // --------------------------------------------- // Init + void d_initParameter(uint32_t index, Parameter& parameter); void d_initProgramName(uint32_t index, d_string& programName); + // --------------------------------------------- // Internal data + float d_parameterValue(uint32_t index); void d_setParameterValue(uint32_t index, float value); void d_setProgram(uint32_t index); + // --------------------------------------------- // Process + void d_activate(); void d_deactivate(); void d_run(float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents); diff --git a/source/backend/native/Makefile b/source/backend/native/Makefile index 6bb7679b8..70f277769 100644 --- a/source/backend/native/Makefile +++ b/source/backend/native/Makefile @@ -9,8 +9,8 @@ include ../Makefile.mk # -------------------------------------------------------------- BUILD_CXX_FLAGS += -I../../libs/distrho -BUILD_CXX_FLAGS += $(shell pkg-config --cflags QtGui gl) -LINK_FLAGS += $(shell pkg-config --libs QtGui gl) +BUILD_CXX_FLAGS += $(shell pkg-config --cflags QtCore QtGui gl) +LINK_FLAGS += $(shell pkg-config --libs QtCore QtGui gl) ifeq ($(HAVE_AF_DEPS),true) AF_CXX_FLAGS = $(BUILD_CXX_FLAGS) @@ -20,8 +20,8 @@ endif ifeq ($(HAVE_ZYN_DEPS),true) ZYN_CXX_FLAGS = $(BUILD_CXX_FLAGS) -ZYN_CXX_FLAGS += $(shell pkg-config --cflags fftw3 mxml) -pthread -LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml) -lpthread +ZYN_CXX_FLAGS += $(shell pkg-config --cflags fftw3 mxml) +LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml) endif # -------------------------------------------------------------- @@ -36,7 +36,8 @@ OBJS = \ OBJS += \ distrho-3bandeq.cpp.o \ distrho-3bandsplitter.cpp.o \ - distrho-pingpongpan.cpp.o + distrho-pingpongpan.cpp.o \ + distrho-notes.cpp.o ifeq ($(HAVE_AF_DEPS),true) OBJS += \ @@ -88,8 +89,16 @@ distrho-3bandsplitter.cpp.o: distrho-3bandsplitter.cpp distrho-pingpongpan.cpp.o: distrho-pingpongpan.cpp $(CXX) $< $(BUILD_CXX_FLAGS) -Ipingpongpan -DDISTRHO_NAMESPACE=DISTRHO_PingPongPan -c -o $@ +distrho-notes.cpp.o: distrho-notes.cpp + $(CXX) $< $(BUILD_CXX_FLAGS) -Inotes -DDISTRHO_NAMESPACE=DISTRHO_Notes -c -o $@ + zynaddsubfx.cpp.o: zynaddsubfx.cpp $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ zynaddsubfx-src.cpp.o: zynaddsubfx-src.cpp $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ + +# -------------------------------------------------------------- + +moc_%.cpp: %.hpp + $(MOC) $< -o $@ diff --git a/source/backend/native/distrho-notes.cpp b/source/backend/native/distrho-notes.cpp new file mode 100644 index 000000000..6e2be6b1e --- /dev/null +++ b/source/backend/native/distrho-notes.cpp @@ -0,0 +1,57 @@ +/* + * Carla Native Plugins + * 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 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 GPL.txt file + */ + +#include "CarlaNative.hpp" + +// Plugin Code +#include "notes/DistrhoPluginNotes.cpp" +#include "notes/DistrhoUINotes.cpp" + +// Carla DISTRHO Plugin +#include "distrho/DistrhoPluginCarla.cpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +static const PluginDescriptor notesDesc = { + /* category */ ::PLUGIN_CATEGORY_UTILITY, + /* hints */ static_cast(::PLUGIN_IS_RTSAFE | ::PLUGIN_HAS_GUI | ::PLUGIN_USES_SINGLE_THREAD), + /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, + /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, + /* midiIns */ 0, + /* midiOuts */ 0, + /* paramIns */ 1, + /* paramOuts */ 0, + /* name */ DISTRHO_PLUGIN_NAME, + /* label */ "Notes", + /* maker */ "falkTX", + /* copyright */ "GPL v2+", + PluginDescriptorFILL(PluginCarla) +}; + +END_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +void carla_register_native_plugin_Notes() +{ + USE_NAMESPACE_DISTRHO + carla_register_native_plugin(¬esDesc); +} + +// ----------------------------------------------------------------------- diff --git a/source/backend/native/distrho/DistrhoPluginCarla.cpp b/source/backend/native/distrho/DistrhoPluginCarla.cpp index cc76ce023..7b0822d99 100644 --- a/source/backend/native/distrho/DistrhoPluginCarla.cpp +++ b/source/backend/native/distrho/DistrhoPluginCarla.cpp @@ -20,7 +20,7 @@ #include "DistrhoPluginMain.cpp" // TODO -#undef DISTRHO_PLUGIN_HAS_UI +//#undef DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI #include @@ -43,11 +43,11 @@ public: kHost(host), kPlugin(plugin), fWidget(this), - fUi(this, (intptr_t)fWidget.winId(), setParameterCallback, setStateCallback, uiEditParameterCallback, uiSendNoteCallback, uiResizeCallback) + fUi(this, (intptr_t)fWidget.winId(), editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback) { setCentralWidget(&fWidget); - setFixedSize(fUi.getWidth(), fUi.getHeight()); - setWindowTitle(fUi.getName()); + setFixedSize(fUi.width(), fUi.height()); + setWindowTitle(fUi.name()); } ~UICarla() @@ -73,17 +73,35 @@ public: void carla_setMidiProgram(const uint32_t realProgram) { +#if DISTRHO_PLUGIN_WANT_PROGRAMS fUi.programChanged(realProgram); +#else + return; + // unused + (void)realProgram; +#endif } void carla_setCustomData(const char* const key, const char* const value) { +#if DISTRHO_PLUGIN_WANT_STATE fUi.stateChanged(key, value); +#else + return; + // unused + (void)key; + (void)value; +#endif } // --------------------------------------------- protected: + void editParameter(uint32_t, bool) + { + // TODO + } + void setParameterValue(uint32_t rindex, float value) { kHost->ui_parameter_changed(kHost->handle, rindex, value); @@ -94,17 +112,12 @@ protected: kHost->ui_custom_data_changed(kHost->handle, key, value); } - void uiEditParameter(uint32_t, bool) + void sendNote(bool, uint8_t, uint8_t, uint8_t) { // TODO } - void uiSendNote(bool, uint8_t, uint8_t, uint8_t) - { - // TODO - } - - void uiResize(int width, int height) + void uiResize(unsigned int width, unsigned int height) { setFixedSize(width, height); } @@ -137,6 +150,11 @@ private: #define handlePtr ((UICarla*)ptr) + static void editParameterCallback(void* ptr, uint32_t index, bool started) + { + handlePtr->editParameter(index, started); + } + static void setParameterCallback(void* ptr, uint32_t rindex, float value) { handlePtr->setParameterValue(rindex, value); @@ -147,17 +165,12 @@ private: handlePtr->setState(key, value); } - static void uiEditParameterCallback(void* ptr, uint32_t index, bool started) + static void sendNoteCallback(void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) { - handlePtr->uiEditParameter(index, started); + handlePtr->sendNote(onOff, channel, note, velocity); } - static void uiSendNoteCallback(void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) - { - handlePtr->uiSendNote(onOff, channel, note, velocity); - } - - static void uiResizeCallback(void* ptr, int width, int height) + static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height) { handlePtr->uiResize(width, height); } @@ -178,14 +191,14 @@ public: : PluginDescriptorClass(host) { #if DISTRHO_PLUGIN_HAS_UI - fUi = nullptr; + fUiPtr = nullptr; #endif } ~PluginCarla() { #if DISTRHO_PLUGIN_HAS_UI - fUi = nullptr; + fUiPtr = nullptr; #endif } @@ -358,51 +371,51 @@ protected: if (show) createUiIfNeeded(); - if (uiPtr != nullptr) - uiPtr->carla_show(show); + if (fUiPtr != nullptr) + fUiPtr->carla_show(show); } void uiIdle() { - CARLA_ASSERT(uiPtr != nullptr); + CARLA_ASSERT(fUiPtr != nullptr); - if (uiPtr != nullptr) - uiPtr->carla_idle(); + if (fUiPtr != nullptr) + fUiPtr->carla_idle(); } void uiSetParameterValue(const uint32_t index, const float value) { - CARLA_ASSERT(uiPtr != nullptr); + CARLA_ASSERT(fUiPtr != nullptr); CARLA_ASSERT(index < getParameterCount()); - if (uiPtr != nullptr) - uiPtr->carla_setParameterValue(index, value); + if (fUiPtr != nullptr) + fUiPtr->carla_setParameterValue(index, value); } # if DISTRHO_PLUGIN_WANT_PROGRAMS void uiSetMidiProgram(const uint32_t bank, const uint32_t program) { - CARLA_ASSERT(uiPtr); + CARLA_ASSERT(fUiPtr != nullptr); uint32_t realProgram = bank * 128 + program; - if (realProgram >= plugin.programCount()) + if (realProgram >= fPlugin.programCount()) return; - if (uiPtr != nullptr) - uiPtr->carla_setMidiProgram(realProgram); + if (fUiPtr != nullptr) + fUiPtr->carla_setMidiProgram(realProgram); } # endif # if DISTRHO_PLUGIN_WANT_STATE void uiSetCustomData(const char* const key, const char* const value) { - CARLA_ASSERT(uiPtr != nullptr); + CARLA_ASSERT(fUiPtr != nullptr); CARLA_ASSERT(key != nullptr); CARLA_ASSERT(value != nullptr); - if (uiPtr != nullptr) - uiPtr->carla_setCustomData(key, value); + if (fUiPtr != nullptr) + fUiPtr->carla_setCustomData(key, value); } # endif #endif @@ -418,14 +431,14 @@ private: #if DISTRHO_PLUGIN_HAS_UI // UI - ScopedPointer fUi; + ScopedPointer fUiPtr; void createUiIfNeeded() { - if (fUi == nullptr) + if (fUiPtr == nullptr) { d_lastUiSampleRate = getSampleRate(); - fUi = new UICarla(getHostHandle(), &fPlugin); + fUiPtr = new UICarla(getHostHandle(), &fPlugin); } } #endif diff --git a/source/backend/native/notes/DistrhoPluginInfo.h b/source/backend/native/notes/DistrhoPluginInfo.h new file mode 100644 index 000000000..0574c6990 --- /dev/null +++ b/source/backend/native/notes/DistrhoPluginInfo.h @@ -0,0 +1,37 @@ +/* + * DISTRHO Notes Plugin + * 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 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 GPL.txt file + */ + +#ifndef __DISTRHO_PLUGIN_INFO_H__ +#define __DISTRHO_PLUGIN_INFO_H__ + +#define DISTRHO_PLUGIN_NAME "Notes" + +#define DISTRHO_PLUGIN_HAS_UI 1 +#define DISTRHO_PLUGIN_IS_SYNTH 0 + +#define DISTRHO_PLUGIN_NUM_INPUTS 2 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 + +#define DISTRHO_PLUGIN_WANT_LATENCY 0 +#define DISTRHO_PLUGIN_WANT_PROGRAMS 0 +#define DISTRHO_PLUGIN_WANT_STATE 1 + +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Notes" + +#define DISTRHO_UI_QT4 + +#endif // __DISTRHO_PLUGIN_INFO_H__ diff --git a/source/backend/native/notes/DistrhoPluginNotes.cpp b/source/backend/native/notes/DistrhoPluginNotes.cpp new file mode 100644 index 000000000..d5a6518be --- /dev/null +++ b/source/backend/native/notes/DistrhoPluginNotes.cpp @@ -0,0 +1,121 @@ +/* + * DISTRHO Notes Plugin + * 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 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 GPL.txt file + */ + +#include "DistrhoPluginNotes.hpp" + +#include + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +DistrhoPluginNotes::DistrhoPluginNotes() + : Plugin(1, 0, 103) // 1 parameter, 0 programs, 103 states +{ + fCurPage = 0; +} + +DistrhoPluginNotes::~DistrhoPluginNotes() +{ +} + +// ------------------------------------------------- +// Init + +void DistrhoPluginNotes::d_initParameter(uint32_t index, Parameter& parameter) +{ + if (index != 0) + return; + + parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; + parameter.name = "Page"; + parameter.symbol = "page"; + parameter.ranges.def = 1; + parameter.ranges.min = 1; + parameter.ranges.max = 100; + parameter.ranges.step = 1; + parameter.ranges.stepSmall = 1; + parameter.ranges.stepLarge = 10; +} + +void DistrhoPluginNotes::d_initStateKey(uint32_t index, d_string& stateKey) +{ + switch (index) + { + case 0: + stateKey = "readOnly"; + break; + case 1 ... 100: + stateKey = "pageText #" + d_string(index); + break; + case 101: + stateKey = "guiWidth"; + break; + case 102: + stateKey = "guiHeight"; + break; + } +} + +// ------------------------------------------------- +// Internal data + +float DistrhoPluginNotes::d_parameterValue(uint32_t index) +{ + if (index != 0) + return 0.0f; + + return fCurPage; +} + +void DistrhoPluginNotes::d_setParameterValue(uint32_t index, float value) +{ + if (index != 0) + return; + + fCurPage = int(value); +} + +void DistrhoPluginNotes::d_setState(const char*, const char*) +{ + // do nothing, used only for UI state +} + +// ------------------------------------------------- +// Process + +void DistrhoPluginNotes::d_run(float** inputs, float** outputs, uint32_t frames, uint32_t, const MidiEvent*) +{ + float* in1 = inputs[0]; + float* in2 = inputs[1]; + float* out1 = outputs[0]; + float* out2 = outputs[1]; + + std::memcpy(out1, in1, sizeof(float)*frames); + std::memcpy(out2, in2, sizeof(float)*frames); +} + +// ------------------------------------------------- + +Plugin* createPlugin() +{ + return new DistrhoPluginNotes(); +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/backend/native/notes/DistrhoPluginNotes.hpp b/source/backend/native/notes/DistrhoPluginNotes.hpp new file mode 100644 index 000000000..fe91716f5 --- /dev/null +++ b/source/backend/native/notes/DistrhoPluginNotes.hpp @@ -0,0 +1,86 @@ +/* + * DISTRHO Notes Plugin + * 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 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 GPL.txt file + */ + +#ifndef __DISTRHO_PLUGIN_NOTES_HPP__ +#define __DISTRHO_PLUGIN_NOTES_HPP__ + +#include "DistrhoPlugin.hpp" + +START_NAMESPACE_DISTRHO + +class DistrhoPluginNotes : public Plugin +{ +public: + DistrhoPluginNotes(); + ~DistrhoPluginNotes(); + +protected: + // --------------------------------------------- + // Information + + const char* d_label() const + { + return "Notes"; + } + + const char* d_maker() const + { + return "DISTRHO"; + } + + const char* d_license() const + { + return "GPL v2+"; + } + + uint32_t d_version() const + { + return 0x1000; + } + + long d_uniqueId() const + { + return d_cconst('D', 'N', 'o', 't'); + } + + // --------------------------------------------- + // Init + + void d_initParameter(uint32_t index, Parameter& parameter); + void d_initStateKey(uint32_t index, d_string& stateKeyName); + + // --------------------------------------------- + // Internal data + + float d_parameterValue(uint32_t index); + void d_setParameterValue(uint32_t index, float value); + void d_setState(const char* key, const char* value); + + // --------------------------------------------- + // Process + + void d_run(float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents); + + // --------------------------------------------- + +private: + int fCurPage; +}; + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_PLUGIN_NOTES_HPP__ diff --git a/source/backend/native/notes/DistrhoUINotes.cpp b/source/backend/native/notes/DistrhoUINotes.cpp new file mode 100644 index 000000000..acbabf375 --- /dev/null +++ b/source/backend/native/notes/DistrhoUINotes.cpp @@ -0,0 +1,222 @@ +/* + * DISTRHO Notes Plugin + * 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 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 GPL.txt file + */ + +#include "DistrhoUINotes.hpp" + +#include + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +DistrhoUINotes::DistrhoUINotes() + : Qt4UI(), + fCurPage(1), + fSaveSizeNowChecker(-1), + fSaveTextNowChecker(-1), + fTextEdit(this), + fButton(this), + fProgressBar(this), + fSpacer(this), + fGridLayout(this) +{ + fButton.setCheckable(true); + fButton.setChecked(true); + fButton.setText("Edit"); + fButton.setFixedSize(fButton.minimumSizeHint()); + + fProgressBar.set_minimum(1); + fProgressBar.set_maximum(100); + fProgressBar.set_value(1); + + fSpacer.setText(""); + fSpacer.setFixedSize(5, 5); + + fTextEdit.setReadOnly(false); + + setLayout(&fGridLayout); + fGridLayout.addWidget(&fTextEdit, 0, 0, 1, 3); + fGridLayout.addWidget(&fButton, 1, 0, 1, 1); + fGridLayout.addWidget(&fProgressBar, 1, 1, 1, 1); + fGridLayout.addWidget(&fSpacer, 1, 2, 1, 1); + fGridLayout.setContentsMargins(0, 0, 0, 0); + + connect(&fButton, SIGNAL(clicked(bool)), SLOT(buttonClicked(bool))); + connect(&fProgressBar, SIGNAL(valueChangedFromBar(float)), SLOT(progressBarValueChanged(float))); + connect(&fTextEdit, SIGNAL(textChanged()), SLOT(textChanged())); + + setFixedSize(300, 200); +} + +DistrhoUINotes::~DistrhoUINotes() +{ +} + +void DistrhoUINotes::saveCurrentTextState() +{ + QString pageKey = QString("pageText #%1").arg(fCurPage); + QString pageValue = fTextEdit.toPlainText(); + + if (pageValue != fNotes[fCurPage-1]) + { + fNotes[fCurPage-1] = pageValue; + d_setState(pageKey.toUtf8().constData(), pageValue.toUtf8().constData()); + } +} + +// ------------------------------------------------- +// DSP Callbacks + +void DistrhoUINotes::d_parameterChanged(uint32_t index, float value) +{ + if (index != 0) + return; + + int nextCurPage = value; + + if (nextCurPage != fCurPage && nextCurPage >= 1 && nextCurPage <= 100) + { + saveCurrentTextState(); + fCurPage = nextCurPage; + + fTextEdit.setPlainText(fNotes[fCurPage-1]); + fProgressBar.set_value(fCurPage); + fProgressBar.update(); + } +} + +void DistrhoUINotes::d_stateChanged(const char* key, const char* value) +{ + if (std::strcmp(key, "guiWidth") == 0) + { + bool ok; + int width = QString(value).toInt(&ok); + + if (ok && width > 0) + setFixedWidth(width); + } + + else if (std::strcmp(key, "guiHeight") == 0) + { + bool ok; + int height = QString(value).toInt(&ok); + + if (ok && height > 0) + setFixedHeight(height); + } + + else if (std::strncmp(key, "pageText #", 10) == 0) + { + bool ok; + int pageIndex = QString(key+10).toInt(&ok); + + if (ok && pageIndex >= 1 && pageIndex <= 100) + { + fNotes[pageIndex-1] = QString(value); + + if (pageIndex == fCurPage) + fTextEdit.setPlainText(fNotes[pageIndex-1]); + } + } + + else if (strcmp(key, "readOnly") == 0) + { + bool readOnly = !strcmp(value, "yes"); + fButton.setChecked(!readOnly); + fTextEdit.setReadOnly(readOnly); + } +} + +// ------------------------------------------------- +// UI Callbacks + +void DistrhoUINotes::d_uiIdle() +{ + if (fSaveSizeNowChecker == 11) + { + d_setState("guiWidth", QString::number(width()).toUtf8().constData()); + d_setState("guiHeight", QString::number(height()).toUtf8().constData()); + fSaveSizeNowChecker = -1; + } + + if (fSaveTextNowChecker == 11) + { + saveCurrentTextState(); + fSaveTextNowChecker = -1; + } + + if (fSaveSizeNowChecker >= 0) + fSaveSizeNowChecker++; + + if (fSaveTextNowChecker >= 0) + fSaveTextNowChecker++; + + Qt4UI::d_uiIdle(); +} + +void DistrhoUINotes::resizeEvent(QResizeEvent* event) +{ + fSaveSizeNowChecker = 0; + QWidget::resizeEvent(event); +} + +// ------------------------------------------------- + +void DistrhoUINotes::buttonClicked(bool click) +{ + bool readOnly = !click; + fTextEdit.setReadOnly(readOnly); + + d_setState("readOnly", readOnly ? "yes" : "no"); +} + +void DistrhoUINotes::progressBarValueChanged(float value) +{ + value = rint(value); + + if (fCurPage == (int)value) + return; + + // maybe save current text before changing page + if (fSaveTextNowChecker >= 0 && value >= 1.0f && value <= 100.0f) + { + saveCurrentTextState(); + fSaveTextNowChecker = -1; + } + + // change current page + d_parameterChanged(0, value); + + // tell host about this change + d_setParameterValue(0, value); +} + +void DistrhoUINotes::textChanged() +{ + fSaveTextNowChecker = 0; +} + +// ------------------------------------------------- + +UI* createUI() +{ + return new DistrhoUINotes; +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/backend/native/notes/DistrhoUINotes.hpp b/source/backend/native/notes/DistrhoUINotes.hpp new file mode 100644 index 000000000..5ce1ea77e --- /dev/null +++ b/source/backend/native/notes/DistrhoUINotes.hpp @@ -0,0 +1,103 @@ +/* + * DISTRHO Notes Plugin + * 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 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 GPL.txt file + */ + +#ifndef __DISTRHO_UI_NOTES_HPP__ +#define __DISTRHO_UI_NOTES_HPP__ + +#include "DistrhoUIQt4.hpp" +#include "ParamProgressBar.hpp" + +#include +#include +#include +#include + +class QResizeEvent; + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +class DistrhoUINotes : public Qt4UI +{ + Q_OBJECT + +public: + DistrhoUINotes(); + ~DistrhoUINotes(); + +protected: + // --------------------------------------------- + // Information + + bool d_resizable() + { + return true; + } + + uint d_minimumWidth() + { + return 180; + } + + uint d_minimumHeight() + { + return 150; + } + + // --------------------------------------------- + // DSP Callbacks + + void d_parameterChanged(uint32_t index, float value); + void d_stateChanged(const char* key, const char* value); + + // --------------------------------------------- + // UI Callbacks + + void d_uiIdle(); + + // --------------------------------------------- + // listen for resize events + + void resizeEvent(QResizeEvent*); + +private slots: + void buttonClicked(bool click); + void progressBarValueChanged(float value); + void textChanged(); + +private: + int fCurPage; + int fSaveSizeNowChecker; + int fSaveTextNowChecker; + + QString fNotes[100]; + + QTextEdit fTextEdit; + QPushButton fButton; + ParamProgressBar fProgressBar; + QLabel fSpacer; + QGridLayout fGridLayout; + + void saveCurrentTextState(); +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_UI_NOTES_HPP__ diff --git a/source/backend/native/notes/ParamProgressBar.cpp b/source/backend/native/notes/ParamProgressBar.cpp new file mode 100644 index 000000000..7c584ae2a --- /dev/null +++ b/source/backend/native/notes/ParamProgressBar.cpp @@ -0,0 +1,118 @@ +/* + * Parameter Progress-Bar, a custom Qt4 widget + * Copyright (C) 2012 Filipe Coelho + * + * 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 COPYING file + */ + +#include "ParamProgressBar.h" + +#include + +ParamProgressBar::ParamProgressBar(QWidget* parent) + : QProgressBar(parent) +{ + m_leftClickDown = false; + + m_minimum = 0.0f; + m_maximum = 1.0f; + m_rvalue = 0.0f; + + m_textCall = nullptr; + + setMinimum(0); + setMaximum(1000); + setValue(0); + setFormat("(none)"); +} + +void ParamProgressBar::set_minimum(float value) +{ + m_minimum = value; +} + +void ParamProgressBar::set_maximum(float value) +{ + m_maximum = value; +} + +void ParamProgressBar::set_value(float value) +{ + m_rvalue = value; + float vper = (value - m_minimum) / (m_maximum - m_minimum); + setValue(vper * 1000); +} + +void ParamProgressBar::set_label(QString label) +{ + m_label = label; + + if (m_label == "(coef)") + { + m_label = ""; + m_preLabel = "*"; + } +} + +void ParamProgressBar::set_text_call(TextCallback* textCall) +{ + m_textCall = textCall; +} + +void ParamProgressBar::handleMouseEventPos(const QPoint& pos) +{ + float xper = float(pos.x()) / width(); + float value = xper * (m_maximum - m_minimum) + m_minimum; + + if (value < m_minimum) + value = m_minimum; + else if (value > m_maximum) + value = m_maximum; + + emit valueChangedFromBar(value); +} + +void ParamProgressBar::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) + { + handleMouseEventPos(event->pos()); + m_leftClickDown = true; + } + else + m_leftClickDown = false; + QProgressBar::mousePressEvent(event); +} + +void ParamProgressBar::mouseMoveEvent(QMouseEvent* event) +{ + if (m_leftClickDown) + handleMouseEventPos(event->pos()); + QProgressBar::mouseMoveEvent(event); +} + +void ParamProgressBar::mouseReleaseEvent(QMouseEvent* event) +{ + m_leftClickDown = false; + QProgressBar::mouseReleaseEvent(event); +} + +void ParamProgressBar::paintEvent(QPaintEvent* event) +{ + if (m_textCall) + setFormat(QString("%1 %2 %3").arg(m_preLabel).arg(m_textCall->textCallBack()).arg(m_label)); + else + setFormat(QString("%1 %2 %3").arg(m_preLabel).arg(m_rvalue).arg(m_label)); + + QProgressBar::paintEvent(event); +} diff --git a/source/backend/native/notes/ParamProgressBar.hpp b/source/backend/native/notes/ParamProgressBar.hpp new file mode 100644 index 000000000..f85d8637f --- /dev/null +++ b/source/backend/native/notes/ParamProgressBar.hpp @@ -0,0 +1,64 @@ +/* + * Parameter Progress-Bar, a custom Qt4 widget + * Copyright (C) 2012 Filipe Coelho + * + * 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 COPYING file + */ + +#ifndef PARAMPROGRESSBAR_H +#define PARAMPROGRESSBAR_H + +#include + +class TextCallback +{ +public: + virtual ~TextCallback(); + virtual const char* textCallBack() = 0; +}; + +class ParamProgressBar : public QProgressBar +{ + Q_OBJECT + +public: + ParamProgressBar(QWidget* parent); + + void set_minimum(float value); + void set_maximum(float value); + void set_value(float value); + void set_label(QString label); + void set_text_call(TextCallback* textCall); + +signals: + void valueChangedFromBar(float value); + +protected: + void handleMouseEventPos(const QPoint& pos); + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + void paintEvent(QPaintEvent* event); + +private: + bool m_leftClickDown; + float m_minimum; + float m_maximum; + float m_rvalue; + QString m_label; + QString m_preLabel; + + TextCallback* m_textCall; +}; + +#endif // #define PARAMPROGRESSBAR_H diff --git a/source/backend/native/pingpongpan/DistrhoPluginPingPongPan.hpp b/source/backend/native/pingpongpan/DistrhoPluginPingPongPan.hpp index 01c1820dd..6d90dc814 100644 --- a/source/backend/native/pingpongpan/DistrhoPluginPingPongPan.hpp +++ b/source/backend/native/pingpongpan/DistrhoPluginPingPongPan.hpp @@ -35,10 +35,10 @@ public: DistrhoPluginPingPongPan(); ~DistrhoPluginPingPongPan(); - // --------------------------------------------- - protected: + // --------------------------------------------- // Information + const char* d_label() const { return "PingPongPan"; @@ -64,16 +64,22 @@ protected: return d_cconst('D', 'P', 'P', 'P'); } + // --------------------------------------------- // Init + void d_initParameter(uint32_t index, Parameter& parameter); void d_initProgramName(uint32_t index, d_string& programName); + // --------------------------------------------- // Internal data + float d_parameterValue(uint32_t index); void d_setParameterValue(uint32_t index, float value); void d_setProgram(uint32_t index); + // --------------------------------------------- // Process + void d_activate(); void d_deactivate(); void d_run(float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents); diff --git a/source/backend/plugin/NativePlugin.cpp b/source/backend/plugin/NativePlugin.cpp index f6e7667ab..b6ef34745 100644 --- a/source/backend/plugin/NativePlugin.cpp +++ b/source/backend/plugin/NativePlugin.cpp @@ -1775,6 +1775,7 @@ private: carla_register_native_plugin_3BandEQ(); carla_register_native_plugin_3BandSplitter(); carla_register_native_plugin_PingPongPan(); + carla_register_native_plugin_Notes(); # ifdef WANT_AUDIOFILE carla_register_native_plugin_audiofile(); diff --git a/source/libs/distrho/DistrhoPlugin.hpp b/source/libs/distrho/DistrhoPlugin.hpp new file mode 100644 index 000000000..041425d76 --- /dev/null +++ b/source/libs/distrho/DistrhoPlugin.hpp @@ -0,0 +1,219 @@ +/* + * 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 + */ + +#ifndef __DISTRHO_PLUGIN_HPP__ +#define __DISTRHO_PLUGIN_HPP__ + +#include "DistrhoUtils.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Parameter Hints + +const uint32_t PARAMETER_IS_AUTOMABLE = 1 << 0; +const uint32_t PARAMETER_IS_BOOLEAN = 1 << 1; +const uint32_t PARAMETER_IS_INTEGER = 1 << 2; +const uint32_t PARAMETER_IS_LOGARITHMIC = 1 << 3; +const uint32_t PARAMETER_IS_OUTPUT = 1 << 4; + +// ------------------------------------------------- +// Parameter Ranges + +struct ParameterRanges { + float def; + float min; + float max; + float step; + float stepSmall; + float stepLarge; + + ParameterRanges() + : def(0.0f), + min(0.0f), + max(1.0f), + step(0.001f), + stepSmall(0.00001f), + stepLarge(0.01f) {} + + ParameterRanges(float def, float min, float max) + : step(0.001f), + stepSmall(0.00001f), + stepLarge(0.01f) + { + this->def = def; + this->min = min; + this->max = max; + } + + ParameterRanges(float def, float min, float max, float step, float stepSmall, float stepLarge) + { + this->def = def; + this->min = min; + this->max = max; + this->step = step; + this->stepSmall = stepSmall; + this->stepLarge = stepLarge; + } + + void fixValue(float& value) const + { + if (value < min) + value = min; + else if (value > max) + value = max; + } + + float normalizeValue(const float& value) const + { + return (value - min) / (max - min); + } + + float unnormalizeValue(const float& value) const + { + return value * (max - min) + min; + } +}; + +// ------------------------------------------------- +// Parameter + +struct Parameter { + uint32_t hints; + d_string name; + d_string symbol; + d_string unit; + ParameterRanges ranges; + + Parameter() + : hints(0x0) {} +}; + +// ------------------------------------------------- +// MidiEvent + +struct MidiEvent { + uint32_t frame; + uint8_t buffer[3]; + + MidiEvent() + { + clear(); + } + + void clear() + { + frame = 0; + buffer[0] = 0; + buffer[1] = 0; + buffer[2] = 0; + } +}; + +// ------------------------------------------------- +// TimePos + +struct TimePos { + double bpm; + + TimePos() + : bpm(120.0) {} +}; + +// ------------------------------------------------- +// Plugin + +struct PluginPrivateData; + +class Plugin +{ +public: + Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount); + virtual ~Plugin(); + + // --------------------------------------------- + // Host state + + uint32_t d_bufferSize() const; + double d_sampleRate() const; + const TimePos& d_timePos() const; +#if DISTRHO_PLUGIN_WANT_LATENCY + void d_setLatency(uint32_t frames); +#endif + +protected: + // --------------------------------------------- + // Information + + virtual const char* d_name() const { return DISTRHO_PLUGIN_NAME; } + virtual const char* d_label() const = 0; + virtual const char* d_maker() const = 0; + virtual const char* d_license() const = 0; + virtual uint32_t d_version() const = 0; + virtual long d_uniqueId() const = 0; + + // --------------------------------------------- + // Init + + virtual void d_initParameter(uint32_t index, Parameter& parameter) = 0; +#if DISTRHO_PLUGIN_WANT_PROGRAMS + virtual void d_initProgramName(uint32_t index, d_string& programName) = 0; +#endif +#if DISTRHO_PLUGIN_WANT_STATE + virtual void d_initStateKey(uint32_t index, d_string& stateKey) = 0; +#endif + + // --------------------------------------------- + // Internal data + + virtual float d_parameterValue(uint32_t index) = 0; + virtual void d_setParameterValue(uint32_t index, float value) = 0; +#if DISTRHO_PLUGIN_WANT_PROGRAMS + virtual void d_setProgram(uint32_t index) = 0; +#endif +#if DISTRHO_PLUGIN_WANT_STATE + virtual void d_setState(const char* key, const char* value) = 0; +#endif + + // --------------------------------------------- + // Process + + virtual void d_activate() {} + virtual void d_deactivate() {} + virtual void d_run(float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents) = 0; + + // --------------------------------------------- + // Callbacks (optional) + + virtual void d_bufferSizeChanged(uint32_t newBufferSize); + virtual void d_sampleRateChanged(double newSampleRate); + + // --------------------------------------------- + +private: + PluginPrivateData* const pData; + friend class PluginInternal; +}; + +// ------------------------------------------------- + +Plugin* createPlugin(); + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_PLUGIN_HPP__ diff --git a/source/libs/distrho/DistrhoPluginMain.cpp b/source/libs/distrho/DistrhoPluginMain.cpp new file mode 100644 index 000000000..7a1ccb6ab --- /dev/null +++ b/source/libs/distrho/DistrhoPluginMain.cpp @@ -0,0 +1,27 @@ +/* + * 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 "src/DistrhoPlugin.cpp" + +#if defined(DISTRHO_PLUGIN_TARGET_JACK) +# include "src/DistrhoPluginJACK.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_LADSPA) || defined(DISTRHO_PLUGIN_TARGET_DSSI) +# include "src/DistrhoPluginLADSPA+DSSI.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_LV2) +# include "src/DistrhoPluginLV2.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_VST) +# include "src/DistrhoPluginVST.cpp" +#endif diff --git a/source/libs/distrho/DistrhoUI.hpp b/source/libs/distrho/DistrhoUI.hpp new file mode 100644 index 000000000..42072dd21 --- /dev/null +++ b/source/libs/distrho/DistrhoUI.hpp @@ -0,0 +1,100 @@ +/* + * 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 + */ + +#ifndef __DISTRHO_UI_HPP__ +#define __DISTRHO_UI_HPP__ + +#include "DistrhoUtils.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// UI + +struct UIPrivateData; + +class UI +{ +public: + UI(); + virtual ~UI(); + + // --------------------------------------------- + // Host DSP State + + double d_sampleRate() const; + void d_editParameter(uint32_t index, bool started); + void d_setParameterValue(uint32_t index, float value); +#if DISTRHO_PLUGIN_WANT_STATE + void d_setState(const char* key, const char* value); +#endif +#if DISTRHO_PLUGIN_IS_SYNTH + void d_sendNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity); +#endif + + // --------------------------------------------- + // Host UI State + + void d_uiResize(unsigned int width, unsigned int height); + +protected: + // --------------------------------------------- + // Information + + virtual const char* d_name() const { return DISTRHO_PLUGIN_NAME; } + virtual unsigned int d_width() const = 0; + virtual unsigned int d_height() const = 0; + + // --------------------------------------------- + // DSP Callbacks + + virtual void d_parameterChanged(uint32_t index, float value) = 0; +#if DISTRHO_PLUGIN_WANT_PROGRAMS + virtual void d_programChanged(uint32_t index) = 0; +#endif +#if DISTRHO_PLUGIN_WANT_STATE + virtual void d_stateChanged(const char* key, const char* value) = 0; +#endif +#if DISTRHO_PLUGIN_IS_SYNTH + virtual void d_noteReceived(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) = 0; +#endif + + // --------------------------------------------- + // UI Callbacks + + virtual void d_uiIdle() = 0; + + // --------------------------------------------- + +private: + UIPrivateData* const pData; + friend class UIInternal; +#ifdef DISTRHO_UI_QT4 + friend class Qt4UI; +#else + friend class OpenGLUI; +#endif +}; + +// ------------------------------------------------- + +UI* createUI(); + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_UI_HPP__ diff --git a/source/libs/distrho/DistrhoUIMain.cpp b/source/libs/distrho/DistrhoUIMain.cpp new file mode 100644 index 000000000..4d2d192ed --- /dev/null +++ b/source/libs/distrho/DistrhoUIMain.cpp @@ -0,0 +1,33 @@ +/* + * 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 "src/DistrhoUI.cpp" + +#if defined(DISTRHO_PLUGIN_TARGET_JACK) +// nothing +#elif defined(DISTRHO_PLUGIN_TARGET_DSSI) +# include "src/DistrhoUIDSSI.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_LV2) +# include "src/DistrhoUILV2.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_VST) +// nothing +#endif + +#ifdef DISTRHO_UI_QT4 +# include "src/DistrhoUIQt4.cpp" +#else +# include "src/DistrhoUIOpenGL.cpp" +#endif diff --git a/source/libs/distrho/DistrhoUIQt4.hpp b/source/libs/distrho/DistrhoUIQt4.hpp new file mode 100644 index 000000000..e60bcf99b --- /dev/null +++ b/source/libs/distrho/DistrhoUIQt4.hpp @@ -0,0 +1,78 @@ +/* + * 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 + */ + +#ifndef __DISTRHO_UI_QT4_HPP__ +#define __DISTRHO_UI_QT4_HPP__ + +#include "DistrhoUI.hpp" + +#include + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Qt4 UI + +class Qt4UI : public UI, + public QWidget +{ +public: + Qt4UI(); + virtual ~Qt4UI(); + +protected: + // --------------------------------------------- + // Information + + virtual bool d_resizable() { return false; } + virtual uint d_minimumWidth() { return 100; } + virtual uint d_minimumHeight() { return 100; } + + // --------------------------------------------- + // DSP Callbacks + + virtual void d_parameterChanged(uint32_t index, float value) = 0; +#if DISTRHO_PLUGIN_WANT_PROGRAMS + virtual void d_programChanged(uint32_t index) = 0; +#endif +#if DISTRHO_PLUGIN_WANT_STATE + virtual void d_stateChanged(const char* key, const char* value) = 0; +#endif +#if DISTRHO_PLUGIN_IS_SYNTH + virtual void d_noteReceived(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) = 0; +#endif + + // --------------------------------------------- + // UI Callbacks + + virtual void d_uiIdle(); + +private: + friend class UIInternal; + + // --------------------------------------------- + // Implement resize internally + + void d_uiResize(unsigned int width, unsigned int height); + unsigned int d_width() const { return width(); } + unsigned int d_height() const { return height(); } +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_UI_QT4_HPP__ diff --git a/source/libs/distrho/DistrhoUtils.hpp b/source/libs/distrho/DistrhoUtils.hpp new file mode 100644 index 000000000..3fb7f9734 --- /dev/null +++ b/source/libs/distrho/DistrhoUtils.hpp @@ -0,0 +1,500 @@ +/* + * 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 + */ + +#ifndef __DISTRHO_UTILS_HPP__ +#define __DISTRHO_UTILS_HPP__ + +#include "src/DistrhoDefines.h" + +#include +#include +#include +#include + +#ifdef DISTRHO_OS_WINDOWS +# include +#else +# include +#endif + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +static inline +long d_cconst(int a, int b, int c, int d) +{ + return (a << 24) | (b << 16) | (c << 8) | (d << 0); +} + +// ------------------------------------------------- + +static inline +void d_sleep(unsigned int secs) +{ +#ifdef DISTRHO_OS_WINDOWS + Sleep(secs * 1000); +#else + sleep(secs); +#endif +} + +static inline +void d_msleep(unsigned int msecs) +{ +#ifdef DISTRHO_OS_WINDOWS + Sleep(msecs); +#else + usleep(msecs * 1000); +#endif +} + +static inline +void d_usleep(unsigned int usecs) +{ +#ifdef DISTRHO_OS_WINDOWS + Sleep(usecs / 1000); +#else + usleep(usecs); +#endif +} + +// ------------------------------------------------- + +static inline +void d_setenv(const char* key, const char* value) +{ +#if DISTRHO_OS_WINDOWS + SetEnvironmentVariableA(key, value); +#else + setenv(key, value, 1); +#endif +} + +// ------------------------------------------------- + +class d_string +{ +public: + // --------------------------------------------- + // constructors (no explicit conversions allowed) + + explicit d_string() + { + _init(); + _dup(nullptr); + } + + explicit d_string(char* const strBuf) + { + _init(); + _dup(strBuf); + } + + explicit d_string(const char* const strBuf) + { + _init(); + _dup(strBuf); + } + + explicit d_string(const int value) + { + const size_t strBufSize = std::abs(value/10) + 3; + char strBuf[strBufSize]; + std::snprintf(strBuf, strBufSize, "%d", value); + + _init(); + _dup(strBuf, strBufSize); + } + + explicit d_string(const unsigned int value, const bool hexadecimal = false) + { + const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0); + char strBuf[strBufSize]; + std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%x" : "%u", value); + + _init(); + _dup(strBuf, strBufSize); + } + + explicit d_string(const long int value) + { + const size_t strBufSize = std::abs(value/10) + 3; + char strBuf[strBufSize]; + std::snprintf(strBuf, strBufSize, "%ld", value); + + _init(); + _dup(strBuf, strBufSize); + } + + explicit d_string(const unsigned long int value, const bool hexadecimal = false) + { + const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0); + char strBuf[strBufSize]; + std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%lx" : "%lu", value); + + _init(); + _dup(strBuf, strBufSize); + } + + explicit d_string(const float value) + { + char strBuf[0xff]; + std::snprintf(strBuf, 0xff, "%f", value); + + _init(); + _dup(strBuf); + } + + explicit d_string(const double value) + { + char strBuf[0xff]; + std::snprintf(strBuf, 0xff, "%g", value); + + _init(); + _dup(strBuf); + } + + // --------------------------------------------- + // non-explicit constructor + + d_string(const d_string& str) + { + _init(); + _dup(str.buffer); + } + + // --------------------------------------------- + // deconstructor + + ~d_string() + { + assert(buffer != nullptr); + + delete[] buffer; + } + + // --------------------------------------------- + // public methods + + size_t length() const + { + return bufferLen; + } + + bool isEmpty() const + { + return (bufferLen == 0); + } + + bool isNotEmpty() const + { + return (bufferLen != 0); + } + +#if __USE_GNU + bool contains(const char* const strBuf, const bool ignoreCase = false) const + { + if (strBuf == nullptr) + return false; + + if (ignoreCase) + return (strcasestr(buffer, strBuf) != nullptr); + else + return (std::strstr(buffer, strBuf) != nullptr); + } + + bool contains(const d_string& str, const bool ignoreCase = false) const + { + return contains(str.buffer, ignoreCase); + } +#else + bool contains(const char* const strBuf) const + { + if (strBuf == nullptr) + return false; + + return (std::strstr(buffer, strBuf) != nullptr); + } + + bool contains(const d_string& str) const + { + return contains(str.buffer); + } +#endif + + bool isDigit(const size_t pos) const + { + if (pos >= bufferLen) + return false; + + return (buffer[pos] >= '0' && buffer[pos] <= '9'); + } + + void clear() + { + truncate(0); + } + + size_t find(const char c) + { + for (size_t i=0; i < bufferLen; i++) + { + if (buffer[i] == c) + return i; + } + + return 0; + } + + size_t rfind(const char c) + { + size_t pos = 0; + + for (size_t i=0; i < bufferLen; i++) + { + if (buffer[i] == c) + pos = i; + } + + return pos; + } + + void replace(const char before, const char after) + { + if (after == '\0') + return; + + for (size_t i=0; i < bufferLen; i++) + { + if (buffer[i] == before) + buffer[i] = after; + else if (buffer[i] == '\0') + break; + } + } + + void truncate(const size_t n) + { + if (n >= bufferLen) + return; + + for (size_t i=n; i < bufferLen; i++) + buffer[i] = '\0'; + + bufferLen = n; + } + + void toBasic() + { + for (size_t i=0; i < bufferLen; i++) + { + if (buffer[i] >= '0' && buffer[i] <= '9') + continue; + if (buffer[i] >= 'A' && buffer[i] <= 'Z') + continue; + if (buffer[i] >= 'a' && buffer[i] <= 'z') + continue; + if (buffer[i] == '_') + continue; + + buffer[i] = '_'; + } + } + + void toLower() + { + static const char charDiff = 'a' - 'A'; + + for (size_t i=0; i < bufferLen; i++) + { + if (buffer[i] >= 'A' && buffer[i] <= 'Z') + buffer[i] += charDiff; + } + } + + void toUpper() + { + static const char charDiff = 'a' - 'A'; + + for (size_t i=0; i < bufferLen; i++) + { + if (buffer[i] >= 'a' && buffer[i] <= 'z') + buffer[i] -= charDiff; + } + } + + // --------------------------------------------- + // public operators + + operator const char*() const + { + return buffer; + } + + char& operator[](const size_t pos) + { + return buffer[pos]; + } + + bool operator==(const char* const strBuf) const + { + return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0); + } + + bool operator==(const d_string& str) const + { + return operator==(str.buffer); + } + + bool operator!=(const char* const strBuf) const + { + return !operator==(strBuf); + } + + bool operator!=(const d_string& str) const + { + return !operator==(str.buffer); + } + + d_string& operator=(const char* const strBuf) + { + _dup(strBuf); + + return *this; + } + + d_string& operator=(const d_string& str) + { + return operator=(str.buffer); + } + + d_string& operator+=(const char* const strBuf) + { + const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1; + char newBuf[newBufSize]; + + std::strcpy(newBuf, buffer); + std::strcat(newBuf, strBuf); + + _dup(newBuf, newBufSize-1); + + return *this; + } + + d_string& operator+=(const d_string& str) + { + return operator+=(str.buffer); + } + + d_string operator+(const char* const strBuf) + { + const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1; + char newBuf[newBufSize]; + + std::strcpy(newBuf, buffer); + std::strcat(newBuf, strBuf); + + return d_string(newBuf); + } + + d_string operator+(const d_string& str) + { + return operator+(str.buffer); + } + + // --------------------------------------------- + +private: + char* buffer; + size_t bufferLen; + bool firstInit; + + void _init() + { + buffer = nullptr; + bufferLen = 0; + firstInit = true; + } + + // allocate string strBuf if not null + // size > 0 only if strBuf is valid + void _dup(const char* const strBuf, const size_t size = 0) + { + if (strBuf != nullptr) + { + // don't recreate string if contents match + if (firstInit || std::strcmp(buffer, strBuf) != 0) + { + if (! firstInit) + { + assert(buffer != nullptr); + delete[] buffer; + } + + bufferLen = (size > 0) ? size : std::strlen(strBuf); + buffer = new char[bufferLen+1]; + + std::strcpy(buffer, strBuf); + + buffer[bufferLen] = '\0'; + + firstInit = false; + } + } + else + { + assert(size == 0); + + // don't recreate null string + if (firstInit || bufferLen != 0) + { + if (! firstInit) + { + assert(buffer != nullptr); + delete[] buffer; + } + + bufferLen = 0; + buffer = new char[1]; + buffer[0] = '\0'; + + firstInit = false; + } + } + } +}; + +// ------------------------------------------------- + +static inline +d_string operator+(const char* const strBufBefore, const d_string& strAfter) +{ + const char* const strBufAfter = (const char*)strAfter; + const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1; + char newBuf[newBufSize]; + + std::strcpy(newBuf, strBufBefore); + std::strcat(newBuf, strBufAfter); + + return d_string(newBuf); +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __UTILS_HPP__ diff --git a/source/libs/distrho/src/DistrhoDefines.h b/source/libs/distrho/src/DistrhoDefines.h new file mode 100644 index 000000000..d21740e5a --- /dev/null +++ b/source/libs/distrho/src/DistrhoDefines.h @@ -0,0 +1,95 @@ +/* + * 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 + */ + +#ifndef __DISTRHO_DEFINES_H__ +#define __DISTRHO_DEFINES_H__ + +#include "DistrhoPluginInfo.h" + +#ifndef DISTRHO_PLUGIN_NAME +# error DISTRHO_PLUGIN_NAME undefined! +#endif + +#ifndef DISTRHO_PLUGIN_HAS_UI +# error DISTRHO_PLUGIN_HAS_UI undefined! +#endif + +#ifndef DISTRHO_PLUGIN_IS_SYNTH +# error DISTRHO_PLUGIN_IS_SYNTH undefined! +#endif + +#ifndef DISTRHO_PLUGIN_NUM_INPUTS +# error DISTRHO_PLUGIN_NUM_INPUTS undefined! +#endif + +#ifndef DISTRHO_PLUGIN_NUM_OUTPUTS +# error DISTRHO_PLUGIN_NUM_OUTPUTS undefined! +#endif + +#ifndef DISTRHO_PLUGIN_WANT_LATENCY +# error DISTRHO_PLUGIN_WANT_LATENCY undefined! +#endif + +#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS +# error DISTRHO_PLUGIN_WANT_PROGRAMS undefined! +#endif + +#ifndef DISTRHO_PLUGIN_WANT_STATE +# error DISTRHO_PLUGIN_WANT_STATE undefined! +#endif + +#if defined(__WIN32__) || defined(__WIN64__) +# define DISTRHO_PLUGIN_EXPORT extern "C" __declspec (dllexport) +# define DISTRHO_OS_WINDOWS 1 +# define DISTRHO_DLL_EXTENSION "dll" +#else +# define DISTRHO_PLUGIN_EXPORT extern "C" __attribute__ ((visibility("default"))) +# if defined(__APPLE__) +# define DISTRHO_OS_MAC 1 +# define DISTRHO_DLL_EXTENSION "dylib" +# elif defined(__HAIKU__) +# define DISTRHO_OS_HAIKU 1 +# define DISTRHO_DLL_EXTENSION "so" +# elif defined(__linux__) +# define DISTRHO_OS_LINUX 1 +# define DISTRHO_DLL_EXTENSION "so" +# endif +#endif + +#ifndef DISTRHO_DLL_EXTENSION +# define DISTRHO_DLL_EXTENSION "so" +#endif + +#ifndef DISTRHO_NO_NAMESPACE +# ifndef DISTRHO_NAMESPACE +# define DISTRHO_NAMESPACE DISTRHO +# endif +# define START_NAMESPACE_DISTRHO namespace DISTRHO_NAMESPACE { +# define END_NAMESPACE_DISTRHO } +# define USE_NAMESPACE_DISTRHO using namespace DISTRHO_NAMESPACE; +#else +# define START_NAMESPACE_DISTRHO +# define END_NAMESPACE_DISTRHO +# define USE_NAMESPACE_DISTRHO +#endif + +#ifndef DISTRHO_UI_QT4 +# define DISTRHO_UI_OPENGL +#endif + +#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" + +#endif // __DISTRHO_DEFINES_H__ diff --git a/source/libs/distrho/src/DistrhoPlugin.cpp b/source/libs/distrho/src/DistrhoPlugin.cpp new file mode 100644 index 000000000..976493671 --- /dev/null +++ b/source/libs/distrho/src/DistrhoPlugin.cpp @@ -0,0 +1,105 @@ +/* + * 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 "DistrhoPluginInternal.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Static data + +uint32_t d_lastBufferSize = 0; +double d_lastSampleRate = 0.0; + +// ------------------------------------------------- +// Static, fallback data + +const d_string PluginInternal::sFallbackString; +const ParameterRanges PluginInternal::sFallbackRanges; + +// ------------------------------------------------- +// Plugin + +Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount) + : pData(new PluginPrivateData) +{ + if (parameterCount > 0) + { + pData->parameterCount = parameterCount; + pData->parameters = new Parameter[parameterCount]; + } + + if (programCount > 0) + { +#if DISTRHO_PLUGIN_WANT_PROGRAMS + pData->programCount = programCount; + pData->programNames = new d_string[programCount]; +#endif + } + + if (stateCount > 0) + { +#if DISTRHO_PLUGIN_WANT_STATE + pData->stateCount = stateCount; + pData->stateKeys = new d_string[stateCount]; +#endif + } +} + +Plugin::~Plugin() +{ + delete pData; +} + +// ------------------------------------------------- +// Host state + +uint32_t Plugin::d_bufferSize() const +{ + return pData->bufferSize; +} + +double Plugin::d_sampleRate() const +{ + return pData->sampleRate; +} + +const TimePos& Plugin::d_timePos() const +{ + return pData->timePos; +} + +#if DISTRHO_PLUGIN_WANT_LATENCY +void Plugin::d_setLatency(uint32_t frames) +{ + pData->latency = frames; +} +#endif + +// ------------------------------------------------- +// Callbacks + +void Plugin::d_bufferSizeChanged(uint32_t) +{ +} + +void Plugin::d_sampleRateChanged(double) +{ +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/libs/distrho/src/DistrhoPluginInternal.hpp b/source/libs/distrho/src/DistrhoPluginInternal.hpp new file mode 100644 index 000000000..c32e8f48d --- /dev/null +++ b/source/libs/distrho/src/DistrhoPluginInternal.hpp @@ -0,0 +1,358 @@ +/* + * 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 + */ + +#ifndef __DISTRHO_PLUGIN_INTERNAL_HPP__ +#define __DISTRHO_PLUGIN_INTERNAL_HPP__ + +#include "../DistrhoPlugin.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +#define MAX_MIDI_EVENTS 512 + +extern uint32_t d_lastBufferSize; +extern double d_lastSampleRate; + +struct PluginPrivateData { + uint32_t bufferSize; + double sampleRate; + + uint32_t parameterCount; + Parameter* parameters; + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t programCount; + d_string* programNames; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + uint32_t stateCount; + d_string* stateKeys; +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY + uint32_t latency; +#endif + + TimePos timePos; + + PluginPrivateData() + : bufferSize(d_lastBufferSize), + sampleRate(d_lastSampleRate), + parameterCount(0), + parameters(nullptr), +#if DISTRHO_PLUGIN_WANT_PROGRAMS + programCount(0), + programNames(nullptr), +#endif +#if DISTRHO_PLUGIN_WANT_STATE + stateCount(0), + stateKeys(nullptr), +#endif +#if DISTRHO_PLUGIN_WANT_LATENCY + latency(0), +#endif + timePos() + { + assert(d_lastBufferSize != 0); + assert(d_lastSampleRate != 0.0); + } + + ~PluginPrivateData() + { + if (parameterCount > 0 && parameters != nullptr) + delete[] parameters; + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + if (programCount > 0 && programNames != nullptr) + delete[] programNames; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + if (stateCount > 0 && stateKeys != nullptr) + delete[] stateKeys; +#endif + } +}; + +// ------------------------------------------------- + +class PluginInternal +{ +public: + PluginInternal() + : kPlugin(createPlugin()), + kData((kPlugin != nullptr) ? kPlugin->pData : nullptr) + { + assert(kPlugin != nullptr); + + if (kPlugin == nullptr) + return; + + for (uint32_t i=0, count=kData->parameterCount; i < count; i++) + kPlugin->d_initParameter(i, kData->parameters[i]); + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + for (uint32_t i=0, count=kData->programCount; i < count; i++) + kPlugin->d_initProgramName(i, kData->programNames[i]); +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + for (uint32_t i=0, count=kData->stateCount; i < count; i++) + kPlugin->d_initStateKey(i, kData->stateKeys[i]); +#endif + } + + ~PluginInternal() + { + if (kPlugin != nullptr) + delete kPlugin; + } + + // --------------------------------------------- + + const char* name() const + { + assert(kPlugin != nullptr); + return (kPlugin != nullptr) ? kPlugin->d_name() : ""; + } + + const char* label() const + { + assert(kPlugin != nullptr); + return (kPlugin != nullptr) ? kPlugin->d_label() : ""; + } + + const char* maker() const + { + assert(kPlugin != nullptr); + return (kPlugin != nullptr) ? kPlugin->d_maker() : ""; + } + + const char* license() const + { + assert(kPlugin != nullptr); + return (kPlugin != nullptr) ? kPlugin->d_license() : ""; + } + + uint32_t version() const + { + assert(kPlugin != nullptr); + return (kPlugin != nullptr) ? kPlugin->d_version() : 1000; + } + + long uniqueId() const + { + assert(kPlugin != nullptr); + return (kPlugin != nullptr) ? kPlugin->d_uniqueId() : 0; + } + + // --------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_LATENCY + uint32_t latency() const + { + assert(kData != nullptr); + return (kData != nullptr) ? kData->latency : 0; + } +#endif + + uint32_t parameterCount() const + { + assert(kData != nullptr); + return (kData != nullptr) ? kData->parameterCount : 0; + } + + uint32_t parameterHints(uint32_t index) const + { + assert(kData != nullptr && index < kData->parameterCount); + return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].hints : 0x0; + } + + bool parameterIsOutput(uint32_t index) const + { + uint32_t hints = parameterHints(index); + return (hints & PARAMETER_IS_OUTPUT); + } + + const d_string& parameterName(uint32_t index) const + { + assert(kData != nullptr && index < kData->parameterCount); + return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].name : sFallbackString; + } + + const d_string& parameterSymbol(uint32_t index) const + { + assert(kData != nullptr && index < kData->parameterCount); + return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].symbol : sFallbackString; + } + + const d_string& parameterUnit(uint32_t index) const + { + assert(kData != nullptr && index < kData->parameterCount); + return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].unit : sFallbackString; + } + + const ParameterRanges& parameterRanges(uint32_t index) const + { + assert(kData != nullptr && index < kData->parameterCount); + return (kData != nullptr && index < kData->parameterCount) ? kData->parameters[index].ranges : sFallbackRanges; + } + + float parameterValue(uint32_t index) + { + assert(kPlugin != nullptr && index < kData->parameterCount); + return (kPlugin != nullptr && index < kData->parameterCount) ? kPlugin->d_parameterValue(index) : 0.0f; + } + + void setParameterValue(uint32_t index, float value) + { + assert(kPlugin != nullptr && index < kData->parameterCount); + + if (kPlugin != nullptr && index < kData->parameterCount) + kPlugin->d_setParameterValue(index, value); + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t programCount() const + { + assert(kData != nullptr); + return (kData != nullptr) ? kData->programCount : 0; + } + + const d_string& programName(uint32_t index) const + { + assert(kData != nullptr && index < kData->programCount); + return (kData != nullptr && index < kData->programCount) ? kData->programNames[index] : sFallbackString; + } + + void setProgram(uint32_t index) + { + assert(kPlugin != nullptr && index < kData->programCount); + + if (kPlugin != nullptr && index < kData->programCount) + kPlugin->d_setProgram(index); + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + uint32_t stateCount() const + { + assert(kData != nullptr); + return kData != nullptr ? kData->stateCount : 0; + } + + const d_string& stateKey(uint32_t index) const + { + assert(kData != nullptr && index < kData->stateCount); + return (kData != nullptr && index < kData->stateCount) ? kData->stateKeys[index] : sFallbackString; + } + + void setState(const char* key, const char* value) + { + assert(kPlugin && key && value); + + if (kPlugin && key && value) + kPlugin->d_setState(key, value); + } +#endif + + // --------------------------------------------- + + void activate() + { + assert(kPlugin != nullptr); + + if (kPlugin != nullptr) + kPlugin->d_activate(); + } + + void deactivate() + { + assert(kPlugin != nullptr); + + if (kPlugin != nullptr) + kPlugin->d_deactivate(); + } + + void run(float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents) + { + assert(kPlugin != nullptr); + + if (kPlugin != nullptr) + kPlugin->d_run(inputs, outputs, frames, midiEventCount, midiEvents); + } + + // --------------------------------------------- + + void setBufferSize(uint32_t bufferSize, bool callback = false) + { + assert(kData != nullptr && kPlugin && bufferSize >= 2); + + if (kData != nullptr) + { + if (callback && kData->bufferSize == bufferSize) + callback = false; + + kData->bufferSize = bufferSize; + } + + if (kPlugin != nullptr && callback) + { + kPlugin->d_deactivate(); + kPlugin->d_bufferSizeChanged(bufferSize); + kPlugin->d_activate(); + } + } + + void setSampleRate(double sampleRate, bool callback = false) + { + assert(kData != nullptr && kPlugin != nullptr && sampleRate > 0.0); + + if (kData != nullptr) + { + if (callback && kData->sampleRate == sampleRate) + callback = false; + + kData->sampleRate = sampleRate; + } + + if (kPlugin != nullptr && callback) + { + kPlugin->d_deactivate(); + kPlugin->d_sampleRateChanged(sampleRate); + kPlugin->d_activate(); + } + } + + // --------------------------------------------- + +protected: + Plugin* const kPlugin; + PluginPrivateData* const kData; + +private: + static const d_string sFallbackString; + static const ParameterRanges sFallbackRanges; +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_PLUGIN_INTERNAL_HPP__ diff --git a/source/libs/distrho/src/DistrhoUI.cpp b/source/libs/distrho/src/DistrhoUI.cpp new file mode 100644 index 000000000..88eda713a --- /dev/null +++ b/source/libs/distrho/src/DistrhoUI.cpp @@ -0,0 +1,92 @@ +/* + * 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 "DistrhoUIInternal.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// Static data + +double d_lastUiSampleRate = 0.0; + +// ------------------------------------------------- +// UI + +UI::UI() + : pData(new UIPrivateData) +{ +#if (defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2)) + pData->parameterOffset = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; +# if DISTRHO_PLUGIN_WANT_LATENCY + pData->parameterOffset += 1; // latency +# endif + pData->parameterOffset += 1; // sample-rate +#endif + +#ifdef DISTRHO_UI_QT4 + pData->widget = (Qt4UI*)this; +#endif +} + +UI::~UI() +{ + delete pData; +} + +// ------------------------------------------------- +// Host DSP State + +double UI::d_sampleRate() const +{ + return pData->sampleRate; +} + +void UI::d_editParameter(uint32_t index, bool started) +{ + pData->editParamCallback(index, started); +} + +void UI::d_setParameterValue(uint32_t index, float value) +{ + pData->setParamCallback(index + pData->parameterOffset, value); +} + +#if DISTRHO_PLUGIN_WANT_STATE +void UI::d_setState(const char* key, const char* value) +{ + pData->setStateCallback(key, value); +} +#endif + +#if DISTRHO_PLUGIN_IS_SYNTH +void UI::d_sendNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) +{ + pData->sendNoteCallback(onOff, channel, note, velocity); +} +#endif + +// ------------------------------------------------- +// Host UI State + +void UI::d_uiResize(unsigned int width, unsigned int height) +{ + pData->uiResizeCallback(width, height); +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/source/libs/distrho/src/DistrhoUIInternal.hpp b/source/libs/distrho/src/DistrhoUIInternal.hpp new file mode 100644 index 000000000..348776b91 --- /dev/null +++ b/source/libs/distrho/src/DistrhoUIInternal.hpp @@ -0,0 +1,455 @@ +/* + * 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 + */ + +#ifndef __DISTRHO_UI_INTERNAL_HPP__ +#define __DISTRHO_UI_INTERNAL_HPP__ + +#include "DistrhoDefines.h" + +//#ifdef DISTRHO_UI_OPENGL +//# include "DistrhoUIOpenGL.h" +// START_NAMESPACE_DISTRHO +//# include "pugl/pugl.h" +// END_NAMESPACE_DISTRHO +//#else + +# include "../DistrhoUIQt4.hpp" +# include +# include +# include +# include +# ifdef Q_WS_X11 +# include +# endif + +//#endif + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- + +//#ifdef DISTRHO_UI_OPENGL +//typedef PuglView NativeWidget; +//#else +typedef QWidget NativeWidget; +//#endif + +typedef void (*editParamFunc) (void* ptr, uint32_t index, bool started); +typedef void (*setParamFunc) (void* ptr, uint32_t index, float value); +typedef void (*setStateFunc) (void* ptr, const char* key, const char* value); +typedef void (*sendNoteFunc) (void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velo); +typedef void (*uiResizeFunc) (void* ptr, unsigned int width, unsigned int height); + +extern double d_lastUiSampleRate; + +// ------------------------------------------------- + +//#ifdef DISTRHO_UI_QT4 +# ifdef Q_WS_X11 +class QEmbedWidget : public QX11EmbedWidget +# else +class QEmbedWidget : public QWidget +# endif +{ +public: + QEmbedWidget(); + ~QEmbedWidget(); + + void embedInto(WId id); + WId containerWinId() const; +}; +//#endif + +// ------------------------------------------------- + +struct UIPrivateData { + // DSP + double sampleRate; + uint32_t parameterOffset; + + // UI + void* ptr; + NativeWidget* widget; + + // Callbacks + editParamFunc editParamCallbackFunc; + setParamFunc setParamCallbackFunc; + setStateFunc setStateCallbackFunc; + sendNoteFunc sendNoteCallbackFunc; + uiResizeFunc uiResizeCallbackFunc; + + UIPrivateData() + : sampleRate(d_lastUiSampleRate), + parameterOffset(0), + ptr(nullptr), + widget(nullptr), + editParamCallbackFunc(nullptr), + setParamCallbackFunc(nullptr), + setStateCallbackFunc(nullptr), + sendNoteCallbackFunc(nullptr), + uiResizeCallbackFunc(nullptr) + { + assert(d_lastUiSampleRate != 0.0); + } + + ~UIPrivateData() + { + } + + void editParamCallback(uint32_t index, bool started) + { + if (editParamCallbackFunc != nullptr) + editParamCallbackFunc(ptr, index, started); + } + + void setParamCallback(uint32_t rindex, float value) + { + if (setParamCallbackFunc != nullptr) + setParamCallbackFunc(ptr, rindex, value); + } + + void setStateCallback(const char* key, const char* value) + { + if (setStateCallbackFunc != nullptr) + setStateCallbackFunc(ptr, key, value); + } + + void sendNoteCallback(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) + { + if (sendNoteCallbackFunc != nullptr) + sendNoteCallbackFunc(ptr, onOff, channel, note, velocity); + } + + void uiResizeCallback(unsigned int width, unsigned int height) + { + if (uiResizeCallbackFunc != nullptr) + uiResizeCallbackFunc(ptr, width, height); + } +}; + +// ------------------------------------------------- + +#ifdef DISTRHO_UI_QT4 +class UIInternal : public QObject // needed for eventFilter() +#else +class UIInternal +#endif +{ +public: + UIInternal(void* ptr, intptr_t winId, editParamFunc editParamCall, setParamFunc setParamCall, setStateFunc setStateCall, sendNoteFunc sendNoteCall, uiResizeFunc uiResizeCall) + : kUi(createUI()), + kData((kUi != nullptr) ? kUi->pData : nullptr), +#ifdef DISTRHO_UI_QT4 + qtMouseDown(false), + qtGrip(nullptr), + qtWidget(nullptr) +#else + glInitiated(false) +#endif + { + assert(kUi != nullptr); + assert(winId != 0); + + if (kUi == nullptr || winId == 0) + return; + + kData->ptr = ptr; + kData->editParamCallbackFunc = editParamCall; + kData->setParamCallbackFunc = setParamCall; + kData->setStateCallbackFunc = setStateCall; + kData->sendNoteCallbackFunc = sendNoteCall; + kData->uiResizeCallbackFunc = uiResizeCall; + + createWindow(winId); + } + + ~UIInternal() + { + if (kUi != nullptr) + { + destroyWindow(); + delete kUi; + } + } + + // --------------------------------------------- + + const char* name() const + { + assert(kUi != nullptr); + return (kUi != nullptr) ? kUi->d_name() : ""; + } + + unsigned int width() + { + assert(kUi != nullptr); + return (kUi != nullptr) ? kUi->d_width() : 0; + } + + unsigned int height() + { + assert(kUi != nullptr); + return (kUi != nullptr) ? kUi->d_height() : 0; + } + + // --------------------------------------------- + + void parameterChanged(uint32_t index, float value) + { + assert(kUi != nullptr); + + if (kUi != nullptr) + kUi->d_parameterChanged(index, value); + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + void programChanged(uint32_t index) + { + assert(kUi != nullptr); + + if (kUi != nullptr) + kUi->d_programChanged(index); + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + void stateChanged(const char* key, const char* value) + { + assert(kUi != nullptr); + + if (kUi != nullptr) + kUi->d_stateChanged(key, value); + } +#endif + +#if DISTRHO_PLUGIN_IS_SYNTH + void noteReceived(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) + { + assert(kUi != nullptr); + + if (kUi != nullptr) + kUi->d_noteReceived(onOff, channel, note, velocity); + } +#endif + + // --------------------------------------------- + + void idle() + { + assert(kUi != nullptr); + + if (kUi != nullptr) + kUi->d_uiIdle(); + } + + intptr_t getWindowId() + { +#ifdef DISTRHO_UI_QT4 + assert(qtWidget != nullptr); + return (qtWidget != nullptr) ? qtWidget->winId() : 0; +#else +#endif + } + + // --------------------------------------------- + + void createWindow(intptr_t parent) + { +#ifdef DISTRHO_UI_QT4 + assert(kUi != nullptr); + assert(kData != nullptr); + assert(kData->widget != nullptr); + assert(qtGrip == nullptr); + assert(qtWidget == nullptr); + + if (kUi == nullptr) + return; + if (kData == nullptr) + return; + if (kData->widget == nullptr) + return; + if (qtGrip != nullptr) + return; + if (qtWidget != nullptr) + return; + + qtMouseDown = false; + + // create embedable widget + qtWidget = new QEmbedWidget; + + // set layout + qtWidget->setLayout(new QVBoxLayout(qtWidget)); + qtWidget->layout()->addWidget(kData->widget); + qtWidget->layout()->setContentsMargins(0, 0, 0, 0); + qtWidget->setFixedSize(kUi->d_width(), kUi->d_height()); + + // set resize grip + if (((Qt4UI*)kUi)->d_resizable()) + { + // listen for resize on the plugin widget + kData->widget->installEventFilter(this); + + // create resize grip on bottom-right + qtGrip = new QSizeGrip(qtWidget); + qtGrip->resize(qtGrip->sizeHint()); + qtGrip->setCursor(Qt::SizeFDiagCursor); + qtGrip->move(kUi->d_width() - qtGrip->width(), kUi->d_height() - qtGrip->height()); + qtGrip->show(); + qtGrip->raise(); + qtGrip->installEventFilter(this); + } + + // reparent widget + qtWidget->embedInto(parent); + + // show it + qtWidget->show(); +#else +#endif + } + + void destroyWindow() + { +#ifdef DISTRHO_UI_QT4 + assert(kData != nullptr); + assert(kData->widget != nullptr); + assert(qtWidget != nullptr); + + if (kData == nullptr) + return; + if (kData->widget == nullptr) + return; + if (qtWidget == nullptr) + return; + + // remove main widget, to prevent it from being auto-deleted + kData->widget->hide(); + qtWidget->layout()->removeWidget(kData->widget); + kData->widget->setParent(nullptr); + kData->widget->close(); + + qtWidget->close(); + qtWidget->removeEventFilter(this); + + if (qtGrip != nullptr) + { + qtGrip->removeEventFilter(this); + delete qtGrip; + qtGrip = nullptr; + } + + delete qtWidget; + qtWidget = nullptr; +#else +#endif + } + + // --------------------------------------------- + +protected: + UI* const kUi; + UIPrivateData* const kData; + +#ifdef DISTRHO_UI_QT4 + // FIXME - remove qtMouseDown usage + bool eventFilter(QObject* obj, QEvent* event) + { + assert(kUi != nullptr); + assert(kData != nullptr); + assert(kData->widget != nullptr); + assert(qtGrip != nullptr); + assert(qtWidget != nullptr); + + if (kUi == nullptr) + return false; + if (kData == nullptr) + return false; + if (kData->widget == nullptr) + return false; + if (qtGrip == nullptr) + return false; + if (qtWidget == nullptr) + return false; + + if (obj == nullptr) + { + // nothing + } + else if (obj == qtGrip) + { + if (event->type() == QEvent::MouseButtonPress) + { + QMouseEvent* mEvent = (QMouseEvent*)event; + if (mEvent->button() == Qt::LeftButton) + qtMouseDown = true; + } + else if (event->type() == QEvent::MouseMove) + { + if (qtMouseDown) + { + Qt4UI* qtUi = (Qt4UI*)kUi; + QMouseEvent* mEvent = (QMouseEvent*)event; + unsigned int width = qtUi->d_width() + mEvent->x() - qtGrip->width(); + unsigned int height = qtUi->d_height() + mEvent->y() - qtGrip->height(); + + if (width < qtUi->d_minimumWidth()) + width = qtUi->d_minimumWidth(); + if (height < qtUi->d_minimumHeight()) + height = qtUi->d_minimumHeight(); + + kData->widget->setFixedSize(width, height); + + return true; + } + } + else if (event->type() == QEvent::MouseButtonRelease) + { + QMouseEvent* mEvent = (QMouseEvent*)event; + if (mEvent->button() == Qt::LeftButton) + qtMouseDown = false; + } + } + else if (obj == kData->widget && event->type() == QEvent::Resize) + { + QResizeEvent* rEvent = (QResizeEvent*)event; + const QSize& size = rEvent->size(); + + qtWidget->setFixedSize(size.width(), size.height()); + qtGrip->move(size.width() - qtGrip->width(), size.height() - qtGrip->height()); + + kUi->d_uiResize(size.width(), size.height()); + } + + return QObject::eventFilter(obj, event); + } +#endif + +private: +#ifdef DISTRHO_UI_QT4 + bool qtMouseDown; + QSizeGrip* qtGrip; + QEmbedWidget* qtWidget; +#else + bool glInitiated; +#endif +}; + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // __DISTRHO_UI_INTERNAL_HPP__ diff --git a/source/libs/distrho/src/DistrhoUIQt4.cpp b/source/libs/distrho/src/DistrhoUIQt4.cpp new file mode 100644 index 000000000..64e20fccf --- /dev/null +++ b/source/libs/distrho/src/DistrhoUIQt4.cpp @@ -0,0 +1,78 @@ +/* + * 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 "DistrhoUIInternal.hpp" + +START_NAMESPACE_DISTRHO + +// ------------------------------------------------- +// QEmbedWidget + +QEmbedWidget::QEmbedWidget() +{ +} + +QEmbedWidget::~QEmbedWidget() +{ +} + +void QEmbedWidget::embedInto(WId id) +{ +#ifdef Q_WS_X11 + QX11EmbedWidget::embedInto(id); +#endif +} + +WId QEmbedWidget::containerWinId() const +{ +#ifdef Q_WS_X11 + return QX11EmbedWidget::containerWinId(); +#else + return 0; +#endif +} + +// ------------------------------------------------- +// Qt4UI + +Qt4UI::Qt4UI() + : UI(), + QWidget(nullptr) +{ +} + +Qt4UI::~Qt4UI() +{ +} + +// ------------------------------------------------- +// UI Callbacks + +void Qt4UI::d_uiIdle() +{ +} + +// ------------------------------------------------- +// Implement resize internally + +void Qt4UI::d_uiResize(unsigned int width, unsigned int height) +{ + UI::d_uiResize(width, height); +} + +// ------------------------------------------------- + +END_NAMESPACE_DISTRHO