diff options
Diffstat (limited to 'src/plugins/qnx-audio/audio')
-rw-r--r-- | src/plugins/qnx-audio/audio/qnxaudiodeviceinfo.h | 18 | ||||
-rw-r--r-- | src/plugins/qnx-audio/audio/qnxaudioinput.h | 44 | ||||
-rw-r--r-- | src/plugins/qnx-audio/audio/qnxaudiooutput.cpp | 162 | ||||
-rw-r--r-- | src/plugins/qnx-audio/audio/qnxaudiooutput.h | 60 | ||||
-rw-r--r-- | src/plugins/qnx-audio/audio/qnxaudioplugin.h | 10 |
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(¶ms); if ((errorCode = snd_pcm_plugin_params(m_pcmHandle, ¶ms)) < 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 |