summaryrefslogtreecommitdiffstats
path: root/src/plugins/qnx-audio/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qnx-audio/audio')
-rw-r--r--src/plugins/qnx-audio/audio/qnxaudiodeviceinfo.h18
-rw-r--r--src/plugins/qnx-audio/audio/qnxaudioinput.h44
-rw-r--r--src/plugins/qnx-audio/audio/qnxaudiooutput.cpp162
-rw-r--r--src/plugins/qnx-audio/audio/qnxaudiooutput.h60
-rw-r--r--src/plugins/qnx-audio/audio/qnxaudioplugin.h10
5 files changed, 219 insertions, 75 deletions
diff --git a/src/plugins/qnx-audio/audio/qnxaudiodeviceinfo.h b/src/plugins/qnx-audio/audio/qnxaudiodeviceinfo.h
index 432c22163..cb620be3b 100644
--- a/src/plugins/qnx-audio/audio/qnxaudiodeviceinfo.h
+++ b/src/plugins/qnx-audio/audio/qnxaudiodeviceinfo.h
@@ -52,15 +52,15 @@ 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;
+ QAudioFormat preferredFormat() const override;
+ bool isFormatSupported(const QAudioFormat &format) const override;
+ QString deviceName() const override;
+ QStringList supportedCodecs() override;
+ QList<int> supportedSampleRates() override;
+ QList<int> supportedChannelCounts() override;
+ QList<int> supportedSampleSizes() override;
+ QList<QAudioFormat::Endian> supportedByteOrders() override;
+ QList<QAudioFormat::SampleType> supportedSampleTypes() override;
private:
const QString m_name;
diff --git a/src/plugins/qnx-audio/audio/qnxaudioinput.h b/src/plugins/qnx-audio/audio/qnxaudioinput.h
index 4c6bb2676..c677b6c96 100644
--- a/src/plugins/qnx-audio/audio/qnxaudioinput.h
+++ b/src/plugins/qnx-audio/audio/qnxaudioinput.h
@@ -59,26 +59,26 @@ 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;
+ void start(QIODevice*) override;
+ QIODevice* start() override;
+ void stop() override;
+ void reset() override;
+ void suspend() override;
+ void resume() override;
+ int bytesReady() const override;
+ int periodSize() const override;
+ void setBufferSize(int ) override;
+ int bufferSize() const override;
+ void setNotifyInterval(int ) override;
+ int notifyInterval() const override;
+ qint64 processedUSecs() const override;
+ qint64 elapsedUSecs() const override;
+ QAudio::Error error() const override;
+ QAudio::State state() const override;
+ void setFormat(const QAudioFormat&) override;
+ QAudioFormat format() const override;
+ void setVolume(qreal) override;
+ qreal volume() const override;
private slots:
void userFeed();
@@ -124,8 +124,8 @@ class InputPrivate : public QIODevice
public:
InputPrivate(QnxAudioInput *audio);
- qint64 readData(char *data, qint64 len) Q_DECL_OVERRIDE;
- qint64 writeData(const char *data, qint64 len) Q_DECL_OVERRIDE;
+ qint64 readData(char *data, qint64 len) override;
+ qint64 writeData(const char *data, qint64 len) override;
void trigger();
diff --git a/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp b/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp
index d08d01e6d..c4c09f543 100644
--- a/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp
+++ b/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp
@@ -43,19 +43,24 @@
#include <private/qaudiohelpers_p.h>
+#pragma GCC diagnostic ignored "-Wvla"
+
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_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)
+#if _NTO_VERSION >= 700
+ , m_pcmNotifier(0)
+#endif
{
m_timer.setSingleShot(false);
m_timer.setInterval(20);
@@ -124,20 +129,16 @@ void QnxAudioOutput::reset()
void QnxAudioOutput::suspend()
{
- m_timer.stop();
snd_pcm_playback_pause(m_pcmHandle);
- setState(QAudio::SuspendedState);
+ if (state() != QAudio::InterruptedState)
+ suspendInternal(QAudio::SuspendedState);
}
void QnxAudioOutput::resume()
{
snd_pcm_playback_resume(m_pcmHandle);
- if (m_pushSource)
- setState(QAudio::IdleState);
- else {
- setState(QAudio::ActiveState);
- m_timer.start();
- }
+ if (state() != QAudio::InterruptedState)
+ resumeInternal();
}
int QnxAudioOutput::bytesFree() const
@@ -146,6 +147,7 @@ int QnxAudioOutput::bytesFree() const
return 0;
snd_pcm_channel_status_t status;
+ memset(&status, 0, sizeof(status));
status.channel = SND_PCM_CHANNEL_PLAYBACK;
const int errorCode = snd_pcm_plugin_status(m_pcmHandle, &status);
@@ -214,9 +216,21 @@ qreal QnxAudioOutput::volume() const
return m_volume;
}
+void QnxAudioOutput::setCategory(const QString &category)
+{
+ m_category = category;
+}
+
+QString QnxAudioOutput::category() const
+{
+ return m_category;
+}
+
void QnxAudioOutput::pullData()
{
- if (m_state == QAudio::StoppedState || m_state == QAudio::SuspendedState)
+ if (m_state == QAudio::StoppedState
+ || m_state == QAudio::SuspendedState
+ || m_state == QAudio::InterruptedState)
return;
const int bytesAvailable = bytesFree();
@@ -290,6 +304,8 @@ bool QnxAudioOutput::open()
return false;
}
+ addPcmEventFilter();
+
// Necessary so that bytesFree() which uses the "free" member of the status struct works
snd_pcm_plugin_set_disable(m_pcmHandle, PLUGIN_MMAP);
@@ -303,6 +319,7 @@ bool QnxAudioOutput::open()
}
snd_pcm_channel_params_t params = QnxAudioUtils::formatToChannelParams(m_format, QAudio::AudioOutput, info.max_fragment_size);
+ setTypeName(&params);
if ((errorCode = snd_pcm_plugin_params(m_pcmHandle, &params)) < 0) {
qWarning("QnxAudioOutput: open error, couldn't set channel params (0x%x)", -errorCode);
@@ -331,6 +348,8 @@ bool QnxAudioOutput::open()
m_intervalOffset = 0;
m_bytesWritten = 0;
+ createPcmNotifiers();
+
return true;
}
@@ -338,6 +357,8 @@ void QnxAudioOutput::close()
{
m_timer.stop();
+ destroyPcmNotifiers();
+
if (m_pcmHandle) {
snd_pcm_plugin_flush(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
snd_pcm_close(m_pcmHandle);
@@ -400,6 +421,109 @@ qint64 QnxAudioOutput::write(const char *data, qint64 len)
}
}
+void QnxAudioOutput::suspendInternal(QAudio::State suspendState)
+{
+ m_timer.stop();
+ setState(suspendState);
+}
+
+void QnxAudioOutput::resumeInternal()
+{
+ if (m_pushSource) {
+ setState(QAudio::IdleState);
+ } else {
+ setState(QAudio::ActiveState);
+ m_timer.start();
+ }
+}
+
+#if _NTO_VERSION >= 700
+
+QAudio::State suspendState(const snd_pcm_event_t &event)
+{
+ Q_ASSERT(event.type == SND_PCM_EVENT_AUDIOMGMT_STATUS);
+ Q_ASSERT(event.data.audiomgmt_status.new_status == SND_PCM_STATUS_SUSPENDED);
+ return event.data.audiomgmt_status.flags & SND_PCM_STATUS_EVENT_HARD_SUSPEND
+ ? QAudio::InterruptedState : QAudio::SuspendedState;
+}
+
+void QnxAudioOutput::addPcmEventFilter()
+{
+ /* Enable PCM events */
+ snd_pcm_filter_t filter;
+ memset(&filter, 0, sizeof(filter));
+ filter.enable = (1<<SND_PCM_EVENT_AUDIOMGMT_STATUS) |
+ (1<<SND_PCM_EVENT_AUDIOMGMT_MUTE) |
+ (1<<SND_PCM_EVENT_OUTPUTCLASS);
+ snd_pcm_set_filter(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK, &filter);
+}
+
+void QnxAudioOutput::createPcmNotifiers()
+{
+ // QSocketNotifier::Read for poll based event dispatcher. Exception for
+ // select based event dispatcher.
+ m_pcmNotifier = new QSocketNotifier(snd_pcm_file_descriptor(m_pcmHandle,
+ SND_PCM_CHANNEL_PLAYBACK),
+ QSocketNotifier::Read, this);
+ connect(m_pcmNotifier, &QSocketNotifier::activated,
+ this, &QnxAudioOutput::pcmNotifierActivated);
+}
+
+void QnxAudioOutput::destroyPcmNotifiers()
+{
+ if (m_pcmNotifier) {
+ delete m_pcmNotifier;
+ m_pcmNotifier = 0;
+ }
+}
+
+void QnxAudioOutput::setTypeName(snd_pcm_channel_params_t *params)
+{
+ if (m_category.isEmpty())
+ return;
+
+ QByteArray latin1Category = m_category.toLatin1();
+
+ if (QString::fromLatin1(latin1Category) != m_category) {
+ qWarning("QnxAudioOutput: audio category name isn't a Latin1 string.");
+ return;
+ }
+
+ if (latin1Category.size() >= static_cast<int>(sizeof(params->audio_type_name))) {
+ qWarning("QnxAudioOutput: audio category name too long.");
+ return;
+ }
+
+ strcpy(params->audio_type_name, latin1Category.constData());
+}
+
+void QnxAudioOutput::pcmNotifierActivated(int socket)
+{
+ Q_UNUSED(socket);
+
+ snd_pcm_event_t pcm_event;
+ memset(&pcm_event, 0, sizeof(pcm_event));
+ while (snd_pcm_channel_read_event(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK, &pcm_event) == 0) {
+ if (pcm_event.type == SND_PCM_EVENT_AUDIOMGMT_STATUS) {
+ if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_SUSPENDED)
+ suspendInternal(suspendState(pcm_event));
+ else if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_RUNNING)
+ resumeInternal();
+ else if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_PAUSED)
+ suspendInternal(QAudio::SuspendedState);
+ }
+ }
+}
+
+#else
+
+void QnxAudioOutput::addPcmEventFilter() {}
+void QnxAudioOutput::createPcmNotifiers() {}
+void QnxAudioOutput::destroyPcmNotifiers() {}
+void QnxAudioOutput::setTypeName(snd_pcm_channel_params_t *) {}
+
+#endif
+
QnxPushIODevice::QnxPushIODevice(QnxAudioOutput *output)
: QIODevice(output),
m_output(output)
diff --git a/src/plugins/qnx-audio/audio/qnxaudiooutput.h b/src/plugins/qnx-audio/audio/qnxaudiooutput.h
index 5ee69b542..7a0979f77 100644
--- a/src/plugins/qnx-audio/audio/qnxaudiooutput.h
+++ b/src/plugins/qnx-audio/audio/qnxaudiooutput.h
@@ -45,8 +45,10 @@
#include <QTime>
#include <QTimer>
#include <QIODevice>
+#include <QSocketNotifier>
#include <sys/asoundlib.h>
+#include <sys/neutrino.h>
QT_BEGIN_NAMESPACE
@@ -60,26 +62,28 @@ 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;
+ void start(QIODevice *source) override;
+ QIODevice *start() override;
+ void stop() override;
+ void reset() override;
+ void suspend() override;
+ void resume() override;
+ int bytesFree() const override;
+ int periodSize() const override;
+ void setBufferSize(int) override {}
+ int bufferSize() const override { return 0; }
+ void setNotifyInterval(int ms) override;
+ int notifyInterval() const override;
+ qint64 processedUSecs() const override;
+ qint64 elapsedUSecs() const override;
+ QAudio::Error error() const override;
+ QAudio::State state() const override;
+ void setFormat(const QAudioFormat &format) override;
+ QAudioFormat format() const override;
+ void setVolume(qreal volume) override;
+ qreal volume() const override;
+ void setCategory(const QString &category) override;
+ QString category() const override;
private slots:
void pullData();
@@ -90,6 +94,14 @@ private:
void setError(QAudio::Error error);
void setState(QAudio::State state);
+ void addPcmEventFilter();
+ void createPcmNotifiers();
+ void destroyPcmNotifiers();
+ void setTypeName(snd_pcm_channel_params_t *params);
+
+ void suspendInternal(QAudio::State suspendState);
+ void resumeInternal();
+
friend class QnxPushIODevice;
qint64 write(const char *data, qint64 len);
@@ -102,6 +114,7 @@ private:
QAudio::State m_state;
QAudioFormat m_format;
qreal m_volume;
+ QString m_category;
int m_periodSize;
snd_pcm_t *m_pcmHandle;
@@ -109,6 +122,13 @@ private:
QTime m_startTimeStamp;
QTime m_intervalTimeStamp;
qint64 m_intervalOffset;
+
+#if _NTO_VERSION >= 700
+ QSocketNotifier *m_pcmNotifier;
+
+private slots:
+ void pcmNotifierActivated(int socket);
+#endif
};
class QnxPushIODevice : public QIODevice
diff --git a/src/plugins/qnx-audio/audio/qnxaudioplugin.h b/src/plugins/qnx-audio/audio/qnxaudioplugin.h
index 1d8b8a74b..d41f4020a 100644
--- a/src/plugins/qnx-audio/audio/qnxaudioplugin.h
+++ b/src/plugins/qnx-audio/audio/qnxaudioplugin.h
@@ -55,11 +55,11 @@ public:
explicit QnxAudioPlugin(QObject *parent = 0);
~QnxAudioPlugin() {}
- QByteArray defaultDevice(QAudio::Mode mode) const Q_DECL_OVERRIDE;
- 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;
+ QByteArray defaultDevice(QAudio::Mode mode) const override;
+ QList<QByteArray> availableDevices(QAudio::Mode mode) const override;
+ QAbstractAudioInput *createInput(const QByteArray &device) override;
+ QAbstractAudioOutput *createOutput(const QByteArray &device) override;
+ QAbstractAudioDeviceInfo *createDeviceInfo(const QByteArray &device, QAudio::Mode mode) override;
};
QT_END_NAMESPACE