15#include <QtCore/qcoreapplication.h>
16#include <QtCore/qvarlengtharray.h>
17#include <QtMultimedia/private/qaudiohelpers_p.h>
30 access = SND_PCM_ACCESS_RW_INTERLEAVED;
31 pcmformat = SND_PCM_FORMAT_S16;
90int QAlsaAudioSource::xrun_recovery(
int err)
103 err = snd_pcm_prepare(
handle);
107 bytesAvailable = checkBytesReady();
108 if (bytesAvailable <= 0)
111 }
else if ((err == -estrpipe)||(err == -EIO)) {
113 while((err = snd_pcm_resume(
handle)) == -EAGAIN){
122 err = snd_pcm_prepare(
handle);
138 snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN;
142 pcmformat = SND_PCM_FORMAT_U8;
146 pcmformat = SND_PCM_FORMAT_S16_LE;
148 pcmformat = SND_PCM_FORMAT_S16_BE;
152 pcmformat = SND_PCM_FORMAT_S32_LE;
154 pcmformat = SND_PCM_FORMAT_S32_BE;
158 pcmformat = SND_PCM_FORMAT_FLOAT_LE;
160 pcmformat = SND_PCM_FORMAT_FLOAT_BE;
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 );
279 err = snd_pcm_hw_params_set_rate_resample(
handle, hwparams, 1 );
286 err = snd_pcm_hw_params_set_access(
handle, hwparams,
access );
307 err = snd_pcm_hw_params_set_rate_near(
handle, hwparams, &sampleRate, 0 );
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);
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;
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)
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
QByteArray toLatin1() const &
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.
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)
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]
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
GLbitfield GLuint64 timeout
[4]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
QVideoFrameFormat::PixelFormat fmt
myObject disconnect()
[26]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent