6#include <private/qaudiohelpers_p.h>
7#include <sys/asoundlib.h>
8#include <sys/asound_common.h>
13#pragma GCC diagnostic ignored "-Wvla"
23 , m_state(
QAudio::StoppedState)
24 , m_suspendedInState(
QAudio::SuspendedState)
28 , m_requestedBufferSize(0)
29 , m_deviceInfo(deviceInfo)
40 m_requestedBufferSize =
info->max_fragment_size;
95#if SND_PCM_VERSION < SND_PROTOCOL_VERSION('P',3,0,2)
96 snd_pcm_playback_drain(m_pcmHandle.get());
98 snd_pcm_channel_drain(m_pcmHandle.get(), SND_PCM_CHANNEL_PLAYBACK);
108 snd_pcm_playback_pause(m_pcmHandle.get());
117 snd_pcm_playback_resume(m_pcmHandle.get());
123 m_requestedBufferSize = std::clamp<qsizetype>(
bufferSize, 0, std::numeric_limits<int>::max());
128 const std::optional<snd_pcm_channel_setup_t> setup = m_pcmHandle
132 return setup ? setup->buf.block.frag_size : m_requestedBufferSize;
143 return status ? status->free : 0;
182void QQnxAudioSink::updateState()
196void QQnxAudioSink::pullData()
214 char buffer[bytesRequested];
215 const int bytesRead = m_source->
read(
buffer, bytesRequested);
239bool QQnxAudioSink::open()
243 qWarning(
"QQnxAudioSink: open error, invalid format.");
245 qWarning(
"QQnxAudioSink: open error, invalid sample rate (%d).", m_format.
sampleRate());
258 if ((errorCode = snd_pcm_nonblock_mode(m_pcmHandle.get(), 0)) < 0) {
259 qWarning(
"QQnxAudioSink: open error, couldn't set non block mode (0x%x)", -errorCode);
267 snd_pcm_plugin_set_disable(m_pcmHandle.get(), PLUGIN_MMAP);
277 const int fragmentSize = std::clamp(m_requestedBufferSize,
278 info->min_fragment_size,
info->max_fragment_size);
283 if ((errorCode = snd_pcm_plugin_params(m_pcmHandle.get(), &
params)) < 0) {
284 qWarning(
"QQnxAudioSink: open error, couldn't set channel params (0x%x)", -errorCode);
289 if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle.get(), SND_PCM_CHANNEL_PLAYBACK)) < 0) {
290 qWarning(
"QQnxAudioSink: open error, couldn't prepare channel (0x%x)", -errorCode);
303 m_periodSize =
qMin(2048, setup->buf.block.frag_size);
306 createPcmNotifiers();
311void QQnxAudioSink::close()
316 destroyPcmNotifiers();
319#if SND_PCM_VERSION < SND_PROTOCOL_VERSION('P',3,0,2)
320 snd_pcm_plugin_flush(m_pcmHandle.get(), SND_PCM_CHANNEL_PLAYBACK);
322 snd_pcm_plugin_drop(m_pcmHandle.get(), SND_PCM_CHANNEL_PLAYBACK);
324 m_pcmHandle =
nullptr;
335 if (m_state !=
state) {
340 if (m_error !=
error) {
360 constexpr int maxRetries = 10;
362 while (totalWritten <
len) {
368 if (retry >= maxRetries) {
399 if (m_volume < 1.0f) {
402 written = snd_pcm_plugin_write(m_pcmHandle.get(),
out,
size);
404 written = snd_pcm_plugin_write(m_pcmHandle.get(),
data,
size);
408 m_bytesWritten += written;
420 m_suspendedInState = m_state;
424void QQnxAudioSink::resumeInternal()
434 Q_ASSERT(
event.data.audiomgmt_status.new_status == SND_PCM_STATUS_SUSPENDED);
438void QQnxAudioSink::addPcmEventFilter()
443 filter.enable = (1<<SND_PCM_EVENT_AUDIOMGMT_STATUS) |
444 (1<<SND_PCM_EVENT_AUDIOMGMT_MUTE) |
445 (1<<SND_PCM_EVENT_OUTPUTCLASS) |
446 (1<<SND_PCM_EVENT_UNDERRUN);
447 snd_pcm_set_filter(m_pcmHandle.get(), SND_PCM_CHANNEL_PLAYBACK, &
filter);
450void QQnxAudioSink::createPcmNotifiers()
454 m_pcmNotifier =
new QSocketNotifier(snd_pcm_file_descriptor(m_pcmHandle.get(),
455 SND_PCM_CHANNEL_PLAYBACK),
458 this, &QQnxAudioSink::pcmNotifierActivated);
461void QQnxAudioSink::destroyPcmNotifiers()
464 delete m_pcmNotifier;
469void QQnxAudioSink::pcmNotifierActivated(
int socket)
473 snd_pcm_event_t pcm_event;
474 memset(&pcm_event, 0,
sizeof(pcm_event));
475 while (snd_pcm_channel_read_event(m_pcmHandle.get(), SND_PCM_CHANNEL_PLAYBACK, &pcm_event) == 0) {
476 if (pcm_event.type == SND_PCM_EVENT_AUDIOMGMT_STATUS) {
477 if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_SUSPENDED)
479 else if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_RUNNING)
481 else if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_PAUSED)
483 }
else if (pcm_event.type == SND_PCM_EVENT_UNDERRUN) {
The QAudioDevice class provides an information about audio devices and their functionality.
QByteArray id
\qmlproperty string QtMultimedia::audioDevice::id
\inmodule QtCore \reentrant
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success,...
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
QAudio::State state() const override
qint64 pushData(const char *data, qint64 len)
void setBufferSize(qsizetype) override
qreal volume() const override
void setFormat(const QAudioFormat &format) override
qsizetype bufferSize() const override
qsizetype bytesFree() const override
QIODevice * start() override
QQnxAudioSink(const QAudioDevice &deviceInfo, QObject *parent)
QAudioFormat format() const override
void setVolume(qreal volume) override
QAudio::Error error() const override
qint64 processedUSecs() const override
void activated(QSocketDescriptor socket, QSocketNotifier::Type activationEvent, QPrivateSignal)
void setSingleShot(bool singleShot)
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
void setInterval(int msec)
void stop()
Stops the timer.
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
QnxPushIODevice(QQnxAudioSink *output)
qint64 writeData(const char *data, qint64 len)
Writes up to maxSize bytes from data to the device.
bool isSequential() const override
Returns true if this device is sequential; otherwise returns false.
qint64 readData(char *data, qint64 len)
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
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< snd_pcm_channel_info_t > pcmChannelInfo(snd_pcm_t *handle, QAudioDevice::Mode mode)
std::optional< snd_pcm_channel_setup_t > pcmChannelSetup(snd_pcm_t *handle, QAudioDevice::Mode mode)
HandleUniquePtr openPcmDevice(const QByteArray &id, QAudioDevice::Mode mode)
std::optional< snd_pcm_channel_status_t > pcmChannelStatus(snd_pcm_t *handle, QAudioDevice::Mode mode)
snd_pcm_channel_params_t formatToChannelParams(const QAudioFormat &format, QAudioDevice::Mode mode, int fragmentSize)
DBusConnection const char DBusError * error
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
constexpr const T & qMax(const T &a, const T &b)
GLenum GLsizei GLuint GLint * bytesWritten
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
GLsizei GLsizei GLchar * source
QAudio::State suspendState(const snd_pcm_event_t &event)
QT_BEGIN_NAMESPACE typedef uchar * output
QFileInfo info(fileName)
[8]
QTextStream out(stdout)
[7]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent