/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <w32std.h> // RWindow, RWsSession.
#include <coemain.h> // CCoeEnv
#include <coecntrl.h>
#include <ecam/ecamdirectviewfinder.h>
#include "cxutils.h"
#include "cxecameradevicecontrolsymbian.h" // CxeCameraDevice
#include "cxeviewfindercontrolsymbian.h"
#include "cxesettings.h"
#include "cxesettingsmappersymbian.h"
#include "cxeerrormappingsymbian.h"
#include "cxestate.h"
#include "cxevideocontainer.h"
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "cxeviewfindercontrolsymbianTraces.h"
#endif
/**
* CxeViewfinderControlSymbian::CxeViewfinderControlSymbian
*/
CxeViewfinderControlSymbian::CxeViewfinderControlSymbian( CxeCameraDevice &cameraDevice,
CxeCameraDeviceControl &cameraDeviceControl )
: CxeStateMachine("CxeViewfinderControlSymbian"),
mCameraDevice( cameraDevice ),
mCameraDeviceControl( cameraDeviceControl ),
mUiWindow(NULL),
mVideoWindow(NULL),
mVideoContainer(NULL),
mDirectViewfinder( NULL ),
mDirectViewfinderInUse( true )
{
CX_DEBUG_ENTER_FUNCTION();
qRegisterMetaType<CxeViewfinderControlSymbian::State>();
initializeStates();
// connect signals from cameraDevice, so we recieve events when camera reference changes
connect(&mCameraDevice, SIGNAL(prepareForCameraDelete()),
this,SLOT(prepareForCameraDelete()));
connect(&mCameraDevice, SIGNAL(prepareForRelease()),
this,SLOT(prepareForRelease()));
connect(&mCameraDevice, SIGNAL(cameraAllocated(CxeError::Id)),
this,SLOT(handleCameraAllocated(CxeError::Id)));
CX_DEBUG_EXIT_FUNCTION();
}
/**
* CxeViewfinderControlSymbian::~CxeViewfinderControlSymbian()
*/
CxeViewfinderControlSymbian::~CxeViewfinderControlSymbian()
{
CX_DEBUG_ENTER_FUNCTION();
// do something
stop(); // stop the vf
releaseCurrentViewfinder(); // release resoruces
delete mVideoContainer;
mUiWindow = NULL;
mVideoWindow = NULL;
CX_DEBUG_EXIT_FUNCTION();
}
/**
* CxeViewfinderControlSymbian::setWindow
*/
void CxeViewfinderControlSymbian::setWindow(WId windowId)
{
CX_DEBUG_ENTER_FUNCTION();
mUiWindow = static_cast<CCoeControl*>(windowId)->DrawableWindow();
CX_DEBUG(("mUiWindow is 0x%08x", mUiWindow));
TSize windowSize = mUiWindow->Size();
CX_DEBUG(("mUiWindow size %dx%d", windowSize.iWidth, windowSize.iHeight));
// Set the window rect
TPoint point = TPoint(0,0);
mWindowRect = TRect(point, windowSize);
CX_DEBUG(("CxeViewfinderControlSymbian::setWindow() mWindowRect iTl=(%d, %d) iBr=(%d, %d)",
mWindowRect.iTl.iX, mWindowRect.iTl.iY, mWindowRect.iBr.iX, mWindowRect.iBr.iY));
CX_DEBUG_EXIT_FUNCTION();
}
/*!
* Returns Device's Display resolution
*/
QSize CxeViewfinderControlSymbian::deviceDisplayResolution() const
{
TSize windowSize(640, 360); // magic: default size if mUiWindow is NULL
if (mUiWindow) {
windowSize = mUiWindow->Size();
}
QSize displaySize = QSize(windowSize.iWidth, windowSize.iHeight);
if (displaySize.height() > displaySize.width()) {
// Window server orientation might differ from the Orbit UI orientation.
// Swap width and height if needed.
displaySize.transpose();
}
CX_DEBUG(("deviceDisplayResolution returning %dx%d", displaySize.width(),
displaySize.height()));
return displaySize;
}
/**
* Stop viewfinder
*/
void CxeViewfinderControlSymbian::stop()
{
CX_DEBUG_ENTER_FUNCTION();
if (state() == Running) {
CX_DEBUG_ASSERT( mCameraDevice.camera() );
CX_DEBUG( ( "Viewfinder is running stopping it" ) );
mCameraDevice.camera()->StopViewFinder();
setState( Ready );
}
CX_DEBUG_EXIT_FUNCTION();
}
/**!
* Start the viewfinder
*/
CxeError::Id CxeViewfinderControlSymbian::start()
{
CX_DEBUG_ENTER_FUNCTION();
TInt err = KErrNone;
if ( state() == Running ) {
OstTrace0( camerax_performance, CXEVIEWFINDERCONTROLSYMBIAN_START, "msg: e_CX_GO_TO_VIDEO_MODE 0" );
CX_DEBUG( ( "Viewfinder already running - ignored start()" ) );
CX_DEBUG_EXIT_FUNCTION();
return CxeError::None;
}
if (!mVideoWindow) {
TRAP(err, createViewfinderWindowL());
if (err != KErrNone) {
CX_DEBUG_EXIT_FUNCTION();
return CxeErrorHandlingSymbian::map(err);
}
}
if (state() == Uninitialized) {
err = initViewfinder();
}
// apply any settings here
if ( mDirectViewfinderInUse && !err && mDirectViewfinder && state() == Ready ) {
// for now only direct vf
switch( mDirectViewfinder->ViewFinderState() ) {
case CCamera::CCameraDirectViewFinder::EViewFinderInActive:
{
CX_DEBUG(("Calling StartViewFinderDirectL"));
// Make UI surface transparent so viewfinder is visible
if (mUiWindow) {
mUiWindow->SetSurfaceTransparency(ETrue);
}
// A local copy of the viewfinder coordinates (in WServ
// coordinates). Needed because calling StartViewFinderDirectL()
// will modify the rectangle and we don't want mWindowRect to be
// modified.
TRect activeViewfinderRect = mWindowRect;
CX_DEBUG(("activeViewfinderRect iTl=(%d, %d) iBr=(%d, %d)",
activeViewfinderRect.iTl.iX, activeViewfinderRect.iTl.iY,
activeViewfinderRect.iBr.iX, activeViewfinderRect.iBr.iY));
TRAP(err, mCameraDevice.camera()->StartViewFinderDirectL(
CCoeEnv::Static()->WsSession(),
*CCoeEnv::Static()->ScreenDevice(),
*mVideoWindow, activeViewfinderRect));
OstTrace0(camerax_performance, DUP1_CXEVIEWFINDERCONTROLSYMBIAN_START, "msg: e_CX_STARTUP 0");
setState(Running);
break;
}
case CCamera::CCameraDirectViewFinder::EViewFinderPause:
TRAP( err, mDirectViewfinder->ResumeViewFinderDirectL() );
if (!err) {
setState( Running );
}
break;
case CCamera::CCameraDirectViewFinder::EViewFinderActive:
// Already running. Not considered as error.
setState( Running );
break;
default:
err = KErrNotSupported;
}
}
else if ( !mDirectViewfinder ) {
// Start bmp vf
//TSize size(320, 240);
TSize size(mWindowRect.Width(), mWindowRect.Height());
CX_DEBUG(("Starting bitmap vf with size %d x %d", size.iWidth, size.iHeight));
TRAP( err, mCameraDevice.camera()->StartViewFinderBitmapsL( size ) );
CX_DEBUG(("Bitmap viewfinder modified to size %d x %d", size.iWidth, size.iHeight));
if ( err ) {
CX_DEBUG( ("StartViewfinderBitmapsL - err:%d", err) );
}
else {
setState( Running );
TRAP( err, mCameraDevice.camera()->SetViewFinderMirrorL(true) );
}
}
else {
// vf already running. nothing to do
}
CX_DEBUG( ("CxeViewfinderControlSymbian::start symbian error code : %d", err ) );
CX_DEBUG_EXIT_FUNCTION();
return CxeErrorHandlingSymbian::map(err);
}
/**
* Intialize the viewfinder based on the VF mode
*/
int CxeViewfinderControlSymbian::initViewfinder()
{
CX_DEBUG_ENTER_FUNCTION();
TInt err = KErrNone;
if (state() != Uninitialized) {
return err;
}
// For now only direct vf. If there is any need for supporting other VF modes, condition checks
// and handling of new states are needed here.
// release first, the prev/current view finder instance.
releaseCurrentViewfinder();
mDirectViewfinderInUse = true;
/*
if ( mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex ) {
mDirectViewfinderInUse = true;
}
else {
mDirectViewfinderInUse = false;
}*/
if ( mDirectViewfinderInUse ) {
// creating an new instance of vf
TRAP( err, mDirectViewfinder = CCamera::CCameraDirectViewFinder::NewL( *mCameraDevice.camera() ) );
}
if ( !err ) {
setState( Ready );
}
else {
CX_DEBUG( ("error: %d", err ) );
}
#if defined(CXE_USE_DUMMY_CAMERA) || defined(__WINSCW__)
//! @todo Temporary code for WINSCW, because CCamera::CCameraDirectViewFinder is not yet supported by dummy engine
setState( Ready );
#endif
CX_DEBUG_EXIT_FUNCTION();
return err;
}
/**
* Create the window for viewfinder to render into.
*/
void CxeViewfinderControlSymbian::createViewfinderWindowL()
{
CX_DEBUG_ENTER_FUNCTION();
if (!mUiWindow) {
CX_DEBUG( ( "mUiWindow not set - cannot create VF window!" ) );
User::Leave(KErrNotReady);
}
// Make UI surface transparent so viewfinder is visible
if (mUiWindow) {
mUiWindow->SetSurfaceTransparency(ETrue);
}
delete mVideoContainer;
mVideoContainer = NULL;
mVideoContainer = new (ELeave) CxeVideoContainer();
mVideoContainer->ConstructL();
CX_DEBUG(("Viewfinder container created ok"));
mVideoContainer->SetRect(mWindowRect);
mVideoWindow = mVideoContainer->DrawableWindow();
CX_DEBUG(("mVideoWindow is 0x%08x", mVideoWindow));
CX_DEBUG(("mUiWindow ordinal position is: %d", mUiWindow->OrdinalPosition()));
// Make sure UI window is on top of viewfinder
CX_DEBUG(("Set viewfinder window ordinal.."));
mVideoWindow->SetOrdinalPosition(-1);
mUiWindow->SetOrdinalPosition(0);
CX_DEBUG(("mVideoWindow ordinal position is: %d", mVideoWindow->OrdinalPosition()));
CX_DEBUG(("mUiWindow ordinal position is: %d", mUiWindow->OrdinalPosition()));
CX_DEBUG_EXIT_FUNCTION();
}
void CxeViewfinderControlSymbian::prepareForRelease()
{
CX_DEBUG_ENTER_FUNCTION();
stop();
CX_DEBUG_EXIT_FUNCTION();
}
/**
* Release Vf resources
*/
void CxeViewfinderControlSymbian::releaseCurrentViewfinder()
{
CX_DEBUG_ENTER_FUNCTION();
delete mDirectViewfinder;
mDirectViewfinder = NULL;
setState( Uninitialized );
CX_DEBUG_EXIT_FUNCTION();
}
/**
* Ecam reference changing, release resources
*/
void CxeViewfinderControlSymbian::prepareForCameraDelete()
{
CX_DEBUG_ENTER_FUNCTION();
stop(); // first stop the viewfinder
releaseCurrentViewfinder();
CX_DEBUG_EXIT_FUNCTION();
}
/**
* Handle new camera instance.
*/
void CxeViewfinderControlSymbian::handleCameraAllocated(CxeError::Id error)
{
CX_DEBUG_ENTER_FUNCTION();
if (!error) {
initViewfinder();
}
CX_DEBUG_EXIT_FUNCTION();
}
CxeViewfinderControl::State CxeViewfinderControlSymbian::state() const
{
return static_cast<State>( stateId() );
}
void CxeViewfinderControlSymbian::handleStateChanged( int newStateId, CxeError::Id error )
{
emit stateChanged( static_cast<State>( newStateId ), error );
}
void CxeViewfinderControlSymbian::initializeStates()
{
// addState( id, name, allowed next states )
addState( new CxeState( Uninitialized , "Uninitialized", Ready ) );
addState( new CxeState( Ready , "Ready", Uninitialized | Running ) );
addState( new CxeState( Running , "Running", Uninitialized | Ready ) );
setInitialState( Uninitialized );
}
void CxeViewfinderControlSymbian::handleVfFrame(MCameraBuffer* /*buffer*/, int /*error*/)
{
CX_DEBUG_IN_FUNCTION();
CX_DEBUG( ( "Bitmap viewfinder not supported" ) );
CX_ASSERT_ALWAYS(false);
}
// end of file