📄 pbc_engine.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2005-2006 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file pbc_engine.cpp
*
* Playback Control Engine core module.
* This module contains the playback control engine task.
* This API is intended to be private and used by other Playback
* Control Engine modules only.
*
* $Id: pbc_engine.cpp,v 1.96 2007/01/26 22:31:59 rbehe Exp $
*/
#include "vdvd_types.h"
#include "utility.h"
#include "pbc_engine.h"
#include "playctrl.h"
#include "pbc_types.h"
#include "pbc_pbscenario.h"
#include "pbc_avpres.h"
#include "pbc_ig.h"
#include "pbc_register.h"
#include "pbc_plcontrol.h"
#include "dr_app.h"
#include "pe_app.h"
#include "../mvplaylistdb.h"
#include "../sounddb.h"
#include "osapi.h"
#include "dbgprint.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
/* Debug macros */
#define DBG_PBCENGINE DBG_ERROR
#define DBG_ON(x) (DBG_PBCENGINE >= x)
/* Local constants */
#define PBCENGINE_MSG_QUEUE_DEPTH 20
/**
* PBC Engine Message
*/
typedef struct tagPBCENGINE_MESSAGE
{
PBCENGINE_MSGTYPE tMsgType;
PBC_HANDLE *hPbc;
ULONG ulData0;
ULONG ulData1;
ULONG ulData2;
ULONG ulData3;
ULONG ulSemID;
ULONG* pulRetVal;
} PBCENGINE_MESSAGE;
/**
* PBC Engine data
*/
typedef struct tagPBC_ENGINE
{
ULONG ulTaskId;
OS_MSG_Q_ID MsgQID;
OS_SEM_ID semMsgSynch;
OS_TIMER_ID NavTimer;
PBC_FUNC_PTR PbcFunc[PLAYCTRL_INVALID_COMMAND];
} PBC_ENGINE;
/**
* Local variables
*/
PBC_ENGINE *hPbcEngine = NULL;
/**
* Local functions
*/
static PLAYCTRL_STATUS PbcEngineMapPBCFunctions(void);
static DR_ERROR PbcEngineDRCallback(PVOID pContext, DR_EVENT_CODE event, PVOID pEventInfo);
static PE_STATUS PbcEnginePECallback(PVOID pContext, PE_EVENT_CODE event, PVOID pEventInfo);
static void PbcEngineNavTimerCallback(PVOID pvParam);
static PLAYCTRL_STATUS PbcEngineTimerUpdate(PBC_HANDLE *hPBC);
static PLAYCTRL_STATUS PbcEnginePlayButtonSound(PBC_HANDLE *hPBC, uint32 sound_id);
static ULONG PbcEngineTask(PVOID pvParam);
/**
* PbcEngineCreate -- Create the playback control engine task and message queue.
*
* @param
* hPBC -- handle to playback control engine private data
*
* @retval
* PLAYCTRL_STATUS
*/
PLAYCTRL_STATUS PbcEngineCreate(PBC_HANDLE *hPBC)
{
ULONG ulPEevents = 0;
if (hPBC == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: NULL handle!\n"));
return (PLAYCTRL_NULL_POINTER);
}
/* Attach DR event handler */
if (DRAttachEvent(hPBC->hDR, PbcEngineDRCallback, hPBC) != DR_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failed to attach DR events handler!\n"));
goto errout;
}
/* Set PE Events to register for */
ulPEevents = PE_EVENT_END_OF_STREAM | PE_EVENT_BEG_OF_STREAM | PE_EVENT_DISCONTINUITY |
PE_EVENT_ASYNC_PREFILL | PE_EVENT_VSYNC | PE_EVENT_ICS_VALID | PE_EVENT_ICS_INVALID |
PE_EVENT_SELECT_PAGE | PE_EVENT_SELECT_BUTTON | PE_EVENT_ACTIVATE_BUTTON | PE_EVENT_DECODE_DONE |
PE_EVENT_PROCESS_BOBJ | PE_EVENT_AM_LEVEL_CHG | PE_EVENT_AM_PANNING_CHG | PE_EVENT_AM_STOP_SOUND |
PE_EVENT_AM_CLOSE_SOUND | PE_EVENT_IDLE;
/* Attach the PE event handler */
if (PERegisterForEvents(hPBC->hPE, PbcEnginePECallback, ulPEevents, hPBC) != PE_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failed to register for PEiStrmCtrl Events!\n"));
goto errout;
}
/* Create pbc engine data handle */
hPbcEngine = (PBC_ENGINE *)OS_MemAlloc(sizeof(PBC_ENGINE) );
if (hPbcEngine == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating local handle!\n"));
goto errout;
}
/* intialize params */
hPbcEngine->ulTaskId = 0;
hPbcEngine->MsgQID = 0;
hPbcEngine->semMsgSynch = 0;
hPbcEngine->NavTimer = 0;
/* Map commands to playback control functions */
if (PbcEngineMapPBCFunctions() != PLAYCTRL_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure mapping functions!\n"));
goto errout;
}
/* Create semaphore used for synchronous message processing */
hPbcEngine->semMsgSynch = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_EMPTY);
if (hPbcEngine->semMsgSynch == 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating semaphore!\n"));
goto errout;
}
/* Create the pbc engine message queuee */
hPbcEngine->MsgQID = OS_MsgQCreate(PBCENGINE_MSG_QUEUE_DEPTH, sizeof(PBCENGINE_MESSAGE), OS_MSG_Q_FIFO);
if (hPbcEngine->MsgQID == 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating msg queue!\n"));
goto errout;
}
/* Create pbc engine task */
hPbcEngine->ulTaskId = OS_TaskSpawnParam("PbcEngineTask", OS_TASK_HIGH_PRIORITY, 4096, PbcEngineTask, NULL, NULL);
if (hPbcEngine->ulTaskId == (ULONG)OS_FAILURE)
{
hPbcEngine->ulTaskId = 0;
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure spawning task!\n"));
goto errout;
}
/* Create nav timer */
if (OS_TimerCreateParam(&hPbcEngine->NavTimer, (OS_FUNCPTR_PARAM)PbcEngineNavTimerCallback, hPBC) != OS_OK)
{
hPbcEngine->NavTimer = 0;
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating nav timer!\n"));
goto errout;
}
/* Set nav timer to fire every second */
if (OS_TimerSetRepeat(hPbcEngine->NavTimer, OS_WAIT_1S) != OS_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure setting repeat nav timer!\n"));
goto errout;
}
return (PLAYCTRL_SUCCESS);
errout:
/* Perform un-initialization routines */
PbcEngineDelete(hPBC);
return (PLAYCTRL_FAILURE);
}
/**
* PbcEngineDelete -- Delete the playback control engine task and message queue.
*
* @param
* hPBC -- handle to playback control engine private data
*
* @retval
* PLAYCTRL_STATUS
*/
PLAYCTRL_STATUS PbcEngineDelete(PBC_HANDLE *hPBC)
{
if (hPbcEngine != NULL)
{
if (hPBC == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDelete: NULL handle!\n"));
return (PLAYCTRL_NULL_POINTER);
}
if (hPbcEngine->NavTimer != 0)
{
/* Stop and delete the nav timer */
OS_TimerStop(hPbcEngine->NavTimer);
OS_TimerDelete(hPbcEngine->NavTimer);
hPbcEngine->NavTimer = 0;
}
if (hPbcEngine->ulTaskId != 0)
{
PBCENGINE_MESSAGE msg;
/* Send an exit message to the PBC engine task */
msg.tMsgType = PBCENGINE_MSGTYPE_EXIT;
msg.ulSemID = 0;
msg.pulRetVal = NULL;
OS_MsgQSend(hPbcEngine->MsgQID, (char *)&msg, sizeof(PBCENGINE_MESSAGE), OS_WAIT_FOREVER, OS_MSG_PRI_NORMAL);
/* Wait for task to exit then delete the task */
OS_TaskJoin(hPbcEngine->ulTaskId);
OS_TaskDelete(hPbcEngine->ulTaskId);
hPbcEngine->ulTaskId = 0;
}
if (hPbcEngine->MsgQID != 0)
{
/* Delete the msg queue */
OS_MsgQDelete(hPbcEngine->MsgQID);
hPbcEngine->MsgQID = 0;
}
if (0 != hPbcEngine->semMsgSynch)
{
OS_SemDelete(hPbcEngine->semMsgSynch);
hPbcEngine->semMsgSynch = 0;
}
/* Detach PE Event handler */
PEDetachEvent(hPBC->hPE, PbcEnginePECallback);
/* Detach DR event handler */
DRDetachEvent(hPBC->hDR);
/* Delete local handle */
OS_MemFree(hPbcEngine);
hPbcEngine = NULL;
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDelete: Not created!\n"));
return (PLAYCTRL_FAILURE);
}
return (PLAYCTRL_SUCCESS);
}
/**
* PbcEngineProcessCmd -- Add a command to the playback control engine message queue
* to be processed in the pbc engine task.
*
* @param
* hPBC -- playback control engine handle
* tCmd -- command to be processed
* data1 -- data parameter
* data2 -- data parameter
* data3 -- data parameter
* fSynch -- flag to indicate whether or not to process the message synchronously
* if true, process the message synchronously, o.w. asynchronous
*
* @retval
* PLAYCTRL_STATUS
*/
PLAYCTRL_STATUS PbcEngineProcessCmd(PBC_HANDLE *hPBC, PLAYCTRL_COMMAND tCmd, ULONG data1, ULONG data2, ULONG data3, BOOLEAN fSynch)
{
PBCENGINE_MESSAGE msg;
ULONG ulRetVal;
PLAYCTRL_STATUS status;
if (hPbcEngine == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: HDMV Module not created!\n"));
return (PLAYCTRL_FAILURE);
}
/* Check that message queue is created */
if (hPbcEngine->MsgQID == 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: Msg queue not created!\n"));
return (PLAYCTRL_FAILURE);
}
/* Load message parameters */
msg.tMsgType = PBCENGINE_MSGTYPE_PBC_CMD;
msg.hPbc = hPBC;
msg.ulData0 = (ULONG)tCmd;
msg.ulData1 = data1;
msg.ulData2 = data2;
msg.ulData3 = data3;
/*
* If synch flag is set, attach semaphore so message is processed sychronously.
* Otherwise, do not attach a semaphore to the message.
*/
if (fSynch == TRUE)
{
msg.ulSemID = (ULONG)hPbcEngine->semMsgSynch;
msg.pulRetVal = &ulRetVal;
}
else
{
msg.ulSemID = 0;
msg.pulRetVal = NULL;
}
/* Send message to be processed by the pbc engine task */
if (OS_MsgQSend(hPbcEngine->MsgQID, (char *)&msg, sizeof(PBCENGINE_MESSAGE), OS_WAIT_FOREVER, OS_MSG_PRI_NORMAL) != OS_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: Failure sending message!\n"));
status = PLAYCTRL_FAILURE;
}
else
{
/*
* If message is being processed synchronously, then
* wait for message processing to complete.
*/
if (fSynch == TRUE)
{
OS_SemTake(hPbcEngine->semMsgSynch, OS_WAIT_FOREVER);
status = *msg.pulRetVal;
}
else
{
status = PLAYCTRL_SUCCESS;
}
}
return (status);
}
/*
* Empty the Playback Control Engines Message Queue
*/
PLAYCTRL_STATUS PbcEngineClearCmdQueue(PBC_HANDLE *hPBC)
{
if (hPbcEngine == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: HDMV Module not created!\n"));
return (PLAYCTRL_FAILURE);
}
/* Check that message queue is created */
if (hPbcEngine->MsgQID == 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: Msg queue not created!\n"));
return (PLAYCTRL_FAILURE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -