Signed-off-by: falkTX <falktx@falktx.com>tags/v1.0
@@ -0,0 +1,3 @@ | |||
/bin/ | |||
/build/ | |||
.kdev4/ |
@@ -0,0 +1,5 @@ | |||
../../dpf/dgl/ | |||
../../dpf/distrho/ | |||
../../dpf-widgets/generic | |||
../../dpf-widgets/opengl | |||
/usr/include/carla |
@@ -15,22 +15,110 @@ | |||
* For a full copy of the GNU General Public License see the LICENSE file. | |||
*/ | |||
#include "CarlaNativePlugin.h" | |||
#include "DistrhoPlugin.hpp" | |||
#include "DistrhoUI.hpp" | |||
START_NAMESPACE_DISTRHO | |||
// ----------------------------------------------------------------------------------------------------------- | |||
static uint32_t host_get_buffer_size(NativeHostHandle); | |||
static double host_get_sample_rate(NativeHostHandle); | |||
static bool host_is_offline(NativeHostHandle); | |||
static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle); | |||
static bool host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event); | |||
static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt); | |||
// ----------------------------------------------------------------------------------------------------------- | |||
class IldaeilPlugin : public Plugin | |||
{ | |||
const NativePluginDescriptor* fCarlaPluginDescriptor; | |||
NativePluginHandle fCarlaPluginHandle; | |||
NativeHostDescriptor fCarlaHostDescriptor; | |||
CarlaHostHandle fCarlaHostHandle; | |||
NativeTimeInfo fCarlaTimeInfo; | |||
UI* fUI; | |||
public: | |||
IldaeilPlugin() | |||
: Plugin(0, 0, 0) | |||
: Plugin(0, 0, 0), | |||
fCarlaPluginDescriptor(nullptr), | |||
fCarlaPluginHandle(nullptr), | |||
fCarlaHostHandle(nullptr), | |||
fUI(nullptr) | |||
{ | |||
fCarlaPluginDescriptor = carla_get_native_rack_plugin(); | |||
DISTRHO_SAFE_ASSERT_RETURN(fCarlaPluginDescriptor != nullptr,); | |||
memset(&fCarlaHostDescriptor, 0, sizeof(fCarlaHostDescriptor)); | |||
memset(&fCarlaTimeInfo, 0, sizeof(fCarlaTimeInfo)); | |||
fCarlaHostDescriptor.handle = this; | |||
fCarlaHostDescriptor.resourceDir = carla_get_library_folder(); | |||
fCarlaHostDescriptor.uiName = "Ildaeil"; | |||
fCarlaHostDescriptor.uiParentId = 0; | |||
fCarlaHostDescriptor.get_buffer_size = host_get_buffer_size; | |||
fCarlaHostDescriptor.get_sample_rate = host_get_sample_rate; | |||
fCarlaHostDescriptor.is_offline = host_is_offline; | |||
fCarlaHostDescriptor.get_time_info = host_get_time_info; | |||
fCarlaHostDescriptor.write_midi_event = host_write_midi_event; | |||
fCarlaHostDescriptor.ui_parameter_changed = nullptr; | |||
fCarlaHostDescriptor.ui_midi_program_changed = nullptr; | |||
fCarlaHostDescriptor.ui_custom_data_changed = nullptr; | |||
fCarlaHostDescriptor.ui_closed = nullptr; | |||
fCarlaHostDescriptor.ui_open_file = nullptr; | |||
fCarlaHostDescriptor.ui_save_file = nullptr; | |||
fCarlaHostDescriptor.dispatcher = host_dispatcher; | |||
fCarlaPluginHandle = fCarlaPluginDescriptor->instantiate(&fCarlaHostDescriptor); | |||
DISTRHO_SAFE_ASSERT_RETURN(fCarlaPluginHandle != nullptr,); | |||
fCarlaHostHandle = carla_create_native_plugin_host_handle(fCarlaPluginDescriptor, fCarlaPluginHandle); | |||
} | |||
~IldaeilPlugin() override | |||
{ | |||
if (fCarlaHostHandle != nullptr) | |||
{ | |||
carla_host_handle_free(fCarlaHostHandle); | |||
} | |||
if (fCarlaPluginHandle != nullptr) | |||
fCarlaPluginDescriptor->cleanup(fCarlaPluginHandle); | |||
} | |||
const NativeTimeInfo* getTimeInfo() | |||
{ | |||
const TimePosition& timePos(getTimePosition()); | |||
fCarlaTimeInfo.playing = timePos.playing; | |||
fCarlaTimeInfo.frame = timePos.frame; | |||
fCarlaTimeInfo.bbt.valid = timePos.bbt.valid; | |||
fCarlaTimeInfo.bbt.bar = timePos.bbt.bar; | |||
fCarlaTimeInfo.bbt.beat = timePos.bbt.beat; | |||
fCarlaTimeInfo.bbt.tick = timePos.bbt.tick; | |||
fCarlaTimeInfo.bbt.barStartTick = timePos.bbt.barStartTick; | |||
fCarlaTimeInfo.bbt.beatsPerBar = timePos.bbt.beatsPerBar; | |||
fCarlaTimeInfo.bbt.beatType = timePos.bbt.beatType; | |||
fCarlaTimeInfo.bbt.ticksPerBeat = timePos.bbt.ticksPerBeat; | |||
fCarlaTimeInfo.bbt.beatsPerMinute = timePos.bbt.beatsPerMinute; | |||
return &fCarlaTimeInfo; | |||
} | |||
void resizeUI(const uint width, const uint height) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
fUI->setSize(width, height); | |||
} | |||
protected: | |||
@@ -43,7 +131,13 @@ protected: | |||
*/ | |||
const char* getLabel() const override | |||
{ | |||
return "Ildaeil"; | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
return "IldaeilSynth"; | |||
#elif DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
return "IldaeilMIDI"; | |||
#else | |||
return "IldaeilFX"; | |||
#endif | |||
} | |||
/** | |||
@@ -51,7 +145,7 @@ protected: | |||
*/ | |||
const char* getDescription() const override | |||
{ | |||
return "..."; | |||
return "Ildaeil is a mini-plugin host working as a plugin, allowing one-to-one plugin format reusage."; | |||
} | |||
/** | |||
@@ -111,17 +205,29 @@ protected: | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* Process */ | |||
/** | |||
Run/process function for plugins without MIDI input. | |||
*/ | |||
void run(const float** inputs, float** outputs, uint32_t frames) override | |||
void activate() override | |||
{ | |||
if (fCarlaPluginHandle != nullptr) | |||
fCarlaPluginDescriptor->activate(fCarlaPluginHandle); | |||
} | |||
void deactivate() override | |||
{ | |||
// copy inputs over outputs if needed | |||
if (outputs[0] != inputs[0]) | |||
std::memcpy(outputs[0], inputs[0], sizeof(float)*frames); | |||
if (fCarlaPluginHandle != nullptr) | |||
fCarlaPluginDescriptor->deactivate(fCarlaPluginHandle); | |||
} | |||
if (outputs[1] != inputs[1]) | |||
std::memcpy(outputs[1], inputs[1], sizeof(float)*frames); | |||
void run(const float** inputs, float** outputs, uint32_t frames) override | |||
{ | |||
if (fCarlaPluginHandle != nullptr) | |||
{ | |||
fCarlaPluginDescriptor->process(fCarlaPluginHandle, (float**)inputs, outputs, frames, nullptr, 0); | |||
} | |||
else | |||
{ | |||
std::memset(outputs[0], 0, sizeof(float)*frames); | |||
std::memset(outputs[1], 0, sizeof(float)*frames); | |||
} | |||
} | |||
// ------------------------------------------------------------------------------------------------------- | |||
@@ -133,6 +239,48 @@ private: | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(IldaeilPlugin) | |||
}; | |||
// ----------------------------------------------------------------------------------------------------------- | |||
static uint32_t host_get_buffer_size(const NativeHostHandle handle) | |||
{ | |||
return static_cast<IldaeilPlugin*>(handle)->getBufferSize(); | |||
} | |||
static double host_get_sample_rate(const NativeHostHandle handle) | |||
{ | |||
return static_cast<IldaeilPlugin*>(handle)->getSampleRate(); | |||
} | |||
static bool host_is_offline(NativeHostHandle) | |||
{ | |||
return false; | |||
} | |||
static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle) | |||
{ | |||
return static_cast<IldaeilPlugin*>(handle)->getTimeInfo(); | |||
} | |||
static bool host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event) | |||
{ | |||
return false; | |||
} | |||
static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, | |||
int32_t index, intptr_t value, void* ptr, float opt) | |||
{ | |||
switch (opcode) | |||
{ | |||
case NATIVE_HOST_OPCODE_UI_RESIZE: | |||
static_cast<IldaeilPlugin*>(handle)->resizeUI(index, value); | |||
break; | |||
default: | |||
break; | |||
} | |||
return 0; | |||
} | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Plugin entry point, called by DPF to create a new plugin instance. */ | |||
@@ -15,32 +15,105 @@ | |||
* For a full copy of the GNU General Public License see the LICENSE file. | |||
*/ | |||
#include "CarlaNativePlugin.h" | |||
#include <X11/Xlib.h> | |||
#include <X11/Xutil.h> | |||
#include "../FX/DistrhoPluginInfo.h" | |||
#include "DistrhoUI.hpp" | |||
#include "DistrhoPlugin.hpp" | |||
#include "ResizeHandle.hpp" | |||
START_NAMESPACE_DISTRHO | |||
class IldaeilPlugin : public Plugin | |||
{ | |||
public: | |||
const NativePluginDescriptor* fCarlaPluginDescriptor; | |||
NativePluginHandle fCarlaPluginHandle; | |||
NativeHostDescriptor fCarlaHostDescriptor; | |||
CarlaHostHandle fCarlaHostHandle; | |||
UI* fUI; | |||
// ... | |||
}; | |||
// ----------------------------------------------------------------------------------------------------------- | |||
// shared resource pointer | |||
// carla_juce_init(); | |||
class IldaeilUI : public UI | |||
{ | |||
void* fContext; | |||
ResizeHandle fResizeHandle; | |||
IldaeilPlugin* const fPlugin; | |||
// ResizeHandle fResizeHandle; | |||
uint fPluginCount; | |||
uint fPluginSelected; | |||
::Window fHostWindowLookingToResize; | |||
public: | |||
IldaeilUI() | |||
: UI(1280, 720), | |||
fContext(getPluginInstancePointer()), | |||
fResizeHandle(this) | |||
fPlugin((IldaeilPlugin*)getPluginInstancePointer()), | |||
// fResizeHandle(this), | |||
fPluginCount(0), | |||
fPluginSelected(0), | |||
fHostWindowLookingToResize(0) | |||
{ | |||
using namespace CarlaBackend; | |||
if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) | |||
return; | |||
const CarlaHostHandle handle = fPlugin->fCarlaHostHandle; | |||
if (carla_get_current_plugin_count(handle) != 0) | |||
{ | |||
const CarlaPluginInfo* const info = carla_get_plugin_info(handle, 0); | |||
if (info->hints & PLUGIN_HAS_CUSTOM_UI) // FIXME use PLUGIN_HAS_CUSTOM_EMBED_UI | |||
{ | |||
const uintptr_t winId = getWindow().getNativeWindowHandle(); | |||
carla_embed_custom_ui(handle, 0, (void*)winId); | |||
fHostWindowLookingToResize = (::Window)winId; | |||
tryResizingToChildWindowContent(); | |||
} | |||
} | |||
// start cache/lookup, maybe spawn thread for this? | |||
fPluginCount = carla_get_cached_plugin_count(PLUGIN_LV2, nullptr); | |||
for (uint i=0; i<fPluginCount; ++i) | |||
carla_get_cached_plugin_info(PLUGIN_LV2, i); | |||
} | |||
~IldaeilUI() override | |||
{ | |||
if (fPlugin != nullptr) | |||
{ | |||
fPlugin->fUI = nullptr; | |||
if (fPlugin->fCarlaHostHandle != nullptr) | |||
carla_show_custom_ui(fPlugin->fCarlaHostHandle, 0, false); | |||
} | |||
} | |||
void onImGuiDisplay() override | |||
{ | |||
if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) | |||
return; | |||
const CarlaHostHandle handle = fPlugin->fCarlaHostHandle; | |||
if (carla_get_current_plugin_count(handle) != 0) | |||
return; | |||
float width = getWidth(); | |||
float height = getHeight(); | |||
float margin = 20.0f; | |||
@@ -48,8 +121,99 @@ public: | |||
ImGui::SetNextWindowPos(ImVec2(margin, margin)); | |||
ImGui::SetNextWindowSize(ImVec2(width - 2 * margin, height - 2 * margin)); | |||
if (ImGui::Begin("Plugin List")) | |||
if (ImGui::Begin("Plugin List", nullptr, ImGuiWindowFlags_NoResize)) | |||
{ | |||
static char searchBuf[0xff] = "Search..."; | |||
ImGui::InputText("", searchBuf, sizeof(searchBuf)-1, ImGuiInputTextFlags_CharsNoBlank|ImGuiInputTextFlags_AutoSelectAll); | |||
using namespace CarlaBackend; | |||
if (ImGui::Button("Load Plugin")) | |||
{ | |||
do { | |||
const CarlaCachedPluginInfo* info = carla_get_cached_plugin_info(PLUGIN_LV2, fPluginSelected); | |||
DISTRHO_SAFE_ASSERT_BREAK(info != nullptr); | |||
const char* const slash = std::strchr(info->label, DISTRHO_OS_SEP); | |||
DISTRHO_SAFE_ASSERT_BREAK(slash != nullptr); | |||
d_stdout("Loading %s...", info->name); | |||
if (carla_add_plugin(handle, BINARY_NATIVE, PLUGIN_LV2, nullptr, nullptr, | |||
slash+1, 0, 0x0, PLUGIN_OPTIONS_NULL)) | |||
{ | |||
const CarlaPluginInfo* const info = carla_get_plugin_info(handle, 0); | |||
if (info->hints & PLUGIN_HAS_CUSTOM_UI) // FIXME use PLUGIN_HAS_CUSTOM_EMBED_UI | |||
{ | |||
const uintptr_t winId = getWindow().getNativeWindowHandle(); | |||
carla_embed_custom_ui(handle, 0, (void*)winId); | |||
fHostWindowLookingToResize = (::Window)winId; | |||
tryResizingToChildWindowContent(); | |||
} | |||
repaint(); | |||
} | |||
} while (false); | |||
} | |||
if (ImGui::BeginChild("pluginlistwindow")) | |||
{ | |||
if (ImGui::BeginTable("pluginlist", 3, ImGuiTableFlags_NoSavedSettings|ImGuiTableFlags_NoClip)) | |||
{ | |||
ImGui::TableSetupColumn("Name"); | |||
ImGui::TableSetupColumn("Bundle"); | |||
ImGui::TableSetupColumn("URI"); | |||
ImGui::TableHeadersRow(); | |||
const char* const search = searchBuf[0] != 0 && std::strcmp(searchBuf, "Search...") != 0 ? searchBuf : nullptr; | |||
if (fPluginCount != 0) | |||
{ | |||
for (uint i=0; i<fPluginCount; ++i) | |||
{ | |||
const CarlaCachedPluginInfo* info = carla_get_cached_plugin_info(PLUGIN_LV2, i); | |||
DISTRHO_SAFE_ASSERT_CONTINUE(info != nullptr); | |||
#if DISTRHO_PLUGIN_IS_SYNTH | |||
if (info->midiIns != 1 || info->audioOuts != 2) | |||
continue; | |||
#elif DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
if (info->midiIns != 1 || info->midiOuts != 1) | |||
continue; | |||
if (info->audioIns != 0 || info->audioOuts != 0) | |||
continue; | |||
#else | |||
if (info->audioIns != 2 || info->audioOuts != 2) | |||
continue; | |||
#endif | |||
const char* const slash = std::strchr(info->label, DISTRHO_OS_SEP); | |||
DISTRHO_SAFE_ASSERT_CONTINUE(slash != nullptr); | |||
if (search != nullptr && strcasestr(info->name, search) == nullptr) | |||
continue; | |||
bool selected = fPluginSelected == i; | |||
ImGui::TableNextRow(); | |||
ImGui::TableSetColumnIndex(0); | |||
ImGui::Selectable(info->name, &selected); | |||
ImGui::TableSetColumnIndex(1); | |||
ImGui::Selectable(slash+1, &selected); | |||
ImGui::TableSetColumnIndex(2); | |||
ImGui::TextUnformatted(info->label, slash); | |||
if (selected) | |||
fPluginSelected = i; | |||
} | |||
} | |||
ImGui::EndTable(); | |||
} | |||
ImGui::EndChild(); | |||
} | |||
} | |||
ImGui::End(); | |||
@@ -57,6 +221,80 @@ public: | |||
void uiIdle() override | |||
{ | |||
if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) | |||
return; | |||
fPlugin->fCarlaPluginDescriptor->ui_idle(fPlugin->fCarlaPluginHandle); | |||
if (fHostWindowLookingToResize == 0) | |||
return; | |||
tryResizingToChildWindowContent(); | |||
} | |||
private: | |||
void tryResizingToChildWindowContent() | |||
{ | |||
if (::Display* const display = XOpenDisplay(nullptr)) | |||
{ | |||
if (const ::Window childWindow = getChildWindow(display, fHostWindowLookingToResize)) | |||
{ | |||
d_stdout("found child window"); | |||
XSizeHints sizeHints; | |||
memset(&sizeHints, 0, sizeof(sizeHints)); | |||
if (XGetNormalHints(display, childWindow, &sizeHints)) | |||
{ | |||
int width = 0; | |||
int height = 0; | |||
if (sizeHints.flags & PSize) | |||
{ | |||
width = sizeHints.width; | |||
height = sizeHints.height; | |||
} | |||
else if (sizeHints.flags & PBaseSize) | |||
{ | |||
width = sizeHints.base_width; | |||
height = sizeHints.base_height; | |||
} | |||
else if (sizeHints.flags & PMinSize) | |||
{ | |||
width = sizeHints.min_width; | |||
height = sizeHints.min_height; | |||
} | |||
d_stdout("child window bounds %u %u", width, height); | |||
if (width > 1 && height > 1) | |||
{ | |||
fHostWindowLookingToResize = 0; | |||
setSize(static_cast<uint>(width), static_cast<uint>(height)); | |||
} | |||
} | |||
else | |||
d_stdout("child window without bounds"); | |||
} | |||
XCloseDisplay(display); | |||
} | |||
} | |||
::Window getChildWindow(::Display* const display, const ::Window hostWindow) const | |||
{ | |||
::Window rootWindow, parentWindow, ret = 0; | |||
::Window* childWindows = nullptr; | |||
uint numChildren = 0; | |||
XQueryTree(display, hostWindow, &rootWindow, &parentWindow, &childWindows, &numChildren); | |||
if (numChildren > 0 && childWindows != nullptr) | |||
{ | |||
ret = childWindows[0]; | |||
XFree(childWindows); | |||
} | |||
return ret; | |||
} | |||
protected: | |||
@@ -1,185 +0,0 @@ | |||
/* | |||
* Resize handle for DPF | |||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* 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 | |||
#include "TopLevelWidget.hpp" | |||
#include "../dgl/Color.hpp" | |||
START_NAMESPACE_DGL | |||
/** Resize handle for DPF windows, will sit on bottom-right. */ | |||
class ResizeHandle : public TopLevelWidget | |||
{ | |||
public: | |||
/** Constructor for placing this handle on top of a window. */ | |||
explicit ResizeHandle(Window& window) | |||
: TopLevelWidget(window), | |||
handleSize(16), | |||
resizing(false) | |||
{ | |||
resetArea(); | |||
} | |||
/** Overloaded constructor, will fetch the window from an existing top-level widget. */ | |||
explicit ResizeHandle(TopLevelWidget* const tlw) | |||
: TopLevelWidget(tlw->getWindow()), | |||
handleSize(16), | |||
resizing(false) | |||
{ | |||
resetArea(); | |||
} | |||
/** Set the handle size, minimum 16. */ | |||
void setHandleSize(const uint size) | |||
{ | |||
handleSize = std::max(16u, size); | |||
resetArea(); | |||
} | |||
protected: | |||
void onDisplay() override | |||
{ | |||
const GraphicsContext& context(getGraphicsContext()); | |||
const double lineWidth = 1.0 * getScaleFactor(); | |||
#ifdef DGL_OPENGL | |||
// glUseProgram(0); | |||
glMatrixMode(GL_MODELVIEW); | |||
#endif | |||
// draw white lines, 1px wide | |||
Color(1.0f, 1.0f, 1.0f).setFor(context); | |||
l1.draw(context, lineWidth); | |||
l2.draw(context, lineWidth); | |||
l3.draw(context, lineWidth); | |||
// draw black lines, offset by 1px and 1px wide | |||
Color(0.0f, 0.0f, 0.0f).setFor(context); | |||
Line<double> l1b(l1), l2b(l2), l3b(l3); | |||
l1b.moveBy(lineWidth, lineWidth); | |||
l2b.moveBy(lineWidth, lineWidth); | |||
l3b.moveBy(lineWidth, lineWidth); | |||
l1b.draw(context, lineWidth); | |||
l2b.draw(context, lineWidth); | |||
l3b.draw(context, lineWidth); | |||
} | |||
bool onMouse(const MouseEvent& ev) override | |||
{ | |||
if (ev.button != 1) | |||
return false; | |||
if (ev.press && area.contains(ev.pos)) | |||
{ | |||
resizing = true; | |||
resizingSize = Size<double>(getWidth(), getHeight()); | |||
lastResizePoint = ev.pos; | |||
return true; | |||
} | |||
if (resizing && ! ev.press) | |||
{ | |||
resizing = false; | |||
return true; | |||
} | |||
return false; | |||
} | |||
bool onMotion(const MotionEvent& ev) override | |||
{ | |||
if (! resizing) | |||
return false; | |||
const Size<double> offset(ev.pos.getX() - lastResizePoint.getX(), | |||
ev.pos.getY() - lastResizePoint.getY()); | |||
resizingSize += offset; | |||
lastResizePoint = ev.pos; | |||
// TODO min width, min height | |||
const uint minWidth = 16; | |||
const uint minHeight = 16; | |||
if (resizingSize.getWidth() < minWidth) | |||
resizingSize.setWidth(minWidth); | |||
if (resizingSize.getWidth() > 16384) | |||
resizingSize.setWidth(16384); | |||
if (resizingSize.getHeight() < minHeight) | |||
resizingSize.setHeight(minHeight); | |||
if (resizingSize.getHeight() > 16384) | |||
resizingSize.setHeight(16384); | |||
setSize(resizingSize.getWidth(), resizingSize.getHeight()); | |||
return true; | |||
} | |||
void onResize(const ResizeEvent& ev) override | |||
{ | |||
TopLevelWidget::onResize(ev); | |||
resetArea(); | |||
} | |||
private: | |||
Rectangle<uint> area; | |||
Line<double> l1, l2, l3; | |||
uint handleSize; | |||
// event handling state | |||
bool resizing; | |||
Point<double> lastResizePoint; | |||
Size<double> resizingSize; | |||
void resetArea() | |||
{ | |||
const double scaleFactor = getScaleFactor(); | |||
const uint margin = 0.0 * scaleFactor; | |||
const uint size = handleSize * scaleFactor; | |||
area = Rectangle<uint>(getWidth() - size - margin, | |||
getHeight() - size - margin, | |||
size, size); | |||
recreateLines(area.getX(), area.getY(), size); | |||
} | |||
void recreateLines(const uint x, const uint y, const uint size) | |||
{ | |||
uint linesize = size; | |||
uint offset = 0; | |||
// 1st line, full diagonal size | |||
l1.setStartPos(x + size, y); | |||
l1.setEndPos(x, y + size); | |||
// 2nd line, bit more to the right and down, cropped | |||
offset += size / 3; | |||
linesize -= size / 3; | |||
l2.setStartPos(x + linesize + offset, y + offset); | |||
l2.setEndPos(x + offset, y + linesize + offset); | |||
// 3rd line, even more right and down | |||
offset += size / 3; | |||
linesize -= size / 3; | |||
l3.setStartPos(x + linesize + offset, y + offset); | |||
l3.setEndPos(x + offset, y + linesize + offset); | |||
} | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ResizeHandle) | |||
}; | |||
END_NAMESPACE_DGL |
@@ -0,0 +1,6 @@ | |||
../Common/ | |||
../../dpf/dgl/ | |||
../../dpf/distrho/ | |||
../../dpf-widgets/generic | |||
../../dpf-widgets/opengl | |||
/usr/include/carla |
@@ -30,7 +30,7 @@ | |||
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 0 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0 | |||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
#define DISTRHO_UI_USE_CUSTOM 1 | |||
#define DISTRHO_UI_USER_RESIZABLE 0 | |||
#define DISTRHO_UI_CUSTOM_INCLUDE_PATH "DearImGui.hpp" | |||
@@ -25,8 +25,12 @@ FILES_UI = \ | |||
include ../../dpf/Makefile.plugins.mk | |||
BUILD_CXX_FLAGS += -I../Common | |||
BUILD_CXX_FLAGS += -I../../dpf-widgets/generic | |||
BUILD_CXX_FLAGS += -I../../dpf-widgets/opengl | |||
BUILD_CXX_FLAGS += $(shell pkg-config --cflags carla-host-plugin carla-native-plugin carla-utils) | |||
LINK_FLAGS += $(shell pkg-config --libs carla-host-plugin carla-native-plugin carla-utils) | |||
# -------------------------------------------------------------- | |||
# Enable all possible plugin types | |||
@@ -29,7 +29,7 @@ | |||
#define DISTRHO_PLUGIN_WANT_LATENCY 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1 | |||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
#define DISTRHO_UI_USE_CUSTOM 1 | |||
#define DISTRHO_UI_USER_RESIZABLE 0 | |||
@@ -29,7 +29,7 @@ | |||
#define DISTRHO_PLUGIN_WANT_LATENCY 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0 | |||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
#define DISTRHO_UI_USE_CUSTOM 1 | |||
#define DISTRHO_UI_USER_RESIZABLE 0 | |||