BlackBerry/QNX: Add a new backend for Blackberry handling audio

For now it only implements the audio output part.
The plugin can be used on all QNX systems (including BB10) that
provide a libasound version < 1.0.10.

Change-Id: Ifcfd871558d5d2bfb9e8a5f5ef0cfe009c0a111d
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
This commit is contained in:
Kevin Ottens
2013-02-21 14:28:12 +01:00
committed by The Qt Project
parent 1ddad9e0f4
commit fb6e49f33f
12 changed files with 1170 additions and 0 deletions

View File

@@ -12,6 +12,10 @@ blackberry {
SUBDIRS += blackberry
}
qnx {
SUBDIRS += qnx
}
win32 {
SUBDIRS += audiocapture
}

View File

@@ -0,0 +1,24 @@
TARGET = qtmedia_qnx_audio
QT += multimedia-private
CONFIG += no_private_qt_headers_warning
PLUGIN_TYPE = audio
load(qt_plugin)
DESTDIR = $$QT.multimedia.plugins/$${PLUGIN_TYPE}
LIBS += -lasound
HEADERS += qnxaudioplugin.h \
qnxaudiodeviceinfo.h \
qnxaudiooutput.h \
qnxaudioutils.h
SOURCES += qnxaudioplugin.cpp \
qnxaudiodeviceinfo.cpp \
qnxaudiooutput.cpp \
qnxaudioutils.cpp
OTHER_FILES += qnx_audio.json
target.path += $$[QT_INSTALL_PLUGINS]/$${PLUGIN_TYPE}
INSTALLS += target

View File

@@ -0,0 +1,3 @@
{
"Keys": ["default"]
}

View File

