From 7fcea568c9c64f3bcebda21f0df02aa0107dfd0c Mon Sep 17 00:00:00 2001
From: Volker Hilsheimer <volker.hilsheimer@qt.io>
Date: Thu, 4 Apr 2024 15:55:10 +0200
Subject: [PATCH] Fix ABI breakage wrt QAudioSink/Source::stateChanged signals
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Amends edaec2bf714c98d65f12c8ed9a2ffbd1603635a7, which
removed the QAudioSink/Source::stateChanged(QAudio::State)
symbols from the API, thus breaking binary compatibility to
Qt 6.6. Since moc-generated code compares pointer-to-member-
functions, we cannot bring that symbol back and still have
such connections work.

The only reasonable way to fix this is to reverse the
namespace aliasing: QAudio is the real namespace, QtAudio
becomes an alias. All symbols are then exported with the
QAudio type in their signature, even if declared with
QtAudio types as parameters, so we don't need any removed_api
tricks to bring the old symbols back.

We just need to trick qdoc into seeing the namespace as
QtAudio, which is trivial and has no ABI implications. The
previous caveat that string-based connections need to use
QAudio doesn't change with this.

[ChangeLog][Binary Compatibility Note] Qt 6.7.0 broke binary
compatibility by renaming the QAudio namespace to QtAudio.
Qt 6.7.1 restores compatibility with previous Qt 6 versions
again by making QtAudio an alias for the QAudio namespace,
but breaks BC with 6.7.0. Code previously built against 6.7.0
needs to be recompiled.

Fixes: QTBUG-123997
Change-Id: I456db61ff0bd1d97af7ce2d2a7968999d891a84d
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
(cherry picked from commit 6f590d44bb186178902a5fc3dc4a12cee8e88eaa)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
 src/multimedia/audio/qaudio.h         |  8 +++-
 src/multimedia/audio/qaudiosink.cpp   |  4 +-
 src/multimedia/audio/qaudiosink.h     | 15 +++-----
 src/multimedia/audio/qaudiosource.cpp |  4 +-
 src/multimedia/audio/qaudiosource.h   | 15 +++-----
 src/multimedia/audio/qtaudio.cpp      |  4 ++
 src/multimedia/compat/removed_api.cpp | 55 ---------------------------
 7 files changed, 26 insertions(+), 79 deletions(-)

diff --git a/src/multimedia/audio/qaudio.h b/src/multimedia/audio/qaudio.h
index b569b3a15c..5ae994b9f0 100644
--- a/src/multimedia/audio/qaudio.h
+++ b/src/multimedia/audio/qaudio.h
@@ -19,7 +19,11 @@ QT_BEGIN_NAMESPACE
 // Class forward declaration required for QDoc bug
 class QString;
 
+#if defined(Q_QDOC)
 namespace QtAudio
+#else
+namespace QAudio
+#endif
 {
     enum Error { NoError, OpenError, IOError, UnderrunError, FatalError };
     enum State { ActiveState, SuspendedState, StoppedState, IdleState };
@@ -34,8 +38,8 @@ namespace QtAudio
     Q_MULTIMEDIA_EXPORT float convertVolume(float volume, VolumeScale from, VolumeScale to);
 }
 
-#if !defined(Q_QDOC) && !QT_MULTIMEDIA_REMOVED_SINCE(6, 7)
-namespace QAudio = QtAudio;
+#if !defined(Q_QDOC)
+namespace QtAudio = QAudio;
 #endif
 
 #ifndef QT_NO_DEBUG_STREAM
diff --git a/src/multimedia/audio/qaudiosink.cpp b/src/multimedia/audio/qaudiosink.cpp
index aac96c342d..12263d32a2 100644
--- a/src/multimedia/audio/qaudiosink.cpp
+++ b/src/multimedia/audio/qaudiosink.cpp
@@ -279,7 +279,7 @@ qint64 QAudioSink::elapsedUSecs() const
 /*!
     Returns the error state.
 */
-QtAudio::Error QAudioSink::error(QT6_IMPL_NEW_OVERLOAD) const
+QtAudio::Error QAudioSink::error() const
 {
     return d ? d->error() : QAudio::OpenError;
 }
@@ -287,7 +287,7 @@ QtAudio::Error QAudioSink::error(QT6_IMPL_NEW_OVERLOAD) const
 /*!
     Returns the state of audio processing.
 */
-QtAudio::State QAudioSink::state(QT6_IMPL_NEW_OVERLOAD) const
+QtAudio::State QAudioSink::state() const
 {
     return d ? d->state() : QAudio::StoppedState;
 }
diff --git a/src/multimedia/audio/qaudiosink.h b/src/multimedia/audio/qaudiosink.h
index 7a4eb732ae..e071e6fbc5 100644
--- a/src/multimedia/audio/qaudiosink.h
+++ b/src/multimedia/audio/qaudiosink.h
@@ -49,21 +49,18 @@ class Q_MULTIMEDIA_EXPORT QAudioSink : public QObject
     qint64 processedUSecs() const;
     qint64 elapsedUSecs() const;
 
-#if QT_MULTIMEDIA_REMOVED_SINCE(6, 7)
-    QAudio::Error error() const;
-    QAudio::State state() const;
-#endif
-    QtAudio::Error error(QT6_DECL_NEW_OVERLOAD) const;
-    QtAudio::State state(QT6_DECL_NEW_OVERLOAD) const;
+    QtAudio::Error error() const;
+    QtAudio::State state() const;
 
     void setVolume(qreal);
     qreal volume() const;
 
 Q_SIGNALS:
