@@ -21,6 +21,7 @@ | |||||
#include "DistrhoUI.hpp" | #include "DistrhoUI.hpp" | ||||
#include "DistrhoPlugin.hpp" | #include "DistrhoPlugin.hpp" | ||||
#include "PluginHostWindow.hpp" | |||||
#include "SizeUtils.hpp" | #include "SizeUtils.hpp" | ||||
#include "extra/Thread.hpp" | #include "extra/Thread.hpp" | ||||
@@ -52,7 +53,9 @@ using namespace CarlaBackend; | |||||
// shared resource pointer | // shared resource pointer | ||||
// carla_juce_init(); | // carla_juce_init(); | ||||
class IldaeilUI : public UI, public Thread | |||||
class IldaeilUI : public UI, | |||||
public Thread, | |||||
public PluginHostWindow::Callbacks | |||||
{ | { | ||||
static constexpr const uint kInitialWidth = 1220; | static constexpr const uint kInitialWidth = 1220; | ||||
static constexpr const uint kInitialHeight = 640; | static constexpr const uint kInitialHeight = 640; | ||||
@@ -70,6 +73,7 @@ class IldaeilUI : public UI, public Thread | |||||
} fDrawingState; | } fDrawingState; | ||||
IldaeilPlugin* const fPlugin; | IldaeilPlugin* const fPlugin; | ||||
PluginHostWindow fPluginHostWindow; | |||||
uint fPluginCount; | uint fPluginCount; | ||||
uint fPluginSelected; | uint fPluginSelected; | ||||
@@ -78,21 +82,17 @@ class IldaeilUI : public UI, public Thread | |||||
bool fPluginSearchActive; | bool fPluginSearchActive; | ||||
char fPluginSearchString[0xff]; | char fPluginSearchString[0xff]; | ||||
bool fInitialSizeHasBeenSet; | |||||
const uintptr_t fOurWindowId; | |||||
public: | public: | ||||
IldaeilUI() | IldaeilUI() | ||||
: UI(kInitialWidth, kInitialHeight), | : UI(kInitialWidth, kInitialHeight), | ||||
Thread("IldaeilScanner"), | Thread("IldaeilScanner"), | ||||
fDrawingState(kDrawingInit), | fDrawingState(kDrawingInit), | ||||
fPlugin((IldaeilPlugin*)getPluginInstancePointer()), | fPlugin((IldaeilPlugin*)getPluginInstancePointer()), | ||||
fPluginHostWindow(getWindow(), this), | |||||
fPluginCount(0), | fPluginCount(0), | ||||
fPluginSelected(0), | fPluginSelected(0), | ||||
fPlugins(nullptr), | fPlugins(nullptr), | ||||
fPluginSearchActive(false), | |||||
fInitialSizeHasBeenSet(false), | |||||
fOurWindowId(getWindow().getNativeWindowHandle()) | |||||
fPluginSearchActive(false) | |||||
{ | { | ||||
if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) | if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) | ||||
{ | { | ||||
@@ -107,10 +107,21 @@ public: | |||||
const double scaleFactor = getScaleFactor(); | const double scaleFactor = getScaleFactor(); | ||||
if (d_isNotEqual(scaleFactor, 1.0)) | if (d_isNotEqual(scaleFactor, 1.0)) | ||||
{ | |||||
setSize(kInitialWidth * scaleFactor, kInitialHeight * scaleFactor); | setSize(kInitialWidth * scaleFactor, kInitialHeight * scaleFactor); | ||||
fPluginHostWindow.setPositionAndSize(0, kExtraHeight * scaleFactor, | |||||
kInitialWidth * scaleFactor, (kInitialHeight - kExtraHeight) * scaleFactor); | |||||
} | |||||
else | |||||
{ | |||||
fPluginHostWindow.setPositionAndSize(0, kExtraHeight, kInitialWidth, kInitialHeight-kExtraHeight); | |||||
} | |||||
const CarlaHostHandle handle = fPlugin->fCarlaHostHandle; | const CarlaHostHandle handle = fPlugin->fCarlaHostHandle; | ||||
// carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_WIN_ID, 0, winIdStr); | |||||
carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_UI_SCALE, getScaleFactor()*1000, nullptr); | |||||
if (carla_get_current_plugin_count(handle) != 0) | if (carla_get_current_plugin_count(handle) != 0) | ||||
{ | { | ||||
showPluginUI(handle); | showPluginUI(handle); | ||||
@@ -128,9 +139,10 @@ public: | |||||
fPlugin->fUI = nullptr; | fPlugin->fUI = nullptr; | ||||
if (fDrawingState == kDrawingPluginCustomUI) | |||||
if (fDrawingState == kDrawingPluginGenericUI || fDrawingState == kDrawingPluginCustomUI) | |||||
carla_show_custom_ui(fPlugin->fCarlaHostHandle, 0, false); | carla_show_custom_ui(fPlugin->fCarlaHostHandle, 0, false); | ||||
fPluginHostWindow.detach(); | |||||
delete[] fPlugins; | delete[] fPlugins; | ||||
} | } | ||||
@@ -140,14 +152,8 @@ public: | |||||
if (info->hints & PLUGIN_HAS_CUSTOM_EMBED_UI) | if (info->hints & PLUGIN_HAS_CUSTOM_EMBED_UI) | ||||
{ | { | ||||
// carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_WIN_ID, 0, winIdStr); | |||||
carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_UI_SCALE, getScaleFactor()*1000, nullptr); | |||||
carla_embed_custom_ui(handle, 0, (void*)fOurWindowId); | |||||
fDrawingState = kDrawingPluginCustomUI; | fDrawingState = kDrawingPluginCustomUI; | ||||
fInitialSizeHasBeenSet = false; | |||||
tryResizingToChildWindowContent(); | |||||
carla_embed_custom_ui(handle, 0, fPluginHostWindow.attachAndGetWindowHandle()); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -161,6 +167,11 @@ public: | |||||
} | } | ||||
protected: | protected: | ||||
void pluginWindowResized(uint width, uint height) override | |||||
{ | |||||
setSize(width, height + kExtraHeight * getScaleFactor()); | |||||
} | |||||
void uiIdle() override | void uiIdle() override | ||||
{ | { | ||||
switch (fDrawingState) | switch (fDrawingState) | ||||
@@ -172,9 +183,9 @@ protected: | |||||
break; | break; | ||||
case kDrawingPluginCustomUI: | case kDrawingPluginCustomUI: | ||||
if (! fInitialSizeHasBeenSet) | |||||
tryResizingToChildWindowContent(); | |||||
// fall-through | |||||
fPlugin->fCarlaPluginDescriptor->ui_idle(fPlugin->fCarlaPluginHandle); | |||||
fPluginHostWindow.idle(); | |||||
break; | |||||
case kDrawingPluginGenericUI: | case kDrawingPluginGenericUI: | ||||
fPlugin->fCarlaPluginDescriptor->ui_idle(fPlugin->fCarlaPluginHandle); | fPlugin->fCarlaPluginDescriptor->ui_idle(fPlugin->fCarlaPluginHandle); | ||||
@@ -225,14 +236,14 @@ protected: | |||||
drawGenericUI(); | drawGenericUI(); | ||||
// fall-through | // fall-through | ||||
case kDrawingPluginCustomUI: | case kDrawingPluginCustomUI: | ||||
drawBottomBar(); | |||||
drawTopBar(); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
void drawBottomBar() | |||||
void drawTopBar() | |||||
{ | { | ||||
ImGui::SetNextWindowPos(ImVec2(0, getHeight() - kExtraHeight * getScaleFactor())); | |||||
ImGui::SetNextWindowPos(ImVec2(0, 0)); | |||||
ImGui::SetNextWindowSize(ImVec2(getWidth(), kExtraHeight * getScaleFactor())); | ImGui::SetNextWindowSize(ImVec2(getWidth(), kExtraHeight * getScaleFactor())); | ||||
if (ImGui::Begin("Current Plugin", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize)) | if (ImGui::Begin("Current Plugin", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize)) | ||||
@@ -368,6 +379,7 @@ protected: | |||||
{ | { | ||||
const CarlaCachedPluginInfo& info(fPlugins[i]); | const CarlaCachedPluginInfo& info(fPlugins[i]); | ||||
/* | |||||
#if DISTRHO_PLUGIN_IS_SYNTH | #if DISTRHO_PLUGIN_IS_SYNTH | ||||
if (info.midiIns != 1 || info.audioOuts != 2) | if (info.midiIns != 1 || info.audioOuts != 2) | ||||
continue; | continue; | ||||
@@ -380,6 +392,7 @@ protected: | |||||
if (info.audioIns != 2 || info.audioOuts != 2) | if (info.audioIns != 2 || info.audioOuts != 2) | ||||
continue; | continue; | ||||
#endif | #endif | ||||
*/ | |||||
const char* const slash = std::strchr(info.label, DISTRHO_OS_SEP); | const char* const slash = std::strchr(info.label, DISTRHO_OS_SEP); | ||||
DISTRHO_SAFE_ASSERT_CONTINUE(slash != nullptr); | DISTRHO_SAFE_ASSERT_CONTINUE(slash != nullptr); | ||||
@@ -409,19 +422,6 @@ protected: | |||||
ImGui::End(); | ImGui::End(); | ||||
} | } | ||||
private: | |||||
void tryResizingToChildWindowContent() | |||||
{ | |||||
Size<uint> size(getChildWindowSize(fOurWindowId)); | |||||
if (size.isValid()) | |||||
{ | |||||
fInitialSizeHasBeenSet = true; | |||||
size.setHeight(size.getHeight() + kExtraHeight * getScaleFactor()); | |||||
setSize(size); | |||||
} | |||||
} | |||||
protected: | protected: | ||||
/* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
* DSP/Plugin Callbacks */ | * DSP/Plugin Callbacks */ | ||||
@@ -0,0 +1,200 @@ | |||||
/* | |||||
* DISTRHO Ildaeil Plugin | |||||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* This program is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU General Public License as | |||||
* published by the Free Software Foundation; either version 2 of | |||||
* the License, or any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* For a full copy of the GNU General Public License see the LICENSE file. | |||||
*/ | |||||
#include "src/DistrhoDefines.h" | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
# import <Cocoa/Cocoa.h> | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
# include <X11/Xlib.h> | |||||
# include <X11/Xutil.h> | |||||
#endif | |||||
#include "PluginHostWindow.hpp" | |||||
#ifdef DISTRHO_OS_MAC | |||||
@interface IldaeilPluginView : NSView | |||||
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize; | |||||
@end | |||||
@implementation IldaeilPluginView | |||||
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize | |||||
{ | |||||
[super resizeWithOldSuperviewSize:oldSize]; | |||||
} | |||||
@end | |||||
#endif | |||||
START_NAMESPACE_DGL | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
struct PluginHostWindow::PrivateData | |||||
{ | |||||
Window& parentWindow; | |||||
const uintptr_t parentWindowId; | |||||
Callbacks* const pluginWindowCallbacks; | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
IldaeilPluginView* view; | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
bool lookingForChildren; | |||||
PrivateData(Window& pw, Callbacks* const cbs) | |||||
: parentWindow(pw), | |||||
parentWindowId(pw.getNativeWindowHandle()), | |||||
pluginWindowCallbacks(cbs), | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
view(nullptr), | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
lookingForChildren(false) | |||||
{ | |||||
view = [[IldaeilPluginView new]retain]; | |||||
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr,) | |||||
[view setAutoresizingMask:NSViewNotSizable]; | |||||
[view setAutoresizesSubviews:YES]; | |||||
[view setHidden:YES]; | |||||
[(NSView*)parentWindowId addSubview:view]; | |||||
} | |||||
~PrivateData() | |||||
{ | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
if (view != nullptr) | |||||
{ | |||||
[view release]; | |||||
view = nullptr; | |||||
} | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
} | |||||
void* attachAndGetWindowHandle() | |||||
{ | |||||
lookingForChildren = true; | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
return view; | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
} | |||||
void detach() | |||||
{ | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
if (view != nullptr) | |||||
[view setHidden:YES]; | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
} | |||||
void idle() | |||||
{ | |||||
if (lookingForChildren) | |||||
{ | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
if (view == nullptr) | |||||
return; | |||||
for (NSView* subview in [view subviews]) | |||||
{ | |||||
const double scaleFactor = [[[view window] screen] backingScaleFactor]; | |||||
const NSSize size = [subview frame].size; | |||||
const double width = size.width; | |||||
const double height = size.height; | |||||
d_stdout("found subview %f %f", width, height); | |||||
if (width <= 1 || height <= 1) | |||||
break; | |||||
lookingForChildren = false; | |||||
[view setFrameSize:size]; | |||||
[view setHidden:NO]; | |||||
[view setNeedsDisplay:YES]; | |||||
pluginWindowCallbacks->pluginWindowResized(width * scaleFactor, height * scaleFactor); | |||||
break; | |||||
} | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
} | |||||
} | |||||
void setPositionAndSize(const uint x, const uint y, const uint width, const uint height) | |||||
{ | |||||
#if defined(DISTRHO_OS_HAIKU) | |||||
#elif defined(DISTRHO_OS_MAC) | |||||
if (view != nullptr) | |||||
{ | |||||
const double scaleFactor = [[[view window] screen] backingScaleFactor]; | |||||
[view setFrame:NSMakeRect(x / scaleFactor, y / scaleFactor, width / scaleFactor, height / scaleFactor)]; | |||||
} | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
#else | |||||
#endif | |||||
} | |||||
}; | |||||
PluginHostWindow::PluginHostWindow(Window& parentWindow, Callbacks* const cbs) | |||||
: pData(new PrivateData(parentWindow, cbs)) {} | |||||
PluginHostWindow::~PluginHostWindow() | |||||
{ | |||||
delete pData; | |||||
} | |||||
void* PluginHostWindow::attachAndGetWindowHandle() | |||||
{ | |||||
return pData->attachAndGetWindowHandle(); | |||||
} | |||||
void PluginHostWindow::detach() | |||||
{ | |||||
pData->detach(); | |||||
} | |||||
void PluginHostWindow::idle() | |||||
{ | |||||
pData->idle(); | |||||
} | |||||
void PluginHostWindow::setPositionAndSize(const uint x, const uint y, const uint width, const uint height) | |||||
{ | |||||
pData->setPositionAndSize(x, y, width, height); | |||||
} | |||||
END_NAMESPACE_DGL |
@@ -0,0 +1,42 @@ | |||||
/* | |||||
* DISTRHO Ildaeil Plugin | |||||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* This program is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU General Public License as | |||||
* published by the Free Software Foundation; either version 2 of | |||||
* the License, or any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* For a full copy of the GNU General Public License see the LICENSE file. | |||||
*/ | |||||
#include "Window.hpp" | |||||
START_NAMESPACE_DGL | |||||
class PluginHostWindow | |||||
{ | |||||
struct PrivateData; | |||||
PrivateData* const pData; | |||||
public: | |||||
struct Callbacks { | |||||
virtual ~Callbacks() {} | |||||
virtual void pluginWindowResized(uint width, uint height) = 0; | |||||
}; | |||||
explicit PluginHostWindow(Window& parentWindow, Callbacks* cbs); | |||||
~PluginHostWindow(); | |||||
void* attachAndGetWindowHandle(); | |||||
void detach(); | |||||
void idle(); | |||||
void setPositionAndSize(uint x, uint y, uint width, uint height); | |||||
}; | |||||
END_NAMESPACE_DGL |
@@ -56,12 +56,14 @@ Size<uint> getChildWindowSize(const uintptr_t winId) | |||||
{ | { | ||||
#if defined(DISTRHO_OS_HAIKU) | #if defined(DISTRHO_OS_HAIKU) | ||||
#elif defined(DISTRHO_OS_MAC) | #elif defined(DISTRHO_OS_MAC) | ||||
/* | |||||
for (NSView* subview in [(NSView*)winId subviews]) | for (NSView* subview in [(NSView*)winId subviews]) | ||||
{ | { | ||||
// [subview setFrame:NSMakeRect(0, 0, width, height)]; | // [subview setFrame:NSMakeRect(0, 0, width, height)]; | ||||
d_stdout("found subview"); | d_stdout("found subview"); | ||||
return Size<uint>(subview.frame.size.width, subview.frame.size.height); | return Size<uint>(subview.frame.size.width, subview.frame.size.height); | ||||
} | } | ||||
*/ | |||||
#elif defined(DISTRHO_OS_WINDOWS) | #elif defined(DISTRHO_OS_WINDOWS) | ||||
#else | #else | ||||
if (::Display* const display = XOpenDisplay(nullptr)) | if (::Display* const display = XOpenDisplay(nullptr)) | ||||
@@ -17,6 +17,7 @@ FILES_DSP = \ | |||||
FILES_UI = \ | FILES_UI = \ | ||||
IldaeilUI.cpp \ | IldaeilUI.cpp \ | ||||
../Common/PluginHostWindow.cpp \ | |||||
../Common/SizeUtils.cpp \ | ../Common/SizeUtils.cpp \ | ||||
../../dpf-widgets/opengl/DearImGui.cpp | ../../dpf-widgets/opengl/DearImGui.cpp | ||||
@@ -65,6 +66,7 @@ BUILD_CXX_FLAGS += -I../../carla/source/backend | |||||
BUILD_CXX_FLAGS += -I../../carla/source/includes | BUILD_CXX_FLAGS += -I../../carla/source/includes | ||||
ifeq ($(MACOS),true) | ifeq ($(MACOS),true) | ||||
$(BUILD_DIR)/../Common/PluginHostWindow.cpp.o: BUILD_CXX_FLAGS += -ObjC++ | |||||
$(BUILD_DIR)/../Common/SizeUtils.cpp.o: BUILD_CXX_FLAGS += -ObjC++ | $(BUILD_DIR)/../Common/SizeUtils.cpp.o: BUILD_CXX_FLAGS += -ObjC++ | ||||
LINK_FLAGS += -framework AppKit | LINK_FLAGS += -framework AppKit | ||||
LINK_FLAGS += -framework Accelerate | LINK_FLAGS += -framework Accelerate | ||||