summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2022-05-22 11:15:20 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2022-05-23 12:28:30 +0200
commit2030dbd190c3b3cd23a4ab1460e6a987a210d641 (patch)
tree5f76c1d0acf3ff56a84efbd782f6e9ce7cbe3bbc
parent616e78c68b524cf5487947762bfe24784b40b66c (diff)
Clean up QPulseAudioSink implementation
Use categorized logging, with logging helpers converted to inline statics and using literal operators. Use member initialization and reorganize members to avoid padding. Remove unused data members, and replace the QTimer with a QBasicTimer, as QPlatformAudioSink is a QObject already. Minor changes to coding style. Pick-to: 6.3 Change-Id: I1aeb909fdcacea50bf9c80c0aeee7c9fa5c15020 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/multimedia/pulseaudio/qpulseaudiosink.cpp151
-rw-r--r--src/multimedia/pulseaudio/qpulseaudiosink_p.h51
-rw-r--r--src/multimedia/pulseaudio/qpulsehelpers.cpp58
-rw-r--r--src/multimedia/pulseaudio/qpulsehelpers_p.h63
4 files changed, 161 insertions, 162 deletions
diff --git a/src/multimedia/pulseaudio/qpulseaudiosink.cpp b/src/multimedia/pulseaudio/qpulseaudiosink.cpp
index 9cebf3677..bef29580c 100644
--- a/src/multimedia/pulseaudio/qpulseaudiosink.cpp
+++ b/src/multimedia/pulseaudio/qpulseaudiosink.cpp
@@ -49,6 +49,8 @@
#include <sys/types.h>
#include <unistd.h>
+Q_DECLARE_LOGGING_CATEGORY(qLcPulseAudio)
+
QT_BEGIN_NAMESPACE
const int PeriodTimeMs = 20;
@@ -58,9 +60,8 @@ const int PeriodTimeMs = 20;
static void outputStreamWriteCallback(pa_stream *stream, size_t length, void *userdata)
{
Q_UNUSED(stream);
- Q_UNUSED(length);
Q_UNUSED(userdata);
-// qDebug() << "write callback!" << length;
+ qCDebug(qLcPulseAudioOut) << "Write callback:" << length;
QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
}
@@ -69,9 +70,7 @@ static void outputStreamStateCallback(pa_stream *stream, void *userdata)
{
Q_UNUSED(userdata);
pa_stream_state_t state = pa_stream_get_state(stream);
-#ifdef DEBUG_PULSE
- qDebug() << "Stream state: " << QPulseAudioInternal::stateToQString(state);
-#endif
+ qCDebug(qLcPulseAudioOut) << "Stream state callback:" << state;
switch (state) {
case PA_STREAM_CREATING:
case PA_STREAM_READY:
@@ -90,15 +89,16 @@ static void outputStreamStateCallback(pa_stream *stream, void *userdata)
static void outputStreamUnderflowCallback(pa_stream *stream, void *userdata)
{
Q_UNUSED(stream);
-// qWarning() << "Got a buffer underflow!";
- ((QPulseAudioSink*)userdata)->streamUnderflowCallback();
+ qCDebug(qLcPulseAudioOut) << "Buffer underflow";
+ if (userdata)
+ static_cast<QPulseAudioSink *>(userdata)->streamUnderflowCallback();
}
static void outputStreamOverflowCallback(pa_stream *stream, void *userdata)
{
Q_UNUSED(stream);
Q_UNUSED(userdata);
- qWarning() << "Got a buffer overflow!";
+ qCDebug(qLcPulseAudioOut) << "Buffer overflow";
}
static void outputStreamLatencyCallback(pa_stream *stream, void *userdata)
@@ -106,25 +106,25 @@ static void outputStreamLatencyCallback(pa_stream *stream, void *userdata)
Q_UNUSED(stream);
Q_UNUSED(userdata);
-#ifdef DEBUG_PULSE
- const pa_timing_info *info = pa_stream_get_timing_info(stream);
+ if (Q_UNLIKELY(qLcPulseAudioOut().isEnabled(QtDebugMsg))) {
+ const pa_timing_info *info = pa_stream_get_timing_info(stream);
- qDebug() << "Latency callback:";
- qDebug() << "Write index corrupt: " << info->write_index_corrupt;
- qDebug() << "Write index: " << info->write_index;
- qDebug() << "Read index corrupt: " << info->read_index_corrupt;
- qDebug() << "Read index: " << info->read_index;
- qDebug() << "Sink usec: " << info->sink_usec;
- qDebug() << "Configured sink usec: " << info->configured_sink_usec;
-#endif
+ qCDebug(qLcPulseAudioOut) << "Latency callback:";
+ qCDebug(qLcPulseAudioOut) << "\tWrite index corrupt: " << info->write_index_corrupt;
+ qCDebug(qLcPulseAudioOut) << "\tWrite index: " << info->write_index;
+ qCDebug(qLcPulseAudioOut) << "\tRead index corrupt: " << info->read_index_corrupt;
+ qCDebug(qLcPulseAudioOut) << "\tRead index: " << info->read_index;
+ qCDebug(qLcPulseAudioOut) << "\tSink usec: " << info->sink_usec;
+ qCDebug(qLcPulseAudioOut) << "\tConfigured sink usec: " << info->configured_sink_usec;
+ }
}
static void outputStreamSuccessCallback(pa_stream *stream, int success, void *userdata)
{
Q_UNUSED(stream);
- Q_UNUSED(success);
Q_UNUSED(userdata);
+ qCDebug(qLcPulseAudioOut) << "Stream successful:" << success;
QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
}
@@ -132,12 +132,8 @@ static void outputStreamSuccessCallback(pa_stream *stream, int success, void *us
static void outputStreamDrainComplete(pa_stream *stream, int success, void *userdata)
{
Q_UNUSED(stream);
- Q_UNUSED(success);
- Q_UNUSED(userdata);
-#ifdef DEBUG_PULSE
- qDebug() << "Draining completed successfully: " << (bool)success;
-#endif
+ qCDebug(qLcPulseAudioOut) << "Stream drained:" << bool(success) << userdata;
}
static void streamAdjustPrebufferCallback(pa_stream *stream, int success, void *userdata)
@@ -146,37 +142,18 @@ static void streamAdjustPrebufferCallback(pa_stream *stream, int success, void *
Q_UNUSED(success);
Q_UNUSED(userdata);
-#ifdef DEBUG_PULSE
- qDebug() << "Adjust prebuffer completed successfully: " << (bool)success;
-#endif
+ qCDebug(qLcPulseAudioOut) << "Prebuffer adjusted:" << bool(success);
}
QPulseAudioSink::QPulseAudioSink(const QByteArray &device)
: m_device(device)
- , m_errorState(QAudio::NoError)
- , m_deviceState(QAudio::StoppedState)
- , m_pullMode(true)
- , m_opened(false)
- , m_audioSource(nullptr)
- , m_periodTime(0)
- , m_stream(nullptr)
- , m_periodSize(0)
- , m_bufferSize(0)
- , m_maxBufferSize(0)
- , m_totalTimeValue(0)
- , m_tickTimer(new QTimer(this))
- , m_audioBuffer(nullptr)
- , m_resuming(false)
- , m_volume(1.0)
-{
- connect(m_tickTimer, SIGNAL(timeout()), SLOT(userFeed()));
+{
}
QPulseAudioSink::~QPulseAudioSink()
{
close();
- disconnect(m_tickTimer, SIGNAL(timeout()));
QCoreApplication::processEvents();
}
@@ -222,9 +199,8 @@ void QPulseAudioSink::start(QIODevice *device)
setError(QAudio::NoError);
// Handle change of mode
- if (m_audioSource && !m_pullMode) {
+ if (m_audioSource && !m_pullMode)
delete m_audioSource;
- }
m_audioSource = nullptr;
close();
@@ -241,19 +217,24 @@ void QPulseAudioSink::start(QIODevice *device)
gettimeofday(&lastTimingInfo, nullptr);
lastProcessedUSecs = 0;
- connect(device, SIGNAL(readyRead()), m_tickTimer, SLOT(start()));
+ connect(m_audioSource, &QIODevice::readyRead, this, &QPulseAudioSink::startReading);
setState(QAudio::ActiveState);
}
+void QPulseAudioSink::startReading()
+{
+ if (!m_tickTimer.isActive())
+ m_tickTimer.start(m_periodTime, this);
+}
+
QIODevice *QPulseAudioSink::start()
{
setState(QAudio::StoppedState);
setError(QAudio::NoError);
// Handle change of mode
- if (m_audioSource && !m_pullMode) {
+ if (m_audioSource && !m_pullMode)
delete m_audioSource;
- }
m_audioSource = nullptr;
close();
@@ -306,12 +287,13 @@ bool QPulseAudioSink::open()
if (m_streamName.isNull())
m_streamName = QString(QLatin1String("QtmPulseStream-%1-%2")).arg(::getpid()).arg(quintptr(this)).toUtf8();
-#ifdef DEBUG_PULSE
- qDebug() << "Format: " << QPulseAudioInternal::sampleFormatToQString(spec.format);
- qDebug() << "Rate: " << spec.rate;
- qDebug() << "Channels: " << spec.channels;
- qDebug() << "Frame size: " << pa_frame_size(&spec);
-#endif
+ if (Q_UNLIKELY(qLcPulseAudioOut().isEnabled(QtDebugMsg))) {
+ qCDebug(qLcPulseAudioOut) << "Opening stream with.";
+ qCDebug(qLcPulseAudioOut) << "\tFormat: " << QPulseAudioInternal::sampleFormatToQString(spec.format);
+ qCDebug(qLcPulseAudioOut) << "\tRate: " << spec.rate;
+ qCDebug(qLcPulseAudioOut) << "\tChannels: " << spec.channels;
+ qCDebug(qLcPulseAudioOut) << "\tFrame size: " << pa_frame_size(&spec);
+ }
pulseEngine->lock();
@@ -339,7 +321,7 @@ bool QPulseAudioSink::open()
m_stream = pa_stream_new_with_proplist(pulseEngine->context(), m_streamName.constData(), &m_spec, &channel_map, propList);
if (!m_stream) {
- qWarning() << "QAudioSink: pa_stream_new_with_proplist() failed!";
+ qCWarning(qLcPulseAudioOut) << "QAudioSink: pa_stream_new_with_proplist() failed!";
pulseEngine->unlock();
setError(QAudio::OpenError);
setState(QAudio::StoppedState);
@@ -363,9 +345,9 @@ bool QPulseAudioSink::open()
requestedBuffer.prebuf = (uint32_t)-1;
requestedBuffer.tlength = m_bufferSize;
- pa_stream_flags flags = (pa_stream_flags)(PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_ADJUST_LATENCY);
+ pa_stream_flags flags = pa_stream_flags(PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_ADJUST_LATENCY);
if (pa_stream_connect_playback(m_stream, m_device.data(), (m_bufferSize > 0) ? &requestedBuffer : nullptr, flags, nullptr, nullptr) < 0) {
- qWarning() << "pa_stream_connect_playback() failed!";
+ qCWarning(qLcPulseAudioOut) << "pa_stream_connect_playback() failed!";
pa_stream_unref(m_stream);
m_stream = nullptr;
pulseEngine->unlock();
@@ -380,7 +362,7 @@ bool QPulseAudioSink::open()
const pa_buffer_attr *buffer = pa_stream_get_buffer_attr(m_stream);
m_periodTime = PeriodTimeMs;
- m_periodSize = pa_usec_to_bytes(m_periodTime*1000, &m_spec);
+ m_periodSize = pa_usec_to_bytes(m_periodTime * 1000, &m_spec);
m_bufferSize = buffer->tlength;
m_maxBufferSize = buffer->maxlength;
m_audioBuffer = new char[m_maxBufferSize];
@@ -395,14 +377,14 @@ bool QPulseAudioSink::open()
pa_operation_unref(o);
}
-#ifdef DEBUG_PULSE
- qDebug() << "Buffering info:";
- qDebug() << "\tMax length: " << buffer->maxlength;
- qDebug() << "\tTarget length: " << buffer->tlength;
- qDebug() << "\tPre-buffering: " << buffer->prebuf;
- qDebug() << "\tMinimum request: " << buffer->minreq;
- qDebug() << "\tFragment size: " << buffer->fragsize;
-#endif
+ if (Q_UNLIKELY(qLcPulseAudioOut().isEnabled(QtDebugMsg))) {
+ qCDebug(qLcPulseAudioOut) << "Buffering info:";
+ qCDebug(qLcPulseAudioOut) << "\tMax length: " << buffer->maxlength;
+ qCDebug(qLcPulseAudioOut) << "\tTarget length: " << buffer->tlength;
+ qCDebug(qLcPulseAudioOut) << "\tPre-buffering: " << buffer->prebuf;
+ qCDebug(qLcPulseAudioOut) << "\tMinimum request: " << buffer->minreq;
+ qCDebug(qLcPulseAudioOut) << "\tFragment size: " << buffer->fragsize;
+ }
pulseEngine->unlock();
@@ -410,7 +392,7 @@ bool QPulseAudioSink::open()
m_opened = true;
- m_tickTimer->start(m_periodTime);
+ startReading();
m_elapsedTimeOffset = 0;
@@ -422,7 +404,7 @@ void QPulseAudioSink::close()
if (!m_opened)
return;
- m_tickTimer->stop();
+ m_tickTimer.stop();
QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
@@ -450,7 +432,7 @@ void QPulseAudioSink::close()
if (m_audioSource) {
if (m_pullMode) {
- disconnect(m_audioSource, SIGNAL(readyRead()), m_tickTimer, SLOT(start()));
+ disconnect(m_audioSource, &QIODevice::readyRead, this, nullptr);
} else {
delete m_audioSource;
m_audioSource = nullptr;
@@ -463,6 +445,14 @@ void QPulseAudioSink::close()
}
}
+void QPulseAudioSink::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_tickTimer.timerId())
+ userFeed();
+
+ QPlatformAudioSink::timerEvent(event);
+}
+
void QPulseAudioSink::userFeed()
{
if (m_deviceState == QAudio::StoppedState || m_deviceState == QAudio::SuspendedState)
@@ -487,8 +477,8 @@ void QPulseAudioSink::userFeed()
Q_ASSERT(audioBytesPulled <= input);
if (audioBytesPulled > 0) {
if (audioBytesPulled > input) {
- qWarning() << "QPulseAudioSink::userFeed() - Invalid audio data size provided from user:"
- << audioBytesPulled << "should be less than" << input;
+ qCWarning(qLcPulseAudioOut) << "Invalid audio data size provided by pull source:"
+ << audioBytesPulled << "should be less than" << input;
audioBytesPulled = input;
}
qint64 bytesWritten = write(m_audioBuffer, audioBytesPulled);
@@ -500,7 +490,8 @@ void QPulseAudioSink::userFeed()
QMetaObject::invokeMethod(this, "userFeed", Qt::QueuedConnection);
}
} else if (audioBytesPulled == 0) {
- m_tickTimer->stop();
+ m_tickTimer.stop();
+ qCDebug(qLcPulseAudioOut) << "No more data available, source is done:" << m_audioSource->atEnd();
setError(m_audioSource->atEnd() ? QAudio::NoError : QAudio::UnderrunError);
setState(QAudio::IdleState);
}
@@ -520,8 +511,8 @@ qint64 QPulseAudioSink::write(const char *data, qint64 len)
void *dest = nullptr;
if (pa_stream_begin_write(m_stream, &dest, &nbytes) < 0) {
- qWarning("QAudioSink(pulseaudio): pa_stream_begin_write, error = %s",
- pa_strerror(pa_context_errno(pulseEngine->context())));
+ qCWarning(qLcPulseAudioOut) << "pa_stream_begin_write error:"
+ << pa_strerror(pa_context_errno(pulseEngine->context()));
setError(QAudio::IOError);
return 0;
}
@@ -539,8 +530,8 @@ qint64 QPulseAudioSink::write(const char *data, qint64 len)
data = reinterpret_cast<char *>(dest);
if ((pa_stream_write(m_stream, data, len, nullptr, 0, PA_SEEK_RELATIVE)) < 0) {
- qWarning("QAudioSink(pulseaudio): pa_stream_write, error = %s",
- pa_strerror(pa_context_errno(pulseEngine->context())));
+ qCWarning(qLcPulseAudioOut) << "pa_stream_write error:"
+ << pa_strerror(pa_context_errno(pulseEngine->context()));
setError(QAudio::IOError);
return 0;
}
@@ -672,7 +663,7 @@ void QPulseAudioSink::resume()
pulseEngine->unlock();
- m_tickTimer->start(m_periodTime);
+ m_tickTimer.start(m_periodTime, this);
setState(m_pullMode ? QAudio::ActiveState : QAudio::IdleState);
setError(QAudio::NoError);
@@ -695,7 +686,7 @@ void QPulseAudioSink::suspend()
setError(QAudio::NoError);
setState(QAudio::SuspendedState);
- m_tickTimer->stop();
+ m_tickTimer.stop();
QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
pa_operation *operation;
diff --git a/src/multimedia/pulseaudio/qpulseaudiosink_p.h b/src/multimedia/pulseaudio/qpulseaudiosink_p.h
index 2f206aadb..6e5780965 100644
--- a/src/multimedia/pulseaudio/qpulseaudiosink_p.h
+++ b/src/multimedia/pulseaudio/qpulseaudiosink_p.h
@@ -93,12 +93,15 @@ public:
void setVolume(qreal volume) override;
qreal volume() const override;
-public:
void streamUnderflowCallback();
+protected:
+ void timerEvent(QTimerEvent *event) override;
+
private:
void setState(QAudio::State state);
void setError(QAudio::Error error);
+ void startReading();
bool open();
void close();
@@ -109,34 +112,36 @@ private Q_SLOTS:
void onPulseContextFailed();
private:
+ pa_sample_spec m_spec = {};
+ // calculate timing manually, as pulseaudio doesn't give us good enough data
+ mutable timeval lastTimingInfo = {};
+
+ mutable QList<qint64> latencyList; // last latency values
+
QByteArray m_device;
QByteArray m_streamName;
QAudioFormat m_format;
- QAudio::Error m_errorState;
- QAudio::State m_deviceState;
- bool m_pullMode;
- bool m_opened;
- QIODevice *m_audioSource;
- QTimer m_periodTimer;
- int m_periodTime;
- pa_stream *m_stream;
- int m_periodSize;
- int m_bufferSize;
- int m_maxBufferSize;
- qint64 m_totalTimeValue;
- QTimer *m_tickTimer;
- char *m_audioBuffer;
- qint64 m_elapsedTimeOffset;
- bool m_resuming;
+ QBasicTimer m_tickTimer;
- // calculate timing manually, as pulseaudio doesn't give us good enough data
- mutable timeval lastTimingInfo = {};
- mutable QList<qint64> latencyList; // last latency values
+ QIODevice *m_audioSource = nullptr;
+ pa_stream *m_stream = nullptr;
+ char *m_audioBuffer = nullptr;
+
+ qint64 m_totalTimeValue = 0;
+ qint64 m_elapsedTimeOffset = 0;
mutable qint64 averageLatency = 0; // average latency
mutable qint64 lastProcessedUSecs = 0;
-
- qreal m_volume;
- pa_sample_spec m_spec;
+ qreal m_volume = 1.0;
+
+ QAudio::Error m_errorState = QAudio::NoError;
+ QAudio::State m_deviceState = QAudio::StoppedState;
+ int m_periodSize = 0;
+ int m_bufferSize = 0;
+ int m_maxBufferSize = 0;
+ int m_periodTime = 0;
+ bool m_pullMode = true;
+ bool m_opened = false;
+ bool m_resuming = false;
};
class PulseOutputPrivate : public QIODevice
diff --git a/src/multimedia/pulseaudio/qpulsehelpers.cpp b/src/multimedia/pulseaudio/qpulsehelpers.cpp
index e92081743..0136fd125 100644
--- a/src/multimedia/pulseaudio/qpulsehelpers.cpp
+++ b/src/multimedia/pulseaudio/qpulsehelpers.cpp
@@ -41,6 +41,8 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(qLcPulseAudioOut, "qt.multimedia.pulseaudio.output")
+
namespace QPulseAudioInternal
{
pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format)
@@ -231,62 +233,6 @@ QAudioFormat sampleSpecToAudioFormat(const pa_sample_spec &spec)
return format;
}
-#ifdef DEBUG_PULSE
-QString stateToQString(pa_stream_state_t state)
-{
- switch (state)
- {
- case PA_STREAM_UNCONNECTED: return "Unconnected";
- case PA_STREAM_CREATING: return "Creating";
- case PA_STREAM_READY: return "Ready";
- case PA_STREAM_FAILED: return "Failed";
- case PA_STREAM_TERMINATED: return "Terminated";
- }
-
- return QString("Unknown state: %0").arg(state);
-}
-
-QString sampleFormatToQString(pa_sample_format format)
-{
- switch (format)
- {
- case PA_SAMPLE_U8: return "Unsigned 8 Bit PCM.";
- case PA_SAMPLE_ALAW: return "8 Bit a-Law ";
- case PA_SAMPLE_ULAW: return "8 Bit mu-Law";
- case PA_SAMPLE_S16LE: return "Signed 16 Bit PCM, little endian (PC).";
- case PA_SAMPLE_S16BE: return "Signed 16 Bit PCM, big endian.";
- case PA_SAMPLE_FLOAT32LE: return "32 Bit IEEE floating point, little endian (PC), range -1.0 to 1.0";
- case PA_SAMPLE_FLOAT32BE: return "32 Bit IEEE floating point, big endian, range -1.0 to 1.0";
- case PA_SAMPLE_S32LE: return "Signed 32 Bit PCM, little endian (PC).";
- case PA_SAMPLE_S32BE: return "Signed 32 Bit PCM, big endian.";
- case PA_SAMPLE_S24LE: return "Signed 24 Bit PCM packed, little endian (PC).";
- case PA_SAMPLE_S24BE: return "Signed 24 Bit PCM packed, big endian.";
- case PA_SAMPLE_S24_32LE: return "Signed 24 Bit PCM in LSB of 32 Bit words, little endian (PC).";
- case PA_SAMPLE_S24_32BE: return "Signed 24 Bit PCM in LSB of 32 Bit words, big endian.";
- case PA_SAMPLE_MAX: return "Upper limit of valid sample types.";
- case PA_SAMPLE_INVALID: return "Invalid sample format";
- }
-
- return QString("Invalid value: %0").arg(format);
-}
-
-QString stateToQString(pa_context_state_t state)
-{
- switch (state)
- {
- case PA_CONTEXT_UNCONNECTED: return "Unconnected";
- case PA_CONTEXT_CONNECTING: return "Connecting";
- case PA_CONTEXT_AUTHORIZING: return "Authorizing";
- case PA_CONTEXT_SETTING_NAME: return "Setting Name";
- case PA_CONTEXT_READY: return "Ready";
- case PA_CONTEXT_FAILED: return "Failed";
- case PA_CONTEXT_TERMINATED: return "Terminated";
- }
-
- return QString("Unknown state: %0").arg(state);
-}
-#endif
-
}
QT_END_NAMESPACE
diff --git a/src/multimedia/pulseaudio/qpulsehelpers_p.h b/src/multimedia/pulseaudio/qpulsehelpers_p.h
index 3a8d04d87..00f26757e 100644
--- a/src/multimedia/pulseaudio/qpulsehelpers_p.h
+++ b/src/multimedia/pulseaudio/qpulsehelpers_p.h
@@ -54,18 +54,75 @@
#include "qaudiodevice.h"
#include <qaudioformat.h>
#include <pulse/pulseaudio.h>
+#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(qLcPulseAudioOut)
+
namespace QPulseAudioInternal
{
pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format);
QAudioFormat sampleSpecToAudioFormat(const pa_sample_spec &spec);
pa_channel_map channelMapForAudioFormat(const QAudioFormat &format);
QAudioFormat::ChannelConfig channelConfigFromMap(const pa_channel_map &map);
-QString stateToQString(pa_stream_state_t state);
-QString stateToQString(pa_context_state_t state);
-QString sampleFormatToQString(pa_sample_format format);
+
+static inline QString stateToQString(pa_stream_state_t state)
+{
+ using namespace Qt::StringLiterals;
+ switch (state)
+ {
+ case PA_STREAM_UNCONNECTED: return "Unconnected"_L1;
+ case PA_STREAM_CREATING: return "Creating"_L1;
+ case PA_STREAM_READY: return "Ready"_L1;
+ case PA_STREAM_FAILED: return "Failed"_L1;
+ case PA_STREAM_TERMINATED: return "Terminated"_L1;
+ }
+
+ return u"Unknown state: %0"_s.arg(int(state));
+}
+
+static inline QString sampleFormatToQString(pa_sample_format format)
+{
+ using namespace Qt::StringLiterals;
+ switch (format)
+ {
+ case PA_SAMPLE_U8: return "Unsigned 8 Bit PCM."_L1;
+ case PA_SAMPLE_ALAW: return "8 Bit a-Law "_L1;
+ case PA_SAMPLE_ULAW: return "8 Bit mu-Law"_L1;
+ case PA_SAMPLE_S16LE: return "Signed 16 Bit PCM, little endian (PC)."_L1;
+ case PA_SAMPLE_S16BE: return "Signed 16 Bit PCM, big endian."_L1;
+ case PA_SAMPLE_FLOAT32LE: return "32 Bit IEEE floating point, little endian (PC), range -1.0 to 1.0"_L1;
+ case PA_SAMPLE_FLOAT32BE: return "32 Bit IEEE floating point, big endian, range -1.0 to 1.0"_L1;
+ case PA_SAMPLE_S32LE: return "Signed 32 Bit PCM, little endian (PC)."_L1;
+ case PA_SAMPLE_S32BE: return "Signed 32 Bit PCM, big endian."_L1;
+ case PA_SAMPLE_S24LE: return "Signed 24 Bit PCM packed, little endian (PC)."_L1;
+ case PA_SAMPLE_S24BE: return "Signed 24 Bit PCM packed, big endian."_L1;
+ case PA_SAMPLE_S24_32LE: return "Signed 24 Bit PCM in LSB of 32 Bit words, little endian (PC)."_L1;
+ case PA_SAMPLE_S24_32BE: return "Signed 24 Bit PCM in LSB of 32 Bit words, big endian."_L1;
+ case PA_SAMPLE_MAX: return "Upper limit of valid sample types."_L1;
+ case PA_SAMPLE_INVALID: return "Invalid sample format"_L1;
+ }
+
+ return u"Invalid value: %0"_s.arg(int(format));
+}
+
+static inline QString stateToQString(pa_context_state_t state)
+{
+ using namespace Qt::StringLiterals;
+ switch (state)
+ {
+ case PA_CONTEXT_UNCONNECTED: return "Unconnected"_L1;
+ case PA_CONTEXT_CONNECTING: return "Connecting"_L1;
+ case PA_CONTEXT_AUTHORIZING: return "Authorizing"_L1;
+ case PA_CONTEXT_SETTING_NAME: return "Setting Name"_L1;
+ case PA_CONTEXT_READY: return "Ready"_L1;
+ case PA_CONTEXT_FAILED: return "Failed"_L1;
+ case PA_CONTEXT_TERMINATED: return "Terminated"_L1;
+ }
+
+ return u"Unknown state: %0"_s.arg(int(state));
+}
}
QT_END_NAMESPACE