Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package pulseaudio-qt for openSUSE:Factory 
checked in at 2024-09-15 12:33:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/pulseaudio-qt (Old)
 and      /work/SRC/openSUSE:Factory/.pulseaudio-qt.new.29891 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "pulseaudio-qt"

Sun Sep 15 12:33:16 2024 rev:7 rq:1200840 version:1.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/pulseaudio-qt/pulseaudio-qt.changes      
2024-05-28 17:29:20.681162742 +0200
+++ /work/SRC/openSUSE:Factory/.pulseaudio-qt.new.29891/pulseaudio-qt.changes   
2024-09-15 12:33:54.950308426 +0200
@@ -1,0 +2,11 @@
+Thu Sep 12 17:49:26 UTC 2024 - Fabian Vogt <fab...@ritter-vogt.de>
+
+- Update to 1.6.0:
+  * context: model states & auto-(re)connect
+  * context: refine autoconnect behavior
+  * verbosity--
+  * server: detect if wireplumber is running
+  * Add since version to new API
+  * Bump version to 1.6.0
+
+-------------------------------------------------------------------

Old:
----
  pulseaudio-qt-1.5.0.tar.xz
  pulseaudio-qt-1.5.0.tar.xz.sig

New:
----
  pulseaudio-qt-1.6.0.tar.xz
  pulseaudio-qt-1.6.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ pulseaudio-qt.spec ++++++
--- /var/tmp/diff_new_pack.QfgSqD/_old  2024-09-15 12:33:55.810344055 +0200
+++ /var/tmp/diff_new_pack.QfgSqD/_new  2024-09-15 12:33:55.810344055 +0200
@@ -32,7 +32,7 @@
 %define rname pulseaudio-qt
 %bcond_without released
 Name:           pulseaudio-qt%{?pkg_suffix}
-Version:        1.5.0
+Version:        1.6.0
 Release:        0
 Summary:        Qt bindings for PulseAudio
 License:        LGPL-2.1-or-later

++++++ pulseaudio-qt-1.5.0.tar.xz -> pulseaudio-qt-1.6.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/CMakeLists.txt 
new/pulseaudio-qt-1.6.0/CMakeLists.txt
--- old/pulseaudio-qt-1.5.0/CMakeLists.txt      2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/CMakeLists.txt      2024-09-12 17:15:02.000000000 
+0200
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.16)
 
-set(PROJECT_VERSION 1.5.0)
+set(PROJECT_VERSION 1.6.0)
 
 project(PulseAudioQt VERSION ${PROJECT_VERSION})
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/src/context.cpp 
new/pulseaudio-qt-1.6.0/src/context.cpp
--- old/pulseaudio-qt-1.5.0/src/context.cpp     2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/src/context.cpp     2024-09-12 17:15:02.000000000 
+0200
@@ -249,6 +249,10 @@
     : QObject(parent)
     , d(new ContextPrivate(this))
 {
+    connect(this, &Context::stateChanged, this, [this] {
+        qCDebug(PULSEAUDIOQT) << "context state changed:" << d->m_state;
+    });
+
     d->m_server = new Server(this);
     d->m_context = nullptr;
     d->m_mainloop = nullptr;
@@ -262,6 +266,7 @@
     });
 
     connect(&d->m_connectTimer, &QTimer::timeout, this, [this] {
+        d->forceDisconnect();
         d->connectToDaemon();
         d->checkConnectTries();
     });
@@ -447,11 +452,35 @@
 
 void ContextPrivate::contextStateCallback(pa_context *c)
 {
-    qCDebug(PULSEAUDIOQT) << "state callback";
     pa_context_state_t state = pa_context_get_state(c);
+    qCDebug(PULSEAUDIOQT) << "state callback" << state;
+
+    m_state = [state]() -> Context::State {
+        switch (state) {
+        case PA_CONTEXT_UNCONNECTED:
+            return Context::State::Unconnected;
+        case PA_CONTEXT_CONNECTING:
+            return Context::State::Connecting;
+        case PA_CONTEXT_AUTHORIZING:
+            return Context::State::Authorizing;
+        case PA_CONTEXT_SETTING_NAME:
+            return Context::State::SettingName;
+        case PA_CONTEXT_READY:
+            return Context::State::Ready;
+        case PA_CONTEXT_FAILED:
+            return Context::State::Failed;
+        case PA_CONTEXT_TERMINATED:
+            return Context::State::Terminated;
+        }
+        return Context::State::Unconnected;
+    }();
+    // Queue state changes to avoid race conditions with changes going on 
below in the code. It's not time critical anyway.
+    QMetaObject::invokeMethod(q, &Context::stateChanged, Qt::QueuedConnection);
+
     if (state == PA_CONTEXT_READY) {
         qCDebug(PULSEAUDIOQT) << "ready, stopping connect timer";
         m_connectTimer.stop();
+        Q_EMIT q->autoConnectingChanged();
 
         // 1. Register for the stream changes (except during probe)
         if (m_context == c) {
@@ -521,9 +550,12 @@
             pa_context_unref(m_context);
             m_context = nullptr;
         }
-        reset();
-        qCDebug(PULSEAUDIOQT) << "Starting connect timer";
-        m_connectTimer.start(std::chrono::seconds(5));
+        if (!m_connectTimer.isActive() && hasConnectionTriesLeft()) {
+            reset();
+            qCDebug(PULSEAUDIOQT) << "Starting connect timer";
+            m_connectTimer.start(std::chrono::seconds(5));
+            Q_EMIT q->autoConnectingChanged();
+        }
     }
 }
 
@@ -650,6 +682,11 @@
         return;
     }
 
+    qCDebug(PULSEAUDIOQT) << "Connecting to daemon.";
+
+    m_state = Context::State::Connecting;
+    Q_EMIT q->stateChanged();
+
     // We require a glib event loop
     if 
(!QByteArray(QAbstractEventDispatcher::instance()->metaObject()->className()).contains("Glib"))
 {
         qCWarning(PULSEAUDIOQT) << "Disabling PulseAudio integration for lack 
of GLib event loop";
@@ -678,10 +715,14 @@
     Q_ASSERT(m_context);
 
     if (pa_context_connect(m_context, NULL, PA_CONTEXT_NOFAIL, nullptr) < 0) {
+        qCWarning(PULSEAUDIOQT) << "Failed to connect context";
         pa_context_unref(m_context);
         pa_glib_mainloop_free(m_mainloop);
+        // Don't reset() here, it'd reset the retry count and possibly lead to 
infinite retries.
         m_context = nullptr;
         m_mainloop = nullptr;
+        m_state = Context::State::Unconnected;
+        Q_EMIT q->stateChanged();
         return;
     }
     pa_context_set_state_callback(m_context, &context_state_callback, this);
@@ -689,9 +730,10 @@
 
 void ContextPrivate::checkConnectTries()
 {
-    if (++m_connectTries == 5) {
+    if (++m_connectTries; !hasConnectionTriesLeft()) {
         qCWarning(PULSEAUDIOQT) << "Giving up after" << m_connectTries << 
"tries to connect";
         m_connectTimer.stop();
+        Q_EMIT q->autoConnectingChanged();
     }
 }
 
@@ -707,6 +749,8 @@
     m_streamRestores.reset();
     m_server->reset();
     m_connectTries = 0;
+    m_state = Context::State::Unconnected;
+    Q_EMIT q->stateChanged();
 }
 
 bool Context::isValid()
@@ -861,4 +905,44 @@
     return d->m_context;
 }
 
+Context::State Context::state() const
+{
+    return d->m_state;
+}
+
+bool Context::isAutoConnecting() const
+{
+    return d->m_connectTimer.isActive();
+}
+
+void Context::reconnectDaemon()
+{
+    if (isAutoConnecting()) { // must not be in the dptr; the dptr function is 
called by the auto connecting logic
+        qCDebug(PULSEAUDIOQT) << "Already in the process of auto connecting. 
Not connecting again.";
+        return;
+    }
+
+    d->forceDisconnect();
+    return d->connectToDaemon();
+}
+
+void ContextPrivate::forceDisconnect()
+{
+    if (m_context) {
+        pa_context_unref(m_context);
+        m_context = nullptr;
+    }
+
+    if (m_mainloop) {
+        pa_glib_mainloop_free(m_mainloop);
+        m_mainloop = nullptr;
+    }
+}
+
+bool ContextPrivate::hasConnectionTriesLeft() const
+{
+    constexpr auto maxTries = 5;
+    return m_connectTries < maxTries;
+}
+
 } // PulseAudioQt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/src/context.h 
new/pulseaudio-qt-1.6.0/src/context.h
--- old/pulseaudio-qt-1.5.0/src/context.h       2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/src/context.h       2024-09-12 17:15:02.000000000 
+0200
@@ -49,8 +49,36 @@
 class PULSEAUDIOQT_EXPORT Context : public QObject
 {
     Q_OBJECT
+    /**
+     * The state of the Context. This is further augmented by the 
autoConnecting property.
+     *
+     * @since 1.6
+     */
+    Q_PROPERTY(State state READ state NOTIFY stateChanged)
+    /**
+     * Regardless of the state, this property indicates whether the Context is 
presently trying to
+     * automatically establish a connection. When this is false it may be 
useful to give the
+     * user a manual way to trigger a connection attempt. AutoConnecting is 
subject to internal
+     * timeouts that when hit will prevent further auto connecting until the 
Context managed to
+     * connect.
+     */
+    Q_PROPERTY(bool autoConnecting READ isAutoConnecting NOTIFY 
autoConnectingChanged)
 
 public:
+    /**
+     * @since 1.6
+     */
+    enum class State {
+        Unconnected = 0,
+        Connecting,
+        Authorizing,
+        SettingName,
+        Ready,
+        Failed,
+        Terminated,
+    };
+    Q_ENUM(State)
+
     ~Context() override;
 
     static Context *instance();
@@ -131,6 +159,28 @@
     void setDefaultSink(const QString &name);
     void setDefaultSource(const QString &name);
 
+    /**
+     * @returns the state of the context.
+     *
+     * @since 1.6
+     */
+    [[nodiscard]] State state() const;
+
+    /**
+     * @returns whether the Context is currently trying to auto-connect to the 
daemon
+     *
+     * @since 1.6
+     */
+    [[nodiscard]] bool isAutoConnecting() const;
+
+public Q_SLOTS:
+    /**
+     * When the Context is not auto-connecting this may be used to give the 
user a manual trigger (e.g. a button)
+     *
+     * @since 1.6
+     */
+    void reconnectDaemon();
+
 Q_SIGNALS:
     /**
      * Indicates that sink was added.
@@ -212,6 +262,20 @@
      */
     void streamRestoreRemoved(PulseAudioQt::StreamRestore *streamRestore);
 
+    /**
+     * Context state changed.
+     *
+     * @since 1.6
+     */
+    void stateChanged();
+
+    /**
+     * Indicates that autoConnecting changed.
+     *
+     * @since 1.6
+     */
+    void autoConnectingChanged();
+
 private:
     explicit Context(QObject *parent = nullptr);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/src/context_p.h 
new/pulseaudio-qt-1.6.0/src/context_p.h
--- old/pulseaudio-qt-1.5.0/src/context_p.h     2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/src/context_p.h     2024-09-12 17:15:02.000000000 
+0200
@@ -6,6 +6,7 @@
 #ifndef CONTEXT_P_H
 #define CONTEXT_P_H
 
+#include "context.h"
 #include "maps.h"
 #include "operation.h"
 #include <QTimer>
@@ -45,6 +46,7 @@
 
     QTimer m_connectTimer;
     int m_connectTries;
+    Context::State m_state = Context::State::Unconnected;
 
     static QString s_applicationId;
 
@@ -80,6 +82,8 @@
     void reset();
     void connectToDaemon();
     void checkConnectTries();
+    void forceDisconnect();
+    [[nodiscard]] bool hasConnectionTriesLeft() const;
 
     Context *q;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/src/models.cpp 
new/pulseaudio-qt-1.6.0/src/models.cpp
--- old/pulseaudio-qt-1.5.0/src/models.cpp      2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/src/models.cpp      2024-09-12 17:15:02.000000000 
+0200
@@ -65,7 +65,6 @@
 QHash<int, QByteArray> AbstractModel::roleNames() const
 {
     if (!d->m_roles.empty()) {
-        qCDebug(PULSEAUDIOQT) << "returning roles" << d->m_roles;
         return d->m_roles;
     }
     Q_UNREACHABLE();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/src/server.cpp 
new/pulseaudio-qt-1.6.0/src/server.cpp
--- old/pulseaudio-qt-1.5.0/src/server.cpp      2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/src/server.cpp      2024-09-12 17:15:02.000000000 
+0200
@@ -13,6 +13,8 @@
 #include "sink.h"
 #include "source.h"
 
+using namespace std::chrono_literals;
+
 namespace PulseAudioQt
 {
 Server::Server(Context *context)
@@ -25,6 +27,17 @@
     connect(&context->d->m_sinks, &MapBaseQObject::removed, this, 
&Server::updateDefaultDevices);
     connect(&context->d->m_sources, &MapBaseQObject::added, this, 
&Server::updateDefaultDevices);
     connect(&context->d->m_sources, &MapBaseQObject::removed, this, 
&Server::updateDefaultDevices);
+
+    // WirePlumber detection works based on connected clients.
+    // Since we act on individual client changes let's compress them otherwise 
we may be switching state multiple times
+    // for no reason.
+    d->m_wirePlumberFindTimer.setInterval(250ms); // arbitrary compression time
+    d->m_wirePlumberFindTimer.setSingleShot(true);
+    connect(&d->m_wirePlumberFindTimer, &QTimer::timeout, this, [this] {
+        d->findWirePlumber();
+    });
+    connect(&context->d->m_clients, &MapBaseQObject::added, 
&d->m_wirePlumberFindTimer, qOverload<>(&QTimer::start));
+    connect(&context->d->m_clients, &MapBaseQObject::removed, 
&d->m_wirePlumberFindTimer, qOverload<>(&QTimer::start));
 }
 
 Server::~Server()
@@ -136,4 +149,28 @@
     return d->m_isPipeWire;
 }
 
+void ServerPrivate::findWirePlumber()
+{
+    if (!m_isPipeWire) {
+        return;
+    }
+
+    const auto clients = Context::instance()->clients();
+    for (const auto &client : clients) {
+        if (client->properties().value(QStringLiteral("wireplumber.daemon")) 
== QLatin1String("true")) {
+            m_hasWirePlumber = true;
+            Q_EMIT q->hasWirePlumberChanged();
+            return;
+        }
+    }
+
+    // Found no plumber, mark false
+    m_hasWirePlumber = false;
+    Q_EMIT q->hasWirePlumberChanged();
+}
+
+bool Server::hasWirePlumber() const
+{
+    return d->m_hasWirePlumber;
+}
 } // PulseAudioQt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/src/server.h 
new/pulseaudio-qt-1.6.0/src/server.h
--- old/pulseaudio-qt-1.5.0/src/server.h        2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/src/server.h        2024-09-12 17:15:02.000000000 
+0200
@@ -26,6 +26,8 @@
     Q_PROPERTY(Source *defaultSource READ defaultSource NOTIFY 
defaultSourceChanged)
     /// Whether the connected Server is PipeWire (rather than PulseAudio)
     Q_PROPERTY(bool isPipeWire READ isPipeWire NOTIFY isPipeWireChanged)
+    /// Whether the connected PipeWire is driven by WirePlumber
+    Q_PROPERTY(bool hasWirePlumber READ hasWirePlumber NOTIFY 
hasWirePlumberChanged)
 public:
     ~Server() override;
 
@@ -40,11 +42,19 @@
      */
     bool isPipeWire() const;
 
+    /**
+     * Whether WirePlumber is running in addition to PipeWire.
+     *
+     * @since 1.6
+     */
+    [[nodiscard]] bool hasWirePlumber() const;
+
 Q_SIGNALS:
     void defaultSinkChanged(PulseAudioQt::Sink *sink);
     void defaultSourceChanged(PulseAudioQt::Source *source);
     void isPipeWireChanged();
     void updated();
+    void hasWirePlumberChanged();
 
 private:
     explicit Server(Context *context);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pulseaudio-qt-1.5.0/src/server_p.h 
new/pulseaudio-qt-1.6.0/src/server_p.h
--- old/pulseaudio-qt-1.5.0/src/server_p.h      2024-05-24 19:11:26.000000000 
+0200
+++ new/pulseaudio-qt-1.6.0/src/server_p.h      2024-09-12 17:15:02.000000000 
+0200
@@ -7,6 +7,8 @@
 #include "server.h"
 #include <pulse/introspect.h>
 
+#include <QTimer>
+
 namespace PulseAudioQt
 {
 class ServerPrivate
@@ -22,7 +24,10 @@
     Sink *m_defaultSink;
     Source *m_defaultSource;
     bool m_isPipeWire = false;
+    bool m_hasWirePlumber = false;
+    QTimer m_wirePlumberFindTimer;
 
     void update(const pa_server_info *info);
+    void findWirePlumber();
 };
 }

Reply via email to