iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IPlugWebView_web.cpp
1/*
2 ==============================================================================
3
4 iPlug2 WebView Library
5 Copyright (c) 2026 Oliver Larkin
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24
25 ==============================================================================
26*/
27
28#include "IPlugWebView.h"
29
30#include <emscripten.h>
31#include <emscripten/bind.h>
32
33#include <cstdint>
34#include <string>
35
36BEGIN_IPLUG_NAMESPACE
37
39{
40public:
41 IWebViewImpl(IWebView* owner);
43
44 void* OpenWebView(void* pParent, float x, float y, float w, float h, float scale);
45 void CloseWebView();
46 void HideWebView(bool hide);
47 void LoadHTML(const char* html);
48 void LoadURL(const char* url);
49 void LoadFile(const char* fileName, const char* bundleID);
50 void ReloadPageContent();
51 void EvaluateJavaScript(const char* scriptStr, IWebView::completionHandlerFunc func);
52 void EnableScroll(bool enable);
53 void EnableInteraction(bool enable);
54 void SetWebViewBounds(float x, float y, float w, float h, float scale);
55 void GetWebRoot(WDL_String& path) const { path.Set(mWebRoot.Get()); }
56 void GetLocalDownloadPathForFile(const char* fileName, WDL_String& localPath);
57
58private:
59 IWebView* mIWebView = nullptr;
60 WDL_String mWebRoot;
61 bool mOpen = false;
62};
63
64END_IPLUG_NAMESPACE
65
66using namespace iplug;
67
68namespace
69{
70uintptr_t OwnerPtr(IWebView* pWebView)
71{
72 return reinterpret_cast<uintptr_t>(pWebView);
73}
74
75void OnMessageFromWebView(uintptr_t ownerPtr, const std::string& json)
76{
77 if (auto* pWebView = reinterpret_cast<IWebView*>(ownerPtr))
78 {
79 pWebView->OnMessageFromWebView(json.c_str());
80 }
81}
82
83void OnWebContentLoaded(uintptr_t ownerPtr)
84{
85 if (auto* pWebView = reinterpret_cast<IWebView*>(ownerPtr))
86 {
87 pWebView->OnWebContentLoaded();
88 }
89}
90}
91
92IWebViewImpl::IWebViewImpl(IWebView* owner)
93: mIWebView(owner)
94{
95 mWebRoot.Set("web");
96}
97
98IWebViewImpl::~IWebViewImpl()
99{
100 CloseWebView();
101}
102
103void* IWebViewImpl::OpenWebView(void* pParent, float x, float y, float w, float h, float scale)
104{
105 (void) pParent;
106 mOpen = true;
107
108 EM_ASM({
109 if (typeof window.__iPlugWebViewOpen === 'function') {
110 window.__iPlugWebViewOpen($0, $1, $2, $3, $4, $5);
111 }
112 }, OwnerPtr(mIWebView), x, y, w, h, scale);
113
114 mIWebView->OnWebViewReady();
115 return reinterpret_cast<void*>(mIWebView);
116}
117
118void IWebViewImpl::CloseWebView()
119{
120 if (!mOpen)
121 return;
122
123 EM_ASM({
124 if (typeof window.__iPlugWebViewClose === 'function') {
125 window.__iPlugWebViewClose($0);
126 }
127 }, OwnerPtr(mIWebView));
128
129 mOpen = false;
130}
131
132void IWebViewImpl::HideWebView(bool hide)
133{
134 EM_ASM({
135 if (typeof window.__iPlugWebViewHide === 'function') {
136 window.__iPlugWebViewHide($0, !!$1);
137 }
138 }, OwnerPtr(mIWebView), hide);
139}
140
141void IWebViewImpl::LoadHTML(const char* html)
142{
143 EM_ASM({
144 if (typeof window.__iPlugWebViewLoadHTML === 'function') {
145 window.__iPlugWebViewLoadHTML($0, UTF8ToString($1));
146 }
147 }, OwnerPtr(mIWebView), html ? html : "");
148}
149
150void IWebViewImpl::LoadURL(const char* url)
151{
152 EM_ASM({
153 if (typeof window.__iPlugWebViewLoadURL === 'function') {
154 window.__iPlugWebViewLoadURL($0, UTF8ToString($1));
155 }
156 }, OwnerPtr(mIWebView), url ? url : "");
157}
158
159void IWebViewImpl::LoadFile(const char* fileName, const char* bundleID)
160{
161 (void) bundleID;
162
163 WDL_String filePart;
164 if (fileName && fileName[0] != '\0')
165 {
166 WDL_String requestedFile(fileName);
167 filePart.Set(requestedFile.get_filepart());
168 }
169
170 if (filePart.GetLength() == 0)
171 {
172 filePart.Set("index.html");
173 }
174
175 mWebRoot.Set("web");
176
177 WDL_String webFile;
178 webFile.SetFormatted(1024, "web/%s", filePart.Get());
179
180 EM_ASM({
181 if (typeof window.__iPlugWebViewLoadFile === 'function') {
182 window.__iPlugWebViewLoadFile($0, UTF8ToString($1), UTF8ToString($2));
183 }
184 }, OwnerPtr(mIWebView), webFile.Get(), mWebRoot.Get());
185}
186
187void IWebViewImpl::ReloadPageContent()
188{
189 EM_ASM({
190 if (typeof window.__iPlugWebViewReload === 'function') {
191 window.__iPlugWebViewReload($0);
192 }
193 }, OwnerPtr(mIWebView));
194}
195
196void IWebViewImpl::EvaluateJavaScript(const char* scriptStr, IWebView::completionHandlerFunc func)
197{
198 EM_ASM({
199 if (typeof window.__iPlugWebViewEvaluate === 'function') {
200 window.__iPlugWebViewEvaluate($0, UTF8ToString($1));
201 }
202 }, OwnerPtr(mIWebView), scriptStr ? scriptStr : "");
203
204 if (func)
205 {
206 func("");
207 }
208}
209
210void IWebViewImpl::EnableScroll(bool enable)
211{
212 EM_ASM({
213 if (typeof window.__iPlugWebViewEnableScroll === 'function') {
214 window.__iPlugWebViewEnableScroll($0, !!$1);
215 }
216 }, OwnerPtr(mIWebView), enable);
217}
218
219void IWebViewImpl::EnableInteraction(bool enable)
220{
221 EM_ASM({
222 if (typeof window.__iPlugWebViewEnableInteraction === 'function') {
223 window.__iPlugWebViewEnableInteraction($0, !!$1);
224 }
225 }, OwnerPtr(mIWebView), enable);
226}
227
228void IWebViewImpl::SetWebViewBounds(float x, float y, float w, float h, float scale)
229{
230 EM_ASM({
231 if (typeof window.__iPlugWebViewSetBounds === 'function') {
232 window.__iPlugWebViewSetBounds($0, $1, $2, $3, $4, $5);
233 }
234 }, OwnerPtr(mIWebView), x, y, w, h, scale);
235}
236
237void IWebViewImpl::GetLocalDownloadPathForFile(const char* fileName, WDL_String& localPath)
238{
239 localPath.Set(fileName ? fileName : "");
240}
241
242EMSCRIPTEN_BINDINGS(IPlugWebViewWeb) {
243 emscripten::function("IPlugWebView_OnMessage", &OnMessageFromWebView);
244 emscripten::function("IPlugWebView_OnContentLoaded", &OnWebContentLoaded);
245}
246
247#include "IPlugWebView.cpp"
IWebView is a base interface for hosting a platform web view inside an IPlug plug-in's UI.
Definition: IPlugWebView.h:44
virtual void OnWebViewReady()
Called when the web view is ready to receive navigation instructions.
Definition: IPlugWebView.h:110