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;
128 std::optional<int32_t> hardwareBufferFrames,
float volume);
156 return m_streamIsIdle.load(order);
160 template <
typename Functor>
163 return m_streamIdleDetectionNotifier.callOnActivated(std::forward<Functor>(f));
166 template <
typename ParentType>
170 Q_ASSERT(thread()->isCurrentThread());
171 parent->setError(QAudio::IOError);
172 parent->updateStreamState(QtAudio::State::StoppedState);
174 parent->m_stream = {};
180 template <
typename Functor>
184 QMetaObject::invokeMethod(&m_streamIdleDetectionNotifier, std::forward<Functor>(f));
189 QIODevice *m_device =
nullptr;
192 std::atomic<
bool> m_streamIsIdle =
false;
193 QAutoResetEvent m_streamIdleDetectionNotifier;
194 QMetaObject::Connection m_streamIdleDetectionConnection;
197 QAutoResetEvent m_ringbufferHasSpace;
198 QMetaObject::Connection m_ringbufferHasSpaceConnection;
199 QMetaObject::Connection m_iodeviceHasNewDataConnection;
201 std::unique_ptr<QtPrivate::QIODeviceRingBufferWriterBase> m_ringbufferWriterDevice;
204 std::atomic_int64_t m_totalFrameCount{};
205 std::atomic_int64_t m_processedFrameCount{};
207 void convertToNative(QSpan<
const std::byte> internal, QSpan<std::byte> native,
float volume,
213 template <
typename Functor>
214 void withPullIODeviceReentrancyGuard(Functor f)
216 if (!m_pullIODeviceReentrancyGuard) {
217 QScopedValueRollback<
bool> guard{
218 m_pullIODeviceReentrancyGuard,
223 QMetaObject::invokeMethod(&m_streamIdleDetectionNotifier,
224 [
this, f = std::move(f)]()
mutable {
225 withPullIODeviceReentrancyGuard(std::move(f));
226 }, Qt::QueuedConnection);
229 bool m_pullIODeviceReentrancyGuard =
false;
231 void pullFromQIODeviceImpl();
244 std::optional<
int> ringbufferSize,
245 std::optional<int32_t> hardwareBufferFrames,
float volume);
270 template <
typename ParentType>
274 Q_ASSERT(thread()->isCurrentThread());
275 parent->setError(QAudio::IOError);
276 parent->updateStreamState(QtAudio::State::StoppedState);
281 parent->m_retiredStream =
std::move(parent->m_stream);
283 parent->m_stream = {};
289 template <
typename Functor>
293 QMetaObject::invokeMethod(&m_ringbufferHasData, std::forward<Functor>(f));
298 QIODevice *m_device =
nullptr;
299 std::unique_ptr<QIODevice> m_ringbufferReaderDevice;
302 QAutoResetEvent m_ringbufferHasData;
303 QAutoResetEvent m_ringbufferIsFull;
305 QMetaObject::Connection m_ringbufferHasDataConnection;
306 QMetaObject::Connection m_ringbufferIsFullConnection;
309 std::atomic_uint64_t m_totalNumberOfFramesPushedToRingbuffer{};
311 void convertFromNative(QSpan<
const std::byte> native, QSpan<std::byte> internal,
float volume,