Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package qpwgraph for openSUSE:Factory checked in at 2023-07-26 13:23:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/qpwgraph (Old) and /work/SRC/openSUSE:Factory/.qpwgraph.new.15225 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "qpwgraph" Wed Jul 26 13:23:58 2023 rev:18 rq:1100590 version:0.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/qpwgraph/qpwgraph.changes 2023-07-11 15:57:41.369306161 +0200 +++ /work/SRC/openSUSE:Factory/.qpwgraph.new.15225/qpwgraph.changes 2023-07-26 13:25:02.756398697 +0200 @@ -1,0 +2,19 @@ +Mon Jul 17 19:34:29 UTC 2023 - Alexei Sorokin <[email protected]> + +- Update to version 0.5.1: + * Fix segfault on initialisation that was affecting Qt5 builds. + +------------------------------------------------------------------- +Sun Jul 16 15:15:29 UTC 2023 - Alexei Sorokin <[email protected]> + +- Update to version 0.5.0: + * Completely refactored the internal PipeWire node registry + logic, just to have unique node names, as seen fit to purpose + to solve an old undefined behaviour to positioning and Patchbay + persistence of multiple nodes with the very same and exact + name. + * Fix the main PipeWire registry thread-safety, into a two-level + critical section, hopefully preventing the race-conditions that + are the suspected cause to some rare crashes. + +------------------------------------------------------------------- Old: ---- qpwgraph-v0.4.5.tar.bz2 New: ---- qpwgraph-v0.5.1.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ qpwgraph.spec ++++++ --- /var/tmp/diff_new_pack.uBX8Pu/_old 2023-07-26 13:25:03.284401884 +0200 +++ /var/tmp/diff_new_pack.uBX8Pu/_new 2023-07-26 13:25:03.284401884 +0200 @@ -17,7 +17,7 @@ Name: qpwgraph -Version: 0.4.5 +Version: 0.5.1 Release: 0 Summary: PipeWire Graph Qt GUI Interface License: GPL-2.0-or-later ++++++ qpwgraph-v0.4.5.tar.bz2 -> qpwgraph-v0.5.1.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/CMakeLists.txt new/qpwgraph-v0.5.1/CMakeLists.txt --- old/qpwgraph-v0.4.5/CMakeLists.txt 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/CMakeLists.txt 2023-07-17 11:59:55.000000000 +0200 @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 3.15) project(qpwgraph - VERSION 0.4.5 + VERSION 0.5.1 DESCRIPTION "A PipeWire Graph Qt GUI Interface" HOMEPAGE_URL "https://gitlab.freedesktop.org/rncbc/qpwgraph" LANGUAGES C CXX) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/ChangeLog new/qpwgraph-v0.5.1/ChangeLog --- old/qpwgraph-v0.4.5/ChangeLog 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/ChangeLog 2023-07-17 11:59:55.000000000 +0200 @@ -2,6 +2,22 @@ -------------------------------------------- +0.5.1 2023-07-17 A summer'23 hot-fix release. + +- Fixed segfault on initialization that was affecting Qt5 builds. + + +0.5.0 2023-07-16 Yet another summer'23 release. + +- Completely refactored the internal PipeWire node registry logic, + just to have unique node names, as seen fit to purpose to solve + an old undefined behavior to positioning and Patchbay persistence + of multiple nodes with the very same and exact name. +- Fixed the main PipeWire registry thread-safety, into a two-level + critical section, hopefully preventing the race-conditions that + are the suspected cause to some rare crashes. + + 0.4.5 2023-07-10 A summer'23 release. - Split non-physical terminal device nodes for monitor and control diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/debian/changelog new/qpwgraph-v0.5.1/debian/changelog --- old/qpwgraph-v0.4.5/debian/changelog 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/debian/changelog 2023-07-17 11:59:55.000000000 +0200 @@ -1,3 +1,15 @@ +qpwgraph (0.5.1-29.1) unstable; urgency=low + + * A summer'23 hot-fix release. + + -- Rui Nuno Capela <[email protected]> Mon, 17 Jul 2023 12:00:00 +0100 + +qpwgraph (0.5.0-28.1) unstable; urgency=low + + * Yet another summer'23 release. + + -- Rui Nuno Capela <[email protected]> Sun, 16 Jul 2023 18:00:00 +0100 + qpwgraph (0.4.5-27.1) unstable; urgency=low * A summer'23 release. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/rpm/qpwgraph.spec new/qpwgraph-v0.5.1/rpm/qpwgraph.spec --- old/qpwgraph-v0.4.5/rpm/qpwgraph.spec 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/rpm/qpwgraph.spec 2023-07-17 11:59:55.000000000 +0200 @@ -16,8 +16,8 @@ # %define name qpwgraph -%define version 0.4.5 -%define release 27.1 +%define version 0.5.1 +%define release 29.1 %define _prefix /usr @@ -141,6 +141,10 @@ %changelog +* Mon Jul 17 2023 Rui Nuno Capela <[email protected]> 0.5.1 +- A summer'23 hot-fix release. +* Sun Jul 16 2023 Rui Nuno Capela <[email protected]> 0.5.0 +- Yet another summer'23 release. * Mon Jul 10 2023 Rui Nuno Capela <[email protected]> 0.4.5 - A summer'23 release. * Sun Jun 18 2023 Rui Nuno Capela <[email protected]> 0.4.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/appdata/org.rncbc.qpwgraph.metainfo.xml new/qpwgraph-v0.5.1/src/appdata/org.rncbc.qpwgraph.metainfo.xml --- old/qpwgraph-v0.4.5/src/appdata/org.rncbc.qpwgraph.metainfo.xml 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/appdata/org.rncbc.qpwgraph.metainfo.xml 2023-07-17 11:59:55.000000000 +0200 @@ -37,7 +37,7 @@ <developer_name>rncbc aka. Rui Nuno Capela</developer_name> <update_contact>[email protected]</update_contact> <releases> - <release version="0.4.5" date="2023-07-10" urgency="low" /> + <release version="0.5.1" date="2023-07-17" urgency="low" /> </releases> <content_rating type="oars-1.0"/> </component> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/config.h.cmake new/qpwgraph-v0.5.1/src/config.h.cmake --- old/qpwgraph-v0.4.5/src/config.h.cmake 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/config.h.cmake 2023-07-17 11:59:55.000000000 +0200 @@ -29,5 +29,6 @@ /* Define if Wayland is supported */ #cmakedefine CONFIG_WAYLAND @CONFIG_WAYLAND@ + #endif // __CONFIG_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph.cpp new/qpwgraph-v0.5.1/src/qpwgraph.cpp --- old/qpwgraph-v0.4.5/src/qpwgraph.cpp 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph.cpp 2023-07-17 11:59:55.000000000 +0200 @@ -232,7 +232,7 @@ if (form && parse_args(QString(data).split(' '))) form->apply_args(this); // Just make it always shows up fine... - if (m_widget) { + if (m_widget && !m_start_minimized) { m_widget->hide(); m_widget->show(); m_widget->raise(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_canvas.cpp new/qpwgraph-v0.5.1/src/qpwgraph_canvas.cpp --- old/qpwgraph-v0.4.5/src/qpwgraph_canvas.cpp 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_canvas.cpp 2023-07-17 11:59:55.000000000 +0200 @@ -305,9 +305,8 @@ emit removed(node); node->removePorts(); removeNodeKeys(node); - } - if (node) m_nodes.removeAll(node); + } } else if (item->type() == qpwgraph_port::Type) { @@ -483,8 +482,8 @@ foreach (qpwgraph_node *node, m_nodes) { if (node->nodeType() == node_type) { - m_node_keys.remove(qpwgraph_node::NodeNameKey(node)); - m_node_ids.remove(qpwgraph_node::NodeIdKey(node)); + m_node_names.remove(qpwgraph_node::NodeNameKey(node), node); + m_node_ids.remove(qpwgraph_node::NodeIdKey(node), node); m_nodes.removeAll(node); nodes.append(node); } @@ -498,23 +497,22 @@ qpwgraph_node *qpwgraph_canvas::findNode ( uint id, qpwgraph_item::Mode mode, uint type ) const { - return static_cast<qpwgraph_node *> ( - m_node_ids.value(qpwgraph_node::IdKey(id, mode, type), nullptr)); + return m_node_ids.value(qpwgraph_item::IdKey(id, mode, type), nullptr); } -// Whether it's in the middle of something... -bool qpwgraph_canvas::isBusy (void) const +qpwgraph_node *qpwgraph_canvas::findNode ( + const QString& name, qpwgraph_item::Mode mode, uint type ) const { - return (m_state != DragNone || m_connect != nullptr - || m_item != nullptr || m_edit_item != nullptr); + return m_node_names.value(qpwgraph_node::NodeNameKey(name, mode, type), nullptr); } -QList<qpwgraph_node *> qpwgraph_canvas::findNodes ( - const QString& name, qpwgraph_item::Mode mode, uint type ) const +// Whether it's in the middle of something... +bool qpwgraph_canvas::isBusy (void) const { - return m_node_keys.values(qpwgraph_node::NodeNameKey(name, mode, type)); + return (m_state != DragNone || m_connect != nullptr + || m_item != nullptr || m_edit_item != nullptr); } @@ -1268,11 +1266,7 @@ if (m_settings == nullptr || node == nullptr) return false; - // Assume node name-keys have been added before this... - // - const qpwgraph_node::NodeNameKey name_key(node); - const int n = m_node_keys.values(name_key).count(); - const QString& node_key = nodeKey(node, n); + const QString& node_key = nodeKey(node); m_settings->beginGroup(NodeAliasesGroup); const QString& node_title @@ -1301,17 +1295,10 @@ if (m_settings == nullptr || node == nullptr) return false; - // Assume node name-keys are to be removed after this... - // - const qpwgraph_node::NodeNameKey name_key(node); - const int n = m_node_keys.values(name_key).count(); - if (n < 1) - return false; - - const QString& node_key = nodeKey(node, n); + const QString& node_key = nodeKey(node); m_settings->beginGroup(NodeAliasesGroup); - if (node->nodeName() != node->nodeTitle()) { + if (node->nodeNameLabel() != node->nodeTitle()) { m_settings->setValue('/' + node_key, node->nodeTitle()); } else { m_settings->remove('/' + node_key); @@ -1354,7 +1341,7 @@ const QString& port_key = portKey(port); m_settings->beginGroup(PortAliasesGroup); - if (port->portName() != port->portTitle()) + if (port->portNameLabel() != port->portTitle()) m_settings->setValue('/' + port_key, port->portTitle()); else m_settings->remove('/' + port_key); @@ -1369,6 +1356,10 @@ if (m_settings == nullptr) return false; +#ifdef CONFIG_CLEANUP_NODE_NAMES + cleanupNodeNames(NodePosGroup); + cleanupNodeNames(NodeAliasesGroup); +#endif m_settings->beginGroup(ColorsGroup); const QRegularExpression rx("^0x"); QStringListIterator key(m_settings->childKeys()); @@ -1410,22 +1401,17 @@ if (item->type() == qpwgraph_node::Type) { qpwgraph_node *node = static_cast<qpwgraph_node *> (item); if (node && !nodes.contains(node)) { - int n = 0; - const QList<qpwgraph_node *>& nodes2 - = m_node_keys.values(qpwgraph_node::NodeNameKey(node)); - foreach (qpwgraph_node *node2, nodes2) { - const QString& node2_key = nodeKey(node2, ++n); - m_settings->beginGroup(NodePosGroup); - m_settings->setValue('/' + node2_key, node2->pos()); - m_settings->endGroup(); - m_settings->beginGroup(NodeAliasesGroup); - if (node2->nodeName() != node2->nodeTitle()) - m_settings->setValue('/' + node2_key, node2->nodeTitle()); - else - m_settings->remove('/' + node2_key); - m_settings->endGroup(); - nodes.append(node2); - } + const QString& node_key = nodeKey(node); + m_settings->beginGroup(NodePosGroup); + m_settings->setValue('/' + node_key, node->pos()); + m_settings->endGroup(); + m_settings->beginGroup(NodeAliasesGroup); + if (node->nodeName() != node->nodeTitle()) + m_settings->setValue('/' + node_key, node->nodeTitle()); + else + m_settings->remove('/' + node_key); + m_settings->endGroup(); + nodes.append(node); } } else @@ -1465,13 +1451,9 @@ // Graph node/port key helpers. -QString qpwgraph_canvas::nodeKey ( qpwgraph_node *node, int n ) const +QString qpwgraph_canvas::nodeKey ( qpwgraph_node *node ) const { QString node_key = node->nodeName(); - if (n > 1) { - node_key += '-'; - node_key += QString::number(n - 1); - } switch (node->nodeMode()) { case qpwgraph_item::Input: @@ -1488,7 +1470,7 @@ } -QString qpwgraph_canvas::portKey ( qpwgraph_port *port, int n ) const +QString qpwgraph_canvas::portKey ( qpwgraph_port *port ) const { QString port_key; @@ -1499,10 +1481,6 @@ port_key += node->nodeName(); port_key += ':'; port_key += port->portName(); - if (n > 1) { - port_key += '-'; - port_key += QString::number(n - 1); - } switch (port->portMode()) { case qpwgraph_item::Input: @@ -1522,14 +1500,14 @@ void qpwgraph_canvas::addNodeKeys ( qpwgraph_node *node ) { m_node_ids.insert(qpwgraph_node::NodeIdKey(node), node); - m_node_keys.insert(qpwgraph_node::NodeNameKey(node), node); + m_node_names.insert(qpwgraph_node::NodeNameKey(node), node); } void qpwgraph_canvas::removeNodeKeys ( qpwgraph_node *node ) { - m_node_keys.remove(qpwgraph_node::NodeNameKey(node)); - m_node_ids.remove(qpwgraph_node::NodeIdKey(node)); + m_node_names.remove(qpwgraph_node::NodeNameKey(node), node); + m_node_ids.remove(qpwgraph_node::NodeIdKey(node), node); } @@ -1813,4 +1791,69 @@ } +#ifdef CONFIG_CLEANUP_NODE_NAMES + +void qpwgraph_canvas::cleanupNodeNames ( const char *group ) +{ + bool cleanup = false; + + m_settings->beginGroup("/CleanupNodeNames"); + cleanup = m_settings->value(group).toBool(); + if (!cleanup) + m_settings->setValue(group, true); + m_settings->endGroup(); + + if (cleanup) + return; + + m_settings->beginGroup(group); + const QRegularExpression rx("\\-([0-9]+).*$"); + QHash<QString, QVariant> keys; + QStringListIterator iter(m_settings->childKeys()); + while (iter.hasNext()) { + const QString& key = iter.next(); + const QVariant& value = m_settings->value(key); + QString key2 = key; + if (cleanupNodeName(key2)) { + int n = 0; + if (keys.find(key2) != keys.end()) { + const QRegularExpressionMatch mx = rx.match(key2); + if (mx.hasMatch()) { + n = mx.captured(1).toInt(); + key2.remove(rx); + } + QString key3; + do { key3 = key2 + '-' + QString::number(++n); } + while (keys.find(key3) != keys.end()); + key2 = key3; + } + if (n == 0) { + keys.insert(key2, value); + m_settings->setValue(key2, value); + } + m_settings->remove(key); + } else { + keys.insert(key, value); + } + } + m_settings->endGroup(); +} + + +bool qpwgraph_canvas::cleanupNodeName ( QString& name ) +{ + const QRegularExpression rx("^.+( \\[.+\\])[^ ]*$"); + const QRegularExpressionMatch& mx = rx.match(name); + if (mx.hasMatch()) { + name.remove(mx.captured(1)); + return true; + } else { + return false; + } +} + +#endif//CONFIG_CLEANUP_NODE_NAMES + + + // end of qpwgraph_canvas.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_canvas.h new/qpwgraph-v0.5.1/src/qpwgraph_canvas.h --- old/qpwgraph-v0.4.5/src/qpwgraph_canvas.h 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_canvas.h 2023-07-17 11:59:55.000000000 +0200 @@ -49,6 +49,10 @@ class qpwgraph_patchbay; +// Define if cleanup of legacy node names is needed (v0.5.0)... +#define CONFIG_CLEANUP_NODE_NAMES 1 + + //---------------------------------------------------------------------------- // qpwgraph_canvas -- Canvas graphics scene/view. @@ -117,7 +121,7 @@ // Special node finders. qpwgraph_node *findNode( uint id, qpwgraph_item::Mode mode, uint type = 0) const; - QList<qpwgraph_node *> findNodes( + qpwgraph_node *findNode( const QString& name, qpwgraph_item::Mode mode, uint type = 0) const; void releaseNode(qpwgraph_node *node); @@ -164,6 +168,10 @@ // Snap into position helper. QPointF snapPos(qreal x, qreal y) const; +#ifdef CONFIG_CLEANUP_NODE_NAMES + static bool cleanupNodeName(QString& name); +#endif + signals: // Node factory notifications. @@ -241,8 +249,8 @@ void pinchGesture(QPinchGesture *pinch); // Graph node/port key helpers. - QString nodeKey(qpwgraph_node *node, int n = 0) const; - QString portKey(qpwgraph_port *port, int n = 0) const; + QString nodeKey(qpwgraph_node *node) const; + QString portKey(qpwgraph_port *port) const; void addNodeKeys(qpwgraph_node *node); void removeNodeKeys(qpwgraph_node *node); @@ -267,6 +275,10 @@ // Snap into position helper. void snapPos(QPointF& pos) const; +#ifdef CONFIG_CLEANUP_NODE_NAMES + void cleanupNodeNames(const char *group); +#endif + private: // Mouse pointer dragging states. @@ -283,9 +295,9 @@ bool m_zoomrange; bool m_gesture; - qpwgraph_node::IdKeys m_node_ids; - qpwgraph_node::NodeKeys m_node_keys; - QList<qpwgraph_node *> m_nodes; + qpwgraph_node::NodeIds m_node_ids; + qpwgraph_node::NodeNames m_node_names; + QList<qpwgraph_node *> m_nodes; QUndoStack *m_commands; QSettings *m_settings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_item.cpp new/qpwgraph-v0.5.1/src/qpwgraph_item.cpp --- old/qpwgraph-v0.4.5/src/qpwgraph_item.cpp 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_item.cpp 2023-07-17 11:59:55.000000000 +0200 @@ -1,7 +1,7 @@ // qpwgraph_item.cpp // /**************************************************************************** - Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_item.h new/qpwgraph-v0.5.1/src/qpwgraph_item.h --- old/qpwgraph-v0.4.5/src/qpwgraph_item.h 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_item.h 2023-07-17 11:59:55.000000000 +0200 @@ -1,7 +1,7 @@ // qpwgraph_item.h // /**************************************************************************** - Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -133,6 +133,8 @@ uint m_type; }; + typedef QHash<IdKey, qpwgraph_item *> NameKeys; + // Item-type hash (static) static uint itemType(const QByteArray& type_name); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_node.cpp new/qpwgraph-v0.5.1/src/qpwgraph_node.cpp --- old/qpwgraph-v0.4.5/src/qpwgraph_node.cpp 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_node.cpp 2023-07-17 11:59:55.000000000 +0200 @@ -1,7 +1,7 @@ // qpwgraph_node.cpp // /**************************************************************************** - Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -69,8 +69,7 @@ QGraphicsPathItem::setFlag(QGraphicsItem::ItemIsMovable); QGraphicsPathItem::setFlag(QGraphicsItem::ItemIsSelectable); - QGraphicsPathItem::setToolTip(m_name); - setNodeTitle(m_name); + setNodeTitle(QString()); const bool is_darkest = (base_value < 24); QColor shadow_color = (is_darkest ? Qt::white : Qt::black); @@ -110,7 +109,7 @@ { m_name = name; - QGraphicsPathItem::setToolTip(m_name); + QGraphicsPathItem::setToolTip(nodeNameLabel()); } @@ -158,11 +157,43 @@ } +void qpwgraph_node::setNodeLabel ( const QString& label ) +{ + m_label = label; + + setNodeTitle(QString()); // reset title. +} + + +const QString& qpwgraph_node::nodeLabel (void) const +{ + return m_label; +} + + +QString qpwgraph_node::nodeNameLabel (void) const +{ + QString label = m_name; + + if (!m_label.isEmpty()) { + label += ' '; + label += '['; + label += m_label; + label += ']'; + } + + return label; +} + + void qpwgraph_node::setNodeTitle ( const QString& title ) { + const QString& name_label = nodeNameLabel(); + QGraphicsPathItem::setToolTip(name_label); + const QFont& font = m_text->font(); m_text->setFont(QFont(font.family(), font.pointSize(), QFont::Bold)); - m_title = (title.isEmpty() ? m_name : title); + m_title = (title.isEmpty() ? name_label : title); static const int MAX_TITLE_LENGTH = 29; static const QString ellipsis(3, '.'); @@ -175,9 +206,9 @@ } -QString qpwgraph_node::nodeTitle (void) const +const QString& qpwgraph_node::nodeTitle (void) const { - return m_title; // m_text->toPlainText(); + return m_title; } @@ -189,7 +220,7 @@ m_ports.append(port); m_port_ids.insert(qpwgraph_port::PortIdKey(port), port); - m_port_keys.insert(qpwgraph_port::PortNameKey(port), port); + m_port_names.insert(qpwgraph_port::PortNameKey(port), port); updatePath(); @@ -213,7 +244,7 @@ void qpwgraph_node::removePort ( qpwgraph_port *port ) { - m_port_keys.remove(qpwgraph_port::PortNameKey(port)); + m_port_names.remove(qpwgraph_port::PortNameKey(port)); m_port_ids.remove(qpwgraph_port::PortIdKey(port)); m_ports.removeAll(port); @@ -231,7 +262,7 @@ //qDeleteAll(m_ports); m_ports.clear(); m_port_ids.clear(); - m_port_keys.clear(); + m_port_names.clear(); } @@ -239,15 +270,14 @@ qpwgraph_port *qpwgraph_node::findPort ( uint id, qpwgraph_item::Mode mode, uint type ) { - return static_cast<qpwgraph_port *> ( - m_port_ids.value(qpwgraph_port::IdKey(id, mode, type), nullptr)); + return m_port_ids.value(qpwgraph_port::PortIdKey(id, mode, type), nullptr); } -QList<qpwgraph_port *> qpwgraph_node::findPorts ( +qpwgraph_port *qpwgraph_node::findPort ( const QString& name, qpwgraph_item::Mode mode, uint type ) { - return m_port_keys.values(qpwgraph_port::PortNameKey(name, mode, type)); + return m_port_names.value(qpwgraph_port::PortNameKey(name, mode, type), nullptr); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_node.h new/qpwgraph-v0.5.1/src/qpwgraph_node.h --- old/qpwgraph-v0.4.5/src/qpwgraph_node.h 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_node.h 2023-07-17 11:59:55.000000000 +0200 @@ -1,7 +1,7 @@ // qpwgraph_node.h // /**************************************************************************** - Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -65,8 +65,12 @@ void setNodeIcon(const QIcon& icon); const QIcon& nodeIcon() const; + void setNodeLabel(const QString& label); + const QString& nodeLabel() const; + QString nodeNameLabel() const; + void setNodeTitle(const QString& title); - QString nodeTitle() const; + const QString& nodeTitle() const; // Port-list methods. qpwgraph_port *addPort(uint id, const QString& name, Mode mode, int type = 0); @@ -79,7 +83,7 @@ // Port finder (by id/name, mode and type) qpwgraph_port *findPort(uint id, Mode mode, uint type = 0); - QList<qpwgraph_port *> findPorts(const QString& name, Mode mode, uint type = 0); + qpwgraph_port *findPort(const QString& name, Mode mode, uint type = 0); // Port-list accessor. const QList<qpwgraph_port *>& ports() const; @@ -99,6 +103,8 @@ : IdKey(node->nodeId(), node->nodeMode(), node->nodeType()) {} }; + typedef QMultiHash<IdKey, qpwgraph_node *> NodeIds; + // Node hash key (by name). class NodeNameKey : public NameKey { @@ -110,7 +116,7 @@ : NameKey(node->nodeName(), node->nodeMode(), node->nodeType()) {} }; - typedef QMultiHash<NodeNameKey, qpwgraph_node *> NodeKeys; + typedef QMultiHash<NodeNameKey, qpwgraph_node *> NodeNames; // Rectangular editor extents. QRectF editorRect() const; @@ -131,15 +137,15 @@ uint m_type; QIcon m_icon; - + QString m_label; QString m_title; QGraphicsPixmapItem *m_pixmap; QGraphicsTextItem *m_text; - qpwgraph_port::IdKeys m_port_ids; - qpwgraph_port::PortKeys m_port_keys; - QList<qpwgraph_port *> m_ports; + qpwgraph_port::PortIds m_port_ids; + qpwgraph_port::PortNames m_port_names; + QList<qpwgraph_port *> m_ports; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_patchbay.cpp new/qpwgraph-v0.5.1/src/qpwgraph_patchbay.cpp --- old/qpwgraph-v0.4.5/src/qpwgraph_patchbay.cpp 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_patchbay.cpp 2023-07-17 11:59:55.000000000 +0200 @@ -121,6 +121,10 @@ QDomElement eroot = nroot.toElement(); if (eroot.isNull()) continue; + #ifdef CONFIG_CLEANUP_NODE_NAMES + const bool cleanup + = (eroot.attribute("version") < "0.5.0"); + #endif if (eroot.tagName() == "items") { for (QDomNode nitem = eroot.firstChild(); !nitem.isNull(); @@ -148,6 +152,14 @@ port2 = eitem2.attribute("port"); } } + #ifdef CONFIG_CLEANUP_NODE_NAMES + if (cleanup) { // FIXME: Cleanup legacy node names... + if (qpwgraph_canvas::cleanupNodeName(node1)) + ++m_dirty; + if (qpwgraph_canvas::cleanupNodeName(node2)) + ++m_dirty; + } + #endif if (node_type > 0 && port_type > 0 && !node1.isEmpty() && !port1.isEmpty() && !node2.isEmpty() && !port2.isEmpty()) { @@ -178,36 +190,6 @@ doc.appendChild(eroot); QDomElement eitems = doc.createElement("items"); -#if 0//--direct snapshot! - QGraphicsScene *scene = m_canvas->scene(); - if (scene) foreach (QGraphicsItem *item, scene->items()) { - if (item->type() == qpwgraph_connect::Type) { - qpwgraph_connect *connect = static_cast<qpwgraph_connect *> (item); - if (connect) { - qpwgraph_port *port1 = connect->port1(); - qpwgraph_port *port2 = connect->port2(); - if (port1 && port2) { - qpwgraph_node *node1 = port1->portNode(); - qpwgraph_node *node2 = port2->portNode(); - if (node1 && node2) { - QDomElement eitem = doc.createElement("item"); - eitem.setAttribute("node-type", textFromNodeType(node1->nodeType())); - eitem.setAttribute("port-type", textFromPortType(port1->portType())); - QDomElement eitem1 = doc.createElement("output"); - eitem1.setAttribute("node", node1->nodeName()); - eitem1.setAttribute("port", port1->portName()); - eitem.appendChild(eitem1); - QDomElement eitem2 = doc.createElement("input"); - eitem2.setAttribute("node", node2->nodeName()); - eitem2.setAttribute("port", port2->portName()); - eitem.appendChild(eitem2); - eitems.appendChild(eitem); - } - } - } - } - } -#else Items::ConstIterator iter = m_items.constBegin(); const Items::ConstIterator& iter_end = m_items.constEnd(); for ( ; iter != iter_end; ++iter) { @@ -225,7 +207,6 @@ eitem.appendChild(eitem2); eitems.appendChild(eitem); } -#endif eroot.appendChild(eitems); QFile file(filename); @@ -261,75 +242,67 @@ const Items::ConstIterator& iter_end = m_items.constEnd(); for ( ; iter != iter_end; ++iter) { Item *item = iter.value(); - QList<qpwgraph_node *> nodes1 - = m_canvas->findNodes( + qpwgraph_node *node1 + = m_canvas->findNode( item->node1, qpwgraph_item::Output, item->node_type); - if (nodes1.isEmpty()) - nodes1 = m_canvas->findNodes( + if (node1 == nullptr) + node1 = m_canvas->findNode( item->node1, qpwgraph_item::Duplex, item->node_type); - if (nodes1.isEmpty()) + if (node1 == nullptr) + continue; + qpwgraph_port *port1 + = node1->findPort( + item->port1, + qpwgraph_item::Output, + item->port_type); + if (port1 == nullptr) + continue; + qpwgraph_node * node2 + = m_canvas->findNode( + item->node2, + qpwgraph_item::Input, + item->node_type); + if (node2 == nullptr) + node2 = m_canvas->findNode( + item->node2, + qpwgraph_item::Duplex, + item->node_type); + if (node2 == nullptr) + continue; + qpwgraph_port * port2 + = node2->findPort( + item->port2, + qpwgraph_item::Input, + item->port_type); + if (port2 == nullptr) continue; - foreach (qpwgraph_node *node1, nodes1) { - QList<qpwgraph_port *> ports1 - = node1->findPorts( - item->port1, - qpwgraph_item::Output, - item->port_type); - if (ports1.isEmpty()) - continue; - foreach (qpwgraph_port *port1, ports1) { - QList<qpwgraph_node *> nodes2 - = m_canvas->findNodes( - item->node2, - qpwgraph_item::Input, - item->node_type); - if (nodes2.isEmpty()) - nodes2 = m_canvas->findNodes( - item->node2, - qpwgraph_item::Duplex, - item->node_type); - if (nodes2.isEmpty()) + if (m_exclusive) { + foreach (qpwgraph_connect *connect, port1->connects()) { + qpwgraph_port *port3 = connect->port2(); + if (port3 == nullptr) continue; - foreach (qpwgraph_node *node2, nodes2) { - QList<qpwgraph_port *> ports2 - = node2->findPorts( - item->port2, - qpwgraph_item::Input, - item->port_type); - if (ports2.isEmpty()) + if (port3 != port2) { + qpwgraph_node *node3 = port3->portNode(); + if (node3 == nullptr) continue; - foreach (qpwgraph_port *port2, ports2) { - if (m_exclusive) { - foreach (qpwgraph_connect *connect, port1->connects()) { - qpwgraph_port *port3 = connect->port2(); - if (port3 == nullptr) - continue; - if (port3 != port2) { - qpwgraph_node *node3 = port3->portNode(); - if (node3 == nullptr) - continue; - const Item item2( - node1->nodeType(), - port1->portType(), - node1->nodeName(), - port1->portName(), - node3->nodeName(), - port3->portName()); - if (m_items.constFind(item2) == iter_end) - connects.insert(item2, connect); - } - } - } - if (!port1->findConnect(port2)) - m_canvas->emitConnected(port1, port2); - } + const Item item2( + node1->nodeType(), + port1->portType(), + node1->nodeName(), + port1->portName(), + node3->nodeName(), + port3->portName()); + if (m_items.constFind(item2) == iter_end) + connects.insert(item2, connect); } } } + if (!port1->findConnect(port2)) + m_canvas->emitConnected(port1, port2); } QHash<Item, qpwgraph_connect *>::ConstIterator iter2 = connects.constBegin(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_pipewire.cpp new/qpwgraph-v0.5.1/src/qpwgraph_pipewire.cpp --- old/qpwgraph-v0.4.5/src/qpwgraph_pipewire.cpp 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_pipewire.cpp 2023-07-17 11:59:55.000000000 +0200 @@ -27,7 +27,7 @@ #include <pipewire/pipewire.h> #include <QMutexLocker> - +#include <QMultiHash> #include <QTimer> @@ -103,6 +103,30 @@ Midi = 4 }; + struct NameKey + { + NameKey (Node *node) + : node_name(node->node_name), + node_mode(node->node_mode), + node_type(node->node_type) {} + + NameKey (const NameKey& key) + : node_name(key.node_name), + node_mode(key.node_mode), + node_type(key.node_type) {} + + bool operator== (const NameKey& key) const + { + return node_type == key.node_type + && node_mode == key.node_mode + && node_name == key.node_name; + } + + QString node_name; + qpwgraph_item::Mode node_mode; + uint node_type; + }; + QString node_name; qpwgraph_item::Mode node_mode; NodeType node_type; @@ -111,6 +135,7 @@ QString media_name; bool node_changed; bool node_ready; + uint name_num; }; struct qpwgraph_pipewire::Port : public qpwgraph_pipewire::Object @@ -157,8 +182,17 @@ int last_seq; int last_res; bool error; + + typedef QMultiHash<Node::NameKey, uint> NodeNames; + + NodeNames *node_names; }; +inline uint qHash ( const qpwgraph_pipewire::Node::NameKey& key ) +{ + return qHash(key.node_name) ^ qHash(uint(key.node_mode)) ^ qHash(key.node_type); +} + // sync-methods... static @@ -626,9 +660,6 @@ //---------------------------------------------------------------------------- // qpwgraph_pipewire -- PipeWire graph driver -QMutex qpwgraph_pipewire::g_mutex; - - // Constructor. qpwgraph_pipewire::qpwgraph_pipewire ( qpwgraph_canvas *canvas ) : qpwgraph_sect(canvas), m_data(nullptr) @@ -650,7 +681,7 @@ // Client methods. bool qpwgraph_pipewire::open (void) { - QMutexLocker locker(&g_mutex); + QMutexLocker locker1(&m_mutex1); pw_init(nullptr, nullptr); @@ -659,6 +690,8 @@ spa_list_init(&m_data->pending); m_data->pending_seq = 0; + m_data->node_names = new Data::NodeNames; + m_data->loop = pw_thread_loop_new("qpwgraph_thread_loop", nullptr); if (m_data->loop == nullptr) { qDebug("pw_thread_loop_new: Can't create thread loop."); @@ -715,7 +748,7 @@ if (m_data == nullptr) return; - QMutexLocker locker(&g_mutex); + QMutexLocker locker1(&m_mutex1); clearObjects(); @@ -738,6 +771,9 @@ if (m_data->loop) pw_thread_loop_destroy(m_data->loop); + if (m_data->node_names) + delete m_data->node_names; + delete m_data; m_data = nullptr; @@ -780,7 +816,7 @@ if (node1 == nullptr || node2 == nullptr) return; - QMutexLocker locker(&g_mutex); + QMutexLocker locker1(&m_mutex1); pw_thread_loop_lock(m_data->loop); @@ -939,6 +975,10 @@ if (add_new && *node == nullptr) { QString node_name = n->node_name; if ((p->port_flags & Port::Physical) == Port::None) { + if (n->name_num > 0) { + node_name += '-'; + node_name += QString::number(n->name_num); + } if (p->port_flags & Port::Monitor) { node_name += ' '; node_name += "[Monitor]"; @@ -947,15 +987,10 @@ node_name += ' '; node_name += "[Control]"; } - if (!n->media_name.isEmpty()) { - node_name += ' '; - node_name += '['; - node_name += n->media_name; - node_name += ']'; - } } *node = new qpwgraph_node(node_id, node_name, node_mode, node_type); (*node)->setNodeIcon(n->node_icon); + (*node)->setNodeLabel(n->media_name); n->node_changed = false; qpwgraph_sect::addItem(*node); } @@ -979,7 +1014,8 @@ #ifdef CONFIG_DEBUG qDebug("qpwgraph_pipewire::updateItems()"); #endif - QMutexLocker locker(&g_mutex); + QMutexLocker locker1(&m_mutex1); + QMutexLocker locker2(&m_mutex2); // 0. Check for core errors... // @@ -1059,7 +1095,7 @@ #ifdef CONFIG_DEBUG qDebug("qpwgraph_pipewire::clearItems()"); #endif - QMutexLocker locker(&g_mutex); + QMutexLocker locker1(&m_mutex1); // Clean-up all items... // @@ -1154,25 +1190,17 @@ void qpwgraph_pipewire::removeObjectEx ( uint id ) { - const bool locked - = g_mutex.tryLock(); + QMutexLocker locker2(&m_mutex2); removeObject(id); - - if (locked) - g_mutex.unlock(); } void qpwgraph_pipewire::addObjectEx ( uint id, Object *object ) { - const bool locked - = g_mutex.tryLock(); + QMutexLocker locker2(&m_mutex2); addObject(id, object); - - if (locked) - g_mutex.unlock(); } @@ -1198,6 +1226,19 @@ node->node_icon = qpwgraph_icon(":/images/itemPipewire.png"); node->node_changed = false; node->node_ready = false; + node->name_num = 0; + + Data::NodeNames *node_names = nullptr; + if (m_data) + node_names = m_data->node_names; + if (node_names) { + const Node::NameKey name_key(node); + Data::NodeNames::Iterator name_iter + = node_names->find(name_key, node->name_num); + while (name_iter != node_names->end()) + name_iter = node_names->find(name_key, ++(node->name_num)); + node_names->insert(name_key, node->name_num); + } addObjectEx(node_id, node); @@ -1207,6 +1248,12 @@ void qpwgraph_pipewire::destroyNode ( Node *node ) { + Data::NodeNames *node_names = nullptr; + if (m_data) + node_names = m_data->node_names; + if (node_names) + node_names->remove(Node::NameKey(node), node->name_num); + foreach (const Port *port, node->node_ports) removeObject(port->id); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_pipewire.h new/qpwgraph-v0.5.1/src/qpwgraph_pipewire.h --- old/qpwgraph-v0.4.5/src/qpwgraph_pipewire.h 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_pipewire.h 2023-07-17 11:59:55.000000000 +0200 @@ -148,7 +148,8 @@ QList<Object *> m_objects; // Callback sanity mutex. - static QMutex g_mutex; + QMutex m_mutex1; + QMutex m_mutex2; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_port.cpp new/qpwgraph-v0.5.1/src/qpwgraph_port.cpp --- old/qpwgraph-v0.4.5/src/qpwgraph_port.cpp 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_port.cpp 2023-07-17 11:59:55.000000000 +0200 @@ -59,9 +59,7 @@ QGraphicsPathItem::setAcceptHoverEvents(true); - QGraphicsPathItem::setToolTip(m_name); - - setPortTitle(m_name); + setPortTitle(QString()); } @@ -93,7 +91,7 @@ { m_name = name; - QGraphicsPathItem::setToolTip(m_name); + QGraphicsPathItem::setToolTip(portNameLabel()); } @@ -139,8 +137,39 @@ } +void qpwgraph_port::setPortLabel ( const QString& label ) +{ + m_label = label; + + setPortTitle(QString()); // reset title. +} + + +const QString& qpwgraph_port::portLabel (void) const +{ + return m_label; +} + + +QString qpwgraph_port::portNameLabel (void) const +{ + QString label = m_name; + + if (!m_label.isEmpty()) { + label += ' '; + label += '['; + label += m_label; + label += ']'; + } + + return label; +} + + void qpwgraph_port::setPortTitle ( const QString& title ) { + QGraphicsPathItem::setToolTip(portNameLabel()); + m_title = (title.isEmpty() ? m_name : title); static const int MAX_TITLE_LENGTH = 29; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/qpwgraph-v0.4.5/src/qpwgraph_port.h new/qpwgraph-v0.5.1/src/qpwgraph_port.h --- old/qpwgraph-v0.4.5/src/qpwgraph_port.h 2023-07-10 17:37:36.000000000 +0200 +++ new/qpwgraph-v0.5.1/src/qpwgraph_port.h 2023-07-17 11:59:55.000000000 +0200 @@ -69,6 +69,10 @@ void setPortType(uint type); uint portType() const; + void setPortLabel(const QString& label); + const QString& portLabel() const; + QString portNameLabel() const; + void setPortTitle(const QString& title); const QString& portTitle() const; @@ -101,10 +105,14 @@ { public: // Constructor. + PortIdKey (uint id, Mode mode, uint type = 0) + : IdKey(id, mode, type) {} PortIdKey(qpwgraph_port *port) : IdKey(port->portId(), port->portMode(), port->portType()) {} }; + typedef QHash<PortIdKey, qpwgraph_port *> PortIds; + // Port hash/map key (by name). class PortNameKey : public NameKey { @@ -116,7 +124,7 @@ : NameKey(port->portName(), port->portMode(), port->portType()) {} }; - typedef QMultiHash<PortNameKey, qpwgraph_port *> PortKeys; + typedef QHash<PortNameKey, qpwgraph_port *> PortNames; // Port sorting type. enum SortType { PortName = 0, PortTitle, PortIndex }; @@ -165,6 +173,7 @@ Mode m_mode; uint m_type; + QString m_label; QString m_title; int m_index;