-#ifdef Q_MOC_RUN
-    void stateChanged(QAudio::State state);
-#else
+#if defined(Q_QDOC)
     void stateChanged(QtAudio::State state);
+#else
+    // use QAudio here to keep string-based connections working
+    void stateChanged(QAudio::State state);
 #endif
 
 private:
diff --git a/src/multimedia/audio/qaudiosource.cpp b/src/multimedia/audio/qaudiosource.cpp
index 5e59a47986..1ed5e82bcf 100644
--- a/src/multimedia/audio/qaudiosource.cpp
+++ b/src/multimedia/audio/qaudiosource.cpp
@@ -340,7 +340,7 @@ qint64 QAudioSource::elapsedUSecs() const
     Returns the error state.
 */
 
-QtAudio::Error QAudioSource::error(QT6_IMPL_NEW_OVERLOAD) const
+QtAudio::Error QAudioSource::error() const
 {
     return d ? d->error() : QAudio::OpenError;
 }
@@ -349,7 +349,7 @@ QtAudio::Error QAudioSource::error(QT6_IMPL_NEW_OVERLOAD) const
     Returns the state of audio processing.
 */
 
-QtAudio::State QAudioSource::state(QT6_IMPL_NEW_OVERLOAD) const
+QtAudio::State QAudioSource::state() const
 {
     return d ? d->state() : QAudio::StoppedState;
 }
diff --git a/src/multimedia/audio/qaudiosource.h b/src/multimedia/audio/qaudiosource.h
index 71c5446eeb..f0ad0ceb5e 100644
--- a/src/multimedia/audio/qaudiosource.h
+++ b/src/multimedia/audio/qaudiosource.h
@@ -50,18 +50,15 @@ class Q_MULTIMEDIA_EXPORT QAudioSource : public QObject
     qint64 processedUSecs() const;
     qint64 elapsedUSecs() const;
 
-#if QT_MULTIMEDIA_REMOVED_SINCE(6, 7)
-    QAudio::Error error() const;
-    QAudio::State state() const;
-#endif
-    QtAudio::Error error(QT6_DECL_NEW_OVERLOAD) const;
-    QtAudio::State state(QT6_DECL_NEW_OVERLOAD) const;
+    QtAudio::Error error() const;
+    QtAudio::State state() const;
 
 Q_SIGNALS:
-#ifdef Q_MOC_RUN
-    void stateChanged(QAudio::State state);
-#else
+#if defined(Q_QDOC)
     void stateChanged(QtAudio::State state);
+#else
+    // use QAudio here to keep string-based connections working
+    void stateChanged(QAudio::State state);
 #endif
 
 private:
diff --git a/src/multimedia/audio/qtaudio.cpp b/src/multimedia/audio/qtaudio.cpp
index 999248bb6b..fb14e50934 100644
--- a/src/multimedia/audio/qtaudio.cpp
+++ b/src/multimedia/audio/qtaudio.cpp
@@ -62,7 +62,11 @@ QT_BEGIN_NAMESPACE
     \sa QtAudio::convertVolume()
 */
 
+#if defined(Q_QDOC)
 namespace QtAudio
+#else
+namespace QAudio
+#endif
 {
 
 /*!
diff --git a/src/multimedia/compat/removed_api.cpp b/src/multimedia/compat/removed_api.cpp
index 15e92c4141..567024c8e4 100644
--- a/src/multimedia/compat/removed_api.cpp
+++ b/src/multimedia/compat/removed_api.cpp
@@ -9,61 +9,6 @@ QT_USE_NAMESPACE
 
 #if QT_MULTIMEDIA_REMOVED_SINCE(6, 7)
 
-// implement removed functions from qaudio.h
-#include <QtMultimedia/qaudio.h>
-#include <qdebug.h>
-
-namespace QAudio
-{
-    enum VolumeScale {};
-    enum Error {};
-    enum State {};
-    Q_MULTIMEDIA_EXPORT float convertVolume(float volume, QAudio::VolumeScale from, QAudio::VolumeScale to)
-    {
-        return QtAudio::convertVolume(volume, static_cast<QtAudio::VolumeScale>(from),
-                                              static_cast<QtAudio::VolumeScale>(to));
-    }
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::Error error)
-{
-    return dbg << static_cast<QtAudio::Error>(error);
-}
-Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::State state)
-{
-    return dbg << static_cast<QtAudio::State>(state);
-}
-Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::VolumeScale role)
-{
-    return dbg << static_cast<QtAudio::VolumeScale>(role);
-}
-#endif
-
-#include <QtMultimedia/qaudiosink.h>
-
-QAudio::Error QAudioSink::error() const
-{
-    return static_cast<QAudio::Error>(error(QT6_CALL_NEW_OVERLOAD));
-}
-
-QAudio::State QAudioSink::state() const
-{
-    return static_cast<QAudio::State>(state(QT6_CALL_NEW_OVERLOAD));
-}
-
-#include <QtMultimedia/qaudiosource.h>
-
-QAudio::Error QAudioSource::error() const
-{
-    return static_cast<QAudio::Error>(error(QT6_CALL_NEW_OVERLOAD));
-}
-
-QAudio::State QAudioSource::state() const
-{
-    return static_cast<QAudio::State>(state(QT6_CALL_NEW_OVERLOAD));
-}
-
 // #include "qotherheader.h"
 // // implement removed functions from qotherheader.h
 // order sections alphabetically
