6#include <QtMultimedia/private/qpipewire_audiocontextmanager_p.h>
7#include <QtMultimedia/private/qpipewire_audiodevice_p.h>
8#include <QtMultimedia/private/qpipewire_support_p.h>
9#include <QtCore/qcoreapplication.h>
10#include <QtCore/qdebug.h>
11#include <QtCore/qloggingcategory.h>
22 std::optional<qsizetype> ringbufferSize,
23 QPipewireAudioSource *parent,
25 std::optional<int32_t> hardwareBufferFrames
41 m_xrunNotification = m_xrunOccurred.callOnActivated([
this] {
42 if (isStopRequested())
44 m_parent->reportXRuns(m_xrunCount.exchange(0));
55 createStream(StreamType::Ringbuffer);
57 Q_ASSERT(hasStream());
58 auto sourceNodeSerial = findSourceNodeSerial();
59 if (!sourceNodeSerial) {
66 bool connected = connectStream(*sourceNodeSerial, SPA_DIRECTION_INPUT);
72 createQIODeviceConnections(device);
75 m_self = shared_from_this();
76 QAudioContextManager::instance()->registerStreamReference(m_self);
83 QIODevice *device = createRingbufferReaderDevice();
85 bool started = start(device);
94 createStream(StreamType::Callback);
96 Q_ASSERT(hasStream());
97 auto sourceNodeSerial = findSourceNodeSerial();
98 if (!sourceNodeSerial) {
103 m_audioCallback = std::move(audioCallback);
105 bool connected = connectStream(*sourceNodeSerial, SPA_DIRECTION_INPUT);
112 m_self = shared_from_this();
122 unregisterDeviceObserver();
123 disconnectQIODeviceConnections();
125 finalizeQIODevice(shutdownPolicy);
126 if (shutdownPolicy == ShutdownPolicy::DiscardRingbuffer) {
129 bool streamDisconnected = m_streamDisconnected.try_acquire_for(5s);
130 if (!streamDisconnected)
131 qWarning() <<
"QPipewireAudioSourceStream::stop: m_streamDisconnected semaphore "
132 "timeout. This should not happen";
140 m_parent->updateStreamIdle(idle);
145 auto extraProperties = std::array{
146 spa_dict_item{ PW_KEY_MEDIA_CATEGORY,
"Capture" },
147 spa_dict_item{ PW_KEY_MEDIA_ROLE,
"Music" },
150 QString applicationName = qApp->applicationName();
151 if (applicationName.isNull())
152 applicationName = u"QPipewireAudioSource"_s;
154 QPipewireAudioStream::createStream(extraProperties, m_hardwareBufferFrames,
155 applicationName.toUtf8().constData(), streamType);
160 const QPipewireAudioDevicePrivate *device =
161 QAudioDevicePrivate::handle<QPipewireAudioDevicePrivate>(m_audioDevice);
163 QByteArray nodeName = device->nodeName();
164 auto ret = QAudioContextManager::deviceMonitor().findSourceNodeSerial(std::string_view{
166 size_t(nodeName.size()),
170 qWarning() <<
"Cannot find device: " << nodeName;
176 auto self = shared_from_this();
178 QPipewireAudioStream::disconnectStream();
180 QObject::disconnect(m_xrunNotification);
192 qCritical() <<
"pw_stream_dequeue_buffer failed";
198 qWarning() <<
"pw_stream_dequeue_buffer received null buffer";
221 qCritical() <<
"pw_stream_dequeue_buffer failed";
227 qWarning() <<
"pw_stream_dequeue_buffer received null buffer";
278 qDebug() <<
"XRuns occurred:" << numberOfXruns;
Combined button and popup list for selecting options.
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