diff options
Diffstat (limited to 'src/plugins/symbian/openmaxal/mediarecorder')
16 files changed, 3444 insertions, 0 deletions
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/mediarecorder.pri b/src/plugins/symbian/openmaxal/mediarecorder/mediarecorder.pri new file mode 100644 index 000000000..ee78e8348 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/mediarecorder.pri @@ -0,0 +1,24 @@ +INCLUDEPATH += $$PWD + +# Input +HEADERS += \ + $$PWD/qxarecordmediaservice.h \ + $$PWD/qxarecordsession.h \ + $$PWD/qxaaudioendpointselector.h \ + $$PWD/qxaaudioencodercontrol.h \ + $$PWD/qxamediacontainercontrol.h \ + $$PWD/qxamediarecordercontrol.h \ + $$PWD/xarecordsessionimpl.h \ + $$PWD/xarecordsessioncommon.h + +SOURCES += \ + $$PWD/qxarecordmediaservice.cpp \ + $$PWD/qxarecordsession.cpp \ + $$PWD/qxaaudioendpointselector.cpp \ + $$PWD/qxaaudioencodercontrol.cpp \ + $$PWD/qxamediacontainercontrol.cpp \ + $$PWD/qxamediarecordercontrol.cpp \ + $$PWD/xarecordsessionimpl.cpp + +LIBS += \ + -lbafl diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.cpp new file mode 100644 index 000000000..2826f79a2 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxaaudioencodercontrol.h" +#include "qxarecordsession.h" +#include "qxacommon.h" + +QXAAudioEncoderControl::QXAAudioEncoderControl(QXARecordSession *session, QObject *parent) +:QAudioEncoderControl(parent), m_session(session) +{ +} + +QXAAudioEncoderControl::~QXAAudioEncoderControl() +{ + QT_TRACE_FUNCTION_ENTRY_EXIT; +} + +QStringList QXAAudioEncoderControl::supportedAudioCodecs() const +{ + if (m_session) + return m_session->supportedAudioCodecs(); + return QStringList(); +} + +QString QXAAudioEncoderControl::codecDescription(const QString &codecName) const +{ + if (m_session) + return m_session->codecDescription(codecName); + return QString(); +} + +QList<int> QXAAudioEncoderControl::supportedSampleRates( + const QAudioEncoderSettings &settings, + bool *continuous) const +{ + if (m_session) + return m_session->supportedSampleRates(settings, continuous); + return QList<int>(); +} + +QAudioEncoderSettings QXAAudioEncoderControl::audioSettings() const +{ + if (m_session) + return m_session->audioSettings(); + return QAudioEncoderSettings(); +} + +void QXAAudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings) +{ + if (m_session) + m_session->setAudioSettings(settings); +} + +QStringList QXAAudioEncoderControl::supportedEncodingOptions(const QString &codec) const +{ + if (m_session) + return m_session->supportedEncodingOptions(codec); + return QStringList(); +} + +QVariant QXAAudioEncoderControl::encodingOption(const QString &codec, const QString &name) const +{ + if (m_session) + return m_session->encodingOption(codec, name); + return QVariant(); +} + +void QXAAudioEncoderControl::setEncodingOption( + const QString &codec, const QString &name, const QVariant &value) +{ + if (m_session) + m_session->setEncodingOption(codec, name, value); +} diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.h b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.h new file mode 100644 index 000000000..117d36fdc --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXAAUDIOENCODERCONTROL_H +#define QXAAUDIOENCODERCONTROL_H + +#include <qaudioencodercontrol.h> + +QT_USE_NAMESPACE + +/* + * This class implements QAudioEncoderControl interface. + */ +class QXARecordSession; + +class QXAAudioEncoderControl : public QAudioEncoderControl +{ + Q_OBJECT + +public: + QXAAudioEncoderControl(QXARecordSession *session, QObject *parent = 0); + virtual ~QXAAudioEncoderControl(); + + QStringList supportedAudioCodecs() const; + QString codecDescription(const QString &codecName) const; + + QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, + bool *continuous = 0) const; + + QAudioEncoderSettings audioSettings() const; + void setAudioSettings(const QAudioEncoderSettings &settings); + + QStringList supportedEncodingOptions(const QString &codec) const; + QVariant encodingOption(const QString &codec, const QString &name) const; + void setEncodingOption(const QString &codec, const QString &name, const QVariant &value); + +private: + QXARecordSession *m_session; +}; + +#endif /* QXAAUDIOENCODERCONTROL_H */ diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.cpp new file mode 100644 index 000000000..7e546595c --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxaaudioendpointselector.h" +#include "qxarecordsession.h" +#include "qxacommon.h" + +QXAAudioEndpointSelector::QXAAudioEndpointSelector(QXARecordSession *session, QObject *parent) +:QAudioEndpointSelector(parent), m_session(session) +{ + connect(m_session, SIGNAL(availableAudioInputsChanged()), + this, SLOT(availableAudioInputsChanged())); + connect(m_session, SIGNAL(activeEndpointChanged(QString)), + this, SIGNAL(activeEndpointChanged(QString))); +} + +QXAAudioEndpointSelector::~QXAAudioEndpointSelector() +{ + QT_TRACE_FUNCTION_ENTRY_EXIT; +} + +QList<QString> QXAAudioEndpointSelector::availableEndpoints() const +{ + if (m_session) + return m_session->availableEndpoints(); + return QList<QString>(); +} + +QString QXAAudioEndpointSelector::endpointDescription(const QString &name) const +{ + if (m_session) + return m_session->endpointDescription(name); + return QString(); +} + +QString QXAAudioEndpointSelector::defaultEndpoint() const +{ + if (m_session) + return m_session->defaultEndpoint(); + return QString(); +} + +QString QXAAudioEndpointSelector::activeEndpoint() const +{ + if (m_session) + return m_session->activeEndpoint(); + return QString(); +} + +void QXAAudioEndpointSelector::setActiveEndpoint(const QString &name) +{ + if (m_session) + m_session->setActiveEndpoint(name); +} + +void QXAAudioEndpointSelector::availableAudioInputsChanged() + { + emit availableEndpointsChanged(); + } + diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.h b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.h new file mode 100644 index 000000000..5fbadbc64 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXAAUDIOENDPOINTSELECTOR_H +#define QXAAUDIOENDPOINTSELECTOR_H + +#include <qaudioendpointselector.h> + +QT_USE_NAMESPACE + +/* + * This class implements QAudioEncoderControl interface. + */ +class QXARecordSession; + +class QXAAudioEndpointSelector : public QAudioEndpointSelector +{ + Q_OBJECT + +public: + QXAAudioEndpointSelector(QXARecordSession *session, QObject *parent); + ~QXAAudioEndpointSelector(); + + QList<QString> availableEndpoints() const; + QString endpointDescription(const QString &name) const; + QString defaultEndpoint() const; + QString activeEndpoint() const; + +public Q_SLOTS: + void setActiveEndpoint(const QString &name); + +private Q_SLOTS: + void availableAudioInputsChanged(); + +private: + QXARecordSession *m_session; +}; + +#endif /* QXAAUDIOENDPOINTSELECTOR_H */ diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.cpp new file mode 100644 index 000000000..0d97fd5e5 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxamediacontainercontrol.h" +#include "qxarecordsession.h" +#include "qxacommon.h" + +QXAMediaContainerControl::QXAMediaContainerControl(QXARecordSession *session, QObject *parent) +:QMediaContainerControl(parent), m_session(session) +{ +} + +QXAMediaContainerControl::~QXAMediaContainerControl() +{ + QT_TRACE_FUNCTION_ENTRY_EXIT; +} + +QStringList QXAMediaContainerControl::supportedContainers() const +{ + if (m_session) + return m_session->supportedContainers(); + return QStringList(); +} + +QString QXAMediaContainerControl::containerMimeType() const +{ + if (m_session) + return m_session->containerMimeType(); + return QString(); +} + +void QXAMediaContainerControl::setContainerMimeType(const QString &formatMimeType) +{ + if (m_session) + m_session->setContainerMimeType(formatMimeType); +} + +QString QXAMediaContainerControl::containerDescription(const QString &formatMimeType) const +{ + if (m_session) + return m_session->containerDescription(formatMimeType); + return QString(); +} diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.h b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.h new file mode 100644 index 000000000..4b05fc190 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXAMEDIACONTAINERCONTROL_H +#define QXAMEDIACONTAINERCONTROL_H + +#include <qmediacontainercontrol.h> + +QT_USE_NAMESPACE + +/* + * This class implements QMediaContainerControl interface. + */ +class QXARecordSession; + +class QXAMediaContainerControl : public QMediaContainerControl +{ + Q_OBJECT + +public: + QXAMediaContainerControl(QXARecordSession *session, QObject *parent = 0); + virtual ~QXAMediaContainerControl(); + + QStringList supportedContainers() const; + QString containerMimeType() const; + void setContainerMimeType(const QString &formatMimeType); + QString containerDescription(const QString &formatMimeType) const; + +private: + QXARecordSession *m_session; +}; + +#endif /* QXAMEDIACONTAINERCONTROL_H */ diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.cpp new file mode 100644 index 000000000..330edf008 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxamediarecordercontrol.h" +#include "qxarecordsession.h" +#include "qxacommon.h" + +QXAMediaRecoderControl::QXAMediaRecoderControl(QXARecordSession *session, QObject *parent) +:QMediaRecorderControl(parent), m_session(session) +{ + connect(m_session, SIGNAL(stateChanged(QMediaRecorder::State)), + this, SIGNAL(stateChanged(QMediaRecorder::State))); + connect(m_session, SIGNAL(error(int,QString)), + this,SIGNAL(error(int,QString))); + connect(m_session, SIGNAL(durationChanged(qint64)), + this, SIGNAL(durationChanged(qint64))); +} + +QXAMediaRecoderControl::~QXAMediaRecoderControl() +{ + QT_TRACE_FUNCTION_ENTRY_EXIT; +} + +QUrl QXAMediaRecoderControl::outputLocation() const +{ + if (m_session) + return m_session->outputLocation(); + return QUrl(); +} + +bool QXAMediaRecoderControl::setOutputLocation(const QUrl &location) +{ + if (m_session) + return m_session->setOutputLocation(location); + return false; +} + +QMediaRecorder::State QXAMediaRecoderControl::state() const +{ + if (m_session) + return m_session->state(); + return QMediaRecorder::StoppedState; +} + +qint64 QXAMediaRecoderControl::duration() const +{ + if (m_session) + return m_session->duration(); + return 0; +} + +void QXAMediaRecoderControl::record() +{ + if (m_session) + m_session->record(); +} + +void QXAMediaRecoderControl::pause() +{ + if (m_session) + m_session->pause(); +} + +void QXAMediaRecoderControl::stop() +{ + if (m_session) + m_session->stop(); +} + +void QXAMediaRecoderControl::applySettings() +{ + if (m_session) + m_session->applySettings(); +} + +bool QXAMediaRecoderControl::isMuted() const +{ + return false; +} + +void QXAMediaRecoderControl::setMuted(bool) +{ + +} diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.h b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.h new file mode 100644 index 000000000..c6495f2e4 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXAMEDIARECORDERCONTROL_H +#define QXAMEDIARECORDERCONTROL_H + +#include <qmediarecorder.h> +#include <qmediarecordercontrol.h> + +QT_USE_NAMESPACE + +/* + * This class implements QMediaRecorderControl interface. + */ + +class QXARecordSession; + +class QXAMediaRecoderControl : public QMediaRecorderControl +{ + Q_OBJECT + +public: + QXAMediaRecoderControl(QXARecordSession *session, QObject *parent = 0); + virtual ~QXAMediaRecoderControl(); + + QUrl outputLocation() const; + bool setOutputLocation(const QUrl &location); + + QMediaRecorder::State state() const; + + qint64 duration() const; + bool isMuted() const; + void applySettings(); + +public Q_SLOTS: + void record(); + void pause(); + void stop(); + void setMuted(bool); + +private: + QXARecordSession *m_session; +}; + +#endif /* QXAMEDIARECORDERCONTROL_H */ diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.cpp new file mode 100644 index 000000000..05c57feb7 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QString> + +#include "qxarecordmediaservice.h" +#include "qxarecordsession.h" +#include "qxamediarecordercontrol.h" +#include "qxaaudioendpointselector.h" +#include "qxaaudioencodercontrol.h" +#include "qxamediacontainercontrol.h" +#include "qxacommon.h" + +QXARecodMediaService::QXARecodMediaService(QObject *parent) +:QMediaService(parent) +{ + QT_TRACE_FUNCTION_ENTRY; + m_session = new QXARecordSession(this); + m_control = new QXAMediaRecoderControl(m_session, this); + m_endpoint = new QXAAudioEndpointSelector(m_session, this); + m_encoder = new QXAAudioEncoderControl(m_session, this); + m_container = new QXAMediaContainerControl(m_session, this); +} + +QXARecodMediaService::~QXARecodMediaService() +{ + QT_TRACE_FUNCTION_ENTRY_EXIT; +} + +QMediaControl* QXARecodMediaService::requestControl(const char *name) +{ + QT_TRACE_FUNCTION_ENTRY; + if (qstrcmp(name, QMediaRecorderControl_iid) == 0) + return m_control; + else if (qstrcmp(name, QAudioEndpointSelector_iid) == 0) + return m_endpoint; + else if (qstrcmp(name, QAudioEncoderControl_iid) == 0) + return m_encoder; + else if (qstrcmp(name, QMediaContainerControl_iid) == 0) + return m_container; + QT_TRACE_FUNCTION_EXIT; + return 0; +} + +void QXARecodMediaService::releaseControl(QMediaControl *control) +{ + Q_UNUSED(control) +} diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.h b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.h new file mode 100644 index 000000000..98f5136e8 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXARECORDMEDIASERVICE_H +#define QXARECORDMEDIASERVICE_H + +#include <QtCore/qobject.h> +#include <qmediaservice.h> + +QT_USE_NAMESPACE + +/* + * This class implements QMediaService interface. + */ + +class QXARecordSession; +class QXAMediaRecoderControl; +class QXAAudioEndpointSelector; +class QXAAudioEncoderControl; +class QXAMediaContainerControl; + +class QXARecodMediaService : public QMediaService +{ + + Q_OBJECT + +public: + QXARecodMediaService(QObject *parent = 0); + ~QXARecodMediaService(); + QMediaControl *requestControl(const char *name); + void releaseControl( QMediaControl *control); +private: + QXARecordSession *m_session; + QXAMediaRecoderControl *m_control; + QXAAudioEndpointSelector *m_endpoint; + QXAAudioEncoderControl *m_encoder; + QXAMediaContainerControl *m_container; +}; + +#endif /* QXARECORDMEDIASERVICE_H */ diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.cpp new file mode 100644 index 000000000..76cdfc3da --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.cpp @@ -0,0 +1,766 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QVariant> +#include <QtCore/qdir.h> +#include <qtmedianamespace.h> +#include "qxarecordsession.h" +#include "xarecordsessionimpl.h" +#include "qxacommon.h" + +/* The following declaration is required to allow QList<int> to be added to + * QVariant + */ +Q_DECLARE_METATYPE(QList<uint>) + +/* This macro checks for m_impl null pointer. If it is, emits an error signal + * error(QMediaRecorder::ResourceError, tr("Service has not been started")); + * and returns from function immediately with value 's'. + */ + +#define RETURN_s_IF_m_impl_IS_NULL(s) \ + if (!m_impl) { \ + emit error(QMediaRecorder::ResourceError, QXARecordSession::tr("Service has not been started")); \ + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Service has not been started\"))"); \ + return s; \ + } + +/* This macro checks for m_impl null pointer. If it is, emits an error signal + * error(QMediaRecorder::ResourceError, tr("Service has not been started")); + * and returns from function immediately. + */ +#define RETURN_IF_m_impl_IS_NULL \ + if (!m_impl) { \ + emit error(QMediaRecorder::ResourceError, QXARecordSession::tr("Service has not been started")); \ + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Service has not been started\"))"); \ + return; \ + } + +QXARecordSession::QXARecordSession(QObject *parent) +:QObject(parent), +m_state(QMediaRecorder::StoppedState), +m_previousState(QMediaRecorder::StoppedState) +{ + QT_TRACE_FUNCTION_ENTRY; + m_impl = NULL; + m_impl = new XARecordSessionImpl(*this); + if (m_impl) { + if (m_impl->postConstruct() == KErrNone) { + initCodecsList(); + initContainersList(); + m_containerMimeType = QString("audio/wav"); + m_audioencodersettings.setCodec("pcm"); + m_audioencodersettings.setBitRate(0); + m_audioencodersettings.setChannelCount(-1); + m_audioencodersettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding); + m_audioencodersettings.setQuality(QtMultimediaKit::NormalQuality); + m_audioencodersettings.setSampleRate(-1); + setEncoderSettingsToImpl(); + m_URItoImplSet = false; + QT_TRACE1("Initialized implementation"); + } + else { + delete m_impl; + m_impl = NULL; + QT_TRACE1("Error initializing implementation"); + } + } + else { + emit error(QMediaRecorder::ResourceError, tr("Unable to start Service")); + } + QT_TRACE_FUNCTION_EXIT; +} + +QXARecordSession::~QXARecordSession() +{ + QT_TRACE_FUNCTION_ENTRY; + delete m_impl; + QT_TRACE_FUNCTION_EXIT; +} + +QUrl QXARecordSession::outputLocation() +{ + return m_outputLocation; +} + +bool QXARecordSession::setOutputLocation(const QUrl &location) +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_s_IF_m_impl_IS_NULL(false); + + // Location can be set only when recorder is in stopped state. + if (state() != QMediaRecorder::StoppedState) + return false; + + // Validate URL + if (!location.isValid()) + return false; + + // If old and new locations are same, do nothing. + QString newUrlStr = (QUrl::fromUserInput(location.toString())).toString(); + QString curUrlStr = (QUrl::fromUserInput(m_outputLocation.toString())).toString(); + if (curUrlStr.compare(newUrlStr) == KErrNone) + return true; + + QT_TRACE2("Location:", newUrlStr); + m_outputLocation = location; + /* New file, so user can set new settings */ + m_previousState = QMediaRecorder::StoppedState; + m_URItoImplSet = false; + + QT_TRACE_FUNCTION_EXIT; + return true; +} + +QMediaRecorder::State QXARecordSession::state() +{ + return m_state; +} + +qint64 QXARecordSession::duration() +{ + TInt64 dur(0); + + QT_TRACE_FUNCTION_ENTRY; + + RETURN_s_IF_m_impl_IS_NULL(dur); + + m_impl->duration(dur); + + QT_TRACE_FUNCTION_EXIT; + return (qint64)dur; +} + +void QXARecordSession::applySettings() +{ + /* Settings can only be applied when the recorder is in the stopped + * state after creation. */ + if ((state() == QMediaRecorder::StoppedState) && (m_state == m_previousState)) { + if (m_appliedaudioencodersettings != m_audioencodersettings) + setEncoderSettingsToImpl(); + } + else { + emit error(QMediaRecorder::FormatError, tr("Settings cannot be changed once recording started")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Settings cannot be changed once recording started\"))"); + } +} + +void QXARecordSession::record() +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_IF_m_impl_IS_NULL; + + /* No op if object is already in recording state */ + if (state() == QMediaRecorder::RecordingState) + return; + + /* 1. Set encoder settings here */ + if (m_appliedaudioencodersettings != m_audioencodersettings) + RET_IF_FALSE(setEncoderSettingsToImpl()); + + /* 2. Set URI to impl */ + RET_IF_FALSE(setURIToImpl()); + + /* 3. Start recording... + * If successful, setRecorderState(QMediaRecorder::RecordingState); + * will be called from the callback cbRecordingStarted() + */ + if (m_impl->record() != KErrNone) { + emit error(QMediaRecorder::ResourceError, tr("Generic error")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Generic error\"))"); + } + + QT_TRACE_FUNCTION_EXIT; +} + +void QXARecordSession::pause() +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_IF_m_impl_IS_NULL; + + /* No op if object is already in paused/stopped state */ + if ((state() == QMediaRecorder::PausedState) || (state() == QMediaRecorder::StoppedState)) { + return; + } + + if (m_impl->pause() == KErrNone) { + setRecorderState(QMediaRecorder::PausedState); + } + else { + emit error(QMediaRecorder::ResourceError, tr("Unable to pause")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Unable to pause\"))"); + } + + QT_TRACE_FUNCTION_EXIT; +} + +void QXARecordSession::stop() +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_IF_m_impl_IS_NULL; + + /* No op if object is already in paused state */ + if (state() == QMediaRecorder::StoppedState) + return; + + if ((m_impl->stop() == KErrNone)) { + setRecorderState(QMediaRecorder::StoppedState); + } + else { + emit error(QMediaRecorder::ResourceError, tr("Unable to stop")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Unable to stop\"))"); + } + + QT_TRACE_FUNCTION_EXIT; +} + +void QXARecordSession::cbDurationChanged(TInt64 new_pos) +{ + QT_TRACE_FUNCTION_ENTRY; + + emit durationChanged((qint64)new_pos); + SIGNAL_EMIT_TRACE1("emit durationChanged((qint64)new_pos);"); + + QT_TRACE_FUNCTION_EXIT; +} + +void QXARecordSession::cbAvailableAudioInputsChanged() +{ + QT_TRACE_FUNCTION_ENTRY; + + emit availableAudioInputsChanged(); + SIGNAL_EMIT_TRACE1("emit availableAudioInputsChanged();"); + + QT_TRACE_FUNCTION_EXIT; +} + +void QXARecordSession::cbRecordingStarted() +{ + QT_TRACE_FUNCTION_ENTRY; + + setRecorderState(QMediaRecorder::RecordingState); + + QT_TRACE_FUNCTION_EXIT; +} + +void QXARecordSession::cbRecordingStopped() +{ + QT_TRACE_FUNCTION_ENTRY; + + emit error(QMediaRecorder::ResourceError, tr("Resources Unavailable")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Resources Unavailable\"))"); + setRecorderState(QMediaRecorder::StoppedState); + /* Set record state to Stopped */ + if (m_impl) + m_impl->stop(); + + QT_TRACE_FUNCTION_EXIT; +} + +/* For QAudioEndpointSelector begin */ +QList<QString> QXARecordSession::availableEndpoints() +{ + QT_TRACE_FUNCTION_ENTRY; + + QList<QString> strList; + + RETURN_s_IF_m_impl_IS_NULL(strList); + + QString str; + RArray<TPtrC> names; + m_impl->getAudioInputDeviceNames(names); + for (TInt index = 0; index < names.Count(); index++) { + str = QString((QChar*)names[index].Ptr(), names[index].Length()); + strList.append(str); + } + + QT_TRACE_FUNCTION_EXIT; + return strList; +} + +QString QXARecordSession::endpointDescription(const QString &name) +{ + /* From AL we get only device name */ + return name; +} + +QString QXARecordSession::defaultEndpoint() +{ + QT_TRACE_FUNCTION_ENTRY; + + QString str; + + RETURN_s_IF_m_impl_IS_NULL(str); + + TPtrC name; + if(m_impl->defaultAudioInputDevice(name) == KErrNone) + str = QString((QChar*)name.Ptr(), name.Length()); + + QT_TRACE_FUNCTION_EXIT; + return str; +} + +QString QXARecordSession::activeEndpoint() +{ + QT_TRACE_FUNCTION_ENTRY; + + QString str; + + RETURN_s_IF_m_impl_IS_NULL(str); + + TPtrC name; + if(m_impl->activeAudioInputDevice(name) == KErrNone) + str = QString((QChar*)name.Ptr(), name.Length()); + + QT_TRACE_FUNCTION_EXIT; + return str; +} + +void QXARecordSession::setActiveEndpoint(const QString &name) +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_IF_m_impl_IS_NULL; + + if (name.isNull() || name.isEmpty()) + return; + + TPtrC16 tempPtr(reinterpret_cast<const TUint16*>(name.utf16())); + if (m_impl->setAudioInputDevice(tempPtr) == true) { + emit activeEndpointChanged(name); + SIGNAL_EMIT_TRACE1("emit activeEndpointChanged(name)"); + } + else { + emit error(QMediaRecorder::ResourceError, tr("Invalid endpoint")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Invalid endpoint\"))"); + } + + QT_TRACE_FUNCTION_EXIT; +} +/* For QAudioEndpointSelector end */ + +/* For QAudioEncoderControl begin */ +QStringList QXARecordSession::supportedAudioCodecs() +{ + return m_codecs; +} + +QString QXARecordSession::codecDescription(const QString &codecName) +{ + if (m_codecs.contains(codecName)) + return QString(codecName); + return QString(); +} + +QList<int> QXARecordSession::supportedSampleRates( + const QAudioEncoderSettings &settings, + bool *continuous) +{ + QT_TRACE_FUNCTION_ENTRY; + + QList<int> srList; + + RETURN_s_IF_m_impl_IS_NULL(srList); + + QString selectedCodec = settings.codec(); + if (selectedCodec.isNull() || selectedCodec.isEmpty()) + selectedCodec = QString("pcm"); + + if (m_codecs.indexOf(selectedCodec) >= 0) { + RArray<TInt32> sampleRates; + TBool isContinuous; + TPtrC16 tempPtr(reinterpret_cast<const TUint16*>(selectedCodec.utf16())); + if (m_impl->getSampleRates(tempPtr, sampleRates, isContinuous) == KErrNone) { + for (TInt index = 0; index < sampleRates.Count(); index++) + srList.append(sampleRates[index]); + sampleRates.Close(); + if (continuous) + { + *continuous = false; + if (isContinuous == true) + *continuous = true; + } + } + } + + QT_TRACE_FUNCTION_EXIT; + return srList; +} + +QAudioEncoderSettings QXARecordSession::audioSettings() +{ + return m_appliedaudioencodersettings; +} + +void QXARecordSession::setAudioSettings(const QAudioEncoderSettings &settings) +{ + /* Settings can only be set when the recorder is in the stopped + * state after creation. */ + if ((state() == QMediaRecorder::StoppedState) && (m_state == m_previousState)) { + /* Validate and ignore rest of the settings */ + m_audioencodersettings = settings; + } + else { + emit error(QMediaRecorder::FormatError, tr("Settings cannot be changed once recording started")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Settings cannot be changed once recording started\"))"); + } +} + +QStringList QXARecordSession::supportedEncodingOptions(const QString &codec) +{ + QT_TRACE_FUNCTION_ENTRY; + Q_UNUSED(codec); + QStringList options; + if ((codec.compare("aac") == 0) || + (codec.compare("amr") == 0)) + { + options << "bitrate" << "quality"; + } + + + QT_TRACE_FUNCTION_EXIT; + return options; +} + +QVariant QXARecordSession::encodingOption(const QString &codec, const QString &name) +{ + QT_TRACE_FUNCTION_ENTRY; + + QVariant encodingOption; + QMap<QString, QVariant> map; + RETURN_s_IF_m_impl_IS_NULL(encodingOption); + + if (name.compare("bitrate") == 0) { + TPtrC16 tempPtr(reinterpret_cast<const TUint16*>(codec.utf16())); + QList<uint> bitrateList; + RArray<TUint32> bitrates; + TBool continuous; + if (m_impl->getBitrates(tempPtr, bitrates, continuous) == KErrNone) { + for (TInt index = 0; index < bitrates.Count(); index++) + bitrateList.append(bitrates[index]); + bitrates.Close(); + } + encodingOption.setValue(bitrateList); + map.insert("continuous", QVariant(continuous)); + map.insert("bitrates", encodingOption); + } + + QT_TRACE_FUNCTION_EXIT; + return map; +} + +void QXARecordSession::setEncodingOption( + const QString &codec, + const QString &name, + const QVariant &value) +{ + /* + * Currently nothing can be set via this function. + * Bitrate is set via QAudioEncoderSettings::setBitrate(). + */ + Q_UNUSED(codec); + Q_UNUSED(name); + Q_UNUSED(value); +} +/* For QAudioEncoderControl end */ + +QStringList QXARecordSession::supportedContainers() +{ + return m_containers; +} + +QString QXARecordSession::containerMimeType() +{ + return m_containerMimeType; +} + +void QXARecordSession::setContainerMimeType(const QString &formatMimeType) +{ + if (formatMimeType.isNull() || formatMimeType.isEmpty()) + return; + else if (m_containers.indexOf(formatMimeType) >= 0 ) + m_containerMimeType = formatMimeType; + else { + emit error(QMediaRecorder::FormatError, tr("Invalid container")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid container\"))"); + } +} + +QString QXARecordSession::containerDescription(const QString &formatMimeType) +{ + int index = m_containers.indexOf(formatMimeType); + if (index >= 0) { + return m_containersDesc.at(index); + } + else { + emit error(QMediaRecorder::FormatError, tr("Invalid container")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid container\"))"); + } + return QString(); +} + +void QXARecordSession::setRecorderState(QMediaRecorder::State state) +{ + if (state != m_state) { + m_previousState = m_state; + m_state = state; + emit stateChanged(m_state); + SIGNAL_EMIT_TRACE1("emit stateChanged(m_state);"); + } +} + +void QXARecordSession::initCodecsList() +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_IF_m_impl_IS_NULL; + + m_codecs.clear(); + + const RArray<TPtrC>& names = m_impl->getAudioEncoderNames(); + QString str; + + for (TInt index = 0; index < names.Count(); index++) { + str = QString((QChar*)names[index].Ptr(), names[index].Length()); + m_codecs.append(str); + } + QT_TRACE_FUNCTION_EXIT; +} + +void QXARecordSession::initContainersList() +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_IF_m_impl_IS_NULL; + + m_containers.clear(); + m_containersDesc.clear(); + + const RArray<TPtrC>& names = m_impl->getContainerNames(); + const RArray<TPtrC>& descs = m_impl->getContainerDescs(); + QString str; + + for (TInt32 index = 0; index < names.Count(); index++) { + str = QString((QChar*)names[index].Ptr(), names[index].Length()); + m_containers.append(str); + str = QString((QChar*)descs[index].Ptr(), descs[index].Length()); + m_containersDesc.append(str); + } + QT_TRACE_FUNCTION_EXIT; +} + +bool QXARecordSession::setEncoderSettingsToImpl() +{ + QT_TRACE_FUNCTION_ENTRY; + + RETURN_s_IF_m_impl_IS_NULL(false); + + m_impl->resetEncoderAttributes(); + + /* m_containerMimeType is alredy validated in ::setContainerMimeType() */ + QString tempStr = m_containerMimeType; + TPtrC16 tempPtr(reinterpret_cast<const TUint16 *>(tempStr.utf16())); + m_impl->setContainerType(tempPtr); + + /* vaidate and assign codec */ + if (m_audioencodersettings.codec().isNull() || m_audioencodersettings.codec().isEmpty()) { + m_audioencodersettings.setCodec(m_appliedaudioencodersettings.codec()); + } + tempStr = m_audioencodersettings.codec(); + if (m_codecs.indexOf(tempStr) >= 0) { + tempPtr.Set(reinterpret_cast<const TUint16*>(tempStr.utf16())); + /* We already did validation above, so function always returns true */ + m_impl->setCodec(tempPtr); + } + else { + QT_TRACE2("Codec selected is :", m_audioencodersettings.codec()); + emit error(QMediaRecorder::FormatError, tr("Invalid codec")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid codec\"));"); + return false; + } + + /* Validate and set bitrate only if encoding mode is other than quality encoding and container type is not wav*/ + if ((m_audioencodersettings.encodingMode() != QtMultimediaKit::ConstantQualityEncoding) && + (m_containerMimeType.compare("audio/wav") != 0)) { + m_impl->setBitRate(m_audioencodersettings.bitRate()); + m_audioencodersettings.setBitRate(m_impl->getBitRate()); + } + + if (m_audioencodersettings.channelCount() == -1) { + m_impl->setOptimalChannelCount(); + } + else { + m_impl->setChannels(m_audioencodersettings.channelCount()); + m_audioencodersettings.setChannelCount(m_impl->getChannels()); + } + + switch (m_audioencodersettings.encodingMode()) { + case QtMultimediaKit::ConstantQualityEncoding: { + switch (m_audioencodersettings.quality()) { + case QtMultimediaKit::VeryLowQuality: + m_impl->setVeryLowQuality(); + m_audioencodersettings.setBitRate(m_impl->getBitRate()); + break; + case QtMultimediaKit::LowQuality: + m_impl->setLowQuality(); + m_audioencodersettings.setBitRate(m_impl->getBitRate()); + break; + case QtMultimediaKit::NormalQuality: + m_impl->setNormalQuality(); + m_audioencodersettings.setBitRate(m_impl->getBitRate()); + break; + case QtMultimediaKit::HighQuality: + m_impl->setHighQuality(); + m_audioencodersettings.setBitRate(m_impl->getBitRate()); + break; + case QtMultimediaKit::VeryHighQuality: + m_impl->setVeryHighQuality(); + m_audioencodersettings.setBitRate(m_impl->getBitRate()); + break; + default: + break; + }; /* end of switch (m_audioencodersettings.quality())*/ + } + break; + case QtMultimediaKit::ConstantBitRateEncoding: { + TInt32 status = m_impl->setCBRMode(); + if (status == KErrNotSupported) { + emit error(QMediaRecorder::FormatError, tr("Invalid encoding mode setting")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid encoding mode setting\"));"); + return false; + } + else if (status != KErrNone) { + emit error(QMediaRecorder::ResourceError, tr("Internal error")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Internal error\"));"); + return false; + } + } + break; + case QtMultimediaKit::AverageBitRateEncoding: { + TInt32 status = m_impl->setVBRMode(); + if (status == KErrNotSupported) { + emit error(QMediaRecorder::FormatError, tr("Invalid encoding mode setting")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid encoding mode setting\"));"); + return false; + } + else if (status != KErrNone) { + emit error(QMediaRecorder::ResourceError, tr("Internal error")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Internal error\"));"); + return false; + } + } + break; + case QtMultimediaKit::TwoPassEncoding: + // fall through + default: { + emit error(QMediaRecorder::FormatError, tr("Invalid encoding mode setting")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid encoding mode setting\"));"); + return false; + } + }; /* switch (m_audioencodersettings.encodingMode()) */ + + if (m_audioencodersettings.sampleRate() == -1) { + m_impl->setOptimalSampleRate(); + } + else { + m_impl->setSampleRate(m_audioencodersettings.sampleRate()); + m_audioencodersettings.setSampleRate(m_impl->getSampleRate()); + } + m_appliedaudioencodersettings = m_audioencodersettings; + + QT_TRACE_FUNCTION_EXIT; + return true; +} + +bool QXARecordSession::setURIToImpl() +{ + QT_TRACE_FUNCTION_ENTRY; + if (m_URItoImplSet) + return true; + + /* If m_outputLocation is null, set a default location */ + if (m_outputLocation.isEmpty()) { + QDir outputDir(QDir::rootPath()); + + int lastImage = 0; + int fileCount = 0; + foreach(QString fileName, outputDir.entryList(QStringList() << "recordclip_*")) { + int imgNumber = fileName.mid(5, fileName.size() - 9).toInt(); + lastImage = qMax(lastImage, imgNumber); + if (outputDir.exists(fileName)) + fileCount += 1; + } + lastImage += fileCount; + m_outputLocation = QUrl(QDir::toNativeSeparators(outputDir.canonicalPath() + QString("/recordclip_%1").arg(lastImage + 1, 4, 10, QLatin1Char('0')))); + } + + QString newUrlStr = (QUrl::fromUserInput(m_outputLocation.toString())).toString(); + // append file prefix if required + if (newUrlStr.lastIndexOf('.') == -1) { + QString fileExtension; + if ((m_containerMimeType.compare("audio/wav")) == KErrNone) { + fileExtension = QString(".wav"); + } + else if ((m_containerMimeType.compare("audio/amr")) == KErrNone) { + fileExtension = QString(".amr"); + } + else if ((m_containerMimeType.compare("audio/mpeg")) == KErrNone) { + fileExtension = QString(".mp4"); + } + newUrlStr.append(fileExtension); + } + + QT_TRACE2("Filename selected is :", newUrlStr); + TPtrC16 tempPtr(reinterpret_cast<const TUint16 *>(newUrlStr.utf16())); + if (m_impl->setURI(tempPtr) != 0) { + emit error(QMediaRecorder::ResourceError, tr("Generic error")); + SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Generic error\"))"); + return false; + } + m_URItoImplSet = true; + m_outputLocation = QUrl(newUrlStr); + QT_TRACE_FUNCTION_EXIT; + return true; +} diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.h b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.h new file mode 100644 index 000000000..cabe58fc9 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXARECORDSESSION_H +#define QXARECORDSESSION_H + +#include <QObject> +#include <QUrl> +#include "qmediarecorder.h" +#include "xarecordsessioncommon.h" + +QT_USE_NAMESPACE + +class XARecordSessionImpl; + +/* + * This is a backend class for all QXXXControl objects. + * This class contains actual implementation of recording functionality + * from the control object's perspective. + */ + + +class QXARecordSession : public QObject, + public XARecordObserver +{ +Q_OBJECT + +public: + QXARecordSession(QObject *parent); + virtual ~QXARecordSession(); + + /* For QMediaRecorderControl begin */ + QUrl outputLocation(); + bool setOutputLocation(const QUrl &location); + QMediaRecorder::State state(); + qint64 duration(); + void applySettings(); + + void record(); + void pause(); + void stop(); + + void cbDurationChanged(TInt64 new_pos); + void cbAvailableAudioInputsChanged(); + void cbRecordingStarted(); + void cbRecordingStopped(); + /* For QMediaRecorderControl end */ + + /* For QAudioEndpointSelector begin */ + QList<QString> availableEndpoints(); + QString endpointDescription(const QString &name); + QString defaultEndpoint(); + QString activeEndpoint(); + void setActiveEndpoint(const QString &name); + /* For QAudioEndpointSelector end */ + + /* For QAudioEncoderControl begin */ + QStringList supportedAudioCodecs(); + QString codecDescription(const QString &codecName); + QList<int> supportedSampleRates( + const QAudioEncoderSettings &settings, + bool *continuous); + QAudioEncoderSettings audioSettings(); + void setAudioSettings(const QAudioEncoderSettings &settings); + QStringList supportedEncodingOptions(const QString &codec); + QVariant encodingOption(const QString &codec, const QString &name); + void setEncodingOption(const QString &codec, const QString &name, const QVariant &value); + /* For QAudioEncoderControl end */ + + /* For QMediaContainerControl begin */ + QStringList supportedContainers(); + QString containerMimeType(); + void setContainerMimeType(const QString &formatMimeType); + QString containerDescription(const QString &formatMimeType); + /* For QMediaContainerControl end */ + +Q_SIGNALS: + void stateChanged(QMediaRecorder::State state); + void durationChanged(qint64 duration); + void error(int error, const QString &errorString); + void activeEndpointChanged(const QString& name); + void availableAudioInputsChanged(); + +private: + void setRecorderState(QMediaRecorder::State state); + void initCodecsList(); + void initContainersList(); + bool setEncoderSettingsToImpl(); + bool setURIToImpl(); + +private: + /* Own */ + XARecordSessionImpl *m_impl; + QUrl m_outputLocation; + bool m_URItoImplSet; + QMediaRecorder::State m_state; + QMediaRecorder::State m_previousState; + QStringList m_codecs; + QAudioEncoderSettings m_audioencodersettings; + QAudioEncoderSettings m_appliedaudioencodersettings; + QStringList m_containers; + QStringList m_containersDesc; + QString m_containerMimeType; +}; + +#endif /* QXARECORDSESSION_H */ diff --git a/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessioncommon.h b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessioncommon.h new file mode 100644 index 000000000..cdf8c1886 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessioncommon.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef XARECORDSESSIONCOMMON_H +#define XARECORDSESSIONCOMMON_H + +#include <e32base.h> +#include "xacommon.h" + +#define MAX_NUMBER_INTERFACES 20 +#define MAX_NUMBER_INPUT_DEVICES 10 +#define MAX_NUMBER_ENCODERS 10 + +//const TInt32 KExtErr = (TInt32)(-2147483648); +const TInt32 KExtErr = -32768; +const TInt32 KExtErrUnspecifiedCodecForContainer = (KExtErr+1); +const TInt32 KExtErrUnsupportedCodecForContainer = (KExtErr+2); +const TInt32 KExtErrUnsupportedURISuffixForContainer = (KExtErr+3); + +class XARecordObserver +{ +public: + virtual void cbDurationChanged(TInt64 new_pos) = 0; + virtual void cbAvailableAudioInputsChanged() = 0; + virtual void cbRecordingStarted() = 0; + virtual void cbRecordingStopped() = 0; +}; + +#endif /* XARECORDSESSIONCOMMON_H */ diff --git a/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.cpp b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.cpp new file mode 100644 index 000000000..d18c781d4 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.cpp @@ -0,0 +1,1378 @@ +/**************************************************************************** + ** + ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the Qt Mobility Components. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** No Commercial Usage + ** This file contains pre-release code and may not be distributed. + ** You may use this file in accordance with the terms and conditions + ** contained in the Technology Preview License Agreement accompanying + ** this package. + ** + ** 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, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** If you have questions regarding the use of this file, please contact + ** Nokia at qt-info@nokia.com. + ** + ** + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ +#include "xarecordsessionimpl.h" +#include "xarecordsessioncommon.h" +_LIT8(K8WAVMIMETYPE, "audio/x-wav"); +/* + * These codec names are not part of AL. Hence we need to define names here. + * */ +_LIT(KAUDIOCODECPCM, "pcm"); +_LIT(KAUDIOCODECAMR, "amr"); +_LIT(KAUDIOCODECAAC, "aac"); +_LIT(KCONTAINERWAV, "audio/wav"); +_LIT(KCONTAINERWAVDESC, "wav container"); +_LIT(KCONTAINERAMR, "audio/amr"); +_LIT(KCONTAINERAMRDESC, "amr File format"); +_LIT(KCONTAINERMP4, "audio/mpeg"); +_LIT(KCONTAINERMP4DESC, "mpeg container"); + +const TUint KRecordPosUpdatePeriod = 1000; +const TUint KMilliToHz = 1000; +const TUint KMaxNameLength = 256; + +/* Local functions for callback registation */ +void cbXAObjectItf( + XAObjectItf caller, + const void *pContext, + XAuint32 event, + XAresult result, + XAuint32 param, + void *pInterface); + +void cbXARecordItf( + XARecordItf caller, + void *pContext, + XAuint32 event); + +void cbXAAvailableAudioInputsChanged( + XAAudioIODeviceCapabilitiesItf caller, + void *pContext, + XAuint32 deviceID, + XAint32 numInputs, + XAboolean isNew); + +XARecordSessionImpl::XARecordSessionImpl(XARecordObserver &parent) : + m_Parent(parent), + m_EOEngine(NULL), + m_MORecorder(NULL), + m_RecordItf(NULL), + m_AudioEncItf(NULL), + m_WAVMime(NULL), + m_URIName(NULL), + m_InputDeviceId(0), + m_ContainerType(0), + m_BitRate(0), + m_RateControl(0), + m_ChannelsOut(1), + m_SampleRate(0), + m_AudioIODevCapsItf(NULL), + m_AudioInputDeviceNames(NULL), + m_DefaultAudioInputDeviceNames(NULL), + m_AudioEncCapsItf(NULL) +{ + TRACE_FUNCTION_ENTRY_EXIT; +} + +XARecordSessionImpl::~XARecordSessionImpl() +{ + TRACE_FUNCTION_ENTRY; + + if (m_MORecorder) + (*m_MORecorder)->Destroy(m_MORecorder); + + if (m_EOEngine) + (*m_EOEngine)->Destroy(m_EOEngine); + + delete m_WAVMime; + delete m_URIName; + + m_InputDeviceIDs.Close(); + if (m_AudioInputDeviceNames) + m_AudioInputDeviceNames->Reset(); + delete m_AudioInputDeviceNames; + m_DefaultInputDeviceIDs.Close(); + if (m_DefaultAudioInputDeviceNames) + m_DefaultAudioInputDeviceNames->Reset(); + delete m_DefaultAudioInputDeviceNames; + m_EncoderIds.Close(); + m_EncoderNames.Close(); + m_ContainerNames.Close(); + m_ContainerDescs.Close(); + + TRACE_FUNCTION_EXIT; +} + +TInt32 XARecordSessionImpl::postConstruct() +{ + TRACE_FUNCTION_ENTRY; + + XAEngineOption engineOption[] = { (XAuint32) XA_ENGINEOPTION_THREADSAFE, (XAuint32) XA_BOOLEAN_TRUE}; + + /* Create and realize Engine object */ + TRACE_LOG(_L("XARecordSessionImpl: Creating Engine...")); + XAresult xa_result = xaCreateEngine(&m_EOEngine, 1, engineOption, 0, NULL, NULL); + TInt returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + TRACE_LOG(_L("XARecordSessionImpl: Realizing engine...")); + xa_result = (*m_EOEngine)->Realize(m_EOEngine, XA_BOOLEAN_FALSE); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + TRACE_LOG(_L("XARecordSessionImpl: OMX AL Engine realized successfully")); + + XAEngineItf engineItf; + xa_result = (*m_EOEngine)->GetInterface(m_EOEngine, XA_IID_ENGINE, (void**) &engineItf); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + xa_result = (*m_EOEngine)->GetInterface(m_EOEngine, + XA_IID_AUDIOIODEVICECAPABILITIES, + (void**) &m_AudioIODevCapsItf); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + xa_result = (*m_AudioIODevCapsItf)->RegisterAvailableAudioInputsChangedCallback( + m_AudioIODevCapsItf, + cbXAAvailableAudioInputsChanged, + (void*)this); + + xa_result = (*m_EOEngine)->GetInterface( + m_EOEngine, + XA_IID_AUDIOENCODERCAPABILITIES, + (void**) &m_AudioEncCapsItf); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRAP(returnValue, m_WAVMime = HBufC8::NewL(K8WAVMIMETYPE().Length() + 1)); + RET_ERR_IF_ERR(returnValue); + TPtr8 ptr = m_WAVMime->Des(); + ptr = K8WAVMIMETYPE(); // copy uri name into local variable + ptr.PtrZ(); // append zero terminator to end of URI + + m_AudioInputDeviceNames = new CDesC16ArrayFlat(2); + if (m_AudioInputDeviceNames == NULL) + returnValue = KErrNoMemory; + RET_ERR_IF_ERR(returnValue); + + m_DefaultAudioInputDeviceNames = new CDesC16ArrayFlat(2); + if (m_DefaultAudioInputDeviceNames == NULL) + returnValue = KErrNoMemory; + RET_ERR_IF_ERR(returnValue); + + returnValue = initContainersList(); + RET_ERR_IF_ERR(returnValue); + returnValue = initAudioEncodersList(); + RET_ERR_IF_ERR(returnValue); + returnValue = initAudioInputDevicesList(); + RET_ERR_IF_ERR(returnValue); + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::setURI(const TDesC &aURI) +{ + TRACE_FUNCTION_ENTRY; + + /* This function will only get called when aURI is different than m_URIName + * and only when recorder is in stopped state. + * If the recorder object was created for a different URI (than aURI), we + * need to tear it down here. + */ + if (m_MORecorder) { + (*m_MORecorder)->Destroy(m_MORecorder); + m_MORecorder = NULL; + m_RecordItf = NULL; + } + + delete m_URIName; + m_URIName = NULL; + TRAPD(returnValue, m_URIName = HBufC8::NewL(aURI.Length()+1)); + RET_ERR_IF_ERR(returnValue); + + TPtr8 uriPtr = m_URIName->Des(); + /* copy uri name into local variable */ + uriPtr.Copy(aURI); + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::record() +{ + TRACE_FUNCTION_ENTRY; + + TInt32 returnValue(KErrGeneral); + if (!m_MORecorder || !m_RecordItf) { + TRACE_LOG(_L("XARecordSessionImpl::Record: MORecorder/RecordItf is not created")); + returnValue = createMediaRecorderObject(); + RET_ERR_IF_ERR(returnValue); + + returnValue = setEncoderSettingsToMediaRecorder(); + RET_ERR_IF_ERR(returnValue); + } + + XAuint32 state; + XAresult xa_result = (*m_RecordItf)->GetRecordState(m_RecordItf, &state); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + if ((state == XA_RECORDSTATE_STOPPED) + || (state == XA_RECORDSTATE_PAUSED)) { + TRACE_LOG(_L("XARecordSessionImpl::Record: Setting State to Recording...")); + xa_result = (*m_RecordItf)->SetRecordState(m_RecordItf, XA_RECORDSTATE_RECORDING); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + TRACE_LOG(_L("XARecordSessionImpl::Record: SetState to Recording")); + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::pause() +{ + TRACE_FUNCTION_ENTRY; + + TInt32 returnValue(KErrGeneral); + if (!m_MORecorder || !m_RecordItf) { + TRACE_LOG(_L("XARecordSessionImpl::Record: MORecorder/RecordItf is not created")); + return returnValue; + } + + XAuint32 state; + XAresult xa_result = (*m_RecordItf)->GetRecordState(m_RecordItf, &state); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + if ((state == XA_RECORDSTATE_STOPPED) + || (state == XA_RECORDSTATE_RECORDING)) { + TRACE_LOG(_L("XARecordSessionImpl::Record: Setting State to Paused...")); + xa_result = (*m_RecordItf)->SetRecordState(m_RecordItf, XA_RECORDSTATE_PAUSED); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + TRACE_LOG(_L("XARecordSessionImpl::Record: SetState to Paused")); + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::stop() +{ + TRACE_FUNCTION_ENTRY; + + TInt32 returnValue(KErrGeneral); + if (!m_MORecorder || !m_RecordItf) { + TRACE_LOG(_L("XARecordSessionImpl::Record: MORecorder/RecordItf is not created")); + return returnValue; + } + + XAuint32 state; + XAresult xa_result = (*m_RecordItf)->GetRecordState(m_RecordItf, &state); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + if ((state == XA_RECORDSTATE_PAUSED) + || (state == XA_RECORDSTATE_RECORDING)) { + TRACE_LOG(_L("XARecordSessionImpl::Record: Setting State to Stopped...")); + xa_result = (*m_RecordItf)->SetRecordState(m_RecordItf, XA_RECORDSTATE_STOPPED); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + TRACE_LOG(_L("XARecordSessionImpl::Record: SetState to Stopped")); + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::duration(TInt64 &aDur) +{ + TRACE_FUNCTION_ENTRY; + + TInt32 returnValue(KErrGeneral); + + if (!m_MORecorder || !m_RecordItf) { + TRACE_LOG(_L("XARecordSessionImpl::Duration: MORecoder/RecordItf is not created")); + return returnValue; + } + + XAmillisecond milliSec; + XAresult xa_result = (*m_RecordItf)->GetPosition(m_RecordItf, &milliSec); + returnValue = mapError(xa_result, ETrue); + if (returnValue == KErrNone) + aDur = (TInt64)milliSec; + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +void XARecordSessionImpl::cbMediaRecorder( + XAObjectItf /*caller*/, + const void */*pContext*/, + XAuint32 event, + XAresult result, + XAuint32 /*param*/, + void */*pInterface*/) +{ + TRACE_FUNCTION_ENTRY; + + switch (event) { + case XA_OBJECT_EVENT_RESOURCES_LOST: + m_Parent.cbRecordingStopped(); + break; + case XA_OBJECT_EVENT_RUNTIME_ERROR: { + switch (result) { + case XA_RESULT_RESOURCE_LOST: + m_Parent.cbRecordingStopped(); + break; + default: + break; + }; /* of switch (result) */ + } + default: + break; + } /* of switch (event) */ + + TRACE_FUNCTION_EXIT; +} + +void XARecordSessionImpl::cbRecordItf( + XARecordItf /*caller*/, + void */*pContext*/, + XAuint32 event) +{ + TRACE_FUNCTION_ENTRY; + + switch(event) { + case XA_RECORDEVENT_HEADATLIMIT: + TRACE_LOG(_L("XA_RECORDEVENT_HEADATLIMIT")); + break; + case XA_RECORDEVENT_HEADATMARKER: + TRACE_LOG(_L("XA_RECORDEVENT_HEADATMARKER")); + break; + case XA_RECORDEVENT_HEADATNEWPOS: { + TInt32 returnValue; + XAresult xa_result; + XAmillisecond milliSec; + xa_result = (*m_RecordItf)->GetPosition(m_RecordItf, &milliSec); + returnValue = mapError(xa_result, ETrue); + if (returnValue == KErrNone) + m_Parent.cbDurationChanged((TInt64) milliSec); + } + break; + case XA_RECORDEVENT_HEADMOVING: + TRACE_LOG(_L("XA_RECORDEVENT_HEADMOVING")); + m_Parent.cbRecordingStarted(); + break; + case XA_RECORDEVENT_HEADSTALLED: + TRACE_LOG(_L("XA_RECORDEVENT_HEADSTALLED")); + break; + case XA_RECORDEVENT_BUFFER_FULL: + TRACE_LOG(_L("XA_RECORDEVENT_BUFFER_FULL")); + break; + default: + TRACE_LOG(_L("UNKNOWN RECORDEVENT EVENT")); + break; + } /* of switch(event) */ + + TRACE_FUNCTION_EXIT; +} + +/* For QAudioEndpointSelector begin */ +void XARecordSessionImpl::getAudioInputDeviceNames(RArray<TPtrC> &aArray) +{ + TRACE_FUNCTION_ENTRY; + + for (TInt index = 0; index < m_AudioInputDeviceNames->MdcaCount(); index++) + aArray.Append(m_AudioInputDeviceNames->MdcaPoint(index)); + TRACE_FUNCTION_EXIT; +} + +TInt32 XARecordSessionImpl::defaultAudioInputDevice(TPtrC &endPoint) +{ + TRACE_FUNCTION_ENTRY; + + TInt32 err(KErrGeneral); + if (m_DefaultAudioInputDeviceNames->MdcaCount() >= 0) { + endPoint.Set(m_DefaultAudioInputDeviceNames->MdcaPoint(0)); + err = KErrNone; + } + + TRACE_FUNCTION_EXIT; + return err; +} + +TInt32 XARecordSessionImpl::activeAudioInputDevice(TPtrC &endPoint) +{ + TRACE_FUNCTION_ENTRY; + + TInt32 returnValue(KErrGeneral); + TBool found(EFalse); + TInt index = 0; + for (; index < m_InputDeviceIDs.Count(); index++) { + if (m_InputDeviceIDs[index] == m_InputDeviceId) { + found = ETrue; + break; + } + } + + /* Comparing found with ETrue produces linker error */ + if (found == true) { + endPoint.Set(m_AudioInputDeviceNames->MdcaPoint(index)); + returnValue = KErrNone; + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TBool XARecordSessionImpl::setAudioInputDevice(const TDesC &aDevice) +{ + TRACE_FUNCTION_ENTRY; + + /* validate if we can set input device id */ + TBool found(EFalse); + m_InputDeviceId = 0; + TInt index = 0; + for (; index < m_AudioInputDeviceNames->MdcaCount(); index++) { + if (m_AudioInputDeviceNames->MdcaPoint(index).Compare(aDevice) == 0) { + found = ETrue; + break; + } + } + if (found == true) { + m_InputDeviceId = m_InputDeviceIDs[index]; + } + + TRACE_FUNCTION_EXIT; + return found; +} + +void XARecordSessionImpl::cbAvailableAudioInputsChanged( + XAAudioIODeviceCapabilitiesItf /*caller*/, + void */*pContext*/, + XAuint32 deviceID, + XAint32 /*numInputs*/, + XAboolean isNew) +{ + TRACE_FUNCTION_ENTRY; + + /* If a new device is added into the system, append it to available input list */ + if (isNew == XA_BOOLEAN_TRUE) { + XAAudioInputDescriptor audioInputDescriptor; + m_InputDeviceIDs.Append(deviceID); + + XAresult xa_result = (*m_AudioIODevCapsItf)->QueryAudioInputCapabilities( + m_AudioIODevCapsItf, + deviceID, + &audioInputDescriptor); + + if ((mapError(xa_result, ETrue)) == KErrNone) { + TUint8* inDevNamePtr = audioInputDescriptor.deviceName; + TUint8* tempPtr = audioInputDescriptor.deviceName; + TInt32 inDevNameLength = 0; + while (*tempPtr++) + inDevNameLength++; + TPtrC8 ptr(inDevNamePtr, inDevNameLength); + /* Convert 8 bit to 16 bit */ + TBuf16<KMaxNameLength> name; + name.Copy(ptr); + /* Using TRAP with returnValue results in compiler error */ + TRAP_IGNORE(m_AudioInputDeviceNames->AppendL(name)); + } + } + else { + /* an available device has been removed from the the system, remove it from + * available input list and also default list */ + TBool found(EFalse); + TInt index = 0; + for (; index < m_InputDeviceIDs.Count(); index++) { + if (deviceID == m_InputDeviceIDs[index]) { + found = ETrue; + break; + } + } + if (found == true) { + m_InputDeviceIDs.Remove(index); + m_AudioInputDeviceNames->Delete(index); + } + if (deviceID == m_InputDeviceId) + m_InputDeviceId = 0; + + found = EFalse; + for (index = 0; index < m_DefaultInputDeviceIDs.Count(); index++) { + if (deviceID == m_DefaultInputDeviceIDs[index]) { + found = ETrue; + break; + } + } + if (found == true) { + m_DefaultInputDeviceIDs.Remove(index); + m_DefaultAudioInputDeviceNames->Delete(index); + } + } + m_Parent.cbAvailableAudioInputsChanged(); + + TRACE_FUNCTION_EXIT; +} +/* For QAudioEndpointSelector end */ + +/* For QAudioEncoderControl begin */ +const RArray<TPtrC>& XARecordSessionImpl::getAudioEncoderNames() +{ + TRACE_FUNCTION_ENTRY_EXIT; + return m_EncoderNames; +} + +TInt32 XARecordSessionImpl::getSampleRates( + const TDesC& aEncoder, + RArray<TInt32> &aSampleRates, + TBool &aIsContinuous) +{ + TRACE_FUNCTION_ENTRY; + + aSampleRates.Reset(); + aIsContinuous = EFalse; + + XAuint32 encoderId = 0; + TBool found(EFalse); + for (TInt index = 0; index < m_EncoderIds.Count(); index++) { + if (m_EncoderNames[index].Compare(aEncoder) == 0) { + found = ETrue; + encoderId = m_EncoderIds[index]; + break; + } + } + + TInt32 returnValue(KErrGeneral); + if (found == false) + return returnValue; + + returnValue = getSampleRatesByAudioCodecID(encoderId, aSampleRates); + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::getBitrates( + const TDesC& aEncoder, + RArray<TUint32> &aBitrates, + TBool& aContinuous) +{ + TRACE_FUNCTION_ENTRY; + + aBitrates.Reset(); + + XAuint32 encoderId = 0; + TBool found(EFalse); + for (TInt index = 0; index < m_EncoderIds.Count(); index++) { + if (m_EncoderNames[index].Compare(aEncoder) == 0) { + found = ETrue; + encoderId = m_EncoderIds[index]; + break; + } + } + + TInt32 returnValue(KErrNotSupported); + XAboolean cont; + if (found == false) + return returnValue; + + returnValue = getBitratesByAudioCodecID(encoderId, aBitrates, cont); + aContinuous = cont; + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +/* For QAudioEncoderControl end */ + +/* For QMediaContainerControl begin */ +const RArray<TPtrC>& XARecordSessionImpl::getContainerNames() +{ + TRACE_FUNCTION_ENTRY_EXIT; + return m_ContainerNames; +} + +const RArray<TPtrC>& XARecordSessionImpl::getContainerDescs() +{ + TRACE_FUNCTION_ENTRY_EXIT; + return m_ContainerDescs; +} + +/* For QMediaContainerControl end */ + +void XARecordSessionImpl::resetEncoderAttributes() +{ + m_ContainerType = 0; + m_AudioEncoderId = 0; + m_ProfileSetting = 0; + m_BitRate = 0; + m_ChannelsOut = 1; + m_SampleRate = 0; + m_RateControl = 0; +} + +void XARecordSessionImpl::setContainerType(const TDesC &aURI) +{ + TRACE_FUNCTION_ENTRY; + + if (aURI.Compare(KCONTAINERWAV()) == 0) + m_ContainerType = XA_CONTAINERTYPE_WAV; + else if (aURI.Compare(KCONTAINERAMR()) == 0) + m_ContainerType = XA_CONTAINERTYPE_AMR; + else if (aURI.Compare(KCONTAINERMP4()) == 0) + m_ContainerType = XA_CONTAINERTYPE_MP4; + + TRACE_FUNCTION_EXIT; +} + +TBool XARecordSessionImpl::setCodec(const TDesC &aCodec) +{ + TRACE_FUNCTION_ENTRY; + + TBool returnValue(EFalse); + if (aCodec.Compare(KAUDIOCODECPCM()) == 0) { + m_AudioEncoderId = XA_AUDIOCODEC_PCM; + m_ProfileSetting = XA_AUDIOPROFILE_PCM; + returnValue = ETrue; + } + else if (aCodec.Compare(KAUDIOCODECAAC()) == 0) { + m_AudioEncoderId = XA_AUDIOCODEC_AAC; + m_ProfileSetting = XA_AUDIOPROFILE_AAC_AAC; + returnValue = ETrue; + } + else if (aCodec.Compare(KAUDIOCODECAMR()) == 0) { + m_AudioEncoderId = XA_AUDIOCODEC_AMR; + m_ProfileSetting = XA_AUDIOPROFILE_AMR; + returnValue = ETrue; + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TUint32 XARecordSessionImpl::getBitRate() +{ + return m_BitRate; +} + +void XARecordSessionImpl::setBitRate(TUint32 aBitRate) +{ + TRACE_FUNCTION_ENTRY; + RArray<TUint32> bitrates; + XAboolean isContinuous; + m_BitRate = 0; + if (getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, isContinuous) == KErrNone) { + bitrates.SortUnsigned(); + TInt loopIndex(0); + while (loopIndex < bitrates.Count() + && aBitRate <= bitrates[loopIndex]) { + m_BitRate = bitrates[loopIndex]; + loopIndex++; + } + bitrates.Close(); + } + TRACE_LOG((_L("BitRate[%d]"), m_BitRate)); + TRACE_FUNCTION_EXIT; +} + +TUint32 XARecordSessionImpl::getChannels() +{ + return m_ChannelsOut; +} + +void XARecordSessionImpl::setChannels(TUint32 aChannels) +{ + TRACE_FUNCTION_ENTRY; + switch (m_AudioEncoderId) { + case XA_AUDIOCODEC_PCM: + case XA_AUDIOCODEC_AAC: + m_ChannelsOut = 1; + if ((aChannels >= 1) && (aChannels <= 2)) + m_ChannelsOut = aChannels; + break; + case XA_AUDIOCODEC_AMR: + m_ChannelsOut = 1; + break; + default: + break; + } + TRACE_LOG((_L("ChannelCount[%d]"), m_ChannelsOut)); + TRACE_FUNCTION_EXIT; +} + +void XARecordSessionImpl::setOptimalChannelCount() +{ + TRACE_FUNCTION_ENTRY; + m_ChannelsOut = 1; + TRACE_FUNCTION_EXIT; +} + +TUint32 XARecordSessionImpl::getSampleRate() +{ + return m_SampleRate; +} + +void XARecordSessionImpl::setSampleRate(TUint32 aSampleRate) +{ + TRACE_FUNCTION_ENTRY; + + m_SampleRate = 0; + + RArray<TInt32> samplerates; + if (getSampleRatesByAudioCodecID(m_AudioEncoderId, samplerates) == KErrNone) { + samplerates.SortUnsigned(); + TInt loopIndex(0); + while (loopIndex < samplerates.Count()) { + m_SampleRate = samplerates[loopIndex]; + if (samplerates[loopIndex] > aSampleRate) + break; + loopIndex++; + } + samplerates.Close(); + } + + /* convert Hz to MilliHz */ + m_SampleRate *= KMilliToHz; + TRACE_LOG((_L("SampleRate[%d]"), m_SampleRate)); + TRACE_FUNCTION_EXIT; +} + +void XARecordSessionImpl::setOptimalSampleRate() +{ + TRACE_FUNCTION_ENTRY; + m_SampleRate = 0; + + if (m_AudioEncoderId == XA_AUDIOCODEC_AAC) { + m_SampleRate = 32000 * KMilliToHz; + } + else if (m_AudioEncoderId == XA_AUDIOCODEC_AMR) { + m_SampleRate = 8000 * KMilliToHz; + } + else { + RArray<TInt32> sampleRates; + TInt res = getSampleRatesByAudioCodecID(m_AudioEncoderId, sampleRates); + if ((res == KErrNone) && (sampleRates.Count() > 0)) { + /* Sort the array and pick the middle range sample rate */ + sampleRates.SortUnsigned(); + m_SampleRate = sampleRates[sampleRates.Count() / 2] * KMilliToHz; + } + sampleRates.Close(); + } + + TRACE_FUNCTION_EXIT; +} + +TInt32 XARecordSessionImpl::setCBRMode() +{ + TRACE_FUNCTION_ENTRY; + + m_RateControl = XA_RATECONTROLMODE_CONSTANTBITRATE; + + TRACE_FUNCTION_EXIT; + return KErrNone; +} + +TInt32 XARecordSessionImpl::setVBRMode() +{ + TRACE_FUNCTION_ENTRY; + + m_RateControl = XA_RATECONTROLMODE_VARIABLEBITRATE; + + TRACE_FUNCTION_EXIT; + return KErrNone; +} + +void XARecordSessionImpl::setVeryLowQuality() +{ + /* Set to very low quality encoder preset */ + RArray<TUint32> bitrates; + XAboolean continuous; + TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous); + if ((res == KErrNone) && (bitrates.Count() > 0)) { + /* Sort the array and pick the lowest bit rate */ + bitrates.SortUnsigned(); + m_BitRate = bitrates[0]; + } + bitrates.Close(); +} + +void XARecordSessionImpl::setLowQuality() +{ + /* Set to low quality encoder preset */ + RArray<TUint32> bitrates; + XAboolean continuous; + TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous); + if ((res == KErrNone) && (bitrates.Count() > 0)) { + /* Sort the array and pick the low quality bit rate */ + bitrates.SortUnsigned(); + if (continuous == XA_BOOLEAN_FALSE) + m_BitRate = bitrates[bitrates.Count() / 4]; + else + m_BitRate = (bitrates[1] - bitrates[0]) / 4; + } + bitrates.Close(); +} + +void XARecordSessionImpl::setNormalQuality() +{ + /* Set to normal quality encoder preset */ + RArray<TUint32> bitrates; + XAboolean continuous; + TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous); + if ((res == KErrNone) && (bitrates.Count() > 0)) { + /* Sort the array and pick the middle range bit rate */ + bitrates.SortUnsigned(); + if (continuous == XA_BOOLEAN_FALSE) + m_BitRate = bitrates[bitrates.Count() / 2]; + else + m_BitRate = (bitrates[1] - bitrates[0]) / 2; + } + bitrates.Close(); +} + +void XARecordSessionImpl::setHighQuality() +{ + /* Set to high quality encoder preset */ + RArray<TUint32> bitrates; + XAboolean continuous; + TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous); + if ((res == KErrNone) && (bitrates.Count() > 0)) { + /* Sort the array and pick the high quality bit rate */ + bitrates.SortUnsigned(); + if (continuous == XA_BOOLEAN_FALSE) + m_BitRate = bitrates[bitrates.Count() * 3 / 4]; + else + m_BitRate = (bitrates[1] - bitrates[0]) * 3 / 4; + } + bitrates.Close(); +} + +void XARecordSessionImpl::setVeryHighQuality() +{ + /* Set to very high quality encoder preset */ + RArray<TUint32> bitrates; + XAboolean continuous; + TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous); + if ((res == KErrNone) && (bitrates.Count() > 0)) { + /* Sort the array and pick the highest bit rate */ + bitrates.SortUnsigned(); + m_BitRate = bitrates[bitrates.Count() - 1]; + } + bitrates.Close(); +} + +/* Internal function */ +TInt32 XARecordSessionImpl::createMediaRecorderObject() +{ + TRACE_FUNCTION_ENTRY; + + if (!m_EOEngine) + return KErrGeneral; + + TInt32 returnValue(KErrNone); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject")); + if (!m_MORecorder && !m_RecordItf) { + + /* Setup the data source */ + m_LocatorMic.locatorType = XA_DATALOCATOR_IODEVICE; + m_LocatorMic.deviceType = XA_IODEVICE_AUDIOINPUT; + m_LocatorMic.deviceID = m_InputDeviceId; + m_LocatorMic.device = NULL; + m_DataSource.pLocator = (void*) &m_LocatorMic; + m_DataSource.pFormat = NULL; + + /* Setup the data sink structure */ + m_Uri.locatorType = XA_DATALOCATOR_URI; + /* append zero terminator to end of URI */ + TPtr8 uriPtr = m_URIName->Des(); + m_Uri.URI = (XAchar*) uriPtr.PtrZ(); + m_Mime.formatType = XA_DATAFORMAT_MIME; + m_Mime.containerType = m_ContainerType; + TPtr8 mimeTypePtr(m_WAVMime->Des()); + m_Mime.mimeType = (XAchar*) mimeTypePtr.Ptr(); + m_DataSink.pLocator = (void*) &m_Uri; + m_DataSink.pFormat = (void*) &m_Mime; + + /* Init arrays required[] and iidArray[] */ + XAboolean required[MAX_NUMBER_INTERFACES]; + XAInterfaceID iidArray[MAX_NUMBER_INTERFACES]; + for (TInt32 i = 0; i < MAX_NUMBER_INTERFACES; i++) { + required[i] = XA_BOOLEAN_FALSE; + iidArray[i] = XA_IID_NULL; + } + XAuint32 noOfInterfaces = 0; + required[noOfInterfaces] = XA_BOOLEAN_FALSE; + iidArray[noOfInterfaces] = XA_IID_RECORD; + noOfInterfaces++; + required[noOfInterfaces] = XA_BOOLEAN_FALSE; + iidArray[noOfInterfaces] = XA_IID_AUDIOENCODER; + noOfInterfaces++; + + XAEngineItf engineItf; + XAresult xa_result = (*m_EOEngine)->GetInterface(m_EOEngine, XA_IID_ENGINE, (void**) &engineItf); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Create Media Recorder...")); + + /* Create recorder with NULL for a the image/video source, since this is for audio-only recording */ + xa_result = (*engineItf)->CreateMediaRecorder( + engineItf, + &m_MORecorder, + &m_DataSource, + NULL, + &m_DataSink, + noOfInterfaces, + iidArray, + required); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Realize Media Recorder...")); + xa_result = (*m_MORecorder)->Realize(m_MORecorder, XA_BOOLEAN_FALSE); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Register Callback on recorder...")); + xa_result = (*m_MORecorder)->RegisterCallback(m_MORecorder, cbXAObjectItf, (void*) this); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Getting Record Interface...")); + xa_result = (*m_MORecorder)->GetInterface(m_MORecorder, XA_IID_RECORD, &m_RecordItf); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Registering Callback on record Interface...")); + xa_result = (*m_RecordItf)->RegisterCallback(m_RecordItf, cbXARecordItf, (void*) this); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: SetPositionUpdatePeriod on record Interface...")); + xa_result = (*m_RecordItf)->SetPositionUpdatePeriod(m_RecordItf, (XAmillisecond)KRecordPosUpdatePeriod); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: SetCallbackEventsMask on record Interface...")); + xa_result = (*m_RecordItf)->SetCallbackEventsMask(m_RecordItf, XA_RECORDEVENT_HEADATNEWPOS | + XA_RECORDEVENT_HEADMOVING | + XA_RECORDEVENT_HEADSTALLED); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Getting Audio Encoder Interface...")); + xa_result = (*m_MORecorder)->GetInterface(m_MORecorder, XA_IID_AUDIOENCODER, &m_AudioEncItf); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::mapError(XAresult xa_err, TBool debPrn) +{ + TInt32 returnValue(KErrGeneral); + switch (xa_err) { + case XA_RESULT_SUCCESS: + returnValue = KErrNone; + break; + case XA_RESULT_PRECONDITIONS_VIOLATED: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_PRECONDITIONS_VIOLATED")); + break; + case XA_RESULT_PARAMETER_INVALID: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_PARAMETER_INVALID")); + break; + case XA_RESULT_MEMORY_FAILURE: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_MEMORY_FAILURE")); + break; + case XA_RESULT_RESOURCE_ERROR: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_RESOURCE_ERROR")); + break; + case XA_RESULT_RESOURCE_LOST: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_RESOURCE_LOST")); + break; + case XA_RESULT_IO_ERROR: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_IO_ERROR")); + break; + case XA_RESULT_BUFFER_INSUFFICIENT: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_BUFFER_INSUFFICIENT")); + break; + case XA_RESULT_CONTENT_CORRUPTED: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_CONTENT_CORRUPTED")); + break; + case XA_RESULT_CONTENT_UNSUPPORTED: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_CONTENT_UNSUPPORTED")); + break; + case XA_RESULT_CONTENT_NOT_FOUND: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_CONTENT_NOT_FOUND")); + break; + case XA_RESULT_PERMISSION_DENIED: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_PERMISSION_DENIED")); + break; + case XA_RESULT_FEATURE_UNSUPPORTED: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_FEATURE_UNSUPPORTED")); + break; + case XA_RESULT_INTERNAL_ERROR: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_INTERNAL_ERROR")); + break; + case XA_RESULT_UNKNOWN_ERROR: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_UNKNOWN_ERROR")); + break; + case XA_RESULT_OPERATION_ABORTED: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_OPERATION_ABORTED")); + break; + case XA_RESULT_CONTROL_LOST: + if (debPrn) + TRACE_LOG(_L("XA_RESULT_CONTROL_LOST")); + break; + default: + if (debPrn) + TRACE_LOG(_L("Unknown Error!!!")); + break; + } + return returnValue; +} + +TInt32 XARecordSessionImpl::initContainersList() +{ + TRACE_FUNCTION_ENTRY; + + m_ContainerNames.Reset(); + m_ContainerDescs.Reset(); + + m_ContainerNames.Append(KCONTAINERWAV()); + m_ContainerNames.Append(KCONTAINERAMR()); + m_ContainerNames.Append(KCONTAINERMP4()); + + m_ContainerDescs.Append(KCONTAINERWAVDESC()); + m_ContainerDescs.Append(KCONTAINERAMRDESC()); + m_ContainerDescs.Append(KCONTAINERMP4DESC()); + + TRACE_FUNCTION_EXIT; + return KErrNone; +} + +TInt32 XARecordSessionImpl::initAudioEncodersList() +{ + TRACE_FUNCTION_ENTRY; + + m_EncoderIds.Reset(); + m_EncoderNames.Reset(); + + XAuint32 encoderIds[MAX_NUMBER_ENCODERS]; + + for (TInt index = 0; index < MAX_NUMBER_ENCODERS; index++) + encoderIds[index] = 0; + + XAuint32 numEncoders = MAX_NUMBER_ENCODERS; + XAresult xa_result = (*m_AudioEncCapsItf)->GetAudioEncoders( + m_AudioEncCapsItf, + &numEncoders, + encoderIds); + TInt32 returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + for (TInt index = 0; index < numEncoders; index++) { + m_EncoderIds.Append(encoderIds[index]); + switch (encoderIds[index]) { + case XA_AUDIOCODEC_PCM: + m_EncoderNames.Append(KAUDIOCODECPCM()); + break; + case XA_AUDIOCODEC_AMR: + m_EncoderNames.Append(KAUDIOCODECAMR()); + break; + case XA_AUDIOCODEC_AAC: + m_EncoderNames.Append(KAUDIOCODECAAC()); + break; + default: + break; + }; + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::initAudioInputDevicesList() +{ + TRACE_FUNCTION_ENTRY; + + m_InputDeviceIDs.Reset(); + + XAuint32 deviceIds[MAX_NUMBER_INPUT_DEVICES]; + for (TInt index = 0; index < MAX_NUMBER_INPUT_DEVICES; index++) + deviceIds[index] = 0; + + XAint32 numInputs = MAX_NUMBER_INPUT_DEVICES; + XAresult xa_result = (*m_AudioIODevCapsItf)->GetAvailableAudioInputs( + m_AudioIODevCapsItf, + &numInputs, + deviceIds); + TInt32 returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + XAAudioInputDescriptor audioInputDescriptor; + for (TInt index = 0; index < numInputs; index++) { + xa_result = (*m_AudioIODevCapsItf)->QueryAudioInputCapabilities( + m_AudioIODevCapsItf, + deviceIds[index], + &audioInputDescriptor); + returnValue = mapError(xa_result, ETrue); + if (returnValue != KErrNone) + continue; + + TUint8 * inDevNamePtr = audioInputDescriptor.deviceName; + TUint8 * tempPtr = audioInputDescriptor.deviceName; + TInt32 inDevNameLength = 0; + while (*tempPtr++) + inDevNameLength++; + TPtrC8 ptr(inDevNamePtr, inDevNameLength); + /* Convert 8 bit to 16 bit */ + TBuf16<KMaxNameLength> name; + name.Copy(ptr); + /* Using TRAP with returnValue results in compiler error */ + TRAPD(err2, m_AudioInputDeviceNames->AppendL(name)); + returnValue = err2; + if (returnValue != KErrNone) + continue; + m_InputDeviceIDs.Append(deviceIds[index]); + } + + numInputs = MAX_NUMBER_INPUT_DEVICES; + for (TInt index = 0; index < MAX_NUMBER_INPUT_DEVICES; index++) + deviceIds[index] = 0; + xa_result = (*m_AudioIODevCapsItf)->GetDefaultAudioDevices( + m_AudioIODevCapsItf, + XA_DEFAULTDEVICEID_AUDIOINPUT, + &numInputs, + deviceIds); + returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + for (TInt index = 0; index < numInputs; index++) { + xa_result = (*m_AudioIODevCapsItf)->QueryAudioInputCapabilities( + m_AudioIODevCapsItf, + deviceIds[index], + &audioInputDescriptor); + returnValue = mapError(xa_result, ETrue); + if (returnValue != KErrNone) + continue; + TUint8* inDevNamePtr = audioInputDescriptor.deviceName; + TUint8* tempPtr = audioInputDescriptor.deviceName; + TInt32 inDevNameLength = 0; + while (*tempPtr++) + inDevNameLength++; + TPtrC8 ptr(inDevNamePtr, inDevNameLength); + /* Convert 8 bit to 16 bit */ + TBuf16<KMaxNameLength> name; + name.Copy(ptr); + /* Using TRAP with returnValue results in compiler error */ + TRAPD(err2, m_DefaultAudioInputDeviceNames->AppendL(name)); + returnValue = err2; + if (returnValue != KErrNone) + continue; + m_DefaultInputDeviceIDs.Append(deviceIds[index]); + m_InputDeviceId = deviceIds[index]; + } + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::setEncoderSettingsToMediaRecorder() +{ + TRACE_FUNCTION_EXIT; + + /* Get current settings */ + XAAudioEncoderSettings settings; + XAresult xa_result = (*m_AudioEncItf)->GetEncoderSettings( + m_AudioEncItf, + &settings); + TInt32 returnValue = mapError(xa_result, ETrue); + + settings.encoderId = m_AudioEncoderId; + settings.channelsOut = m_ChannelsOut; + if ((m_SampleRate != 0) && (m_SampleRate != 0xffffffff)) + settings.sampleRate = m_SampleRate; + if ((m_BitRate != 0) && (m_BitRate != 0xffffffff)) + settings.bitRate = m_BitRate; + if (m_RateControl != 0) + settings.rateControl = m_RateControl; + settings.profileSetting = m_ProfileSetting; + xa_result = (*m_AudioEncItf)->SetEncoderSettings( + m_AudioEncItf, + &settings); + returnValue = mapError(xa_result, ETrue); + + TRACE_FUNCTION_EXIT; + return returnValue; +} + +TInt32 XARecordSessionImpl::getBitratesByAudioCodecID( + XAuint32 encoderId, + RArray<TUint32> &aBitrates, + XAboolean& aContinuous) +{ + TRACE_FUNCTION_ENTRY; + + if (!m_AudioEncCapsItf) + return KErrGeneral; + + XAuint32 numCaps = 0; + XAAudioCodecDescriptor codecDesc; + XAresult xa_result = (*m_AudioEncCapsItf)->GetAudioEncoderCapabilities( + m_AudioEncCapsItf, + encoderId, + &numCaps, + &codecDesc); + TInt32 returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + aContinuous = codecDesc.isBitrateRangeContinuous; + /* TODO What do we do if we have more than one caps?? */ + if (codecDesc.isBitrateRangeContinuous == XA_BOOLEAN_TRUE) { + aBitrates.Append(codecDesc.minBitRate); + aBitrates.Append(codecDesc.maxBitRate); + } + else { + XAuint32 numBrSupported = codecDesc.numBitratesSupported; + XAuint32 * pBitratesSupported(NULL); + pBitratesSupported = codecDesc.pBitratesSupported; + TInt32 index = 0; + for (index = 0; index < numBrSupported; index++) + aBitrates.Append(*(pBitratesSupported + index)); + } + + TRACE_FUNCTION_ENTRY; + return returnValue; +} + +TInt32 XARecordSessionImpl::getSampleRatesByAudioCodecID(XAuint32 encoderId, + RArray<TInt32> &aSampleRates) +{ + TRACE_FUNCTION_ENTRY; + + if (!m_AudioEncCapsItf) + return KErrGeneral; + + XAuint32 numCaps = 0; + XAAudioCodecDescriptor codecDesc; + XAresult xa_result = (*m_AudioEncCapsItf)->GetAudioEncoderCapabilities( + m_AudioEncCapsItf, + encoderId, + &numCaps, + &codecDesc); + TInt returnValue = mapError(xa_result, ETrue); + RET_ERR_IF_ERR(returnValue); + + /* TODO What do we do if we have more than one caps?? */ + if (codecDesc.isFreqRangeContinuous == XA_BOOLEAN_TRUE) { + aSampleRates.Append(codecDesc.minSampleRate / KMilliToHz); + aSampleRates.Append(codecDesc.maxSampleRate / KMilliToHz); + } + else { + XAuint32 numSRSupported = codecDesc.numSampleRatesSupported; + XAmilliHertz *pSampleRatesSupported(NULL); + pSampleRatesSupported = codecDesc.pSampleRatesSupported; + for (TInt index = 0; index < numSRSupported; index++) + aSampleRates.Append((*(pSampleRatesSupported + index)) / KMilliToHz); + } + + TRACE_FUNCTION_ENTRY; + return returnValue; +} + +/* Local function implementation */ +void cbXAObjectItf( + XAObjectItf caller, + const void *pContext, + XAuint32 event, + XAresult result, + XAuint32 param, + void *pInterface) +{ + if (pContext) { + ((XARecordSessionImpl*)pContext)->cbMediaRecorder( + caller, + pContext, + event, + result, + param, + pInterface); + } +} + +void cbXARecordItf( + XARecordItf caller, + void *pContext, + XAuint32 event) +{ + if (pContext) { + ((XARecordSessionImpl*)pContext)->cbRecordItf( + caller, + pContext, + event); + } +} + +void cbXAAvailableAudioInputsChanged( + XAAudioIODeviceCapabilitiesItf caller, + void * pContext, + XAuint32 deviceID, + XAint32 numInputs, + XAboolean isNew) +{ + if (pContext) { + ((XARecordSessionImpl*)pContext)->cbAvailableAudioInputsChanged( + caller, + pContext, + deviceID, + numInputs, + isNew); + } +} diff --git a/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.h b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.h new file mode 100644 index 000000000..81e4ac763 --- /dev/null +++ b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.h @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef XARECORDSESSIONIMPL_H +#define XARECORDSESSIONIMPL_H + +#include <OpenMAXAL.h> +#include <badesca.h> + + +class XARecordObserver; +class XARecordSessionImpl +{ +public: + XARecordSessionImpl(XARecordObserver &parent); + ~XARecordSessionImpl(); + TInt32 postConstruct(); + + /* For QMediaRecorderControl begin */ + TInt32 setURI(const TDesC &aURI); + TInt32 record(); + TInt32 pause(); + TInt32 stop(); + TInt32 duration(TInt64 &aDur); + /* For QMediaRecorderControl end */ + + void cbMediaRecorder(XAObjectItf caller, + const void *pContext, + XAuint32 event, + XAresult result, + XAuint32 param, + void *pInterface); + void cbRecordItf(XARecordItf caller, + void *pContext, + XAuint32 event); + + /* For QAudioEndpointSelector begin */ + void getAudioInputDeviceNames(RArray<TPtrC> &aArray); + TInt32 defaultAudioInputDevice(TPtrC &endPoint); + TInt32 activeAudioInputDevice(TPtrC &endPoint); + TBool setAudioInputDevice(const TDesC &aDevice); + void cbAvailableAudioInputsChanged(XAAudioIODeviceCapabilitiesItf caller, + void *pContext, + XAuint32 deviceID, + XAint32 numInputs, + XAboolean isNew); + /* For QAudioEndpointSelector end */ + + /* For QAudioEncoderControl begin */ + const RArray<TPtrC>& getAudioEncoderNames(); + TInt32 getSampleRates(const TDesC &aEncoder, + RArray<TInt32> &aSampleRates, + TBool &aIsContinuous); + TInt32 getBitrates(const TDesC &aEncoder, + RArray<TUint32> &aBitrates, + TBool& aContinuous); + /* For QAudioEncoderControl end */ + + /* For QMediaContainerControl begin */ + const RArray<TPtrC>& getContainerNames(); + const RArray<TPtrC>& getContainerDescs(); + /* For QMediaContainerControl end */ + + void resetEncoderAttributes(); + void setContainerType(const TDesC &aURI); + TBool setCodec(const TDesC &aURI); + TUint32 getBitRate(); + void setBitRate(TUint32 aBitRate); + TUint32 getChannels(); + void setChannels(TUint32 aChannels); + void setOptimalChannelCount(); + TUint32 getSampleRate(); + void setSampleRate(TUint32 aSampleRate); + void setOptimalSampleRate(); + TInt32 setCBRMode(); + TInt32 setVBRMode(); + void setVeryLowQuality(); + void setLowQuality(); + void setNormalQuality(); + void setHighQuality(); + void setVeryHighQuality(); + +private: + TInt32 createMediaRecorderObject(); + TInt32 mapError(XAresult xa_err, + TBool debPrn); + TInt32 initContainersList(); + TInt32 initAudioEncodersList(); + TInt32 initAudioInputDevicesList(); + TInt32 setEncoderSettingsToMediaRecorder(); + TInt32 getBitratesByAudioCodecID(XAuint32 encoderId, + RArray<TUint32> &aBitrates, + XAboolean& aContinuous); + TInt32 getSampleRatesByAudioCodecID(XAuint32 encoderId, + RArray<TInt32> &aSampleRates); + + +private: + XARecordObserver &m_Parent; + XAObjectItf m_EOEngine; + XAObjectItf m_MORecorder; + XARecordItf m_RecordItf; + XAAudioEncoderItf m_AudioEncItf; + /* Audio Source */ + XADataSource m_DataSource; + XADataLocator_IODevice m_LocatorMic; + XADataFormat_MIME m_Mime; + XADataLocator_URI m_Uri; + /*Audio Sink*/ + XADataSink m_DataSink; + HBufC8 *m_WAVMime; + + /* Set by client*/ + HBufC8 *m_URIName; + XAuint32 m_AudioEncoderId; + XAuint32 m_InputDeviceId; + XAuint32 m_ContainerType; + XAuint32 m_BitRate; + XAuint32 m_RateControl; + XAuint32 m_ProfileSetting; + XAuint32 m_ChannelsOut; + XAuint32 m_SampleRate; + + /* For QAudioEndpointSelector begin */ + XAAudioIODeviceCapabilitiesItf m_AudioIODevCapsItf; + RArray<TUint32> m_InputDeviceIDs; + CDesC16ArrayFlat *m_AudioInputDeviceNames; + RArray<TUint32> m_DefaultInputDeviceIDs; + CDesC16ArrayFlat *m_DefaultAudioInputDeviceNames; + /* For QAudioEndpointSelector end */ + + /* For QAudioEncoderControl begin */ + XAAudioEncoderCapabilitiesItf m_AudioEncCapsItf; + RArray<XAuint32> m_EncoderIds; + RArray<TPtrC> m_EncoderNames; + RArray<TPtrC> m_ContainerNames; + RArray<TPtrC> m_ContainerDescs; + /* For QAudioEncoderControl begin */ +}; + +#endif /* XARECORDSESSIONIMPL_H */ |