diff options
Diffstat (limited to 'src/plugins/symbian/ecam/s60cameracontrol.cpp')
-rw-r--r-- | src/plugins/symbian/ecam/s60cameracontrol.cpp | 983 |
1 files changed, 983 insertions, 0 deletions
diff --git a/src/plugins/symbian/ecam/s60cameracontrol.cpp b/src/plugins/symbian/ecam/s60cameracontrol.cpp new file mode 100644 index 000000000..64a3ff37e --- /dev/null +++ b/src/plugins/symbian/ecam/s60cameracontrol.cpp @@ -0,0 +1,983 @@ +/**************************************************************************** +** +** 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 <QtCore/qstring.h> +#include <QTimer> + +#include "s60cameraservice.h" +#include "s60cameraengine.h" +#include "s60cameracontrol.h" +#include "s60imagecapturesession.h" +#include "s60videowidgetcontrol.h" +#include "s60cameraviewfinderengine.h" +#include "s60cameraconstants.h" + +S60CameraControl::S60CameraControl(QObject *parent) : + QCameraControl(parent) +{ +} + +S60CameraControl::S60CameraControl(S60VideoCaptureSession *videosession, + S60ImageCaptureSession *imagesession, + QObject *parent): + QCameraControl(parent), + m_cameraEngine(0), + m_viewfinderEngine(0), + m_imageSession(0), + m_videoSession(0), + m_advancedSettings(0), + m_videoOutput(0), + m_inactivityTimer(0), + m_captureMode(QCamera::CaptureStillImage), // Default CaptureMode + m_requestedCaptureMode(QCamera::CaptureStillImage), + m_settingCaptureModeInternally(false), + m_internalState(QCamera::UnloadedStatus), // Default Status + m_requestedState(QCamera::UnloadedState), // Default State + m_deviceIndex(KDefaultCameraDevice), + m_error(KErrNone), + m_changeCaptureModeWhenReady(false), + m_rotateCameraWhenReady(false), + m_videoCaptureState(S60VideoCaptureSession::ENotInitialized) +{ + m_videoSession = videosession; + m_imageSession = imagesession; + + m_inactivityTimer = new QTimer; + if (m_inactivityTimer) + m_inactivityTimer->setSingleShot(true); + + TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, KECamCameraPriority, this)); + if (err) { + m_error = err; + if (err == KErrPermissionDenied) + qWarning("Failed to create camera. Possibly missing capabilities."); + else + qWarning("Failed to create camera."); + return; + } + + m_viewfinderEngine = new S60CameraViewfinderEngine(this, m_cameraEngine, this); + if (m_viewfinderEngine == 0) { + m_error = KErrNoMemory; + qWarning("Failed to create viewfinder engine."); + return; + } + + // Connect signals + connect(m_inactivityTimer, SIGNAL(timeout()), this, SLOT(toStandByStatus())); + connect(this, SIGNAL(statusChanged(QCamera::Status)), + m_imageSession, SLOT(cameraStatusChanged(QCamera::Status))); + connect(this, SIGNAL(statusChanged(QCamera::Status)), + m_videoSession, SLOT(cameraStatusChanged(QCamera::Status))); + connect(m_videoSession, SIGNAL(stateChanged(S60VideoCaptureSession::TVideoCaptureState)), + this, SLOT(videoStateChanged(S60VideoCaptureSession::TVideoCaptureState))); + connect(m_imageSession, SIGNAL(advancedSettingChanged()), this, SLOT(advancedSettingsCreated())); + connect(this, SIGNAL(cameraReadyChanged(bool)), m_imageSession, SIGNAL(readyForCaptureChanged(bool))); + connect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&))); + connect(m_imageSession, SIGNAL(cameraError(int, const QString&)), this, SIGNAL(error(int, const QString&))); + connect(m_imageSession, SIGNAL(captureSizeChanged(const QSize&)), + m_viewfinderEngine, SLOT(handleContentAspectRatioChange(const QSize&))); + connect(m_videoSession, SIGNAL(captureSizeChanged(const QSize&)), + m_viewfinderEngine, SLOT(handleContentAspectRatioChange(const QSize&))); + + setCameraHandles(); +} + +S60CameraControl::~S60CameraControl() +{ + unloadCamera(); + + if (m_viewfinderEngine) { + delete m_viewfinderEngine; + m_viewfinderEngine = 0; + } + + // Make sure AdvancedSettings are destructed + m_imageSession->deleteAdvancedSettings(); + + if (m_cameraEngine) { + delete m_cameraEngine; + m_cameraEngine = 0; + } + + if (m_inactivityTimer) { + delete m_inactivityTimer; + m_inactivityTimer = 0; + } +} + +void S60CameraControl::setState(QCamera::State state) +{ + if (m_error) { // Most probably failure in contructor + setError(m_error, tr("Unexpected camera error.")); + return; + } + + if (m_requestedState == state) + return; + + if (m_inactivityTimer->isActive()) + m_inactivityTimer->stop(); + + // Save the target state + m_requestedState = state; + emit stateChanged(m_requestedState); + + switch (state) { + case QCamera::UnloadedState: // To UnloadedState - Release resources + switch (m_internalState) { + case QCamera::UnloadedStatus: + // Do nothing + break; + case QCamera::LoadingStatus: + case QCamera::StartingStatus: + // Release resources when ready (setting state handles this) + return; + case QCamera::LoadedStatus: + case QCamera::StandbyStatus: + // Unload + unloadCamera(); + break; + case QCamera::ActiveStatus: + // Stop and Unload + stopCamera(); + unloadCamera(); + break; + + default: + // Unrecognized internal state (Status) + setError(KErrGeneral, tr("Unexpected camera error.")); + return; + } + break; + + case QCamera::LoadedState: // To LoadedState - Reserve resources OR Stop ViewFinder and Cancel Capture + switch (m_internalState) { + case QCamera::UnloadedStatus: + case QCamera::StandbyStatus: + // Load + loadCamera(); + break; + case QCamera::LoadingStatus: + // Discard, already moving to LoadedStatus + return; + case QCamera::StartingStatus: + // Stop when ready (setting state handles this) + return; + case QCamera::LoadedStatus: + m_inactivityTimer->start(KInactivityTimerTimeout); + break; + case QCamera::ActiveStatus: + // Stop + stopCamera(); + break; + + default: + // Unregocnized internal state (Status) + setError(KErrGeneral, tr("Unexpected camera error.")); + return; + } + break; + + case QCamera::ActiveState: // To ActiveState - (Reserve Resources and) Start ViewFinder + switch (m_internalState) { + case QCamera::UnloadedStatus: + case QCamera::StandbyStatus: + // Load and Start (setting state handles starting) + loadCamera(); + break; + case QCamera::LoadingStatus: + // Start when loaded (setting state handles this) + break; + case QCamera::StartingStatus: + // Discard, already moving to ActiveStatus + return; + case QCamera::LoadedStatus: + // Start + startCamera(); + break; + case QCamera::ActiveStatus: + // Do nothing + break; + + default: + // Unregocnized internal state (Status) + setError(KErrGeneral, tr("Unexpected camera error.")); + return; + } + break; + + default: + setError(KErrNotSupported, tr("Requested state is not supported.")); + return; + } +} + +QCamera::State S60CameraControl::state() const +{ + return m_requestedState; +} + +QCamera::Status S60CameraControl::status() const +{ + return m_internalState; +} + +QCamera::CaptureMode S60CameraControl::captureMode() const +{ + return m_captureMode; +} + +void S60CameraControl::setCaptureMode(QCamera::CaptureMode mode) +{ + if (m_error) { // Most probably failure in contructor + setError(m_error, tr("Unexpected camera error.")); + return; + } + + if (m_captureMode == mode) + return; + + // Setting CaptureMode Internally or Externally (Client) + if (!m_settingCaptureModeInternally) { + // Save the requested mode + m_requestedCaptureMode = mode; + + // CaptureMode change pending (backend busy), wait + if (m_changeCaptureModeWhenReady) + return; + } else { + m_changeCaptureModeWhenReady = false; // Reset + } + m_settingCaptureModeInternally = false; // Reset + + if (!isCaptureModeSupported(mode)) { + setError(KErrNotSupported, tr("Requested capture mode is not supported.")); + return; + } + + if (m_inactivityTimer->isActive()) + m_inactivityTimer->stop(); + + switch (m_internalState) { + case QCamera::UnloadedStatus: + case QCamera::LoadedStatus: + case QCamera::StandbyStatus: + switch (mode) { + case QCamera::CaptureStillImage: + m_videoSession->releaseVideoRecording(); + m_captureMode = QCamera::CaptureStillImage; + if (m_internalState == QCamera::LoadedStatus) + m_inactivityTimer->start(KInactivityTimerTimeout); + else if (m_internalState == QCamera::StandbyStatus) + loadCamera(); + break; + case QCamera::CaptureVideo: + m_imageSession->releaseImageCapture(); + m_captureMode = QCamera::CaptureVideo; + if (m_internalState == QCamera::LoadedStatus) { + // Revet InternalState as we need to wait for the video + // side initialization to complete + m_internalState = QCamera::LoadingStatus; + emit statusChanged(m_internalState); + int prepareSuccess = m_videoSession->initializeVideoRecording(); + setError(prepareSuccess, tr("Loading video capture failed.")); + } else if (m_internalState == QCamera::StandbyStatus) + loadCamera(); + break; + } + break; + case QCamera::LoadingStatus: + case QCamera::StartingStatus: + m_changeCaptureModeWhenReady = true; + return; + case QCamera::ActiveStatus: + // Stop, Change Mode and Start again + stopCamera(); + switch (mode) { + case QCamera::CaptureStillImage: + m_videoSession->releaseVideoRecording(); + m_captureMode = QCamera::CaptureStillImage; + startCamera(); + break; + case QCamera::CaptureVideo: + m_imageSession->releaseImageCapture(); + m_captureMode = QCamera::CaptureVideo; + // Revet InternalState as we need to wait for the video + // side initialization to complete + m_internalState = QCamera::LoadingStatus; + emit statusChanged(m_internalState); + int prepareSuccess = m_videoSession->initializeVideoRecording(); + setError(prepareSuccess, tr("Loading video recorder failed.")); + break; + } + break; + + default: + // Unregocnized internal state (Status) + setError(KErrNotSupported, tr("Requested capture mode is not supported.")); + break; + } + + emit captureModeChanged(mode); +} + +bool S60CameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const +{ + switch (mode) { + case QCamera::CaptureStillImage: + return true; + case QCamera::CaptureVideo: + return true; + + default: + return false; + } +} + +bool S60CameraControl::canChangeProperty(QCameraControl::PropertyChangeType changeType, QCamera::Status status) const +{ + Q_UNUSED(status); + + bool returnValue = false; + + switch (changeType) { + case QCameraControl::CaptureMode: + case QCameraControl::VideoEncodingSettings: + case QCameraControl::ImageEncodingSettings: + returnValue = true; + break; + + case QCameraControl::Viewfinder: + returnValue = false; + break; + + default: + // Safer to revert state before the unknown operation + returnValue = false; + break; + } + + return returnValue; +} + +void S60CameraControl::setVideoOutput(QObject *output, + S60CameraViewfinderEngine::ViewfinderOutputType type) +{ + if (!m_viewfinderEngine) { + setError(KErrGeneral, tr("Failed to set viewfinder")); + return; + } + + switch (type) { + case S60CameraViewfinderEngine::OutputTypeVideoWidget: + m_viewfinderEngine->setVideoWidgetControl(output); + break; + case S60CameraViewfinderEngine::OutputTypeRenderer: + m_viewfinderEngine->setVideoRendererControl(output); + break; + case S60CameraViewfinderEngine::OutputTypeVideoWindow: + m_viewfinderEngine->setVideoWindowControl(output); + break; + + default: + break; + } +} + +void S60CameraControl::releaseVideoOutput(const S60CameraViewfinderEngine::ViewfinderOutputType type) +{ + m_viewfinderEngine->releaseControl(type); +} + +void S60CameraControl::loadCamera() +{ + if (m_internalState < QCamera::LoadingStatus) { + m_internalState = QCamera::LoadingStatus; + emit statusChanged(m_internalState); + } else if (m_internalState == QCamera::LoadedStatus + || m_internalState >= QCamera::StartingStatus) { + // Nothing to load (already loaded) + return; + } + // Status = Loading or Standby + + m_cameraEngine->ReserveAndPowerOn(); + + // Completion notified in MceoCameraReady() +} + +void S60CameraControl::unloadCamera() +{ + if (m_internalState > QCamera::LoadingStatus) { + m_internalState = QCamera::LoadingStatus; + emit statusChanged(m_internalState); + } else if (m_internalState < QCamera::LoadingStatus) { + // Nothing to unload + return; + } + // Status = Loading + + if (m_inactivityTimer->isActive()) + m_inactivityTimer->stop(); + + m_cameraEngine->ReleaseAndPowerOff(); + + m_internalState = QCamera::UnloadedStatus; + emit statusChanged(m_internalState); +} + +void S60CameraControl::startCamera() +{ + if (m_internalState < QCamera::StartingStatus) { + m_internalState = QCamera::StartingStatus; + emit statusChanged(m_internalState); + } else if (m_internalState > QCamera::StartingStatus) { + // Nothing to start (already started) + return; + } + // Status = Starting + + if (m_inactivityTimer->isActive()) + m_inactivityTimer->stop(); + + if (m_viewfinderEngine) + m_viewfinderEngine->startViewfinder(); + else + setError(KErrGeneral, tr("Failed to start viewfinder.")); + + m_internalState = QCamera::ActiveStatus; + emit statusChanged(m_internalState); + + emit cameraReadyChanged(true); + +#ifdef Q_CC_NOKIAX86 // Emulator + MceoCameraReady(); // Signal that we are ready +#endif +} + +void S60CameraControl::stopCamera() +{ + if (m_internalState > QCamera::StartingStatus) { + m_internalState = QCamera::StartingStatus; + emit statusChanged(m_internalState); + } else if (m_internalState < QCamera::StartingStatus) { + // Nothing to stop + return; + } + // Status = Starting + + // Cancel ongoing operations if any + m_imageSession->cancelCapture(); + m_videoSession->stopRecording(); + + emit cameraReadyChanged(false); + if (m_viewfinderEngine) + m_viewfinderEngine->stopViewfinder(); + else + setError(KErrGeneral, tr("Failed to stop viewfinder.")); + + m_internalState = QCamera::LoadedStatus; + emit statusChanged(m_internalState); + + m_inactivityTimer->start(KInactivityTimerTimeout); +} + +void S60CameraControl::videoStateChanged(const S60VideoCaptureSession::TVideoCaptureState state) +{ + // Save video state + m_videoCaptureState = state; + + if (m_rotateCameraWhenReady) { + if (m_videoCaptureState != S60VideoCaptureSession::ERecording && + m_videoCaptureState != S60VideoCaptureSession::EPaused) + resetCameraOrientation(); + } + + // If video recording was stopped, video state reverts back to + // Initializing. In that case revert also Camera status to notify that + // video initialization needs to be completed. + if (state == S60VideoCaptureSession::EInitializing) { + if (m_internalState > QCamera::LoadingStatus) { + m_internalState = QCamera::LoadingStatus; + emit statusChanged(m_internalState); + } + + // Handle video initialization completion + } else if (state == S60VideoCaptureSession::EInitialized) { + + // Make sure state is not downgraded + if (m_internalState == QCamera::LoadedStatus + || m_internalState == QCamera::ActiveStatus) { + // Do nothing (already in target state) + } else if (m_internalState == QCamera::StartingStatus) { + m_internalState = QCamera::ActiveStatus; + emit statusChanged(m_internalState); + } else { + m_internalState = QCamera::LoadedStatus; + emit statusChanged(m_internalState); + } + + switch (m_requestedState) { + case QCamera::UnloadedState: + stopCamera(); + unloadCamera(); + if (m_changeCaptureModeWhenReady) { + m_settingCaptureModeInternally = true; + setCaptureMode(m_requestedCaptureMode); + } + break; + case QCamera::LoadedState: + stopCamera(); + if (m_changeCaptureModeWhenReady) { + m_settingCaptureModeInternally = true; + setCaptureMode(m_requestedCaptureMode); + } + m_inactivityTimer->start(KInactivityTimerTimeout); + break; + case QCamera::ActiveState: + if (m_changeCaptureModeWhenReady) { + m_settingCaptureModeInternally = true; + setCaptureMode(m_requestedCaptureMode); + } + startCamera(); + break; + + default: + setError(KErrGeneral, tr("Unexpected camera error.")); + return; + } + } +} + +void S60CameraControl::imageCaptured(const int imageId, const QImage& preview) +{ + Q_UNUSED(imageId); + Q_UNUSED(preview); + + // Unsubscribe the readyForCaptureChanged notification + disconnect(m_imageSession, SIGNAL(imageCaptured(const int, const QImage&)), + this, SLOT(imageCaptured(const int, const QImage&))); + + if (m_rotateCameraWhenReady) + resetCameraOrientation(); +} + +void S60CameraControl::advancedSettingsCreated() +{ + m_advancedSettings = m_imageSession->advancedSettings(); + + if (m_advancedSettings) + connect(m_advancedSettings, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int, const QString&))); +} + +void S60CameraControl::MceoCameraReady() +{ + // Rotate camera if requested + if (m_rotateCameraWhenReady) { + resetCameraOrientation(); + return; + } + + if (m_internalState != QCamera::LoadedStatus) { + + switch (m_requestedState) { + case QCamera::UnloadedState: + m_internalState = QCamera::LoadedStatus; + emit statusChanged(QCamera::LoadedStatus); + + stopCamera(); + unloadCamera(); + + if (m_changeCaptureModeWhenReady) { + m_settingCaptureModeInternally = true; + setCaptureMode(m_requestedCaptureMode); + } + break; + + case QCamera::LoadedState: + if (m_captureMode == QCamera::CaptureVideo) { + int prepareSuccess = m_videoSession->initializeVideoRecording(); + setError(prepareSuccess, tr("Loading video capture failed.")); + + // State change signalled when reservation is complete (in videoStateChanged()) + return; + } + m_internalState = QCamera::LoadedStatus; + emit statusChanged(QCamera::LoadedStatus); + + if (m_changeCaptureModeWhenReady) { + setCaptureMode(m_requestedCaptureMode); + m_changeCaptureModeWhenReady = false; // Reset + } + + if (m_requestedState == QCamera::LoadedStatus && + m_internalState == QCamera::LoadedStatus) + m_inactivityTimer->start(KInactivityTimerTimeout); + break; + + case QCamera::ActiveState: + if (m_captureMode == QCamera::CaptureVideo) { + int prepareSuccess = m_videoSession->initializeVideoRecording(); + setError(prepareSuccess, tr("Loading video capture failed.")); + + // State change signalled when reservation is complete (in videoStateChanged()) + return; + } + + m_internalState = QCamera::LoadedStatus; + emit statusChanged(QCamera::LoadedStatus); + + if (m_changeCaptureModeWhenReady) { + setCaptureMode(m_requestedCaptureMode); + m_changeCaptureModeWhenReady = false; // Reset + } + startCamera(); + break; + + default: + setError(KErrGeneral, tr("Unexpected camera error.")); + return; + } + } +} + +void S60CameraControl::MceoHandleError(TCameraEngineError aErrorType, TInt aError) +{ + Q_UNUSED(aErrorType); + + if (aError == KErrAccessDenied) { + setError(KErrGeneral, tr("Access to camera device was rejected.")); + } else if (aError == KErrHardwareNotAvailable) { + setError(aError, tr("Camera resources were lost.")); + toStandByStatus(); + } + else + setError(aError, tr("Unexpected camera error.")); +} + +void S60CameraControl::setError(const TInt error, const QString &description) +{ + if (error == KErrNone) + return; + + m_error = error; + QCamera::Error cameraError = fromSymbianErrorToQtMultimediaError(m_error); + + emit this->error(int(cameraError), description); + + // Reset everything, if other than not supported error or resource loss + if (error != KErrNotSupported && error != KErrHardwareNotAvailable) + resetCamera(true); // Try to recover from error + else + m_error = KErrNone; // Reset error +} + +QCamera::Error S60CameraControl::fromSymbianErrorToQtMultimediaError(int aError) +{ + switch(aError) { + case KErrNone: + return QCamera::NoError; // No errors have occurred + + case KErrNotSupported: + return QCamera::NotSupportedFeatureError; // The feature is not supported + case KErrNotFound: + case KErrBadHandle: + return QCamera::ServiceMissingError; // No camera service available + case KErrArgument: + case KErrNotReady: + return QCamera::InvalidRequestError; // Invalid parameter or state + + default: + return QCamera::CameraError; // An error has occurred (i.e. General Error) + } +} + +// For S60CameraVideoDeviceControl +int S60CameraControl::deviceCount() +{ +#ifdef Q_CC_NOKIAX86 // Emulator + return 1; +#endif + + return CCameraEngine::CamerasAvailable(); +} + +int S60CameraControl::defaultDevice() const +{ + return KDefaultCameraDevice; +} + +int S60CameraControl::selectedDevice() const +{ + return m_deviceIndex; +} + +void S60CameraControl::setSelectedDevice(const int index) +{ + if (m_deviceIndex != index) { + if (index >= 0 && index < deviceCount()) { + m_deviceIndex = index; + resetCamera(); + } else { + setError(KErrNotSupported, tr("Requested camera is not available.")); + } + } +} + +QString S60CameraControl::name(const int index) +{ + QString cameraName; + switch (index) { + case 0: + cameraName = tr("Primary camera"); + break; + case 1: + cameraName = tr("Secondary camera"); + break; + case 2: + cameraName = tr("Tertiary camera"); + break; + + default: + cameraName = tr("Unidentified Camera"); + break; + } + + return cameraName; +} + +QString S60CameraControl::description(const int index) +{ + QString cameraDesc; + switch (index) { + case 0: + cameraDesc = tr("Device primary camera"); + break; + case 1: + cameraDesc = tr("Device secondary camera"); + break; + case 2: + cameraDesc = tr("Device tertiary camera"); + break; + + default: + cameraDesc = tr("Unidentified Camera"); + break; + } + + return cameraDesc; +} + +void S60CameraControl::resetCamera(bool errorHandling) +{ + if (m_inactivityTimer->isActive()) + m_inactivityTimer->stop(); + + // Cancel ongoing activity + m_imageSession->cancelCapture(); + m_videoSession->stopRecording(false); // Don't re-initialize video + + // Advanced settings must be destructed before the camera + m_imageSession->deleteAdvancedSettings(); + + // Release resources + stopCamera(); + unloadCamera(); + + disconnect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&))); + if (m_viewfinderEngine) { + delete m_viewfinderEngine; + m_viewfinderEngine = 0; + } + + if (m_cameraEngine) { + delete m_cameraEngine; + m_cameraEngine = 0; + } + + TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, 0, this)); + if (err) { + m_cameraEngine = 0; + if (errorHandling) { + qWarning("Failed to recover from error."); + if (err == KErrPermissionDenied) + emit error(int(QCamera::ServiceMissingError), tr("Recovering from error failed. Possibly missing capabilities.")); + else + emit error(int(QCamera::CameraError), tr("Recovering from error failed.")); + } else { + if (err == KErrPermissionDenied) + setError(err, tr("Camera device creation failed. Possibly missing capabilities.")); + else + setError(err, tr("Camera device creation failed.")); + } + return; + } + + // Notify list of available camera devices has been updated + emit devicesChanged(); + + m_viewfinderEngine = new S60CameraViewfinderEngine(this, m_cameraEngine, this); + if (m_viewfinderEngine == 0) + setError(KErrNoMemory, tr("Viewfinder device creation failed.")); + connect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&))); + + setCameraHandles(); + + // Reset state + //setState(QCamera::UnloadedState); + if (m_internalState != QCamera::UnloadedStatus) { + m_internalState = QCamera::UnloadedStatus; + emit statusChanged(m_internalState); + } + if (m_requestedState != QCamera::UnloadedState) { + m_requestedState = QCamera::UnloadedState; + emit stateChanged(m_requestedState); + } + + // Reset error + m_error = KErrNone; +} + +/* + * Reset everything else than viewfinder engine and errors. + */ +void S60CameraControl::resetCameraOrientation() +{ + // If camera has not been created, it will be created automatically to correct orientation + if (!m_cameraEngine) + return; + + // Check Image/VideoCapture allow rotation + if ((!m_cameraEngine->IsCameraReady() && m_internalState != QCamera::UnloadedStatus) || + m_videoCaptureState == S60VideoCaptureSession::ERecording || + m_videoCaptureState == S60VideoCaptureSession::EPaused) { + + // If image capture is ongoing, request notification about the + // completion (imageCaptured() is used because that comes asynchronously + // after the image is captured) + // Obs! If preview creation is changed to be synchnonously done during + // the image capture this implementation needs to be changed) + if (m_videoCaptureState != S60VideoCaptureSession::ERecording && + m_videoCaptureState != S60VideoCaptureSession::EPaused && + m_internalState == QCamera::ActiveStatus) + connect(m_imageSession, SIGNAL(imageCaptured(const int, const QImage&)), + this, SLOT(imageCaptured(const int, const QImage&))); + + m_rotateCameraWhenReady = true; + return; + } + + m_rotateCameraWhenReady = false; // Reset + + QCamera::State originalState = m_requestedState; + + // Cancel ongoing activity + m_imageSession->cancelCapture(); + m_videoSession->stopRecording(false); // Don't re-initialize video + + // Advanced settings must be destructed before the camera + m_imageSession->deleteAdvancedSettings(); + + // Release resources + stopCamera(); + unloadCamera(); + + // Unset CameraEngine to ViewfinderEngine + m_viewfinderEngine->setNewCameraEngine(0); + if (m_cameraEngine) { + delete m_cameraEngine; + m_cameraEngine = 0; + } + + TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, 0, this)); + if (err) { + setError(err, tr("Camera device creation failed.")); + return; + } + // Reset CameraEngine to ViewfinderEngine + m_viewfinderEngine->setNewCameraEngine(m_cameraEngine); + + // Notify list of available camera devices has been updated + emit devicesChanged(); + + setCameraHandles(); + + // Reset state + if (m_internalState != QCamera::UnloadedStatus) { + m_internalState = QCamera::UnloadedStatus; + emit statusChanged(m_internalState); + } + if (m_requestedState != QCamera::UnloadedState) { + m_requestedState = QCamera::UnloadedState; + emit stateChanged(m_requestedState); + } + + setState(originalState); +} + +void S60CameraControl::setCameraHandles() +{ + m_imageSession->setCurrentDevice(m_deviceIndex); + m_imageSession->setCameraHandle(m_cameraEngine); + m_cameraEngine->SetImageCaptureObserver(m_imageSession); + m_videoSession->setCameraHandle(m_cameraEngine); +} + +void S60CameraControl::toStandByStatus() +{ + // Cancel ongoing operations if any + m_imageSession->cancelCapture(); + m_videoSession->stopRecording(false); // Don't re-initialize video + + emit cameraReadyChanged(false); + if (m_viewfinderEngine) + m_viewfinderEngine->stopViewfinder(); + else + setError(KErrGeneral, tr("Failed to stop viewfinder.")); + + m_cameraEngine->ReleaseAndPowerOff(); + + m_internalState = QCamera::StandbyStatus; + emit statusChanged(m_internalState); +} + +// End of file |