diff options
Diffstat (limited to 'src/plugins/qnx')
80 files changed, 9400 insertions, 1536 deletions
diff --git a/src/plugins/qnx/audio/audio.pro b/src/plugins/qnx/audio/audio.pro deleted file mode 100644 index 35ddf73de..000000000 --- a/src/plugins/qnx/audio/audio.pro +++ /dev/null @@ -1,22 +0,0 @@ -TARGET = qtmedia_qnx_audio -QT += multimedia-private -CONFIG += no_private_qt_headers_warning - -PLUGIN_TYPE = audio -load(qt_plugin) - -LIBS += -lasound - -HEADERS += qnxaudioplugin.h \ - qnxaudiodeviceinfo.h \ - qnxaudioinput.h \ - qnxaudiooutput.h \ - qnxaudioutils.h - -SOURCES += qnxaudioplugin.cpp \ - qnxaudiodeviceinfo.cpp \ - qnxaudioinput.cpp \ - qnxaudiooutput.cpp \ - qnxaudioutils.cpp - -OTHER_FILES += qnx_audio.json diff --git a/src/plugins/qnx/audio/qnx_audio.json b/src/plugins/qnx/audio/qnx_audio.json deleted file mode 100644 index a31d52107..000000000 --- a/src/plugins/qnx/audio/qnx_audio.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Keys": ["default"] -} diff --git a/src/plugins/qnx/audio/qnxaudiodeviceinfo.cpp b/src/plugins/qnx/audio/qnxaudiodeviceinfo.cpp deleted file mode 100644 index ce8083573..000000000 --- a/src/plugins/qnx/audio/qnxaudiodeviceinfo.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** 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, ¶ms); - 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 diff --git a/src/plugins/qnx/audio/qnxaudioinput.cpp b/src/plugins/qnx/audio/qnxaudioinput.cpp deleted file mode 100644 index eb8064598..000000000 --- a/src/plugins/qnx/audio/qnxaudioinput.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/**************************************************************************** -** -** 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 diff --git a/src/plugins/qnx/audio/qnxaudioinput.h b/src/plugins/qnx/audio/qnxaudioinput.h deleted file mode 100644 index 3084b1de3..000000000 --- a/src/plugins/qnx/audio/qnxaudioinput.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** 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 diff --git a/src/plugins/qnx/audio/qnxaudiooutput.cpp b/src/plugins/qnx/audio/qnxaudiooutput.cpp deleted file mode 100644 index 4a82e93bb..000000000 --- a/src/plugins/qnx/audio/qnxaudiooutput.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/**************************************************************************** -** -** 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, ¶ms)) < 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 diff --git a/src/plugins/qnx/audio/qnxaudiooutput.h b/src/plugins/qnx/audio/qnxaudiooutput.h deleted file mode 100644 index 77c15e47a..000000000 --- a/src/plugins/qnx/audio/qnxaudiooutput.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** 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 diff --git a/src/plugins/qnx/audio/qnxaudioutils.cpp b/src/plugins/qnx/audio/qnxaudioutils.cpp deleted file mode 100644 index d6400c2b1..000000000 --- a/src/plugins/qnx/audio/qnxaudioutils.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** 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(¶ms, 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 diff --git a/src/plugins/qnx/bbserviceplugin.cpp b/src/plugins/qnx/bbserviceplugin.cpp new file mode 100644 index 000000000..59be46453 --- /dev/null +++ b/src/plugins/qnx/bbserviceplugin.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "bbserviceplugin.h" + +#include "bbcameraservice.h" +#include "bbvideodeviceselectorcontrol.h" +#include "mmrenderermediaplayerservice.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbServicePlugin::BbServicePlugin() +{ +} + +QMediaService *BbServicePlugin::create(const QString &key) +{ + if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)) + return new BbCameraService(); + + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) + return new MmRendererMediaPlayerService(); + + return 0; +} + +void BbServicePlugin::release(QMediaService *service) +{ + delete service; +} + +QMediaServiceProviderHint::Features BbServicePlugin::supportedFeatures(const QByteArray &service) const +{ + Q_UNUSED(service) + return QMediaServiceProviderHint::Features(); +} + +QList<QByteArray> BbServicePlugin::devices(const QByteArray &service) const +{ + if (service == Q_MEDIASERVICE_CAMERA) { + if (m_cameraDevices.isEmpty()) + updateDevices(); + + return m_cameraDevices; + } + + return QList<QByteArray>(); +} + +QString BbServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) +{ + if (service == Q_MEDIASERVICE_CAMERA) { + if (m_cameraDevices.isEmpty()) + updateDevices(); + + for (int i = 0; i < m_cameraDevices.count(); i++) + if (m_cameraDevices[i] == device) + return m_cameraDescriptions[i]; + } + + return QString(); +} + +void BbServicePlugin::updateDevices() const +{ + BbVideoDeviceSelectorControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions); + + if (m_cameraDevices.isEmpty()) { + qWarning() << "No camera devices found"; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/bbserviceplugin.h b/src/plugins/qnx/bbserviceplugin.h new file mode 100644 index 000000000..62fc4a0df --- /dev/null +++ b/src/plugins/qnx/bbserviceplugin.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 BBRSERVICEPLUGIN_H +#define BBRSERVICEPLUGIN_H + +#include <qmediaserviceproviderplugin.h> + +QT_BEGIN_NAMESPACE + +class BbServicePlugin + : public QMediaServiceProviderPlugin, + public QMediaServiceSupportedDevicesInterface, + public QMediaServiceFeaturesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedDevicesInterface) + Q_INTERFACES(QMediaServiceFeaturesInterface) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "blackberry_mediaservice.json") +public: + BbServicePlugin(); + + QMediaService *create(const QString &key) Q_DECL_OVERRIDE; + void release(QMediaService *service) Q_DECL_OVERRIDE; + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE; + + QList<QByteArray> devices(const QByteArray &service) const Q_DECL_OVERRIDE; + QString deviceDescription(const QByteArray &service, const QByteArray &device) Q_DECL_OVERRIDE; + QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property) Q_DECL_OVERRIDE; + +private: + void updateDevices() const; + + mutable QList<QByteArray> m_cameraDevices; + mutable QStringList m_cameraDescriptions; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/blackberry_mediaservice.json b/src/plugins/qnx/blackberry_mediaservice.json new file mode 100644 index 000000000..2a59cc770 --- /dev/null +++ b/src/plugins/qnx/blackberry_mediaservice.json @@ -0,0 +1,4 @@ +{ + "Keys": ["blackberrymultimedia"], + "Services": ["org.qt-project.qt.camera", "org.qt-project.qt.mediaplayer"] +} diff --git a/src/plugins/qnx/camera/bbcameraaudioencodersettingscontrol.cpp b/src/plugins/qnx/camera/bbcameraaudioencodersettingscontrol.cpp new file mode 100644 index 000000000..2ff800a0f --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraaudioencodersettingscontrol.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 "bbcameraaudioencodersettingscontrol.h" + +#include "bbcamerasession.h" + +QT_BEGIN_NAMESPACE + +BbCameraAudioEncoderSettingsControl::BbCameraAudioEncoderSettingsControl(BbCameraSession *session, QObject *parent) + : QAudioEncoderSettingsControl(parent) + , m_session(session) +{ +} + +QStringList BbCameraAudioEncoderSettingsControl::supportedAudioCodecs() const +{ + return QStringList() << QLatin1String("none") << QLatin1String("aac") << QLatin1String("raw"); +} + +QString BbCameraAudioEncoderSettingsControl::codecDescription(const QString &codecName) const +{ + if (codecName == QLatin1String("none")) + return tr("No compression"); + else if (codecName == QLatin1String("aac")) + return tr("AAC compression"); + else if (codecName == QLatin1String("raw")) + return tr("PCM uncompressed"); + + return QString(); +} + +QList<int> BbCameraAudioEncoderSettingsControl::supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const +{ + Q_UNUSED(settings); + Q_UNUSED(continuous); + + // no API provided by BB10 yet + return QList<int>(); +} + +QAudioEncoderSettings BbCameraAudioEncoderSettingsControl::audioSettings() const +{ + return m_session->audioSettings(); +} + +void BbCameraAudioEncoderSettingsControl::setAudioSettings(const QAudioEncoderSettings &settings) +{ + m_session->setAudioSettings(settings); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/audio/qnxaudiodeviceinfo.h b/src/plugins/qnx/camera/bbcameraaudioencodersettingscontrol.h index 72c10cc75..21fb520e7 100644 --- a/src/plugins/qnx/audio/qnxaudiodeviceinfo.h +++ b/src/plugins/qnx/camera/bbcameraaudioencodersettingscontrol.h @@ -38,35 +38,29 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef BBCAMERAAUDIOENCODERSETTINGSCONTROL_H +#define BBCAMERAAUDIOENCODERSETTINGSCONTROL_H -#ifndef QNXAUDIODEVICEINFO_H -#define QNXAUDIODEVICEINFO_H - -#include "qaudiosystem.h" +#include <qaudioencodersettingscontrol.h> QT_BEGIN_NAMESPACE -class QnxAudioDeviceInfo : public QAbstractAudioDeviceInfo +class BbCameraSession; + +class BbCameraAudioEncoderSettingsControl : public QAudioEncoderSettingsControl { Q_OBJECT - public: - QnxAudioDeviceInfo(const QString &deviceName, QAudio::Mode mode); - ~QnxAudioDeviceInfo(); + explicit BbCameraAudioEncoderSettingsControl(BbCameraSession *session, QObject *parent = 0); - 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; + QStringList supportedAudioCodecs() const Q_DECL_OVERRIDE; + QString codecDescription(const QString &codecName) const Q_DECL_OVERRIDE; + QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QAudioEncoderSettings audioSettings() const Q_DECL_OVERRIDE; + void setAudioSettings(const QAudioEncoderSettings &settings) Q_DECL_OVERRIDE; private: - const QString m_name; - const QAudio::Mode m_mode; + BbCameraSession *m_session; }; QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameracapturebufferformatcontrol.cpp b/src/plugins/qnx/camera/bbcameracapturebufferformatcontrol.cpp new file mode 100644 index 000000000..57f3c9fb1 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameracapturebufferformatcontrol.cpp @@ -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$ +** +****************************************************************************/ +#include "bbcameracapturebufferformatcontrol.h" + +QT_BEGIN_NAMESPACE + +BbCameraCaptureBufferFormatControl::BbCameraCaptureBufferFormatControl(QObject *parent) + : QCameraCaptureBufferFormatControl(parent) +{ +} + +QList<QVideoFrame::PixelFormat> BbCameraCaptureBufferFormatControl::supportedBufferFormats() const +{ + return (QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_Jpeg); +} + +QVideoFrame::PixelFormat BbCameraCaptureBufferFormatControl::bufferFormat() const +{ + return QVideoFrame::Format_Jpeg; +} + +void BbCameraCaptureBufferFormatControl::setBufferFormat(QVideoFrame::PixelFormat format) +{ + Q_UNUSED(format) + // Do nothing, we support only Jpeg for now +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameracapturebufferformatcontrol.h b/src/plugins/qnx/camera/bbcameracapturebufferformatcontrol.h new file mode 100644 index 000000000..2897cb2fd --- /dev/null +++ b/src/plugins/qnx/camera/bbcameracapturebufferformatcontrol.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 BBCAMERACAPTUREBUFFERFORMATCONTROL_H +#define BBCAMERACAPTUREBUFFERFORMATCONTROL_H + +#include <qcameracapturebufferformatcontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraCaptureBufferFormatControl : public QCameraCaptureBufferFormatControl +{ + Q_OBJECT +public: + explicit BbCameraCaptureBufferFormatControl(QObject *parent = 0); + + QList<QVideoFrame::PixelFormat> supportedBufferFormats() const Q_DECL_OVERRIDE; + QVideoFrame::PixelFormat bufferFormat() const Q_DECL_OVERRIDE; + void setBufferFormat(QVideoFrame::PixelFormat format) Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameracapturedestinationcontrol.cpp b/src/plugins/qnx/camera/bbcameracapturedestinationcontrol.cpp new file mode 100644 index 000000000..6b6bcfcb9 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameracapturedestinationcontrol.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 "bbcameracapturedestinationcontrol.h" + +#include "bbcamerasession.h" + +QT_BEGIN_NAMESPACE + +BbCameraCaptureDestinationControl::BbCameraCaptureDestinationControl(BbCameraSession *session, QObject *parent) + : QCameraCaptureDestinationControl(parent) + , m_session(session) +{ + connect(m_session, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)), + this, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations))); +} + +bool BbCameraCaptureDestinationControl::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const +{ + return m_session->isCaptureDestinationSupported(destination); +} + +QCameraImageCapture::CaptureDestinations BbCameraCaptureDestinationControl::captureDestination() const +{ + return m_session->captureDestination();; +} + +void BbCameraCaptureDestinationControl::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) +{ + m_session->setCaptureDestination(destination); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameracapturedestinationcontrol.h b/src/plugins/qnx/camera/bbcameracapturedestinationcontrol.h new file mode 100644 index 000000000..93a7d2d14 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameracapturedestinationcontrol.h @@ -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 BBCAMERACAPTUREDESTINATIONCONTROL_H +#define BBCAMERACAPTUREDESTINATIONCONTROL_H + +#include <qcameracapturedestinationcontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraCaptureDestinationControl : public QCameraCaptureDestinationControl +{ + Q_OBJECT +public: + explicit BbCameraCaptureDestinationControl(BbCameraSession *session, QObject *parent = 0); + + bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const Q_DECL_OVERRIDE; + QCameraImageCapture::CaptureDestinations captureDestination() const Q_DECL_OVERRIDE; + void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameracontrol.cpp b/src/plugins/qnx/camera/bbcameracontrol.cpp new file mode 100644 index 000000000..bc3c78264 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameracontrol.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 "bbcameracontrol.h" + +#include "bbcamerasession.h" + +QT_BEGIN_NAMESPACE + +BbCameraControl::BbCameraControl(BbCameraSession *session, QObject *parent) + : QCameraControl(parent) + , m_session(session) +{ + connect(m_session, SIGNAL(statusChanged(QCamera::Status)), this, SIGNAL(statusChanged(QCamera::Status))); + connect(m_session, SIGNAL(stateChanged(QCamera::State)), this, SIGNAL(stateChanged(QCamera::State))); + connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); + connect(m_session, SIGNAL(captureModeChanged(QCamera::CaptureModes)), this, SIGNAL(captureModeChanged(QCamera::CaptureModes))); +} + +QCamera::State BbCameraControl::state() const +{ + return m_session->state(); +} + +void BbCameraControl::setState(QCamera::State state) +{ + m_session->setState(state); +} + +QCamera::CaptureModes BbCameraControl::captureMode() const +{ + return m_session->captureMode(); +} + +void BbCameraControl::setCaptureMode(QCamera::CaptureModes mode) +{ + m_session->setCaptureMode(mode); +} + +QCamera::Status BbCameraControl::status() const +{ + return m_session->status(); +} + +bool BbCameraControl::isCaptureModeSupported(QCamera::CaptureModes mode) const +{ + return m_session->isCaptureModeSupported(mode); +} + +bool BbCameraControl::canChangeProperty(PropertyChangeType /* changeType */, QCamera::Status /* status */) const +{ + return false; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameracontrol.h b/src/plugins/qnx/camera/bbcameracontrol.h new file mode 100644 index 000000000..a5792c5df --- /dev/null +++ b/src/plugins/qnx/camera/bbcameracontrol.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 BBCAMERACONTROL_H +#define BBCAMERACONTROL_H + +#include <qcameracontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraControl : public QCameraControl +{ + Q_OBJECT +public: + explicit BbCameraControl(BbCameraSession *session, QObject *parent = 0); + + QCamera::State state() const Q_DECL_OVERRIDE; + void setState(QCamera::State state) Q_DECL_OVERRIDE; + + QCamera::Status status() const Q_DECL_OVERRIDE; + + QCamera::CaptureModes captureMode() const Q_DECL_OVERRIDE; + void setCaptureMode(QCamera::CaptureModes) Q_DECL_OVERRIDE; + bool isCaptureModeSupported(QCamera::CaptureModes mode) const Q_DECL_OVERRIDE; + + bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameraexposurecontrol.cpp b/src/plugins/qnx/camera/bbcameraexposurecontrol.cpp new file mode 100644 index 000000000..b1d637cd0 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraexposurecontrol.cpp @@ -0,0 +1,236 @@ +/**************************************************************************** +** +** 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 "bbcameraexposurecontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbCameraExposureControl::BbCameraExposureControl(BbCameraSession *session, QObject *parent) + : QCameraExposureControl(parent) + , m_session(session) + , m_requestedExposureMode(QCameraExposure::ExposureAuto) +{ + connect(m_session, SIGNAL(statusChanged(QCamera::Status)), this, SLOT(statusChanged(QCamera::Status))); +} + +bool BbCameraExposureControl::isParameterSupported(ExposureParameter parameter) const +{ + switch (parameter) { + case QCameraExposureControl::ISO: + return false; + case QCameraExposureControl::Aperture: + return false; + case QCameraExposureControl::ShutterSpeed: + return false; + case QCameraExposureControl::ExposureCompensation: + return false; + case QCameraExposureControl::FlashPower: + return false; + case QCameraExposureControl::FlashCompensation: + return false; + case QCameraExposureControl::TorchPower: + return false; + case QCameraExposureControl::SpotMeteringPoint: + return false; + case QCameraExposureControl::ExposureMode: + return true; + case QCameraExposureControl::MeteringMode: + return false; + default: + return false; + } +} + +QVariantList BbCameraExposureControl::supportedParameterRange(ExposureParameter parameter, bool *continuous) const +{ + if (parameter != QCameraExposureControl::ExposureMode) // no other parameter supported by BB10 API at the moment + return QVariantList(); + + if (m_session->status() != QCamera::ActiveStatus) // we can query supported exposure modes only with active viewfinder + return QVariantList(); + + if (continuous) + *continuous = false; + + int supported = 0; + camera_scenemode_t modes[20]; + const camera_error_t result = camera_get_scene_modes(m_session->handle(), 20, &supported, modes); + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve supported scene modes:" << result; + return QVariantList(); + } + + QVariantList exposureModes; + for (int i = 0; i < supported; ++i) { + switch (modes[i]) { + case CAMERA_SCENE_AUTO: + exposureModes << QVariant::fromValue(QCameraExposure::ExposureAuto); + break; + case CAMERA_SCENE_SPORTS: + exposureModes << QVariant::fromValue(QCameraExposure::ExposureSports); + break; + case CAMERA_SCENE_CLOSEUP: + exposureModes << QVariant::fromValue(QCameraExposure::ExposurePortrait); + break; + case CAMERA_SCENE_ACTION: + exposureModes << QVariant::fromValue(QCameraExposure::ExposureSports); + break; + case CAMERA_SCENE_BEACHANDSNOW: + exposureModes << QVariant::fromValue(QCameraExposure::ExposureBeach) << QVariant::fromValue(QCameraExposure::ExposureSnow); + break; + case CAMERA_SCENE_NIGHT: + exposureModes << QVariant::fromValue(QCameraExposure::ExposureNight); + break; + default: break; + } + } + + return exposureModes; +} + +QVariant BbCameraExposureControl::requestedValue(ExposureParameter parameter) const +{ + if (parameter != QCameraExposureControl::ExposureMode) // no other parameter supported by BB10 API at the moment + return QVariant(); + + return QVariant::fromValue(m_requestedExposureMode); +} + +QVariant BbCameraExposureControl::actualValue(ExposureParameter parameter) const +{ +#ifndef Q_OS_BLACKBERRY_TABLET + if (parameter != QCameraExposureControl::ExposureMode) // no other parameter supported by BB10 API at the moment + return QVariantList(); + + if (m_session->status() != QCamera::ActiveStatus) // we can query actual scene modes only with active viewfinder + return QVariantList(); + + camera_scenemode_t sceneMode = CAMERA_SCENE_DEFAULT; + const camera_error_t result = camera_get_scene_mode(m_session->handle(), &sceneMode); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve scene mode:" << result; + return QVariant(); + } + + switch (sceneMode) { + case CAMERA_SCENE_AUTO: + return QVariant::fromValue(QCameraExposure::ExposureAuto); + case CAMERA_SCENE_SPORTS: + return QVariant::fromValue(QCameraExposure::ExposureSports); + case CAMERA_SCENE_CLOSEUP: + return QVariant::fromValue(QCameraExposure::ExposurePortrait); + case CAMERA_SCENE_ACTION: + return QVariant::fromValue(QCameraExposure::ExposureSports); + case CAMERA_SCENE_BEACHANDSNOW: + return (m_requestedExposureMode == QCameraExposure::ExposureBeach ? QVariant::fromValue(QCameraExposure::ExposureBeach) + : QVariant::fromValue(QCameraExposure::ExposureSnow)); + case CAMERA_SCENE_NIGHT: + return QVariant::fromValue(QCameraExposure::ExposureNight); + default: + return QVariant(); + } +#else + return QVariant(); +#endif +} + +bool BbCameraExposureControl::setValue(ExposureParameter parameter, const QVariant& value) +{ + if (parameter != QCameraExposureControl::ExposureMode) // no other parameter supported by BB10 API at the moment + return false; + + if (m_session->status() != QCamera::ActiveStatus) // we can set actual scene modes only with active viewfinder + return false; + + camera_scenemode_t sceneMode = CAMERA_SCENE_DEFAULT; + + if (value.isValid()) { + m_requestedExposureMode = value.value<QCameraExposure::ExposureMode>(); + emit requestedValueChanged(QCameraExposureControl::ExposureMode); + + switch (m_requestedExposureMode) { + case QCameraExposure::ExposureAuto: + sceneMode = CAMERA_SCENE_AUTO; + break; + case QCameraExposure::ExposureSports: + sceneMode = CAMERA_SCENE_SPORTS; + break; + case QCameraExposure::ExposurePortrait: + sceneMode = CAMERA_SCENE_CLOSEUP; + break; + case QCameraExposure::ExposureBeach: + sceneMode = CAMERA_SCENE_BEACHANDSNOW; + break; + case QCameraExposure::ExposureSnow: + sceneMode = CAMERA_SCENE_BEACHANDSNOW; + break; + case QCameraExposure::ExposureNight: + sceneMode = CAMERA_SCENE_NIGHT; + break; + default: + sceneMode = CAMERA_SCENE_DEFAULT; + break; + } + } + + const camera_error_t result = camera_set_scene_mode(m_session->handle(), sceneMode); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to set scene mode:" << result; + return false; + } + + emit actualValueChanged(QCameraExposureControl::ExposureMode); + + return true; +} + +void BbCameraExposureControl::statusChanged(QCamera::Status status) +{ + if (status == QCamera::ActiveStatus || status == QCamera::LoadedStatus) + emit parameterRangeChanged(QCameraExposureControl::ExposureMode); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameraexposurecontrol.h b/src/plugins/qnx/camera/bbcameraexposurecontrol.h new file mode 100644 index 000000000..f4659b624 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraexposurecontrol.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 BBCAMERAEXPOSURECONTROL_H +#define BBCAMERAEXPOSURECONTROL_H + +#include <qcameraexposurecontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraExposureControl : public QCameraExposureControl +{ + Q_OBJECT +public: + explicit BbCameraExposureControl(BbCameraSession *session, QObject *parent = 0); + + virtual bool isParameterSupported(ExposureParameter parameter) const Q_DECL_OVERRIDE; + virtual QVariantList supportedParameterRange(ExposureParameter parameter, bool *continuous) const Q_DECL_OVERRIDE; + + virtual QVariant requestedValue(ExposureParameter parameter) const Q_DECL_OVERRIDE; + virtual QVariant actualValue(ExposureParameter parameter) const Q_DECL_OVERRIDE; + virtual bool setValue(ExposureParameter parameter, const QVariant& value) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void statusChanged(QCamera::Status status); + +private: + BbCameraSession *m_session; + QCameraExposure::ExposureMode m_requestedExposureMode; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameraflashcontrol.cpp b/src/plugins/qnx/camera/bbcameraflashcontrol.cpp new file mode 100644 index 000000000..06ebe01f6 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraflashcontrol.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 "bbcameraflashcontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbCameraFlashControl::BbCameraFlashControl(BbCameraSession *session, QObject *parent) + : QCameraFlashControl(parent) + , m_session(session) + , m_flashMode(QCameraExposure::FlashAuto) +{ +} + +QCameraExposure::FlashModes BbCameraFlashControl::flashMode() const +{ + return m_flashMode; +} + +void BbCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode) +{ + if (m_flashMode == mode) + return; + + if (m_session->status() != QCamera::ActiveStatus) // can only be changed when viewfinder is active + return; + + if (m_flashMode == QCameraExposure::FlashVideoLight) { + const camera_error_t result = camera_config_videolight(m_session->handle(), CAMERA_VIDEOLIGHT_OFF); + if (result != CAMERA_EOK) + qWarning() << "Unable to switch off video light:" << result; + } + + m_flashMode = mode; + + if (m_flashMode == QCameraExposure::FlashVideoLight) { + const camera_error_t result = camera_config_videolight(m_session->handle(), CAMERA_VIDEOLIGHT_ON); + if (result != CAMERA_EOK) + qWarning() << "Unable to switch on video light:" << result; + } else { + camera_flashmode_t flashMode = CAMERA_FLASH_AUTO; + + if (m_flashMode.testFlag(QCameraExposure::FlashAuto)) flashMode = CAMERA_FLASH_AUTO; + else if (mode.testFlag(QCameraExposure::FlashOff)) flashMode = CAMERA_FLASH_OFF; + else if (mode.testFlag(QCameraExposure::FlashOn)) flashMode = CAMERA_FLASH_ON; + + const camera_error_t result = camera_config_flash(m_session->handle(), flashMode); + if (result != CAMERA_EOK) + qWarning() << "Unable to configure flash:" << result; + } +} + +bool BbCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const +{ + bool supportsVideoLight = false; + if (m_session->handle() != CAMERA_HANDLE_INVALID) { + supportsVideoLight = camera_has_feature(m_session->handle(), CAMERA_FEATURE_VIDEOLIGHT); + } + + return (mode == QCameraExposure::FlashOff || + mode == QCameraExposure::FlashOn || + mode == QCameraExposure::FlashAuto || + ((mode == QCameraExposure::FlashVideoLight) && supportsVideoLight)); +} + +bool BbCameraFlashControl::isFlashReady() const +{ + //TODO: check for flash charge-level here?!? + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/audio/qnxaudioplugin.h b/src/plugins/qnx/camera/bbcameraflashcontrol.h index 1886057b4..d46dc8c12 100644 --- a/src/plugins/qnx/audio/qnxaudioplugin.h +++ b/src/plugins/qnx/camera/bbcameraflashcontrol.h @@ -38,27 +38,29 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef BBCAMERAFLASHCONTROL_H +#define BBCAMERAFLASHCONTROL_H -#ifndef QNXAUDIOPLUGIN_H -#define QNXAUDIOPLUGIN_H - -#include <qaudiosystemplugin.h> +#include <qcameraflashcontrol.h> QT_BEGIN_NAMESPACE -class QnxAudioPlugin : public QAudioSystemPlugin +class BbCameraSession; + +class BbCameraFlashControl : public QCameraFlashControl { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "qnx_audio.json") - public: - explicit QnxAudioPlugin(QObject *parent = 0); - ~QnxAudioPlugin() {} + explicit BbCameraFlashControl(BbCameraSession *session, QObject *parent = 0); + + QCameraExposure::FlashModes flashMode() const Q_DECL_OVERRIDE; + void setFlashMode(QCameraExposure::FlashModes mode) Q_DECL_OVERRIDE; + bool isFlashModeSupported(QCameraExposure::FlashModes mode) const Q_DECL_OVERRIDE; + bool isFlashReady() 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; +private: + BbCameraSession *m_session; + QCameraExposure::FlashModes m_flashMode; }; QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcamerafocuscontrol.cpp b/src/plugins/qnx/camera/bbcamerafocuscontrol.cpp new file mode 100644 index 000000000..e0b57d6c6 --- /dev/null +++ b/src/plugins/qnx/camera/bbcamerafocuscontrol.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** +** +** 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 "bbcamerafocuscontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbCameraFocusControl::BbCameraFocusControl(BbCameraSession *session, QObject *parent) + : QCameraFocusControl(parent) + , m_session(session) + , m_focusMode(QCameraFocus::FocusModes()) + , m_focusPointMode(QCameraFocus::FocusPointAuto) + , m_customFocusPoint(QPointF(0, 0)) +{ +} + +QCameraFocus::FocusModes BbCameraFocusControl::focusMode() const +{ + camera_focusmode_t focusMode = CAMERA_FOCUSMODE_OFF; + + const camera_error_t result = camera_get_focus_mode(m_session->handle(), &focusMode); + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve focus mode from camera:" << result; + return QCameraFocus::FocusModes(); + } + + switch (focusMode) { + case CAMERA_FOCUSMODE_EDOF: + return QCameraFocus::HyperfocalFocus; + case CAMERA_FOCUSMODE_MANUAL: + return QCameraFocus::ManualFocus; + case CAMERA_FOCUSMODE_AUTO: + return QCameraFocus::AutoFocus; + case CAMERA_FOCUSMODE_MACRO: + return QCameraFocus::MacroFocus; + case CAMERA_FOCUSMODE_CONTINUOUS_AUTO: + return QCameraFocus::ContinuousFocus; + case CAMERA_FOCUSMODE_CONTINUOUS_MACRO: // fall through + case CAMERA_FOCUSMODE_OFF: // fall through + default: + return QCameraFocus::FocusModes(); + } +} + +void BbCameraFocusControl::setFocusMode(QCameraFocus::FocusModes mode) +{ + if (m_focusMode == mode) + return; + + camera_focusmode_t focusMode = CAMERA_FOCUSMODE_OFF; + + if (mode == QCameraFocus::HyperfocalFocus) + focusMode = CAMERA_FOCUSMODE_EDOF; + else if (mode == QCameraFocus::ManualFocus) + focusMode = CAMERA_FOCUSMODE_MANUAL; + else if (mode == QCameraFocus::AutoFocus) + focusMode = CAMERA_FOCUSMODE_AUTO; + else if (mode == QCameraFocus::MacroFocus) + focusMode = CAMERA_FOCUSMODE_MACRO; + else if (mode == QCameraFocus::ContinuousFocus) + focusMode = CAMERA_FOCUSMODE_CONTINUOUS_AUTO; + + const camera_error_t result = camera_set_focus_mode(m_session->handle(), focusMode); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to set focus mode:" << result; + return; + } + + m_focusMode = mode; + emit focusModeChanged(m_focusMode); +} + +bool BbCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusModes mode) const +{ + if (m_session->state() == QCamera::UnloadedState) + return false; + + if (mode == QCameraFocus::HyperfocalFocus) + return false; //TODO how to check? + else if (mode == QCameraFocus::ManualFocus) + return camera_has_feature(m_session->handle(), CAMERA_FEATURE_MANUALFOCUS); + else if (mode == QCameraFocus::AutoFocus) + return camera_has_feature(m_session->handle(), CAMERA_FEATURE_AUTOFOCUS); + else if (mode == QCameraFocus::MacroFocus) + return camera_has_feature(m_session->handle(), CAMERA_FEATURE_MACROFOCUS); + else if (mode == QCameraFocus::ContinuousFocus) + return camera_has_feature(m_session->handle(), CAMERA_FEATURE_AUTOFOCUS); + + return false; +} + +QCameraFocus::FocusPointMode BbCameraFocusControl::focusPointMode() const +{ + return m_focusPointMode; +} + +void BbCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode) +{ + if (m_session->status() != QCamera::ActiveStatus) + return; + + if (m_focusPointMode == mode) + return; + + m_focusPointMode = mode; + emit focusPointModeChanged(m_focusPointMode); + + if (m_focusPointMode == QCameraFocus::FocusPointAuto) { + //TODO: is this correct? + const camera_error_t result = camera_set_focus_regions(m_session->handle(), 0, 0); + if (result != CAMERA_EOK) { + qWarning() << "Unable to set focus region:" << result; + return; + } + + emit focusZonesChanged(); + } else if (m_focusPointMode == QCameraFocus::FocusPointCenter) { + // get the size of the viewfinder + int viewfinderWidth = 0; + int viewfinderHeight = 0; + + if (!retrieveViewfinderSize(&viewfinderWidth, &viewfinderHeight)) + return; + + // define a 40x40 pixel focus region in the center of the viewfinder + camera_region_t focusRegion; + focusRegion.left = (viewfinderWidth / 2) - 20; + focusRegion.top = (viewfinderHeight / 2) - 20; + focusRegion.width = 40; + focusRegion.height = 40; + + camera_error_t result = camera_set_focus_regions(m_session->handle(), 1, &focusRegion); + if (result != CAMERA_EOK) { + qWarning() << "Unable to set focus region:" << result; + return; + } + + // re-set focus mode to apply focus region changes + camera_focusmode_t focusMode = CAMERA_FOCUSMODE_OFF; + result = camera_get_focus_mode(m_session->handle(), &focusMode); + camera_set_focus_mode(m_session->handle(), focusMode); + + emit focusZonesChanged(); + + } else if (m_focusPointMode == QCameraFocus::FocusPointFaceDetection) { + //TODO: implement later + } else if (m_focusPointMode == QCameraFocus::FocusPointCustom) { + updateCustomFocusRegion(); + } +} + +bool BbCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const +{ + if (m_session->state() == QCamera::UnloadedState) + return false; + + if (mode == QCameraFocus::FocusPointAuto) { + return camera_has_feature(m_session->handle(), CAMERA_FEATURE_AUTOFOCUS); + } else if (mode == QCameraFocus::FocusPointCenter) { + return camera_has_feature(m_session->handle(), CAMERA_FEATURE_REGIONFOCUS); + } else if (mode == QCameraFocus::FocusPointFaceDetection) { + return false; //TODO: implement via custom region in combination with face detection in viewfinder + } else if (mode == QCameraFocus::FocusPointCustom) { + return camera_has_feature(m_session->handle(), CAMERA_FEATURE_REGIONFOCUS); + } + + return false; +} + +QPointF BbCameraFocusControl::customFocusPoint() const +{ + return m_customFocusPoint; +} + +void BbCameraFocusControl::setCustomFocusPoint(const QPointF &point) +{ + if (m_customFocusPoint == point) + return; + + m_customFocusPoint = point; + emit customFocusPointChanged(m_customFocusPoint); + + updateCustomFocusRegion(); +} + +QCameraFocusZoneList BbCameraFocusControl::focusZones() const +{ + if (m_session->state() == QCamera::UnloadedState) + return QCameraFocusZoneList(); + + camera_region_t regions[20]; + int supported = 0; + int asked = 0; + camera_error_t result = camera_get_focus_regions(m_session->handle(), 20, &supported, &asked, regions); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve focus regions:" << result; + return QCameraFocusZoneList(); + } + + // retrieve width and height of viewfinder + int viewfinderWidth = 0; + int viewfinderHeight = 0; + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_get_photovf_property(m_session->handle(), + CAMERA_IMGPROP_WIDTH, &viewfinderWidth, + CAMERA_IMGPROP_HEIGHT, &viewfinderHeight); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_get_videovf_property(m_session->handle(), + CAMERA_IMGPROP_WIDTH, &viewfinderWidth, + CAMERA_IMGPROP_HEIGHT, &viewfinderHeight); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve viewfinder size:" << result; + return QCameraFocusZoneList(); + } + + QCameraFocusZoneList list; + for (int i = 0; i < asked; ++i) { + const int x = regions[i].left; + const int y = regions[i].top; + const int width = regions[i].width; + const int height = regions[i].height; + + QRectF rect(static_cast<float>(x)/static_cast<float>(viewfinderWidth), + static_cast<float>(y)/static_cast<float>(viewfinderHeight), + static_cast<float>(width)/static_cast<float>(viewfinderWidth), + static_cast<float>(height)/static_cast<float>(viewfinderHeight)); + + list << QCameraFocusZone(rect, QCameraFocusZone::Focused); //TODO: how to know if a zone is unused/selected/focused?!? + } + + return list; +} + +void BbCameraFocusControl::updateCustomFocusRegion() +{ + // get the size of the viewfinder + int viewfinderWidth = 0; + int viewfinderHeight = 0; + + if (!retrieveViewfinderSize(&viewfinderWidth, &viewfinderHeight)) + return; + + // define a 40x40 pixel focus region around the custom focus point + camera_region_t focusRegion; + focusRegion.left = qMax(0, static_cast<int>(m_customFocusPoint.x() * viewfinderWidth) - 20); + focusRegion.top = qMax(0, static_cast<int>(m_customFocusPoint.y() * viewfinderHeight) - 20); + focusRegion.width = 40; + focusRegion.height = 40; + + camera_error_t result = camera_set_focus_regions(m_session->handle(), 1, &focusRegion); + if (result != CAMERA_EOK) { + qWarning() << "Unable to set focus region:" << result; + return; + } + + // re-set focus mode to apply focus region changes + camera_focusmode_t focusMode = CAMERA_FOCUSMODE_OFF; + result = camera_get_focus_mode(m_session->handle(), &focusMode); + camera_set_focus_mode(m_session->handle(), focusMode); + + emit focusZonesChanged(); +} + +bool BbCameraFocusControl::retrieveViewfinderSize(int *width, int *height) +{ + if (!width || !height) + return false; + + camera_error_t result = CAMERA_EOK; + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_get_photovf_property(m_session->handle(), + CAMERA_IMGPROP_WIDTH, width, + CAMERA_IMGPROP_HEIGHT, height); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_get_videovf_property(m_session->handle(), + CAMERA_IMGPROP_WIDTH, width, + CAMERA_IMGPROP_HEIGHT, height); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve viewfinder size:" << result; + return false; + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcamerafocuscontrol.h b/src/plugins/qnx/camera/bbcamerafocuscontrol.h new file mode 100644 index 000000000..052c29b4b --- /dev/null +++ b/src/plugins/qnx/camera/bbcamerafocuscontrol.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 BBCAMERAFOCUSCONTROL_H +#define BBCAMERAFOCUSCONTROL_H + +#include <qcamerafocuscontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraFocusControl : public QCameraFocusControl +{ + Q_OBJECT +public: + explicit BbCameraFocusControl(BbCameraSession *session, QObject *parent = 0); + + QCameraFocus::FocusModes focusMode() const Q_DECL_OVERRIDE; + void setFocusMode(QCameraFocus::FocusModes mode) Q_DECL_OVERRIDE; + bool isFocusModeSupported(QCameraFocus::FocusModes mode) const Q_DECL_OVERRIDE; + QCameraFocus::FocusPointMode focusPointMode() const Q_DECL_OVERRIDE; + void setFocusPointMode(QCameraFocus::FocusPointMode mode) Q_DECL_OVERRIDE; + bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const Q_DECL_OVERRIDE; + QPointF customFocusPoint() const Q_DECL_OVERRIDE; + void setCustomFocusPoint(const QPointF &point) Q_DECL_OVERRIDE; + QCameraFocusZoneList focusZones() const Q_DECL_OVERRIDE; + +private: + void updateCustomFocusRegion(); + bool retrieveViewfinderSize(int *width, int *height); + + BbCameraSession *m_session; + + QCameraFocus::FocusModes m_focusMode; + QCameraFocus::FocusPointMode m_focusPointMode; + QPointF m_customFocusPoint; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameraimagecapturecontrol.cpp b/src/plugins/qnx/camera/bbcameraimagecapturecontrol.cpp new file mode 100644 index 000000000..a2f61f73d --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraimagecapturecontrol.cpp @@ -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 "bbcameraimagecapturecontrol.h" + +#include "bbcamerasession.h" + +QT_BEGIN_NAMESPACE + +BbCameraImageCaptureControl::BbCameraImageCaptureControl(BbCameraSession *session, QObject *parent) + : QCameraImageCaptureControl(parent) + , m_session(session) +{ + connect(m_session, SIGNAL(readyForCaptureChanged(bool)), this, SIGNAL(readyForCaptureChanged(bool))); + connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int))); + connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage))); + connect(m_session, SIGNAL(imageMetadataAvailable(int,QString,QVariant)), this, SIGNAL(imageMetadataAvailable(int,QString,QVariant))); + connect(m_session, SIGNAL(imageAvailable(int,QVideoFrame)), this, SIGNAL(imageAvailable(int,QVideoFrame))); + connect(m_session, SIGNAL(imageSaved(int,QString)), this, SIGNAL(imageSaved(int,QString))); + connect(m_session, SIGNAL(imageCaptureError(int,int,QString)), this, SIGNAL(error(int,int,QString))); +} + +bool BbCameraImageCaptureControl::isReadyForCapture() const +{ + return m_session->isReadyForCapture(); +} + +QCameraImageCapture::DriveMode BbCameraImageCaptureControl::driveMode() const +{ + return m_session->driveMode(); +} + +void BbCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode) +{ + m_session->setDriveMode(mode); +} + +int BbCameraImageCaptureControl::capture(const QString &fileName) +{ + return m_session->capture(fileName); +} + +void BbCameraImageCaptureControl::cancelCapture() +{ + m_session->cancelCapture(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameraimagecapturecontrol.h b/src/plugins/qnx/camera/bbcameraimagecapturecontrol.h new file mode 100644 index 000000000..a73a4f1d5 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraimagecapturecontrol.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 BBCAMERAIMAGECAPTURECONTROL_H +#define BBCAMERAIMAGECAPTURECONTROL_H + +#include <qcameraimagecapturecontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraImageCaptureControl : public QCameraImageCaptureControl +{ + Q_OBJECT +public: + explicit BbCameraImageCaptureControl(BbCameraSession *session, QObject *parent = 0); + + bool isReadyForCapture() const Q_DECL_OVERRIDE; + + QCameraImageCapture::DriveMode driveMode() const Q_DECL_OVERRIDE; + void setDriveMode(QCameraImageCapture::DriveMode mode) Q_DECL_OVERRIDE; + + int capture(const QString &fileName) Q_DECL_OVERRIDE; + void cancelCapture() Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameraimageprocessingcontrol.cpp b/src/plugins/qnx/camera/bbcameraimageprocessingcontrol.cpp new file mode 100644 index 000000000..54ae48c6b --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraimageprocessingcontrol.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** 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 "bbcameraimageprocessingcontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbCameraImageProcessingControl::BbCameraImageProcessingControl(BbCameraSession *session, QObject *parent) + : QCameraImageProcessingControl(parent) + , m_session(session) +{ +} + +bool BbCameraImageProcessingControl::isParameterSupported(ProcessingParameter parameter) const +{ + return (parameter == QCameraImageProcessingControl::WhiteBalancePreset); +} + +bool BbCameraImageProcessingControl::isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const +{ + if (parameter != QCameraImageProcessingControl::WhiteBalancePreset) + return false; + + if (m_session->handle() == CAMERA_HANDLE_INVALID) + return false; + + int supported = 0; + camera_whitebalancemode_t modes[20]; + const camera_error_t result = camera_get_whitebalance_modes(m_session->handle(), 20, &supported, modes); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve supported whitebalance modes:" << result; + return false; + } + + QSet<QCameraImageProcessing::WhiteBalanceMode> supportedModes; + for (int i = 0; i < supported; ++i) { + switch (modes[i]) { + case CAMERA_WHITEBALANCEMODE_AUTO: + supportedModes.insert(QCameraImageProcessing::WhiteBalanceAuto); + break; + case CAMERA_WHITEBALANCEMODE_MANUAL: + supportedModes.insert(QCameraImageProcessing::WhiteBalanceManual); + break; + default: + break; + } + } + + return supportedModes.contains(value.value<QCameraImageProcessing::WhiteBalanceMode>()); +} + +QVariant BbCameraImageProcessingControl::parameter(ProcessingParameter parameter) const +{ + if (parameter != QCameraImageProcessingControl::WhiteBalancePreset) + return QVariant(); + + if (m_session->handle() == CAMERA_HANDLE_INVALID) + return QVariant(); + + camera_whitebalancemode_t mode; + const camera_error_t result = camera_get_whitebalance_mode(m_session->handle(), &mode); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve current whitebalance mode:" << result; + return QVariant(); + } + + switch (mode) { + case CAMERA_WHITEBALANCEMODE_AUTO: + return QVariant::fromValue(QCameraImageProcessing::WhiteBalanceAuto); + case CAMERA_WHITEBALANCEMODE_MANUAL: + return QVariant::fromValue(QCameraImageProcessing::WhiteBalanceManual); + default: + return QVariant(); + } +} + +void BbCameraImageProcessingControl::setParameter(ProcessingParameter parameter, const QVariant &value) +{ + if (parameter != QCameraImageProcessingControl::WhiteBalancePreset) + return; + + if (m_session->handle() == CAMERA_HANDLE_INVALID) + return; + + camera_whitebalancemode_t mode = CAMERA_WHITEBALANCEMODE_DEFAULT; + switch (value.value<QCameraImageProcessing::WhiteBalanceMode>()) { + case QCameraImageProcessing::WhiteBalanceAuto: + mode = CAMERA_WHITEBALANCEMODE_AUTO; + break; + case QCameraImageProcessing::WhiteBalanceManual: + mode = CAMERA_WHITEBALANCEMODE_MANUAL; + break; + default: + break; + } + + const camera_error_t result = camera_set_whitebalance_mode(m_session->handle(), mode); + + if (result != CAMERA_EOK) + qWarning() << "Unable to set whitebalance mode:" << result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameraimageprocessingcontrol.h b/src/plugins/qnx/camera/bbcameraimageprocessingcontrol.h new file mode 100644 index 000000000..ec16d66d7 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraimageprocessingcontrol.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 BBCAMERAIMAGEPROCESSINGCONTROL_H +#define BBCAMERAIMAGEPROCESSINGCONTROL_H + +#include <qcameraimageprocessingcontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraImageProcessingControl : public QCameraImageProcessingControl +{ + Q_OBJECT +public: + explicit BbCameraImageProcessingControl(BbCameraSession *session, QObject *parent = 0); + + bool isParameterSupported(ProcessingParameter) const Q_DECL_OVERRIDE; + bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const Q_DECL_OVERRIDE; + QVariant parameter(ProcessingParameter parameter) const Q_DECL_OVERRIDE; + void setParameter(ProcessingParameter parameter, const QVariant &value) Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameralockscontrol.cpp b/src/plugins/qnx/camera/bbcameralockscontrol.cpp new file mode 100644 index 000000000..d2537361c --- /dev/null +++ b/src/plugins/qnx/camera/bbcameralockscontrol.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** 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 "bbcameralockscontrol.h" + +#include "bbcamerasession.h" + +QT_BEGIN_NAMESPACE + +BbCameraLocksControl::BbCameraLocksControl(BbCameraSession *session, QObject *parent) + : QCameraLocksControl(parent) + , m_session(session) + , m_locksApplyMode(IndependentMode) + , m_focusLockStatus(QCamera::Unlocked) + , m_exposureLockStatus(QCamera::Unlocked) + , m_whiteBalanceLockStatus(QCamera::Unlocked) + , m_currentLockTypes(QCamera::NoLock) + , m_supportedLockTypes(QCamera::NoLock) +{ + connect(m_session, SIGNAL(cameraOpened()), SLOT(cameraOpened())); + connect(m_session, SIGNAL(focusStatusChanged(int)), SLOT(focusStatusChanged(int))); +} + +QCamera::LockTypes BbCameraLocksControl::supportedLocks() const +{ + return (QCamera::LockFocus | QCamera::LockExposure | QCamera::LockWhiteBalance); +} + +QCamera::LockStatus BbCameraLocksControl::lockStatus(QCamera::LockType lock) const +{ + if (!m_supportedLockTypes.testFlag(lock) || (m_session->handle() == CAMERA_HANDLE_INVALID)) + return QCamera::Locked; + + switch (lock) { + case QCamera::LockExposure: + return m_exposureLockStatus; + case QCamera::LockWhiteBalance: + return m_whiteBalanceLockStatus; + case QCamera::LockFocus: + return m_focusLockStatus; + default: + return QCamera::Locked; + } +} + +void BbCameraLocksControl::searchAndLock(QCamera::LockTypes locks) +{ + if (m_session->handle() == CAMERA_HANDLE_INVALID) + return; + + // filter out unsupported locks + locks &= m_supportedLockTypes; + + m_currentLockTypes |= locks; + + uint32_t lockModes = CAMERA_3A_NONE; + + switch (m_locksApplyMode) { + case IndependentMode: + if (m_currentLockTypes & QCamera::LockExposure) + lockModes |= CAMERA_3A_AUTOEXPOSURE; + if (m_currentLockTypes & QCamera::LockWhiteBalance) + lockModes |= CAMERA_3A_AUTOWHITEBALANCE; + if (m_currentLockTypes & QCamera::LockFocus) + lockModes |= CAMERA_3A_AUTOFOCUS; + break; + case FocusExposureBoundMode: + if ((m_currentLockTypes & QCamera::LockExposure) || (m_currentLockTypes & QCamera::LockFocus)) + lockModes = (CAMERA_3A_AUTOEXPOSURE | CAMERA_3A_AUTOFOCUS); + break; + case AllBoundMode: + lockModes = (CAMERA_3A_AUTOEXPOSURE | CAMERA_3A_AUTOFOCUS | CAMERA_3A_AUTOWHITEBALANCE); + break; + case FocusOnlyMode: + lockModes = CAMERA_3A_AUTOFOCUS; + break; + } + + const camera_error_t result = camera_set_3a_lock(m_session->handle(), lockModes); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to set lock modes:" << result; + } else { + if (lockModes & CAMERA_3A_AUTOFOCUS) { + // handled by focusStatusChanged() + } + + if (lockModes & CAMERA_3A_AUTOEXPOSURE) { + m_exposureLockStatus = QCamera::Locked; + emit lockStatusChanged(QCamera::LockExposure, QCamera::Locked, QCamera::LockAcquired); + } + + if (lockModes & CAMERA_3A_AUTOWHITEBALANCE) { + m_whiteBalanceLockStatus = QCamera::Locked; + emit lockStatusChanged(QCamera::LockWhiteBalance, QCamera::Locked, QCamera::LockAcquired); + } + } +} + +void BbCameraLocksControl::unlock(QCamera::LockTypes locks) +{ + // filter out unsupported locks + locks &= m_supportedLockTypes; + + m_currentLockTypes &= ~locks; + + uint32_t lockModes = CAMERA_3A_NONE; + + switch (m_locksApplyMode) { + case IndependentMode: + if (m_currentLockTypes & QCamera::LockExposure) + lockModes |= CAMERA_3A_AUTOEXPOSURE; + if (m_currentLockTypes & QCamera::LockWhiteBalance) + lockModes |= CAMERA_3A_AUTOWHITEBALANCE; + if (m_currentLockTypes & QCamera::LockFocus) + lockModes |= CAMERA_3A_AUTOFOCUS; + break; + case FocusExposureBoundMode: + if ((m_currentLockTypes & QCamera::LockExposure) || (m_currentLockTypes & QCamera::LockFocus)) + lockModes = (CAMERA_3A_AUTOEXPOSURE | CAMERA_3A_AUTOFOCUS); + break; + case AllBoundMode: + lockModes = (CAMERA_3A_AUTOEXPOSURE | CAMERA_3A_AUTOFOCUS | CAMERA_3A_AUTOWHITEBALANCE); + break; + case FocusOnlyMode: + lockModes = CAMERA_3A_AUTOFOCUS; + break; + } + + const camera_error_t result = camera_set_3a_lock(m_session->handle(), lockModes); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to set lock modes:" << result; + } else { + if (locks.testFlag(QCamera::LockFocus)) { + // handled by focusStatusChanged() + } + + if (locks.testFlag(QCamera::LockExposure)) { + m_exposureLockStatus = QCamera::Unlocked; + emit lockStatusChanged(QCamera::LockExposure, QCamera::Unlocked, QCamera::UserRequest); + } + + if (locks.testFlag(QCamera::LockWhiteBalance)) { + m_whiteBalanceLockStatus = QCamera::Unlocked; + emit lockStatusChanged(QCamera::LockWhiteBalance, QCamera::Unlocked, QCamera::UserRequest); + } + } +} + +void BbCameraLocksControl::cameraOpened() +{ + // retrieve information about lock apply modes + int supported = 0; + uint32_t modes[20]; + + const camera_error_t result = camera_get_3a_lock_modes(m_session->handle(), 20, &supported, modes); + + if (result == CAMERA_EOK) { + // see API documentation of camera_get_3a_lock_modes for explanation of case discrimination below + if (supported == 4) { + m_locksApplyMode = IndependentMode; + } else if (supported == 3) { + m_locksApplyMode = FocusExposureBoundMode; + } else if (supported == 2) { + if (modes[0] == (CAMERA_3A_AUTOFOCUS | CAMERA_3A_AUTOEXPOSURE | CAMERA_3A_AUTOWHITEBALANCE)) + m_locksApplyMode = AllBoundMode; + else + m_locksApplyMode = FocusOnlyMode; + } + } + + // retrieve information about supported lock types + m_supportedLockTypes = QCamera::NoLock; + + if (camera_has_feature(m_session->handle(), CAMERA_FEATURE_AUTOFOCUS)) + m_supportedLockTypes |= QCamera::LockFocus; + + if (camera_has_feature(m_session->handle(), CAMERA_FEATURE_AUTOEXPOSURE)) + m_supportedLockTypes |= QCamera::LockExposure; + + if (camera_has_feature(m_session->handle(), CAMERA_FEATURE_AUTOWHITEBALANCE)) + m_supportedLockTypes |= QCamera::LockWhiteBalance; + + m_focusLockStatus = QCamera::Unlocked; + m_exposureLockStatus = QCamera::Unlocked; + m_whiteBalanceLockStatus = QCamera::Unlocked; +} + +void BbCameraLocksControl::focusStatusChanged(int value) +{ + const camera_focusstate_t focusState = static_cast<camera_focusstate_t>(value); + + switch (focusState) { + case CAMERA_FOCUSSTATE_NONE: + m_focusLockStatus = QCamera::Unlocked; + emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::UserRequest); + break; + case CAMERA_FOCUSSTATE_WAITING: + case CAMERA_FOCUSSTATE_SEARCHING: + m_focusLockStatus = QCamera::Searching; + emit lockStatusChanged(QCamera::LockFocus, QCamera::Searching, QCamera::UserRequest); + break; + case CAMERA_FOCUSSTATE_FAILED: + m_focusLockStatus = QCamera::Unlocked; + emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed); + break; + case CAMERA_FOCUSSTATE_LOCKED: + m_focusLockStatus = QCamera::Locked; + emit lockStatusChanged(QCamera::LockFocus, QCamera::Locked, QCamera::LockAcquired); + break; + case CAMERA_FOCUSSTATE_SCENECHANGE: + m_focusLockStatus = QCamera::Unlocked; + emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockTemporaryLost); + break; + default: + break; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameralockscontrol.h b/src/plugins/qnx/camera/bbcameralockscontrol.h new file mode 100644 index 000000000..8257abdbc --- /dev/null +++ b/src/plugins/qnx/camera/bbcameralockscontrol.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 BBCAMERALOCKSCONTROL_H +#define BBCAMERALOCKSCONTROL_H + +#include <qcameralockscontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraLocksControl : public QCameraLocksControl +{ + Q_OBJECT +public: + enum LocksApplyMode + { + IndependentMode, + FocusExposureBoundMode, + AllBoundMode, + FocusOnlyMode + }; + + explicit BbCameraLocksControl(BbCameraSession *session, QObject *parent = 0); + + QCamera::LockTypes supportedLocks() const Q_DECL_OVERRIDE; + QCamera::LockStatus lockStatus(QCamera::LockType lock) const Q_DECL_OVERRIDE; + void searchAndLock(QCamera::LockTypes locks) Q_DECL_OVERRIDE; + void unlock(QCamera::LockTypes locks) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void cameraOpened(); + void focusStatusChanged(int value); + +private: + BbCameraSession *m_session; + + LocksApplyMode m_locksApplyMode; + QCamera::LockStatus m_focusLockStatus; + QCamera::LockStatus m_exposureLockStatus; + QCamera::LockStatus m_whiteBalanceLockStatus; + QCamera::LockTypes m_currentLockTypes; + QCamera::LockTypes m_supportedLockTypes; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameramediarecordercontrol.cpp b/src/plugins/qnx/camera/bbcameramediarecordercontrol.cpp new file mode 100644 index 000000000..44c19fb46 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameramediarecordercontrol.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** 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 "bbcameramediarecordercontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> +#include <QUrl> + +#ifndef Q_OS_BLACKBERRY_TABLET +#include <audio/audio_manager_device.h> +#include <audio/audio_manager_volume.h> +#endif + +QT_BEGIN_NAMESPACE + +#ifndef Q_OS_BLACKBERRY_TABLET +static audio_manager_device_t currentAudioInputDevice() +{ + audio_manager_device_t device = AUDIO_DEVICE_HEADSET; + + const int result = audio_manager_get_default_input_device(&device); + if (result != EOK) { + qWarning() << "Unable to retrieve default audio input device:" << result; + return AUDIO_DEVICE_HEADSET; + } + + return device; +} +#endif + +BbCameraMediaRecorderControl::BbCameraMediaRecorderControl(BbCameraSession *session, QObject *parent) + : QMediaRecorderControl(parent) + , m_session(session) +{ + connect(m_session, SIGNAL(videoStateChanged(QMediaRecorder::State)), this, SIGNAL(stateChanged(QMediaRecorder::State))); + connect(m_session, SIGNAL(videoStatusChanged(QMediaRecorder::Status)), this, SIGNAL(statusChanged(QMediaRecorder::Status))); + connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64))); + connect(m_session, SIGNAL(actualLocationChanged(QUrl)), this, SIGNAL(actualLocationChanged(QUrl))); + connect(m_session, SIGNAL(videoError(int,QString)), this, SIGNAL(error(int,QString))); +} + +QUrl BbCameraMediaRecorderControl::outputLocation() const +{ + return m_session->outputLocation(); +} + +bool BbCameraMediaRecorderControl::setOutputLocation(const QUrl &location) +{ + return m_session->setOutputLocation(location); +} + +QMediaRecorder::State BbCameraMediaRecorderControl::state() const +{ + return m_session->videoState(); +} + +QMediaRecorder::Status BbCameraMediaRecorderControl::status() const +{ + return m_session->videoStatus(); +} + +qint64 BbCameraMediaRecorderControl::duration() const +{ + return m_session->duration(); +} + +bool BbCameraMediaRecorderControl::isMuted() const +{ + bool muted = false; + +#ifndef Q_OS_BLACKBERRY_TABLET + const int result = audio_manager_get_input_mute(currentAudioInputDevice(), &muted); + if (result != EOK) { + emit const_cast<BbCameraMediaRecorderControl*>(this)->error(QMediaRecorder::ResourceError, tr("Unable to retrieve mute status")); + return false; + } +#endif + return muted; +} + +qreal BbCameraMediaRecorderControl::volume() const +{ + double level = 0.0; + +#ifndef Q_OS_BLACKBERRY_TABLET + const int result = audio_manager_get_input_level(currentAudioInputDevice(), &level); + if (result != EOK) { + emit const_cast<BbCameraMediaRecorderControl*>(this)->error(QMediaRecorder::ResourceError, tr("Unable to retrieve audio input volume")); + return 0.0; + } +#endif + + return (level / 100); +} + +void BbCameraMediaRecorderControl::applySettings() +{ + m_session->applyVideoSettings(); +} + +void BbCameraMediaRecorderControl::setState(QMediaRecorder::State state) +{ + m_session->setVideoState(state); +} + +void BbCameraMediaRecorderControl::setMuted(bool muted) +{ +#ifndef Q_OS_BLACKBERRY_TABLET + const int result = audio_manager_set_input_mute(currentAudioInputDevice(), muted); + if (result != EOK) { + emit error(QMediaRecorder::ResourceError, tr("Unable to set mute status")); + } else { + emit mutedChanged(muted); + } +#endif +} + +void BbCameraMediaRecorderControl::setVolume(qreal volume) +{ +#ifndef Q_OS_BLACKBERRY_TABLET + const int result = audio_manager_set_input_level(currentAudioInputDevice(), (volume * 100)); + if (result != EOK) { + emit error(QMediaRecorder::ResourceError, tr("Unable to set audio input volume")); + } else { + emit volumeChanged(volume); + } +#endif +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameramediarecordercontrol.h b/src/plugins/qnx/camera/bbcameramediarecordercontrol.h new file mode 100644 index 000000000..dffd18be5 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameramediarecordercontrol.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 BBCAMERAMEDIARECORDERCONTROL_H +#define BBCAMERAMEDIARECORDERCONTROL_H + +#include <qmediarecordercontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraMediaRecorderControl : public QMediaRecorderControl +{ + Q_OBJECT +public: + explicit BbCameraMediaRecorderControl(BbCameraSession *session, QObject *parent = 0); + + QUrl outputLocation() const Q_DECL_OVERRIDE; + bool setOutputLocation(const QUrl &location) Q_DECL_OVERRIDE; + QMediaRecorder::State state() const Q_DECL_OVERRIDE; + QMediaRecorder::Status status() const Q_DECL_OVERRIDE; + qint64 duration() const Q_DECL_OVERRIDE; + bool isMuted() const Q_DECL_OVERRIDE; + qreal volume() const Q_DECL_OVERRIDE; + void applySettings() Q_DECL_OVERRIDE; + +public Q_SLOTS: + void setState(QMediaRecorder::State state) Q_DECL_OVERRIDE; + void setMuted(bool muted) Q_DECL_OVERRIDE; + void setVolume(qreal volume) Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameraorientationhandler.cpp b/src/plugins/qnx/camera/bbcameraorientationhandler.cpp new file mode 100644 index 000000000..b715249f9 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraorientationhandler.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** 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 "bbcameraorientationhandler.h" + +#include <QAbstractEventDispatcher> +#include <QCoreApplication> +#include <QDebug> + +#include <bps/orientation.h> + +QT_BEGIN_NAMESPACE + +BbCameraOrientationHandler::BbCameraOrientationHandler(QObject *parent) + : QObject(parent) + , m_orientation(0) +{ + QCoreApplication::eventDispatcher()->installNativeEventFilter(this); + int result = orientation_request_events(0); + if (result == BPS_FAILURE) + qWarning() << "Unable to register for orientation change events"; + + orientation_direction_t direction = ORIENTATION_FACE_UP; + int angle = 0; + + result = orientation_get(&direction, &angle); + if (result == BPS_FAILURE) { + qWarning() << "Unable to retrieve initial orientation"; + } else { + m_orientation = angle; + } +} + +BbCameraOrientationHandler::~BbCameraOrientationHandler() +{ +#ifndef Q_OS_BLACKBERRY_TABLET + const int result = orientation_stop_events(0); + if (result == BPS_FAILURE) + qWarning() << "Unable to unregister for orientation change events"; +#endif + + QCoreApplication::eventDispatcher()->removeNativeEventFilter(this); +} + +bool BbCameraOrientationHandler::nativeEventFilter(const QByteArray&, void *message, long*) +{ + bps_event_t* const event = static_cast<bps_event_t*>(message); + if (!event || bps_event_get_domain(event) != orientation_get_domain()) + return false; + + const int angle = orientation_event_get_angle(event); + if (angle != m_orientation) { + m_orientation = angle; + emit orientationChanged(m_orientation); + } + + return false; // do not drop the event +} + +int BbCameraOrientationHandler::orientation() const +{ + return m_orientation; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameraorientationhandler.h b/src/plugins/qnx/camera/bbcameraorientationhandler.h new file mode 100644 index 000000000..3d236b884 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraorientationhandler.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 BBCAMERAORIENTATIONHANDLER_H +#define BBCAMERAORIENTATIONHANDLER_H + +#include <QAbstractNativeEventFilter> +#include <QObject> + +QT_BEGIN_NAMESPACE + +class BbCameraOrientationHandler : public QObject, public QAbstractNativeEventFilter +{ + Q_OBJECT +public: + explicit BbCameraOrientationHandler(QObject *parent = 0); + ~BbCameraOrientationHandler(); + + bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + + int orientation() const; + +Q_SIGNALS: + void orientationChanged(int degree); + +private: + int m_orientation; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameraservice.cpp b/src/plugins/qnx/camera/bbcameraservice.cpp new file mode 100644 index 000000000..d9adc7c9d --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraservice.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** 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 "bbcameraservice.h" + +#include "bbcameraaudioencodersettingscontrol.h" +#include "bbcameracapturebufferformatcontrol.h" +#include "bbcameracapturedestinationcontrol.h" +#include "bbcameracontrol.h" +#include "bbcameraexposurecontrol.h" +#include "bbcameraflashcontrol.h" +#include "bbcamerafocuscontrol.h" +#include "bbcameraimagecapturecontrol.h" +#include "bbcameraimageprocessingcontrol.h" +#include "bbcameralockscontrol.h" +#include "bbcameramediarecordercontrol.h" +#include "bbcamerasession.h" +#include "bbcameravideoencodersettingscontrol.h" +#include "bbcameraviewfindersettingscontrol.h" +#include "bbcamerazoomcontrol.h" +#include "bbimageencodercontrol.h" +#include "bbvideodeviceselectorcontrol.h" +#include "bbvideorenderercontrol.h" + +#include <QDebug> +#include <QVariant> + +QT_BEGIN_NAMESPACE + +BbCameraService::BbCameraService(QObject *parent) + : QMediaService(parent) + , m_cameraSession(new BbCameraSession(this)) + , m_cameraAudioEncoderSettingsControl(new BbCameraAudioEncoderSettingsControl(m_cameraSession, this)) + , m_cameraCaptureBufferFormatControl(new BbCameraCaptureBufferFormatControl(this)) + , m_cameraCaptureDestinationControl(new BbCameraCaptureDestinationControl(m_cameraSession, this)) + , m_cameraControl(new BbCameraControl(m_cameraSession, this)) + , m_cameraExposureControl(new BbCameraExposureControl(m_cameraSession, this)) + , m_cameraFlashControl(new BbCameraFlashControl(m_cameraSession, this)) + , m_cameraFocusControl(new BbCameraFocusControl(m_cameraSession, this)) + , m_cameraImageCaptureControl(new BbCameraImageCaptureControl(m_cameraSession, this)) + , m_cameraImageProcessingControl(new BbCameraImageProcessingControl(m_cameraSession, this)) + , m_cameraLocksControl(new BbCameraLocksControl(m_cameraSession, this)) + , m_cameraMediaRecorderControl(new BbCameraMediaRecorderControl(m_cameraSession, this)) + , m_cameraVideoEncoderSettingsControl(new BbCameraVideoEncoderSettingsControl(m_cameraSession, this)) + , m_cameraViewfinderSettingsControl(new BbCameraViewfinderSettingsControl(m_cameraSession, this)) + , m_cameraZoomControl(new BbCameraZoomControl(m_cameraSession, this)) + , m_imageEncoderControl(new BbImageEncoderControl(m_cameraSession, this)) + , m_videoDeviceSelectorControl(new BbVideoDeviceSelectorControl(m_cameraSession, this)) + , m_videoRendererControl(new BbVideoRendererControl(m_cameraSession, this)) +{ +} + +BbCameraService::~BbCameraService() +{ +} + +QMediaControl* BbCameraService::requestControl(const char *name) +{ + if (qstrcmp(name, QAudioEncoderSettingsControl_iid) == 0) + return m_cameraAudioEncoderSettingsControl; + else if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0) + return m_cameraCaptureBufferFormatControl; + else if (qstrcmp(name, QCameraCaptureDestinationControl_iid) == 0) + return m_cameraCaptureDestinationControl; + else if (qstrcmp(name, QCameraControl_iid) == 0) + return m_cameraControl; + else if (qstrcmp(name, QCameraExposureControl_iid) == 0) + return m_cameraExposureControl; + else if (qstrcmp(name, QCameraFlashControl_iid) == 0) + return m_cameraFlashControl; + else if (qstrcmp(name, QCameraFocusControl_iid) == 0) + return m_cameraFocusControl; + else if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0) + return m_cameraImageCaptureControl; + else if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0) + return m_cameraImageProcessingControl; + else if (qstrcmp(name, QCameraLocksControl_iid) == 0) + return m_cameraLocksControl; + else if (qstrcmp(name, QMediaRecorderControl_iid) == 0) + return m_cameraMediaRecorderControl; + else if (qstrcmp(name, QVideoEncoderSettingsControl_iid) == 0) + return m_cameraVideoEncoderSettingsControl; + else if (qstrcmp(name, QCameraViewfinderSettingsControl_iid) == 0) + return m_cameraViewfinderSettingsControl; + else if (qstrcmp(name, QCameraZoomControl_iid) == 0) + return m_cameraZoomControl; + else if (qstrcmp(name, QImageEncoderControl_iid) == 0) + return m_imageEncoderControl; + else if (qstrcmp(name, QVideoDeviceSelectorControl_iid) == 0) + return m_videoDeviceSelectorControl; + else if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return m_videoRendererControl; + + return 0; +} + +void BbCameraService::releaseControl(QMediaControl *control) +{ + Q_UNUSED(control) + + // Implemented as a singleton, so we do nothing. +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameraservice.h b/src/plugins/qnx/camera/bbcameraservice.h new file mode 100644 index 000000000..374d03c36 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraservice.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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 BBCAMERASERVICE_H +#define BBCAMERASERVICE_H + +#include <QObject> + +#include <qmediaservice.h> + +QT_BEGIN_NAMESPACE + +class BbCameraAudioEncoderSettingsControl; +class BbCameraCaptureBufferFormatControl; +class BbCameraCaptureDestinationControl; +class BbCameraControl; +class BbCameraExposureControl; +class BbCameraFlashControl; +class BbCameraFocusControl; +class BbCameraImageCaptureControl; +class BbCameraImageProcessingControl; +class BbCameraLocksControl; +class BbCameraMediaRecorderControl; +class BbCameraSession; +class BbCameraVideoEncoderSettingsControl; +class BbCameraViewfinderSettingsControl; +class BbCameraZoomControl; +class BbImageEncoderControl; +class BbVideoDeviceSelectorControl; +class BbVideoRendererControl; + +class BbCameraService : public QMediaService +{ + Q_OBJECT + +public: + explicit BbCameraService(QObject *parent = 0); + ~BbCameraService(); + + virtual QMediaControl* requestControl(const char *name); + virtual void releaseControl(QMediaControl *control); + +private: + BbCameraSession* m_cameraSession; + + BbCameraAudioEncoderSettingsControl* m_cameraAudioEncoderSettingsControl; + BbCameraCaptureBufferFormatControl* m_cameraCaptureBufferFormatControl; + BbCameraCaptureDestinationControl* m_cameraCaptureDestinationControl; + BbCameraControl* m_cameraControl; + BbCameraExposureControl* m_cameraExposureControl; + BbCameraFlashControl* m_cameraFlashControl; + BbCameraFocusControl* m_cameraFocusControl; + BbCameraImageCaptureControl* m_cameraImageCaptureControl; + BbCameraImageProcessingControl* m_cameraImageProcessingControl; + BbCameraLocksControl* m_cameraLocksControl; + BbCameraMediaRecorderControl* m_cameraMediaRecorderControl; + BbCameraVideoEncoderSettingsControl* m_cameraVideoEncoderSettingsControl; + BbCameraViewfinderSettingsControl* m_cameraViewfinderSettingsControl; + BbCameraZoomControl* m_cameraZoomControl; + BbImageEncoderControl* m_imageEncoderControl; + BbVideoDeviceSelectorControl* m_videoDeviceSelectorControl; + BbVideoRendererControl* m_videoRendererControl; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcamerasession.cpp b/src/plugins/qnx/camera/bbcamerasession.cpp new file mode 100644 index 000000000..59db66f4a --- /dev/null +++ b/src/plugins/qnx/camera/bbcamerasession.cpp @@ -0,0 +1,1164 @@ +/**************************************************************************** +** +** 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 "bbcamerasession.h" + +#include "bbcameraorientationhandler.h" +#include "bbcameraviewfindersettingscontrol.h" +#include "windowgrabber.h" + +#include <QAbstractVideoSurface> +#include <QBuffer> +#include <QDebug> +#include <QImage> +#include <QUrl> +#include <QVideoSurfaceFormat> +#include <qmath.h> + +#include <algorithm> + +QT_BEGIN_NAMESPACE + +static QString errorToString(camera_error_t error) +{ + switch (error) { + case CAMERA_EOK: + return QLatin1String("No error"); + case CAMERA_EAGAIN: + return QLatin1String("Camera unavailable"); + case CAMERA_EINVAL: + return QLatin1String("Inavlid argument"); + case CAMERA_ENODEV: + return QLatin1String("Camera not found"); + case CAMERA_EMFILE: + return QLatin1String("File table overflow"); + case CAMERA_EBADF: + return QLatin1String("Invalid handle passed"); + case CAMERA_EACCESS: + return QLatin1String("No permission"); + case CAMERA_EBADR: + return QLatin1String("Invalid file descriptor"); + case CAMERA_ENOENT: + return QLatin1String("File or directory does not exists"); + case CAMERA_ENOMEM: + return QLatin1String("Memory allocation failed"); + case CAMERA_EOPNOTSUPP: + return QLatin1String("Operation not supported"); + case CAMERA_ETIMEDOUT: + return QLatin1String("Communication timeout"); + case CAMERA_EALREADY: + return QLatin1String("Operation already in progress"); + case CAMERA_EUNINIT: + return QLatin1String("Camera library not initialized"); + case CAMERA_EREGFAULT: + return QLatin1String("Callback registration failed"); + case CAMERA_EMICINUSE: + return QLatin1String("Microphone in use already"); +#ifndef Q_OS_BLACKBERRY_TABLET + case CAMERA_ENODATA: + return QLatin1String("Data does not exist"); + case CAMERA_EBUSY: + return QLatin1String("Camera busy"); + case CAMERA_EDESKTOPCAMERAINUSE: + return QLatin1String("Desktop camera in use already"); + case CAMERA_ENOSPC: + return QLatin1String("Disk is full"); + case CAMERA_EPOWERDOWN: + return QLatin1String("Camera in power down state"); + case CAMERA_3ALOCKED: + return QLatin1String("3A have been locked"); +// case CAMERA_EVIEWFINDERFROZEN: // not yet available in 10.2 NDK +// return QLatin1String("Freeze flag set"); +#endif + default: + return QLatin1String("Unknown error"); + } +} + +QDebug operator<<(QDebug debug, camera_error_t error) +{ + debug.nospace() << errorToString(error); + return debug.space(); +} + +BbCameraSession::BbCameraSession(QObject *parent) + : QObject(parent) + , m_nativeCameraOrientation(0) + , m_orientationHandler(new BbCameraOrientationHandler(this)) + , m_status(QCamera::UnloadedStatus) + , m_state(QCamera::UnloadedState) + , m_captureMode(QCamera::CaptureStillImage) + , m_device("bb:RearCamera") + , m_previewIsVideo(true) + , m_surface(0) + , m_captureImageDriveMode(QCameraImageCapture::SingleImageCapture) + , m_lastImageCaptureId(0) + , m_captureDestination(QCameraImageCapture::CaptureToFile) + , m_videoState(QMediaRecorder::StoppedState) + , m_videoStatus(QMediaRecorder::LoadedStatus) + , m_handle(CAMERA_HANDLE_INVALID) + , m_windowGrabber(new WindowGrabber(this)) +{ + connect(this, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateReadyForCapture())); + connect(this, SIGNAL(captureModeChanged(QCamera::CaptureModes)), SLOT(updateReadyForCapture())); + connect(m_orientationHandler, SIGNAL(orientationChanged(int)), SLOT(deviceOrientationChanged(int))); + + connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage)), SLOT(viewfinderFrameGrabbed(QImage))); +} + +BbCameraSession::~BbCameraSession() +{ + stopViewFinder(); + closeCamera(); +} + +camera_handle_t BbCameraSession::handle() const +{ + return m_handle; +} + +QCamera::State BbCameraSession::state() const +{ + return m_state; +} + +void BbCameraSession::setState(QCamera::State state) +{ + if (m_state == state) + return; + + const QCamera::State previousState = m_state; + + if (previousState == QCamera::UnloadedState) { + if (state == QCamera::LoadedState) { + if (openCamera()) { + m_state = state; + } + } else if (state == QCamera::ActiveState) { + if (openCamera()) { + QMetaObject::invokeMethod(this, "applyConfiguration", Qt::QueuedConnection); + m_state = state; + } + } + } else if (previousState == QCamera::LoadedState) { + if (state == QCamera::UnloadedState) { + closeCamera(); + m_state = state; + } else if (state == QCamera::ActiveState) { + QMetaObject::invokeMethod(this, "applyConfiguration", Qt::QueuedConnection); + m_state = state; + } + } else if (previousState == QCamera::ActiveState) { + if (state == QCamera::LoadedState) { + stopViewFinder(); + m_state = state; + } else if (state == QCamera::UnloadedState) { + stopViewFinder(); + closeCamera(); + m_state = state; + } + } + + if (m_state != previousState) + emit stateChanged(m_state); +} + +QCamera::Status BbCameraSession::status() const +{ + return m_status; +} + +QCamera::CaptureModes BbCameraSession::captureMode() const +{ + return m_captureMode; +} + +void BbCameraSession::setCaptureMode(QCamera::CaptureModes captureMode) +{ + if (m_captureMode == captureMode) + return; + + m_captureMode = captureMode; + emit captureModeChanged(m_captureMode); +} + +bool BbCameraSession::isCaptureModeSupported(QCamera::CaptureModes mode) const +{ + if (m_handle == CAMERA_HANDLE_INVALID) { + // the camera has not been loaded yet via QCamera::load(), so + // we open it temporarily to peek for the supported capture modes + + camera_unit_t unit = CAMERA_UNIT_REAR; + if (m_device == cameraIdentifierFront()) + unit = CAMERA_UNIT_FRONT; + else if (m_device == cameraIdentifierRear()) + unit = CAMERA_UNIT_REAR; + else if (m_device == cameraIdentifierDesktop()) + unit = CAMERA_UNIT_DESKTOP; + + camera_handle_t handle; + const camera_error_t result = camera_open(unit, CAMERA_MODE_RW, &handle); + if (result != CAMERA_EOK) + return true; + + const bool supported = isCaptureModeSupported(handle, mode); + + camera_close(handle); + + return supported; + } else { + return isCaptureModeSupported(m_handle, mode); + } +} + +QByteArray BbCameraSession::cameraIdentifierFront() +{ + return "bb:FrontCamera"; +} + +QByteArray BbCameraSession::cameraIdentifierRear() +{ + return "bb:RearCamera"; +} + +QByteArray BbCameraSession::cameraIdentifierDesktop() +{ + return "bb:DesktopCamera"; +} + +void BbCameraSession::setDevice(const QByteArray &device) +{ + m_device = device; +} + +QByteArray BbCameraSession::device() const +{ + return m_device; +} + +QAbstractVideoSurface* BbCameraSession::surface() const +{ + return m_surface; +} + +void BbCameraSession::setSurface(QAbstractVideoSurface *surface) +{ + QMutexLocker locker(&m_surfaceMutex); + + if (m_surface == surface) + return; + + m_surface = surface; +} + +bool BbCameraSession::isReadyForCapture() const +{ + if (m_captureMode & QCamera::CaptureStillImage) + return (m_status == QCamera::ActiveStatus); + + if (m_captureMode & QCamera::CaptureVideo) + return (m_status == QCamera::ActiveStatus); + + return false; +} + +QCameraImageCapture::DriveMode BbCameraSession::driveMode() const +{ + return m_captureImageDriveMode; +} + +void BbCameraSession::setDriveMode(QCameraImageCapture::DriveMode mode) +{ + m_captureImageDriveMode = mode; +} + +/** + * A helper structure that keeps context data for image capture callbacks. + */ +struct ImageCaptureData +{ + int requestId; + QString fileName; + BbCameraSession *session; +}; + +static void imageCaptureShutterCallback(camera_handle_t handle, void *context) +{ + Q_UNUSED(handle) + + const ImageCaptureData *data = static_cast<ImageCaptureData*>(context); + + // We are inside a worker thread here, so emit imageExposed inside the main thread + QMetaObject::invokeMethod(data->session, "imageExposed", Qt::QueuedConnection, + Q_ARG(int, data->requestId)); +} + +static void imageCaptureImageCallback(camera_handle_t handle, camera_buffer_t *buffer, void *context) +{ + Q_UNUSED(handle) + + QScopedPointer<ImageCaptureData> data(static_cast<ImageCaptureData*>(context)); + + if (buffer->frametype != CAMERA_FRAMETYPE_JPEG) { + // We are inside a worker thread here, so emit error signal inside the main thread + QMetaObject::invokeMethod(data->session, "imageCaptureError", Qt::QueuedConnection, + Q_ARG(int, data->requestId), + Q_ARG(QCameraImageCapture::Error, QCameraImageCapture::FormatError), + Q_ARG(QString, BbCameraSession::tr("Camera provides image in unsupported format"))); + return; + } + + const QByteArray rawData((const char*)buffer->framebuf, buffer->framedesc.jpeg.bufsize); + + QImage image; + const bool ok = image.loadFromData(rawData, "JPG"); + if (!ok) { + const QString errorMessage = BbCameraSession::tr("Could not load JPEG data from frame"); + // We are inside a worker thread here, so emit error signal inside the main thread + QMetaObject::invokeMethod(data->session, "imageCaptureError", Qt::QueuedConnection, + Q_ARG(int, data->requestId), + Q_ARG(QCameraImageCapture::Error, QCameraImageCapture::FormatError), + Q_ARG(QString, errorMessage)); + return; + } + + + // We are inside a worker thread here, so invoke imageCaptured inside the main thread + QMetaObject::invokeMethod(data->session, "imageCaptured", Qt::QueuedConnection, + Q_ARG(int, data->requestId), + Q_ARG(QImage, image), + Q_ARG(QString, data->fileName)); +} + +int BbCameraSession::capture(const QString &fileName) +{ + m_lastImageCaptureId++; + + if (!isReadyForCapture()) { + emit imageCaptureError(m_lastImageCaptureId, QCameraImageCapture::NotReadyError, tr("Camera not ready")); + return m_lastImageCaptureId; + } + + if (m_captureImageDriveMode == QCameraImageCapture::SingleImageCapture) { + // prepare context object for callback + ImageCaptureData *context = new ImageCaptureData; + context->requestId = m_lastImageCaptureId; + context->fileName = fileName; + context->session = this; + + const camera_error_t result = camera_take_photo(m_handle, + imageCaptureShutterCallback, + 0, + 0, + imageCaptureImageCallback, + context, false); + + if (result != CAMERA_EOK) + qWarning() << "Unable to take photo:" << result; + } else { + // TODO: implement burst mode when available in Qt API + } + + return m_lastImageCaptureId; +} + +void BbCameraSession::cancelCapture() +{ + // BB10 API doesn't provide functionality for that +} + +bool BbCameraSession::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const +{ + // capture to buffer, file and both are supported. + return destination & (QCameraImageCapture::CaptureToFile | QCameraImageCapture::CaptureToBuffer); +} + +QCameraImageCapture::CaptureDestinations BbCameraSession::captureDestination() const +{ + return m_captureDestination; +} + +void BbCameraSession::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) +{ + if (m_captureDestination != destination) { + m_captureDestination = destination; + emit captureDestinationChanged(m_captureDestination); + } +} + +QList<QSize> BbCameraSession::supportedResolutions(const QImageEncoderSettings&, bool *continuous) const +{ + if (continuous) + *continuous = false; + + if (m_status == QCamera::UnloadedStatus) + return QList<QSize>(); + + if (m_captureMode & QCamera::CaptureStillImage) { + return supportedResolutions(QCamera::CaptureStillImage); + } else if (m_captureMode & QCamera::CaptureVideo) { + return supportedResolutions(QCamera::CaptureVideo); + } + + return QList<QSize>(); +} + +QImageEncoderSettings BbCameraSession::imageSettings() const +{ + return m_imageEncoderSettings; +} + +void BbCameraSession::setImageSettings(const QImageEncoderSettings &settings) +{ + m_imageEncoderSettings = settings; + if (m_imageEncoderSettings.codec().isEmpty()) + m_imageEncoderSettings.setCodec(QLatin1String("jpeg")); +} + +QUrl BbCameraSession::outputLocation() const +{ + return QUrl::fromLocalFile(m_videoOutputLocation); +} + +bool BbCameraSession::setOutputLocation(const QUrl &location) +{ + m_videoOutputLocation = location.toLocalFile(); + + return true; +} + +QMediaRecorder::State BbCameraSession::videoState() const +{ + return m_videoState; +} + +void BbCameraSession::setVideoState(QMediaRecorder::State state) +{ + if (m_videoState == state) + return; + + const QMediaRecorder::State previousState = m_videoState; + + if (previousState == QMediaRecorder::StoppedState) { + if (state == QMediaRecorder::RecordingState) { + if (startVideoRecording()) { + m_videoState = state; + } + } else if (state == QMediaRecorder::PausedState) { + // do nothing + } + } else if (previousState == QMediaRecorder::RecordingState) { + if (state == QMediaRecorder::StoppedState) { + stopVideoRecording(); + m_videoState = state; + } else if (state == QMediaRecorder::PausedState) { + //TODO: (pause) not supported by BB10 API yet + } + } else if (previousState == QMediaRecorder::PausedState) { + if (state == QMediaRecorder::StoppedState) { + stopVideoRecording(); + m_videoState = state; + } else if (state == QMediaRecorder::RecordingState) { + //TODO: (resume) not supported by BB10 API yet + } + } + + emit videoStateChanged(m_videoState); +} + +QMediaRecorder::Status BbCameraSession::videoStatus() const +{ + return m_videoStatus; +} + +qint64 BbCameraSession::duration() const +{ + return (m_videoRecordingDuration.isValid() ? m_videoRecordingDuration.elapsed() : 0); +} + +void BbCameraSession::applyVideoSettings() +{ + if (m_handle == CAMERA_HANDLE_INVALID) + return; + + // apply viewfinder configuration + const QList<QSize> videoOutputResolutions = supportedResolutions(QCamera::CaptureVideo); + + if (!m_videoEncoderSettings.resolution().isValid() || !videoOutputResolutions.contains(m_videoEncoderSettings.resolution())) + m_videoEncoderSettings.setResolution(videoOutputResolutions.first()); + + QSize viewfinderResolution; + + if (m_previewIsVideo) { + // The viewfinder is responsible for encoding the video frames, so the resolutions must match. + viewfinderResolution = m_videoEncoderSettings.resolution(); + } else { + // The frames are encoded separately from the viewfinder, so only the aspect ratio must match. + const QSize videoResolution = m_videoEncoderSettings.resolution(); + const qreal aspectRatio = static_cast<qreal>(videoResolution.width())/static_cast<qreal>(videoResolution.height()); + + QList<QSize> sizes = supportedViewfinderResolutions(QCamera::CaptureVideo); + std::reverse(sizes.begin(), sizes.end()); // use smallest possible resolution + foreach (const QSize &size, sizes) { + // search for viewfinder resolution with the same aspect ratio + if (qFuzzyCompare(aspectRatio, (static_cast<qreal>(size.width())/static_cast<qreal>(size.height())))) { + viewfinderResolution = size; + break; + } + } + } + + Q_ASSERT(viewfinderResolution.isValid()); + + const QByteArray windowId = QString().sprintf("qcamera_vf_%p", this).toLatin1(); + m_windowGrabber->setWindowId(windowId); + + const QByteArray windowGroupId = m_windowGrabber->windowGroupId(); + + const int rotationAngle = (360 - m_nativeCameraOrientation); + + camera_error_t result = CAMERA_EOK; + result = camera_set_videovf_property(m_handle, + CAMERA_IMGPROP_WIN_GROUPID, windowGroupId.data(), + CAMERA_IMGPROP_WIN_ID, windowId.data(), + CAMERA_IMGPROP_WIDTH, viewfinderResolution.width(), + CAMERA_IMGPROP_HEIGHT, viewfinderResolution.height(), + CAMERA_IMGPROP_ROTATION, rotationAngle); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to apply video viewfinder settings:" << result; + return; + } + + const QSize resolution = m_videoEncoderSettings.resolution(); + +#ifndef Q_OS_BLACKBERRY_TABLET + QString videoCodec = m_videoEncoderSettings.codec(); + if (videoCodec.isEmpty()) + videoCodec = QLatin1String("h264"); + + camera_videocodec_t cameraVideoCodec = CAMERA_VIDEOCODEC_H264; + if (videoCodec == QLatin1String("none")) + cameraVideoCodec = CAMERA_VIDEOCODEC_NONE; + else if (videoCodec == QLatin1String("avc1")) + cameraVideoCodec = CAMERA_VIDEOCODEC_AVC1; + else if (videoCodec == QLatin1String("h264")) + cameraVideoCodec = CAMERA_VIDEOCODEC_H264; + + qreal frameRate = m_videoEncoderSettings.frameRate(); + if (frameRate == 0) { + const QList<qreal> frameRates = supportedFrameRates(QVideoEncoderSettings(), 0); + if (!frameRates.isEmpty()) + frameRate = frameRates.last(); + } + + QString audioCodec = m_audioEncoderSettings.codec(); + if (audioCodec.isEmpty()) + audioCodec = QLatin1String("aac"); + + camera_audiocodec_t cameraAudioCodec = CAMERA_AUDIOCODEC_AAC; + if (audioCodec == QLatin1String("none")) + cameraAudioCodec = CAMERA_AUDIOCODEC_NONE; + else if (audioCodec == QLatin1String("aac")) + cameraAudioCodec = CAMERA_AUDIOCODEC_AAC; + else if (audioCodec == QLatin1String("raw")) + cameraAudioCodec = CAMERA_AUDIOCODEC_RAW; + + result = camera_set_video_property(m_handle, + CAMERA_IMGPROP_WIDTH, resolution.width(), + CAMERA_IMGPROP_HEIGHT, resolution.height(), + CAMERA_IMGPROP_ROTATION, rotationAngle, + CAMERA_IMGPROP_VIDEOCODEC, cameraVideoCodec, + CAMERA_IMGPROP_AUDIOCODEC, cameraAudioCodec); +#else + result = camera_set_video_property(m_handle, + CAMERA_IMGPROP_WIDTH, resolution.width(), + CAMERA_IMGPROP_HEIGHT, resolution.height()); +#endif + + if (result != CAMERA_EOK) { + qWarning() << "Unable to apply video settings:" << result; + emit videoError(QMediaRecorder::ResourceError, tr("Unable to apply video settings")); + } +} + +QList<QSize> BbCameraSession::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const +{ + Q_UNUSED(settings); + + if (continuous) + *continuous = false; + + return supportedResolutions(QCamera::CaptureVideo); +} + +QList<qreal> BbCameraSession::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const +{ + Q_UNUSED(settings); + + if (m_handle == CAMERA_HANDLE_INVALID) + return QList<qreal>(); + + int supported = 0; + double rates[20]; + bool maxmin = false; + + /** + * Since in current version of the BB10 platform the video viewfinder encodes the video frames, we use + * the values as returned by camera_get_video_vf_framerates(). + */ + const camera_error_t result = camera_get_video_vf_framerates(m_handle, 20, &supported, rates, &maxmin); + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve supported viewfinder framerates:" << result; + return QList<qreal>(); + } + + QList<qreal> frameRates; + for (int i = 0; i < supported; ++i) + frameRates << rates[i]; + + if (continuous) + *continuous = maxmin; + + return frameRates; +} + +QVideoEncoderSettings BbCameraSession::videoSettings() const +{ + return m_videoEncoderSettings; +} + +void BbCameraSession::setVideoSettings(const QVideoEncoderSettings &settings) +{ + m_videoEncoderSettings = settings; +} + +QAudioEncoderSettings BbCameraSession::audioSettings() const +{ + return m_audioEncoderSettings; +} + +void BbCameraSession::setAudioSettings(const QAudioEncoderSettings &settings) +{ + m_audioEncoderSettings = settings; +} + +void BbCameraSession::updateReadyForCapture() +{ + emit readyForCaptureChanged(isReadyForCapture()); +} + +void BbCameraSession::imageCaptured(int requestId, const QImage &rawImage, const QString &fileName) +{ + QTransform transform; + + // subtract out the native rotation + transform.rotate(m_nativeCameraOrientation); + + // subtract out the current device orientation + if (m_device == cameraIdentifierRear()) + transform.rotate(360 - m_orientationHandler->orientation()); + else + transform.rotate(m_orientationHandler->orientation()); + + const QImage image = rawImage.transformed(transform); + + // Generate snap preview as downscaled image + { + QSize previewSize = image.size(); + int downScaleSteps = 0; + while (previewSize.width() > 800 && downScaleSteps < 8) { + previewSize.rwidth() /= 2; + previewSize.rheight() /= 2; + downScaleSteps++; + } + + const QImage snapPreview = image.scaled(previewSize); + + emit imageCaptured(requestId, snapPreview); + } + + if (m_captureDestination & QCameraImageCapture::CaptureToBuffer) { + QVideoFrame frame(image); + + emit imageAvailable(requestId, frame); + } + + if (m_captureDestination & QCameraImageCapture::CaptureToFile) { + const QString actualFileName = m_mediaStorageLocation.generateFileName(fileName, + QCamera::CaptureStillImage, + QLatin1String("IMG_"), + QLatin1String("jpg")); + + QFile file(actualFileName); + if (file.open(QFile::WriteOnly)) { + if (image.save(&file, "JPG")) { + emit imageSaved(requestId, actualFileName); + } else { + emit imageCaptureError(requestId, QCameraImageCapture::OutOfSpaceError, file.errorString()); + } + } else { + const QString errorMessage = tr("Could not open destination file:\n%1").arg(actualFileName); + emit imageCaptureError(requestId, QCameraImageCapture::ResourceError, errorMessage); + } + } +} + +void BbCameraSession::handleVideoRecordingPaused() +{ + //TODO: implement once BB10 API supports pausing a video +} + +void BbCameraSession::handleVideoRecordingResumed() +{ + if (m_videoStatus == QMediaRecorder::StartingStatus) { + m_videoStatus = QMediaRecorder::RecordingStatus; + emit videoStatusChanged(m_videoStatus); + + m_videoRecordingDuration.restart(); + } +} + +void BbCameraSession::deviceOrientationChanged(int angle) +{ + if (m_handle != CAMERA_HANDLE_INVALID) + camera_set_device_orientation(m_handle, angle); +} + +void BbCameraSession::handleCameraPowerUp() +{ + stopViewFinder(); + startViewFinder(); +} + +void BbCameraSession::viewfinderFrameGrabbed(const QImage &image) +{ + QTransform transform; + + transform.rotate(m_nativeCameraOrientation); + + QImage frame = image.copy().transformed(transform); + if (m_device == cameraIdentifierFront()) + frame = frame.mirrored(true, false); + + QMutexLocker locker(&m_surfaceMutex); + if (m_surface) { + if (frame.size() != m_surface->surfaceFormat().frameSize()) { + m_surface->stop(); + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + } + + QVideoFrame videoFrame(frame); + + m_surface->present(videoFrame); + } +} + +bool BbCameraSession::openCamera() +{ + if (m_handle != CAMERA_HANDLE_INVALID) // camera is already open + return true; + + m_status = QCamera::LoadingStatus; + emit statusChanged(m_status); + + camera_unit_t unit = CAMERA_UNIT_REAR; + if (m_device == cameraIdentifierFront()) + unit = CAMERA_UNIT_FRONT; + else if (m_device == cameraIdentifierRear()) + unit = CAMERA_UNIT_REAR; + else if (m_device == cameraIdentifierDesktop()) + unit = CAMERA_UNIT_DESKTOP; + + camera_error_t result = camera_open(unit, CAMERA_MODE_RW, &m_handle); + if (result != CAMERA_EOK) { + m_handle = CAMERA_HANDLE_INVALID; + m_status = QCamera::UnloadedStatus; + emit statusChanged(m_status); + + qWarning() << "Unable to open camera:" << result; + emit error(QCamera::CameraError, tr("Unable to open camera")); + return false; + } + + result = camera_get_native_orientation(m_handle, &m_nativeCameraOrientation); + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve native camera orientation:" << result; + emit error(QCamera::CameraError, tr("Unable to retrieve native camera orientation")); + return false; + } + + m_previewIsVideo = camera_has_feature(m_handle, CAMERA_FEATURE_PREVIEWISVIDEO); + + m_status = QCamera::LoadedStatus; + emit statusChanged(m_status); + + emit cameraOpened(); + + return true; +} + +void BbCameraSession::closeCamera() +{ + if (m_handle == CAMERA_HANDLE_INVALID) // camera is closed already + return; + + m_status = QCamera::UnloadingStatus; + emit statusChanged(m_status); + + const camera_error_t result = camera_close(m_handle); + if (result != CAMERA_EOK) { + m_status = QCamera::LoadedStatus; + emit statusChanged(m_status); + + qWarning() << "Unable to close camera:" << result; + emit error(QCamera::CameraError, tr("Unable to close camera")); + return; + } + + m_handle = CAMERA_HANDLE_INVALID; + + m_status = QCamera::UnloadedStatus; + emit statusChanged(m_status); +} + +static void viewFinderStatusCallback(camera_handle_t handle, camera_devstatus_t status, uint16_t value, void *context) +{ + Q_UNUSED(handle) + + if (status == CAMERA_STATUS_FOCUS_CHANGE) { + BbCameraSession *session = static_cast<BbCameraSession*>(context); + QMetaObject::invokeMethod(session, "focusStatusChanged", Qt::QueuedConnection, Q_ARG(int, value)); + return; + } +#ifndef Q_OS_BLACKBERRY_TABLET + else if (status == CAMERA_STATUS_POWERUP) { + BbCameraSession *session = static_cast<BbCameraSession*>(context); + QMetaObject::invokeMethod(session, "handleCameraPowerUp", Qt::QueuedConnection); + } +#endif +} + +bool BbCameraSession::startViewFinder() +{ + m_status = QCamera::StartingStatus; + emit statusChanged(m_status); + + QSize viewfinderResolution; + camera_error_t result = CAMERA_EOK; + if (m_captureMode & QCamera::CaptureStillImage) { + result = camera_start_photo_viewfinder(m_handle, 0, viewFinderStatusCallback, this); + viewfinderResolution = currentViewfinderResolution(QCamera::CaptureStillImage); + } else if (m_captureMode & QCamera::CaptureVideo) { + result = camera_start_video_viewfinder(m_handle, 0, viewFinderStatusCallback, this); + viewfinderResolution = currentViewfinderResolution(QCamera::CaptureVideo); + } + + if (result != CAMERA_EOK) { + qWarning() << "Unable to start viewfinder:" << result; + return false; + } + + const int angle = m_orientationHandler->orientation(); + + const QSize rotatedSize = ((angle == 0 || angle == 180) ? viewfinderResolution + : viewfinderResolution.transposed()); + + m_surfaceMutex.lock(); + if (m_surface) { + const bool ok = m_surface->start(QVideoSurfaceFormat(rotatedSize, QVideoFrame::Format_ARGB32)); + if (!ok) + qWarning() << "Unable to start camera viewfinder surface"; + } + m_surfaceMutex.unlock(); + + m_status = QCamera::ActiveStatus; + emit statusChanged(m_status); + + return true; +} + +void BbCameraSession::stopViewFinder() +{ + m_windowGrabber->stop(); + + m_status = QCamera::StoppingStatus; + emit statusChanged(m_status); + + m_surfaceMutex.lock(); + if (m_surface) { + m_surface->stop(); + } + m_surfaceMutex.unlock(); + + camera_error_t result = CAMERA_EOK; + if (m_captureMode & QCamera::CaptureStillImage) + result = camera_stop_photo_viewfinder(m_handle); + else if (m_captureMode & QCamera::CaptureVideo) + result = camera_stop_video_viewfinder(m_handle); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to stop viewfinder:" << result; + return; + } + + m_status = QCamera::LoadedStatus; + emit statusChanged(m_status); +} + +void BbCameraSession::applyConfiguration() +{ + if (m_captureMode & QCamera::CaptureStillImage) { + const QList<QSize> photoOutputResolutions = supportedResolutions(QCamera::CaptureStillImage); + + if (!m_imageEncoderSettings.resolution().isValid() || !photoOutputResolutions.contains(m_imageEncoderSettings.resolution())) + m_imageEncoderSettings.setResolution(photoOutputResolutions.first()); + + const QSize photoResolution = m_imageEncoderSettings.resolution(); + const qreal aspectRatio = static_cast<qreal>(photoResolution.width())/static_cast<qreal>(photoResolution.height()); + + // apply viewfinder configuration + QSize viewfinderResolution; + QList<QSize> sizes = supportedViewfinderResolutions(QCamera::CaptureStillImage); + std::reverse(sizes.begin(), sizes.end()); // use smallest possible resolution + foreach (const QSize &size, sizes) { + // search for viewfinder resolution with the same aspect ratio + if (qFuzzyCompare(aspectRatio, (static_cast<qreal>(size.width())/static_cast<qreal>(size.height())))) { + viewfinderResolution = size; + break; + } + } + + Q_ASSERT(viewfinderResolution.isValid()); + + const QByteArray windowId = QString().sprintf("qcamera_vf_%p", this).toLatin1(); + m_windowGrabber->setWindowId(windowId); + + const QByteArray windowGroupId = m_windowGrabber->windowGroupId(); + + camera_error_t result = camera_set_photovf_property(m_handle, + CAMERA_IMGPROP_WIN_GROUPID, windowGroupId.data(), + CAMERA_IMGPROP_WIN_ID, windowId.data(), + CAMERA_IMGPROP_WIDTH, viewfinderResolution.width(), + CAMERA_IMGPROP_HEIGHT, viewfinderResolution.height(), + CAMERA_IMGPROP_FORMAT, CAMERA_FRAMETYPE_NV12, + CAMERA_IMGPROP_ROTATION, 360 - m_nativeCameraOrientation); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to apply photo viewfinder settings:" << result; + return; + } + + + int jpegQuality = 100; + switch (m_imageEncoderSettings.quality()) { + case QMultimedia::VeryLowQuality: + jpegQuality = 20; + break; + case QMultimedia::LowQuality: + jpegQuality = 40; + break; + case QMultimedia::NormalQuality: + jpegQuality = 60; + break; + case QMultimedia::HighQuality: + jpegQuality = 80; + break; + case QMultimedia::VeryHighQuality: + jpegQuality = 100; + break; + } + + // apply photo configuration + result = camera_set_photo_property(m_handle, + CAMERA_IMGPROP_WIDTH, photoResolution.width(), + CAMERA_IMGPROP_HEIGHT, photoResolution.height(), + CAMERA_IMGPROP_JPEGQFACTOR, jpegQuality, + CAMERA_IMGPROP_ROTATION, 360 - m_nativeCameraOrientation); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to apply photo settings:" << result; + return; + } + + } else if (m_captureMode & QCamera::CaptureVideo) { + applyVideoSettings(); + } + + startViewFinder(); +} + +static void videoRecordingStatusCallback(camera_handle_t handle, camera_devstatus_t status, uint16_t value, void *context) +{ + Q_UNUSED(handle) + Q_UNUSED(value) + +#ifndef Q_OS_BLACKBERRY_TABLET + if (status == CAMERA_STATUS_VIDEO_PAUSE) { + BbCameraSession *session = static_cast<BbCameraSession*>(context); + QMetaObject::invokeMethod(session, "handleVideoRecordingPaused", Qt::QueuedConnection); + } else if (status == CAMERA_STATUS_VIDEO_RESUME) { + BbCameraSession *session = static_cast<BbCameraSession*>(context); + QMetaObject::invokeMethod(session, "handleVideoRecordingResumed", Qt::QueuedConnection); + } +#endif +} + +bool BbCameraSession::startVideoRecording() +{ + m_videoRecordingDuration.invalidate(); + + m_videoStatus = QMediaRecorder::StartingStatus; + emit videoStatusChanged(m_videoStatus); + + if (m_videoOutputLocation.isEmpty()) + m_videoOutputLocation = m_mediaStorageLocation.generateFileName(QLatin1String("VID_"), m_mediaStorageLocation.defaultDir(QCamera::CaptureVideo), QLatin1String("mp4")); + + emit actualLocationChanged(m_videoOutputLocation); + + const camera_error_t result = camera_start_video(m_handle, QFile::encodeName(m_videoOutputLocation), 0, videoRecordingStatusCallback, this); + if (result != CAMERA_EOK) { + m_videoStatus = QMediaRecorder::LoadedStatus; + emit videoStatusChanged(m_videoStatus); + + emit videoError(QMediaRecorder::ResourceError, tr("Unable to start video recording")); + return false; + } + + return true; +} + +void BbCameraSession::stopVideoRecording() +{ + m_videoStatus = QMediaRecorder::FinalizingStatus; + emit videoStatusChanged(m_videoStatus); + + const camera_error_t result = camera_stop_video(m_handle); + if (result != CAMERA_EOK) { + emit videoError(QMediaRecorder::ResourceError, tr("Unable to stop video recording")); + } + + m_videoStatus = QMediaRecorder::LoadedStatus; + emit videoStatusChanged(m_videoStatus); + + m_videoRecordingDuration.invalidate(); +} + +bool BbCameraSession::isCaptureModeSupported(camera_handle_t handle, QCamera::CaptureModes mode) const +{ + if (mode & QCamera::CaptureStillImage) + return camera_has_feature(handle, CAMERA_FEATURE_PHOTO); + + if (mode & QCamera::CaptureVideo) + return camera_has_feature(handle, CAMERA_FEATURE_VIDEO); + + return false; +} + +QList<QSize> BbCameraSession::supportedResolutions(QCamera::CaptureMode mode) const +{ + Q_ASSERT(m_handle != CAMERA_HANDLE_INVALID); + + QList<QSize> list; + + camera_error_t result = CAMERA_EOK; + camera_res_t resolutions[20]; + unsigned int supported = 0; + + if (mode == QCamera::CaptureStillImage) + result = camera_get_photo_output_resolutions(m_handle, CAMERA_FRAMETYPE_JPEG, 20, &supported, resolutions); + else if (mode == QCamera::CaptureVideo) + result = camera_get_video_output_resolutions(m_handle, 20, &supported, resolutions); + + if (result != CAMERA_EOK) + return list; + + for (unsigned int i = 0; i < supported; ++i) + list << QSize(resolutions[i].width, resolutions[i].height); + + return list; +} + +QList<QSize> BbCameraSession::supportedViewfinderResolutions(QCamera::CaptureMode mode) const +{ + Q_ASSERT(m_handle != CAMERA_HANDLE_INVALID); + + QList<QSize> list; + + camera_error_t result = CAMERA_EOK; + camera_res_t resolutions[20]; + unsigned int supported = 0; + + if (mode == QCamera::CaptureStillImage) + result = camera_get_photo_vf_resolutions(m_handle, 20, &supported, resolutions); + else if (mode == QCamera::CaptureVideo) + result = camera_get_video_vf_resolutions(m_handle, 20, &supported, resolutions); + + if (result != CAMERA_EOK) + return list; + + for (unsigned int i = 0; i < supported; ++i) + list << QSize(resolutions[i].width, resolutions[i].height); + + return list; +} + +QSize BbCameraSession::currentViewfinderResolution(QCamera::CaptureMode mode) const +{ + Q_ASSERT(m_handle != CAMERA_HANDLE_INVALID); + + camera_error_t result = CAMERA_EOK; + int width = 0; + int height = 0; + + if (mode == QCamera::CaptureStillImage) + result = camera_get_photovf_property(m_handle, CAMERA_IMGPROP_WIDTH, &width, + CAMERA_IMGPROP_HEIGHT, &height); + else if (mode == QCamera::CaptureVideo) + result = camera_get_videovf_property(m_handle, CAMERA_IMGPROP_WIDTH, &width, + CAMERA_IMGPROP_HEIGHT, &height); + + if (result != CAMERA_EOK) + return QSize(); + + return QSize(width, height); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcamerasession.h b/src/plugins/qnx/camera/bbcamerasession.h new file mode 100644 index 000000000..e757a83c3 --- /dev/null +++ b/src/plugins/qnx/camera/bbcamerasession.h @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** 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 BBCAMERASESSION_H +#define BBCAMERASESSION_H + +#include "bbmediastoragelocation.h" + +#include <QCamera> +#include <QCameraImageCapture> +#include <QCameraViewfinderSettingsControl> +#include <QElapsedTimer> +#include <QMediaRecorder> +#include <QMutex> +#include <QObject> +#include <QPointer> + +#include <camera/camera_api.h> + +QT_BEGIN_NAMESPACE + +class BbCameraOrientationHandler; +class WindowGrabber; + +class BbCameraSession : public QObject +{ + Q_OBJECT +public: + explicit BbCameraSession(QObject *parent = 0); + ~BbCameraSession(); + + camera_handle_t handle() const; + + // camera control + QCamera::State state() const; + void setState(QCamera::State state); + QCamera::Status status() const; + QCamera::CaptureModes captureMode() const; + void setCaptureMode(QCamera::CaptureModes); + bool isCaptureModeSupported(QCamera::CaptureModes mode) const; + + // video device selector control + static QByteArray cameraIdentifierFront(); + static QByteArray cameraIdentifierRear(); + static QByteArray cameraIdentifierDesktop(); + + void setDevice(const QByteArray &device); + QByteArray device() const; + + // video renderer control + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + // image capture control + bool isReadyForCapture() const; + QCameraImageCapture::DriveMode driveMode() const; + void setDriveMode(QCameraImageCapture::DriveMode mode); + int capture(const QString &fileName); + void cancelCapture(); + + // capture destination control + bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const; + QCameraImageCapture::CaptureDestinations captureDestination() const; + void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination); + + // image encoder control + QList<QSize> supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const; + QImageEncoderSettings imageSettings() const; + void setImageSettings(const QImageEncoderSettings &settings); + + // media recorder control + QUrl outputLocation() const; + bool setOutputLocation(const QUrl &location); + QMediaRecorder::State videoState() const; + void setVideoState(QMediaRecorder::State state); + QMediaRecorder::Status videoStatus() const; + qint64 duration() const; + void applyVideoSettings(); + + // video encoder settings control + QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const; + QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const; + QVideoEncoderSettings videoSettings() const; + void setVideoSettings(const QVideoEncoderSettings &settings); + + // audio encoder settings control + QAudioEncoderSettings audioSettings() const; + void setAudioSettings(const QAudioEncoderSettings &settings); + +Q_SIGNALS: + // camera control + void statusChanged(QCamera::Status); + void stateChanged(QCamera::State); + void error(int error, const QString &errorString); + void captureModeChanged(QCamera::CaptureModes); + + // image capture control + void readyForCaptureChanged(bool); + void imageExposed(int id); + void imageCaptured(int id, const QImage &preview); + void imageMetadataAvailable(int id, const QString &key, const QVariant &value); + void imageAvailable(int id, const QVideoFrame &buffer); + void imageSaved(int id, const QString &fileName); + void imageCaptureError(int id, int error, const QString &errorString); + + // capture destination control + void captureDestinationChanged(QCameraImageCapture::CaptureDestinations destination); + + // media recorder control + void videoStateChanged(QMediaRecorder::State state); + void videoStatusChanged(QMediaRecorder::Status status); + void durationChanged(qint64 duration); + void actualLocationChanged(const QUrl &location); + void videoError(int error, const QString &errorString); + + void cameraOpened(); + void focusStatusChanged(int status); + +private slots: + void updateReadyForCapture(); + void imageCaptured(int, const QImage&, const QString&); + void handleVideoRecordingPaused(); + void handleVideoRecordingResumed(); + void deviceOrientationChanged(int); + void handleCameraPowerUp(); + void viewfinderFrameGrabbed(const QImage &image); + void applyConfiguration(); + +private: + bool openCamera(); + void closeCamera(); + bool startViewFinder(); + void stopViewFinder(); + bool startVideoRecording(); + void stopVideoRecording(); + + bool isCaptureModeSupported(camera_handle_t handle, QCamera::CaptureModes mode) const; + QList<QSize> supportedResolutions(QCamera::CaptureMode mode) const; + QList<QSize> supportedViewfinderResolutions(QCamera::CaptureMode mode) const; + QSize currentViewfinderResolution(QCamera::CaptureMode mode) const; + + quint32 m_nativeCameraOrientation; + BbCameraOrientationHandler* m_orientationHandler; + + QCamera::Status m_status; + QCamera::State m_state; + QCamera::CaptureModes m_captureMode; + + QByteArray m_device; + bool m_previewIsVideo; + + QPointer<QAbstractVideoSurface> m_surface; + QMutex m_surfaceMutex; + + QCameraImageCapture::DriveMode m_captureImageDriveMode; + int m_lastImageCaptureId; + QCameraImageCapture::CaptureDestinations m_captureDestination; + + QImageEncoderSettings m_imageEncoderSettings; + + QString m_videoOutputLocation; + QMediaRecorder::State m_videoState; + QMediaRecorder::Status m_videoStatus; + QElapsedTimer m_videoRecordingDuration; + + QVideoEncoderSettings m_videoEncoderSettings; + QAudioEncoderSettings m_audioEncoderSettings; + + BbMediaStorageLocation m_mediaStorageLocation; + + camera_handle_t m_handle; + + WindowGrabber* m_windowGrabber; +}; + +QDebug operator<<(QDebug debug, camera_error_t error); + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameravideoencodersettingscontrol.cpp b/src/plugins/qnx/camera/bbcameravideoencodersettingscontrol.cpp new file mode 100644 index 000000000..eae448e5b --- /dev/null +++ b/src/plugins/qnx/camera/bbcameravideoencodersettingscontrol.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 "bbcameravideoencodersettingscontrol.h" + +#include "bbcamerasession.h" + +QT_BEGIN_NAMESPACE + +BbCameraVideoEncoderSettingsControl::BbCameraVideoEncoderSettingsControl(BbCameraSession *session, QObject *parent) + : QVideoEncoderSettingsControl(parent) + , m_session(session) +{ +} + +QList<QSize> BbCameraVideoEncoderSettingsControl::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const +{ + return m_session->supportedResolutions(settings, continuous); +} + +QList<qreal> BbCameraVideoEncoderSettingsControl::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const +{ + return m_session->supportedFrameRates(settings, continuous); +} + +QStringList BbCameraVideoEncoderSettingsControl::supportedVideoCodecs() const +{ + return QStringList() << QLatin1String("none") << QLatin1String("avc1") << QLatin1String("h264"); +} + +QString BbCameraVideoEncoderSettingsControl::videoCodecDescription(const QString &codecName) const +{ + if (codecName == QLatin1String("none")) + return tr("No compression"); + else if (codecName == QLatin1String("avc1")) + return tr("AVC1 compression"); + else if (codecName == QLatin1String("h264")) + return tr("H264 compression"); + + return QString(); +} + +QVideoEncoderSettings BbCameraVideoEncoderSettingsControl::videoSettings() const +{ + return m_session->videoSettings(); +} + +void BbCameraVideoEncoderSettingsControl::setVideoSettings(const QVideoEncoderSettings &settings) +{ + m_session->setVideoSettings(settings); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameravideoencodersettingscontrol.h b/src/plugins/qnx/camera/bbcameravideoencodersettingscontrol.h new file mode 100644 index 000000000..8ecf49c85 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameravideoencodersettingscontrol.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 BBCAMERAVIDEOENCODERSETTINGSCONTROL_H +#define BBCAMERAVIDEOENCODERSETTINGSCONTROL_H + +#include <qvideoencodersettingscontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraVideoEncoderSettingsControl : public QVideoEncoderSettingsControl +{ + Q_OBJECT +public: + explicit BbCameraVideoEncoderSettingsControl(BbCameraSession *session, QObject *parent = 0); + + QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QStringList supportedVideoCodecs() const Q_DECL_OVERRIDE; + QString videoCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE; + QVideoEncoderSettings videoSettings() const Q_DECL_OVERRIDE; + void setVideoSettings(const QVideoEncoderSettings &settings) Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcameraviewfindersettingscontrol.cpp b/src/plugins/qnx/camera/bbcameraviewfindersettingscontrol.cpp new file mode 100644 index 000000000..5c7671e80 --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraviewfindersettingscontrol.cpp @@ -0,0 +1,249 @@ +/**************************************************************************** +** +** 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 "bbcameraviewfindersettingscontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbCameraViewfinderSettingsControl::BbCameraViewfinderSettingsControl(BbCameraSession *session, QObject *parent) + : QCameraViewfinderSettingsControl(parent) + , m_session(session) +{ +} + +bool BbCameraViewfinderSettingsControl::isViewfinderParameterSupported(ViewfinderParameter parameter) const +{ + switch (parameter) { + case QCameraViewfinderSettingsControl::Resolution: + return true; + case QCameraViewfinderSettingsControl::PixelAspectRatio: + return false; + case QCameraViewfinderSettingsControl::MinimumFrameRate: + return true; + case QCameraViewfinderSettingsControl::MaximumFrameRate: + return true; + case QCameraViewfinderSettingsControl::PixelFormat: + return true; + default: + return false; + } +} + +QVariant BbCameraViewfinderSettingsControl::viewfinderParameter(ViewfinderParameter parameter) const +{ + if (parameter == QCameraViewfinderSettingsControl::Resolution) { + camera_error_t result = CAMERA_EOK; + unsigned int width = 0; + unsigned int height = 0; + + if (m_session->captureMode() & QCamera::CaptureStillImage) { + result = camera_get_photovf_property(m_session->handle(), CAMERA_IMGPROP_WIDTH, &width, + CAMERA_IMGPROP_HEIGHT, &height); + } else if (m_session->captureMode() & QCamera::CaptureVideo) { + result = camera_get_videovf_property(m_session->handle(), CAMERA_IMGPROP_WIDTH, &width, + CAMERA_IMGPROP_HEIGHT, &height); + } + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve resolution of viewfinder:" << result; + return QVariant(); + } + + return QSize(width, height); + + } else if (parameter == QCameraViewfinderSettingsControl::MinimumFrameRate) { + camera_error_t result = CAMERA_EOK; + double minimumFrameRate = 0; + + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_get_photovf_property(m_session->handle(), CAMERA_IMGPROP_MINFRAMERATE, &minimumFrameRate); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_get_videovf_property(m_session->handle(), CAMERA_IMGPROP_MINFRAMERATE, &minimumFrameRate); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve minimum framerate of viewfinder:" << result; + return QVariant(); + } + + return QVariant(static_cast<qreal>(minimumFrameRate)); + + } else if (parameter == QCameraViewfinderSettingsControl::MaximumFrameRate) { + camera_error_t result = CAMERA_EOK; + double maximumFrameRate = 0; + + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_get_photovf_property(m_session->handle(), CAMERA_IMGPROP_FRAMERATE, &maximumFrameRate); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_get_videovf_property(m_session->handle(), CAMERA_IMGPROP_FRAMERATE, &maximumFrameRate); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve maximum framerate of viewfinder:" << result; + return QVariant(); + } + + return QVariant(static_cast<qreal>(maximumFrameRate)); + } else if (parameter == QCameraViewfinderSettingsControl::PixelFormat) { + camera_error_t result = CAMERA_EOK; + camera_frametype_t format = CAMERA_FRAMETYPE_UNSPECIFIED; + + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_get_photovf_property(m_session->handle(), CAMERA_IMGPROP_FORMAT, &format); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_get_videovf_property(m_session->handle(), CAMERA_IMGPROP_FORMAT, &format); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve pixel format of viewfinder:" << result; + return QVariant(); + } + + switch (format) { + case CAMERA_FRAMETYPE_UNSPECIFIED: + return QVideoFrame::Format_Invalid; + case CAMERA_FRAMETYPE_NV12: + return QVideoFrame::Format_NV12; + case CAMERA_FRAMETYPE_RGB8888: + return QVideoFrame::Format_ARGB32; + case CAMERA_FRAMETYPE_RGB888: + return QVideoFrame::Format_RGB24; + case CAMERA_FRAMETYPE_JPEG: + return QVideoFrame::Format_Jpeg; + case CAMERA_FRAMETYPE_GRAY8: + return QVideoFrame::Format_Y8; + case CAMERA_FRAMETYPE_METADATA: + return QVideoFrame::Format_Invalid; + case CAMERA_FRAMETYPE_BAYER: + return QVideoFrame::Format_Invalid; + case CAMERA_FRAMETYPE_CBYCRY: + return QVideoFrame::Format_Invalid; +#ifndef Q_OS_BLACKBERRY_TABLET + case CAMERA_FRAMETYPE_COMPRESSEDVIDEO: + return QVideoFrame::Format_Invalid; + case CAMERA_FRAMETYPE_COMPRESSEDAUDIO: + return QVideoFrame::Format_Invalid; +#endif + default: + return QVideoFrame::Format_Invalid; + } + } + + return QVariant(); +} + +void BbCameraViewfinderSettingsControl::setViewfinderParameter(ViewfinderParameter parameter, const QVariant &value) +{ + if (parameter == QCameraViewfinderSettingsControl::Resolution) { + camera_error_t result = CAMERA_EOK; + const QSize size = value.toSize(); + + if (m_session->captureMode() & QCamera::CaptureStillImage) { + result = camera_set_photovf_property(m_session->handle(), CAMERA_IMGPROP_WIDTH, size.width(), + CAMERA_IMGPROP_HEIGHT, size.height()); + } else if (m_session->captureMode() & QCamera::CaptureVideo) { + result = camera_set_videovf_property(m_session->handle(), CAMERA_IMGPROP_WIDTH, size.width(), + CAMERA_IMGPROP_HEIGHT, size.height()); + } + + if (result != CAMERA_EOK) + qWarning() << "Unable to set resolution of viewfinder:" << result; + + } else if (parameter == QCameraViewfinderSettingsControl::MinimumFrameRate) { + camera_error_t result = CAMERA_EOK; + const double minimumFrameRate = value.toReal(); + + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_set_photovf_property(m_session->handle(), CAMERA_IMGPROP_MINFRAMERATE, minimumFrameRate); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_set_videovf_property(m_session->handle(), CAMERA_IMGPROP_MINFRAMERATE, minimumFrameRate); + + if (result != CAMERA_EOK) + qWarning() << "Unable to set minimum framerate of viewfinder:" << result; + + } else if (parameter == QCameraViewfinderSettingsControl::MaximumFrameRate) { + camera_error_t result = CAMERA_EOK; + const double maximumFrameRate = value.toReal(); + + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_set_photovf_property(m_session->handle(), CAMERA_IMGPROP_FRAMERATE, maximumFrameRate); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_set_videovf_property(m_session->handle(), CAMERA_IMGPROP_FRAMERATE, maximumFrameRate); + + if (result != CAMERA_EOK) + qWarning() << "Unable to set maximum framerate of viewfinder:" << result; + + } else if (parameter == QCameraViewfinderSettingsControl::PixelFormat) { + camera_error_t result = CAMERA_EOK; + camera_frametype_t format = CAMERA_FRAMETYPE_UNSPECIFIED; + + switch (value.value<QVideoFrame::PixelFormat>()) { + case QVideoFrame::Format_NV12: + format = CAMERA_FRAMETYPE_NV12; + break; + case QVideoFrame::Format_ARGB32: + format = CAMERA_FRAMETYPE_RGB8888; + break; + case QVideoFrame::Format_RGB24: + format = CAMERA_FRAMETYPE_RGB888; + break; + case QVideoFrame::Format_Jpeg: + format = CAMERA_FRAMETYPE_JPEG; + break; + case QVideoFrame::Format_Y8: + format = CAMERA_FRAMETYPE_GRAY8; + break; + default: + format = CAMERA_FRAMETYPE_UNSPECIFIED; + break; + } + + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_set_photovf_property(m_session->handle(), CAMERA_IMGPROP_FORMAT, format); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_set_videovf_property(m_session->handle(), CAMERA_IMGPROP_FORMAT, format); + + if (result != CAMERA_EOK) + qWarning() << "Unable to set pixel format of viewfinder:" << result; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcameraviewfindersettingscontrol.h b/src/plugins/qnx/camera/bbcameraviewfindersettingscontrol.h new file mode 100644 index 000000000..f1434c31c --- /dev/null +++ b/src/plugins/qnx/camera/bbcameraviewfindersettingscontrol.h @@ -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 BBCAMERAVIEWVINDERSETTINGSCONTROL_H +#define BBCAMERAVIEWVINDERSETTINGSCONTROL_H + +#include <qcameraviewfindersettingscontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraViewfinderSettingsControl : public QCameraViewfinderSettingsControl +{ + Q_OBJECT +public: + explicit BbCameraViewfinderSettingsControl(BbCameraSession *session, QObject *parent = 0); + + bool isViewfinderParameterSupported(ViewfinderParameter parameter) const Q_DECL_OVERRIDE; + QVariant viewfinderParameter(ViewfinderParameter parameter) const Q_DECL_OVERRIDE; + void setViewfinderParameter(ViewfinderParameter parameter, const QVariant &value) Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbcamerazoomcontrol.cpp b/src/plugins/qnx/camera/bbcamerazoomcontrol.cpp new file mode 100644 index 000000000..f73cf000a --- /dev/null +++ b/src/plugins/qnx/camera/bbcamerazoomcontrol.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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 "bbcamerazoomcontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbCameraZoomControl::BbCameraZoomControl(BbCameraSession *session, QObject *parent) + : QCameraZoomControl(parent) + , m_session(session) + , m_minimumZoomFactor(1.0) + , m_maximumZoomFactor(1.0) + , m_supportsSmoothZoom(false) + , m_requestedZoomFactor(1.0) +{ + connect(m_session, SIGNAL(statusChanged(QCamera::Status)), this, SLOT(statusChanged(QCamera::Status))); +} + +qreal BbCameraZoomControl::maximumOpticalZoom() const +{ + //TODO: optical zoom support not available in BB10 API yet + return 1.0; +} + +qreal BbCameraZoomControl::maximumDigitalZoom() const +{ + return m_maximumZoomFactor; +} + +qreal BbCameraZoomControl::requestedOpticalZoom() const +{ + //TODO: optical zoom support not available in BB10 API yet + return 1.0; +} + +qreal BbCameraZoomControl::requestedDigitalZoom() const +{ + return currentDigitalZoom(); +} + +qreal BbCameraZoomControl::currentOpticalZoom() const +{ + //TODO: optical zoom support not available in BB10 API yet + return 1.0; +} + +qreal BbCameraZoomControl::currentDigitalZoom() const +{ + if (m_session->status() != QCamera::ActiveStatus) + return 1.0; + + unsigned int zoomFactor = 0; + camera_error_t result = CAMERA_EOK; + + if (m_session->captureMode() & QCamera::CaptureStillImage) + result = camera_get_photovf_property(m_session->handle(), CAMERA_IMGPROP_ZOOMFACTOR, &zoomFactor); + else if (m_session->captureMode() & QCamera::CaptureVideo) + result = camera_get_videovf_property(m_session->handle(), CAMERA_IMGPROP_ZOOMFACTOR, &zoomFactor); + + if (result != CAMERA_EOK) + return 1.0; + + return zoomFactor; +} + +void BbCameraZoomControl::zoomTo(qreal optical, qreal digital) +{ + Q_UNUSED(optical) + + if (m_session->status() != QCamera::ActiveStatus) + return; + + const qreal actualZoom = qBound(m_minimumZoomFactor, digital, m_maximumZoomFactor); + + const camera_error_t result = camera_set_zoom(m_session->handle(), actualZoom, false); + + if (result != CAMERA_EOK) { + qWarning() << "Unable to change zoom factor:" << result; + return; + } + + if (m_requestedZoomFactor != digital) { + m_requestedZoomFactor = digital; + emit requestedDigitalZoomChanged(m_requestedZoomFactor); + } + + emit currentDigitalZoomChanged(actualZoom); +} + +void BbCameraZoomControl::statusChanged(QCamera::Status status) +{ + if (status == QCamera::ActiveStatus) { + // retrieve information about zoom limits + unsigned int maximumZoomLimit = 0; + unsigned int minimumZoomLimit = 0; + bool smoothZoom = false; + + const camera_error_t result = camera_get_zoom_limits(m_session->handle(), &maximumZoomLimit, &minimumZoomLimit, &smoothZoom); + if (result == CAMERA_EOK) { + const qreal oldMaximumZoomFactor = m_maximumZoomFactor; + m_maximumZoomFactor = maximumZoomLimit; + + if (oldMaximumZoomFactor != m_maximumZoomFactor) + emit maximumDigitalZoomChanged(m_maximumZoomFactor); + + m_minimumZoomFactor = minimumZoomLimit; + m_supportsSmoothZoom = smoothZoom; + } else { + m_maximumZoomFactor = 1.0; + m_minimumZoomFactor = 1.0; + m_supportsSmoothZoom = false; + } + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbcamerazoomcontrol.h b/src/plugins/qnx/camera/bbcamerazoomcontrol.h new file mode 100644 index 000000000..a1fecab89 --- /dev/null +++ b/src/plugins/qnx/camera/bbcamerazoomcontrol.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 BBCAMERAZOOMCONTROL_H +#define BBCAMERAZOOMCONTROL_H + +#include <qcamera.h> +#include <qcamerazoomcontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbCameraZoomControl : public QCameraZoomControl +{ + Q_OBJECT +public: + explicit BbCameraZoomControl(BbCameraSession *session, QObject *parent = 0); + + qreal maximumOpticalZoom() const Q_DECL_OVERRIDE; + qreal maximumDigitalZoom() const Q_DECL_OVERRIDE; + qreal requestedOpticalZoom() const Q_DECL_OVERRIDE; + qreal requestedDigitalZoom() const Q_DECL_OVERRIDE; + qreal currentOpticalZoom() const Q_DECL_OVERRIDE; + qreal currentDigitalZoom() const Q_DECL_OVERRIDE; + void zoomTo(qreal optical, qreal digital) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void statusChanged(QCamera::Status status); + +private: + BbCameraSession *m_session; + + qreal m_minimumZoomFactor; + qreal m_maximumZoomFactor; + bool m_supportsSmoothZoom; + qreal m_requestedZoomFactor; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/audio/qnxaudioplugin.cpp b/src/plugins/qnx/camera/bbimageencodercontrol.cpp index f63474f90..1265b9ca4 100644 --- a/src/plugins/qnx/audio/qnxaudioplugin.cpp +++ b/src/plugins/qnx/camera/bbimageencodercontrol.cpp @@ -38,51 +38,44 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "bbimageencodercontrol.h" -#include "qnxaudioplugin.h" - -#include "qnxaudiodeviceinfo.h" -#include "qnxaudioinput.h" -#include "qnxaudiooutput.h" - -#include <sys/asoundlib.h> - -static const char *INPUT_ID = "QnxAudioInput"; -static const char *OUTPUT_ID = "QnxAudioOutput"; +#include "bbcamerasession.h" QT_BEGIN_NAMESPACE -QnxAudioPlugin::QnxAudioPlugin(QObject *parent) - : QAudioSystemPlugin(parent) +BbImageEncoderControl::BbImageEncoderControl(BbCameraSession *session, QObject *parent) + : QImageEncoderControl(parent) + , m_session(session) { } -QList<QByteArray> QnxAudioPlugin::availableDevices(QAudio::Mode mode) const +QStringList BbImageEncoderControl::supportedImageCodecs() const { - if (mode == QAudio::AudioOutput) - return QList<QByteArray>() << OUTPUT_ID; - else - return QList<QByteArray>() << INPUT_ID; + return QStringList() << QLatin1String("jpeg"); +} + +QString BbImageEncoderControl::imageCodecDescription(const QString &codecName) const +{ + if (codecName == QLatin1String("jpeg")) + return tr("JPEG image"); + + return QString(); } -QAbstractAudioInput *QnxAudioPlugin::createInput(const QByteArray &device) +QList<QSize> BbImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const { - Q_ASSERT(device == INPUT_ID); - Q_UNUSED(device); - return new QnxAudioInput(); + return m_session->supportedResolutions(settings, continuous); } -QAbstractAudioOutput *QnxAudioPlugin::createOutput(const QByteArray &device) +QImageEncoderSettings BbImageEncoderControl::imageSettings() const { - Q_ASSERT(device == OUTPUT_ID); - Q_UNUSED(device); - return new QnxAudioOutput(); + return m_session->imageSettings(); } -QAbstractAudioDeviceInfo *QnxAudioPlugin::createDeviceInfo(const QByteArray &device, QAudio::Mode mode) +void BbImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings) { - Q_ASSERT(device == OUTPUT_ID || device == INPUT_ID); - return new QnxAudioDeviceInfo(device, mode); + m_session->setImageSettings(settings); } QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbimageencodercontrol.h b/src/plugins/qnx/camera/bbimageencodercontrol.h new file mode 100644 index 000000000..4db2e7def --- /dev/null +++ b/src/plugins/qnx/camera/bbimageencodercontrol.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 BBIMAGEENCODERCONTROL_H +#define BBIMAGEENCODERCONTROL_H + +#include <qimageencodercontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbImageEncoderControl : public QImageEncoderControl +{ + Q_OBJECT +public: + explicit BbImageEncoderControl(BbCameraSession *session, QObject *parent = 0); + + QStringList supportedImageCodecs() const Q_DECL_OVERRIDE; + QString imageCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE; + QList<QSize> supportedResolutions(const QImageEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QImageEncoderSettings imageSettings() const Q_DECL_OVERRIDE; + void setImageSettings(const QImageEncoderSettings &settings) Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbmediastoragelocation.cpp b/src/plugins/qnx/camera/bbmediastoragelocation.cpp new file mode 100644 index 000000000..3d939ce4f --- /dev/null +++ b/src/plugins/qnx/camera/bbmediastoragelocation.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** 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 "bbmediastoragelocation.h" + +#include <QStandardPaths> + +QT_BEGIN_NAMESPACE + +BbMediaStorageLocation::BbMediaStorageLocation() +{ +} + +QDir BbMediaStorageLocation::defaultDir(QCamera::CaptureMode mode) const +{ + QStringList dirCandidates; + + dirCandidates << QLatin1String("shared/camera"); + + if (mode == QCamera::CaptureVideo) { + dirCandidates << QStandardPaths::writableLocation(QStandardPaths::MoviesLocation); + } else { + dirCandidates << QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); + } + + dirCandidates << QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + dirCandidates << QDir::homePath(); + dirCandidates << QDir::currentPath(); + dirCandidates << QDir::tempPath(); + + Q_FOREACH (const QString &path, dirCandidates) { + if (QFileInfo(path).isWritable()) + return QDir(path); + } + + return QDir(); +} + +QString BbMediaStorageLocation::generateFileName(const QString &requestedName, QCamera::CaptureMode mode, const QString &prefix, const QString &extension) const +{ + if (requestedName.isEmpty()) + return generateFileName(prefix, defaultDir(mode), extension); + + if (QFileInfo(requestedName).isDir()) + return generateFileName(prefix, QDir(requestedName), extension); + + return requestedName; +} + +QString BbMediaStorageLocation::generateFileName(const QString &prefix, const QDir &dir, const QString &extension) const +{ + const QString lastMediaKey = dir.absolutePath() + QLatin1Char(' ') + prefix + QLatin1Char(' ') + extension; + qint64 lastMediaIndex = m_lastUsedIndex.value(lastMediaKey, 0); + + if (lastMediaIndex == 0) { + // first run, find the maximum media number during the fist capture + Q_FOREACH (const QString &fileName, dir.entryList(QStringList() << QString("%1*.%2").arg(prefix).arg(extension))) { + const qint64 mediaIndex = fileName.mid(prefix.length(), fileName.size() - prefix.length() - extension.length() - 1).toInt(); + lastMediaIndex = qMax(lastMediaIndex, mediaIndex); + } + } + + // don't just rely on cached lastMediaIndex value, + // someone else may create a file after camera started + while (true) { + const QString name = QString("%1%2.%3").arg(prefix) + .arg(lastMediaIndex + 1, 8, 10, QLatin1Char('0')) + .arg(extension); + + const QString path = dir.absoluteFilePath(name); + if (!QFileInfo(path).exists()) { + m_lastUsedIndex[lastMediaKey] = lastMediaIndex + 1; + return path; + } + + lastMediaIndex++; + } + + return QString(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbmediastoragelocation.h b/src/plugins/qnx/camera/bbmediastoragelocation.h new file mode 100644 index 000000000..efa89c8ed --- /dev/null +++ b/src/plugins/qnx/camera/bbmediastoragelocation.h @@ -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 BBMEDIASTORAGELOCATION_H +#define BBMEDIASTORAGELOCATION_H + +#include <QCamera> +#include <QDir> +#include <QHash> + +QT_BEGIN_NAMESPACE + +class BbMediaStorageLocation +{ +public: + BbMediaStorageLocation(); + + QDir defaultDir(QCamera::CaptureMode mode) const; + + QString generateFileName(const QString &requestedName, QCamera::CaptureMode mode, const QString &prefix, const QString &extension) const; + QString generateFileName(const QString &prefix, const QDir &dir, const QString &extension) const; + +private: + mutable QHash<QString, qint64> m_lastUsedIndex; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbvideodeviceselectorcontrol.cpp b/src/plugins/qnx/camera/bbvideodeviceselectorcontrol.cpp new file mode 100644 index 000000000..6a6e9d3cd --- /dev/null +++ b/src/plugins/qnx/camera/bbvideodeviceselectorcontrol.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** 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 "bbvideodeviceselectorcontrol.h" + +#include "bbcamerasession.h" + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +BbVideoDeviceSelectorControl::BbVideoDeviceSelectorControl(BbCameraSession *session, QObject *parent) + : QVideoDeviceSelectorControl(parent) + , m_session(session) + , m_selected(0) +{ + enumerateDevices(&m_devices, &m_descriptions); + + // pre-select the rear camera + const int index = m_devices.indexOf(BbCameraSession::cameraIdentifierRear()); + if (index != -1) + m_selected = index; +} + +int BbVideoDeviceSelectorControl::deviceCount() const +{ + return m_devices.count(); +} + +QString BbVideoDeviceSelectorControl::deviceName(int index) const +{ + if (index < 0 || index >= m_devices.count()) + return QString(); + + return QString::fromUtf8(m_devices.at(index)); +} + +QString BbVideoDeviceSelectorControl::deviceDescription(int index) const +{ + if (index < 0 || index >= m_descriptions.count()) + return QString(); + + return m_descriptions.at(index); +} + +int BbVideoDeviceSelectorControl::defaultDevice() const +{ + return 0; +} + +int BbVideoDeviceSelectorControl::selectedDevice() const +{ + return m_selected; +} + +void BbVideoDeviceSelectorControl::enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions) +{ + devices->clear(); + descriptions->clear(); + + camera_unit_t cameras[10]; + + unsigned int knownCameras = 0; + const camera_error_t result = camera_get_supported_cameras(10, &knownCameras, cameras); + if (result != CAMERA_EOK) { + qWarning() << "Unable to retrieve supported camera types:" << result; + return; + } + + for (unsigned int i = 0; i < knownCameras; ++i) { + switch (cameras[i]) { + case CAMERA_UNIT_FRONT: + devices->append(BbCameraSession::cameraIdentifierFront()); + descriptions->append(tr("Front Camera")); + break; + case CAMERA_UNIT_REAR: + devices->append(BbCameraSession::cameraIdentifierRear()); + descriptions->append(tr("Rear Camera")); + break; + case CAMERA_UNIT_DESKTOP: + devices->append(BbCameraSession::cameraIdentifierDesktop()); + descriptions->append(tr("Desktop Camera")); + break; + default: + break; + } + } +} + +void BbVideoDeviceSelectorControl::setSelectedDevice(int index) +{ + if (index < 0 || index >= m_devices.count()) + return; + + if (!m_session) + return; + + const QByteArray device = m_devices.at(index); + if (device == m_session->device()) + return; + + m_session->setDevice(device); + m_selected = index; + + emit selectedDeviceChanged(QString::fromUtf8(device)); + emit selectedDeviceChanged(index); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbvideodeviceselectorcontrol.h b/src/plugins/qnx/camera/bbvideodeviceselectorcontrol.h new file mode 100644 index 000000000..1987f5491 --- /dev/null +++ b/src/plugins/qnx/camera/bbvideodeviceselectorcontrol.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 BBVIDEODEVICESELECTORCONTROL_H +#define BBVIDEODEVICESELECTORCONTROL_H + +#include <qvideodeviceselectorcontrol.h> +#include <QStringList> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbVideoDeviceSelectorControl : public QVideoDeviceSelectorControl +{ + Q_OBJECT +public: + explicit BbVideoDeviceSelectorControl(BbCameraSession *session, QObject *parent = 0); + + int deviceCount() const Q_DECL_OVERRIDE; + QString deviceName(int index) const Q_DECL_OVERRIDE; + QString deviceDescription(int index) const Q_DECL_OVERRIDE; + int defaultDevice() const Q_DECL_OVERRIDE; + int selectedDevice() const Q_DECL_OVERRIDE; + + static void enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions); + +public Q_SLOTS: + void setSelectedDevice(int index) Q_DECL_OVERRIDE; + +private: + BbCameraSession* m_session; + + QList<QByteArray> m_devices; + QStringList m_descriptions; + + int m_selected; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/bbvideorenderercontrol.cpp b/src/plugins/qnx/camera/bbvideorenderercontrol.cpp new file mode 100644 index 000000000..4fadf9afb --- /dev/null +++ b/src/plugins/qnx/camera/bbvideorenderercontrol.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** 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 "bbvideorenderercontrol.h" + +#include "bbcamerasession.h" + +QT_BEGIN_NAMESPACE + +BbVideoRendererControl::BbVideoRendererControl(BbCameraSession *session, QObject *parent) + : QVideoRendererControl(parent) + , m_session(session) +{ +} + +QAbstractVideoSurface* BbVideoRendererControl::surface() const +{ + return m_session->surface(); +} + +void BbVideoRendererControl::setSurface(QAbstractVideoSurface *surface) +{ + m_session->setSurface(surface); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/camera/bbvideorenderercontrol.h b/src/plugins/qnx/camera/bbvideorenderercontrol.h new file mode 100644 index 000000000..93b2b6475 --- /dev/null +++ b/src/plugins/qnx/camera/bbvideorenderercontrol.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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 BBVIDEORENDERERCONTROL_H +#define BBVIDEORENDERERCONTROL_H + +#include <qvideorenderercontrol.h> + +QT_BEGIN_NAMESPACE + +class BbCameraSession; + +class BbVideoRendererControl : public QVideoRendererControl +{ + Q_OBJECT +public: + explicit BbVideoRendererControl(BbCameraSession *session, QObject *parent = 0); + + QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE; + void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE; + +private: + BbCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/camera/camera.pri b/src/plugins/qnx/camera/camera.pri new file mode 100644 index 000000000..6665573b0 --- /dev/null +++ b/src/plugins/qnx/camera/camera.pri @@ -0,0 +1,53 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/bbcameraaudioencodersettingscontrol.h \ + $$PWD/bbcameracapturebufferformatcontrol.h \ + $$PWD/bbcameracapturedestinationcontrol.h \ + $$PWD/bbcameracontrol.h \ + $$PWD/bbcameraexposurecontrol.h \ + $$PWD/bbcameraflashcontrol.h \ + $$PWD/bbcamerafocuscontrol.h \ + $$PWD/bbcameraimagecapturecontrol.h \ + $$PWD/bbcameraimageprocessingcontrol.h \ + $$PWD/bbcameralockscontrol.h \ + $$PWD/bbcameramediarecordercontrol.h \ + $$PWD/bbcameraorientationhandler.h \ + $$PWD/bbcameraservice.h \ + $$PWD/bbcamerasession.h \ + $$PWD/bbcameravideoencodersettingscontrol.h \ + $$PWD/bbcameraviewfindersettingscontrol.h \ + $$PWD/bbcamerazoomcontrol.h \ + $$PWD/bbimageencodercontrol.h \ + $$PWD/bbmediastoragelocation.h \ + $$PWD/bbvideodeviceselectorcontrol.h \ + $$PWD/bbvideorenderercontrol.h + +SOURCES += \ + $$PWD/bbcameraaudioencodersettingscontrol.cpp \ + $$PWD/bbcameracapturebufferformatcontrol.cpp \ + $$PWD/bbcameracapturedestinationcontrol.cpp \ + $$PWD/bbcameracontrol.cpp \ + $$PWD/bbcameraexposurecontrol.cpp \ + $$PWD/bbcameraflashcontrol.cpp \ + $$PWD/bbcamerafocuscontrol.cpp \ + $$PWD/bbcameraimagecapturecontrol.cpp \ + $$PWD/bbcameraimageprocessingcontrol.cpp \ + $$PWD/bbcameralockscontrol.cpp \ + $$PWD/bbcameramediarecordercontrol.cpp \ + $$PWD/bbcameraorientationhandler.cpp \ + $$PWD/bbcameraservice.cpp \ + $$PWD/bbcamerasession.cpp \ + $$PWD/bbcameravideoencodersettingscontrol.cpp \ + $$PWD/bbcameraviewfindersettingscontrol.cpp \ + $$PWD/bbcamerazoomcontrol.cpp \ + $$PWD/bbimageencodercontrol.cpp \ + $$PWD/bbmediastoragelocation.cpp \ + $$PWD/bbvideodeviceselectorcontrol.cpp \ + $$PWD/bbvideorenderercontrol.cpp + +LIBS += -lcamapi + +!blackberry-playbook { + LIBS += -laudio_manager +} diff --git a/src/plugins/qnx/common/common.pri b/src/plugins/qnx/common/common.pri new file mode 100644 index 000000000..1a6693474 --- /dev/null +++ b/src/plugins/qnx/common/common.pri @@ -0,0 +1,7 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/windowgrabber.h + +SOURCES += \ + $$PWD/windowgrabber.cpp diff --git a/src/plugins/qnx/common/windowgrabber.cpp b/src/plugins/qnx/common/windowgrabber.cpp new file mode 100644 index 000000000..5ed54b87e --- /dev/null +++ b/src/plugins/qnx/common/windowgrabber.cpp @@ -0,0 +1,367 @@ +/**************************************************************************** +** +** 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 "windowgrabber.h" + +#include <QAbstractEventDispatcher> +#include <QDebug> +#include <QGuiApplication> +#include <QImage> +#include <qpa/qplatformnativeinterface.h> + +#ifdef Q_OS_BLACKBERRY +#include <bps/event.h> +#include <bps/screen.h> +#endif +#include <errno.h> + +QT_BEGIN_NAMESPACE + +WindowGrabber::WindowGrabber(QObject *parent) + : QObject(parent), + m_screenBuffer(0), + m_screenBufferWidth(-1), + m_screenBufferHeight(-1), + m_active(false), + m_screenContextInitialized(false), + m_screenPixmapInitialized(false), + m_screenPixmapBufferInitialized(false) +{ + // grab the window frame with 60 frames per second + m_timer.setInterval(1000/60); + + connect(&m_timer, SIGNAL(timeout()), SLOT(grab())); + + QCoreApplication::eventDispatcher()->installNativeEventFilter(this); +} + +WindowGrabber::~WindowGrabber() +{ + QCoreApplication::eventDispatcher()->removeNativeEventFilter(this); +} + +void WindowGrabber::setFrameRate(int frameRate) +{ + m_timer.setInterval(1000/frameRate); +} + +void WindowGrabber::setWindowId(const QByteArray &windowId) +{ + m_windowId = windowId; +} + +void WindowGrabber::start() +{ + int result = 0; + +#ifdef Q_OS_BLACKBERRY_TABLET + + // HACK: On the Playbook, screen_read_window() will fail for invisible windows. + // To workaround this, make the window visible again, but set a global + // alpha of less than 255. The global alpha makes the window completely invisible + // (due to a bug?), but screen_read_window() will work again. + + errno = 0; + int val = 200; // anything less than 255 + result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_GLOBAL_ALPHA, &val); + if (result != 0) { + qWarning() << "WindowGrabber: unable to set global alpha:" << strerror(errno); + return; + } + + errno = 0; + val = 1; + result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &val); + if (result != 0) { + qWarning() << "WindowGrabber: unable to make window visible:" << strerror(errno); + return; + } +#endif + + result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT); + if (result != 0) { + qWarning() << "WindowGrabber: cannot create screen context:" << strerror(errno); + return; + } else { + m_screenContextInitialized = true; + } + + result = screen_create_pixmap(&m_screenPixmap, m_screenContext); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot create pixmap:" << strerror(errno); + return; + } else { + m_screenPixmapInitialized = true; + } + + const int usage = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE; + result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_USAGE, &usage); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot set pixmap usage:" << strerror(errno); + return; + } + + const int format = SCREEN_FORMAT_RGBA8888; + result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_FORMAT, &format); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot set pixmap format:" << strerror(errno); + return; + } + + int size[2] = { 0, 0 }; + + result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, size); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot get window size:" << strerror(errno); + return; + } + + m_screenBufferWidth = size[0]; + m_screenBufferHeight = size[1]; + + updateFrameSize(); + + m_timer.start(); + + m_active = true; +} + +void WindowGrabber::updateFrameSize() +{ + int size[2] = { m_screenBufferWidth, m_screenBufferHeight }; + + int result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_BUFFER_SIZE, size); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot set pixmap size:" << strerror(errno); + return; + } + + result = screen_create_pixmap_buffer(m_screenPixmap); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot create pixmap buffer:" << strerror(errno); + return; + } + + result = screen_get_pixmap_property_pv(m_screenPixmap, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)&m_screenPixmapBuffer); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot get pixmap buffer:" << strerror(errno); + return; + } else { + m_screenPixmapBufferInitialized = true; + } + + result = screen_get_buffer_property_pv(m_screenPixmapBuffer, SCREEN_PROPERTY_POINTER, (void**)&m_screenBuffer); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot get pixmap buffer pointer:" << strerror(errno); + return; + } + + result = screen_get_buffer_property_iv(m_screenPixmapBuffer, SCREEN_PROPERTY_STRIDE, &m_screenBufferStride); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot get pixmap buffer stride:" << strerror(errno); + return; + } +} + +void WindowGrabber::stop() +{ + if (!m_active) + return; + + cleanup(); + + m_timer.stop(); + + m_active = false; +} + +void WindowGrabber::pause() +{ + m_timer.stop(); +} + +void WindowGrabber::resume() +{ + if (!m_active) + return; + + m_timer.start(); +} + +bool WindowGrabber::handleScreenEvent(screen_event_t screen_event) +{ + + int eventType; + if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) { + qWarning() << "WindowGrabber: Failed to query screen event type"; + return false; + } + + if (eventType != SCREEN_EVENT_CREATE) + return false; + + screen_window_t window = 0; + if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) { + qWarning() << "WindowGrabber: Failed to query window property"; + return false; + } + + const int maxIdStrLength = 128; + char idString[maxIdStrLength]; + if (screen_get_window_property_cv(window, SCREEN_PROPERTY_ID_STRING, maxIdStrLength, idString) != 0) { + qWarning() << "WindowGrabber: Failed to query window ID string"; + return false; + } + + if (m_windowId == idString) { + m_window = window; + start(); + } + + return false; +} + +bool WindowGrabber::nativeEventFilter(const QByteArray &eventType, void *message, long*) +{ +#ifdef Q_OS_BLACKBERRY + Q_UNUSED(eventType) + bps_event_t * const event = static_cast<bps_event_t *>(message); + + if (event && bps_event_get_domain(event) == screen_get_domain()) { + const screen_event_t screen_event = screen_event_get_event(event); + return handleScreenEvent(screen_event); + } +#else + if (eventType == "screen_event_t") { + const screen_event_t event = static_cast<screen_event_t>(message); + return handleScreenEvent(event); + } +#endif + + return false; +} + +QByteArray WindowGrabber::windowGroupId() const +{ + QWindow *window = QGuiApplication::allWindows().isEmpty() ? 0 : QGuiApplication::allWindows().first(); + if (!window) + return QByteArray(); + + QPlatformNativeInterface * const nativeInterface = QGuiApplication::platformNativeInterface(); + if (!nativeInterface) { + qWarning() << "WindowGrabber: Unable to get platform native interface"; + return QByteArray(); + } + + const char * const groupIdData = static_cast<const char *>( + nativeInterface->nativeResourceForWindow("windowGroup", window)); + if (!groupIdData) { + qWarning() << "WindowGrabber: Unable to find window group for window" << window; + return QByteArray(); + } + + return QByteArray(groupIdData); +} + +void WindowGrabber::grab() +{ + int size[2] = { 0, 0 }; + + int result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, size); + if (result != 0) { + cleanup(); + qWarning() << "WindowGrabber: cannot get window size:" << strerror(errno); + return; + } + + if (m_screenBufferWidth != size[0] || m_screenBufferHeight != size[1]) { + // The source viewport size changed, so we have to adapt our buffers + + if (m_screenPixmapBufferInitialized) { + screen_destroy_pixmap_buffer(m_screenPixmap); + m_screenPixmapBufferInitialized = false; + } + + m_screenBufferWidth = size[0]; + m_screenBufferHeight = size[1]; + + updateFrameSize(); + } + + const int rect[] = { 0, 0, m_screenBufferWidth, m_screenBufferHeight }; + result = screen_read_window(m_window, m_screenPixmapBuffer, 1, rect, 0); + if (result != 0) + return; + + const QImage frame((unsigned char*)m_screenBuffer, m_screenBufferWidth, m_screenBufferHeight, + m_screenBufferStride, QImage::Format_ARGB32); + + emit frameGrabbed(frame); +} + +void WindowGrabber::cleanup() +{ + if (m_screenPixmapBufferInitialized) { + screen_destroy_buffer(m_screenPixmapBuffer); + m_screenPixmapBufferInitialized = false; + } + + if (m_screenPixmapInitialized) { + screen_destroy_pixmap(m_screenPixmap); + m_screenPixmapInitialized = false; + } + + if (m_screenContextInitialized) { + screen_destroy_context(m_screenContext); + m_screenContextInitialized = false; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/common/windowgrabber.h b/src/plugins/qnx/common/windowgrabber.h new file mode 100644 index 000000000..7ec4202a2 --- /dev/null +++ b/src/plugins/qnx/common/windowgrabber.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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 WINDOWGRABBER_H +#define WINDOWGRABBER_H + +#include <QAbstractNativeEventFilter> +#include <QObject> +#include <QTimer> + +#include <screen/screen.h> + +QT_BEGIN_NAMESPACE + +class WindowGrabber : public QObject, public QAbstractNativeEventFilter +{ + Q_OBJECT + +public: + explicit WindowGrabber(QObject *parent = 0); + ~WindowGrabber(); + + void setFrameRate(int frameRate); + + void setWindowId(const QByteArray &windowId); + + void start(); + void stop(); + + void pause(); + void resume(); + + bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + + bool handleScreenEvent(screen_event_t event); + + QByteArray windowGroupId() const; + +signals: + void frameGrabbed(const QImage &frame); + +private slots: + void grab(); + +private: + void cleanup(); + void updateFrameSize(); + + QTimer m_timer; + + QByteArray m_windowId; + + screen_window_t m_window; + screen_context_t m_screenContext; + screen_pixmap_t m_screenPixmap; + screen_buffer_t m_screenPixmapBuffer; + + char* m_screenBuffer; + + int m_screenBufferWidth; + int m_screenBufferHeight; + int m_screenBufferStride; + + bool m_active : 1; + bool m_screenContextInitialized : 1; + bool m_screenPixmapInitialized : 1; + bool m_screenPixmapBufferInitialized : 1; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp new file mode 100644 index 000000000..dde03ad59 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** 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 "bpsmediaplayercontrol.h" +#include "mmrenderervideowindowcontrol.h" + +#include <bps/mmrenderer.h> +#include <bps/screen.h> + +QT_BEGIN_NAMESPACE + +BpsMediaPlayerControl::BpsMediaPlayerControl(QObject *parent) + : MmRendererMediaPlayerControl(parent), + m_eventMonitor(0) +{ + openConnection(); +} + +BpsMediaPlayerControl::~BpsMediaPlayerControl() +{ + destroy(); +} + +void BpsMediaPlayerControl::startMonitoring(int contextId, const QString &contextName) +{ + m_eventMonitor = mmrenderer_request_events(contextName.toLatin1().constData(), 0, contextId); + if (!m_eventMonitor) { + qDebug() << "Unable to request multimedia events"; + emit error(0, "Unable to request multimedia events"); + } +} + +void BpsMediaPlayerControl::stopMonitoring() +{ + if (m_eventMonitor) { + mmrenderer_stop_events(m_eventMonitor); + m_eventMonitor = 0; + } +} + +bool BpsMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +{ + Q_UNUSED(result) + Q_UNUSED(eventType) + + bps_event_t * const event = static_cast<bps_event_t *>(message); + if (!event || + (bps_event_get_domain(event) != mmrenderer_get_domain() && + bps_event_get_domain(event) != screen_get_domain())) + return false; + + if (event && bps_event_get_domain(event) == screen_get_domain()) { + const screen_event_t screen_event = screen_event_get_event(event); + if (MmRendererVideoWindowControl *control = videoWindowControl()) + control->screenEventHandler(screen_event); + } + + if (bps_event_get_domain(event) == mmrenderer_get_domain()) { + if (bps_event_get_code(event) == MMRENDERER_STATE_CHANGE) { + const mmrenderer_state_t newState = mmrenderer_event_get_state(event); + if (newState == MMR_STOPPED) { + handleMmStopped(); + return false; + } + } + + if (bps_event_get_code(event) == MMRENDERER_STATUS_UPDATE) { + const qint64 newPosition = QString::fromLatin1(mmrenderer_event_get_position(event)).toLongLong(); + handleMmStatusUpdate(newPosition); + + const QString bufferStatus = QString::fromLatin1(mmrenderer_event_get_bufferlevel(event)); + setMmBufferStatus(bufferStatus); + } + } + + return false; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h new file mode 100644 index 000000000..f0c132346 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h @@ -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 BPSMEDIAPLAYERCONTROL_H +#define BPSMEDIAPLAYERCONTROL_H + +#include "mmrenderermediaplayercontrol.h" + +QT_BEGIN_NAMESPACE + +class BpsMediaPlayerControl Q_DECL_FINAL : public MmRendererMediaPlayerControl +{ + Q_OBJECT +public: + explicit BpsMediaPlayerControl(QObject *parent = 0); + ~BpsMediaPlayerControl(); + + void startMonitoring(int contextId, const QString &contextName) Q_DECL_OVERRIDE; + void stopMonitoring() Q_DECL_OVERRIDE; + + bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + +private: + mmrenderer_monitor_t *m_eventMonitor; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/mediaplayer.pri b/src/plugins/qnx/mediaplayer/mediaplayer.pri new file mode 100644 index 000000000..9dedab0fd --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mediaplayer.pri @@ -0,0 +1,31 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/mmrenderermediaplayercontrol.h \ + $$PWD/mmrenderermediaplayerservice.h \ + $$PWD/mmrenderermetadata.h \ + $$PWD/mmrenderermetadatareadercontrol.h \ + $$PWD/mmrendererplayervideorenderercontrol.h \ + $$PWD/mmrendererutil.h \ + $$PWD/mmrenderervideowindowcontrol.h + +SOURCES += \ + $$PWD/mmrenderermediaplayercontrol.cpp \ + $$PWD/mmrenderermediaplayerservice.cpp \ + $$PWD/mmrenderermetadata.cpp \ + $$PWD/mmrenderermetadatareadercontrol.cpp \ + $$PWD/mmrendererplayervideorenderercontrol.cpp \ + $$PWD/mmrendererutil.cpp \ + $$PWD/mmrenderervideowindowcontrol.cpp + +LIBS += -lmmrndclient -lstrm + +blackberry { + HEADERS += $$PWD/bpsmediaplayercontrol.h + SOURCES += $$PWD/bpsmediaplayercontrol.cpp +} else { + HEADERS += $$PWD/ppsmediaplayercontrol.h + SOURCES += $$PWD/ppsmediaplayercontrol.cpp + QT += core-private + LIBS += -lpps +} diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp new file mode 100644 index 000000000..2a376198b --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp @@ -0,0 +1,634 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "mmrenderermediaplayercontrol.h" +#include "mmrenderermetadatareadercontrol.h" +#include "mmrendererplayervideorenderercontrol.h" +#include "mmrendererutil.h" +#include "mmrenderervideowindowcontrol.h" +#include <QtCore/qabstracteventdispatcher.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qdir.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/quuid.h> +#include <mm/renderer.h> + +#include <errno.h> +#include <sys/strm.h> +#include <sys/stat.h> + +QT_BEGIN_NAMESPACE + +static int idCounter = 0; + +MmRendererMediaPlayerControl::MmRendererMediaPlayerControl(QObject *parent) + : QMediaPlayerControl(parent), + m_connection(0), + m_context(0), + m_audioId(-1), + m_state(QMediaPlayer::StoppedState), + m_volume(100), + m_muted(false), + m_rate(1), + m_id(-1), + m_position(0), + m_mediaStatus(QMediaPlayer::NoMedia), + m_playAfterMediaLoaded(false), + m_inputAttached(false), + m_stopEventsToIgnore(0), + m_bufferStatus(0) +{ + m_loadingTimer.setSingleShot(true); + m_loadingTimer.setInterval(0); + connect(&m_loadingTimer, SIGNAL(timeout()), this, SLOT(continueLoadMedia())); + QCoreApplication::eventDispatcher()->installNativeEventFilter(this); +} + +void MmRendererMediaPlayerControl::destroy() +{ + stop(); + detach(); + closeConnection(); + QCoreApplication::eventDispatcher()->removeNativeEventFilter(this); +} + +void MmRendererMediaPlayerControl::openConnection() +{ + m_connection = mmr_connect(NULL); + if (!m_connection) { + emitPError("Unable to connect to the multimedia renderer"); + return; + } + + m_id = idCounter++; + m_contextName = QString("MmRendererMediaPlayerControl_%1_%2").arg(m_id) + .arg(QCoreApplication::applicationPid()); + m_context = mmr_context_create(m_connection, m_contextName.toLatin1(), + 0, S_IRWXU|S_IRWXG|S_IRWXO); + if (!m_context) { + emitPError("Unable to create context"); + closeConnection(); + return; + } + + startMonitoring(m_id, m_contextName); +} + +void MmRendererMediaPlayerControl::handleMmStatusUpdate(qint64 newPosition) +{ + // Prevent spurious position change events from overriding our own position, for example + // when setting the position to 0 in stop(). + // Also, don't change the position while we're loading the media, as then play() would + // set a wrong initial position. + if (m_state != QMediaPlayer::PlayingState || + m_mediaStatus == QMediaPlayer::LoadingMedia || + m_mediaStatus == QMediaPlayer::NoMedia || + m_mediaStatus == QMediaPlayer::InvalidMedia) + return; + + setMmPosition(newPosition); +} + +void MmRendererMediaPlayerControl::handleMmStopped() +{ + // Only react to stop events that happen when the end of the stream is reached and + // playback is stopped because of this. + // Ignore other stop event sources, souch as calling mmr_stop() ourselves and + // mmr_input_attach(). + if (m_stopEventsToIgnore > 0) { + --m_stopEventsToIgnore; + } else { + setMediaStatus(QMediaPlayer::EndOfMedia); + stopInternal(IgnoreMmRenderer); + } +} + +void MmRendererMediaPlayerControl::closeConnection() +{ + stopMonitoring(); + + if (m_context) { + mmr_context_destroy(m_context); + m_context = 0; + m_contextName.clear(); + } + + if (m_connection) { + mmr_disconnect(m_connection); + m_connection = 0; + } +} + +QByteArray MmRendererMediaPlayerControl::resourcePathForUrl(const QUrl &url) +{ + // If this is a local file, mmrenderer expects the file:// prefix and an absolute path. + // We treat URLs without scheme as local files, most likely someone just forgot to set the + // file:// prefix when constructing the URL. + if (url.isLocalFile() || url.scheme().isEmpty()) { + QString relativeFilePath; + if (!url.scheme().isEmpty()) + relativeFilePath = url.toLocalFile(); + else + relativeFilePath = url.path(); + const QFileInfo fileInfo(relativeFilePath); + return QFile::encodeName(QStringLiteral("file://") + fileInfo.absoluteFilePath()); + + // QRC, copy to temporary file, as mmrenderer does not support resource files + } else if (url.scheme() == QStringLiteral("qrc")) { + const QString qrcPath = ':' + url.path(); + const QFileInfo resourceFileInfo(qrcPath); + m_tempMediaFileName = QDir::tempPath() + QStringLiteral("/qtmedia_") + + QUuid::createUuid().toString() + QStringLiteral(".") + + resourceFileInfo.suffix(); + if (!QFile::copy(qrcPath, m_tempMediaFileName)) { + const QString errorMsg = QString("Failed to copy resource file to temporary file " + "%1 for playback").arg(m_tempMediaFileName); + qDebug() << errorMsg; + emit error(0, errorMsg); + return QByteArray(); + } + return QFile::encodeName(m_tempMediaFileName); + + // HTTP or similar URL + } else { + return url.toEncoded(); + } +} + +void MmRendererMediaPlayerControl::attach() +{ + // Should only be called in detached state + Q_ASSERT(m_audioId == -1 && !m_inputAttached && m_tempMediaFileName.isEmpty()); + + if (m_media.isNull() || !m_context) { + setMediaStatus(QMediaPlayer::NoMedia); + return; + } + + if (m_videoRendererControl) + m_videoRendererControl->attachDisplay(m_context); + + if (m_videoWindowControl) + m_videoWindowControl->attachDisplay(m_context); + + m_audioId = mmr_output_attach(m_context, "audio:default", "audio"); + if (m_audioId == -1) { + emitMmError("mmr_output_attach() for audio failed"); + return; + } + + const QByteArray resourcePath = resourcePathForUrl(m_media.canonicalUrl()); + if (resourcePath.isEmpty()) { + detach(); + return; + } + + if (mmr_input_attach(m_context, resourcePath.constData(), "track") != 0) { + emitMmError(QStringLiteral("mmr_input_attach() failed for ") + QString(resourcePath)); + setMediaStatus(QMediaPlayer::InvalidMedia); + detach(); + return; + } + + // For whatever reason, the mmrenderer sends out a MMR_STOPPED event when calling + // mmr_input_attach() above. Ignore it, as otherwise we'll trigger stopping right after we + // started. + m_stopEventsToIgnore++; + + m_inputAttached = true; + setMediaStatus(QMediaPlayer::LoadedMedia); + m_bufferStatus = 0; + emit bufferStatusChanged(m_bufferStatus); +} + +void MmRendererMediaPlayerControl::detach() +{ + if (m_context) { + if (m_inputAttached) { + mmr_input_detach(m_context); + m_inputAttached = false; + } + if (m_videoRendererControl) + m_videoRendererControl->detachDisplay(); + if (m_videoWindowControl) + m_videoWindowControl->detachDisplay(); + if (m_audioId != -1 && m_context) { + mmr_output_detach(m_context, m_audioId); + m_audioId = -1; + } + } + + if (!m_tempMediaFileName.isEmpty()) { + QFile::remove(m_tempMediaFileName); + m_tempMediaFileName.clear(); + } + m_loadingTimer.stop(); +} + +QMediaPlayer::State MmRendererMediaPlayerControl::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus MmRendererMediaPlayerControl::mediaStatus() const +{ + return m_mediaStatus; +} + +qint64 MmRendererMediaPlayerControl::duration() const +{ + return m_metaData.duration(); +} + +qint64 MmRendererMediaPlayerControl::position() const +{ + return m_position; +} + +void MmRendererMediaPlayerControl::setPosition(qint64 position) +{ + if (m_position != position) { + m_position = position; + + // Don't update in stopped state, it would not have any effect. Instead, the position is + // updated in play(). + if (m_state != QMediaPlayer::StoppedState) + setPositionInternal(m_position); + + emit positionChanged(m_position); + } +} + +int MmRendererMediaPlayerControl::volume() const +{ + return m_volume; +} + +void MmRendererMediaPlayerControl::setVolumeInternal(int newVolume) +{ + if (!m_context) + return; + + newVolume = qBound(0, newVolume, 100); + if (m_audioId != -1) { + strm_dict_t * dict = strm_dict_new(); + dict = strm_dict_set(dict, "volume", QString::number(newVolume).toLatin1()); + if (mmr_output_parameters(m_context, m_audioId, dict) != 0) + emitMmError("mmr_output_parameters: Setting volume failed"); + } +} + +void MmRendererMediaPlayerControl::setPlaybackRateInternal(qreal rate) +{ + if (!m_context) + return; + + const int mmRate = rate * 1000; + if (mmr_speed_set(m_context, mmRate) != 0) + emitMmError("mmr_speed_set failed"); +} + +void MmRendererMediaPlayerControl::setPositionInternal(qint64 position) +{ + if (!m_context) + return; + + if (m_metaData.isSeekable()) { + if (mmr_seek(m_context, QString::number(position).toLatin1()) != 0) + emitMmError("Seeking failed"); + } +} + +void MmRendererMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status) +{ + if (m_mediaStatus != status) { + m_mediaStatus = status; + emit mediaStatusChanged(m_mediaStatus); + } +} + +void MmRendererMediaPlayerControl::setState(QMediaPlayer::State state) +{ + if (m_state != state) { + if (m_videoRendererControl) { + if (state == QMediaPlayer::PausedState) + m_videoRendererControl->pause(); + else if ((state == QMediaPlayer::PlayingState) + && (m_state == QMediaPlayer::PausedState)) { + m_videoRendererControl->resume(); + } + } + + m_state = state; + emit stateChanged(m_state); + } +} + +void MmRendererMediaPlayerControl::stopInternal(StopCommand stopCommand) +{ + if (m_state != QMediaPlayer::StoppedState) { + + if (stopCommand == StopMmRenderer) { + ++m_stopEventsToIgnore; + mmr_stop(m_context); + } + + setState(QMediaPlayer::StoppedState); + } + + if (m_position != 0) { + m_position = 0; + emit positionChanged(0); + } +} + +void MmRendererMediaPlayerControl::setVolume(int volume) +{ + const int newVolume = qBound(0, volume, 100); + if (m_volume != newVolume) { + m_volume = newVolume; + if (!m_muted) + setVolumeInternal(m_volume); + emit volumeChanged(m_volume); + } +} + +bool MmRendererMediaPlayerControl::isMuted() const +{ + return m_muted; +} + +void MmRendererMediaPlayerControl::setMuted(bool muted) +{ + if (m_muted != muted) { + m_muted = muted; + setVolumeInternal(muted ? 0 : m_volume); + emit mutedChanged(muted); + } +} + +int MmRendererMediaPlayerControl::bufferStatus() const +{ + return m_bufferStatus; +} + +bool MmRendererMediaPlayerControl::isAudioAvailable() const +{ + return m_metaData.hasAudio(); +} + +bool MmRendererMediaPlayerControl::isVideoAvailable() const +{ + return m_metaData.hasVideo(); +} + +bool MmRendererMediaPlayerControl::isSeekable() const +{ + return m_metaData.isSeekable(); +} + +QMediaTimeRange MmRendererMediaPlayerControl::availablePlaybackRanges() const +{ + // We can't get this information from the mmrenderer API yet, so pretend we can seek everywhere + return QMediaTimeRange(0, m_metaData.duration()); +} + +qreal MmRendererMediaPlayerControl::playbackRate() const +{ + return m_rate; +} + +void MmRendererMediaPlayerControl::setPlaybackRate(qreal rate) +{ + if (m_rate != rate) { + m_rate = rate; + setPlaybackRateInternal(m_rate); + emit playbackRateChanged(m_rate); + } +} + +QMediaContent MmRendererMediaPlayerControl::media() const +{ + return m_media; +} + +const QIODevice *MmRendererMediaPlayerControl::mediaStream() const +{ + // Always 0, we don't support QIODevice streams + return 0; +} + +void MmRendererMediaPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream) +{ + Q_UNUSED(stream); // not supported + + stop(); + detach(); + + m_media = media; + emit mediaChanged(m_media); + + // Slight hack: With MediaPlayer QtQuick elements that have autoPlay set to true, playback + // would start before the QtQuick canvas is propagated to all elements, and therefore our + // video output would not work. Therefore, delay actually playing the media a bit so that the + // canvas is ready. + // The mmrenderer doesn't allow to attach video outputs after playing has started, otherwise + // this would be unnecessary. + if (!m_media.isNull()) { + setMediaStatus(QMediaPlayer::LoadingMedia); + m_loadingTimer.start(); // singleshot timer to continueLoadMedia() + } else { + continueLoadMedia(); // still needed, as it will update the media status and clear metadata + } +} + +void MmRendererMediaPlayerControl::continueLoadMedia() +{ + attach(); + updateMetaData(); + if (m_playAfterMediaLoaded) + play(); +} + +QString MmRendererMediaPlayerControl::contextName() const +{ + return m_contextName; +} + +MmRendererVideoWindowControl *MmRendererMediaPlayerControl::videoWindowControl() const +{ + return m_videoWindowControl; +} + +void MmRendererMediaPlayerControl::play() +{ + if (m_playAfterMediaLoaded) + m_playAfterMediaLoaded = false; + + // No-op if we are already playing, except if we were called from continueLoadMedia(), in which + // case m_playAfterMediaLoaded is true (hence the 'else'). + else if (m_state == QMediaPlayer::PlayingState) + return; + + if (m_mediaStatus == QMediaPlayer::LoadingMedia) { + + // State changes are supposed to be synchronous + setState(QMediaPlayer::PlayingState); + + // Defer playing to later, when the timer triggers continueLoadMedia() + m_playAfterMediaLoaded = true; + return; + } + + // Un-pause the state when it is paused + if (m_state == QMediaPlayer::PausedState) { + setPlaybackRateInternal(m_rate); + setState(QMediaPlayer::PlayingState); + return; + } + + if (m_media.isNull() || !m_connection || !m_context || m_audioId == -1) { + setState(QMediaPlayer::StoppedState); + return; + } + + setPositionInternal(m_position); + setVolumeInternal(m_volume); + setPlaybackRateInternal(m_rate); + + if (mmr_play(m_context) != 0) { + setState(QMediaPlayer::StoppedState); + emitMmError("mmr_play() failed"); + return; + } + + setState( QMediaPlayer::PlayingState); +} + +void MmRendererMediaPlayerControl::pause() +{ + if (m_state == QMediaPlayer::PlayingState) { + setPlaybackRateInternal(0); + setState(QMediaPlayer::PausedState); + } +} + +void MmRendererMediaPlayerControl::stop() +{ + stopInternal(StopMmRenderer); +} + +MmRendererPlayerVideoRendererControl *MmRendererMediaPlayerControl::videoRendererControl() const +{ + return m_videoRendererControl; +} + +void MmRendererMediaPlayerControl::setVideoRendererControl(MmRendererPlayerVideoRendererControl *videoControl) +{ + m_videoRendererControl = videoControl; +} + +void MmRendererMediaPlayerControl::setVideoWindowControl(MmRendererVideoWindowControl *videoControl) +{ + m_videoWindowControl = videoControl; +} + +void MmRendererMediaPlayerControl::setMetaDataReaderControl(MmRendererMetaDataReaderControl *metaDataReaderControl) +{ + m_metaDataReaderControl = metaDataReaderControl; +} + +void MmRendererMediaPlayerControl::setMmPosition(qint64 newPosition) +{ + if (newPosition != 0 && newPosition != m_position) { + m_position = newPosition; + emit positionChanged(m_position); + } +} + +void MmRendererMediaPlayerControl::setMmBufferStatus(const QString &bufferStatus) +{ + const int slashPos = bufferStatus.indexOf('/'); + if (slashPos != -1) { + const int fill = bufferStatus.left(slashPos).toInt(); + const int capacity = bufferStatus.mid(slashPos + 1).toInt(); + if (capacity != 0) { + m_bufferStatus = fill / static_cast<float>(capacity) * 100.0f; + emit bufferStatusChanged(m_bufferStatus); + } + } +} + +void MmRendererMediaPlayerControl::updateMetaData() +{ + if (m_mediaStatus == QMediaPlayer::LoadedMedia) + m_metaData.parse(m_contextName); + else + m_metaData.clear(); + + if (m_videoWindowControl) + m_videoWindowControl->setMetaData(m_metaData); + + if (m_metaDataReaderControl) + m_metaDataReaderControl->setMetaData(m_metaData); + + emit durationChanged(m_metaData.duration()); + emit audioAvailableChanged(m_metaData.hasAudio()); + emit videoAvailableChanged(m_metaData.hasVideo()); + emit availablePlaybackRangesChanged(availablePlaybackRanges()); + emit seekableChanged(m_metaData.isSeekable()); +} + +void MmRendererMediaPlayerControl::emitMmError(const QString &msg) +{ + int errorCode = MMR_ERROR_NONE; + const QString errorMessage = mmErrorMessage(msg, m_context, &errorCode); + qDebug() << errorMessage; + emit error(errorCode, errorMessage); +} + +void MmRendererMediaPlayerControl::emitPError(const QString &msg) +{ + const QString errorMessage = QString("%1: %2").arg(msg).arg(strerror(errno)); + qDebug() << errorMessage; + emit error(errno, errorMessage); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h new file mode 100644 index 000000000..a22e71bfc --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 MMRENDERERMEDIAPLAYERCONTROL_H +#define MMRENDERERMEDIAPLAYERCONTROL_H + +#include "mmrenderermetadata.h" +#include <qmediaplayercontrol.h> +#include <QtCore/qabstractnativeeventfilter.h> +#include <QtCore/qpointer.h> +#include <QtCore/qtimer.h> + +typedef struct mmr_connection mmr_connection_t; +typedef struct mmr_context mmr_context_t; +typedef struct mmrenderer_monitor mmrenderer_monitor_t; + +QT_BEGIN_NAMESPACE + +class MmRendererMetaDataReaderControl; +class MmRendererPlayerVideoRendererControl; +class MmRendererVideoWindowControl; + +class MmRendererMediaPlayerControl : public QMediaPlayerControl, public QAbstractNativeEventFilter +{ + Q_OBJECT +public: + explicit MmRendererMediaPlayerControl(QObject *parent = 0); + + QMediaPlayer::State state() const Q_DECL_OVERRIDE; + + QMediaPlayer::MediaStatus mediaStatus() const Q_DECL_OVERRIDE; + + qint64 duration() const Q_DECL_OVERRIDE; + + qint64 position() const Q_DECL_OVERRIDE; + void setPosition(qint64 position) Q_DECL_OVERRIDE; + + int volume() const Q_DECL_OVERRIDE; + void setVolume(int volume) Q_DECL_OVERRIDE; + + bool isMuted() const Q_DECL_OVERRIDE; + void setMuted(bool muted) Q_DECL_OVERRIDE; + + int bufferStatus() const Q_DECL_OVERRIDE; + + bool isAudioAvailable() const Q_DECL_OVERRIDE; + bool isVideoAvailable() const Q_DECL_OVERRIDE; + + bool isSeekable() const Q_DECL_OVERRIDE; + + QMediaTimeRange availablePlaybackRanges() const Q_DECL_OVERRIDE; + + qreal playbackRate() const Q_DECL_OVERRIDE; + void setPlaybackRate(qreal rate) Q_DECL_OVERRIDE; + + QMediaContent media() const Q_DECL_OVERRIDE; + const QIODevice *mediaStream() const Q_DECL_OVERRIDE; + void setMedia(const QMediaContent &media, QIODevice *stream) Q_DECL_OVERRIDE; + + void play() Q_DECL_OVERRIDE; + void pause() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + + MmRendererPlayerVideoRendererControl *videoRendererControl() const; + void setVideoRendererControl(MmRendererPlayerVideoRendererControl *videoControl); + + MmRendererVideoWindowControl *videoWindowControl() const; + void setVideoWindowControl(MmRendererVideoWindowControl *videoControl); + void setMetaDataReaderControl(MmRendererMetaDataReaderControl *metaDataReaderControl); + +protected: + virtual void startMonitoring(int contextId, const QString &contextName) = 0; + virtual void stopMonitoring() = 0; + + QString contextName() const; + void openConnection(); + void emitMmError(const QString &msg); + void emitPError(const QString &msg); + void setMmPosition(qint64 newPosition); + void setMmBufferStatus(const QString &bufferStatus); + void handleMmStopped(); + void handleMmStatusUpdate(qint64 position); + + // must be called from subclass dtors (calls virtual function stopMonitoring()) + void destroy(); + +private Q_SLOTS: + void continueLoadMedia(); + +private: + QByteArray resourcePathForUrl(const QUrl &url); + void closeConnection(); + void attach(); + void detach(); + void updateMetaData(); + + // All these set the specified value to the backend, but neither emit changed signals + // nor change the member value. + void setVolumeInternal(int newVolume); + void setPlaybackRateInternal(qreal rate); + void setPositionInternal(qint64 position); + + void setMediaStatus(QMediaPlayer::MediaStatus status); + void setState(QMediaPlayer::State state); + + enum StopCommand { StopMmRenderer, IgnoreMmRenderer }; + void stopInternal(StopCommand stopCommand); + + QMediaContent m_media; + mmr_connection_t *m_connection; + mmr_context_t *m_context; + QString m_contextName; + int m_audioId; + QMediaPlayer::State m_state; + int m_volume; + bool m_muted; + qreal m_rate; + QPointer<MmRendererPlayerVideoRendererControl> m_videoRendererControl; + QPointer<MmRendererVideoWindowControl> m_videoWindowControl; + QPointer<MmRendererMetaDataReaderControl> m_metaDataReaderControl; + MmRendererMetaData m_metaData; + int m_id; + qint64 m_position; + QMediaPlayer::MediaStatus m_mediaStatus; + bool m_playAfterMediaLoaded; + bool m_inputAttached; + int m_stopEventsToIgnore; + int m_bufferStatus; + QString m_tempMediaFileName; + QTimer m_loadingTimer; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp new file mode 100644 index 000000000..1e75674e3 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "mmrenderermediaplayerservice.h" + +#include "mmrenderermediaplayercontrol.h" +#include "mmrenderermetadatareadercontrol.h" +#include "mmrendererplayervideorenderercontrol.h" +#include "mmrendererutil.h" +#include "mmrenderervideowindowcontrol.h" + +#ifdef Q_OS_BLACKBERRY +#include "bpsmediaplayercontrol.h" +typedef BpsMediaPlayerControl PlatformSpecificMediaPlayerControl; +#else +#include "ppsmediaplayercontrol.h" +typedef PpsMediaPlayerControl PlatformSpecificMediaPlayerControl; +#endif + +QT_BEGIN_NAMESPACE + +MmRendererMediaPlayerService::MmRendererMediaPlayerService(QObject *parent) + : QMediaService(parent), + m_videoRendererControl(0), + m_videoWindowControl(0), + m_mediaPlayerControl(0), + m_metaDataReaderControl(0), + m_appHasDrmPermission(false), + m_appHasDrmPermissionChecked(false) +{ +} + +MmRendererMediaPlayerService::~MmRendererMediaPlayerService() +{ + // Someone should have called releaseControl(), but better be safe + delete m_videoRendererControl; + delete m_videoWindowControl; + delete m_mediaPlayerControl; + delete m_metaDataReaderControl; +} + +QMediaControl *MmRendererMediaPlayerService::requestControl(const char *name) +{ + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) { + if (!m_mediaPlayerControl) { + m_mediaPlayerControl = new PlatformSpecificMediaPlayerControl; + updateControls(); + } + return m_mediaPlayerControl; + } + else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) { + if (!m_metaDataReaderControl) { + m_metaDataReaderControl = new MmRendererMetaDataReaderControl(); + updateControls(); + } + return m_metaDataReaderControl; + } + else if (qstrcmp(name, QVideoRendererControl_iid) == 0) { + if (!m_appHasDrmPermissionChecked) { + m_appHasDrmPermission = checkForDrmPermission(); + m_appHasDrmPermissionChecked = true; + } + + if (m_appHasDrmPermission) { + // When the application wants to play back DRM secured media, we can't use + // the QVideoRendererControl, because we won't have access to the pixel data + // in this case. + return 0; + } + + if (!m_videoRendererControl) { + m_videoRendererControl = new MmRendererPlayerVideoRendererControl(); + updateControls(); + } + return m_videoRendererControl; + } + else if (qstrcmp(name, QVideoWindowControl_iid) == 0) { + if (!m_videoWindowControl) { + m_videoWindowControl = new MmRendererVideoWindowControl(); + updateControls(); + } + return m_videoWindowControl; + } + return 0; +} + +void MmRendererMediaPlayerService::releaseControl(QMediaControl *control) +{ + if (control == m_videoRendererControl) + m_videoRendererControl = 0; + if (control == m_videoWindowControl) + m_videoWindowControl = 0; + if (control == m_mediaPlayerControl) + m_mediaPlayerControl = 0; + if (control == m_metaDataReaderControl) + m_metaDataReaderControl = 0; + delete control; +} + +void MmRendererMediaPlayerService::updateControls() +{ + if (m_videoRendererControl && m_mediaPlayerControl) + m_mediaPlayerControl->setVideoRendererControl(m_videoRendererControl); + + if (m_videoWindowControl && m_mediaPlayerControl) + m_mediaPlayerControl->setVideoWindowControl(m_videoWindowControl); + + if (m_metaDataReaderControl && m_mediaPlayerControl) + m_mediaPlayerControl->setMetaDataReaderControl(m_metaDataReaderControl); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h new file mode 100644 index 000000000..3d55de8d5 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 MMRENDERERMEDIAPLAYERSERVICE_H +#define MMRENDERERMEDIAPLAYERSERVICE_H + +#include <qmediaservice.h> +#include <QtCore/qpointer.h> + +QT_BEGIN_NAMESPACE + +class MmRendererMediaPlayerControl; +class MmRendererMetaDataReaderControl; +class MmRendererPlayerVideoRendererControl; +class MmRendererVideoWindowControl; + +class MmRendererMediaPlayerService : public QMediaService +{ + Q_OBJECT +public: + explicit MmRendererMediaPlayerService(QObject *parent = 0); + ~MmRendererMediaPlayerService(); + + QMediaControl *requestControl(const char *name) Q_DECL_OVERRIDE; + void releaseControl(QMediaControl *control) Q_DECL_OVERRIDE; + +private: + void updateControls(); + + QPointer<MmRendererPlayerVideoRendererControl> m_videoRendererControl; + QPointer<MmRendererVideoWindowControl> m_videoWindowControl; + QPointer<MmRendererMediaPlayerControl> m_mediaPlayerControl; + QPointer<MmRendererMetaDataReaderControl> m_metaDataReaderControl; + + bool m_appHasDrmPermission : 1; + bool m_appHasDrmPermissionChecked : 1; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadata.cpp b/src/plugins/qnx/mediaplayer/mmrenderermetadata.cpp new file mode 100644 index 000000000..07f5ddd62 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermetadata.cpp @@ -0,0 +1,269 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "mmrenderermetadata.h" + +#include <QtCore/qdebug.h> +#include <QtCore/qfile.h> +#include <QtCore/qstringlist.h> + +QT_BEGIN_NAMESPACE + +MmRendererMetaData::MmRendererMetaData() +{ + clear(); +} + +static const char * titleKey = "md_title_name"; +static const char * artistKey = "md_title_artist"; +static const char * commentKey = "md_title_comment"; +static const char * genreKey = "md_title_genre"; +static const char * yearKey = "md_title_year"; +static const char * durationKey = "md_title_duration"; +static const char * bitRateKey = "md_title_bitrate"; +static const char * sampleKey = "md_title_samplerate"; +static const char * albumKey = "md_title_album"; +static const char * trackKey = "md_title_track"; +static const char * widthKey = "md_video_width"; +static const char * heightKey = "md_video_height"; +static const char * mediaTypeKey = "md_title_mediatype"; +static const char * pixelWidthKey = "md_video_pixel_width"; +static const char * pixelHeightKey = "md_video_pixel_height"; +static const char * seekableKey = "md_title_seekable"; + +static const int mediaTypeAudioFlag = 4; +static const int mediaTypeVideoFlag = 2; + +bool MmRendererMetaData::parse(const QString &contextName) +{ + clear(); + QString fileName = + QString("/pps/services/multimedia/renderer/context/%1/metadata").arg(contextName); + + // In newer OS versions, the filename is "metadata0", not metadata, so try both. + if (!QFile::exists(fileName)) + fileName += '0'; + + QFile metaDataFile(fileName); + if (!metaDataFile.open(QFile::ReadOnly)) { + qWarning() << "Unable to open media metadata file" << fileName << ":" + << metaDataFile.errorString(); + return false; + } + + const QString separator("::"); + QTextStream stream(&metaDataFile); + Q_FOREVER { + const QString line = stream.readLine(); + if (line.isNull()) + break; + + const int separatorPos = line.indexOf(separator); + if (separatorPos != -1) { + const QString key = line.left(separatorPos); + const QString value = line.mid(separatorPos + separator.length()); + + if (key == durationKey) + m_duration = value.toLongLong(); + else if (key == widthKey) + m_width = value.toInt(); + else if (key == heightKey) + m_height = value.toInt(); + else if (key == mediaTypeKey) + m_mediaType = value.toInt(); + else if (key == pixelWidthKey) + m_pixelWidth = value.toFloat(); + else if (key == pixelHeightKey) + m_pixelHeight = value.toFloat(); + else if (key == titleKey) + m_title = value; + else if (key == seekableKey) + m_seekable = !(value == QLatin1String("0")); + else if (key == artistKey) + m_artist = value; + else if (key == commentKey) + m_comment = value; + else if (key == genreKey) + m_genre = value; + else if (key == yearKey) + m_year = value.toInt(); + else if (key == bitRateKey) + m_audioBitRate = value.toInt(); + else if (key == sampleKey) + m_sampleRate = value.toInt(); + else if (key == albumKey) + m_album = value; + else if (key == trackKey) + m_track = value.toInt(); + } + } + + return true; +} + +void MmRendererMetaData::clear() +{ + m_duration = 0; + m_height = 0; + m_width = 0; + m_mediaType = -1; + m_pixelWidth = 1; + m_pixelHeight = 1; + m_seekable = true; + m_title.clear(); + m_artist.clear(); + m_comment.clear(); + m_genre.clear(); + m_year = 0; + m_audioBitRate = 0; + m_sampleRate = 0; + m_album.clear(); + m_track = 0; +} + +qlonglong MmRendererMetaData::duration() const +{ + return m_duration; +} + +// Handling of pixel aspect ratio +// +// If the pixel aspect ratio is different from 1:1, it means the video needs to be stretched in +// order to look natural. +// For example, if the pixel width is 2, and the pixel height is 1, it means a video of 300x200 +// pixels needs to be displayed as 600x200 to look correct. +// In order to support this the easiest way, we simply pretend that the actual size of the video +// is 600x200, which will cause the video to be displayed in an aspect ratio of 3:1 instead of 3:2, +// and therefore look correct. + +int MmRendererMetaData::height() const +{ + return m_height * m_pixelHeight; +} + +int MmRendererMetaData::width() const +{ + return m_width * m_pixelWidth; +} + +bool MmRendererMetaData::hasVideo() const +{ + // By default, assume no video if we can't extract the information + if (m_mediaType == -1) + return false; + + return (m_mediaType & mediaTypeVideoFlag); +} + +bool MmRendererMetaData::hasAudio() const +{ + // By default, assume audio only if we can't extract the information + if (m_mediaType == -1) + return true; + + return (m_mediaType & mediaTypeAudioFlag); +} + +QString MmRendererMetaData::title() const +{ + return m_title; +} + +bool MmRendererMetaData::isSeekable() const +{ + return m_seekable; +} + +QString MmRendererMetaData::artist() const +{ + return m_artist; +} + +QString MmRendererMetaData::comment() const +{ + return m_comment; +} + +QString MmRendererMetaData::genre() const +{ + return m_genre; +} + +int MmRendererMetaData::year() const +{ + return m_year; +} + +QString MmRendererMetaData::mediaType() const +{ + if (hasVideo()) + return QLatin1String("video"); + else if (hasAudio()) + return QLatin1String("audio"); + else + return QString(); +} + +int MmRendererMetaData::audioBitRate() const +{ + return m_audioBitRate; +} + +int MmRendererMetaData::sampleRate() const +{ + return m_sampleRate; +} + +QString MmRendererMetaData::album() const +{ + return m_album; +} + +int MmRendererMetaData::track() const +{ + return m_track; +} + +QSize MmRendererMetaData::resolution() const +{ + return QSize(width(), height()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadata.h b/src/plugins/qnx/mediaplayer/mmrenderermetadata.h new file mode 100644 index 000000000..deb848a80 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermetadata.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 MMRENDERERMETADATA_H +#define MMRENDERERMETADATA_H + +#include <QtCore/qglobal.h> +#include <QtCore/QSize> +#include <QtCore/QString> + +QT_BEGIN_NAMESPACE + +class MmRendererMetaData +{ +public: + MmRendererMetaData(); + bool parse(const QString &contextName); + void clear(); + + // Duration in milliseconds + qlonglong duration() const; + + int height() const; + int width() const; + bool hasVideo() const; + bool hasAudio() const; + bool isSeekable() const; + + QString title() const; + QString artist() const; + QString comment() const; + QString genre() const; + int year() const; + QString mediaType() const; + int audioBitRate() const; + int sampleRate() const; + QString album() const; + int track() const; + QSize resolution() const; + +private: + qlonglong m_duration; + int m_height; + int m_width; + int m_mediaType; + float m_pixelWidth; + float m_pixelHeight; + bool m_seekable; + QString m_title; + QString m_artist; + QString m_comment; + QString m_genre; + int m_year; + int m_audioBitRate; + int m_sampleRate; + QString m_album; + int m_track; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.cpp new file mode 100644 index 000000000..c0fe7d085 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** 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 "mmrenderermetadatareadercontrol.h" +#include <QtMultimedia/qmediametadata.h> + +QT_BEGIN_NAMESPACE + +MmRendererMetaDataReaderControl::MmRendererMetaDataReaderControl(QObject *parent) + : QMetaDataReaderControl(parent) +{ +} + +bool MmRendererMetaDataReaderControl::isMetaDataAvailable() const +{ + return !availableMetaData().isEmpty(); +} + +QVariant MmRendererMetaDataReaderControl::metaData(const QString &key) const +{ + if (key == QMediaMetaData::Title) + return m_metaData.title(); + else if (key == QMediaMetaData::Author) + return m_metaData.artist(); + else if (key == QMediaMetaData::Comment) + return m_metaData.comment(); + else if (key == QMediaMetaData::Genre) + return m_metaData.genre(); + else if (key == QMediaMetaData::Year) + return m_metaData.year(); + else if (key == QMediaMetaData::MediaType) + return m_metaData.mediaType(); + else if (key == QMediaMetaData::Duration) + return m_metaData.duration(); + else if (key == QMediaMetaData::AudioBitRate) + return m_metaData.audioBitRate(); + else if (key == QMediaMetaData::SampleRate) + return m_metaData.sampleRate(); + else if (key == QMediaMetaData::AlbumTitle) + return m_metaData.album(); + else if (key == QMediaMetaData::TrackNumber) + return m_metaData.track(); + else if (key == QMediaMetaData::Resolution) + return m_metaData.resolution(); + + return QVariant(); +} + +QStringList MmRendererMetaDataReaderControl::availableMetaData() const +{ + QStringList metaData; + + if (!m_metaData.title().isEmpty()) + metaData << QMediaMetaData::Title; + if (!m_metaData.artist().isEmpty()) + metaData << QMediaMetaData::Author; + if (!m_metaData.comment().isEmpty()) + metaData << QMediaMetaData::Comment; + if (!m_metaData.genre().isEmpty()) + metaData << QMediaMetaData::Genre; + if (m_metaData.year() != 0) + metaData << QMediaMetaData::Year; + if (!m_metaData.mediaType().isEmpty()) + metaData << QMediaMetaData::MediaType; + if (m_metaData.duration() != 0) + metaData << QMediaMetaData::Duration; + if (m_metaData.audioBitRate() != 0) + metaData << QMediaMetaData::AudioBitRate; + if (m_metaData.sampleRate() != 0) + metaData << QMediaMetaData::SampleRate; + if (!m_metaData.album().isEmpty()) + metaData << QMediaMetaData::AlbumTitle; + if (m_metaData.track() != 0) + metaData << QMediaMetaData::TrackNumber; + if (m_metaData.resolution().isValid()) + metaData << QMediaMetaData::Resolution; + + return metaData; +} + +void MmRendererMetaDataReaderControl::setMetaData(const MmRendererMetaData &data) +{ + const MmRendererMetaData oldMetaData = m_metaData; + const bool oldMetaDataAvailable = isMetaDataAvailable(); + + m_metaData = data; + + bool changed = false; + if (m_metaData.title() != oldMetaData.title()) { + changed = true; + emit metaDataChanged(QMediaMetaData::Title, m_metaData.title()); + } else if (m_metaData.artist() != oldMetaData.artist()) { + changed = true; + emit metaDataChanged(QMediaMetaData::Author, m_metaData.artist()); + } else if (m_metaData.comment() != oldMetaData.comment()) { + changed = true; + emit metaDataChanged(QMediaMetaData::Comment, m_metaData.comment()); + } else if (m_metaData.genre() != oldMetaData.genre()) { + changed = true; + emit metaDataChanged(QMediaMetaData::Genre, m_metaData.genre()); + } else if (m_metaData.year() != oldMetaData.year()) { + changed = true; + emit metaDataChanged(QMediaMetaData::Year, m_metaData.year()); + } else if (m_metaData.mediaType() != oldMetaData.mediaType()) { + changed = true; + emit metaDataChanged(QMediaMetaData::MediaType, m_metaData.mediaType()); + } else if (m_metaData.duration() != oldMetaData.duration()) { + changed = true; + emit metaDataChanged(QMediaMetaData::Duration, m_metaData.duration()); + } else if (m_metaData.audioBitRate() != oldMetaData.audioBitRate()) { + changed = true; + emit metaDataChanged(QMediaMetaData::AudioBitRate, m_metaData.audioBitRate()); + } else if (m_metaData.sampleRate() != oldMetaData.sampleRate()) { + changed = true; + emit metaDataChanged(QMediaMetaData::SampleRate, m_metaData.sampleRate()); + } else if (m_metaData.album() != oldMetaData.album()) { + changed = true; + emit metaDataChanged(QMediaMetaData::AlbumTitle, m_metaData.album()); + } else if (m_metaData.track() != oldMetaData.track()) { + changed = true; + emit metaDataChanged(QMediaMetaData::TrackNumber, m_metaData.track()); + } else if (m_metaData.resolution() != oldMetaData.resolution()) { + changed = true; + emit metaDataChanged(QMediaMetaData::Resolution, m_metaData.resolution()); + } + + if (changed) + emit metaDataChanged(); + + const bool metaDataAvailable = isMetaDataAvailable(); + if (metaDataAvailable != oldMetaDataAvailable) + emit metaDataAvailableChanged(metaDataAvailable); +} diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.h b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.h new file mode 100644 index 000000000..f824ca4d0 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 MMRENDERERMETADATAREADERCONTROL_H +#define MMRENDERERMETADATAREADERCONTROL_H + +#include "mmrenderermetadata.h" +#include <qmetadatareadercontrol.h> + +QT_BEGIN_NAMESPACE + +class MmRendererMetaDataReaderControl : public QMetaDataReaderControl +{ + Q_OBJECT +public: + explicit MmRendererMetaDataReaderControl(QObject *parent = 0); + + bool isMetaDataAvailable() const Q_DECL_OVERRIDE; + + QVariant metaData(const QString &key) const Q_DECL_OVERRIDE; + QStringList availableMetaData() const Q_DECL_OVERRIDE; + + void setMetaData(const MmRendererMetaData &data); + +private: + MmRendererMetaData m_metaData; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp new file mode 100644 index 000000000..0abdfec49 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** 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 "mmrendererplayervideorenderercontrol.h" + +#include "windowgrabber.h" + +#include <QCoreApplication> +#include <QDebug> +#include <QVideoSurfaceFormat> + +#include <mm/renderer.h> + +QT_BEGIN_NAMESPACE + +static int winIdCounter = 0; + +MmRendererPlayerVideoRendererControl::MmRendererPlayerVideoRendererControl(QObject *parent) + : QVideoRendererControl(parent) + , m_windowGrabber(new WindowGrabber(this)) + , m_context(0) + , m_videoId(-1) +{ + connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage)), SLOT(frameGrabbed(QImage))); +} + +MmRendererPlayerVideoRendererControl::~MmRendererPlayerVideoRendererControl() +{ + detachDisplay(); +} + +QAbstractVideoSurface *MmRendererPlayerVideoRendererControl::surface() const +{ + return m_surface; +} + +void MmRendererPlayerVideoRendererControl::setSurface(QAbstractVideoSurface *surface) +{ + m_surface = QPointer<QAbstractVideoSurface>(surface); +} + +void MmRendererPlayerVideoRendererControl::attachDisplay(mmr_context_t *context) +{ + if (m_videoId != -1) { + qWarning() << "MmRendererPlayerVideoRendererControl: Video output already attached!"; + return; + } + + if (!context) { + qWarning() << "MmRendererPlayerVideoRendererControl: No media player context!"; + return; + } + + const QByteArray windowGroupId = m_windowGrabber->windowGroupId(); + if (windowGroupId.isEmpty()) { + qWarning() << "MmRendererPlayerVideoRendererControl: Unable to find window group"; + return; + } + + const QString windowName = QStringLiteral("MmRendererPlayerVideoRendererControl_%1_%2") + .arg(winIdCounter++) + .arg(QCoreApplication::applicationPid()); + + m_windowGrabber->setWindowId(windowName.toLatin1()); + + // Start with an invisible window, because we just want to grab the frames from it. + const QString videoDeviceUrl = QStringLiteral("screen:?winid=%1&wingrp=%2&initflags=invisible&nodstviewport=1") + .arg(windowName) + .arg(QString::fromLatin1(windowGroupId)); + + m_videoId = mmr_output_attach(context, videoDeviceUrl.toLatin1(), "video"); + if (m_videoId == -1) { + qWarning() << "mmr_output_attach() for video failed"; + return; + } + + m_context = context; +} + +void MmRendererPlayerVideoRendererControl::detachDisplay() +{ + m_windowGrabber->stop(); + + if (m_surface) + m_surface->stop(); + + if (m_context && m_videoId != -1) + mmr_output_detach(m_context, m_videoId); + + m_context = 0; + m_videoId = -1; +} + +void MmRendererPlayerVideoRendererControl::pause() +{ + m_windowGrabber->pause(); +} + +void MmRendererPlayerVideoRendererControl::resume() +{ + m_windowGrabber->resume(); +} + +void MmRendererPlayerVideoRendererControl::frameGrabbed(const QImage &frame) +{ + if (m_surface) { + if (!m_surface->isActive()) { + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + } else { + if (m_surface->surfaceFormat().frameSize() != frame.size()) { + m_surface->stop(); + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + } + } + + m_surface->present(frame.copy()); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h new file mode 100644 index 000000000..4e271ad5d --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 MMRENDERERPLAYERVIDEORENDERERCONTROL_H +#define MMRENDERERPLAYERVIDEORENDERERCONTROL_H + +#include <QPointer> +#include <qabstractvideosurface.h> +#include <qvideorenderercontrol.h> + +typedef struct mmr_context mmr_context_t; + +QT_BEGIN_NAMESPACE + +class WindowGrabber; + +class MmRendererPlayerVideoRendererControl : public QVideoRendererControl +{ + Q_OBJECT +public: + explicit MmRendererPlayerVideoRendererControl(QObject *parent = 0); + ~MmRendererPlayerVideoRendererControl(); + + QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE; + void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE; + + // Called by media control + void attachDisplay(mmr_context_t *context); + void detachDisplay(); + void pause(); + void resume(); + +private Q_SLOTS: + void frameGrabbed(const QImage &frame); + +private: + QPointer<QAbstractVideoSurface> m_surface; + + WindowGrabber* m_windowGrabber; + mmr_context_t *m_context; + + int m_videoId; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/mmrendererutil.cpp b/src/plugins/qnx/mediaplayer/mmrendererutil.cpp new file mode 100644 index 000000000..61f85f3d9 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrendererutil.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "mmrendererutil.h" + +#include <QDebug> +#include <QDir> +#include <QFile> +#include <QString> +#include <QXmlStreamReader> + +#include <mm/renderer.h> + +QT_BEGIN_NAMESPACE + +struct MmError { + int errorCode; + const char *name; +}; + +#define MM_ERROR_ENTRY(error) { error, #error } +static const MmError mmErrors[] = { + MM_ERROR_ENTRY(MMR_ERROR_NONE), + MM_ERROR_ENTRY(MMR_ERROR_UNKNOWN ), + MM_ERROR_ENTRY(MMR_ERROR_INVALID_PARAMETER ), + MM_ERROR_ENTRY(MMR_ERROR_INVALID_STATE), + MM_ERROR_ENTRY(MMR_ERROR_UNSUPPORTED_VALUE), + MM_ERROR_ENTRY(MMR_ERROR_UNSUPPORTED_MEDIA_TYPE), + MM_ERROR_ENTRY(MMR_ERROR_MEDIA_PROTECTED), + MM_ERROR_ENTRY(MMR_ERROR_UNSUPPORTED_OPERATION), + MM_ERROR_ENTRY(MMR_ERROR_READ), + MM_ERROR_ENTRY(MMR_ERROR_WRITE), + MM_ERROR_ENTRY(MMR_ERROR_MEDIA_UNAVAILABLE), + MM_ERROR_ENTRY(MMR_ERROR_MEDIA_CORRUPTED), + MM_ERROR_ENTRY(MMR_ERROR_OUTPUT_UNAVAILABLE), + MM_ERROR_ENTRY(MMR_ERROR_NO_MEMORY), + MM_ERROR_ENTRY(MMR_ERROR_RESOURCE_UNAVAILABLE), + MM_ERROR_ENTRY(MMR_ERROR_MEDIA_DRM_NO_RIGHTS), + MM_ERROR_ENTRY(MMR_ERROR_DRM_CORRUPTED_DATA_STORE), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OUTPUT_PROTECTION), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_HDMI), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_DISPLAYPORT), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_DVI), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_ANALOG_VIDEO), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_ANALOG_AUDIO), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_TOSLINK), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_SPDIF), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_BLUETOOTH), + MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_WIRELESSHD), +}; +static const unsigned int numMmErrors = sizeof(mmErrors) / sizeof(MmError); + +QString mmErrorMessage(const QString &msg, mmr_context_t *context, int *errorCode) +{ + const mmr_error_info_t * const mmError = mmr_error_info(context); + + if (errorCode) + *errorCode = mmError->error_code; + + if (mmError->error_code < numMmErrors) { + return QString("%1: %2 (code %3)").arg(msg).arg(mmErrors[mmError->error_code].name) + .arg(mmError->error_code); + } else { + return QString("%1: Unknown error code %2").arg(msg).arg(mmError->error_code); + } +} + +bool checkForDrmPermission() +{ + QDir sandboxDir = QDir::home(); // always returns 'data' directory + sandboxDir.cdUp(); // change to app sandbox directory + + QFile file(sandboxDir.filePath("app/native/bar-descriptor.xml")); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "checkForDrmPermission: Unable to open bar-descriptor.xml"; + return false; + } + + QXmlStreamReader reader(&file); + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.name() == QLatin1String("action") + || reader.name() == QLatin1String("permission")) { + if (reader.readElementText().trimmed() == QLatin1String("access_protected_media")) + return true; + } + } + + return false; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/audio/qnxaudioutils.h b/src/plugins/qnx/mediaplayer/mmrendererutil.h index ddd30b191..4b9adc27e 100644 --- a/src/plugins/qnx/audio/qnxaudioutils.h +++ b/src/plugins/qnx/mediaplayer/mmrendererutil.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Research In Motion +** Copyright (C) 2012 Research In Motion ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -38,19 +38,20 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef MMRENDERERUTIL_H +#define MMRENDERERUTIL_H -#ifndef QNXAUDIOUTILS_H -#define QNXAUDIOUTILS_H +#include <QtCore/qglobal.h> -#include "qaudiosystem.h" -#include <sys/asoundlib.h> +typedef struct mmr_context mmr_context_t; QT_BEGIN_NAMESPACE -namespace QnxAudioUtils -{ - snd_pcm_channel_params_t formatToChannelParams(const QAudioFormat &format, QAudio::Mode mode, int fragmentSize); -} +class QString; + +QString mmErrorMessage(const QString &msg, mmr_context_t *context, int * errorCode = 0); + +bool checkForDrmPermission(); QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp new file mode 100644 index 000000000..c35c6d1ad --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "mmrenderervideowindowcontrol.h" +#include "mmrendererutil.h" +#include <QtCore/qdebug.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/qpa/qplatformnativeinterface.h> +#include <QtGui/qscreen.h> +#include <QtGui/qwindow.h> +#include <mm/renderer.h> + +QT_BEGIN_NAMESPACE + +static int winIdCounter = 0; + +MmRendererVideoWindowControl::MmRendererVideoWindowControl(QObject *parent) + : QVideoWindowControl(parent), + m_videoId(-1), + m_winId(0), + m_context(0), + m_fullscreen(false), + m_aspectRatioMode(Qt::IgnoreAspectRatio), + m_window(0), + m_hue(0), + m_brightness(0), + m_contrast(0), + m_saturation(0) +{ +} + +MmRendererVideoWindowControl::~MmRendererVideoWindowControl() +{ +} + +WId MmRendererVideoWindowControl::winId() const +{ + return m_winId; +} + +void MmRendererVideoWindowControl::setWinId(WId id) +{ + m_winId = id; +} + +QRect MmRendererVideoWindowControl::displayRect() const +{ + return m_displayRect ; +} + +void MmRendererVideoWindowControl::setDisplayRect(const QRect &rect) +{ + if (m_displayRect != rect) { + m_displayRect = rect; + updateVideoPosition(); + } +} + +bool MmRendererVideoWindowControl::isFullScreen() const +{ + return m_fullscreen; +} + +void MmRendererVideoWindowControl::setFullScreen(bool fullScreen) +{ + if (m_fullscreen != fullScreen) { + m_fullscreen = fullScreen; + updateVideoPosition(); + emit fullScreenChanged(m_fullscreen); + } +} + +void MmRendererVideoWindowControl::repaint() +{ + // Nothing we can or should do here +} + +QSize MmRendererVideoWindowControl::nativeSize() const +{ + return QSize(m_metaData.width(), m_metaData.height()); +} + +Qt::AspectRatioMode MmRendererVideoWindowControl::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void MmRendererVideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode) +{ + m_aspectRatioMode = mode; +} + +int MmRendererVideoWindowControl::brightness() const +{ + return m_brightness; +} + +void MmRendererVideoWindowControl::setBrightness(int brightness) +{ + if (m_brightness != brightness) { + m_brightness = brightness; + updateBrightness(); + emit brightnessChanged(m_brightness); + } +} + +int MmRendererVideoWindowControl::contrast() const +{ + return m_contrast; +} + +void MmRendererVideoWindowControl::setContrast(int contrast) +{ + if (m_contrast != contrast) { + m_contrast = contrast; + updateContrast(); + emit contrastChanged(m_contrast); + } +} + +int MmRendererVideoWindowControl::hue() const +{ + return m_hue; +} + +void MmRendererVideoWindowControl::setHue(int hue) +{ + if (m_hue != hue) { + m_hue = hue; + updateHue(); + emit hueChanged(m_hue); + } +} + +int MmRendererVideoWindowControl::saturation() const +{ + return m_saturation; +} + +void MmRendererVideoWindowControl::setSaturation(int saturation) +{ + if (m_saturation != saturation) { + m_saturation = saturation; + updateSaturation(); + emit saturationChanged(m_saturation); + } +} + +void MmRendererVideoWindowControl::attachDisplay(mmr_context_t *context) +{ + if (m_videoId != -1) { + qDebug() << "MmRendererVideoWindowControl: Video output already attached!"; + return; + } + + if (!context) { + qDebug() << "MmRendererVideoWindowControl: No media player context!"; + return; + } + + QWindow *window = findWindow(m_winId); + if (!window) { + qDebug() << "MmRendererVideoWindowControl: No video window!"; + return; + } + + QPlatformNativeInterface * const nativeInterface = QGuiApplication::platformNativeInterface(); + if (!nativeInterface) { + qDebug() << "MmRendererVideoWindowControl: Unable to get platform native interface"; + return; + } + + const char * const groupNameData = static_cast<const char *>( + nativeInterface->nativeResourceForWindow("windowGroup", window)); + if (!groupNameData) { + qDebug() << "MmRendererVideoWindowControl: Unable to find window group for window" << window; + return; + } + + const QString groupName = QString::fromLatin1(groupNameData); + m_windowName = QString("MmRendererVideoWindowControl_%1_%2").arg(winIdCounter++) + .arg(QCoreApplication::applicationPid()); + + nativeInterface->setWindowProperty(window->handle(), + QStringLiteral("mmRendererWindowName"), m_windowName); + + // Start with an invisible window. If it would be visible right away, it would be at the wrong + // position, and we can only change the position once we get the window handle. + const QString videoDeviceUrl = + QString("screen:?winid=%1&wingrp=%2&initflags=invisible&nodstviewport=1").arg(m_windowName).arg(groupName); + + m_videoId = mmr_output_attach(context, videoDeviceUrl.toLatin1(), "video"); + if (m_videoId == -1) { + qDebug() << mmErrorMessage("mmr_output_attach() for video failed", context); + return; + } + + m_context = context; + updateVideoPosition(); + updateHue(); + updateContrast(); + updateBrightness(); + updateSaturation(); +} + +void MmRendererVideoWindowControl::updateVideoPosition() +{ + QWindow * const window = findWindow(m_winId); + if (m_context && m_videoId != -1 && window) { + QPoint topLeft = m_fullscreen ? + QPoint(0,0) : + window->mapToGlobal(m_displayRect.topLeft()); + + QScreen * const screen = window->screen(); + int width = m_fullscreen ? + screen->size().width() : + m_displayRect.width(); + int height = m_fullscreen ? + screen->size().height() : + m_displayRect.height(); + + if (m_metaData.hasVideo()) { // We need the source size to do aspect ratio scaling + const qreal sourceRatio = m_metaData.width() / static_cast<float>(m_metaData.height()); + const qreal targetRatio = width / static_cast<float>(height); + + if (m_aspectRatioMode == Qt::KeepAspectRatio) { + if (targetRatio < sourceRatio) { + // Need to make height smaller + const int newHeight = width / sourceRatio; + const int heightDiff = height - newHeight; + topLeft.ry() += heightDiff / 2; + height = newHeight; + } else { + // Need to make width smaller + const int newWidth = sourceRatio * height; + const int widthDiff = width - newWidth; + topLeft.rx() += widthDiff / 2; + width = newWidth; + } + + } else if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) { + if (targetRatio < sourceRatio) { + // Need to make width larger + const int newWidth = sourceRatio * height; + const int widthDiff = newWidth - width; + topLeft.rx() -= widthDiff / 2; + width = newWidth; + } else { + // Need to make height larger + const int newHeight = width / sourceRatio; + const int heightDiff = newHeight - height; + topLeft.ry() -= heightDiff / 2; + height = newHeight; + } + } + } + + if (m_window != 0) { + const int position[2] = { topLeft.x(), topLeft.y() }; + const int size[2] = { width, height }; + const int visible = m_displayRect.isValid(); + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, position) != 0) + perror("Setting video position failed"); + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, size) != 0) + perror("Setting video size failed"); + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &visible) != 0) + perror("Setting video visibility failed"); + } + } +} + +void MmRendererVideoWindowControl::updateBrightness() +{ + if (m_window != 0) { + const int backendValue = m_brightness * 2.55f; + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BRIGHTNESS, &backendValue) != 0) + perror("Setting brightness failed"); + } +} + +void MmRendererVideoWindowControl::updateContrast() +{ + if (m_window != 0) { + const int backendValue = m_contrast * 1.27f; + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_CONTRAST, &backendValue) != 0) + perror("Setting contrast failed"); + } +} + +void MmRendererVideoWindowControl::updateHue() +{ + if (m_window != 0) { + const int backendValue = m_hue * 1.27f; + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_HUE, &backendValue) != 0) + perror("Setting hue failed"); + } +} + +void MmRendererVideoWindowControl::updateSaturation() +{ + if (m_window != 0) { + const int backendValue = m_saturation * 1.27f; + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SATURATION, &backendValue) != 0) + perror("Setting saturation failed"); + } +} + +void MmRendererVideoWindowControl::detachDisplay() +{ + if (m_context && m_videoId != -1) + mmr_output_detach(m_context, m_videoId); + + m_context = 0; + m_videoId = -1; + m_metaData.clear(); + m_windowName.clear(); + m_window = 0; + m_hue = 0; + m_brightness = 0; + m_contrast = 0; + m_saturation = 0; +} + +void MmRendererVideoWindowControl::setMetaData(const MmRendererMetaData &metaData) +{ + m_metaData = metaData; + emit nativeSizeChanged(); + + // To handle the updated source size data + updateVideoPosition(); +} + +void MmRendererVideoWindowControl::screenEventHandler(const screen_event_t &screen_event) +{ + int eventType; + if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) { + perror("MmRendererVideoWindowControl: Failed to query screen event type"); + return; + } + + if (eventType != SCREEN_EVENT_CREATE) + return; + + screen_window_t window = 0; + if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) { + perror("MmRendererVideoWindowControl: Failed to query window property"); + return; + } + + const int maxIdStrLength = 128; + char idString[maxIdStrLength]; + if (screen_get_window_property_cv(window, SCREEN_PROPERTY_ID_STRING, maxIdStrLength, idString) != 0) { + perror("MmRendererVideoWindowControl: Failed to query window ID string"); + return; + } + + if (m_windowName == idString) { + m_window = window; + updateVideoPosition(); + + const int visibleFlag = 1; + if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &visibleFlag) != 0) { + perror("MmRendererVideoWindowControl: Failed to make window visible"); + return; + } + } +} + +QWindow *MmRendererVideoWindowControl::findWindow(WId id) const +{ + Q_FOREACH (QWindow *window, QGuiApplication::allWindows()) + if (window->winId() == id) + return window; + return 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.h b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.h new file mode 100644 index 000000000..cfc9603bb --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 MMRENDERERVIDEOWINDOWCONTROL_H +#define MMRENDERERVIDEOWINDOWCONTROL_H + +#include "mmrenderermetadata.h" +#include <qvideowindowcontrol.h> +#include <screen/screen.h> + +typedef struct mmr_context mmr_context_t; + +QT_BEGIN_NAMESPACE + +class MmRendererVideoWindowControl : public QVideoWindowControl +{ + Q_OBJECT +public: + explicit MmRendererVideoWindowControl(QObject *parent = 0); + ~MmRendererVideoWindowControl(); + + WId winId() const Q_DECL_OVERRIDE; + void setWinId(WId id) Q_DECL_OVERRIDE; + + QRect displayRect() const Q_DECL_OVERRIDE; + void setDisplayRect(const QRect &rect) Q_DECL_OVERRIDE; + + bool isFullScreen() const Q_DECL_OVERRIDE; + void setFullScreen(bool fullScreen) Q_DECL_OVERRIDE; + + void repaint() Q_DECL_OVERRIDE; + + QSize nativeSize() const Q_DECL_OVERRIDE; + + Qt::AspectRatioMode aspectRatioMode() const Q_DECL_OVERRIDE; + void setAspectRatioMode(Qt::AspectRatioMode mode) Q_DECL_OVERRIDE; + + int brightness() const Q_DECL_OVERRIDE; + void setBrightness(int brightness) Q_DECL_OVERRIDE; + + int contrast() const Q_DECL_OVERRIDE; + void setContrast(int contrast) Q_DECL_OVERRIDE; + + int hue() const Q_DECL_OVERRIDE; + void setHue(int hue) Q_DECL_OVERRIDE; + + int saturation() const Q_DECL_OVERRIDE; + void setSaturation(int saturation) Q_DECL_OVERRIDE; + + // + // Called by media control + // + void detachDisplay(); + void attachDisplay(mmr_context_t *context); + void setMetaData(const MmRendererMetaData &metaData); + void screenEventHandler(const screen_event_t &event); + +private: + QWindow *findWindow(WId id) const; + void updateVideoPosition(); + void updateBrightness(); + void updateContrast(); + void updateHue(); + void updateSaturation(); + + int m_videoId; + WId m_winId; + QRect m_displayRect; + mmr_context_t *m_context; + bool m_fullscreen; + MmRendererMetaData m_metaData; + Qt::AspectRatioMode m_aspectRatioMode; + QString m_windowName; + screen_window_t m_window; + int m_hue; + int m_brightness; + int m_contrast; + int m_saturation; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp new file mode 100644 index 000000000..eb0842fb9 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** 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 "ppsmediaplayercontrol.h" +#include "mmrenderervideowindowcontrol.h" + +#include <QtCore/qfile.h> +#include <QtCore/qsocketnotifier.h> +#include <QtCore/private/qcore_unix_p.h> + +#include <screen/screen.h> +#include <sys/pps.h> + +QT_BEGIN_NAMESPACE + +PpsMediaPlayerControl::PpsMediaPlayerControl(QObject *parent) + : MmRendererMediaPlayerControl(parent), + m_ppsStatusNotifier(0), + m_ppsStatusFd(-1), + m_ppsStateNotifier(0), + m_ppsStateFd(-1) + , m_previouslySeenState("STOPPED") +{ + openConnection(); +} + +PpsMediaPlayerControl::~PpsMediaPlayerControl() +{ + destroy(); +} + +void PpsMediaPlayerControl::startMonitoring(int, const QString &contextName) +{ + const QString ppsContextPath = QStringLiteral("/pps/services/multimedia/renderer/context/%1/").arg(contextName); + const QString ppsStatusPath = ppsContextPath + QStringLiteral("/status"); + + Q_ASSERT(m_ppsStatusFd == -1); + errno = 0; + m_ppsStatusFd = qt_safe_open(QFile::encodeName(ppsStatusPath).constData(), O_RDONLY); + if (m_ppsStatusFd == -1) { + emitPError(QStringLiteral("Unable to open %1: %2").arg(ppsStatusPath, qt_error_string(errno))); + return; + } + + Q_ASSERT(!m_ppsStatusNotifier); + m_ppsStatusNotifier = new QSocketNotifier(m_ppsStatusFd, QSocketNotifier::Read); + connect(m_ppsStatusNotifier, SIGNAL(activated(int)), this, SLOT(ppsReadyRead(int))); + + + const QString ppsStatePath = ppsContextPath + QStringLiteral("/state"); + + Q_ASSERT(m_ppsStateFd == -1); + errno = 0; + m_ppsStateFd = qt_safe_open(QFile::encodeName(ppsStatePath).constData(), O_RDONLY); + if (m_ppsStateFd == -1) { + emitPError(QStringLiteral("Unable to open %1: %2").arg(ppsStatePath, qt_error_string(errno))); + return; + } + + Q_ASSERT(!m_ppsStateNotifier); + m_ppsStateNotifier = new QSocketNotifier(m_ppsStateFd, QSocketNotifier::Read); + connect(m_ppsStateNotifier, SIGNAL(activated(int)), this, SLOT(ppsReadyRead(int))); + + //ensure we receive any initial state + ppsReadyRead(m_ppsStatusFd); + ppsReadyRead(m_ppsStateFd); +} + +void PpsMediaPlayerControl::stopMonitoring() +{ + + if (m_ppsStatusFd != -1) { + ::close(m_ppsStatusFd); + m_ppsStatusFd = -1; + } + + delete m_ppsStatusNotifier; + m_ppsStatusNotifier = 0; + + if (m_ppsStateFd != -1) { + ::close(m_ppsStateFd); + m_ppsStateFd = -1; + } + + delete m_ppsStateNotifier; + m_ppsStateNotifier = 0; +} + +bool PpsMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +{ + Q_UNUSED(result) + if (eventType == "screen_event_t") { + screen_event_t event = static_cast<screen_event_t>(message); + if (MmRendererVideoWindowControl *control = videoWindowControl()) + control->screenEventHandler(event); + } + + return false; +} + +void PpsMediaPlayerControl::ppsReadyRead(int fd) +{ + Q_ASSERT(fd == m_ppsStateFd || fd == m_ppsStatusFd); + const int bufferSize = 2048; + char buffer[bufferSize]; + const ssize_t nread = qt_safe_read(fd, buffer, bufferSize - 1); + if (nread < 0) { + //TODO emit error? + } + + if (nread == 0) { + return; + } + + // nread is the real space necessary, not the amount read. + if (static_cast<size_t>(nread) > bufferSize - 1) { + //TODO emit error? + qCritical("BBMediaPlayerControl: PPS buffer size too short; need %u.", nread + 1); + return; + } + + buffer[nread] = 0; + + pps_decoder_t decoder; + + if (pps_decoder_initialize(&decoder, buffer) != PPS_DECODER_OK) { + //TODO emit error? + qCritical("Could not initialize pps_decoder"); + pps_decoder_cleanup(&decoder); + return; + } + + pps_decoder_push(&decoder, 0); + + const char *value = 0; + if (pps_decoder_get_string(&decoder, "bufferlevel", &value) == PPS_DECODER_OK) { + setMmBufferStatus(QString::fromLatin1(value)); + } + + if (pps_decoder_get_string(&decoder, "state", &value) == PPS_DECODER_OK) { + const QByteArray state = value; + if (state != m_previouslySeenState && state == "STOPPED") + handleMmStopped(); + m_previouslySeenState = state; + } + + if (pps_decoder_get_string(&decoder, "position", &value) == PPS_DECODER_OK) { + const QByteArray valueBa = QByteArray(value); + bool ok; + const qint64 position = valueBa.toLongLong(&ok); + if (!ok) { + qCritical("Could not parse position from '%s'", valueBa.constData()); + } else { + setMmPosition(position); + } + } + + pps_decoder_cleanup(&decoder); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h new file mode 100644 index 000000000..e00d44dfd --- /dev/null +++ b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 PPSMEDIAPLAYERCONTROL_H +#define PPSMEDIAPLAYERCONTROL_H + +#include "mmrenderermediaplayercontrol.h" + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class PpsMediaPlayerControl Q_DECL_FINAL : public MmRendererMediaPlayerControl +{ + Q_OBJECT +public: + explicit PpsMediaPlayerControl(QObject *parent = 0); + ~PpsMediaPlayerControl(); + + void startMonitoring(int contextId, const QString &contextName) Q_DECL_OVERRIDE; + void stopMonitoring() Q_DECL_OVERRIDE; + + bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void ppsReadyRead(int fd); + +private: + QSocketNotifier *m_ppsStatusNotifier; + int m_ppsStatusFd; + QSocketNotifier *m_ppsStateNotifier; + int m_ppsStateFd; + QByteArray m_previouslySeenState; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/neutrino_mediaservice.json b/src/plugins/qnx/neutrino_mediaservice.json new file mode 100644 index 000000000..919368d73 --- /dev/null +++ b/src/plugins/qnx/neutrino_mediaservice.json @@ -0,0 +1,4 @@ +{ + "Keys": ["neutrinomultimedia"], + "Services": ["org.qt-project.qt.mediaplayer"] +} diff --git a/src/plugins/qnx/neutrinoserviceplugin.cpp b/src/plugins/qnx/neutrinoserviceplugin.cpp new file mode 100644 index 000000000..423af1a84 --- /dev/null +++ b/src/plugins/qnx/neutrinoserviceplugin.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "neutrinoserviceplugin.h" + +#include "mmrenderermediaplayerservice.h" + +QT_BEGIN_NAMESPACE + +NeutrinoServicePlugin::NeutrinoServicePlugin() +{ +} + +QMediaService *NeutrinoServicePlugin::create(const QString &key) +{ + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) + return new MmRendererMediaPlayerService(); + + return 0; +} + +void NeutrinoServicePlugin::release(QMediaService *service) +{ + delete service; +} + +QMediaServiceProviderHint::Features NeutrinoServicePlugin::supportedFeatures(const QByteArray &service) const +{ + Q_UNUSED(service) + return QMediaServiceProviderHint::Features(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/neutrinoserviceplugin.h b/src/plugins/qnx/neutrinoserviceplugin.h new file mode 100644 index 000000000..2fc28233f --- /dev/null +++ b/src/plugins/qnx/neutrinoserviceplugin.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 NEUTRINOSERVICEPLUGIN_H +#define NEUTRINOSERVICEPLUGIN_H + +#include <qmediaserviceproviderplugin.h> + +QT_BEGIN_NAMESPACE + +class NeutrinoServicePlugin + : public QMediaServiceProviderPlugin, + public QMediaServiceFeaturesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceFeaturesInterface) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "neutrino_mediaservice.json") +public: + NeutrinoServicePlugin(); + + QMediaService *create(const QString &key) Q_DECL_OVERRIDE; + void release(QMediaService *service) Q_DECL_OVERRIDE; + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro index 3049729b8..f01562116 100644 --- a/src/plugins/qnx/qnx.pro +++ b/src/plugins/qnx/qnx.pro @@ -1,3 +1,22 @@ -TEMPLATE = subdirs +TARGET = qtmedia_qnx +QT += multimedia-private gui-private -SUBDIRS = audio +PLUGIN_TYPE=mediaservice +PLUGIN_CLASS_NAME = BbServicePlugin +load(qt_plugin) + +LIBS += -lscreen + +include(common/common.pri) +include(mediaplayer/mediaplayer.pri) + +blackberry { + include(camera/camera.pri) + HEADERS += bbserviceplugin.h + SOURCES += bbserviceplugin.cpp + OTHER_FILES += blackberry_mediaservice.json +} else { + HEADERS += neutrinoserviceplugin.h + SOURCES += neutrinoserviceplugin.cpp + OTHER_FILES += neutrino_mediaservice.json +} |