Signed-off-by: falkTX <falktx@falktx.com>tags/v2.2.0-RC1
@@ -1858,6 +1858,10 @@ public: | |||
0, 0, 0, 0.0f, nullptr); | |||
} | |||
} | |||
else | |||
{ | |||
fInlineDisplayNeedsRedraw = false; | |||
} | |||
} | |||
CarlaPlugin::idle(); | |||
@@ -996,6 +996,10 @@ public: | |||
0, 0, 0, 0.0f, nullptr); | |||
} | |||
} | |||
else | |||
{ | |||
fInlineDisplayNeedsRedraw = false; | |||
} | |||
} | |||
CarlaPlugin::idle(); | |||
@@ -915,6 +915,7 @@ class HostWindow(QMainWindow): | |||
return True | |||
def engineStopFinal(self): | |||
patchcanvas.handleAllPluginsRemoved() | |||
self.killTimers() | |||
if self.host.is_engine_running(): | |||
@@ -2719,6 +2720,8 @@ class HostWindow(QMainWindow): | |||
event.ignore() | |||
return | |||
patchcanvas.handleAllPluginsRemoved() | |||
if MACOS and self.fMacClosingHelper and not (self.host.isControl or self.host.isPlugin): | |||
self.fCustomStopAction = self.CUSTOM_ACTION_APP_CLOSE | |||
self.fMacClosingHelper = False | |||
@@ -113,6 +113,7 @@ class CanvasBox(QGraphicsObject): | |||
self.m_inline_data = None | |||
self.m_inline_image = None | |||
self.m_inline_scaling = 1.0 | |||
self.m_inline_first = True | |||
self.m_will_signal_pos_change = False | |||
self.m_port_list_ids = [] | |||
@@ -196,7 +197,7 @@ class CanvasBox(QGraphicsObject): | |||
self.m_plugin_id = -1 | |||
self.m_plugin_ui = False | |||
#self.m_plugin_inline = self.INLINE_DISPLAY_DISABLED | |||
self.m_plugin_inline = self.INLINE_DISPLAY_DISABLED | |||
def setAsPlugin(self, plugin_id, hasUI, hasInlineDisplay): | |||
if hasInlineDisplay and not options.inline_displays: | |||
@@ -317,7 +318,7 @@ class CanvasBox(QGraphicsObject): | |||
# Check Text Name size | |||
app_name_size = QFontMetrics(self.m_font_name).width(self.m_group_name) + 30 | |||
self.p_width = max(200 if self.m_plugin_inline != self.INLINE_DISPLAY_DISABLED else 50, app_name_size) | |||
self.p_width = max(50, app_name_size) | |||
# Get Port List | |||
port_list = [] | |||
@@ -363,33 +364,38 @@ class CanvasBox(QGraphicsObject): | |||
port.widget.setY(last_out_pos) | |||
last_out_pos += port_spacing | |||
self.p_width = max(self.p_width, (100 if self.m_plugin_inline != self.INLINE_DISPLAY_DISABLED else 30) + max_in_width + max_out_width) | |||
self.p_width_in = max_in_width | |||
self.p_width = max(self.p_width, 30 + max_in_width + max_out_width) | |||
self.p_width_in = max_in_width | |||
self.p_width_out = max_out_width | |||
#if self.m_plugin_inline: | |||
#self.p_width += 10 | |||
# Horizontal ports re-positioning | |||
inX = canvas.theme.port_offset | |||
outX = self.p_width - max_out_width - canvas.theme.port_offset - 12 | |||
for port_type in port_types: | |||
for port in port_list: | |||
if port.port_mode == PORT_MODE_INPUT: | |||
port.widget.setX(inX) | |||
port.widget.setPortWidth(max_in_width) | |||
elif port.port_mode == PORT_MODE_OUTPUT: | |||
port.widget.setX(outX) | |||
port.widget.setPortWidth(max_out_width) | |||
self.p_height = max(last_in_pos, last_out_pos) | |||
self.p_height = max(last_in_pos, last_out_pos) | |||
self.p_height += max(canvas.theme.port_spacing, canvas.theme.port_spacingT) - canvas.theme.port_spacing | |||
self.p_height += canvas.theme.box_pen.widthF() | |||
self.p_height += canvas.theme.box_pen.width() | |||
self.repositionPorts(port_list) | |||
self.repaintLines(True) | |||
self.update() | |||
def repositionPorts(self, port_list = None): | |||
if port_list is None: | |||
port_list = [] | |||
for port in canvas.port_list: | |||
if port.group_id == self.m_group_id and port.port_id in self.m_port_list_ids: | |||
port_list.append(port) | |||
# Horizontal ports re-positioning | |||
inX = canvas.theme.port_offset | |||
outX = self.p_width - self.p_width_out - canvas.theme.port_offset - 12 | |||
for port in port_list: | |||
if port.port_mode == PORT_MODE_INPUT: | |||
port.widget.setX(inX) | |||
port.widget.setPortWidth(self.p_width_in) | |||
elif port.port_mode == PORT_MODE_OUTPUT: | |||
port.widget.setX(outX) | |||
port.widget.setPortWidth(self.p_width_out) | |||
def repaintLines(self, forced=False): | |||
if self.pos() != self.m_last_pos or forced: | |||
for connection in self.m_connection_lines: | |||
@@ -736,24 +742,39 @@ class CanvasBox(QGraphicsObject): | |||
if not options.inline_displays: | |||
return | |||
inwidth = self.p_width - self.p_width_in - self.p_width_out - 16 | |||
inheight = self.p_height - canvas.theme.box_header_height - canvas.theme.box_header_spacing - canvas.theme.port_spacing - 3 | |||
inwidth = self.p_width - 16 - self.p_width_in - self.p_width_out | |||
inheight = self.p_height - 3 - canvas.theme.box_header_height - canvas.theme.box_header_spacing - canvas.theme.port_spacing | |||
scaling = canvas.scene.getScaleFactor() * canvas.scene.getDevicePixelRatioF() | |||
if self.m_plugin_id >= 0 and self.m_plugin_id <= MAX_PLUGIN_ID_ALLOWED and ( | |||
self.m_plugin_inline == self.INLINE_DISPLAY_ENABLED or self.m_inline_scaling != scaling): | |||
size = "%i:%i" % (int(inwidth*scaling), int(inheight*scaling)) | |||
if self.m_inline_first: | |||
size = "%i:%i" % (int(50*scaling), int(50*scaling)) | |||
else: | |||
size = "%i:%i" % (int(inwidth*scaling), int(inheight*scaling)) | |||
data = canvas.callback(ACTION_INLINE_DISPLAY, self.m_plugin_id, 0, size) | |||
if data is None: | |||
return | |||
# invalidate old image first | |||
del self.m_inline_image | |||
self.m_inline_data = pack("%iB" % (data['height'] * data['stride']), *data['data']) | |||
self.m_inline_image = QImage(voidptr(self.m_inline_data), data['width'], data['height'], data['stride'], QImage.Format_ARGB32) | |||
new_inline_data = pack("%iB" % (data['height'] * data['stride']), *data['data']) | |||
self.m_inline_image = QImage(voidptr(new_inline_data), | |||
data['width'], data['height'], data['stride'], | |||
QImage.Format_ARGB32) | |||
self.m_inline_data = new_inline_data | |||
self.m_inline_scaling = scaling | |||
self.m_plugin_inline = self.INLINE_DISPLAY_CACHED | |||
self.m_plugin_inline = self.INLINE_DISPLAY_CACHED | |||
# make room for inline display, in a square shape | |||
if self.m_inline_first: | |||
self.m_inline_first = False | |||
aspectRatio = data['width'] / data['height'] | |||
self.p_height = int(max(50*scaling, self.p_height)) | |||
self.p_width += int(min((80 - 14)*scaling, (inheight-inwidth) * aspectRatio * scaling)) | |||
self.repositionPorts() | |||
self.repaintLines(True) | |||
self.update() | |||
return | |||
if self.m_inline_image is None: | |||
print("ERROR: inline display image is None for", self.m_plugin_id, self.m_group_name) | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Native Plugins | |||
* Copyright (C) 2013-2019 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2013-2020 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 | |||
@@ -312,15 +312,17 @@ protected: | |||
// Plugin dispatcher calls | |||
#ifdef HAVE_PYQT | |||
const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t width, const uint32_t height) override | |||
const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t rwidth, const uint32_t height) override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(width > 0 && height > 0, nullptr); | |||
CARLA_SAFE_ASSERT_RETURN(height > 4, nullptr); | |||
const uint32_t width = rwidth == height ? height * 4 : rwidth; | |||
/* NOTE the code is this function is not optimized, still learning my way through pixels... | |||
*/ | |||
const size_t stride = width * 4; | |||
const size_t dataSize = stride * height; | |||
const uint pxToMove = fInlineDisplay.writtenValues; | |||
const uint pxToMove = fDoProcess ? fInlineDisplay.writtenValues : 0; | |||
uchar* data = fInlineDisplay.data; | |||
@@ -344,70 +346,73 @@ protected: | |||
fInlineDisplay.height = static_cast<int>(height); | |||
fInlineDisplay.stride = static_cast<int>(stride); | |||
const uint h2 = height / 2; | |||
// clear current line | |||
for (uint w=width-pxToMove; w < width; ++w) | |||
for (uint h=0; h < height; ++h) | |||
memset(&data[h * stride + w * 4], 0, 4); | |||
// draw upper/left | |||
for (uint i=0; i < pxToMove; ++i) | |||
if (pxToMove != 0) | |||
{ | |||
const float valueL = fInlineDisplay.lastValuesL[i]; | |||
const float valueR = fInlineDisplay.lastValuesR[i]; | |||
const uint h2 = height / 2; | |||
const uint h2L = static_cast<uint>(valueL * (float)h2); | |||
const uint h2R = static_cast<uint>(valueR * (float)h2); | |||
const uint w = width - pxToMove + i; | |||
// clear current line | |||
for (uint w=width-pxToMove; w < width; ++w) | |||
for (uint h=0; h < height; ++h) | |||
memset(&data[h * stride + w * 4], 0, 4); | |||
for (uint h=0; h < h2L; ++h) | |||
// draw upper/left | |||
for (uint i=0; i < pxToMove && i < 32; ++i) | |||
{ | |||
// -30dB | |||
//if (valueL < 0.032f) | |||
// continue; | |||
const float valueL = fInlineDisplay.lastValuesL[i]; | |||
const float valueR = fInlineDisplay.lastValuesR[i]; | |||
data[(h2 - h) * stride + w * 4 + 3] = 160; | |||
const uint h2L = static_cast<uint>(valueL * (float)h2); | |||
const uint h2R = static_cast<uint>(valueR * (float)h2); | |||
const uint w = width - pxToMove + i; | |||
// -12dB | |||
if (valueL < 0.25f) | |||
{ | |||
data[(h2 - h) * stride + w * 4 + 1] = 255; | |||
} | |||
// -3dB | |||
else if (valueL < 0.70f) | |||
{ | |||
data[(h2 - h) * stride + w * 4 + 2] = 255; | |||
data[(h2 - h) * stride + w * 4 + 1] = 255; | |||
} | |||
else | |||
for (uint h=0; h < h2L; ++h) | |||
{ | |||
data[(h2 - h) * stride + w * 4 + 2] = 255; | |||
} | |||
} | |||
for (uint h=0; h < h2R; ++h) | |||
{ | |||
// -30dB | |||
//if (valueR < 0.032f) | |||
// continue; | |||
// -30dB | |||
//if (valueL < 0.032f) | |||
// continue; | |||
data[(h2 + h) * stride + w * 4 + 3] = 160; | |||
data[(h2 - h) * stride + w * 4 + 3] = 160; | |||
// -12dB | |||
if (valueR < 0.25f) | |||
{ | |||
data[(h2 + h) * stride + w * 4 + 1] = 255; | |||
} | |||
// -3dB | |||
else if (valueR < 0.70f) | |||
{ | |||
data[(h2 + h) * stride + w * 4 + 2] = 255; | |||
data[(h2 + h) * stride + w * 4 + 1] = 255; | |||
// -12dB | |||
if (valueL < 0.25f) | |||
{ | |||
data[(h2 - h) * stride + w * 4 + 1] = 255; | |||
} | |||
// -3dB | |||
else if (valueL < 0.70f) | |||
{ | |||
data[(h2 - h) * stride + w * 4 + 2] = 255; | |||
data[(h2 - h) * stride + w * 4 + 1] = 255; | |||
} | |||
else | |||
{ | |||
data[(h2 - h) * stride + w * 4 + 2] = 255; | |||
} | |||
} | |||
else | |||
for (uint h=0; h < h2R; ++h) | |||
{ | |||
data[(h2 + h) * stride + w * 4 + 2] = 255; | |||
// -30dB | |||
//if (valueR < 0.032f) | |||
// continue; | |||
data[(h2 + h) * stride + w * 4 + 3] = 160; | |||
// -12dB | |||
if (valueR < 0.25f) | |||
{ | |||
data[(h2 + h) * stride + w * 4 + 1] = 255; | |||
} | |||
// -3dB | |||
else if (valueR < 0.70f) | |||
{ | |||
data[(h2 + h) * stride + w * 4 + 2] = 255; | |||
data[(h2 + h) * stride + w * 4 + 1] = 255; | |||
} | |||
else | |||
{ | |||
data[(h2 + h) * stride + w * 4 + 2] = 255; | |||
} | |||
} | |||
} | |||
} | |||
@@ -161,7 +161,7 @@ protected: | |||
fOutLeft = carla_findMaxNormalizedFloat(inputs[0], frames); | |||
fOutRight = carla_findMaxNormalizedFloat(inputs[1], frames); | |||
bool needsInlineRender = false; | |||
bool needsInlineRender = fInlineDisplay.pending < 0; | |||
if (carla_isNotEqual(fOutLeft, fInlineDisplay.lastLeft)) | |||
{ | |||
@@ -175,9 +175,9 @@ protected: | |||
needsInlineRender = true; | |||
} | |||
if (needsInlineRender && ! fInlineDisplay.pending) | |||
if (needsInlineRender && fInlineDisplay.pending != 1) | |||
{ | |||
fInlineDisplay.pending = true; | |||
fInlineDisplay.pending = 1; | |||
hostQueueDrawInlineDisplay(); | |||
} | |||
} | |||
@@ -185,11 +185,11 @@ protected: | |||
// ------------------------------------------------------------------- | |||
// Plugin dispatcher calls | |||
const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t width_, const uint32_t height) override | |||
const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t rwidth, const uint32_t height) override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(width_ > 0 && height > 0, nullptr); | |||
CARLA_SAFE_ASSERT_RETURN(rwidth > 0 && height > 0, nullptr); | |||
const uint32_t width = width_ < height ? width_ : height; | |||
const uint32_t width = rwidth == height ? height / 6 : rwidth; | |||
const size_t stride = width * 4; | |||
const size_t dataSize = stride * height; | |||
@@ -282,7 +282,7 @@ protected: | |||
data[h * stride + (width - 1) * 4 + 3] = 120; | |||
} | |||
fInlineDisplay.pending = false; | |||
fInlineDisplay.pending = rwidth == height ? -1 : 0; | |||
return (NativeInlineDisplayImageSurface*)(NativeInlineDisplayImageSurfaceCompat*)&fInlineDisplay; | |||
} | |||
@@ -293,13 +293,13 @@ private: | |||
struct InlineDisplay : NativeInlineDisplayImageSurfaceCompat { | |||
float lastLeft; | |||
float lastRight; | |||
volatile bool pending; | |||
volatile int pending; | |||
InlineDisplay() | |||
: NativeInlineDisplayImageSurfaceCompat(), | |||
lastLeft(0.0f), | |||
lastRight(0.0f), | |||
pending(false) {} | |||
pending(0) {} | |||
~InlineDisplay() | |||
{ | |||