qtmobility/plugins/multimedia/symbian/openmaxal/mediarecorder/qxarecordsession.cpp
changeset 4 90517678cc4f
child 5 453da2cfceef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qtmobility/plugins/multimedia/symbian/openmaxal/mediarecorder/qxarecordsession.cpp	Mon May 03 13:18:40 2010 +0300
@@ -0,0 +1,647 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 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 <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<int>)
+
+/* 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, 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, 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)
+{
+    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();
+            m_audioencodersettings.setBitRate(0);
+            m_audioencodersettings.setChannelCount(-1);
+            m_audioencodersettings.setEncodingMode(QtMedia::ConstantQualityEncoding);
+            m_audioencodersettings.setQuality(QtMedia::NormalQuality);
+            m_audioencodersettings.setSampleRate(-1);
+            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().toLower())).toString();
+    QString curUrlStr = (QUrl::fromUserInput(m_outputLocation.toString().toLower())).toString();
+    if (curUrlStr.compare(newUrlStr) == KErrNone)
+        return true;
+
+    bool retVal = false;
+    TPtrC16 tempPtr(reinterpret_cast<const TUint16 *>(newUrlStr.utf16()));
+    if (m_impl->setURI(tempPtr) == 0) {
+        m_outputLocation = location;
+        retVal = true;
+    }
+    else {
+        emit error(QMediaRecorder::ResourceError, tr("Generic error"));
+        SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Generic error\"))");
+    }
+
+    QT_TRACE_FUNCTION_EXIT;
+    return retVal;
+}
+
+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()
+{
+    if (m_appliedaudioencodersettings != m_audioencodersettings)
+        setEncoderSettingsToImpl();
+}
+
+void QXARecordSession::record()
+{
+    QT_TRACE_FUNCTION_ENTRY;
+
+    RETURN_IF_m_impl_IS_NULL;
+
+    /* 1. Set encoder settings here */
+    if (m_appliedaudioencodersettings != m_audioencodersettings)
+        RET_IF_FALSE(setEncoderSettingsToImpl());
+
+    /* 2. 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;
+
+    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;
+
+    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)
+{
+    emit durationChanged((qint64)new_pos);
+    SIGNAL_EMIT_TRACE1("emit durationChanged((qint64)new_pos);");
+}
+
+void QXARecordSession::cbAvailableAudioInputsChanged()
+{
+    emit availableAudioInputsChanged();
+    SIGNAL_EMIT_TRACE1("emit availableAudioInputsChanged();");
+}
+
+void QXARecordSession::cbRecordingStarted()
+{
+    setRecorderState(QMediaRecorder::RecordingState);
+}
+
+void QXARecordSession::cbRecordingStopped()
+{
+    emit error(QMediaRecorder::ResourceError, tr("Resources Unavailable"));
+    SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Resources Unavailable\"))");
+    setRecorderState(QMediaRecorder::StoppedState);
+}
+
+/* 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;
+
+    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.toLower()))
+        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().toLower();
+
+    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();
+            *continuous = false;
+            if (isContinuous == true)
+                *continuous = true;
+        }
+    }
+
+    QT_TRACE_FUNCTION_EXIT;
+    return srList;
+}
+
+QAudioEncoderSettings QXARecordSession::audioSettings()
+{
+    return m_audioencodersettings;
+}
+
+void QXARecordSession::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+    m_audioencodersettings = settings;
+}
+
+QStringList QXARecordSession::supportedEncodingOptions(const QString &codec)
+{
+    QT_TRACE_FUNCTION_ENTRY;
+    Q_UNUSED(codec);
+    QStringList options;
+    options << "bitrate";
+
+    QT_TRACE_FUNCTION_EXIT;
+    return options;
+}
+
+QVariant QXARecordSession::encodingOption(const QString &codec, const QString &name)
+{
+    QT_TRACE_FUNCTION_ENTRY;
+
+    QVariant encodingOption;
+
+    RETURN_s_IF_m_impl_IS_NULL(encodingOption);
+
+    if (name.toLower().compare("bitrate") == 0) {
+        TPtrC16 tempPtr(reinterpret_cast<const TUint16*>(codec.toLower().utf16()));
+        QList<int> bitrateList;
+        RArray<TUint32> bitrates;
+        if (m_impl->getBitrates(tempPtr, bitrates) == KErrNone) {
+            for (TInt index = 0; index < bitrates.Count(); index++)
+                bitrateList.append(bitrates[index]);
+            bitrates.Close();
+        }
+        encodingOption.setValue(bitrateList);
+    }
+
+    QT_TRACE_FUNCTION_EXIT;
+    return encodingOption;
+}
+
+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 (m_containers.indexOf(formatMimeType.toLower()) >= 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.toLower());
+    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_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();
+
+    QString tempStr = m_containerMimeType.toLower();
+    TPtrC16 tempPtr(reinterpret_cast<const TUint16 *>(tempStr.utf16()));
+    m_impl->setContainerType(tempPtr);
+
+    /* Validate and set bitrate only if encoding mode is other than quality encoding */
+    if (m_audioencodersettings.encodingMode() != QtMedia::ConstantQualityEncoding) {
+        if (m_audioencodersettings.bitRate() < 0 ) {
+            emit error(QMediaRecorder::FormatError, tr("Invalid bitrate"));
+            SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid bitrate\"))");
+            return false;
+        }
+        else {
+            m_impl->setBitRate(m_audioencodersettings.bitRate());
+        }
+    }
+
+    if (m_audioencodersettings.channelCount() == -1) {
+        m_impl->setOptimalChannelCount();
+    }
+    else if (m_audioencodersettings.channelCount() <= 0) {
+        emit error(QMediaRecorder::FormatError, tr("Invalid channel count"));
+        SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid channel count\"));");
+        return false;
+    }
+    else {
+        m_impl->setChannels(m_audioencodersettings.channelCount());
+    }
+
+    tempStr = m_audioencodersettings.codec().toLower();
+    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 {
+        emit error(QMediaRecorder::FormatError, tr("Invalid codec"));
+        SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid codec\"));");
+        return false;
+    }
+
+    switch (m_audioencodersettings.encodingMode()) {
+    case QtMedia::ConstantQualityEncoding: {
+            switch (m_audioencodersettings.quality()) {
+            case QtMedia::VeryLowQuality:
+                m_impl->setVeryLowQuality();
+                break;
+            case QtMedia::LowQuality:
+                m_impl->setLowQuality();
+                break;
+            case QtMedia::NormalQuality:
+                m_impl->setNormalQuality();
+                break;
+            case QtMedia::HighQuality:
+                m_impl->setHighQuality();
+                break;
+            case QtMedia::VeryHighQuality:
+                m_impl->setVeryHighQuality();
+                break;
+            default:
+                emit error(QMediaRecorder::FormatError, tr("Invalid encoding quality setting"));
+                SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid encoding quality setting\"));");
+                return false;
+            }; /* end of switch (m_audioencodersettings.quality())*/
+        }
+        break;
+    case QtMedia::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 QtMedia::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 QtMedia::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 if (m_audioencodersettings.sampleRate() <= 0) {
+        emit error(QMediaRecorder::FormatError, tr("Invalid sample rate"));
+        SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid sample rate\"));");
+        return false;
+    }
+    else {
+        m_impl->setSampleRate(m_audioencodersettings.sampleRate());
+    }
+    m_appliedaudioencodersettings = m_audioencodersettings;
+    QT_TRACE_FUNCTION_EXIT;
+    return true;
+}