@@ -4,29 +4,29 @@ This file describes the available features for each plugin format. | |||||
The limitations could be due to the plugin format itself or within DPF. | The limitations could be due to the plugin format itself or within DPF. | ||||
If the limitation is within DPF, a link is provided to a description below on the reason for it. | If the limitation is within DPF, a link is provided to a description below on the reason for it. | ||||
| Feature | JACK/Standalone | LADSPA | DSSI | LV2 | VST2 | VST3 | Feature | | |||||
|---------------------|---------------------------------------|-------------------------|---------------------|-------------------------------|--------------------------------|----------------------------------|---------------------| | |||||
| Audio port groups | [Yes*](#jack-audio-port-groups) | No | No | Yes | No | [No*](#vst3-is-work-in-progress) | Audio port groups | | |||||
| Audio port as CV | Yes | No | No | Yes | No | [No*](#vst3-is-work-in-progress) | Audio port as CV | | |||||
| Audio sidechan | Yes | No | No | Yes | [No*](#vst2-potential-support) | [No*](#vst3-is-work-in-progress) | Audio sidechan | | |||||
| Bypass control | No | No | No | Yes | [No*](#vst2-potential-support) | [No*](#vst3-is-work-in-progress) | Bypass control | | |||||
| MIDI input | Yes | No | Yes | Yes | Yes | Yes | MIDI input | | |||||
| MIDI output | Yes | No | No | Yes | Yes | Yes | MIDI output | | |||||
| Parameter changes | Yes | No | No | [No*](#lv2-parameter-changes) | Yes | Yes | Parameter changes | | |||||
| Parameter groups | No | No | No | Yes | Yes | [No*](#vst3-is-work-in-progress) | Parameter groups | | |||||
| Parameter outputs | No | No | No | Yes | No | [No*](#vst3-is-work-in-progress) | Parameter outputs | | |||||
| Parameter triggers | Yes | No | No | Yes | [No*](#parameter-triggers) | [No*](#parameter-triggers) | Parameter triggers | | |||||
| Programs | [Yes*](#jack-parameters-and-programs) | [No*](#ladspa-programs) | [Yes*](#dssi-state) | Yes | [No*](#vst2-programs) | Yes | Programs | | |||||
| States | Yes | No | [Yes*](#dssi-state) | Yes | Yes | Yes | States | | |||||
| Full/internal state | Yes | No | No | Yes | Yes | Yes | Full/internal state | | |||||
| Time position | Yes | No | No | Yes | Yes | Yes | Time position | | |||||
| UI | [Yes*](#jack-custom-ui-only) | No | External only | Yes | Embed only | Embed only | UI | | |||||
| UI bg/fg colors | No | No | No | Yes | No | No? | UI bg/fg colors | | |||||
| UI direct access | Yes | No | No | Yes | Yes | Yes | UI direct access | | |||||
| UI host-filebrowser | No | No | No | Yes | [No*](#vst2-potential-support) | [No*](#vst3-is-work-in-progress) | UI host-filebrowser | | |||||
| UI host-resize | Yes | No | Yes | Yes | No | [No*](#vst3-is-work-in-progress) | UI host-resize | | |||||
| UI remote control | No | No | Yes | Yes | No | Yes | UI remote control | | |||||
| UI send midi note | Yes | No | Yes | Yes | Yes | Yes | UI send midi note | | |||||
| Feature | JACK/Standalone | LADSPA | DSSI | LV2 | VST2 | VST3 | CLAP | Feature | | |||||
|---------------------|---------------------------------------|--------------------|---------------------|-------------------------------|----------------------------|----------------------------|-------------------------------|---------------------| | |||||
| Audio port groups | [Yes*](#jack-audio-port-groups) | No | No | Yes | No | Yes | Yes | Audio port groups | | |||||
| Audio port as CV | Yes | No | No | Yes | No | [Yes*](#vst3-cv) | [No*](#work-in-progress) | Audio port as CV | | |||||
| Audio sidechan | Yes | No | No | Yes | [No*](#vst2-deprecated) | Yes | Yes | Audio sidechan | | |||||
| Bypass control | No | No | No | Yes | [No*](#vst2-deprecated) | Yes | Yes | Bypass control | | |||||
| MIDI input | Yes | No | Yes | Yes | Yes | Yes | Yes | MIDI input | | |||||
| MIDI output | Yes | No | No | Yes | Yes | Yes | Yes | MIDI output | | |||||
| Parameter changes | Yes | No | No | [No*](#lv2-parameter-changes) | Yes | Yes | Yes | Parameter changes | | |||||
| Parameter groups | No | No | No | Yes | Yes | [No*](#work-in-progress) | Yes | Parameter groups | | |||||
| Parameter outputs | No | No | No | Yes | No | Yes | Yes | Parameter outputs | | |||||
| Parameter triggers | Yes | No | No | Yes | [No*](#parameter-triggers) | [No*](#parameter-triggers) | [No*](#parameter-triggers) | Parameter triggers | | |||||
| Programs | [Yes*](#jack-parameters-and-programs) | [No*](#ladspa-rdf) | [Yes*](#dssi-state) | Yes | [No*](#vst2-programs) | Yes | No | Programs | | |||||
| States | Yes | No | [Yes*](#dssi-state) | Yes | Yes | Yes | Yes | States | | |||||
| Full/internal state | Yes | No | No | Yes | Yes | Yes | Yes | Full/internal state | | |||||
| Time position | Yes | No | No | Yes | Yes | Yes | Yes | Time position | | |||||
| UI | [Yes*](#jack-custom-ui-only) | No | External only | Yes | Embed only | Embed only | Yes | UI | | |||||
| UI bg/fg colors | No | No | No | Yes | No | No? | No | UI bg/fg colors | | |||||
| UI direct access | Yes | No | No | Yes | Yes | Yes | Yes | UI direct access | | |||||
| UI host-filebrowser | No | No | No | Yes | [No*](#vst2-deprecated) | [No*](#work-in-progress) | [No*](#work-in-progress) | UI host-filebrowser | | |||||
| UI host-resize | Yes | No | Yes | Yes | No | Yes | Yes | UI host-resize | | |||||
| UI remote control | No | No | Yes | Yes | No | Yes | No | UI remote control | | |||||
| UI send midi note | Yes | No | Yes | Yes | Yes | Yes | Yes | UI send midi note | | |||||
For things that could be unclear: | For things that could be unclear: | ||||
@@ -59,7 +59,7 @@ MIDI CCs are used for parameter changes (matching the `midiCC` value you set on | |||||
There is no generic plugin editor view. | There is no generic plugin editor view. | ||||
If your plugin has no custom UI, the standalone executable will run but not show any window. | If your plugin has no custom UI, the standalone executable will run but not show any window. | ||||
## LADSPA programs | |||||
## LADSPA RDF | |||||
Programs for LADSPA could be done via LRDF but this is not supported in DPF. | Programs for LADSPA could be done via LRDF but this is not supported in DPF. | ||||
@@ -78,7 +78,7 @@ But if we involve programs, they would need to pass through the UI in order to w | |||||
Although this is already implemented in DPF (through a custom extension), this is not implemented on most hosts. | Although this is already implemented in DPF (through a custom extension), this is not implemented on most hosts. | ||||
So for now you can pretty much treat it as if not supported. | So for now you can pretty much treat it as if not supported. | ||||
## VST2 potential support | |||||
## VST2 deprecated | |||||
Not supported in DPF at the moment. | Not supported in DPF at the moment. | ||||
It could eventually be, but likely not due to VST2 being phased out by Steinberg. | It could eventually be, but likely not due to VST2 being phased out by Steinberg. | ||||
@@ -88,6 +88,11 @@ Contact DPF authors if you require such a feature. | |||||
VST2 program support requires saving state of all programs in memory, which is very expensive and thus not done in DPF. | VST2 program support requires saving state of all programs in memory, which is very expensive and thus not done in DPF. | ||||
## VST3 is work in progress | |||||
## VST3 CV | |||||
Although VST3 officially supports CV (Control Voltage) tagged audio ports, | |||||
at the moment no host supports such feature and thus it is not possible to validate it. | |||||
## Work in progress | |||||
Feature is possible, just not implemented yet in DPF. | Feature is possible, just not implemented yet in DPF. |
@@ -3,21 +3,21 @@ | |||||
[](https://github.com/DISTRHO/DPF/actions/workflows/cmake.yml) | [](https://github.com/DISTRHO/DPF/actions/workflows/cmake.yml) | ||||
[](https://github.com/DISTRHO/DPF/actions/workflows/example-plugins.yml) | [](https://github.com/DISTRHO/DPF/actions/workflows/example-plugins.yml) | ||||
DPF is designed to make development of new plugins an easy and enjoyable task.<br/> | |||||
It allows developers to create plugins with custom UIs using a simple C++ API.<br/> | |||||
The framework facilitates exporting various different plugin formats from the same code-base.<br/> | |||||
DPF is designed to make development of new plugins an easy and enjoyable task. | |||||
It allows developers to create plugins with custom UIs using a simple C++ API. | |||||
The framework facilitates exporting various different plugin formats from the same code-base. | |||||
DPF can build for LADSPA, DSSI, LV2, VST2, VST3 and CLAP formats.<br/> | |||||
All current plugin format implementations are complete.<br/> | |||||
A JACK/Standalone mode is also available, allowing you to quickly test plugins.<br/> | |||||
DPF can build for LADSPA, DSSI, LV2, VST2, VST3 and CLAP formats. | |||||
A JACK/Standalone mode is also available, allowing you to quickly test plugins. | |||||
Plugin DSP and UI communication is done via key-value string pairs.<br/> | |||||
You send messages from the UI to the DSP side, which is automatically saved in the host when required.<br/> | |||||
(You can also store state internally if needed, but this breaks DSSI compatibility).<br/> | |||||
Plugin DSP and UI communication is done via key-value string pairs. | |||||
You send messages from the UI to the DSP side, which is automatically saved in the host when required. | |||||
(You can also store state internally if needed, but this breaks DSSI compatibility). | |||||
Getting time information from the host is possible.<br/> | |||||
It uses the same format as the JACK Transport API, making porting some code easier.<br/> | |||||
Getting time information from the host is possible. | |||||
It uses the same format as the JACK Transport API, making porting some code easier. | |||||
Provided features and implementation status for specific plugin formats can be seen in [FEATURES.md](FEATURES.md). | |||||
## Licensing | ## Licensing | ||||
@@ -31,43 +31,11 @@ Bug reports happen on the [DPF github project](https://github.com/DISTRHO/DPF/is | |||||
Online documentation is available at [https://distrho.github.io/DPF/](https://distrho.github.io/DPF/). | Online documentation is available at [https://distrho.github.io/DPF/](https://distrho.github.io/DPF/). | ||||
Online help and discussion about DPF happens in the [kx.studio chat, DPF room](https://chat.kx.studio/). | |||||
Online help and discussion about DPF happens in the [kx.studio chat, DPF room](https://chat.kx.studio/channel/dpf). | |||||
## List of plugins made with DPF: | ## List of plugins made with DPF: | ||||
- [DISTRHO glBars](https://github.com/DISTRHO/glBars) | |||||
- [DISTRHO Kars](https://github.com/DISTRHO/Kars) | |||||
- [DISTRHO Mini-Series](https://github.com/DISTRHO/Mini-Series) | |||||
- [DISTRHO MVerb](https://github.com/DISTRHO/MVerb) | |||||
- [DISTRHO ndc Plugs](https://github.com/DISTRHO/ndc-Plugs) | |||||
- [DISTRHO Nekobi](https://github.com/DISTRHO/Nekobi) | |||||
- [DISTRHO ProM](https://github.com/DISTRHO/ProM) | |||||
- [Dragonfly Reverb](https://michaelwillis.github.io/dragonfly-reverb) | |||||
- [Fogpad-port](https://github.com/linuxmao-org/fogpad-port) | |||||
- [master_me](https://github.com/trummerschlunk/master_me) | |||||
- [Ninjas2](https://github.com/rghvdberg/ninjas2) | |||||
- [osamc-lv2-workshop](https://github.com/osamc-lv2-workshop/lv2-workshop) (simple plugins code examples) | |||||
- [QuadraFuzz](https://github.com/jpcima/quadrafuzz) | |||||
- [Regrader-Port](https://github.com/linuxmao-org/regrader-port) | |||||
- [Rezonateur](https://github.com/jpcima/rezonateur) | |||||
- [Spectacle-analyzer](https://github.com/jpcima/spectacle/) | |||||
- [Stone Phaser](https://github.com/jpcima/stone-phaser) | |||||
- [String-machine](https://github.com/jpcima/string-machine) | |||||
- [Uhhyou Plugins](https://github.com/ryukau/LV2Plugins) | |||||
- [VL1-emulator](https://github.com/linuxmao-org/VL1-emulator) | |||||
- [Wolf Shaper](https://github.com/pdesaulniers/wolf-shaper) | |||||
- [Wolf Spectrum](https://github.com/pdesaulniers/wolf-spectrum) | |||||
- [YK Chorus](https://github.com/SpotlightKid/ykchorus) | |||||
- [ZamAudio Suite](https://github.com/zamaudio/zam-plugins) | |||||
## Work in progress | |||||
- [CV-LFO-blender-LV2](https://github.com/BramGiesen/cv-lfo-blender-lv2) | |||||
- [fverb](https://github.com/jpcima/fverb) | |||||
- [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) | |||||
- [gunshot](https://github.com/soerenbnoergaard/gunshot) | |||||
- [midiomatic](https://github.com/SpotlightKid/midiomatic) | |||||
- [Shiro Plugins](https://github.com/ninodewit/SHIRO-Plugins/) | |||||
- [Shiru Plugins](https://github.com/linuxmao-org/shiru-plugins) | |||||
Checking the [github "DPF" tag](https://github.com/topics/dpf) can potentially bring up other DPF-made plugins. | |||||
Plugin examples are available in the `example/` folder inside this repo. | |||||
See [this wiki page](https://github.com/DISTRHO/DPF/wiki/Plugins-made-with-DPF) for a list of plugins made with DPF. | |||||
Plugin examples are also available in the `example/` folder inside this repo. |
@@ -28,6 +28,17 @@ TopLevelWidget::PrivateData::PrivateData(TopLevelWidget* const s, Window& w) | |||||
selfw(s), | selfw(s), | ||||
window(w) | window(w) | ||||
{ | { | ||||
/* if window already has a top-level-widget, make the new one match the first one in size | |||||
* this is needed because window creation and resize is a synchronous operation in some systems. | |||||
* as such, there's a chance the non-1st top-level-widgets would never get a valid size. | |||||
*/ | |||||
if (!window.pData->topLevelWidgets.empty()) | |||||
{ | |||||
TopLevelWidget* const first = window.pData->topLevelWidgets.front(); | |||||
selfw->pData->size = first->getSize(); | |||||
} | |||||
window.pData->topLevelWidgets.push_back(self); | window.pData->topLevelWidgets.push_back(self); | ||||
} | } | ||||
@@ -35,6 +35,16 @@ | |||||
#define PUGL_LOCAL_CLIENT_MSG (WM_USER + 52) | #define PUGL_LOCAL_CLIENT_MSG (WM_USER + 52) | ||||
#define PUGL_USER_TIMER_MIN 9470 | #define PUGL_USER_TIMER_MIN 9470 | ||||
#ifdef __cplusplus | |||||
# define PUGL_INIT_STRUCT \ | |||||
{} | |||||
#else | |||||
# define PUGL_INIT_STRUCT \ | |||||
{ \ | |||||
0 \ | |||||
} | |||||
#endif | |||||
typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void); | typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void); | ||||
typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*); | typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*); | ||||
typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*); | typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*); | ||||
@@ -80,7 +90,7 @@ puglRegisterWindowClass(const char* name) | |||||
module = GetModuleHandle(NULL); | module = GetModuleHandle(NULL); | ||||
} | } | ||||
WNDCLASSEX wc = {0}; | |||||
WNDCLASSEX wc = PUGL_INIT_STRUCT; | |||||
if (GetClassInfoEx(module, name, &wc)) { | if (GetClassInfoEx(module, name, &wc)) { | ||||
return true; // Already registered | return true; // Already registered | ||||
} | } | ||||
@@ -472,8 +482,8 @@ initKeyEvent(PuglKeyEvent* event, | |||||
} | } | ||||
} else if (!dead) { | } else if (!dead) { | ||||
// Translate unshifted key | // Translate unshifted key | ||||
BYTE keyboardState[256] = {0}; | |||||
wchar_t buf[5] = {0}; | |||||
BYTE keyboardState[256] = PUGL_INIT_STRUCT; | |||||
wchar_t buf[5] = PUGL_INIT_STRUCT; | |||||
event->key = puglDecodeUTF16( | event->key = puglDecodeUTF16( | ||||
buf, ToUnicode(vkey, vcode, keyboardState, buf, 4, 1 << 2)); | buf, ToUnicode(vkey, vcode, keyboardState, buf, 4, 1 << 2)); | ||||
@@ -689,7 +699,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) | |||||
pt.y = GET_Y_LPARAM(lParam); | pt.y = GET_Y_LPARAM(lParam); | ||||
if (!view->impl->mouseTracked) { | if (!view->impl->mouseTracked) { | ||||
TRACKMOUSEEVENT tme = {0}; | |||||
TRACKMOUSEEVENT tme = PUGL_INIT_STRUCT; | |||||
tme.cbSize = sizeof(tme); | tme.cbSize = sizeof(tme); | ||||
tme.dwFlags = TME_LEAVE; | tme.dwFlags = TME_LEAVE; | ||||
@@ -72,6 +72,12 @@ static const uint32_t kCVPortHasPositiveUnipolarRange = 0x40; | |||||
*/ | */ | ||||
static const uint32_t kCVPortHasScaledRange = 0x80; | static const uint32_t kCVPortHasScaledRange = 0x80; | ||||
/** | |||||
CV port is optional, allowing hosts that do no CV ports to load the plugin. | |||||
When loaded in hosts that don't support CV, the float* buffer for this port will be null. | |||||
*/ | |||||
static const uint32_t kCVPortIsOptional = 0x100; | |||||
/** @} */ | /** @} */ | ||||
/* ------------------------------------------------------------------------------------------------------------ | /* ------------------------------------------------------------------------------------------------------------ | ||||
@@ -14,6 +14,14 @@ | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
*/ | */ | ||||
/* TODO items: | |||||
* CV: write a specification | |||||
* INFO: define url, manual url, support url and string version | |||||
* PARAMETERS: test parameter triggers | |||||
* States: skip DSP/UI only states as appropriate | |||||
* UI: expose external-only UIs | |||||
*/ | |||||
#include "DistrhoPluginInternal.hpp" | #include "DistrhoPluginInternal.hpp" | ||||
#include "extra/ScopedPointer.hpp" | #include "extra/ScopedPointer.hpp" | ||||
@@ -1070,8 +1078,7 @@ public: | |||||
fPlugin.run(audioInputs, audioOutputs, frames); | fPlugin.run(audioInputs, audioOutputs, frames); | ||||
#endif | #endif | ||||
// TODO set last frame | |||||
flushParameters(nullptr, process->out_events); | |||||
flushParameters(nullptr, process->out_events, frames - 1); | |||||
fOutputEvents = nullptr; | fOutputEvents = nullptr; | ||||
} | } | ||||
@@ -1210,7 +1217,9 @@ public: | |||||
return true; | return true; | ||||
} | } | ||||
void flushParameters(const clap_input_events_t* const in, const clap_output_events_t* const out) | |||||
void flushParameters(const clap_input_events_t* const in, | |||||
const clap_output_events_t* const out, | |||||
const uint32_t frameOffset) | |||||
{ | { | ||||
if (const uint32_t len = in != nullptr ? in->size(in) : 0) | if (const uint32_t len = in != nullptr ? in->size(in) : 0) | ||||
{ | { | ||||
@@ -1231,7 +1240,7 @@ public: | |||||
if (out != nullptr) | if (out != nullptr) | ||||
{ | { | ||||
clap_event_param_value_t clapEvent = { | clap_event_param_value_t clapEvent = { | ||||
{ sizeof(clap_event_param_value_t), 0, 0, CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_IS_LIVE }, | |||||
{ sizeof(clap_event_param_value_t), frameOffset, 0, CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_IS_LIVE }, | |||||
0, nullptr, 0, 0, 0, 0, 0.0 | 0, nullptr, 0, 0, 0, 0, 0.0 | ||||
}; | }; | ||||
@@ -2336,7 +2345,7 @@ static CLAP_ABI bool clap_plugin_params_text_to_value(const clap_plugin_t* plugi | |||||
static CLAP_ABI void clap_plugin_params_flush(const clap_plugin_t* plugin, const clap_input_events_t* in, const clap_output_events_t* out) | static CLAP_ABI void clap_plugin_params_flush(const clap_plugin_t* plugin, const clap_input_events_t* in, const clap_output_events_t* out) | ||||
{ | { | ||||
PluginCLAP* const instance = static_cast<PluginCLAP*>(plugin->plugin_data); | PluginCLAP* const instance = static_cast<PluginCLAP*>(plugin->plugin_data); | ||||
return instance->flushParameters(in, out); | |||||
return instance->flushParameters(in, out, 0); | |||||
} | } | ||||
static const clap_plugin_params_t clap_plugin_params = { | static const clap_plugin_params_t clap_plugin_params = { | ||||
@@ -532,6 +532,9 @@ void lv2_generate_ttl(const char* const basename) | |||||
} | } | ||||
} | } | ||||
if ((port.hints & (kAudioPortIsCV|kCVPortIsOptional)) == (kAudioPortIsCV|kCVPortIsOptional)) | |||||
pluginString += " lv2:portProperty lv2:connectionOptional;\n"; | |||||
if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS) | if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS) | ||||
pluginString += " ] ;\n"; | pluginString += " ] ;\n"; | ||||
else | else | ||||
@@ -817,11 +820,10 @@ void lv2_generate_ttl(const char* const basename) | |||||
// MIDI CC binding | // MIDI CC binding | ||||
if (const uint8_t midiCC = plugin.getParameterMidiCC(i)) | if (const uint8_t midiCC = plugin.getParameterMidiCC(i)) | ||||
{ | { | ||||
char midiCCBuf[7]; | |||||
snprintf(midiCCBuf, sizeof(midiCCBuf), "B0%02x00", midiCC); | |||||
pluginString += " midi:binding \""; | |||||
pluginString += midiCCBuf; | |||||
pluginString += "\"^^midi:MidiEvent ;\n"; | |||||
pluginString += " midi:binding [\n"; | |||||
pluginString += " a midi:Controller ;\n"; | |||||
pluginString += " midi:controllerNumber " + String(midiCC) + " ;\n"; | |||||
pluginString += " ] ;\n"; | |||||
} | } | ||||
// unit | // unit | ||||
@@ -14,28 +14,6 @@ | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
*/ | */ | ||||
#include "DistrhoPluginInternal.hpp" | |||||
#include "../DistrhoPluginUtils.hpp" | |||||
#include "../extra/ScopedPointer.hpp" | |||||
#define DPF_VST3_MAX_BUFFER_SIZE 32768 | |||||
#define DPF_VST3_MAX_SAMPLE_RATE 384000 | |||||
#define DPF_VST3_MAX_LATENCY DPF_VST3_MAX_SAMPLE_RATE * 10 | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
# include "../extra/RingBuffer.hpp" | |||||
#endif | |||||
#include "travesty/audio_processor.h" | |||||
#include "travesty/component.h" | |||||
#include "travesty/edit_controller.h" | |||||
#include "travesty/factory.h" | |||||
#include "travesty/host.h" | |||||
#include <map> | |||||
#include <string> | |||||
#include <vector> | |||||
/* TODO items: | /* TODO items: | ||||
* == parameters | * == parameters | ||||
* - test parameter triggers | * - test parameter triggers | ||||
@@ -43,7 +21,6 @@ | |||||
* - parameter groups via unit ids | * - parameter groups via unit ids | ||||
* - test parameter changes from DSP (aka requestParameterValueChange) | * - test parameter changes from DSP (aka requestParameterValueChange) | ||||
* - implement getParameterNormalized/setParameterNormalized for MIDI CC params ? | * - implement getParameterNormalized/setParameterNormalized for MIDI CC params ? | ||||
* - fully implemented parameter stuff and verify | |||||
* - float to int safe casting | * - float to int safe casting | ||||
* - verify that latency changes works (with and without DPF_VST3_USES_SEPARATE_CONTROLLER) | * - verify that latency changes works (with and without DPF_VST3_USES_SEPARATE_CONTROLLER) | ||||
* == MIDI | * == MIDI | ||||
@@ -60,6 +37,28 @@ | |||||
* - do something with set_io_mode? | * - do something with set_io_mode? | ||||
*/ | */ | ||||
#include "DistrhoPluginInternal.hpp" | |||||
#include "../DistrhoPluginUtils.hpp" | |||||
#include "../extra/ScopedPointer.hpp" | |||||
#define DPF_VST3_MAX_BUFFER_SIZE 32768 | |||||
#define DPF_VST3_MAX_SAMPLE_RATE 384000 | |||||
#define DPF_VST3_MAX_LATENCY DPF_VST3_MAX_SAMPLE_RATE * 10 | |||||
#if DISTRHO_PLUGIN_HAS_UI | |||||
# include "../extra/RingBuffer.hpp" | |||||
#endif | |||||
#include "travesty/audio_processor.h" | |||||
#include "travesty/component.h" | |||||
#include "travesty/edit_controller.h" | |||||
#include "travesty/factory.h" | |||||
#include "travesty/host.h" | |||||
#include <map> | |||||
#include <string> | |||||
#include <vector> | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
@@ -2733,7 +2732,7 @@ private: | |||||
} | } | ||||
if (busId < busInfo.groups) | if (busId < busInfo.groups) | ||||
return portCountToSpeaker(fPlugin.getAudioPortCountWithGroupId(isInput, busId)); | |||||
return portCountToSpeaker(fPlugin.getAudioPortCountWithGroupId(isInput, portGroupId)); | |||||
if (busInfo.audio != 0 && busId == busInfo.groups) | if (busInfo.audio != 0 && busId == busInfo.groups) | ||||
return portCountToSpeaker(busInfo.audioPorts); | return portCountToSpeaker(busInfo.audioPorts); | ||||
@@ -27,7 +27,7 @@ | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT | #if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
static const sendNoteFunc sendNoteCallback = nullptr; | |||||
static constexpr const sendNoteFunc sendNoteCallback = nullptr; | |||||
#endif | #endif | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -373,13 +373,12 @@ void DistrhoPluginNekobi::run(const float**, float** outputs, uint32_t frames, c | |||||
fSynth.nugget_remains = XSYNTH_NUGGET_SIZE; | fSynth.nugget_remains = XSYNTH_NUGGET_SIZE; | ||||
/* process any ready events */ | /* process any ready events */ | ||||
while (curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame) | |||||
for (; curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame; ++curEventIndex) | |||||
{ | { | ||||
if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) | if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) | ||||
continue; | continue; | ||||
nekobee_handle_raw_event(&fSynth, midiEvents[curEventIndex].size, midiEvents[curEventIndex].data); | nekobee_handle_raw_event(&fSynth, midiEvents[curEventIndex].size, midiEvents[curEventIndex].data); | ||||
curEventIndex++; | |||||
} | } | ||||
/* calculate the sample count (burstSize) for the next nekobee_voice_render() call to be the smallest of: | /* calculate the sample count (burstSize) for the next nekobee_voice_render() call to be the smallest of: | ||||
@@ -376,7 +376,7 @@ nekobee_voice_render(nekobee_synth_t *synth, nekobee_voice_t *voice, | |||||
osc_index += sample_count; | osc_index += sample_count; | ||||
if (do_control_update) { | |||||
if (do_control_update || osc_index > MINBLEP_BUFFER_LENGTH - (XSYNTH_NUGGET_SIZE + LONGEST_DD_PULSE_LENGTH)) { | |||||
/* do those things should be done only once per control-calculation | /* do those things should be done only once per control-calculation | ||||
* interval ("nugget"), such as voice check-for-dead, pitch envelope | * interval ("nugget"), such as voice check-for-dead, pitch envelope | ||||
* calculations, volume envelope phase transition checks, etc. */ | * calculations, volume envelope phase transition checks, etc. */ | ||||
@@ -25,16 +25,6 @@ START_NAMESPACE_DGL | |||||
class ResizeHandle : public TopLevelWidget | class ResizeHandle : public TopLevelWidget | ||||
{ | { | ||||
public: | public: | ||||
/** Constructor for placing this handle on top of a window. */ | |||||
explicit ResizeHandle(Window& window) | |||||
: TopLevelWidget(window), | |||||
handleSize(16), | |||||
hasCursor(false), | |||||
isResizing(false) | |||||
{ | |||||
resetArea(); | |||||
} | |||||
/** Overloaded constructor, will fetch the window from an existing top-level widget. */ | /** Overloaded constructor, will fetch the window from an existing top-level widget. */ | ||||
explicit ResizeHandle(TopLevelWidget* const tlw) | explicit ResizeHandle(TopLevelWidget* const tlw) | ||||
: TopLevelWidget(tlw->getWindow()), | : TopLevelWidget(tlw->getWindow()), | ||||
@@ -56,31 +46,27 @@ public: | |||||
protected: | protected: | ||||
void onDisplay() override | void onDisplay() override | ||||
{ | { | ||||
// TODO implement gl3 stuff in DPF | |||||
#ifndef DGL_USE_OPENGL3 | |||||
const GraphicsContext& context(getGraphicsContext()); | const GraphicsContext& context(getGraphicsContext()); | ||||
const double lineWidth = 1.0 * getScaleFactor(); | const double lineWidth = 1.0 * getScaleFactor(); | ||||
#if defined(DGL_OPENGL) && !defined(DGL_USE_OPENGL3) | |||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
#endif | |||||
glLineWidth(lineWidth); | |||||
// draw white lines, 1px wide | // draw white lines, 1px wide | ||||
Color(1.0f, 1.0f, 1.0f).setFor(context); | |||||
l1.draw(context, lineWidth); | |||||
l2.draw(context, lineWidth); | |||||
l3.draw(context, lineWidth); | |||||
glColor3f(1.0f, 1.0f, 1.0f); | |||||
drawLine(l1); | |||||
drawLine(l2); | |||||
drawLine(l3); | |||||
// draw black lines, offset by 1px and 1px wide | // draw black lines, offset by 1px and 1px wide | ||||
Color(0.0f, 0.0f, 0.0f).setFor(context); | |||||
glColor3f(0.0f, 0.0f, 0.0f); | |||||
Line<double> l1b(l1), l2b(l2), l3b(l3); | Line<double> l1b(l1), l2b(l2), l3b(l3); | ||||
l1b.moveBy(lineWidth, lineWidth); | l1b.moveBy(lineWidth, lineWidth); | ||||
l2b.moveBy(lineWidth, lineWidth); | l2b.moveBy(lineWidth, lineWidth); | ||||
l3b.moveBy(lineWidth, lineWidth); | l3b.moveBy(lineWidth, lineWidth); | ||||
l1b.draw(context, lineWidth); | |||||
l2b.draw(context, lineWidth); | |||||
l3b.draw(context, lineWidth); | |||||
#endif | |||||
drawLine(l1b); | |||||
drawLine(l2b); | |||||
drawLine(l3b); | |||||
} | } | ||||
bool onMouse(const MouseEvent& ev) override | bool onMouse(const MouseEvent& ev) override | ||||
@@ -201,6 +187,25 @@ private: | |||||
l3.setEndPos(x + offset, y + linesize + offset); | l3.setEndPos(x + offset, y + linesize + offset); | ||||
} | } | ||||
void drawLine(const Line<double>& line) | |||||
{ | |||||
drawLine(line.getStartPos(), line.getEndPos()); | |||||
} | |||||
void drawLine(const Point<double>& posStart, const Point<double>& posEnd) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,); | |||||
glBegin(GL_LINES); | |||||
{ | |||||
glVertex2d(posStart.getX(), posStart.getY()); | |||||
glVertex2d(posEnd.getX(), posEnd.getY()); | |||||
} | |||||
glEnd(); | |||||
} | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ResizeHandle) | DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ResizeHandle) | ||||
}; | }; | ||||