videoview.cpp
来自「《UIQ 3 The Complete Guide》书的源代码」· C++ 代码 · 共 347 行
CPP
347 行
//
// VideoView.cpp - Video playback
//
// Copyright (C) UIQ Technology AB, 2007
//
// This material is provided "as is" without any warranty to its performance or functionality.
// In no event shall UIQ Technology be liable for any damages whatsoever arising out of the
// use or inabilty to use this material.
//
#include "VideoView.h"
#include "SignedAppUids.h"
#include "SignedApp.hrh"
#include <SignedApp_0x20000462.rsg>
#include <QikCommand.h>
// Despite the CVideoPlayerUtility having a set of enums + presumably tracking its internal
// state via TMMFVideoPlayerState, these are i) private and ii) inaccessible... so
// we have to duplicate something equivalent in our control.
enum TVideoDisplayState
{
EVidDispStateClosed,
EVidDispStateGetFrame,
EVidDispStateIdle,
EVidDispStatePlaying,
};
class CVideoDisplayControl : public CCoeControl,
public MVideoPlayerUtilityObserver
{
protected:
// from MVideoPlayerUtilityObserver
void MvpuoOpenComplete(TInt aError);
void MvpuoPrepareComplete(TInt aError);
void MvpuoFrameReady(CFbsBitmap& aFrame,TInt aError);
void MvpuoPlayComplete(TInt aError);
void MvpuoEvent(const TMMFEvent& aEvent);
// from CCoeControl
void Draw(const TRect& aRect) const;
public:
// new methods
~CVideoDisplayControl();
CVideoDisplayControl(CAppEngine* aEngine);
void ConstructL();
void NewVideoSelectedL();
void CloseVideo();
void PlayL();
protected:
CAppEngine* iEngine;
CVideoPlayerUtility* iVideoPlayer;
CFbsBitmap* iBitmap;
TVideoDisplayState iState;
};
CVideoDisplayControl::~CVideoDisplayControl()
// We no longer want to use the image.. free up those resources
{
CloseVideo();
}
CVideoDisplayControl::CVideoDisplayControl(CAppEngine* aEngine) :
iEngine(aEngine)
{}
void CVideoDisplayControl::Draw(const TRect& aRect) const
{
if (iBitmap && iState==EVidDispStateIdle)
{ // weve got a frame from the video + not currently replaying it..
CGraphicsContext& gc=SystemGc();
gc.SetDrawMode(CGraphicsContext::EDrawModePEN);
// Draw as much of the bitmap as will fit in the space we have been allocated. This
// particular implementation simply crops the image if its too big.
TRect rect(Rect());
TRect r2(0,0,rect.Width(),rect.Height());
TSize size(iBitmap->SizeInPixels());
if (size.iWidth<r2.iBr.iX)
{
r2.iBr.iX=size.iWidth;
rect.iBr.iX=rect.iTl.iX+size.iWidth;
}
if (size.iHeight<r2.iBr.iY)
{
r2.iBr.iY=size.iHeight;
rect.iBr.iY=rect.iTl.iY+size.iWidth;
}
gc.DrawBitmap(rect,iBitmap,r2);
}
}
void CVideoDisplayControl::MvpuoOpenComplete(TInt aError)
//
// The clip has been opened, however cant do anything useful until its been prepared. So
// not very clear why we need this intermediate state...
//
{
if (aError==KErrNone)
iVideoPlayer->Prepare(); // eventually calls MvpuoPrepareComplete()
else
{
iEikonEnv->BusyMsgCancel();
TBuf<128>bb;
iEikonEnv->Format128(bb,R_STR_OPEN_ERROR,aError);
iEikonEnv->InfoMsg(bb);
CloseVideo();
}
}
void CVideoDisplayControl::MvpuoPrepareComplete(TInt aError)
//
// Called back by the system code when the iVideoPlayer->Prepare() completes
//
{
iEikonEnv->BusyMsgCancel(); // the 'Loading...' busy msg
if (aError==KErrNone)
{
TRAP(aError,
iVideoPlayer->SetPositionL(0);
// iEikonEnv->ScreenDevice()->DisplayMode() generates a KErrArgument in callback
// whereas EColor64K seems to work...
iVideoPlayer->GetFrameL(EColor64K); // calls back MvpuoFrameReady()
iState=EVidDispStateGetFrame;
);
}
if (aError!=KErrNone)
{
TBuf<128>bb;
iEikonEnv->Format128(bb,R_STR_PREPARE_ERROR,aError);
iEikonEnv->InfoMsg(bb);
CloseVideo();
}
}
void CVideoDisplayControl::MvpuoPlayComplete(TInt aError)
//
// Called back by the framework when iVideoPlayer->Play() completes
// EXCEPT THAT IT ISNT ON M600 - another 'feature'.
// Works on P990, W950.
//
{
// we want to be able to replay.. so dont close the image down here
iState=EVidDispStateIdle;
DrawNow(); // restore the background frame
}
void CVideoDisplayControl::MvpuoFrameReady(CFbsBitmap& aFrame,TInt aError)
//
// Called back by the framework when iVideoPlayer->GetFrameL() completes
//
{
iState=EVidDispStateIdle; // irrespective of whether we managed to get a frame or not
if (aError==KErrNone)
{
iBitmap=(&aFrame); // doubt if we are supposed to take ownership...
DrawNow(); // update our display now we have a bmp. + in Idle state.
}
if (aError!=KErrNone)
{
TBuf<128>bb;
_LIT(KFrameErr,"FrameErr %d");
bb.Format(KFrameErr,aError);
iEikonEnv->InfoMsg(bb);
CloseVideo();
}
}
void CVideoDisplayControl::MvpuoEvent(const TMMFEvent& aEvent)
// Part of the Mixin i/f.
{
}
void CVideoDisplayControl::ConstructL()
{
}
void CVideoDisplayControl::CloseVideo()
{
if (iVideoPlayer)
{
iVideoPlayer->Stop();
iVideoPlayer->Close();
delete(iVideoPlayer);
iVideoPlayer=NULL;
}
iBitmap=NULL;
iState=EVidDispStateClosed;
}
void CVideoDisplayControl::PlayL()
//
// Start the video clip playback
//
{
/*
Whilst the following functionality, to cancel current playback and restart may superficially
appear a good thing to do, there is a bit of a features of P990s, whereby calling
Stop() then attempting to restart playback will cause the entire phone to reset !!.
Unfortunately such actions, irrespective of whether its in the system code or not, will cause
our app to fail Symbian Signed testing.
if (iState<EVidDispStateIdle)
User::Leave(KErrNotSupported);
if (iState==EVidDispStatePlaying)
{ // if were still playing previous clip, cancel so we can re-start
iVideoPlayer->Stop(); // calls back MvpuoPlayComplete()
}
_LIT(KVideoPlayL,"VideoPlayL");
__ASSERT_ALWAYS(iState==EVidDispStateIdle,User::Panic(KVideoPlayL,0));
Possibly have to Stop(), Close(), Re-Open(), Re-Prepare() on P990.
Perhaps a Pause() then SetPosition(0) would work....
The only sensible soln we can implement at this time is to block replay attempts until the
current clip has finished playing.
*/
if (iState!=EVidDispStateIdle)
User::Leave(KErrNotSupported);
iVideoPlayer->SetPositionL(0); // from the start
iVideoPlayer->Play();
iState=EVidDispStatePlaying;
DrawNow(); // remove the background Frame
}
void CVideoDisplayControl::NewVideoSelectedL()
//
// Open the entry currently selected in the list view
//
{
// lose any previous one
CloseVideo();
// the video playback uses direct screen access, hence we have to translate our
// content rectangle to be screen relative for playback to occur at the correct place.
TRect rect(Rect());
rect.Move(PositionRelativeToScreen());
iVideoPlayer=CVideoPlayerUtility::NewL(*this,EMdaPriorityNormal,EMdaPriorityPreferenceNone,
iEikonEnv->WsSession(),*iEikonEnv->ScreenDevice(),Window(),rect,rect);
TFileName name;
iEngine->EntryFullName(name);
TRAPD(err,
iVideoPlayer->OpenFileL(name); // calls back MvpuoOpenComplete()
iEikonEnv->BusyMsgL(R_STR_LOADING);
);
if (err!=KErrNone)
{
CloseVideo();
User::Leave(err);
}
}
//////////////////////////////////////////////////////////////////////////////////
CVideoPlaybackView::~CVideoPlaybackView()
{
}
CVideoPlaybackView::CVideoPlaybackView(CQikAppUi& aAppUi,CAppEngine* aEngine) :
CQikViewBase(aAppUi,KViewIdListView),iEngine(aEngine)
{}
TVwsViewId CVideoPlaybackView::ViewId() const
//
// All views are uniquely identified within the entire system. A TVwsViewId consists of
// the application uid (uid3) and app specific view uid
//
{
return(KViewIdVideoPlaybackView);
}
void CVideoPlaybackView::HandleCommandL(CQikCommand& aCommand)
//
// Handle the commands coming in from the controls that can deliver cmds..
//
{
switch (aCommand.Id())
{
case EAppCmdPlayVideo:
static_cast<CVideoDisplayControl *>(iContainer->Controls().At(0).iControl)->PlayL();
break;
default: // e.g. the back button...
CQikViewBase::HandleCommandL(aCommand);
break;
}
}
void CVideoPlaybackView::ViewConstructL()
{
// Loads information about the UI configurations this view supports
// together with definition of each view.
ViewConstructFromResourceL(R_VIDEO_PLAYBACK_VIEW_CONFIGURATIONS);
// A container type object is expected to exist. The layout manager - as defined in the
// resource will drive the container, e.g. will call its SetRect() method.
CQikContainer* container = new(ELeave)CQikContainer();
Controls().AppendLC(container);
container->ConstructL(ETrue);
container->SetRect(Rect());
CleanupStack::Pop(container);
iContainer=container;
// we have an video display control - is is responsible for displaying any image that
// has been loaded, handling commands etc.
CVideoDisplayControl *q=new(ELeave)CVideoDisplayControl(iEngine);
iContainer->AddControlLC(q);
q->ConstructL();
CleanupStack::Pop(q);
}
void CVideoPlaybackView::ViewDeactivated()
//
// The view is being de-activated.
//
{
CVideoDisplayControl *q=static_cast<CVideoDisplayControl *>(iContainer->Controls().At(0).iControl);
q->CloseVideo();
}
void CVideoPlaybackView::ViewActivatedL(
//
// The view is being activated.
//
const TVwsViewId& aPrevViewId,
const TUid aCustomMessageId,
const TDesC8& aCustomMessage)
{
// we only have a single control added to the container - so we can get at it like this
CVideoDisplayControl *q=static_cast<CVideoDisplayControl *>(iContainer->Controls().At(0).iControl);
q->SetRect(iContainer->Rect());
q->NewVideoSelectedL();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?