4#ifndef QAUDIOSYSTEM_PLATFORM_STREAM_SUPPORT_P_H
5#define QAUDIOSYSTEM_PLATFORM_STREAM_SUPPORT_P_H
18#include <QtMultimedia/private/qaudio_qiodevice_support_p.h>
19#include <QtMultimedia/private/qaudiohelpers_p.h>
20#include <QtMultimedia/private/qaudioringbuffer_p.h>
21#include <QtMultimedia/private/qaudiosystem_p.h>
22#include <QtMultimedia/private/qautoresetevent_p.h>
23#include <QtMultimedia/qaudiodevice.h>
24#include <QtMultimedia/qaudioformat.h>
25#include <QtMultimedia/qtmultimediaglobal.h>
26#include <QtCore/qscopedvaluerollback.h>
27#include <QtCore/qthread.h>
50 const std::optional<NativePeriodFrames> &nativePeriodFrames,
51 const QAudioFormat &);
53 const std::optional<NativePeriodFrames> &nativePeriodFrames,
54 const QAudioFormat &);
61 std::optional<
int> ringbufferSize,
62 std::optional<NativePeriodFrames> nativePeriodFrames,
float volume);
67 float volume()
const {
return m_volume.load(std::memory_order_relaxed); }
69 template <
typename Functor>
72 return std::visit(f, m_ringbuffer);
75 template <
typename Functor>
78 return std::visit(f, m_ringbuffer);
88 return m_stopRequested.load(memory_order);
97 std::atomic<
float> m_volume{
101 Ringbuffer m_ringbuffer{
107 std::atomic<
bool> m_stopRequested =
false;
129 std::optional<NativePeriodFrames> nativePeriodFrames,
float volume);
157 return m_streamIsIdle.load(order);
161 template <
typename Functor>
164 return m_streamIdleDetectionNotifier.callOnActivated(std::forward<Functor>(f));
167 template <
typename ParentType>
171 Q_ASSERT(thread()->isCurrentThread());
172 parent->m_stream = {};
173 parent->setError(QAudio::IOError);
174 parent->updateStreamState(QtAudio::State::StoppedState);
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();
246 std::optional<
int> ringbufferSize,
247 std::optional<NativePeriodFrames> nativePeriodFrames,
float volume);
272 template <
typename ParentType>
276 Q_ASSERT(thread()->isCurrentThread());
281 parent->m_retiredStream =
std::move(parent->m_stream);
283 parent->m_stream = {};
285 parent->setError(QAudio::IOError);
286 parent->updateStreamState(QtAudio::State::StoppedState);
292 template <
typename Functor>
296 QMetaObject::invokeMethod(&m_ringbufferHasData, std::forward<Functor>(f));
301 QIODevice *m_device =
nullptr;
302 std::unique_ptr<QIODevice> m_ringbufferReaderDevice;
305 QAutoResetEvent m_ringbufferHasData;
306 QAutoResetEvent m_ringbufferIsFull;
308 QMetaObject::Connection m_ringbufferHasDataConnection;
309 QMetaObject::Connection m_ringbufferIsFullConnection;
312 std::atomic_uint64_t m_totalNumberOfFramesPushedToRingbuffer{};
314 void convertFromNative(QSpan<
const std::byte> native, QSpan<std::byte> internal,
float volume,
Combined button and popup list for selecting options.