diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp index aed60510..d7232a2f 100644 --- a/distrho/DistrhoPlugin.hpp +++ b/distrho/DistrhoPlugin.hpp @@ -951,6 +951,16 @@ public: */ bool isDummyInstance() const noexcept; + /** + Check if this plugin instance is a "selftest" one used for automated plugin tests.@n + To enable this mode build with `DPF_RUNTIME_TESTING` macro defined (i.e. set as compiler build flag), + and run the JACK/Standalone executable with "selftest" as its only and single argument. + + A few basic DSP and UI tests will run in self-test mode, with once instance having this function returning true.@n + You can use this chance to do a few tests of your own as well. + */ + bool isSelfTestInstance() const noexcept; + #if DISTRHO_PLUGIN_WANT_TIMEPOS /** Get the current host transport time position.@n diff --git a/distrho/src/DistrhoPlugin.cpp b/distrho/src/DistrhoPlugin.cpp index 9c4c9b65..03902fe1 100644 --- a/distrho/src/DistrhoPlugin.cpp +++ b/distrho/src/DistrhoPlugin.cpp @@ -25,6 +25,7 @@ uint32_t d_nextBufferSize = 0; double d_nextSampleRate = 0.0; const char* d_nextBundlePath = nullptr; bool d_nextPluginIsDummy = false; +bool d_nextPluginIsSelfTest = false; bool d_nextCanRequestParameterValueChanges = false; /* ------------------------------------------------------------------------------------------------------------ @@ -42,45 +43,45 @@ const PortGroupWithId PluginExporter::sFallbackPortGroup; Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount) : pData(new PrivateData()) { -#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 pData->audioPorts = new AudioPortWithBusId[DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS]; -#endif + #endif -#ifdef DPF_ABORT_ON_ERROR -# define DPF_ABORT abort(); -#else -# define DPF_ABORT -#endif + #if defined(DPF_ABORT_ON_ERROR) || defined(DPF_RUNTIME_TESTING) + #define DPF_ABORT abort(); + #else + #define DPF_ABORT + #endif if (parameterCount > 0) { pData->parameterCount = parameterCount; - pData->parameters = new Parameter[parameterCount]; + pData->parameters = new Parameter[parameterCount]; } if (programCount > 0) { -#if DISTRHO_PLUGIN_WANT_PROGRAMS + #if DISTRHO_PLUGIN_WANT_PROGRAMS pData->programCount = programCount; pData->programNames = new String[programCount]; -#else + #else d_stderr2("DPF warning: Plugins with programs must define `DISTRHO_PLUGIN_WANT_PROGRAMS` to 1"); DPF_ABORT -#endif + #endif } if (stateCount > 0) { -#if DISTRHO_PLUGIN_WANT_STATE + #if DISTRHO_PLUGIN_WANT_STATE pData->stateCount = stateCount; - pData->states = new State[stateCount]; -#else + pData->states = new State[stateCount]; + #else d_stderr2("DPF warning: Plugins with state must define `DISTRHO_PLUGIN_WANT_STATE` to 1"); DPF_ABORT -#endif + #endif } -#undef DPF_ABORT + #undef DPF_ABORT } Plugin::~Plugin() @@ -111,6 +112,11 @@ bool Plugin::isDummyInstance() const noexcept return pData->isDummy; } +bool Plugin::isSelfTestInstance() const noexcept +{ + return pData->isSelfTest; +} + #if DISTRHO_PLUGIN_WANT_TIMEPOS const TimePosition& Plugin::getTimePosition() const noexcept { diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp index 94868aee..8ea789d9 100644 --- a/distrho/src/DistrhoPluginInternal.hpp +++ b/distrho/src/DistrhoPluginInternal.hpp @@ -39,6 +39,7 @@ extern uint32_t d_nextBufferSize; extern double d_nextSampleRate; extern const char* d_nextBundlePath; extern bool d_nextPluginIsDummy; +extern bool d_nextPluginIsSelfTest; extern bool d_nextCanRequestParameterValueChanges; // ----------------------------------------------------------------------- @@ -92,6 +93,7 @@ static void fillInPredefinedPortGroupData(const uint32_t groupId, PortGroup& por struct Plugin::PrivateData { const bool canRequestParameterValueChanges; const bool isDummy; + const bool isSelfTest; bool isProcessing; #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 @@ -136,6 +138,7 @@ struct Plugin::PrivateData { PrivateData() noexcept : canRequestParameterValueChanges(d_nextCanRequestParameterValueChanges), isDummy(d_nextPluginIsDummy), + isSelfTest(d_nextPluginIsSelfTest), isProcessing(false), #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 audioPorts(nullptr), diff --git a/distrho/src/DistrhoPluginJACK.cpp b/distrho/src/DistrhoPluginJACK.cpp index d3d1347e..2373fa75 100644 --- a/distrho/src/DistrhoPluginJACK.cpp +++ b/distrho/src/DistrhoPluginJACK.cpp @@ -795,11 +795,11 @@ protected: while (! shouldThreadExit()) { -#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT plugin.run(inputs, outputs, 128, nullptr, 0); -#else + #else plugin.run(inputs, outputs, 128); -#endif + #endif d_msleep(100); } @@ -824,7 +824,17 @@ bool runSelfTests() // simple processing { + d_nextPluginIsSelfTest = true; PluginExporter plugin(nullptr, nullptr, nullptr, nullptr); + d_nextPluginIsSelfTest = false; + + #if DISTRHO_PLUGIN_HAS_UI + UIExporter ui(nullptr, 0, plugin.getSampleRate(), + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + plugin.getInstancePointer(), 0.0); + ui.showAndFocus(); + #endif + plugin.activate(); plugin.deactivate(); plugin.setBufferSize(128); @@ -839,15 +849,21 @@ bool runSelfTests() for (int i=0; i(std::atoll(argv[2])); -#endif + #endif const PluginJack p(client, winId); -#if defined(DISTRHO_OS_WINDOWS) && DISTRHO_PLUGIN_HAS_UI + #if defined(DISTRHO_OS_WINDOWS) && DISTRHO_PLUGIN_HAS_UI /* the code below is based on * https://www.tillett.info/2013/05/13/how-to-create-a-windows-program-that-works-as-both-as-a-gui-and-console-application/ */ @@ -1091,14 +1112,9 @@ int main(int argc, char* argv[]) ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release SendInput(1, &ip, sizeof(INPUT)); } -#endif + #endif return 0; - -#ifndef DPF_RUNTIME_TESTING - // unused - (void)argc; (void)argv; -#endif } // -----------------------------------------------------------------------