BlackBerry/QNX: Implement audio recording with QAudioInput
Change-Id: I62cad152a7b7fd92905744439de838306dc7a558 Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
This commit is contained in:
committed by
The Qt Project
parent
909a09069f
commit
6a83c20318
@@ -10,11 +10,13 @@ LIBS += -lasound
|
|||||||
|
|
||||||
HEADERS += qnxaudioplugin.h \
|
HEADERS += qnxaudioplugin.h \
|
||||||
qnxaudiodeviceinfo.h \
|
qnxaudiodeviceinfo.h \
|
||||||
|
qnxaudioinput.h \
|
||||||
qnxaudiooutput.h \
|
qnxaudiooutput.h \
|
||||||
qnxaudioutils.h
|
qnxaudioutils.h
|
||||||
|
|
||||||
SOURCES += qnxaudioplugin.cpp \
|
SOURCES += qnxaudioplugin.cpp \
|
||||||
qnxaudiodeviceinfo.cpp \
|
qnxaudiodeviceinfo.cpp \
|
||||||
|
qnxaudioinput.cpp \
|
||||||
qnxaudiooutput.cpp \
|
qnxaudiooutput.cpp \
|
||||||
qnxaudioutils.cpp
|
qnxaudioutils.cpp
|
||||||
|
|
||||||
|
|||||||
447
src/plugins/qnx/audio/qnxaudioinput.cpp
Normal file
447
src/plugins/qnx/audio/qnxaudioinput.cpp
Normal file
@@ -0,0 +1,447 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Research In Motion
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3.0 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qnxaudioinput.h"
|
||||||
|
|
||||||
|
#include "qnxaudioutils.h"
|
||||||
|
|
||||||
|
#include <private/qaudiohelpers_p.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
QnxAudioInput::QnxAudioInput()
|
||||||
|
: m_audioSource(0)
|
||||||
|
, m_pcmHandle(0)
|
||||||
|
, m_pcmNotifier(0)
|
||||||
|
, m_error(QAudio::NoError)
|
||||||
|
, m_state(QAudio::StoppedState)
|
||||||
|
, m_bytesRead(0)
|
||||||
|
, m_elapsedTimeOffset(0)
|
||||||
|
, m_totalTimeValue(0)
|
||||||
|
, m_volume(qreal(1.0f))
|
||||||
|
, m_bytesAvailable(0)
|
||||||
|
, m_bufferSize(0)
|
||||||
|
, m_periodSize(0)
|
||||||
|
, m_intervalTime(1000)
|
||||||
|
, m_pullMode(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QnxAudioInput::~QnxAudioInput()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::start(QIODevice *device)
|
||||||
|
{
|
||||||
|
if (m_state != QAudio::StoppedState)
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (!m_pullMode && m_audioSource)
|
||||||
|
delete m_audioSource;
|
||||||
|
|
||||||
|
m_pullMode = true;
|
||||||
|
m_audioSource = device;
|
||||||
|
|
||||||
|
if (open()) {
|
||||||
|
setError(QAudio::NoError);
|
||||||
|
setState(QAudio::ActiveState);
|
||||||
|
} else {
|
||||||
|
setError(QAudio::OpenError);
|
||||||
|
setState(QAudio::StoppedState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QIODevice *QnxAudioInput::start()
|
||||||
|
{
|
||||||
|
if (m_state != QAudio::StoppedState)
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (!m_pullMode && m_audioSource)
|
||||||
|
delete m_audioSource;
|
||||||
|
|
||||||
|
m_pullMode = false;
|
||||||
|
m_audioSource = new InputPrivate(this);
|
||||||
|
m_audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||||
|
|
||||||
|
if (open()) {
|
||||||
|
setError(QAudio::NoError);
|
||||||
|
setState(QAudio::IdleState);
|
||||||
|
} else {
|
||||||
|
delete m_audioSource;
|
||||||
|
m_audioSource = 0;
|
||||||
|
|
||||||
|
setError(QAudio::OpenError);
|
||||||
|
setState(QAudio::StoppedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_audioSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::stop()
|
||||||
|
{
|
||||||
|
if (m_state == QAudio::StoppedState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setError(QAudio::NoError);
|
||||||
|
setState(QAudio::StoppedState);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::reset()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
m_bytesAvailable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::suspend()
|
||||||
|
{
|
||||||
|
if (m_pcmNotifier)
|
||||||
|
m_pcmNotifier->setEnabled(false);
|
||||||
|
|
||||||
|
setState(QAudio::SuspendedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::resume()
|
||||||
|
{
|
||||||
|
if (m_pcmNotifier)
|
||||||
|
m_pcmNotifier->setEnabled(true);
|
||||||
|
|
||||||
|
if (m_pullMode) {
|
||||||
|
setState(QAudio::ActiveState);
|
||||||
|
} else {
|
||||||
|
setState(QAudio::IdleState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int QnxAudioInput::bytesReady() const
|
||||||
|
{
|
||||||
|
return qMax(m_bytesAvailable, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int QnxAudioInput::periodSize() const
|
||||||
|
{
|
||||||
|
return m_periodSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::setBufferSize(int bufferSize)
|
||||||
|
{
|
||||||
|
m_bufferSize = bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QnxAudioInput::bufferSize() const
|
||||||
|
{
|
||||||
|
return m_bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::setNotifyInterval(int milliSeconds)
|
||||||
|
{
|
||||||
|
m_intervalTime = qMax(0, milliSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
int QnxAudioInput::notifyInterval() const
|
||||||
|
{
|
||||||
|
return m_intervalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QnxAudioInput::processedUSecs() const
|
||||||
|
{
|
||||||
|
return qint64(1000000) * m_format.framesForBytes(m_bytesRead) / m_format.sampleRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QnxAudioInput::elapsedUSecs() const
|
||||||
|
{
|
||||||
|
if (m_state == QAudio::StoppedState)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_clockStamp.elapsed() * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAudio::Error QnxAudioInput::error() const
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAudio::State QnxAudioInput::state() const
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::setFormat(const QAudioFormat &format)
|
||||||
|
{
|
||||||
|
if (m_state == QAudio::StoppedState)
|
||||||
|
m_format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAudioFormat QnxAudioInput::format() const
|
||||||
|
{
|
||||||
|
return m_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::setVolume(qreal volume)
|
||||||
|
{
|
||||||
|
m_volume = qBound(qreal(0.0), volume, qreal(1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal QnxAudioInput::volume() const
|
||||||
|
{
|
||||||
|
return m_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::userFeed()
|
||||||
|
{
|
||||||
|
if (m_state == QAudio::StoppedState || m_state == QAudio::SuspendedState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
deviceReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QnxAudioInput::deviceReady()
|
||||||
|
{
|
||||||
|
if (m_pullMode) {
|
||||||
|
// reads some audio data and writes it to QIODevice
|
||||||
|
read(0, 0);
|
||||||
|
} else {
|
||||||
|
m_bytesAvailable = m_periodSize;
|
||||||
|
|
||||||
|
// emits readyRead() so user will call read() on QIODevice to get some audio data
|
||||||
|
if (m_audioSource != 0) {
|
||||||
|
InputPrivate *input = qobject_cast<InputPrivate*>(m_audioSource);
|
||||||
|
input->trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state != QAudio::ActiveState)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (m_intervalTime && (m_timeStamp.elapsed() + m_elapsedTimeOffset) > m_intervalTime) {
|
||||||
|
emit notify();
|
||||||
|
m_elapsedTimeOffset = m_timeStamp.elapsed() + m_elapsedTimeOffset - m_intervalTime;
|
||||||
|
m_timeStamp.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QnxAudioInput::open()
|
||||||
|
{
|
||||||
|
if (!m_format.isValid() || m_format.sampleRate() <= 0) {
|
||||||
|
if (!m_format.isValid())
|
||||||
|
qWarning("QnxAudioInput: open error, invalid format.");
|
||||||
|
else
|
||||||
|
qWarning("QnxAudioInput: open error, invalid sample rate (%d).", m_format.sampleRate());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int errorCode = 0;
|
||||||
|
|
||||||
|
int card = 0;
|
||||||
|
int device = 0;
|
||||||
|
if ((errorCode = snd_pcm_open_preferred(&m_pcmHandle, &card, &device, SND_PCM_OPEN_CAPTURE)) < 0) {
|
||||||
|
qWarning("QnxAudioInput: open error, couldn't open card (0x%x)", -errorCode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Necessary so that bytesFree() which uses the "free" member of the status struct works
|
||||||
|
snd_pcm_plugin_set_disable(m_pcmHandle, PLUGIN_DISABLE_MMAP);
|
||||||
|
|
||||||
|
snd_pcm_channel_info_t info;
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
info.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||||
|
if ((errorCode = snd_pcm_plugin_info(m_pcmHandle, &info)) < 0) {
|
||||||
|
qWarning("QnxAudioInput: open error, couldn't get channel info (0x%x)", -errorCode);
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_pcm_channel_params_t params = QnxAudioUtils::formatToChannelParams(m_format, QAudio::AudioInput, info.max_fragment_size);
|
||||||
|
|
||||||
|
if ((errorCode = snd_pcm_plugin_params(m_pcmHandle, ¶ms)) < 0) {
|
||||||
|
qWarning("QnxAudioInput: open error, couldn't set channel params (0x%x)", -errorCode);
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE)) < 0) {
|
||||||
|
qWarning("QnxAudioInput: open error, couldn't prepare channel (0x%x)", -errorCode);
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_pcm_channel_setup_t setup;
|
||||||
|
|
||||||
|
memset(&setup, 0, sizeof(setup));
|
||||||
|
setup.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||||
|
if ((errorCode = snd_pcm_plugin_setup(m_pcmHandle, &setup)) < 0) {
|
||||||
|
qWarning("QnxAudioInput: open error, couldn't get channel setup (0x%x)", -errorCode);
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_periodSize = qMin(2048, setup.buf.block.frag_size);
|
||||||
|
|
||||||
|
m_clockStamp.restart();
|
||||||
|
m_timeStamp.restart();
|
||||||
|
m_elapsedTimeOffset = 0;
|
||||||
|
m_totalTimeValue = 0;
|
||||||
|
m_bytesRead = 0;
|
||||||
|
|
||||||
|
m_pcmNotifier = new QSocketNotifier(snd_pcm_file_descriptor(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE),
|
||||||
|
QSocketNotifier::Read, this);
|
||||||
|
connect(m_pcmNotifier, SIGNAL(activated(int)), SLOT(userFeed()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::close()
|
||||||
|
{
|
||||||
|
if (m_pcmHandle)
|
||||||
|
snd_pcm_plugin_flush(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE);
|
||||||
|
|
||||||
|
if (m_pcmNotifier) {
|
||||||
|
delete m_pcmNotifier;
|
||||||
|
m_pcmNotifier = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pcmHandle) {
|
||||||
|
snd_pcm_close(m_pcmHandle);
|
||||||
|
m_pcmHandle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_pullMode && m_audioSource) {
|
||||||
|
delete m_audioSource;
|
||||||
|
m_audioSource = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QnxAudioInput::read(char *data, qint64 len)
|
||||||
|
{
|
||||||
|
int errorCode = 0;
|
||||||
|
QByteArray tempBuffer(m_periodSize, 0);
|
||||||
|
|
||||||
|
const int actualRead = snd_pcm_plugin_read(m_pcmHandle, tempBuffer.data(), m_periodSize);
|
||||||
|
if (actualRead < 1) {
|
||||||
|
snd_pcm_channel_status_t status;
|
||||||
|
memset(&status, 0, sizeof(status));
|
||||||
|
status.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||||
|
if ((errorCode = snd_pcm_plugin_status(m_pcmHandle, &status)) < 0) {
|
||||||
|
qWarning("QnxAudioInput: read error, couldn't get plugin status (0x%x)", -errorCode);
|
||||||
|
close();
|
||||||
|
setError(QAudio::FatalError);
|
||||||
|
setState(QAudio::StoppedState);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.status == SND_PCM_STATUS_READY
|
||||||
|
|| status.status == SND_PCM_STATUS_OVERRUN) {
|
||||||
|
if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE)) < 0) {
|
||||||
|
qWarning("QnxAudioInput: read error, couldn't prepare plugin (0x%x)", -errorCode);
|
||||||
|
close();
|
||||||
|
setError(QAudio::FatalError);
|
||||||
|
setState(QAudio::StoppedState);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setError(QAudio::NoError);
|
||||||
|
setState(QAudio::ActiveState);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_volume < 1.0f)
|
||||||
|
QAudioHelperInternal::qMultiplySamples(m_volume, m_format, tempBuffer.data(), tempBuffer.data(), actualRead);
|
||||||
|
|
||||||
|
m_bytesRead += actualRead;
|
||||||
|
|
||||||
|
if (m_pullMode) {
|
||||||
|
m_audioSource->write(tempBuffer.data(), actualRead);
|
||||||
|
} else {
|
||||||
|
memcpy(data, tempBuffer.data(), qMin(static_cast<qint64>(actualRead), len));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bytesAvailable = 0;
|
||||||
|
|
||||||
|
return actualRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::setError(QAudio::Error error)
|
||||||
|
{
|
||||||
|
if (m_error == error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_error = error;
|
||||||
|
emit errorChanged(m_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxAudioInput::setState(QAudio::State state)
|
||||||
|
{
|
||||||
|
if (m_state == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_state = state;
|
||||||
|
emit stateChanged(m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
InputPrivate::InputPrivate(QnxAudioInput *audio)
|
||||||
|
: m_audioDevice(audio)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 InputPrivate::readData(char *data, qint64 len)
|
||||||
|
{
|
||||||
|
return m_audioDevice->read(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 InputPrivate::writeData(const char *data, qint64 len)
|
||||||
|
{
|
||||||
|
Q_UNUSED(data)
|
||||||
|
Q_UNUSED(len)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputPrivate::trigger()
|
||||||
|
{
|
||||||
|
emit readyRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
139
src/plugins/qnx/audio/qnxaudioinput.h
Normal file
139
src/plugins/qnx/audio/qnxaudioinput.h
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Research In Motion
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3.0 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QNXAUDIOINPUT_H
|
||||||
|
#define QNXAUDIOINPUT_H
|
||||||
|
|
||||||
|
#include "qaudiosystem.h"
|
||||||
|
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <sys/asoundlib.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QnxAudioInput : public QAbstractAudioInput
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QnxAudioInput();
|
||||||
|
~QnxAudioInput();
|
||||||
|
|
||||||
|
void start(QIODevice*) Q_DECL_OVERRIDE;
|
||||||
|
QIODevice* start() Q_DECL_OVERRIDE;
|
||||||
|
void stop() Q_DECL_OVERRIDE;
|
||||||
|
void reset() Q_DECL_OVERRIDE;
|
||||||
|
void suspend() Q_DECL_OVERRIDE;
|
||||||
|
void resume() Q_DECL_OVERRIDE;
|
||||||
|
int bytesReady() const Q_DECL_OVERRIDE;
|
||||||
|
int periodSize() const Q_DECL_OVERRIDE;
|
||||||
|
void setBufferSize(int ) Q_DECL_OVERRIDE;
|
||||||
|
int bufferSize() const Q_DECL_OVERRIDE;
|
||||||
|
void setNotifyInterval(int ) Q_DECL_OVERRIDE;
|
||||||
|
int notifyInterval() const Q_DECL_OVERRIDE;
|
||||||
|
qint64 processedUSecs() const Q_DECL_OVERRIDE;
|
||||||
|
qint64 elapsedUSecs() const Q_DECL_OVERRIDE;
|
||||||
|
QAudio::Error error() const Q_DECL_OVERRIDE;
|
||||||
|
QAudio::State state() const Q_DECL_OVERRIDE;
|
||||||
|
void setFormat(const QAudioFormat&) Q_DECL_OVERRIDE;
|
||||||
|
QAudioFormat format() const Q_DECL_OVERRIDE;
|
||||||
|
void setVolume(qreal) Q_DECL_OVERRIDE;
|
||||||
|
qreal volume() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void userFeed();
|
||||||
|
bool deviceReady();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class InputPrivate;
|
||||||
|
|
||||||
|
bool open();
|
||||||
|
void close();
|
||||||
|
qint64 read(char *data, qint64 len);
|
||||||
|
void setError(QAudio::Error error);
|
||||||
|
void setState(QAudio::State state);
|
||||||
|
|
||||||
|
QTime m_timeStamp;
|
||||||
|
QTime m_clockStamp;
|
||||||
|
QAudioFormat m_format;
|
||||||
|
|
||||||
|
QIODevice *m_audioSource;
|
||||||
|
snd_pcm_t *m_pcmHandle;
|
||||||
|
QSocketNotifier *m_pcmNotifier;
|
||||||
|
|
||||||
|
QAudio::Error m_error;
|
||||||
|
QAudio::State m_state;
|
||||||
|
|
||||||
|
qint64 m_bytesRead;
|
||||||
|
qint64 m_elapsedTimeOffset;
|
||||||
|
qint64 m_totalTimeValue;
|
||||||
|
|
||||||
|
qreal m_volume;
|
||||||
|
|
||||||
|
int m_bytesAvailable;
|
||||||
|
int m_bufferSize;
|
||||||
|
int m_periodSize;
|
||||||
|
int m_intervalTime;
|
||||||
|
|
||||||
|
bool m_pullMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InputPrivate : public QIODevice
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
InputPrivate(QnxAudioInput *audio);
|
||||||
|
|
||||||
|
qint64 readData(char *data, qint64 len) Q_DECL_OVERRIDE;
|
||||||
|
qint64 writeData(const char *data, qint64 len) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void trigger();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QnxAudioInput *m_audioDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -42,10 +42,12 @@
|
|||||||
#include "qnxaudioplugin.h"
|
#include "qnxaudioplugin.h"
|
||||||
|
|
||||||
#include "qnxaudiodeviceinfo.h"
|
#include "qnxaudiodeviceinfo.h"
|
||||||
|
#include "qnxaudioinput.h"
|
||||||
#include "qnxaudiooutput.h"
|
#include "qnxaudiooutput.h"
|
||||||
|
|
||||||
#include <sys/asoundlib.h>
|
#include <sys/asoundlib.h>
|
||||||
|
|
||||||
|
static const char *INPUT_ID = "QnxAudioInput";
|
||||||
static const char *OUTPUT_ID = "QnxAudioOutput";
|
static const char *OUTPUT_ID = "QnxAudioOutput";
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -60,13 +62,14 @@ QList<QByteArray> QnxAudioPlugin::availableDevices(QAudio::Mode mode) const
|
|||||||
if (mode == QAudio::AudioOutput)
|
if (mode == QAudio::AudioOutput)
|
||||||
return QList<QByteArray>() << OUTPUT_ID;
|
return QList<QByteArray>() << OUTPUT_ID;
|
||||||
else
|
else
|
||||||
return QList<QByteArray>();
|
return QList<QByteArray>() << INPUT_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractAudioInput *QnxAudioPlugin::createInput(const QByteArray &device)
|
QAbstractAudioInput *QnxAudioPlugin::createInput(const QByteArray &device)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(device == INPUT_ID);
|
||||||
Q_UNUSED(device);
|
Q_UNUSED(device);
|
||||||
return 0;
|
return new QnxAudioInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractAudioOutput *QnxAudioPlugin::createOutput(const QByteArray &device)
|
QAbstractAudioOutput *QnxAudioPlugin::createOutput(const QByteArray &device)
|
||||||
|
|||||||
Reference in New Issue
Block a user