Revision control

Copy as Markdown

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOREAAUDIOSINK_P_H
#define QCOREAAUDIOSINK_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtMultimedia/private/qaudio_platform_implementation_support_p.h>
#include <AudioUnit/AudioUnit.h>
#include <QtMultimedia/private/qcoreaudioutils_p.h>
#include <QtMultimedia/private/qcoreaudiodevices_p.h>
#ifdef Q_OS_MACOS
# include <QtMultimedia/private/qmacosaudiodatautils_p.h>
#else
# include <QtMultimedia/private/qavaudiosessionrecovery_p.h>
#endif
QT_BEGIN_NAMESPACE
class QCoreAudioSink;
class QCoreAudioSinkStream final : public std::enable_shared_from_this<QCoreAudioSinkStream>,
public QtMultimediaPrivate::QPlatformAudioSinkStream
{
using QPlatformAudioSinkStream = QtMultimediaPrivate::QPlatformAudioSinkStream;
using AudioEndpointRole = QtMultimediaPrivate::AudioEndpointRole;
public:
using SinkType = QCoreAudioSink;
explicit QCoreAudioSinkStream(QAudioDevice, const QAudioFormat &,
std::optional<qsizetype> ringbufferSize, QCoreAudioSink *parent,
float volume, std::optional<QtMultimediaPrivate::NativePeriodFrames> nativePeriodFrames,
AudioEndpointRole);
Q_DISABLE_COPY_MOVE(QCoreAudioSinkStream)
~QCoreAudioSinkStream();
bool open();
bool start(QIODevice *device);
QIODevice *start();
bool start(AudioCallback cb);
void stop(ShutdownPolicy policy);
void stopStreamWhenBufferDrained();
void stopStream();
void suspend();
bool resume();
using QPlatformAudioSinkStream::bytesFree;
using QPlatformAudioSinkStream::processedDuration;
using QPlatformAudioSinkStream::ringbufferSizeInBytes;
using QPlatformAudioSinkStream::setVolume;
bool resumeIfNecessary();
void reportIOError();
void invalidateAudioUnit();
private:
OSStatus processRingbuffer(uint32_t numberOfFrames,
AudioBufferList *ioData) noexcept Q_DECL_NONBLOCKING_FUNCTION;
OSStatus processAudioCallback(uint32_t numberOfFrames,
AudioBufferList *ioData) noexcept Q_DECL_NONBLOCKING_FUNCTION;
void updateStreamIdle(bool arg) override;
bool startAudioUnit();
void stopAudioUnit();
#ifdef Q_OS_MACOS
bool setDisconnectListener(AudioObjectID id);
void cancelDisconnectFutures();
QCoreAudioUtils::DeviceDisconnectMonitor m_disconnectMonitor;
QFuture<void> m_disconnectFuture;
QFuture<void> m_stopOnDisconnected;
#endif
std::unique_ptr<QIODevice> m_reader;
QCoreAudioUtils::AudioUnitHandle m_audioUnit;
QCoreAudioSink *m_parent;
std::optional<AudioCallback> m_audioCallback;
#ifndef Q_OS_MACOS
// Held for as long as this stream wants the shared AVAudioSession active; acquired in
// start(), released in stopStream(). suspend()/resume() (interruption handling) must not
// touch it: the stream still wants the session active across a suspend/resume cycle, only
// the OS-level session state changed.
std::optional<QtMultimediaPrivate::QAVAudioSessionManager::ActivationToken> m_sessionActivation;
#endif
};
class QCoreAudioSink final
: public QtMultimediaPrivate::QPlatformAudioSinkImplementation<QCoreAudioSinkStream,
QCoreAudioSink>
{
using BaseClass = QtMultimediaPrivate::QPlatformAudioSinkImplementation<QCoreAudioSinkStream,
QCoreAudioSink>;
public:
QCoreAudioSink(QAudioDevice device, const QAudioFormat &format, QObject *parent);
~QCoreAudioSink() override;
void resumeStreamIfNecessary();
#ifndef Q_OS_MACOS
void resume() override;
// Interface required by QAVAudioSessionRecovery.
QCoreAudioSinkStream *currentStream() const { return m_stream.get(); }
using BaseClass::updateStreamState;
void notifyStreamStopped() { m_recovery.streamStopped(); }
private:
QtMultimediaPrivate::QAVAudioSessionRecovery<QCoreAudioSink> m_recovery{ *this };
#endif
};
QT_END_NAMESPACE
#endif // QCOREAAUDIOSINK_P_H