diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 93e1f72c..06763ccf 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -34,14 +34,13 @@ jobs: CXXFLAGS: -Werror run: | xvfb-run make -C tests run -# FIXME enable again after finishing web-ui stuff -# - name: As C++98 mode -# env: -# CFLAGS: -Werror -# CXXFLAGS: -Werror -std=gnu++98 -# run: | -# make clean >/dev/null -# make -j $(nproc) + - name: As C++98 mode + env: + CFLAGS: -Werror + CXXFLAGS: -Werror -std=gnu++98 + run: | + make clean >/dev/null + make -j $(nproc) - name: No namespace env: CFLAGS: -Werror diff --git a/distrho/DistrhoUtils.hpp b/distrho/DistrhoUtils.hpp index bdd367a2..6b9b9af8 100644 --- a/distrho/DistrhoUtils.hpp +++ b/distrho/DistrhoUtils.hpp @@ -19,6 +19,10 @@ #include "src/DistrhoDefines.h" +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif + #include #include #include diff --git a/distrho/extra/ChildProcess.hpp b/distrho/extra/ChildProcess.hpp index 5638edb6..7f599872 100644 --- a/distrho/extra/ChildProcess.hpp +++ b/distrho/extra/ChildProcess.hpp @@ -1,5 +1,18 @@ -// SPDX-FileCopyrightText: 2023-2024 MOD Audio UG -// SPDX-License-Identifier: AGPL-3.0-or-later +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2024 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #pragma once @@ -24,13 +37,18 @@ START_NAMESPACE_DISTRHO class ChildProcess { #ifdef _WIN32 - PROCESS_INFORMATION pinfo = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0 }; + PROCESS_INFORMATION pinfo; #else - pid_t pid = -1; + pid_t pid; #endif public: ChildProcess() + #ifdef _WIN32 + : pinfo(CPP_AGGREGATE_INIT(PROCESS_INFORMATION){ INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0 }) + #else + : pid(-1) + #endif { } @@ -120,7 +138,7 @@ public: return; const PROCESS_INFORMATION opinfo = pinfo; - pinfo = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0 }; + pinfo = (PROCESS_INFORMATION){ INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0 }; for (DWORD exitCode;;) { @@ -226,7 +244,7 @@ public: WaitForSingleObject(pinfo.hProcess, 0) != WAIT_TIMEOUT) { const PROCESS_INFORMATION opinfo = pinfo; - pinfo = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0 }; + pinfo = (PROCESS_INFORMATION){ INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0 }; CloseHandle(opinfo.hThread); CloseHandle(opinfo.hProcess); return false; diff --git a/distrho/extra/ExternalWindow.hpp b/distrho/extra/ExternalWindow.hpp index 1f1c360b..65ca1cfe 100644 --- a/distrho/extra/ExternalWindow.hpp +++ b/distrho/extra/ExternalWindow.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2021 Filipe Coelho + * Copyright (C) 2012-2024 Filipe Coelho * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this @@ -78,13 +78,13 @@ public: Constructor. */ explicit ExternalWindow() - : pData() {} + : pData() {} /** Constructor for DPF internal use. */ explicit ExternalWindow(const PrivateData& data) - : pData(data) {} + : pData(data) {} /** Destructor. diff --git a/distrho/extra/RingBuffer.hpp b/distrho/extra/RingBuffer.hpp index be744dd1..f23104d6 100644 --- a/distrho/extra/RingBuffer.hpp +++ b/distrho/extra/RingBuffer.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2021 Filipe Coelho + * Copyright (C) 2012-2024 Filipe Coelho * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this @@ -119,14 +119,6 @@ struct HugeStackBuffer { uint8_t buf[size]; }; -#ifdef DISTRHO_PROPER_CPP11_SUPPORT -# define HeapBuffer_INIT {0, 0, 0, 0, false, nullptr} -# define StackBuffer_INIT {0, 0, 0, false, {0}} -#else -# define HeapBuffer_INIT -# define StackBuffer_INIT -#endif - // ----------------------------------------------------------------------- // RingBufferControl templated class @@ -799,12 +791,7 @@ class HeapRingBuffer : public RingBufferControl public: /** Constructor. */ HeapRingBuffer() noexcept - : heapBuffer(HeapBuffer_INIT) - { -#ifndef DISTRHO_PROPER_CPP11_SUPPORT - std::memset(&heapBuffer, 0, sizeof(heapBuffer)); -#endif - } + : heapBuffer(CPP_AGGREGATE_INIT(HeapBuffer){0, 0, 0, 0, false, nullptr}) {} /** Destructor. */ ~HeapRingBuffer() noexcept override @@ -874,11 +861,8 @@ class SmallStackRingBuffer : public RingBufferControl public: /** Constructor. */ SmallStackRingBuffer() noexcept - : stackBuffer(StackBuffer_INIT) + : stackBuffer(CPP_AGGREGATE_INIT(SmallStackBuffer){0, 0, 0, false, {0}}) { -#ifndef DISTRHO_PROPER_CPP11_SUPPORT - std::memset(&stackBuffer, 0, sizeof(stackBuffer)); -#endif setRingBuffer(&stackBuffer, true); } diff --git a/distrho/extra/WebViewImpl.cpp b/distrho/extra/WebViewImpl.cpp index eb725369..cea63578 100644 --- a/distrho/extra/WebViewImpl.cpp +++ b/distrho/extra/WebViewImpl.cpp @@ -73,13 +73,15 @@ # include "String.hpp" # include # include -# include # include # include # include # include # include # include +# ifdef DISTRHO_PROPER_CPP11_SUPPORT +# include +# endif # ifdef __linux__ # include # include @@ -351,21 +353,49 @@ struct WebViewData { NSURLRequest* urlreq; WEB_VIEW_DELEGATE_CLASS_NAME* delegate; #elif WEB_VIEW_USING_X11_IPC - int shmfd = 0; - char shmname[128] = {}; - WebViewRingBuffer* shmptr = nullptr; - WebViewMessageCallback callback = nullptr; - void* callbackPtr = nullptr; + int shmfd; + char shmname[128]; + WebViewRingBuffer* shmptr; + WebViewMessageCallback callback; + void* callbackPtr; ChildProcess p; RingBufferControl rbctrl, rbctrl2; - ::Display* display = nullptr; - ::Window childWindow = 0; - ::Window ourWindow = 0; + ::Display* display; + ::Window childWindow; + ::Window ourWindow; #endif - WebViewData() {} + WebViewData(); DISTRHO_DECLARE_NON_COPYABLE(WebViewData); }; +WebViewData::WebViewData() + #if WEB_VIEW_USING_CHOC + : webview(nullptr), + url() + #elif WEB_VIEW_USING_MACOS_WEBKIT + : view(nullptr), + webview(nullptr), + urlreq(nullptr), + delegate(nullptr) + #elif WEB_VIEW_USING_X11_IPC + : shmfd(0), + shmname(), + shmptr(nullptr), + callback(nullptr), + callbackPtr(nullptr), + p(), + rbctrl(), + rbctrl2(), + display(nullptr), + childWindow(0), + ourWindow(0) + #endif +{ + #if WEB_VIEW_USING_X11_IPC + std::memset(shmname, 0, sizeof(shmname)); + #endif +} + // ----------------------------------------------------------------------------------------------------------- WebViewHandle webViewCreate(const char* const url, @@ -833,10 +863,13 @@ void webViewResize(const WebViewHandle handle, const uint width, const uint heig // ----------------------------------------------------------------------------------------------------------- static bool running = false; -static std::function evaluateFn; -static std::function reloadFn; -static std::function terminateFn; -static std::function wakeFn; +static struct WebFramework { + virtual ~WebFramework() {} + virtual void evaluate(const char* js) = 0; + virtual void reload() = 0; + virtual void terminate() = 0; + virtual void wake(WebViewRingBuffer* rb) = 0; +}* webFramework = nullptr; // ----------------------------------------------------------------------------------------------------------- @@ -887,22 +920,19 @@ class QWebEngineView { uint8_t _[56 * 2]; }; class QWindow; struct QPoint { - int x, y; + int _x, _y; + QPoint(int x, int y) : _x(x), _y(y) {} }; struct QSize { - int w, h; + int _w, _h; + QSize(int w, int h) : _w(w), _h(h) {} }; // ----------------------------------------------------------------------------------------------------------- #define JOIN(A, B) A ## B -#define AUTOSYM(S) \ - using JOIN(gtk3_, S) = decltype(&S); \ - JOIN(gtk3_, S) S = reinterpret_cast(dlsym(nullptr, #S)); \ - DISTRHO_SAFE_ASSERT_RETURN(S != nullptr, false); - #define CSYM(S, NAME) \ S NAME = reinterpret_cast(dlsym(nullptr, #NAME)); \ DISTRHO_SAFE_ASSERT_RETURN(NAME != nullptr, false); @@ -943,14 +973,14 @@ static void web_wake_idle(void* const ptr) if (rbctrl.readCustomData(buffer, len)) { d_debug("client kWebViewMessageEvaluateJS -> '%s'", static_cast(buffer)); - evaluateFn(static_cast(buffer)); + webFramework->evaluate(static_cast(buffer)); continue; } } break; case kWebViewMessageReload: d_debug("client kWebViewMessageReload"); - reloadFn(); + webFramework->reload(); continue; } @@ -968,9 +998,9 @@ static int gtk3_js_cb(WebKitUserContentManager*, WebKitJavascriptResult* const r { WebViewRingBuffer* const shmptr = static_cast(arg); - using g_free_t = void (*)(void*); - using jsc_value_to_string_t = char* (*)(JSCValue*); - using webkit_javascript_result_get_js_value_t = JSCValue* (*)(WebKitJavascriptResult*); + typedef void (*g_free_t)(void*); + typedef char* (*jsc_value_to_string_t)(JSCValue*); + typedef JSCValue* (*webkit_javascript_result_get_js_value_t)(WebKitJavascriptResult*); CSYM(g_free_t, g_free) CSYM(jsc_value_to_string_t, jsc_value_to_string) @@ -1015,32 +1045,32 @@ static bool gtk3(Display* const display, return false; } - using g_main_context_invoke_t = void (*)(void*, void*, void*); - using g_signal_connect_data_t = ulong (*)(void*, const char*, void*, void*, void*, int); - using gdk_set_allowed_backends_t = void (*)(const char*); - using gtk_container_add_t = void (*)(GtkContainer*, GtkWidget*); - using gtk_init_check_t = gboolean (*)(int*, char***); - using gtk_main_t = void (*)(); - using gtk_main_quit_t = void (*)(); - using gtk_plug_get_id_t = Window (*)(GtkPlug*); - using gtk_plug_new_t = GtkWidget* (*)(Window); - using gtk_widget_show_all_t = void (*)(GtkWidget*); - using gtk_window_move_t = void (*)(GtkWindow*, int, int); - using gtk_window_set_default_size_t = void (*)(GtkWindow*, int, int); - using webkit_settings_new_t = WebKitSettings* (*)(); - using webkit_settings_set_enable_developer_extras_t = void (*)(WebKitSettings*, gboolean); - using webkit_settings_set_enable_write_console_messages_to_stdout_t = void (*)(WebKitSettings*, gboolean); - using webkit_settings_set_hardware_acceleration_policy_t = void (*)(WebKitSettings*, int); - using webkit_settings_set_javascript_can_access_clipboard_t = void (*)(WebKitSettings*, gboolean); - using webkit_user_content_manager_add_script_t = void (*)(WebKitUserContentManager*, WebKitUserScript*); - using webkit_user_content_manager_register_script_message_handler_t = gboolean (*)(WebKitUserContentManager*, const char*); - using webkit_user_script_new_t = WebKitUserScript* (*)(const char*, int, int, const char* const*, const char* const*); - using webkit_web_view_evaluate_javascript_t = void* (*)(WebKitWebView*, const char*, ssize_t, const char*, const char*, void*, void*, void*); - using webkit_web_view_get_user_content_manager_t = WebKitUserContentManager* (*)(WebKitWebView*); - using webkit_web_view_load_uri_t = void (*)(WebKitWebView*, const char*); - using webkit_web_view_new_with_settings_t = GtkWidget* (*)(WebKitSettings*); - using webkit_web_view_run_javascript_t = void* (*)(WebKitWebView*, const char*, void*, void*, void*); - using webkit_web_view_set_background_color_t = void (*)(WebKitWebView*, const double*); + typedef void (*g_main_context_invoke_t)(void*, void*, void*); + typedef ulong (*g_signal_connect_data_t)(void*, const char*, void*, void*, void*, int); + typedef void (*gdk_set_allowed_backends_t)(const char*); + typedef void (*gtk_container_add_t)(GtkContainer*, GtkWidget*); + typedef gboolean (*gtk_init_check_t)(int*, char***); + typedef void (*gtk_main_t)(); + typedef void (*gtk_main_quit_t)(); + typedef Window (*gtk_plug_get_id_t)(GtkPlug*); + typedef GtkWidget* (*gtk_plug_new_t)(Window); + typedef void (*gtk_widget_show_all_t)(GtkWidget*); + typedef void (*gtk_window_move_t)(GtkWindow*, int, int); + typedef void (*gtk_window_set_default_size_t)(GtkWindow*, int, int); + typedef WebKitSettings* (*webkit_settings_new_t)(); + typedef void (*webkit_settings_set_enable_developer_extras_t)(WebKitSettings*, gboolean); + typedef void (*webkit_settings_set_enable_write_console_messages_to_stdout_t)(WebKitSettings*, gboolean); + typedef void (*webkit_settings_set_hardware_acceleration_policy_t)(WebKitSettings*, int); + typedef void (*webkit_settings_set_javascript_can_access_clipboard_t)(WebKitSettings*, gboolean); + typedef void (*webkit_user_content_manager_add_script_t)(WebKitUserContentManager*, WebKitUserScript*); + typedef gboolean (*webkit_user_content_manager_register_script_message_handler_t)(WebKitUserContentManager*, const char*); + typedef WebKitUserScript* (*webkit_user_script_new_t)(const char*, int, int, const char* const*, const char* const*); + typedef void* (*webkit_web_view_evaluate_javascript_t)(WebKitWebView*, const char*, ssize_t, const char*, const char*, void*, void*, void*); + typedef WebKitUserContentManager* (*webkit_web_view_get_user_content_manager_t)(WebKitWebView*); + typedef void (*webkit_web_view_load_uri_t)(WebKitWebView*, const char*); + typedef GtkWidget* (*webkit_web_view_new_with_settings_t)(WebKitSettings*); + typedef void* (*webkit_web_view_run_javascript_t)(WebKitWebView*, const char*, void*, void*, void*); + typedef void (*webkit_web_view_set_background_color_t)(WebKitWebView*, const double*); CSYM(g_main_context_invoke_t, g_main_context_invoke) CSYM(g_signal_connect_data_t, g_signal_connect_data) @@ -1155,31 +1185,74 @@ static bool gtk3(Display* const display, XMapWindow(display, wid); XFlush(display); - evaluateFn = [=](const char* const js){ - if (webkit_web_view_evaluate_javascript != nullptr) - webkit_web_view_evaluate_javascript(WEBKIT_WEB_VIEW(webview), js, -1, - nullptr, nullptr, nullptr, nullptr, nullptr); - else - webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(webview), js, nullptr, nullptr, nullptr); - }; + struct Gtk3WebFramework : WebFramework { + const char* const _url; + WebViewRingBuffer* const _shmptr; + GtkWidget* const _webview; + const webkit_web_view_evaluate_javascript_t _webkit_web_view_evaluate_javascript; + const webkit_web_view_run_javascript_t _webkit_web_view_run_javascript; + const webkit_web_view_load_uri_t _webkit_web_view_load_uri; + const gtk_main_quit_t _gtk_main_quit; + const g_main_context_invoke_t _g_main_context_invoke; + + Gtk3WebFramework(const char* const url, + WebViewRingBuffer* const shmptr, + GtkWidget* const webview, + const webkit_web_view_evaluate_javascript_t webkit_web_view_evaluate_javascript, + const webkit_web_view_run_javascript_t webkit_web_view_run_javascript, + const webkit_web_view_load_uri_t webkit_web_view_load_uri, + const gtk_main_quit_t gtk_main_quit, + const g_main_context_invoke_t g_main_context_invoke) + : _url(url), + _shmptr(shmptr), + _webview(webview), + _webkit_web_view_evaluate_javascript(webkit_web_view_evaluate_javascript), + _webkit_web_view_run_javascript(webkit_web_view_run_javascript), + _webkit_web_view_load_uri(webkit_web_view_load_uri), + _gtk_main_quit(gtk_main_quit), + _g_main_context_invoke(g_main_context_invoke) {} + + void evaluate(const char* const js) override + { + if (_webkit_web_view_evaluate_javascript != nullptr) + _webkit_web_view_evaluate_javascript(WEBKIT_WEB_VIEW(_webview), js, -1, + nullptr, nullptr, nullptr, nullptr, nullptr); + else + _webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(_webview), js, nullptr, nullptr, nullptr); + } - reloadFn = [=](){ - webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview), url); - }; + void reload() override + { + _webkit_web_view_load_uri(WEBKIT_WEB_VIEW(_webview), _url); + } - terminateFn = [=](){ - if (running) + void terminate() override { - running = false; - webview_wake(&shmptr->client.sem); - gtk_main_quit(); + if (running) + { + running = false; + webview_wake(&_shmptr->client.sem); + _gtk_main_quit(); + } } - }; - wakeFn = [=](WebViewRingBuffer* const rb){ - g_main_context_invoke(NULL, G_CALLBACK(web_wake_idle), rb); + void wake(WebViewRingBuffer* const rb) override + { + _g_main_context_invoke(NULL, G_CALLBACK(web_wake_idle), rb); + } }; + Gtk3WebFramework webFrameworkObj(url, + shmptr, + webview, + webkit_web_view_evaluate_javascript, + webkit_web_view_run_javascript, + webkit_web_view_load_uri, + gtk_main_quit, + g_main_context_invoke); + + webFramework = &webFrameworkObj; + // notify server we started ok webview_wake(&shmptr->server.sem); @@ -1203,14 +1276,14 @@ class QObject public: QObject(QObject* parent = nullptr) { - static void (*m)(QObject*, QObject*) = reinterpret_cast(dlsym( + static void (*m)(QObject*, QObject*) = reinterpret_cast(dlsym( nullptr, "_ZN7QObjectC1EPS_")); m(this, parent); } virtual const QMetaObject* metaObject() const { - static const QMetaObject* (*m)(const QObject*) = reinterpret_cast(dlsym( + static const QMetaObject* (*m)(const QObject*) = reinterpret_cast(dlsym( nullptr, "_ZNK7QObject10metaObjectEv")); return m(this); } @@ -1221,49 +1294,49 @@ public: virtual bool event(QEvent* e) { - static bool (*m)(QObject*, QEvent*) = reinterpret_cast(dlsym( + static bool (*m)(QObject*, QEvent*) = reinterpret_cast(dlsym( nullptr, "_ZN7QObject5eventEP6QEvent")); return m(this, e); } virtual bool eventFilter(QObject* watched, QEvent* event) { - static bool (*m)(QObject*, QObject*, QEvent*) = reinterpret_cast(dlsym( + static bool (*m)(QObject*, QObject*, QEvent*) = reinterpret_cast(dlsym( nullptr, "_ZN7QObject11eventFilterEPS_P6QEvent")); return m(this, watched, event); } virtual void timerEvent(QTimerEvent* event) { - static void (*m)(QObject*, QTimerEvent*) = reinterpret_cast(dlsym( + static void (*m)(QObject*, QTimerEvent*) = reinterpret_cast(dlsym( nullptr, "_ZN7QObject10timerEventEP11QTimerEvent")); m(this, event); } virtual void childEvent(QChildEvent* event) { - static void (*m)(QObject*, QChildEvent*) = reinterpret_cast(dlsym( + static void (*m)(QObject*, QChildEvent*) = reinterpret_cast(dlsym( nullptr, "_ZN7QObject10childEventEP11QChildEvent")); m(this, event); } virtual void customEvent(QEvent* event) { - static void (*m)(QObject*, QEvent*) = reinterpret_cast(dlsym( + static void (*m)(QObject*, QEvent*) = reinterpret_cast(dlsym( nullptr, "_ZN7QObject11customEventEP6QEvent")); m(this, event); } virtual void connectNotify(const QMetaMethod& signal) { - static void (*m)(QObject*, const QMetaMethod&) = reinterpret_cast(dlsym( + static void (*m)(QObject*, const QMetaMethod&) = reinterpret_cast(dlsym( nullptr, "_ZN7QObject13connectNotifyERK11QMetaMethod")); m(this, signal); } virtual void disconnectNotify(const QMetaMethod& signal) { - static void (*m)(QObject*, const QMetaMethod&) = reinterpret_cast(dlsym( + static void (*m)(QObject*, const QMetaMethod&) = reinterpret_cast(dlsym( nullptr, "_ZN7QObject16disconnectNotifyERK11QMetaMethod")); m(this, signal); } @@ -1277,7 +1350,7 @@ class QWebChannelAbstractTransport : public QObject protected: const QMetaObject* metaObject() const override { - static const QMetaObject* (*m)(const QObject*) = reinterpret_cast(dlsym( + static const QMetaObject* (*m)(const QObject*) = reinterpret_cast(dlsym( nullptr, "_ZNK28QWebChannelAbstractTransport10metaObjectEv")); return m(this); } @@ -1290,7 +1363,7 @@ public: QWebChannelAbstractTransport(QObject* parent = nullptr) : QObject(parent) { - static void (*m)(QObject*, QObject*) = reinterpret_cast(dlsym( + static void (*m)(QObject*, QObject*) = reinterpret_cast(dlsym( nullptr, "_ZN28QWebChannelAbstractTransportC1EP7QObject")); m(this, parent); } @@ -1314,12 +1387,12 @@ public: isQt5(false) { void (*QString__init)(QString*, const QChar*, int) = - reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QCharx")); + reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QCharx")); if (QString__init == nullptr) { isQt5 = true; - QString__init = reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QChari")); + QString__init = reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QChari")); } const ushort key_qchar[] = { 'm', 0 }; @@ -1334,22 +1407,22 @@ public: void sendMessage(const QJsonObject& obj) override { static void (*QByteArray_clear)(QByteArray*) = - reinterpret_cast(dlsym(nullptr, "_ZN10QByteArray5clearEv")); + reinterpret_cast(dlsym(nullptr, "_ZN10QByteArray5clearEv")); static QJsonValue (*QJsonObject_value)(const QJsonObject*, const QString&) = - reinterpret_cast(dlsym(nullptr, "_ZNK11QJsonObject5valueERK7QString")); + reinterpret_cast(dlsym(nullptr, "_ZNK11QJsonObject5valueERK7QString")); static void (*QJsonValue__deinit)(const QJsonValue*) = - reinterpret_cast(dlsym(nullptr, "_ZN10QJsonValueD1Ev")); + reinterpret_cast(dlsym(nullptr, "_ZN10QJsonValueD1Ev")); static QString (*QJsonValue_toString)(const QJsonValue*) = - reinterpret_cast(dlsym(nullptr, "_ZNK10QJsonValue8toStringEv")); + reinterpret_cast(dlsym(nullptr, "_ZNK10QJsonValue8toStringEv")); static QString& (*QString_setRawData)(QString*, const QChar*, int) = - reinterpret_cast(dlsym(nullptr, "_ZN7QString10setRawDataEPK5QCharx")) ?: - reinterpret_cast(dlsym(nullptr, "_ZN7QString10setRawDataEPK5QChari")); + reinterpret_cast(dlsym(nullptr, "_ZN7QString10setRawDataEPK5QCharx")) ?: + reinterpret_cast(dlsym(nullptr, "_ZN7QString10setRawDataEPK5QChari")); static QByteArray (*QString_toUtf8)(const QString*) = - reinterpret_cast(dlsym(nullptr, "_ZNK7QString6toUtf8Ev")) ?: - reinterpret_cast(dlsym(nullptr, "_ZN7QString13toUtf8_helperERKS_")); + reinterpret_cast(dlsym(nullptr, "_ZNK7QString6toUtf8Ev")) ?: + reinterpret_cast(dlsym(nullptr, "_ZN7QString13toUtf8_helperERKS_")); const QJsonValue json = QJsonObject_value(&obj, qstrkey); QString qstrvalue = QJsonValue_toString(&json); @@ -1415,73 +1488,89 @@ static bool qtwebengine(const int qtVersion, return false; } + // Qt >= 6 uses int void (*QByteArray__init)(QByteArray*, const char*, int) = - reinterpret_cast(dlsym(nullptr, "_ZN10QByteArrayC1EPKcx")) ?: - reinterpret_cast(dlsym(nullptr, "_ZN10QByteArrayC1EPKci")); + reinterpret_cast(dlsym(nullptr, "_ZN10QByteArrayC1EPKcx")) ?: + reinterpret_cast(dlsym(nullptr, "_ZN10QByteArrayC1EPKci")); DISTRHO_SAFE_ASSERT_RETURN(QByteArray__init != nullptr, false); - void (*QString__init)(QString*, const QChar*, int) = - reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QCharx")) ?: - reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QChari")); + typedef void (*QString__init_t)(QString*, const QChar*, int); + const QString__init_t QString__init = + reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QCharx")) ?: + reinterpret_cast(dlsym(nullptr, "_ZN7QStringC2EPK5QChari")); DISTRHO_SAFE_ASSERT_RETURN(QString__init != nullptr, false); - void (*QWebEnginePage_runJavaScript)(QWebEnginePage*, const QString&, uint, const std::function&) = - reinterpret_cast(dlsym( - nullptr, "_ZN14QWebEnginePage13runJavaScriptERK7QStringjRKSt8functionIFvRK8QVariantEE")); - void (*QWebEnginePage_runJavaScript_compat)(QWebEnginePage*, const QString&) = - reinterpret_cast(dlsym( - nullptr, "_ZN14QWebEnginePage13runJavaScriptERK7QString")); - DISTRHO_SAFE_ASSERT_RETURN(QWebEnginePage_runJavaScript != nullptr || - QWebEnginePage_runJavaScript_compat != nullptr, false); - void (*QWebEnginePage_setWebChannel)(QWebEnginePage*, QWebChannel*, uint) = - reinterpret_cast(dlsym( + reinterpret_cast(dlsym( nullptr, "_ZN14QWebEnginePage13setWebChannelEP11QWebChannelj")) ?: - reinterpret_cast(dlsym( + reinterpret_cast(dlsym( nullptr, "_ZN14QWebEnginePage13setWebChannelEP11QWebChannel")); DISTRHO_SAFE_ASSERT_RETURN(QWebEnginePage_setWebChannel != nullptr, false); - using QApplication__init_t = void (*)(QApplication*, int&, char**, int); - using QApplication_exec_t = void (*)(); - using QApplication_postEvent_t = void (*)(QObject*, QEvent*, int); - using QApplication_quit_t = void (*)(); - using QApplication_setAttribute_t = void (*)(int, bool); - using QEvent__init_t = void (*)(QEvent*, int /* QEvent::Type */); - using QJsonObject_value_t = QJsonValue (*)(const QJsonObject*, const QString &); - using QJsonValue_toString_t = QString (*)(const QJsonValue*); - using QUrl__init_t = void (*)(QUrl*, const QString&, int /* QUrl::ParsingMode */); - using QWebChannel__init_t = void (*)(QWebChannel*, QObject*); - using QWebChannel_registerObject_t = void (*)(QWebChannel*, const QString&, QObject*); - using QWebEnginePage__init_t = void (*)(QWebEnginePage*, QWebEngineProfile*, QObject*); - using QWebEnginePage_setBackgroundColor_t = void (*)(QWebEnginePage*, const QColor&); - using QWebEnginePage_webChannel_t = QWebChannel* (*)(QWebEnginePage*); - using QWebEngineProfile_defaultProfile_t = QWebEngineProfile* (*)(); - using QWebEngineProfile_installUrlSchemeHandler_t = void (*)(QWebEngineProfile*, const QByteArray&, QWebEngineUrlSchemeHandler*); - using QWebEngineProfile_settings_t = QWebEngineSettings* (*)(QWebEngineProfile*); - using QWebEngineProfile_scripts_t = QWebEngineScriptCollection* (*)(QWebEngineProfile*); - using QWebEngineScript__init_t = void (*)(QWebEngineScript*); - using QWebEngineScript_setInjectionPoint_t = void (*)(QWebEngineScript*, int /* QWebEngineScript::InjectionPoint */); - using QWebEngineScript_setRunsOnSubFrames_t = void (*)(QWebEngineScript*, bool); - using QWebEngineScript_setSourceCode_t = void (*)(QWebEngineScript*, const QString &); - using QWebEngineScript_setWorldId_t = void (*)(QWebEngineScript*, uint32_t); - using QWebEngineScriptCollection_insert_t = void (*)(QWebEngineScriptCollection*, QWebEngineScript&); - using QWebEngineSettings_setAttribute_t = void (*)(QWebEngineSettings*, int /* QWebEngineSettings::WebAttribute */, bool); - // using QWebEngineUrlRequestJob_reply_t = void (QWebEngineUrlRequestJob*, const QByteArray&, QIODevice*); - using QWebEngineUrlScheme__init_t = void (*)(QWebEngineUrlScheme*, const QByteArray&); - using QWebEngineUrlScheme_registerScheme_t = void (*)(QWebEngineUrlScheme&); - using QWebEngineUrlScheme_setFlags_t = void (*)(QWebEngineUrlScheme*, int /* QWebEngineUrlScheme::Flags */); - using QWebEngineUrlScheme_setSyntax_t = void (*)(QWebEngineUrlScheme*, int /* QWebEngineUrlScheme::Syntax */); - using QWebEngineUrlSchemeHandler__init_t = void (*)(QObject*, QObject*); - using QWebEngineView__init_t = void (*)(QWebEngineView*, QObject*); - using QWebEngineView_move_t = void (*)(QWebEngineView*, const QPoint&); - using QWebEngineView_resize_t = void (*)(QWebEngineView*, const QSize&); - using QWebEngineView_setPage_t = void (*)(QWebEngineView*, QWebEnginePage*); - using QWebEngineView_setUrl_t = void (*)(QWebEngineView*, const QUrl&); - using QWebEngineView_show_t = void (*)(QWebEngineView*); - using QWebEngineView_winId_t = ulonglong (*)(QWebEngineView*); - using QWebEngineView_windowHandle_t = QWindow* (*)(QWebEngineView*); - using QWindow_fromWinId_t = QWindow* (*)(ulonglong); - using QWindow_setParent_t = void (*)(QWindow*, void*); + // Qt >= 6 has new function signature with lambdas +#ifdef DISTRHO_PROPER_CPP11_SUPPORT + typedef void (*QWebEnginePage_runJavaScript_t)(QWebEnginePage*, const QString&, uint, const std::function&); +#else + typedef void (*QWebEnginePage_runJavaScript_t)(QWebEnginePage*, const QString&, uint, const uintptr_t&); +#endif + typedef void (*QWebEnginePage_runJavaScript_compat_t)(QWebEnginePage*, const QString&); + + QWebEnginePage_runJavaScript_t QWebEnginePage_runJavaScript; + QWebEnginePage_runJavaScript_compat_t QWebEnginePage_runJavaScript_compat; + + if (qtVersion == 5) { + QWebEnginePage_runJavaScript = nullptr; + QWebEnginePage_runJavaScript_compat = reinterpret_cast(dlsym( + nullptr, "_ZN14QWebEnginePage13runJavaScriptERK7QString")); + DISTRHO_SAFE_ASSERT_RETURN(QWebEnginePage_runJavaScript_compat != nullptr, false); + } else { + QWebEnginePage_runJavaScript_compat = nullptr; + QWebEnginePage_runJavaScript = reinterpret_cast(dlsym( + nullptr, "_ZN14QWebEnginePage13runJavaScriptERK7QStringjRKSt8functionIFvRK8QVariantEE")); + DISTRHO_SAFE_ASSERT_RETURN(QWebEnginePage_runJavaScript != nullptr, false); + } + + typedef void (*QApplication__init_t)(QApplication*, int&, char**, int); + typedef void (*QApplication_exec_t)(); + typedef void (*QApplication_postEvent_t)(QObject*, QEvent*, int); + typedef void (*QApplication_quit_t)(); + typedef void (*QApplication_setAttribute_t)(int, bool); + typedef void (*QEvent__init_t)(QEvent*, int /* QEvent::Type */); + typedef QJsonValue (*QJsonObject_value_t)(const QJsonObject*, const QString &); + typedef QString (*QJsonValue_toString_t)(const QJsonValue*); + typedef void (*QUrl__init_t)(QUrl*, const QString&, int /* QUrl::ParsingMode */); + typedef void (*QWebChannel__init_t)(QWebChannel*, QObject*); + typedef void (*QWebChannel_registerObject_t)(QWebChannel*, const QString&, QObject*); + typedef void (*QWebEnginePage__init_t)(QWebEnginePage*, QWebEngineProfile*, QObject*); + typedef void (*QWebEnginePage_setBackgroundColor_t)(QWebEnginePage*, const QColor&); + typedef QWebChannel* (*QWebEnginePage_webChannel_t)(QWebEnginePage*); + typedef QWebEngineProfile* (*QWebEngineProfile_defaultProfile_t)(); + typedef void (*QWebEngineProfile_installUrlSchemeHandler_t)(QWebEngineProfile*, const QByteArray&, QWebEngineUrlSchemeHandler*); + typedef QWebEngineSettings* (*QWebEngineProfile_settings_t)(QWebEngineProfile*); + typedef QWebEngineScriptCollection* (*QWebEngineProfile_scripts_t)(QWebEngineProfile*); + typedef void (*QWebEngineScript__init_t)(QWebEngineScript*); + typedef void (*QWebEngineScript_setInjectionPoint_t)(QWebEngineScript*, int /* QWebEngineScript::InjectionPoint */); + typedef void (*QWebEngineScript_setRunsOnSubFrames_t)(QWebEngineScript*, bool); + typedef void (*QWebEngineScript_setSourceCode_t)(QWebEngineScript*, const QString &); + typedef void (*QWebEngineScript_setWorldId_t)(QWebEngineScript*, uint32_t); + typedef void (*QWebEngineScriptCollection_insert_t)(QWebEngineScriptCollection*, QWebEngineScript&); + typedef void (*QWebEngineSettings_setAttribute_t)(QWebEngineSettings*, int /* QWebEngineSettings::WebAttribute */, bool); + // typedef void (*QWebEngineUrlRequestJob_reply_t)(QWebEngineUrlRequestJob*, const QByteArray&, QIODevice*); + typedef void (*QWebEngineUrlScheme__init_t)(QWebEngineUrlScheme*, const QByteArray&); + typedef void (*QWebEngineUrlScheme_registerScheme_t)(QWebEngineUrlScheme&); + typedef void (*QWebEngineUrlScheme_setFlags_t)(QWebEngineUrlScheme*, int /* QWebEngineUrlScheme::Flags */); + typedef void (*QWebEngineUrlScheme_setSyntax_t)(QWebEngineUrlScheme*, int /* QWebEngineUrlScheme::Syntax */); + typedef void (*QWebEngineUrlSchemeHandler__init_t)(QObject*, QObject*); + typedef void (*QWebEngineView__init_t)(QWebEngineView*, QObject*); + typedef void (*QWebEngineView_move_t)(QWebEngineView*, const QPoint&); + typedef void (*QWebEngineView_resize_t)(QWebEngineView*, const QSize&); + typedef void (*QWebEngineView_setPage_t)(QWebEngineView*, QWebEnginePage*); + typedef void (*QWebEngineView_setUrl_t)(QWebEngineView*, const QUrl&); + typedef void (*QWebEngineView_show_t)(QWebEngineView*); + typedef ulonglong (*QWebEngineView_winId_t)(QWebEngineView*); + typedef QWindow* (*QWebEngineView_windowHandle_t)(QWebEngineView*); + typedef QWindow* (*QWindow_fromWinId_t)(ulonglong); + typedef void (*QWindow_setParent_t)(QWindow*, void*); CPPSYM(QApplication__init_t, QApplication__init, _ZN12QApplicationC1ERiPPci) CPPSYM(QApplication_exec_t, QApplication_exec, _ZN15QGuiApplication4execEv) @@ -1684,8 +1773,8 @@ static bool qtwebengine(const int qtVersion, QWebChannel_registerObject(&channel, qstrchannel, &eventFilter); QWebEnginePage_setWebChannel(&page, &channel, 0); - QWebEngineView_move(&webview, QPoint{x, y}); - QWebEngineView_resize(&webview, QSize{static_cast(width), static_cast(height)}); + QWebEngineView_move(&webview, QPoint(x, y)); + QWebEngineView_resize(&webview, QSize(static_cast(width), static_cast(height))); QWebEngineView_winId(&webview); QWindow_setParent(QWebEngineView_windowHandle(&webview), QWindow_fromWinId(winId)); @@ -1701,45 +1790,114 @@ static bool qtwebengine(const int qtVersion, QWebEngineView_show(&webview); - evaluateFn = [=, &page](const char* const js){ - QString qstrjs; + struct QtWebFramework : WebFramework { + const int _qtVersion; + WebViewRingBuffer* const _shmptr; + const QUrl& _qurl; + QWebEnginePage& _page; + QWebEngineView& _webview; + EventFilterQObject& _eventFilter; + const QString__init_t _QString__init; + const QWebEnginePage_runJavaScript_compat_t _QWebEnginePage_runJavaScript_compat; + const QWebEnginePage_runJavaScript_t _QWebEnginePage_runJavaScript; + const QWebEngineView_setUrl_t _QWebEngineView_setUrl; + const QApplication_quit_t _QApplication_quit; + const QEvent__init_t _QEvent__init; + const QApplication_postEvent_t _QApplication_postEvent; + + QtWebFramework(const int qtVersion, + WebViewRingBuffer* const shmptr, + const QUrl& qurl, + QWebEnginePage& page, + QWebEngineView& webview, + EventFilterQObject& eventFilter, + const QString__init_t QString__init, + const QWebEnginePage_runJavaScript_compat_t QWebEnginePage_runJavaScript_compat, + const QWebEnginePage_runJavaScript_t QWebEnginePage_runJavaScript, + const QWebEngineView_setUrl_t QWebEngineView_setUrl, + const QApplication_quit_t QApplication_quit, + const QEvent__init_t QEvent__init, + const QApplication_postEvent_t QApplication_postEvent) + : _qtVersion(qtVersion), + _shmptr(shmptr), + _qurl(qurl), + _page(page), + _webview(webview), + _eventFilter(eventFilter), + _QString__init(QString__init), + _QWebEnginePage_runJavaScript_compat(QWebEnginePage_runJavaScript_compat), + _QWebEnginePage_runJavaScript(QWebEnginePage_runJavaScript), + _QWebEngineView_setUrl(QWebEngineView_setUrl), + _QApplication_quit(QApplication_quit), + _QEvent__init(QEvent__init), + _QApplication_postEvent(QApplication_postEvent) {} + + void evaluate(const char* const js) override { - const size_t js_len = std::strlen(js); - ushort* const js_qchar = new ushort[js_len + 1]; + QString qstrjs; + { + const size_t js_len = std::strlen(js); + ushort* const js_qchar = new ushort[js_len + 1]; + + for (size_t i = 0; i < js_len; ++i) + js_qchar[i] = js[i]; - for (size_t i = 0; i < js_len; ++i) - js_qchar[i] = js[i]; + js_qchar[js_len] = 0; - js_qchar[js_len] = 0; + _QString__init(&qstrjs, reinterpret_cast(js_qchar), js_len); + } - QString__init(&qstrjs, reinterpret_cast(js_qchar), js_len); + if (_qtVersion == 5) + _QWebEnginePage_runJavaScript_compat(&_page, qstrjs); + else + _QWebEnginePage_runJavaScript(&_page, qstrjs, 0, + #ifdef DISTRHO_PROPER_CPP11_SUPPORT + {} + #else + 0 + #endif + ); } - if (qtVersion == 5) - QWebEnginePage_runJavaScript_compat(&page, qstrjs); - else - QWebEnginePage_runJavaScript(&page, qstrjs, 0, {}); - }; + void reload() override + { + _QWebEngineView_setUrl(&_webview, _qurl); + } - reloadFn = [=, &webview](){ - QWebEngineView_setUrl(&webview, qurl); - }; + void terminate() override + { + if (running) + { + running = false; + webview_wake(&_shmptr->client.sem); + _QApplication_quit(); + } + } - terminateFn = [=](){ - if (running) + void wake(WebViewRingBuffer*) override { - running = false; - webview_wake(&shmptr->client.sem); - QApplication_quit(); + // NOTE event pointer is deleted by Qt + QEvent* const qevent = new QEvent; + _QEvent__init(qevent, 1000 /* QEvent::User */); + _QApplication_postEvent(&_eventFilter, qevent, 1 /* Qt::HighEventPriority */); } }; - wakeFn = [=, &eventFilter](WebViewRingBuffer*){ - // NOTE event pointer is deleted by Qt - QEvent* const qevent = new QEvent; - QEvent__init(qevent, 1000 /* QEvent::User */); - QApplication_postEvent(&eventFilter, qevent, 1 /* Qt::HighEventPriority */); - }; + QtWebFramework webFrameworkObj(qtVersion, + shmptr, + qurl, + page, + webview, + eventFilter, + QString__init, + QWebEnginePage_runJavaScript_compat, + QWebEnginePage_runJavaScript, + QWebEngineView_setUrl, + QApplication_quit, + QEvent__init, + QApplication_postEvent); + + webFramework = &webFrameworkObj; // notify server we started ok webview_wake(&shmptr->server.sem); @@ -1762,7 +1920,7 @@ static void signalHandler(const int sig) switch (sig) { case SIGTERM: - terminateFn(); + webFramework->terminate(); break; } } @@ -1774,7 +1932,7 @@ static void* threadHandler(void* const ptr) while (running && shmptr->valid) { if (webview_timedwait(&shmptr->client.sem) && running) - wakeFn(shmptr); + webFramework->wake(shmptr); } return nullptr; diff --git a/distrho/src/DistrhoDefines.h b/distrho/src/DistrhoDefines.h index 3b1d97a9..4250f293 100644 --- a/distrho/src/DistrhoDefines.h +++ b/distrho/src/DistrhoDefines.h @@ -215,6 +215,12 @@ private: \ #define STRINGIFY2(s) #s #define STRINGIFY(s) STRINGIFY2(s) +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +#define CPP_AGGREGATE_INIT(ClassName) ClassName +#else +#define CPP_AGGREGATE_INIT(ClassName) (ClassName) +#endif + /* Useful typedefs */ typedef unsigned char uchar; typedef unsigned short int ushort; diff --git a/distrho/src/DistrhoPluginCLAP.cpp b/distrho/src/DistrhoPluginCLAP.cpp index 04933ebc..498957ec 100644 --- a/distrho/src/DistrhoPluginCLAP.cpp +++ b/distrho/src/DistrhoPluginCLAP.cpp @@ -171,12 +171,9 @@ struct ClapEventQueue ClapEventQueue() #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT - : fNotesBuffer(StackBuffer_INIT) + : fNotesBuffer(CPP_AGGREGATE_INIT(SmallStackBuffer){0, 0, 0, false, {0}}) #endif { - #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) - std::memset(&fNotesBuffer, 0, sizeof(fNotesBuffer)); - #endif #if DISTRHO_PLUGIN_WANT_PROGRAMS fCurrentProgram = 0; #endif diff --git a/distrho/src/DistrhoPluginVST2.cpp b/distrho/src/DistrhoPluginVST2.cpp index b9b9926b..686341a8 100644 --- a/distrho/src/DistrhoPluginVST2.cpp +++ b/distrho/src/DistrhoPluginVST2.cpp @@ -117,13 +117,10 @@ struct ParameterAndNotesHelper #if DISTRHO_PLUGIN_HAS_UI , parameterChecks(nullptr) #if DISTRHO_PLUGIN_WANT_MIDI_INPUT - , notesRingBuffer(StackBuffer_INIT) + , notesRingBuffer(CPP_AGGREGATE_INIT(SmallStackBuffer){0, 0, 0, false, {0}}) #endif #endif { - #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) - std::memset(¬esRingBuffer, 0, sizeof(notesRingBuffer)); - #endif } virtual ~ParameterAndNotesHelper() diff --git a/distrho/src/DistrhoUI.cpp b/distrho/src/DistrhoUI.cpp index a4e81129..ca8894dc 100644 --- a/distrho/src/DistrhoUI.cpp +++ b/distrho/src/DistrhoUI.cpp @@ -119,7 +119,7 @@ static double getDesktopScaleFactor(const uintptr_t parentWindowHandle) { const HMONITOR hMon = parentWindowHandle != 0 ? MonitorFromWindow((HWND)parentWindowHandle, MONITOR_DEFAULTTOPRIMARY) - : MonitorFromPoint(POINT{0,0}, MONITOR_DEFAULTTOPRIMARY); + : MonitorFromPoint(POINT(), MONITOR_DEFAULTTOPRIMARY); GetScaleFactorForMonitor(hMon, &scaleFactor); }