10#include <QtCore/qcoreapplication.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qloggingcategory.h>
23 std::optional<qsizetype> ringbufferSize,
24 QPipewireAudioSource *parent,
26 std::optional<int32_t> hardwareBufferFrames
42 m_xrunNotification = m_xrunOccurred.callOnActivated([
this] {
43 if (isStopRequested())
45 m_parent->reportXRuns(m_xrunCount.exchange(0));
56 createStream(StreamType::Ringbuffer);
58 Q_ASSERT(hasStream());
59 auto sourceNodeSerial = findSourceNodeSerial();
60 if (!sourceNodeSerial) {
67 bool connected = connectStream(*sourceNodeSerial, SPA_DIRECTION_INPUT);
73 createQIODeviceConnections(device);
76 m_self = shared_from_this();
84 QIODevice *device = createRingbufferReaderDevice();
86 bool started = start(device);
95 createStream(StreamType::Callback);
97 Q_ASSERT(hasStream());
98 auto sourceNodeSerial = findSourceNodeSerial();
99 if (!sourceNodeSerial) {
104 m_audioCallback = std::move(audioCallback);
106 bool connected = connectStream(*sourceNodeSerial, SPA_DIRECTION_INPUT);
113 m_self = shared_from_this();
123 unregisterDeviceObserver();
124 disconnectQIODeviceConnections();
126 finalizeQIODevice(shutdownPolicy);
127 if (shutdownPolicy == ShutdownPolicy::DiscardRingbuffer) {
130 bool streamDisconnected = m_streamDisconnected.try_acquire_for(5s);
131 if (!streamDisconnected)
132 qWarning() <<
"QPipewireAudioSourceStream::stop: m_streamDisconnected semaphore "
133 "timeout. This should not happen";
141 m_parent->updateStreamIdle(idle);
146 auto extraProperties = std::array{
147 spa_dict_item{ PW_KEY_MEDIA_CATEGORY,
"Capture" },
148 spa_dict_item{ PW_KEY_MEDIA_ROLE,
"Music" },
151 QString applicationName = qApp->applicationName();
152 if (applicationName.isNull())
153 applicationName = u"QPipewireAudioSource"_s;
155 QPipewireAudioStream::createStream(extraProperties, m_hardwareBufferFrames,
156 applicationName.toUtf8().constData(), streamType);
161 const QPipewireAudioDevicePrivate *device =
162 QAudioDevicePrivate::handle<QPipewireAudioDevicePrivate>(m_audioDevice);
164 QByteArray nodeName = device->nodeName();
167 size_t(nodeName.size()),
171 qWarning() <<
"Cannot find device: " << nodeName;
177 auto self = shared_from_this();
179 QPipewireAudioStream::disconnectStream();
181 QObject::disconnect(m_xrunNotification);
193 qCritical() <<
"pw_stream_dequeue_buffer failed";
199 qWarning() <<
"pw_stream_dequeue_buffer received null buffer";
222 qCritical() <<
"pw_stream_dequeue_buffer failed";
228 qWarning() <<
"pw_stream_dequeue_buffer received null buffer";
279 qDebug() <<
"XRuns occurred:" << numberOfXruns;
static QAudioDeviceMonitor & deviceMonitor()
static QAudioContextManager * instance()
void registerStreamReference(std::shared_ptr< QPipewireAudioStream >)
Combined button and popup list for selecting options.
StrongIdType< uint64_t, ObjectSerialTag > ObjectSerial
bool start(QIODevice *device)
void finalizeStream() override
void stop(ShutdownPolicy)
QPipewireAudioSourceStream(QAudioDevice, const QAudioFormat &, std::optional< qsizetype > ringbufferSize, QPipewireAudioSource *parent, float volume, std::optional< int32_t > hardwareBufferFrames)
bool start(AudioCallback &&)
void updateStreamIdle(bool idle) override
QAudioFormat::SampleFormat SampleFormat