aboutsummaryrefslogtreecommitdiffstats
path: root/src/jalv_qt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jalv_qt.cpp')
-rw-r--r--src/jalv_qt.cpp1066
1 files changed, 511 insertions, 555 deletions
diff --git a/src/jalv_qt.cpp b/src/jalv_qt.cpp
index f23a005..a63a508 100644
--- a/src/jalv_qt.cpp
+++ b/src/jalv_qt.cpp
@@ -1,348 +1,293 @@
-/*
- Copyright 2007-2016 David Robillard <http://drobilla.net>
-
- 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.
-
- THIS 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.
-*/
+// Copyright 2007-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+#include "jalv_qt.hpp"
+#include "frontend.h"
#include "jalv_internal.h"
-
-#include "lv2/patch/patch.h"
-#include "lv2/port-props/port-props.h"
-
-#include <qglobal.h>
-
-#if QT_VERSION >= 0x050000
-# include <QAction>
-# include <QApplication>
-# include <QDial>
-# include <QGroupBox>
-# include <QLabel>
-# include <QLayout>
-# include <QMainWindow>
-# include <QMenu>
-# include <QMenuBar>
-# include <QScreen>
-# include <QScrollArea>
-# include <QStyle>
-# include <QTimer>
-# include <QWidget>
-# include <QWindow>
-#else
-# include <QtGui>
-#endif
+#include "nodes.h"
+#include "options.h"
+#include "port.h"
+
+#include "lilv/lilv.h"
+#include "suil/suil.h"
+#include "zix/sem.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QDial>
+#include <QFontMetrics>
+#include <QGroupBox>
+#include <QGuiApplication>
+#include <QHBoxLayout>
+#include <QKeySequence>
+#include <QLabel>
+#include <QLayout>
+#include <QLayoutItem>
+#include <QList>
+#include <QMainWindow>
+#include <QMenu>
+#include <QMenuBar>
+#include <QObject>
+#include <QPoint>
+#include <QRect>
+#include <QScreen>
+#include <QScrollArea>
+#include <QSize>
+#include <QSizePolicy>
+#include <QString>
+#include <QStyle>
+#include <QTimer>
+#include <QVBoxLayout>
+#include <QWidget>
+#include <QtCore>
#include <algorithm>
#include <cmath>
-#include <cstdio>
+#include <cstdint>
+#include <cstring>
+#include <map>
+#include <vector>
-#define CONTROL_WIDTH 150
-#define DIAL_STEPS 10000
+constexpr int CONTROL_WIDTH = 150;
+constexpr int DIAL_STEPS = 10000;
-static QApplication* app = NULL;
+static QApplication* app = nullptr;
-class FlowLayout : public QLayout
+class FlowLayout final : public QLayout
{
public:
- FlowLayout(QWidget* parent,
- int margin = -1,
- int hSpacing = -1,
- int vSpacing = -1);
-
- FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
-
- ~FlowLayout();
-
- void addItem(QLayoutItem* item);
- int horizontalSpacing() const;
- int verticalSpacing() const;
- Qt::Orientations expandingDirections() const;
- bool hasHeightForWidth() const;
- int heightForWidth(int) const;
- int count() const;
- QLayoutItem* itemAt(int index) const;
- QSize minimumSize() const;
- void setGeometry(const QRect &rect);
- QSize sizeHint() const;
- QLayoutItem* takeAt(int index);
+ explicit FlowLayout(QWidget* parent, int margin, int hSpacing, int vSpacing);
+
+ explicit FlowLayout(int margin, int hSpacing, int vSpacing);
+
+ FlowLayout(const FlowLayout&) = delete;
+ FlowLayout& operator=(const FlowLayout&) = delete;
+
+ FlowLayout(FlowLayout&&) = delete;
+ FlowLayout&& operator=(FlowLayout&&) = delete;
+
+ ~FlowLayout() override;
+
+ void addItem(QLayoutItem* item) override;
+ int horizontalSpacing() const;
+ int verticalSpacing() const;
+ Qt::Orientations expandingDirections() const override;
+ bool hasHeightForWidth() const override;
+ int heightForWidth(int) const override;
+ int count() const override;
+ QLayoutItem* itemAt(int index) const override;
+ QSize minimumSize() const override;
+ void setGeometry(const QRect& rect) override;
+ QSize sizeHint() const override;
+ QLayoutItem* takeAt(int index) override;
private:
- int doLayout(const QRect &rect, bool testOnly) const;
- int smartSpacing(QStyle::PixelMetric pm) const;
+ int doLayout(const QRect& rect, bool testOnly) const;
+ int smartSpacing(QStyle::PixelMetric pm) const;
- QList<QLayoutItem*> itemList;
- int m_hSpace;
- int m_vSpace;
+ QList<QLayoutItem*> itemList;
+ int m_hSpace;
+ int m_vSpace;
};
FlowLayout::FlowLayout(QWidget* parent, int margin, int hSpacing, int vSpacing)
- : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
+ : QLayout(parent)
+ , m_hSpace(hSpacing)
+ , m_vSpace(vSpacing)
{
- setContentsMargins(margin, margin, margin, margin);
+ setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
- : m_hSpace(hSpacing), m_vSpace(vSpacing)
+ : m_hSpace(hSpacing)
+ , m_vSpace(vSpacing)
{
- setContentsMargins(margin, margin, margin, margin);
+ setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::~FlowLayout()
{
- QLayoutItem* item;
- while ((item = takeAt(0))) {
- delete item;
- }
+ QLayoutItem* item = nullptr;
+ while ((item = takeAt(0))) {
+ delete item;
+ }
}
void
FlowLayout::addItem(QLayoutItem* item)
{
- itemList.append(item);
+ itemList.append(item);
}
int
FlowLayout::horizontalSpacing() const
{
- if (m_hSpace >= 0) {
- return m_hSpace;
- } else {
- return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
- }
+ if (m_hSpace >= 0) {
+ return m_hSpace;
+ }
+
+ return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
int
FlowLayout::verticalSpacing() const
{
- if (m_vSpace >= 0) {
- return m_vSpace;
- } else {
- return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
- }
+ if (m_vSpace >= 0) {
+ return m_vSpace;
+ }
+
+ return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
int
FlowLayout::count() const
{
- return itemList.size();
+ return itemList.size();
}
QLayoutItem*
FlowLayout::itemAt(int index) const
{
- return itemList.value(index);
+ return itemList.value(index);
}
QLayoutItem*
FlowLayout::takeAt(int index)
{
- if (index >= 0 && index < itemList.size()) {
- return itemList.takeAt(index);
- } else {
- return 0;
- }
+ if (index >= 0 && index < itemList.size()) {
+ return itemList.takeAt(index);
+ }
+
+ return nullptr;
}
Qt::Orientations
FlowLayout::expandingDirections() const
{
- return 0;
+ return {};
}
bool
FlowLayout::hasHeightForWidth() const
{
- return true;
+ return true;
}
int
FlowLayout::heightForWidth(int width) const
{
- return doLayout(QRect(0, 0, width, 0), true);
+ return doLayout(QRect(0, 0, width, 0), true);
}
void
-FlowLayout::setGeometry(const QRect &rect)
+FlowLayout::setGeometry(const QRect& rect)
{
- QLayout::setGeometry(rect);
- doLayout(rect, false);
+ QLayout::setGeometry(rect);
+ doLayout(rect, false);
}
QSize
FlowLayout::sizeHint() const
{
- return minimumSize();
+ return minimumSize();
}
QSize
FlowLayout::minimumSize() const
{
- QSize size;
- QLayoutItem* item;
- foreach (item, itemList) {
- size = size.expandedTo(item->minimumSize());
- }
+ QSize size = {};
+ QLayoutItem* item = nullptr;
+ foreach (item, itemList) {
+ size = size.expandedTo(item->minimumSize());
+ }
- return size + QSize(2 * margin(), 2 * margin());
+ return size + QSize(2 * margin(), 2 * margin());
}
int
-FlowLayout::doLayout(const QRect &rect, bool testOnly) const
-{
- int left, top, right, bottom;
- getContentsMargins(&left, &top, &right, &bottom);
-
- QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
- int x = effectiveRect.x();
- int y = effectiveRect.y();
- int lineHeight = 0;
-
- QLayoutItem* item;
- foreach (item, itemList) {
- QWidget* wid = item->widget();
-
- int spaceX = horizontalSpacing();
- if (spaceX == -1) {
- spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton,
- QSizePolicy::PushButton,
- Qt::Horizontal);
- }
- int spaceY = verticalSpacing();
- if (spaceY == -1) {
- spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton,
- QSizePolicy::PushButton,
- Qt::Vertical);
- }
-
- int nextX = x + item->sizeHint().width() + spaceX;
- if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
- x = effectiveRect.x();
- y = y + lineHeight + spaceY;
- nextX = x + item->sizeHint().width() + spaceX;
- lineHeight = 0;
- }
-
- if (!testOnly) {
- item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
- }
-
- x = nextX;
- lineHeight = qMax(lineHeight, item->sizeHint().height());
- }
- return y + lineHeight - rect.y() + bottom;
+FlowLayout::doLayout(const QRect& rect, bool testOnly) const
+{
+ int left = 0;
+ int top = 0;
+ int right = 0;
+ int bottom = 0;
+ getContentsMargins(&left, &top, &right, &bottom);
+
+ const QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
+ int x = effectiveRect.x();
+ int y = effectiveRect.y();
+ int lineHeight = 0;
+
+ QLayoutItem* item = nullptr;
+ foreach (item, itemList) {
+ QWidget* wid = item->widget();
+
+ int spaceX = horizontalSpacing();
+ if (spaceX == -1) {
+ spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton,
+ QSizePolicy::PushButton,
+ Qt::Horizontal,
+ nullptr,
+ nullptr);
+ }
+ int spaceY = verticalSpacing();
+ if (spaceY == -1) {
+ spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton,
+ QSizePolicy::PushButton,
+ Qt::Vertical,
+ nullptr,
+ nullptr);
+ }
+
+ int nextX = x + item->sizeHint().width() + spaceX;
+ if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
+ x = effectiveRect.x();
+ y = y + lineHeight + spaceY;
+ nextX = x + item->sizeHint().width() + spaceX;
+ lineHeight = 0;
+ }
+
+ if (!testOnly) {
+ item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
+ }
+
+ x = nextX;
+ lineHeight = qMax(lineHeight, item->sizeHint().height());
+ }
+ return y + lineHeight - rect.y() + bottom;
}
int
FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
- QObject* parent = this->parent();
- if (!parent) {
- return -1;
- } else if (parent->isWidgetType()) {
- QWidget* pw = static_cast<QWidget*>(parent);
- return pw->style()->pixelMetric(pm, 0, pw);
- } else {
- return static_cast<QLayout*>(parent)->spacing();
- }
-}
+ QObject* parent = this->parent();
+ if (!parent) {
+ return -1;
+ }
-class PresetAction : public QAction
-{
- Q_OBJECT
-
-public:
- PresetAction(QObject* parent, Jalv* jalv, LilvNode* preset)
- : QAction(parent)
- , _jalv(jalv)
- , _preset(preset)
- {
- connect(this, SIGNAL(triggered()),
- this, SLOT(presetChosen()));
- }
-
- Q_SLOT void presetChosen() {
- jalv_apply_preset(_jalv, _preset);
- }
-
-private:
- Jalv* _jalv;
- LilvNode* _preset;
-};
-
-typedef struct {
- Jalv* jalv;
- struct Port* port;
-} PortContainer;
-
-class Control : public QGroupBox
-{
- Q_OBJECT
-
-public:
- Control(PortContainer portContainer, QWidget* parent = 0);
-
- Q_SLOT void dialChanged(int value);
-
- void setValue(float value);
-
- QDial* dial;
-
-private:
- void setRange(float min, float max);
- QString getValueLabel(float value);
- float getValue();
- int stringWidth(const QString& str);
-
- const LilvPlugin* plugin;
- struct Port* port;
-
- QLabel* label;
- QString name;
- int steps;
- float max;
- float min;
- bool isInteger;
- bool isEnum;
- bool isLogarithmic;
-
- std::vector<float> scalePoints;
- std::map<float, const char*> scaleMap;
-};
+ if (parent->isWidgetType()) {
+ auto* const pw = static_cast<QWidget*>(parent);
+ return pw->style()->pixelMetric(pm, nullptr, pw);
+ }
-#if QT_VERSION >= 0x050000
-# include "jalv_qt5_meta.hpp"
-#else
-# include "jalv_qt4_meta.hpp"
-#endif
+ return static_cast<QLayout*>(parent)->spacing();
+}
extern "C" {
int
-jalv_init(int* argc, char*** argv, JalvOptions* opts)
+jalv_frontend_init(int* argc, char*** argv, JalvOptions*)
{
- app = new QApplication(*argc, *argv, true);
- app->setStyleSheet("QGroupBox::title { subcontrol-position: top center }");
+ app = new QApplication(*argc, *argv, true);
+ app->setStyleSheet("QGroupBox::title { subcontrol-position: top center }");
- return 0;
+ return 0;
}
const char*
-jalv_native_ui_type(void)
+jalv_frontend_ui_type(void)
{
-#if QT_VERSION >= 0x050000
- return "http://lv2plug.in/ns/extensions/ui#Qt5UI";
-#else
- return "http://lv2plug.in/ns/extensions/ui#Qt4UI";
-#endif
+ return "http://lv2plug.in/ns/extensions/ui#Qt5UI";
}
void
@@ -352,28 +297,28 @@ jalv_ui_port_event(Jalv* jalv,
uint32_t protocol,
const void* buffer)
{
- if (jalv->ui_instance) {
- suil_instance_port_event(jalv->ui_instance, port_index,
- buffer_size, protocol, buffer);
- } else {
- Control* control = (Control*)jalv->ports[port_index].widget;
- if (control) {
- control->setValue(*(const float*)buffer);
- }
- }
+ if (jalv->ui_instance) {
+ suil_instance_port_event(
+ jalv->ui_instance, port_index, buffer_size, protocol, buffer);
+ } else {
+ auto* const control = static_cast<Control*>(jalv->ports[port_index].widget);
+ if (control) {
+ control->setValue(*static_cast<const float*>(buffer));
+ }
+ }
}
class Timer : public QTimer
{
public:
- explicit Timer(Jalv* jalv) : _jalv(jalv) {}
+ explicit Timer(Jalv* jalv)
+ : _jalv(jalv)
+ {}
- void timerEvent(QTimerEvent* e) {
- jalv_update(_jalv);
- }
+ void timerEvent(QTimerEvent*) override { jalv_update(_jalv); }
private:
- Jalv* _jalv;
+ Jalv* _jalv;
};
static int
@@ -382,376 +327,387 @@ add_preset_to_menu(Jalv* jalv,
const LilvNode* title,
void* data)
{
- QMenu* menu = (QMenu*)data;
- const char* label = lilv_node_as_string(title);
+ auto* const menu = static_cast<QMenu*>(data);
+ const char* label = lilv_node_as_string(title);
- QAction* action = new PresetAction(menu, jalv, lilv_node_duplicate(node));
- action->setText(label);
- menu->addAction(action);
- return 0;
+ QAction* action = new PresetAction(menu, jalv, lilv_node_duplicate(node));
+ action->setText(label);
+ menu->addAction(action);
+ return 0;
}
Control::Control(PortContainer portContainer, QWidget* parent)
- : QGroupBox(parent)
- , dial(new QDial())
- , plugin(portContainer.jalv->plugin)
- , port(portContainer.port)
- , label(new QLabel())
-{
- JalvNodes* nodes = &portContainer.jalv->nodes;
- const LilvPort* lilvPort = port->lilv_port;
-
- LilvNode* nmin;
- LilvNode* nmax;
- LilvNode* ndef;
- lilv_port_get_range(plugin, lilvPort, &ndef, &nmin, &nmax);
-
- LilvNode* stepsNode = lilv_port_get(plugin, lilvPort, nodes->pprops_rangeSteps);
- if (lilv_node_is_int(stepsNode)) {
- steps = std::max(lilv_node_as_int(stepsNode), 2);
- } else {
- steps = DIAL_STEPS;
- }
- lilv_node_free(stepsNode);
-
- // Fill scalePoints Map
- LilvScalePoints* sp = lilv_port_get_scale_points(plugin, lilvPort);
- if (sp) {
- LILV_FOREACH(scale_points, s, sp) {
- const LilvScalePoint* p = lilv_scale_points_get(sp, s);
- const LilvNode* val = lilv_scale_point_get_value(p);
- if (!lilv_node_is_float(val) && !lilv_node_is_int(val)) {
- continue;
- }
-
- const float f = lilv_node_as_float(val);
- scalePoints.push_back(f);
- scaleMap[f] = lilv_node_as_string(lilv_scale_point_get_label(p));
- }
-
- lilv_scale_points_free(sp);
- }
-
- // Check port properties
- isLogarithmic = lilv_port_has_property(plugin, lilvPort, nodes->pprops_logarithmic);
- isInteger = lilv_port_has_property(plugin, lilvPort, nodes->lv2_integer);
- isEnum = lilv_port_has_property(plugin, lilvPort, nodes->lv2_enumeration);
-
- if (lilv_port_has_property(plugin, lilvPort, nodes->lv2_toggled)) {
- isInteger = true;
-
- if (!scaleMap[0]) {
- scaleMap[0] = "Off";
- }
- if (!scaleMap[1]) {
- scaleMap[1] = "On" ;
- }
- }
-
- // Find and set min, max and default values for port
- float defaultValue = ndef ? lilv_node_as_float(ndef) : port->control;
- setRange(lilv_node_as_float(nmin), lilv_node_as_float(nmax));
- setValue(defaultValue);
-
- // Fill layout
- QVBoxLayout* layout = new QVBoxLayout();
- layout->addWidget(label, 0, Qt::AlignHCenter);
- layout->addWidget(dial, 0, Qt::AlignHCenter);
- setLayout(layout);
-
- setMinimumWidth(CONTROL_WIDTH);
- setMaximumWidth(CONTROL_WIDTH);
-
- LilvNode* nname = lilv_port_get_name(plugin, lilvPort);
- name = QString("%1").arg(lilv_node_as_string(nname));
-
- // Handle long names
- if (stringWidth(name) > CONTROL_WIDTH) {
- setTitle(fontMetrics().elidedText(name, Qt::ElideRight, CONTROL_WIDTH));
- } else {
- setTitle(name);
- }
-
- // Set tooltip if comment is available
- LilvNode* comment = lilv_port_get(plugin, lilvPort, nodes->rdfs_comment);
- if (comment) {
- QString* tooltip = new QString();
- tooltip->append(lilv_node_as_string(comment));
- setToolTip(*tooltip);
- }
-
- setFlat(true);
-
- connect(dial, SIGNAL(valueChanged(int)), this, SLOT(dialChanged(int)));
-
- lilv_node_free(nmin);
- lilv_node_free(nmax);
- lilv_node_free(ndef);
- lilv_node_free(nname);
- lilv_node_free(comment);
+ : QGroupBox(parent)
+ , dial(new QDial())
+ , plugin(portContainer.jalv->plugin)
+ , port(portContainer.port)
+ , label(new QLabel())
+{
+ JalvNodes* nodes = &portContainer.jalv->nodes;
+ const LilvPort* lilvPort = port->lilv_port;
+
+ LilvNode* nmin = nullptr;
+ LilvNode* nmax = nullptr;
+ LilvNode* ndef = nullptr;
+ lilv_port_get_range(plugin, lilvPort, &ndef, &nmin, &nmax);
+
+ LilvNode* stepsNode =
+ lilv_port_get(plugin, lilvPort, nodes->pprops_rangeSteps);
+ if (lilv_node_is_int(stepsNode)) {
+ steps = std::max(lilv_node_as_int(stepsNode), 2);
+ } else {
+ steps = DIAL_STEPS;
+ }
+ lilv_node_free(stepsNode);
+
+ // Fill scalePoints Map
+ LilvScalePoints* sp = lilv_port_get_scale_points(plugin, lilvPort);
+ if (sp) {
+ LILV_FOREACH (scale_points, s, sp) {
+ const LilvScalePoint* p = lilv_scale_points_get(sp, s);
+ const LilvNode* val = lilv_scale_point_get_value(p);
+ if (!lilv_node_is_float(val) && !lilv_node_is_int(val)) {
+ continue;
+ }
+
+ const float f = lilv_node_as_float(val);
+ scalePoints.push_back(f);
+ scaleMap[f] = lilv_node_as_string(lilv_scale_point_get_label(p));
+ }
+
+ lilv_scale_points_free(sp);
+ }
+
+ // Check port properties
+ isLogarithmic =
+ lilv_port_has_property(plugin, lilvPort, nodes->pprops_logarithmic);
+ isInteger = lilv_port_has_property(plugin, lilvPort, nodes->lv2_integer);
+ isEnum = lilv_port_has_property(plugin, lilvPort, nodes->lv2_enumeration);
+
+ if (lilv_port_has_property(plugin, lilvPort, nodes->lv2_toggled)) {
+ isInteger = true;
+
+ if (!scaleMap[0]) {
+ scaleMap[0] = "Off";
+ }
+ if (!scaleMap[1]) {
+ scaleMap[1] = "On";
+ }
+ }
+
+ // Find and set min, max and default values for port
+ const float defaultValue = ndef ? lilv_node_as_float(ndef) : port->control;
+ setRange(lilv_node_as_float(nmin), lilv_node_as_float(nmax));
+ setValue(defaultValue);
+
+ // Fill layout
+ auto* const layout = new QVBoxLayout();
+ layout->addWidget(label, 0, Qt::AlignHCenter);
+ layout->addWidget(dial, 0, Qt::AlignHCenter);
+ setLayout(layout);
+
+ setMinimumWidth(CONTROL_WIDTH);
+ setMaximumWidth(CONTROL_WIDTH);
+
+ LilvNode* nname = lilv_port_get_name(plugin, lilvPort);
+ name = QString("%1").arg(lilv_node_as_string(nname));
+
+ // Handle long names
+ if (stringWidth(name) > CONTROL_WIDTH) {
+ setTitle(fontMetrics().elidedText(name, Qt::ElideRight, CONTROL_WIDTH));
+ } else {
+ setTitle(name);
+ }
+
+ // Set tooltip if comment is available
+ LilvNode* comment = lilv_port_get(plugin, lilvPort, nodes->rdfs_comment);
+ if (comment) {
+ auto* const tooltip = new QString();
+ tooltip->append(lilv_node_as_string(comment));
+ setToolTip(*tooltip);
+ }
+
+ setFlat(true);
+
+ connect(dial, SIGNAL(valueChanged(int)), this, SLOT(dialChanged(int)));
+
+ lilv_node_free(nmin);
+ lilv_node_free(nmax);
+ lilv_node_free(ndef);
+ lilv_node_free(nname);
+ lilv_node_free(comment);
}
void
Control::setValue(float value)
{
- float step;
+ float step = 0.0f;
- if (isInteger) {
- step = value;
- } else if (isEnum) {
- step = (std::find(scalePoints.begin(), scalePoints.end(), value)
- - scalePoints.begin());
- } else if (isLogarithmic) {
- step = steps * log(value / min) / log(max / min);
- } else {
- step = value * steps;
- }
+ if (isInteger) {
+ step = value;
+ } else if (isEnum) {
+ step = (std::find(scalePoints.begin(), scalePoints.end(), value) -
+ scalePoints.begin());
+ } else if (isLogarithmic) {
+ step = steps * logf(value / min) / logf(max / min);
+ } else {
+ step = value * steps;
+ }
- dial->setValue(step);
- label->setText(getValueLabel(value));
+ dial->setValue(step);
+ label->setText(getValueLabel(value));
}
QString
Control::getValueLabel(float value)
{
- if (scaleMap[value]) {
- if (stringWidth(scaleMap[value]) > CONTROL_WIDTH) {
- label->setToolTip(scaleMap[value]);
- return fontMetrics().elidedText(QString(scaleMap[value]),
- Qt::ElideRight,
- CONTROL_WIDTH);
- }
- return scaleMap[value];
- }
+ if (scaleMap[value]) {
+ if (stringWidth(scaleMap[value]) > CONTROL_WIDTH) {
+ label->setToolTip(scaleMap[value]);
+ return fontMetrics().elidedText(
+ QString(scaleMap[value]), Qt::ElideRight, CONTROL_WIDTH);
+ }
+ return scaleMap[value];
+ }
- return QString("%1").arg(value);
+ return QString("%1").arg(value);
}
void
Control::setRange(float minRange, float maxRange)
{
- min = minRange;
- max = maxRange;
+ min = minRange;
+ max = maxRange;
- if (isLogarithmic) {
- minRange = 1;
- maxRange = steps;
- } else if (isEnum) {
- minRange = 0;
- maxRange = scalePoints.size() - 1;
- } else if (!isInteger) {
- minRange *= steps;
- maxRange *= steps;
- }
+ if (isLogarithmic) {
+ minRange = 1;
+ maxRange = steps;
+ } else if (isEnum) {
+ minRange = 0;
+ maxRange = scalePoints.size() - 1;
+ } else if (!isInteger) {
+ minRange *= steps;
+ maxRange *= steps;
+ }
- dial->setRange(minRange, maxRange);
+ dial->setRange(minRange, maxRange);
}
float
Control::getValue()
{
- if (isEnum) {
- return scalePoints[dial->value()];
- } else if (isInteger) {
- return dial->value();
- } else if (isLogarithmic) {
- return min * pow(max / min, (float)dial->value() / (steps - 1));
- } else {
- return (float)dial->value() / steps;
- }
+ if (isEnum) {
+ return scalePoints[dial->value()];
+ }
+
+ if (isInteger) {
+ return dial->value();
+ }
+
+ if (isLogarithmic) {
+ return min *
+ powf(max / min, static_cast<float>(dial->value()) / (steps - 1));
+ }
+
+ return static_cast<float>(dial->value()) / steps;
}
int
Control::stringWidth(const QString& str)
{
#if QT_VERSION >= 0x050B00
- return fontMetrics().horizontalAdvance(str);
+ return fontMetrics().horizontalAdvance(str);
#else
- return fontMetrics().width(str);
+ return fontMetrics().width(str);
#endif
}
void
-Control::dialChanged(int dialValue)
+Control::dialChanged(int)
{
- float value = getValue();
+ const float value = getValue();
- label->setText(getValueLabel(value));
- port->control = value;
+ label->setText(getValueLabel(value));
+ port->control = value;
}
static bool
-portGroupLessThan(const PortContainer &p1, const PortContainer &p2)
+portGroupLessThan(const PortContainer& p1, const PortContainer& p2)
{
- Jalv* jalv = p1.jalv;
- const LilvPort* port1 = p1.port->lilv_port;
- const LilvPort* port2 = p2.port->lilv_port;
+ Jalv* jalv = p1.jalv;
+ const LilvPort* port1 = p1.port->lilv_port;
+ const LilvPort* port2 = p2.port->lilv_port;
- LilvNode* group1 = lilv_port_get(
- jalv->plugin, port1, jalv->nodes.pg_group);
- LilvNode* group2 = lilv_port_get(
- jalv->plugin, port2, jalv->nodes.pg_group);
+ LilvNode* group1 = lilv_port_get(jalv->plugin, port1, jalv->nodes.pg_group);
+ LilvNode* group2 = lilv_port_get(jalv->plugin, port2, jalv->nodes.pg_group);
- const int cmp = (group1 && group2)
- ? strcmp(lilv_node_as_string(group1), lilv_node_as_string(group2))
- : ((intptr_t)group1 - (intptr_t)group2);
+ const int cmp = (group1 && group2) ? strcmp(lilv_node_as_string(group1),
+ lilv_node_as_string(group2))
+ : (intptr_t(group1) - intptr_t(group2));
- lilv_node_free(group2);
- lilv_node_free(group1);
+ lilv_node_free(group2);
+ lilv_node_free(group1);
- return cmp < 0;
+ return cmp < 0;
}
static QWidget*
build_control_widget(Jalv* jalv)
{
- const LilvPlugin* plugin = jalv->plugin;
- LilvWorld* world = jalv->world;
-
- QList<PortContainer> portContainers;
- for (unsigned i = 0; i < jalv->num_ports; ++i) {
- if (!jalv->opts.show_hidden &&
- lilv_port_has_property(plugin, jalv->ports[i].lilv_port,
- jalv->nodes.pprops_notOnGUI)) {
- continue;
- }
-
- if (jalv->ports[i].type == TYPE_CONTROL) {
- PortContainer portContainer;
- portContainer.jalv = jalv;
- portContainer.port = &jalv->ports[i];
- portContainers.append(portContainer);
- }
- }
-
- std::sort(portContainers.begin(), portContainers.end(), portGroupLessThan);
-
- QWidget* grid = new QWidget();
- FlowLayout* flowLayout = new FlowLayout();
- QLayout* layout = flowLayout;
-
- LilvNode* lastGroup = NULL;
- QHBoxLayout* groupLayout = NULL;
- for (int i = 0; i < portContainers.count(); ++i) {
- PortContainer portContainer = portContainers[i];
- Port* port = portContainer.port;
-
- Control* control = new Control(portContainer);
- LilvNode* group = lilv_port_get(
- plugin, port->lilv_port, jalv->nodes.pg_group);
- if (group) {
- if (!lilv_node_equals(group, lastGroup)) {
- /* Group has changed */
- LilvNode* groupName = lilv_world_get(
- world, group, jalv->nodes.lv2_name, NULL);
- if (!groupName) {
- groupName = lilv_world_get(
- world, group, jalv->nodes.rdfs_label, NULL);
- }
-
- QGroupBox* groupBox = new QGroupBox(lilv_node_as_string(groupName));
-
- groupLayout = new QHBoxLayout();
- groupBox->setLayout(groupLayout);
- layout->addWidget(groupBox);
- }
-
- groupLayout->addWidget(control);
- } else {
- layout->addWidget(control);
- }
- lilv_node_free(lastGroup);
- lastGroup = group;
-
- uint32_t index = lilv_port_get_index(plugin, port->lilv_port);
- jalv->ports[index].widget = control;
- }
- lilv_node_free(lastGroup);
-
- grid->setLayout(layout);
-
- return grid;
+ const LilvPlugin* plugin = jalv->plugin;
+ LilvWorld* world = jalv->world;
+
+ QList<PortContainer> portContainers;
+ for (unsigned i = 0; i < jalv->num_ports; ++i) {
+ if (!jalv->opts.show_hidden &&
+ lilv_port_has_property(
+ plugin, jalv->ports[i].lilv_port, jalv->nodes.pprops_notOnGUI)) {
+ continue;
+ }
+
+ if (jalv->ports[i].type == TYPE_CONTROL) {
+ portContainers.append(PortContainer{jalv, &jalv->ports[i]});
+ }
+ }
+
+ std::sort(portContainers.begin(), portContainers.end(), portGroupLessThan);
+
+ auto* const grid = new QWidget();
+ auto* const flowLayout = new FlowLayout(-1, -1, -1);
+ QLayout* layout = flowLayout;
+
+ LilvNode* lastGroup = nullptr;
+ QHBoxLayout* groupLayout = nullptr;
+ for (int i = 0; i < portContainers.count(); ++i) {
+ const PortContainer portContainer = portContainers[i];
+ Port* const port = portContainer.port;
+
+ auto* const control = new Control(portContainer, nullptr);
+ LilvNode* group =
+ lilv_port_get(plugin, port->lilv_port, jalv->nodes.pg_group);
+ if (group) {
+ if (!groupLayout || !lilv_node_equals(group, lastGroup)) {
+ // Group has changed
+ LilvNode* groupName =
+ lilv_world_get(world, group, jalv->nodes.lv2_name, nullptr);
+ if (!groupName) {
+ groupName =
+ lilv_world_get(world, group, jalv->nodes.rdfs_label, nullptr);
+ }
+
+ auto* const groupBox = new QGroupBox(lilv_node_as_string(groupName));
+
+ groupLayout = new QHBoxLayout();
+ groupBox->setLayout(groupLayout);
+ layout->addWidget(groupBox);
+ }
+
+ groupLayout->addWidget(control);
+ } else {
+ layout->addWidget(control);
+ }
+ lilv_node_free(lastGroup);
+ lastGroup = group;
+
+ const uint32_t index = lilv_port_get_index(plugin, port->lilv_port);
+ jalv->ports[index].widget = control;
+ }
+ lilv_node_free(lastGroup);
+
+ grid->setLayout(layout);
+
+ return grid;
}
bool
-jalv_discover_ui(Jalv* jalv)
+jalv_frontend_discover(Jalv*)
{
- return true;
+ return true;
}
float
-jalv_ui_refresh_rate(Jalv* jalv)
+jalv_frontend_refresh_rate(Jalv*)
{
-#if QT_VERSION >= 0x050000
- return (float)QGuiApplication::primaryScreen()->refreshRate();
-#else
- return 30.0f;
-#endif
+ return static_cast<float>(QGuiApplication::primaryScreen()->refreshRate());
+}
+
+float
+jalv_frontend_scale_factor(Jalv*)
+{
+ return static_cast<float>(
+ QGuiApplication::primaryScreen()->devicePixelRatio());
+}
+
+LilvNode*
+jalv_frontend_select_plugin(Jalv*)
+{
+ return nullptr;
}
int
-jalv_open_ui(Jalv* jalv)
-{
- QMainWindow* win = new QMainWindow();
- QMenu* file_menu = win->menuBar()->addMenu("&File");
- QMenu* presets_menu = win->menuBar()->addMenu("&Presets");
- QAction* quit_action = new QAction("&Quit", win);
-
- QObject::connect(quit_action, SIGNAL(triggered()), win, SLOT(close()));
- quit_action->setShortcuts(QKeySequence::Quit);
- quit_action->setStatusTip("Quit Jalv");
- file_menu->addAction(quit_action);
-
- jalv_load_presets(jalv, add_preset_to_menu, presets_menu);
-
- if (jalv->ui && !jalv->opts.generic_ui) {
- jalv_ui_instantiate(jalv, jalv_native_ui_type(), win);
- }
-
- QWidget* widget;
- if (jalv->ui_instance) {
- widget = (QWidget*)suil_instance_get_widget(jalv->ui_instance);
- } else {
- QWidget* controlWidget = build_control_widget(jalv);
-
- widget = new QScrollArea();
- ((QScrollArea*)widget)->setWidget(controlWidget);
- ((QScrollArea*)widget)->setWidgetResizable(true);
- widget->setMinimumWidth(800);
- widget->setMinimumHeight(600);
- }
-
- LilvNode* name = lilv_plugin_get_name(jalv->plugin);
- win->setWindowTitle(lilv_node_as_string(name));
- lilv_node_free(name);
-
- win->setCentralWidget(widget);
- app->connect(app, SIGNAL(lastWindowClosed()), app, SLOT(quit()));
-
- win->show();
- if (jalv->ui_instance && !jalv_ui_is_resizable(jalv)) {
- widget->setMinimumSize(widget->width(), widget->height());
- widget->setMaximumSize(widget->width(), widget->height());
- win->adjustSize();
- win->setFixedSize(win->width(), win->height());
- } else {
- win->resize(widget->width(),
- widget->height() + win->menuBar()->height());
- }
-
- Timer* timer = new Timer(jalv);
- timer->start(1000 / jalv->ui_update_hz);
-
- int ret = app->exec();
- zix_sem_post(&jalv->done);
- return ret;
+jalv_frontend_open(Jalv* jalv)
+{
+ auto* const win = new QMainWindow();
+ QMenu* file_menu = win->menuBar()->addMenu("&File");
+ QMenu* presets_menu = win->menuBar()->addMenu("&Presets");
+ auto* const quit_action = new QAction("&Quit", win);
+
+ QObject::connect(quit_action, SIGNAL(triggered()), win, SLOT(close()));
+ quit_action->setShortcuts(QKeySequence::Quit);
+ quit_action->setStatusTip("Quit Jalv");
+ file_menu->addAction(quit_action);
+
+ jalv_load_presets(jalv, add_preset_to_menu, presets_menu);
+
+ if (jalv->ui && !jalv->opts.generic_ui) {
+ jalv_ui_instantiate(jalv, jalv_frontend_ui_type(), win);
+ }
+
+ QWidget* widget = nullptr;
+ if (jalv->ui_instance) {
+ widget = static_cast<QWidget*>(suil_instance_get_widget(jalv->ui_instance));
+ } else {
+ QWidget* controlWidget = build_control_widget(jalv);
+
+ widget = new QScrollArea();
+ static_cast<QScrollArea*>(widget)->setWidget(controlWidget);
+ static_cast<QScrollArea*>(widget)->setWidgetResizable(true);
+ widget->setMinimumWidth(800);
+ widget->setMinimumHeight(600);
+ }
+
+ LilvNode* name = lilv_plugin_get_name(jalv->plugin);
+ win->setWindowTitle(lilv_node_as_string(name));
+ lilv_node_free(name);
+
+ win->setCentralWidget(widget);
+ app->connect(app, SIGNAL(lastWindowClosed()), app, SLOT(quit()));
+
+ jalv_init_ui(jalv);
+
+ win->show();
+ if (jalv->ui_instance && !jalv_ui_is_resizable(jalv)) {
+ widget->setMinimumSize(widget->width(), widget->height());
+ widget->setMaximumSize(widget->width(), widget->height());
+ win->adjustSize();
+ win->setFixedSize(win->width(), win->height());
+ } else {
+ win->resize(widget->width(), widget->height() + win->menuBar()->height());
+ }
+
+ auto* const timer = new Timer(jalv);
+ timer->start(1000 / jalv->ui_update_hz);
+
+ const int ret = app->exec();
+ zix_sem_post(&jalv->done);
+ return ret;
}
int
-jalv_close_ui(Jalv* jalv)
+jalv_frontend_close(Jalv*)
{
- app->quit();
- return 0;
+ app->quit();
+ return 0;
}
-} // extern "C"
+} // extern "C"