20#include <QtCore/QDataStream>
21#include <QtCore/qtimer.h>
22#include <QtCore/qloggingcategory.h>
23#include <QtCore/qpointer.h>
25#include <private/qaudiohelpers_p.h>
27#include <audioclient.h>
28#include <mmdeviceapi.h>
55 if (framesAllocated && framesInUse)
56 return *framesAllocated - *framesInUse;
76qint64 QWindowsAudioSink::remainingPlayTimeUs()
84 if (
state != deviceState) {
86 m_audioClient->Start();
87 qCDebug(qLcAudioOutput) <<
"Audio client started";
91 m_audioClient->Stop();
92 qCDebug(qLcAudioOutput) <<
"Audio client stopped";
102 if (
error != errorState) {
119void QWindowsAudioSink::pullSource()
121 qCDebug(qLcAudioOutput) <<
"Pull source";
137 auto playTimeUs = remainingPlayTimeUs();
138 if (playTimeUs == 0) {
142 m_timer->
start(playTimeUs / 2000);
148 qCDebug(qLcAudioOutput) <<
"start(ioDevice)" << deviceState;
165 m_timer->
callOnTimeout(
this, &QWindowsAudioSink::pullSource);
177 m_timer->
start(remainingPlayTimeUs() /1000);
185 qCDebug(qLcAudioOutput) <<
"start()";
202 return m_pushSource.
get();
205bool QWindowsAudioSink::open()
210 HRESULT hr = m_device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,
211 nullptr, (
void**)m_audioClient.GetAddressOf());
213 qCWarning(qLcAudioOutput) <<
"Failed to activate audio device" << errorString(hr);
217 auto resetClient =
qScopeGuard([
this](){ m_audioClient.Reset(); });
220 hr = m_audioClient->GetMixFormat(pwfx.address());
227 qCWarning(qLcAudioOutput) <<
"Failed to set up resampler";
231 if (m_bufferSize == 0)
234 REFERENCE_TIME requestedDuration = m_format.
durationForBytes(m_bufferSize) * 10;
236 hr = m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, requestedDuration, 0, pwfx.get(),
245 if (!framesAllocated) {
246 qCWarning(qLcAudioOutput) <<
"Failed to get audio client buffer size";
253 hr = m_audioClient->GetService(__uuidof(IAudioRenderClient), (
void**)m_renderClient.GetAddressOf());
255 qCWarning(qLcAudioOutput) <<
"Failed to obtain audio client rendering service"
260 resetClient.dismiss();
265void QWindowsAudioSink::close()
267 qCDebug(qLcAudioOutput) <<
"close()";
275 m_audioClient.Reset();
276 m_renderClient.Reset();
277 m_pullSource =
nullptr;
294 m_bufferSize =
value;
313 if (!framesAvailable)
324 HRESULT hr = m_renderClient->GetBuffer(writeFramesNum, &
buffer);
330 if (m_volume <
qreal(1.0))
335 DWORD
flags = writeBytes.
isEmpty() ? AUDCLNT_BUFFERFLAGS_SILENT : 0;
336 hr = m_renderClient->ReleaseBuffer(writeFramesNum,
flags);
347 qCDebug(qLcAudioOutput) <<
"resume()";
353 if (remainingPlayTimeUs() > 0)
354 m_audioClient->Start();
361 qCDebug(qLcAudioOutput) <<
"suspend()";
363 suspendedInState = deviceState;
388#include "qwindowsaudiosink.moc"
IOBluetoothDevice * device
qint64 writeData(const char *data, qint64 len) override
Writes up to maxSize bytes from data to the device.
qint64 readData(char *, qint64) override
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
~OutputPrivate() override=default
OutputPrivate(QWindowsAudioSink &audio)
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
\inmodule QtCore \reentrant
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
void readyRead()
This signal is emitted once every time new data is available for reading from the device's current re...
bool isOpen() const
Returns true if the device is open; otherwise returns false.
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i....
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
void setSingleShot(bool singleShot)
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
void stop()
Stops the timer.
QMetaObject::Connection callOnTimeout(Args &&...args)
void setTimerType(Qt::TimerType atype)
qint64 processedUSecs() const override
void setFormat(const QAudioFormat &fmt) override
QAudioFormat format() const override
QAudio::State state() const override
void setVolume(qreal) override
qsizetype bytesFree() const override
void setBufferSize(qsizetype value) override
QAudio::Error error() const override
QWindowsAudioSink(ComPtr< IMMDevice > device, QObject *parent)
QIODevice * start() override
quint64 totalInputBytes() const
bool setup(const QAudioFormat &in, const QAudioFormat &out)
QByteArray resample(const QByteArrayView &in)
quint64 inputBufferSize(quint64 outputBufferSize) const
QAudioFormat outputFormat() const
void qMultiplySamples(qreal factor, const QAudioFormat &format, const void *src, void *dest, int len)
The QAudio namespace contains enums used by the audio classes.
State
\value ActiveState Audio data is being processed, this state is set after start() is called and while...
Error
\value NoError No errors have occurred \value OpenError An error occurred opening the audio device \v...
Combined button and popup list for selecting options.
std::optional< quint32 > audioClientFramesInUse(IAudioClient *client)
std::optional< quint32 > audioClientFramesAllocated(IAudioClient *client)
QAudioFormat waveFormatExToFormat(const WAVEFORMATEX &in)
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
GLsizei const GLfloat * v
[13]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
QVideoFrameFormat::PixelFormat fmt
std::optional< quint32 > audioClientFramesAvailable(IAudioClient *client)
myObject disconnect()
[26]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent