4#ifndef QAUDIOSYSTEM_PLATFORM_STREAM_SUPPORT_P_H
5#define QAUDIOSYSTEM_PLATFORM_STREAM_SUPPORT_P_H
18#include <QtMultimedia/qtmultimediaglobal.h>
19#include <QtMultimedia/qaudioformat.h>
20#include <QtMultimedia/qaudiodevice.h>
21#include <QtMultimedia/private/qautoresetevent_p.h>
22#include <QtMultimedia/private/qaudio_qiodevice_support_p.h>
23#include <QtMultimedia/private/qaudio_rtsan_support_p.h>
24#include <QtMultimedia/private/qaudiosystem_p.h>
25#include <QtMultimedia/private/qaudiohelpers_p.h>
26#include <QtMultimedia/private/qaudioringbuffer_p.h>
27#include <QtCore/qscopedvaluerollback.h>
28#include <QtCore/qthread.h>
51 const std::optional<int32_t> &hardwareBufferFrames,
52 const QAudioFormat &);
54 const std::optional<int32_t> &hardwareBufferFrames,
55 const QAudioFormat &);
62 std::optional<
int> ringbufferSize,
63 std::optional<int32_t> hardwareBufferFrames,
float volume);
68 float volume()
const {
return m_volume.load(std::memory_order_relaxed); }
70 template <
typename Functor>
73 return std::visit(f, m_ringbuffer);
76 template <
typename Functor>
79 return std::visit(f, m_ringbuffer);
89 return m_stopRequested.load(memory_order);
98 std::atomic<
float> m_volume{
102 Ringbuffer m_ringbuffer{
108 std::atomic<
bool> m_stopRequested =
false;
130 std::optional<int32_t> hardwareBufferFrames,
float volume);
158 return m_streamIsIdle.load(order);
162 template <
typename Functor>
165 return m_streamIdleDetectionNotifier.callOnActivated(std::forward<Functor>(f));
168 template <
typename ParentType>
172 Q_ASSERT(thread()->isCurrentThread());
173 parent->setError(QAudio::IOError);
174 parent->updateStreamState(QtAudio::State::StoppedState);
176 parent->m_stream = {};
182 template <
typename Functor>
186 QMetaObject::invokeMethod(&m_streamIdleDetectionNotifier, std::forward<Functor>(f));
191 QIODevice *m_device =
nullptr;
194 std::atomic<
bool> m_streamIsIdle =
false;
195 QAutoResetEvent m_streamIdleDetectionNotifier;
196 QMetaObject::Connection m_streamIdleDetectionConnection;
199 QAutoResetEvent m_ringbufferHasSpace;
200 QMetaObject::Connection m_ringbufferHasSpaceConnection;
201 QMetaObject::Connection m_iodeviceHasNewDataConnection;
203 std::unique_ptr<QtPrivate::QIODeviceRingBufferWriterBase> m_ringbufferWriterDevice;
206 std::atomic_int64_t m_totalFrameCount{};
207 std::atomic_int64_t m_processedFrameCount{};
209 void convertToNative(QSpan<
const std::byte> internal, QSpan<std::byte> native,
float volume,
215 template <
typename Functor>
216 void withPullIODeviceReentrancyGuard(Functor f)
218 if (!m_pullIODeviceReentrancyGuard) {
219 QScopedValueRollback<
bool> guard{
220 m_pullIODeviceReentrancyGuard,
225 QMetaObject::invokeMethod(&m_streamIdleDetectionNotifier,
226 [
this, f = std::move(f)]()
mutable {
227 withPullIODeviceReentrancyGuard(std::move(f));
228 }, Qt::QueuedConnection);
231 bool m_pullIODeviceReentrancyGuard =
false;
233 void pullFromQIODeviceImpl();
248 std::optional<
int> ringbufferSize,
249 std::optional<int32_t> hardwareBufferFrames,
float volume);
274 template <
typename ParentType>
278 Q_ASSERT(thread()->isCurrentThread());
279 parent->setError(QAudio::IOError);
280 parent->updateStreamState(QtAudio::State::StoppedState);
285 parent->m_retiredStream =
std::move(parent->m_stream);
287 parent->m_stream = {};
293 template <
typename Functor>
297 QMetaObject::invokeMethod(&m_ringbufferHasData, std::forward<Functor>(f));
302 QIODevice *m_device =
nullptr;
303 std::unique_ptr<QIODevice> m_ringbufferReaderDevice;
306 QAutoResetEvent m_ringbufferHasData;
307 QAutoResetEvent m_ringbufferIsFull;
309 QMetaObject::Connection m_ringbufferHasDataConnection;
310 QMetaObject::Connection m_ringbufferIsFullConnection;
313 std::atomic_uint64_t m_totalNumberOfFramesPushedToRingbuffer{};
315 void convertFromNative(QSpan<
const std::byte> native, QSpan<std::byte> internal,
float volume,