15#include <QtCore/qcoreapplication.h>
16#include <QtCore/qvarlengtharray.h>
17#include <QtMultimedia/private/qaudiohelpers_p.h>
29 access = SND_PCM_ACCESS_RW_INTERLEAVED;
30 pcmformat = SND_PCM_FORMAT_S16;
89int QAlsaAudioSource::xrun_recovery(
int err)
102 err = snd_pcm_prepare(
handle);
106 bytesAvailable = checkBytesReady();
107 if (bytesAvailable <= 0)
110 }
else if ((err == -estrpipe)||(err == -EIO)) {
112 while((err = snd_pcm_resume(
handle)) == -EAGAIN){
121 err = snd_pcm_prepare(
handle);
137 snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN;
141 pcmformat = SND_PCM_FORMAT_U8;
145 pcmformat = SND_PCM_FORMAT_S16_BE;
147 pcmformat = SND_PCM_FORMAT_S16_LE;
151 pcmformat = SND_PCM_FORMAT_S32_BE;
153 pcmformat = SND_PCM_FORMAT_S32_LE;
157 pcmformat = SND_PCM_FORMAT_FLOAT_BE;
159 pcmformat = SND_PCM_FORMAT_FLOAT_LE;
165 return pcmformat != SND_PCM_FORMAT_UNKNOWN
166 ? snd_pcm_hw_params_set_format(
handle, hwparams, pcmformat)
222bool QAlsaAudioSource::open()
228 elapsedTimeOffset = 0;
236 qWarning(
"QAudioSource: open error, invalid format.");
238 qWarning(
"QAudioSource: open error, invalid sample rate (%d).",
253 while((
count < 5) && (err < 0)) {
254 err = snd_pcm_open(&
handle, m_device.
constData(), SND_PCM_STREAM_CAPTURE,0);
258 if (( err < 0)||(
handle == 0)) {
264 snd_pcm_nonblock(
handle, 0 );
267 snd_pcm_hw_params_alloca( &hwparams );
271 unsigned int chunks = 8;
273 err = snd_pcm_hw_params_any(
handle, hwparams );
276 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_any: err = %1").arg(err);
279 err = snd_pcm_hw_params_set_rate_resample(
handle, hwparams, 1 );
282 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err);
286 err = snd_pcm_hw_params_set_access(
handle, hwparams,
access );
289 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_access: err = %1").arg(err);
296 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_format: err = %1").arg(err);
303 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_channels: err = %1").arg(err);
307 err = snd_pcm_hw_params_set_rate_near(
handle, hwparams, &sampleRate, 0 );
310 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_rate_near: err = %1").arg(err);
314 err = snd_pcm_hw_params_set_buffer_time_near(
handle, hwparams, &buffer_time, &
dir);
317 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
321 err = snd_pcm_hw_params_set_period_time_near(
handle, hwparams, &period_time, &
dir);
324 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err);
328 err = snd_pcm_hw_params_set_periods_near(
handle, hwparams, &chunks, &
dir);
331 errMessage =
QString::fromLatin1(
"QAudioSource: snd_pcm_hw_params_set_periods_near: err = %1").arg(err);
335 err = snd_pcm_hw_params(
handle, hwparams);
348 snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
349 buffer_size = snd_pcm_frames_to_bytes(
handle,buffer_frames);
350 snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &
dir);
351 period_size = snd_pcm_frames_to_bytes(
handle,period_frames);
352 snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &
dir);
353 snd_pcm_hw_params_get_period_time(hwparams,&period_time, &
dir);
356 snd_pcm_sw_params_t *swparams;
357 snd_pcm_sw_params_alloca(&swparams);
358 snd_pcm_sw_params_current(
handle, swparams);
359 snd_pcm_sw_params_set_start_threshold(
handle,swparams,period_frames);
360 snd_pcm_sw_params_set_stop_threshold(
handle,swparams,buffer_frames);
361 snd_pcm_sw_params_set_avail_min(
handle, swparams,period_frames);
362 snd_pcm_sw_params(
handle, swparams);
365 ringBuffer.
resize(buffer_size);
366 snd_pcm_prepare(
handle );
370 bytesAvailable = checkBytesReady();
376 chunks = buffer_size/period_size;
377 timer->
start(period_time*chunks/2000);
386void QAlsaAudioSource::close()
397int QAlsaAudioSource::checkBytesReady()
400 bytesAvailable = period_size;
405 int frames = snd_pcm_avail_update(
handle);
407 bytesAvailable = frames;
409 if((
int)frames > (
int)buffer_frames)
410 frames = buffer_frames;
411 bytesAvailable = snd_pcm_frames_to_bytes(
handle, frames);
414 return bytesAvailable;
419 return qMax(bytesAvailable, 0);
434 int bytesToRead = checkBytesReady();
436 if (bytesToRead < 0) {
438 xrun_recovery(bytesToRead);
439 bytesToRead = checkBytesReady();
440 if (bytesToRead < 0) {
450 bytesToRead = qMin<qint64>(
len, bytesToRead);
451 bytesToRead = qMin<qint64>(ringBuffer.
freeBytes(), bytesToRead);
452 bytesToRead -= bytesToRead % period_size;
456 QVarLengthArray<char, 4096>
buffer(bytesToRead);
457 while(count < 5 && bytesToRead > 0) {
458 int chunks = bytesToRead / period_size;
459 int frames = chunks * period_frames;
460 if (frames > (
int)buffer_frames)
461 frames = buffer_frames;
463 int readFrames = snd_pcm_readi(
handle,
buffer.data(), frames);
464 bytesRead = snd_pcm_frames_to_bytes(
handle, readFrames);
468 buffer.data(), bytesRead);
470 if (readFrames >= 0) {
476 }
else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
481 if(readFrames == -EPIPE) {
483 err = snd_pcm_prepare(
handle);
485 }
else if(readFrames == -ESTRPIPE) {
486 err = snd_pcm_prepare(
handle);
496 bytesRead += bytesInRingbufferBeforeRead;
501 qDebug() <<
"frames to write to QIODevice = " <<
502 snd_pcm_bytes_to_frames(
handle, (
int)bytesRead ) <<
" (" << bytesRead <<
") bytes";
551 bytesAvailable -= bytesRead;
573 err = snd_pcm_prepare(
handle );
577 err = snd_pcm_start(
handle);
581 bytesAvailable = buffer_size;
585 int chunks = buffer_size/period_size;
586 timer->
start(period_time*chunks/2000);
620void QAlsaAudioSource::userFeed()
626 qDebug()<<
now.second()<<
"s "<<
now.msec()<<
"ms :userFeed() IN";
631bool QAlsaAudioSource::deviceReady()
635 read(0, buffer_size);
641 bytesAvailable = checkBytesReady();
646 if (bytesAvailable < 0) {
648 xrun_recovery(bytesAvailable);
649 bytesAvailable = checkBytesReady();
650 if (bytesAvailable < 0) {
671void QAlsaAudioSource::drain()
679 audioDevice = qobject_cast<QAlsaAudioSource*>(audio);
717 return m_tail - m_head;
718 else if (m_tail < m_head)
719 return m_data.
size() + m_tail - m_head;
727 return m_head - m_tail - 1;
728 else if (m_tail > m_head)
729 return m_data.
size() - m_tail + m_head - 1;
731 return m_data.
size() - 1;
742 return m_data.
size() - m_head;
743 else if (m_tail > m_head)
744 return m_tail - m_head;
751 m_head = (m_head + bytes) % m_data.
size();
756 if (m_tail +
len < m_data.
size()) {
760 int bytesUntilEnd = m_data.
size() - m_tail;
761 memcpy(m_data.
data() + m_tail,
data, bytesUntilEnd);
762 if (
len - bytesUntilEnd > 0)
763 memcpy(m_data.
data(),
data + bytesUntilEnd,
len - bytesUntilEnd);
764 m_tail =
len - bytesUntilEnd;
770#include "moc_qalsaaudiosource_p.cpp"
IOBluetoothDevice * device
QAlsaAudioSource(const QByteArray &device, QObject *parent)
qsizetype bytesReady() const override
QAudio::State deviceState
QAudioFormat format() const override
QIODevice * start() override
void setFormat(const QAudioFormat &fmt) override
void setVolume(qreal) override
qreal volume() const override
void setBufferSize(qsizetype value) override
QAudio::Error error() const override
QAudio::State state() const override
qsizetype bufferSize() const override
qint64 processedUSecs() const override
qint64 read(char *data, qint64 len)
void stateChanged(QAudio::State state)
void errorChanged(QAudio::Error error)
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
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.
void readyRead()
This signal is emitted once every time new data is available for reading from the device's current re...
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
\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...
\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 timeout(QPrivateSignal)
This signal is emitted when the timer times out.
const char * availableData() const
int availableDataBlockSize() const
void write(char *data, int len)
void readBytes(int bytes)
int bytesOfDataInBuffer() const
void qMultiplySamples(qreal factor, const QAudioFormat &format, const void *src, void *dest, int len)
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMax(const T &a, const T &b)
GLenum GLsizei GLuint GLint * bytesWritten
GLuint64 GLenum void * handle
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
QVideoFrameFormat::PixelFormat fmt
myObject disconnect()
[26]