15#include <QtCore/qcoreapplication.h>
16#include <QtCore/qvarlengtharray.h>
17#include <QtMultimedia/private/qaudiohelpers_p.h>
20#include <QLoggingCategory>
64int QAlsaAudioSink::xrun_recovery(
int err)
78 err = snd_pcm_prepare(
handle);
82 }
else if ((err == -estrpipe)||(err == -EIO)) {
85 while((err = snd_pcm_resume(
handle)) == -EAGAIN){
94 err = snd_pcm_prepare(
handle);
110 snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN;
114 pcmformat = SND_PCM_FORMAT_U8;
118 pcmformat = SND_PCM_FORMAT_S16_LE;
120 pcmformat = SND_PCM_FORMAT_S16_BE;
124 pcmformat = SND_PCM_FORMAT_S32_LE;
126 pcmformat = SND_PCM_FORMAT_S32_BE;
130 pcmformat = SND_PCM_FORMAT_FLOAT_LE;
132 pcmformat = SND_PCM_FORMAT_FLOAT_BE;
137 return pcmformat != SND_PCM_FORMAT_UNKNOWN
138 ? snd_pcm_hw_params_set_format(
handle, hwparams, pcmformat)
205bool QAlsaAudioSink::open()
214 elapsedTimeOffset = 0;
222 qWarning(
"QAudioSink: open error, invalid format.");
224 qWarning(
"QAudioSink: open error, invalid sample rate (%d).",
238 while((
count < 5) && (err < 0)) {
239 err=snd_pcm_open(&
handle, m_device.
constData(),SND_PCM_STREAM_PLAYBACK,0);
243 if (( err < 0)||(
handle == 0)) {
249 snd_pcm_nonblock(
handle, 0 );
252 snd_pcm_hw_params_alloca( &hwparams );
256 unsigned int chunks = 8;
258 err = snd_pcm_hw_params_any(
handle, hwparams );
264 err = snd_pcm_hw_params_set_rate_resample(
handle, hwparams, 1 );
271 err = snd_pcm_hw_params_set_access(
handle, hwparams,
access );
292 err = snd_pcm_hw_params_set_rate_near(
handle, hwparams, &sampleRate, 0 );
299 unsigned int maxBufferTime = 0;
300 unsigned int minBufferTime = 0;
301 unsigned int maxPeriodTime = 0;
302 unsigned int minPeriodTime = 0;
304 err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &maxBufferTime, &
dir);
306 err = snd_pcm_hw_params_get_buffer_time_min(hwparams, &minBufferTime, &
dir);
308 err = snd_pcm_hw_params_get_period_time_max(hwparams, &maxPeriodTime, &
dir);
310 err = snd_pcm_hw_params_get_period_time_min(hwparams, &minPeriodTime, &
dir);
318 const bool outOfRange = maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time;
319 if (outOfRange || user_period_time || user_buffer_time) {
320 period_time = user_period_time ? user_period_time : minPeriodTime;
321 if (!user_buffer_time) {
322 chunks = maxBufferTime / period_time;
323 buffer_time = period_time * chunks;
325 buffer_time = user_buffer_time;
326 chunks = buffer_time / period_time;
329 qCDebug(lcAlsaOutput) <<
"buffer time: [" << minBufferTime <<
"-" << maxBufferTime <<
"] =" << buffer_time;
330 qCDebug(lcAlsaOutput) <<
"period time: [" << minPeriodTime <<
"-" << maxPeriodTime <<
"] =" << period_time;
331 qCDebug(lcAlsaOutput) <<
"chunks =" << chunks;
335 err = snd_pcm_hw_params_set_buffer_time_near(
handle, hwparams, &buffer_time, &
dir);
338 errMessage =
QString::fromLatin1(
"QAudioSink: snd_pcm_hw_params_set_buffer_time_near: err = %1").
arg(err);
342 err = snd_pcm_hw_params_set_period_time_near(
handle, hwparams, &period_time, &
dir);
345 errMessage =
QString::fromLatin1(
"QAudioSink: snd_pcm_hw_params_set_period_time_near: err = %1").
arg(err);
349 err = snd_pcm_hw_params_set_periods_near(
handle, hwparams, &chunks, &
dir);
356 err = snd_pcm_hw_params(
handle, hwparams);
369 snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
370 buffer_size = snd_pcm_frames_to_bytes(
handle,buffer_frames);
371 snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &
dir);
372 period_size = snd_pcm_frames_to_bytes(
handle,period_frames);
373 snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &
dir);
374 snd_pcm_hw_params_get_period_time(hwparams,&period_time, &
dir);
377 snd_pcm_sw_params_t *swparams;
378 snd_pcm_sw_params_alloca(&swparams);
379 snd_pcm_sw_params_current(
handle, swparams);
380 snd_pcm_sw_params_set_start_threshold(
handle,swparams,period_frames);
381 snd_pcm_sw_params_set_stop_threshold(
handle,swparams,buffer_frames);
382 snd_pcm_sw_params_set_avail_min(
handle, swparams,period_frames);
383 snd_pcm_sw_params(
handle, swparams);
387 audioBuffer =
new char[snd_pcm_frames_to_bytes(
handle,buffer_frames)];
388 snd_pcm_prepare(
handle );
395 timer->
start(period_time/1000);
397 elapsedTimeOffset = 0;
405void QAlsaAudioSink::close()
413 delete [] audioBuffer;
431 int frames = snd_pcm_avail_update(
handle);
432 if (frames == -EPIPE) {
434 int err = snd_pcm_recover(
handle, frames, 0);
438 frames = snd_pcm_avail_update(
handle);
439 }
else if (frames < 0) {
443 if ((
int)frames > (
int)buffer_frames)
444 frames = buffer_frames;
446 return snd_pcm_frames_to_bytes(
handle, frames);
455 qDebug()<<
"frames to write out = "<<
456 snd_pcm_bytes_to_frames(
handle, (
int)
len )<<
" ("<<
len<<
") bytes";
467 frames = snd_pcm_bytes_to_frames(
handle, space);
469 if (m_volume < 1.0f) {
472 err = snd_pcm_writei(
handle,
out.constData(), frames);
478 totalTimeValue += err;
485 return snd_pcm_frames_to_bytes(
handle, err );
487 err = xrun_recovery(err);
521 err = snd_pcm_prepare(
handle );
525 err = snd_pcm_start(
handle);
529 bytesAvailable = (int)snd_pcm_frames_to_bytes(
handle, buffer_frames);
535 timer->
start(period_time/1000);
562void QAlsaAudioSink::userFeed()
568 qDebug()<<
now.second()<<
"s "<<
now.msec()<<
"ms :userFeed() OUT";
576bool QAlsaAudioSink::deviceReady()
580 int chunks = bytesAvailable/period_size;
586 qDebug()<<
"deviceReady() avail="<<bytesAvailable<<
" bytes, period size="<<period_size<<
" bytes";
587 qDebug()<<
"deviceReady() no. of chunks that can fit ="<<chunks<<
", chunks in bytes ="<<period_size*chunks;
589 int input = period_frames*chunks;
590 if(
input > (
int)buffer_frames)
591 input = buffer_frames;
610 if(bytesAvailable > snd_pcm_frames_to_bytes(
handle, buffer_frames-period_frames)) {
629 if(bytesAvailable > snd_pcm_frames_to_bytes(
handle, buffer_frames-period_frames)) {
656 audioDevice = qobject_cast<QAlsaAudioSink*>(audio);
675 while(written <
len) {
676 int chunk = audioDevice->
write(
data+written,(
len-written));
690#include "moc_qalsaaudiosink_p.cpp"
IOBluetoothDevice * device
qint64 writeData(const char *data, qint64 len) override
Writes up to maxSize bytes from data to the device.
AlsaOutputPrivate(QAlsaAudioSink *audio)
qint64 readData(char *data, qint64 len) override
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
friend class AlsaOutputPrivate
QIODevice * start() override
void setBufferSize(qsizetype value) override
QAudio::State suspendedInState
qint64 processedUSecs() const override
void setFormat(const QAudioFormat &fmt) override
void setVolume(qreal) override
QAudio::State deviceState
QAudio::State state() const override
qreal volume() const override
qsizetype bytesFree() const override
QAudioFormat format() const override
qsizetype bufferSize() const override
QAudio::Error error() const override
qint64 write(const char *data, qint64 len)
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Processes some pending events for the calling thread according to the specified flags.
\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.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
\inmodule QtCore \reentrant
static QTime currentTime()
Returns the current time as reported by the system clock.
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
void stop()
Stops the timer.
void qMultiplySamples(qreal factor, const QAudioFormat &format, const void *src, void *dest, int len)
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.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLenum GLsizei GLuint GLint * bytesWritten
GLuint64 GLenum void * handle
GLenum GLenum GLsizei count
GLbitfield GLuint64 timeout
[4]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLenum input
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
QVideoFrameFormat::PixelFormat fmt
QTextStream out(stdout)
[7]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
myObject disconnect()
[26]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent