Browse Source

Handle web-ui for choc too, cleanup shared details

Signed-off-by: falkTX <falktx@falktx.com>
web-ui
falkTX 1 year ago
parent
commit
100fdf406b
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
2 changed files with 80 additions and 95 deletions
  1. +74
    -89
      distrho/extra/WebViewImpl.cpp
  2. +6
    -6
      distrho/src/DistrhoUI.cpp

+ 74
- 89
distrho/extra/WebViewImpl.cpp View File

@@ -307,11 +307,35 @@ static bool webview_timedwait(ipc_sem_t* const sem)
#endif
}

static void getFilenameFromFunctionPtr(char filename[PATH_MAX], const void* const ptr)
{
Dl_info info = {};
dladdr(ptr, &info);

if (info.dli_fname[0] == '.')
{
getcwd(filename, PATH_MAX - 1);
std::strncat(filename, info.dli_fname + 1, PATH_MAX - 1);
}
else if (info.dli_fname[0] != '/')
{
getcwd(filename, PATH_MAX - 1);
std::strncat(filename, "/", PATH_MAX - 1);
std::strncat(filename, info.dli_fname, PATH_MAX - 1);
}
else
{
std::strncpy(filename, info.dli_fname, PATH_MAX - 1);
}
}
#endif

struct WebViewData {
#if WEB_VIEW_USING_CHOC
choc::ui::WebView* const webview;
choc::ui::WebView* webview;
WebViewMessageCallback callback;
void* callbackPtr;
std::string url;
#elif WEB_VIEW_USING_MACOS_WEBKIT
NSView* view;
WKWebView* webview;
@@ -335,77 +359,6 @@ struct WebViewData {

// -----------------------------------------------------------------------------------------------------------

#if WEB_VIEW_USING_CHOC
static std::optional<choc::ui::WebView::Options::Resource> fetch_resource(const std::string& path)
{
d_stdout("requested path %s", path.c_str());

if (path == "/")
{
const std::string html = R"PREFIX(
<html>
<head>
<style>
html, body { background: black; background-image: url(img.svg); }
</style>
<script>
function parameterChanged(index, value) {
console.log("parameterChanged received", index, value);
}
</script>
</head>
<body>
hello world!
</body>
</html>
)PREFIX";
const std::vector<uint8_t> data(html.begin(), html.end());
return choc::ui::WebView::Options::Resource{ data, "text/html" };
}
if (path == "/img.svg")
{
const std::string html = R"PREFIX(<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- based on https://github.com/n0jo/rackwindows/blob/master/res/components/rw_knob_large_dark.svg -->
<svg width="47px" height="47px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;">
<g id="knobLDark">
<path id="path3832" d="M23.521,45.109c-7.674,0 -3.302,3.9 -10.224,0.498c-6.922,-3.403 -1.202,-2.341 -5.997,-8.501c-4.795,-6.159 -5.059,-0.201 -6.763,-7.827c-1.704,-7.625 1.043,-2.42 2.76,-10.046c1.718,-7.626 -2.998,-4.102 1.797,-10.221c4.795,-6.12 2.51,-0.673 9.432,-4.035c6.921,-3.363 1.321,-4.977 8.995,-4.977c7.675,0 2.087,1.574 8.996,4.977c6.909,3.402 4.636,-2.045 9.432,4.035c4.795,6.078 0.079,2.689 1.796,10.26c1.717,7.572 4.465,2.422 2.761,10.048c-1.704,7.625 -1.982,1.708 -6.763,7.827c-4.782,6.119 0.924,5.057 -5.998,8.46c-6.921,3.402 -2.549,-0.498 -10.224,-0.498Z" style="fill:#ccc;fill-rule:nonzero;"/>
</g>
</svg>

)PREFIX";
const std::vector<uint8_t> data(html.begin(), html.end());
return choc::ui::WebView::Options::Resource{ data, "image/svg+xml" };
}

return {};
}
#elif WEB_VIEW_USING_X11_IPC
static void getFilenameFromFunctionPtr(char filename[PATH_MAX], const void* const ptr)
{
Dl_info info = {};
dladdr(ptr, &info);

if (info.dli_fname[0] == '.')
{
getcwd(filename, PATH_MAX - 1);
std::strncat(filename, info.dli_fname + 1, PATH_MAX - 1);
}
else if (info.dli_fname[0] != '/')
{
getcwd(filename, PATH_MAX - 1);
std::strncat(filename, "/", PATH_MAX - 1);
std::strncat(filename, info.dli_fname, PATH_MAX - 1);
}
else
{
std::strncpy(filename, info.dli_fname, PATH_MAX - 1);
}
}
#endif

// -----------------------------------------------------------------------------------------------------------

WebViewHandle webViewCreate(const char* const url,
const uintptr_t windowId,
const uint initialWidth,
@@ -417,7 +370,6 @@ WebViewHandle webViewCreate(const char* const url,
choc::ui::WebView::Options woptions;
woptions.acceptsFirstMouseClick = true;
woptions.enableDebugMode = true;
woptions.fetchResource = fetch_resource;

std::unique_ptr<choc::ui::WebView> webview = std::make_unique<choc::ui::WebView>(woptions);
DISTRHO_SAFE_ASSERT_RETURN(webview->loadedOK(), nullptr);
@@ -425,16 +377,25 @@ WebViewHandle webViewCreate(const char* const url,
void* const handle = webview->getViewHandle();
DISTRHO_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);

choc::ui::WebView* const www = webview.get();
webview->bind("setParameterValue", [www](const choc::value::ValueView&) -> choc::value::Value {
static int pp = 0;
std::string toeval = "typeof(parameterChanged) === 'function' && parameterChanged(";
toeval += std::to_string(++pp);
toeval += ", 0.1)";
d_stdout("param received | %s", toeval.c_str());
www->evaluateJavascript(toeval);
return {};
});
if (const WebViewMessageCallback callback = options.callback)
{
webview->addInitScript("function postMessage(m) { js2cpp(m); }");

void* const callbackPtr = options.callbackPtr;
webview->bind("js2cpp", [callback, callbackPtr](const choc::value::ValueView& args) -> choc::value::Value {
callback(callbackPtr, args[0].toString().data());
return {};
});
}
else
{
webview->addInitScript("function postMessage(m) {}");
}

if (options.initialJS != nullptr)
webview->addInitScript(options.initialJS);

webview->navigate(url);

#ifdef DISTRHO_OS_MAC
NSView* const view = static_cast<NSView*>(handle);
@@ -461,7 +422,12 @@ WebViewHandle webViewCreate(const char* const url,
ShowWindow(hwnd, SW_SHOW);
#endif

return new WebViewData{options.callback, webview.release()};
WebViewData* const whandle = new WebViewData;
whandle->webview = webview.release();
whandle->callback = options.callback;
whandle->callbackPtr = options.callbackPtr;
whandle->url = url;
return whandle;
#elif WEB_VIEW_USING_MACOS_WEBKIT
NSView* const view = reinterpret_cast<NSView*>(windowId);

@@ -498,9 +464,18 @@ WebViewHandle webViewCreate(const char* const url,

if (WKUserContentController* const controller = [config userContentController])
{
[controller retain];
[controller addScriptMessageHandler:delegate name:@"external"];

WKUserScript* const mscript = [[WKUserScript alloc]
initWithSource:(options.callback != nullptr
? @"function postMessage(m){window.webkit.messageHandlers.external.postMessage(m)}"
: @"function postMessage(m){}}")
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:true
];
[controller addUserScript:mscript];
[mscript release];

if (options.initialJS != nullptr)
{
NSString* const nsInitialJS = [[NSString alloc] initWithBytes:options.initialJS
@@ -742,6 +717,10 @@ void webViewDestroy(const WebViewHandle handle)
[handle->urlreq release];
// [handle->delegate release];
#elif WEB_VIEW_USING_X11_IPC
#ifndef __linux__
sem_destroy(&handle->shmptr->client.sem);
sem_destroy(&handle->shmptr->server.sem);
#endif
munmap(handle->shmptr, sizeof(WebViewRingBuffer));
close(handle->shmfd);
shm_unlink(handle->shmname);
@@ -800,6 +779,7 @@ void webViewIdle(const WebViewHandle handle)
void webViewEvaluateJS(const WebViewHandle handle, const char* const js)
{
#if WEB_VIEW_USING_CHOC
handle->webview->evaluateJavascript(js);
#elif WEB_VIEW_USING_MACOS_WEBKIT
NSString* const nsjs = [[NSString alloc] initWithBytes:js
length:std::strlen(js)
@@ -824,6 +804,7 @@ void webViewEvaluateJS(const WebViewHandle handle, const char* const js)
void webViewReload(const WebViewHandle handle)
{
#if WEB_VIEW_USING_CHOC
handle->webview->navigate(handle->url);
#elif WEB_VIEW_USING_MACOS_WEBKIT
[handle->webview loadRequest:handle->urlreq];
#elif WEB_VIEW_USING_X11_IPC
@@ -1144,14 +1125,18 @@ static bool gtk3(Display* const display,

if (WebKitUserContentManager* const manager = webkit_web_view_get_user_content_manager(WEBKIT_WEB_VIEW(webview)))
{
g_signal_connect_data(manager, "script-message-received::external", G_CALLBACK(gtk3_js_cb), shmptr, nullptr, 0);
webkit_user_content_manager_register_script_message_handler(manager, "external");

WebKitUserScript* const mscript = webkit_user_script_new(
"function postMessage(m){window.webkit.messageHandlers.external.postMessage(m)}", 0, 0, nullptr, nullptr);
webkit_user_content_manager_add_script(manager, mscript);

if (initialJS != nullptr)
{
WebKitUserScript* const script = webkit_user_script_new(initialJS, 0, 0, nullptr, nullptr);
webkit_user_content_manager_add_script(manager, script);
}

g_signal_connect_data(manager, "script-message-received::external", G_CALLBACK(gtk3_js_cb), shmptr, nullptr, 0);
webkit_user_content_manager_register_script_message_handler(manager, "external");
}

webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview), url);


+ 6
- 6
distrho/src/DistrhoUI.cpp View File

@@ -290,14 +290,14 @@ UI::UI(const uint width, const uint height, const bool automaticallyScaleAndSetA
}

init("file://" + path + "/index.html",
"editParameter=function(index,started){window.webkit.messageHandlers.external.postMessage('editparam '+index+' '+(started ? 1 : 0))};"
"setParameterValue=function(index,value){window.webkit.messageHandlers.external.postMessage('setparam '+index+' '+value)};"
"editParameter = function(index, started){ postMessage('editparam '+index+' '+(started ? 1 : 0)) };"
"setParameterValue = function(index, value){ postMessage('setparam '+index+' '+value) };"
#if DISTRHO_PLUGIN_WANT_STATE
"setState=function(key,value){window.webkit.messageHandlers.external.postMessage('setstate '+key+' '+value)};"
"requestStateFile=function(key){window.webkit.messageHandlers.external.postMessage('reqstatefile '+key)};"
"setState = function(key, value){ postMessage('setstate '+key+' '+value) };"
"requestStateFile = function(key){ postMessage('reqstatefile '+key) };"
#endif
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
"sendNote=function(channel,note,velocity){window.webkit.messageHandlers.external.postMessage('sendnote '+channel+' '+note+' '+velocity)};"
"sendNote = function(channel, note, velocity){ postMessage('sendnote '+channel+' '+note+' '+velocity) };"
#endif
);
#endif
@@ -652,7 +652,7 @@ void UI::onMessage(char* const message)
}
#endif

d_stderr("UI received unknown message %s", message);
d_stderr("UI received unknown message '%s'", message);
}
#endif



Loading…
Cancel
Save