@@ -0,0 +1,150 @@
/****************************************************************************
**
** 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 "qnxaudiodeviceinfo.h"
#include "qnxaudioutils.h"
#include <sys/asoundlib.h>
QT_BEGIN_NAMESPACE
QnxAudioDeviceInfo::QnxAudioDeviceInfo(const QString &deviceName, QAudio::Mode mode)
: m_name(deviceName),
m_mode(mode)
{
}
QnxAudioDeviceInfo::~QnxAudioDeviceInfo()
{
}
QAudioFormat QnxAudioDeviceInfo::preferredFormat() const
{
QAudioFormat format;
if (m_mode == QAudio::AudioOutput) {
format.setSampleRate(44100);
format.setChannelCount(2);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
format.setSampleSize(16);
format.setCodec(QLatin1String("audio/pcm"));
} else {
format.setSampleRate(8000);
format.setChannelCount(1);
format.setSampleType(QAudioFormat::UnSignedInt);
format.setSampleSize(8);
format.setCodec(QLatin1String("audio/pcm"));
if (!isFormatSupported(format)) {
format.setChannelCount(2);
format.setSampleSize(16);
format.setSampleType(QAudioFormat::SignedInt);
}
}
return format;
}
bool QnxAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const
{
if (!format.codec().startsWith(QLatin1String("audio/pcm")))
return false;
const int pcmMode = (m_mode == QAudio::AudioOutput) ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE;
snd_pcm_t *handle;
int card = 0;
int device = 0;
if (snd_pcm_open_preferred(&handle, &card, &device, pcmMode) < 0)
return false;
snd_pcm_channel_info_t info;
memset (&info, 0, sizeof(info));
info.channel = (m_mode == QAudio::AudioOutput) ? SND_PCM_CHANNEL_PLAYBACK : SND_PCM_CHANNEL_CAPTURE;
if (snd_pcm_plugin_info(handle, &info) < 0) {
qWarning("QAudioDeviceInfo: couldn't get channel info");
snd_pcm_close(handle);
return false;
}
snd_pcm_channel_params_t params = QnxAudioUtils::formatToChannelParams(format, m_mode, info.max_fragment_size);
const int errorCode = snd_pcm_plugin_params(handle, &params);
snd_pcm_close(handle);
return errorCode == 0;
}
QString QnxAudioDeviceInfo::deviceName() const
{
return m_name;
}
QStringList QnxAudioDeviceInfo::supportedCodecs()
{
return QStringList() << QLatin1String("audio/pcm");
}
QList<int> QnxAudioDeviceInfo::supportedSampleRates()
{
return QList<int>() << 8000 << 11025 << 22050 << 44100 << 48000;
}
QList<int> QnxAudioDeviceInfo::supportedChannelCounts()
{
return QList<int>() << 1 << 2;
}
QList<int> QnxAudioDeviceInfo::supportedSampleSizes()
{
return QList<int>() << 8 << 16 << 32;
}
QList<QAudioFormat::Endian> QnxAudioDeviceInfo::supportedByteOrders()
{
return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian;
}
QList<QAudioFormat::SampleType> QnxAudioDeviceInfo::supportedSampleTypes()
{
return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** 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 QNXAUDIODEVICEINFO_H
#define QNXAUDIODEVICEINFO_H
#include "qaudiosystem.h"
QT_BEGIN_NAMESPACE
class QnxAudioDeviceInfo : public QAbstractAudioDeviceInfo
{
Q_OBJECT
public:
QnxAudioDeviceInfo(const QString &deviceName, QAudio::Mode mode);
~QnxAudioDeviceInfo();
QAudioFormat preferredFormat() const Q_DECL_OVERRIDE;
bool isFormatSupported(const QAudioFormat &format) const Q_DECL_OVERRIDE;
QString deviceName() const Q_DECL_OVERRIDE;
QStringList supportedCodecs() Q_DECL_OVERRIDE;
QList<int> supportedSampleRates() Q_DECL_OVERRIDE;
QList<int> supportedChannelCounts() Q_DECL_OVERRIDE;
QList<int> supportedSampleSizes() Q_DECL_OVERRIDE;
QList<QAudioFormat::Endian> supportedByteOrders() Q_DECL_OVERRIDE;
QList<QAudioFormat::SampleType> supportedSampleTypes() Q_DECL_OVERRIDE;
private:
const QString m_name;
const QAudio::Mode m_mode;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,443 @@
/****************************************************************************
**
** 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 "qnxaudiooutput.h"
#include "qnxaudioutils.h"
#include <private/qaudiohelpers_p.h>
QT_BEGIN_NAMESPACE
QnxAudioOutput::QnxAudioOutput()
: m_source(0),
m_pushSource(false),
m_notifyInterval(1000),
m_error(QAudio::NoError),
m_state(QAudio::StoppedState),
m_volume(1.0),
m_periodSize(0),
m_pcmHandle(0),
m_bytesWritten(0),
m_intervalOffset(0)
{
m_timer.setSingleShot(false);
m_timer.setInterval(20);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(pullData()));
}
QnxAudioOutput::~QnxAudioOutput()
{
stop();
}
void QnxAudioOutput::start(QIODevice *source)
{
if (m_state != QAudio::StoppedState)
stop();
m_error = QAudio::NoError;
m_source = source;
m_pushSource = false;
if (open()) {
setState(QAudio::ActiveState);
m_timer.start();
} else {
setError(QAudio::OpenError);
setState(QAudio::StoppedState);
}
}
QIODevice *QnxAudioOutput::start()
{
if (m_state != QAudio::StoppedState)
stop();
m_error = QAudio::NoError;
m_source = new QnxPushIODevice(this);
m_source->open(QIODevice::WriteOnly|QIODevice::Unbuffered);
m_pushSource = true;
if (open())
setState(QAudio::IdleState);
else {
setError(QAudio::OpenError);
setState(QAudio::StoppedState);
}
return m_source;
}
void QnxAudioOutput::stop()
{
if (m_state == QAudio::StoppedState)
return;
setError(QAudio::NoError);
setState(QAudio::StoppedState);
close();
}
void QnxAudioOutput::reset()
{
if (m_pcmHandle)
snd_pcm_playback_drain(m_pcmHandle);
stop();
}
void QnxAudioOutput::suspend()
{
m_timer.stop();
setState(QAudio::SuspendedState);
}
void QnxAudioOutput::resume()
{
if (m_pushSource)
setState(QAudio::IdleState);
else {
setState(QAudio::ActiveState);
m_timer.start();
}
}
int QnxAudioOutput::bytesFree() const
{
if (m_state != QAudio::ActiveState && m_state != QAudio::IdleState)
return 0;
snd_pcm_channel_status_t status;
status.channel = SND_PCM_CHANNEL_PLAYBACK;
const int errorCode = snd_pcm_plugin_status(m_pcmHandle, &status);
if (errorCode)
return 0;
else
return status.free;
}
int QnxAudioOutput::periodSize() const
{
return m_periodSize;
}
void QnxAudioOutput::setNotifyInterval(int ms)
{
m_notifyInterval = ms;
}
int QnxAudioOutput::notifyInterval() const
{
return m_notifyInterval;
}
qint64 QnxAudioOutput::processedUSecs() const
{
return qint64(1000000) * m_format.framesForBytes(m_bytesWritten) / m_format.sampleRate();
}
qint64 QnxAudioOutput::elapsedUSecs() const
{
if (m_state == QAudio::StoppedState)
return 0;
else
return m_startTimeStamp.elapsed() * 1000;
}
QAudio::Error QnxAudioOutput::error() const
{
return m_error;
}
QAudio::State QnxAudioOutput::state() const
{
return m_state;
}
void QnxAudioOutput::setFormat(const QAudioFormat &format)
{
if (m_state == QAudio::StoppedState)
m_format = format;
}
QAudioFormat QnxAudioOutput::format() const
{
return m_format;
}
void QnxAudioOutput::setVolume(qreal volume)
{
m_volume = qBound(qreal(0.0), volume, qreal(1.0));
}
qreal QnxAudioOutput::volume() const
{
return m_volume;
}
void QnxAudioOutput::pullData()
{
if (m_state == QAudio::StoppedState || m_state == QAudio::SuspendedState)
return;
const int bytesAvailable = bytesFree();
const int frames = m_format.framesForBytes(bytesAvailable);
if (frames == 0 || bytesAvailable < periodSize())
return;
const int bytesRequested = m_format.bytesForFrames(frames);
char buffer[bytesRequested];
const int bytesRead = m_source->read(buffer, bytesRequested);
// reading can take a while and stream may have been stopped
if (!m_pcmHandle)
return;
if (bytesRead > 0) {
// Got some data to output
if (m_state != QAudio::ActiveState)
return;
const qint64 bytesWritten = write(buffer, bytesRead);
if (bytesWritten != bytesRead)
m_source->seek(m_source->pos()-(bytesRead-bytesWritten));
} else {
// We're done
close();
if (bytesRead != 0)
setError(QAudio::IOError);
setState(QAudio::StoppedState);
}
if (m_state != QAudio::ActiveState)
return;
if (m_notifyInterval > 0 && (m_intervalTimeStamp.elapsed() + m_intervalOffset) > m_notifyInterval) {
emit notify();
m_intervalOffset = m_intervalTimeStamp.elapsed() + m_intervalOffset - m_notifyInterval;
m_intervalTimeStamp.restart();
}
}
bool QnxAudioOutput::open()
{
if (!m_format.isValid() || m_format.sampleRate() <= 0) {
if (!m_format.isValid())
qWarning("QnxAudioOutput: open error, invalid format.");
else
qWarning("QnxAudioOutput: 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_PLAYBACK)) < 0) {
qWarning("QnxAudioOutput: open error, couldn't open card (0x%x)", -errorCode);
return false;
}
if ((errorCode = snd_pcm_nonblock_mode(m_pcmHandle, 0)) < 0) {
qWarning("QnxAudioOutput: open error, couldn't set non block mode (0x%x)", -errorCode);
close();
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_PLAYBACK;
if ((errorCode = snd_pcm_plugin_info(m_pcmHandle, &info)) < 0) {
qWarning("QnxAudioOutput: open error, couldn't get channel info (0x%x)", -errorCode);
close();
return false;
}
snd_pcm_channel_params_t params = QnxAudioUtils::formatToChannelParams(m_format, QAudio::AudioOutput, info.max_fragment_size);
if ((errorCode = snd_pcm_plugin_params(m_pcmHandle, &params)) < 0) {
qWarning("QnxAudioOutput: open error, couldn't set channel params (0x%x)", -errorCode);
close();
return false;
}
if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
qWarning("QnxAudioOutput: 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_PLAYBACK;
if ((errorCode = snd_pcm_plugin_setup(m_pcmHandle, &setup)) < 0) {
qWarning("QnxAudioOutput: open error, couldn't get channel setup (0x%x)", -errorCode);
close();
return false;
}
m_periodSize = qMin(2048, setup.buf.block.frag_size);
m_startTimeStamp.restart();
m_intervalTimeStamp.restart();
m_intervalOffset = 0;
m_bytesWritten = 0;
return true;
}
void QnxAudioOutput::close()
{
m_timer.stop();
if (m_pcmHandle) {
snd_pcm_plugin_flush(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
snd_pcm_close(m_pcmHandle);
m_pcmHandle = 0;
}
if (m_pushSource) {
delete m_source;
m_source = 0;
}
}
void QnxAudioOutput::setError(QAudio::Error error)
{
if (m_error != error) {
m_error = error;
emit errorChanged(error);
}
}
void QnxAudioOutput::setState(QAudio::State state)
{
if (m_state != state) {
m_state = state;
emit stateChanged(state);
}
}
qint64 QnxAudioOutput::write(const char *data, qint64 len)
{
if (!m_pcmHandle)
return 0;
// Make sure we're writing (N * frame) worth of bytes
const int size = m_format.bytesForFrames(qBound(qint64(0), qint64(bytesFree()), len) / m_format.bytesPerFrame());
if (size == 0)
return 0;
int written = 0;
if (m_volume < 1.0f) {
char out[size];
QAudioHelperInternal::qMultiplySamples(m_volume, m_format, data, out, size);
written = snd_pcm_plugin_write(m_pcmHandle, out, size);
} else {
written = snd_pcm_plugin_write(m_pcmHandle, data, size);
}
if (written > 0) {
m_bytesWritten += written;
setError(QAudio::NoError);
setState(QAudio::ActiveState);
return written;
} else {
close();
setError(QAudio::FatalError);
setState(QAudio::StoppedState);
return 0;
}
}
QnxPushIODevice::QnxPushIODevice(QnxAudioOutput *output)
: QIODevice(output),
m_output(output)
{
}
QnxPushIODevice::~QnxPushIODevice()
{
}
qint64 QnxPushIODevice::readData(char *data, qint64 len)
{
Q_UNUSED(data);
Q_UNUSED(len);
return 0;
}
qint64 QnxPushIODevice::writeData(const char *data, qint64 len)
{
int retry = 0;
qint64 written = 0;
if (m_output->state() == QAudio::ActiveState
|| m_output->state() == QAudio::IdleState) {
while (written < len) {
const int writeSize = m_output->write(data + written, len - written);
if (writeSize <= 0) {
retry++;
if (retry > 10)
return written;
else
continue;
}
retry = 0;
written += writeSize;
}
}
return written;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,131 @@
/****************************************************************************
**
** 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 QNXAUDIOOUTPUT_H
#define QNXAUDIOOUTPUT_H
#include "qaudiosystem.h"
#include <QTime>
#include <QTimer>
#include <sys/asoundlib.h>
QT_BEGIN_NAMESPACE
class QnxPushIODevice;
class QnxAudioOutput : public QAbstractAudioOutput
{
Q_OBJECT
public:
QnxAudioOutput();
~QnxAudioOutput();
void start(QIODevice *source) 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 bytesFree() const Q_DECL_OVERRIDE;
int periodSize() const Q_DECL_OVERRIDE;
void setBufferSize(int) Q_DECL_OVERRIDE {}
int bufferSize() const Q_DECL_OVERRIDE { return 0; }
void setNotifyInterval(int ms) 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 &format) Q_DECL_OVERRIDE;
QAudioFormat format() const Q_DECL_OVERRIDE;
void setVolume(qreal volume) Q_DECL_OVERRIDE;
qreal volume() const Q_DECL_OVERRIDE;
private slots:
void pullData();
private:
bool open();
void close();
void setError(QAudio::Error error);
void setState(QAudio::State state);
friend class QnxPushIODevice;
qint64 write(const char *data, qint64 len);
QIODevice *m_source;
bool m_pushSource;
QTimer m_timer;
int m_notifyInterval;
QAudio::Error m_error;
QAudio::State m_state;
QAudioFormat m_format;
qreal m_volume;
int m_periodSize;
snd_pcm_t *m_pcmHandle;
qint64 m_bytesWritten;
QTime m_startTimeStamp;
QTime m_intervalTimeStamp;
qint64 m_intervalOffset;
};
class QnxPushIODevice : public QIODevice
{
Q_OBJECT
public:
explicit QnxPushIODevice(QnxAudioOutput *output);
~QnxPushIODevice();
qint64 readData(char *data, qint64 len);
qint64 writeData(const char *data, qint64 len);
private:
QnxAudioOutput *m_output;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** 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 "qnxaudioplugin.h"
#include "qnxaudiodeviceinfo.h"
#include "qnxaudiooutput.h"
#include <sys/asoundlib.h>
static const char *OUTPUT_ID = "QnxAudioOutput";
QT_BEGIN_NAMESPACE
QnxAudioPlugin::QnxAudioPlugin(QObject *parent)
: QAudioSystemPlugin(parent)
{
}
QList<QByteArray> QnxAudioPlugin::availableDevices(QAudio::Mode mode) const
{
if (mode == QAudio::AudioOutput)
return QList<QByteArray>() << OUTPUT_ID;
else
return QList<QByteArray>();
}
QAbstractAudioInput *QnxAudioPlugin::createInput(const QByteArray &device)
{
Q_UNUSED(device);
return 0;
}
QAbstractAudioOutput *QnxAudioPlugin::createOutput(const QByteArray &device)
{
Q_ASSERT(device == OUTPUT_ID);
Q_UNUSED(device);
return new QnxAudioOutput();
}
QAbstractAudioDeviceInfo *QnxAudioPlugin::createDeviceInfo(const QByteArray &device, QAudio::Mode mode)
{
Q_ASSERT(device == OUTPUT_ID || device == INPUT_ID);
return new QnxAudioDeviceInfo(device, mode);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** 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 QNXAUDIOPLUGIN_H
#define QNXAUDIOPLUGIN_H
#include <qaudiosystemplugin.h>
QT_BEGIN_NAMESPACE
class QnxAudioPlugin : public QAudioSystemPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "qnx_audio.json")
public:
explicit QnxAudioPlugin(QObject *parent = 0);
~QnxAudioPlugin() {}
QList<QByteArray> availableDevices(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QAbstractAudioInput *createInput(const QByteArray &device) Q_DECL_OVERRIDE;
QAbstractAudioOutput *createOutput(const QByteArray &device) Q_DECL_OVERRIDE;
QAbstractAudioDeviceInfo *createDeviceInfo(const QByteArray &device, QAudio::Mode mode) Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,130 @@
/****************************************************************************
**
** 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 "qnxaudioutils.h"
QT_BEGIN_NAMESPACE
snd_pcm_channel_params_t QnxAudioUtils::formatToChannelParams(const QAudioFormat &format, QAudio::Mode mode, int fragmentSize)
{
snd_pcm_channel_params_t params;
memset(&params, 0, sizeof(params));
params.channel = (mode == QAudio::AudioOutput) ? SND_PCM_CHANNEL_PLAYBACK : SND_PCM_CHANNEL_CAPTURE;
params.mode = SND_PCM_MODE_BLOCK;
params.start_mode = SND_PCM_START_DATA;
params.stop_mode = SND_PCM_STOP_ROLLOVER;
params.buf.block.frag_size = fragmentSize;
params.buf.block.frags_min = 1;
params.buf.block.frags_max = 1;
strcpy(params.sw_mixer_subchn_name, "QAudio Channel");
params.format.interleave = 1;
params.format.rate = format.sampleRate();
params.format.voices = format.channelCount();
switch (format.sampleSize()) {
case 8:
switch (format.sampleType()) {
case QAudioFormat::SignedInt:
params.format.format = SND_PCM_SFMT_S8;
break;
case QAudioFormat::UnSignedInt:
params.format.format = SND_PCM_SFMT_U8;
break;
default:
break;
}
break;
case 16:
switch (format.sampleType()) {
case QAudioFormat::SignedInt:
if (format.byteOrder() == QAudioFormat::LittleEndian) {
params.format.format = SND_PCM_SFMT_S16_LE;
} else {
params.format.format = SND_PCM_SFMT_S16_BE;
}
break;
case QAudioFormat::UnSignedInt:
if (format.byteOrder() == QAudioFormat::LittleEndian) {
params.format.format = SND_PCM_SFMT_U16_LE;
} else {
params.format.format = SND_PCM_SFMT_U16_BE;
}
break;
default:
break;
}
break;
case 32:
switch (format.sampleType()) {
case QAudioFormat::SignedInt:
if (format.byteOrder() == QAudioFormat::LittleEndian) {
params.format.format = SND_PCM_SFMT_S32_LE;
} else {
params.format.format = SND_PCM_SFMT_S32_BE;
}
break;
case QAudioFormat::UnSignedInt:
if (format.byteOrder() == QAudioFormat::LittleEndian) {
params.format.format = SND_PCM_SFMT_U32_LE;
} else {
params.format.format = SND_PCM_SFMT_U32_BE;
}
break;
case QAudioFormat::Float:
if (format.byteOrder() == QAudioFormat::LittleEndian) {
params.format.format = SND_PCM_SFMT_FLOAT_LE;
} else {
params.format.format = SND_PCM_SFMT_FLOAT_BE;
}
break;
default:
break;
}
break;
}
return params;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** 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 QNXAUDIOUTILS_H
#define QNXAUDIOUTILS_H
#include "qaudiosystem.h"
#include <sys/asoundlib.h>
QT_BEGIN_NAMESPACE
namespace QnxAudioUtils
{
snd_pcm_channel_params_t formatToChannelParams(const QAudioFormat &format, QAudio::Mode mode, int fragmentSize);
}
QT_END_NAMESPACE
#endif

3
src/plugins/qnx/qnx.pro Normal file
View File

@@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = audio