📄 voip_stream_server.c
字号:
| Error handling section
*--------------------------------------------------------------------------------------------------------------------------*/
ERROR_HANDLING
{
/* Print the error to the user */
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_ERROR,
NULL,
"VoipStreamServerStart: %s (Result 0x%08X, %s, line %d)\n",
TBX_ERROR_DESCRIPTION,
TBX_ERROR_RESULT,
__FILE__,
TBX_ERROR_LINE);
}
/*---------------------------------------------------------------------------------------------------------------------------
| Cleanup section
*--------------------------------------------------------------------------------------------------------------------------*/
CLEANUP
{
TBX_SEM_GIV( pStreamServerContext->StreamServerSem );
}
RETURN;
}
/*-------------------------------------------------------------------------------------------------------------------------------
|
| VoipStreamServerClose : This function closes the stream server library.
|
| Note : ~
|
| Return : TBX_RESULT_OK if the function succeeded
| Other error code if the function could not complete properly.
|
*------------------------------------------------------------------------------------------------------------------------------*/
TBX_RESULT
VoipStreamServerClose()
{
PVOIP_CLI_CONTEXT pCliContext;
PVOIP_STREAM_SERVER_CONTEXT pStreamServerContext;
TBX_THREAD hThread;
/*---------------------------------------------------------------------------------------------------------------------------
| Code section
*--------------------------------------------------------------------------------------------------------------------------*/
CODE
{
/* Initialize local variables */
pCliContext = &g_pContext->CliContext;
pStreamServerContext = &g_pContext->StreamServerContext;
if( pStreamServerContext->hStreamServerLib != (TBX_STREAM_SERVER_LIB_HANDLE)TBX_HANDLE_INVALID )
{
TBX_SEM_GET( pStreamServerContext->StreamServerSem, TBX_SEM_WAIT_FOREVER );
/* Close the receive thread */
hThread = pStreamServerContext->hRecvThread;
pStreamServerContext->hRecvThread = TBX_THREAD_INVALID;
if( hThread != TBX_THREAD_INVALID )
{
/* Unblock the thread from its "read" function */
StreamServerLibCancelReceive( pStreamServerContext->hStreamServerLib );
while( !pStreamServerContext->fRecvThreadDone )
{
TBX_SEM_GIV( pStreamServerContext->StreamServerSem );
TBX_SLEEP_MS( 10 );
TBX_SEM_GET( pStreamServerContext->StreamServerSem, TBX_SEM_WAIT_FOREVER );
}
TBX_THREAD_DESTROY( &hThread );
}
StreamServerLibClose( pStreamServerContext->hStreamServerLib );
pStreamServerContext->hStreamServerLib = (TBX_STREAM_SERVER_LIB_HANDLE)TBX_HANDLE_INVALID;
/* Destroy the pool of prompt contexts */
if( pStreamServerContext->hPoolOfPrompts != TBX_HANDLE_INVALID )
{
TBXPoolOfBuffersDestroy( pStreamServerContext->hPoolOfPrompts );
pStreamServerContext->hPoolOfPrompts = TBX_HANDLE_INVALID;
}
TBX_SEM_GIV( pStreamServerContext->StreamServerSem );
TBX_SEM_DESTROY( &pStreamServerContext->StreamServerSem );
}
/* Mark the stream server as not enable */
pStreamServerContext->fEnable = TBX_FALSE;
/* End of the code (skip to cleanup) */
TBX_EXIT_SUCCESS (TBX_RESULT_OK);
}
/*---------------------------------------------------------------------------------------------------------------------------
| Error handling section
*--------------------------------------------------------------------------------------------------------------------------*/
ERROR_HANDLING
{
/* Print the error to the user */
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_ERROR,
NULL,
"VoipStreamServerClose: %s (Result 0x%08X, %s, line %d)\n",
TBX_ERROR_DESCRIPTION,
TBX_ERROR_RESULT,
__FILE__,
TBX_ERROR_LINE);
}
/*---------------------------------------------------------------------------------------------------------------------------
| Cleanup section
*--------------------------------------------------------------------------------------------------------------------------*/
CLEANUP
{
}
RETURN;
}
/*-------------------------------------------------------------------------------------------------------------------------------
|
| VoipStreamServerReceiveThread : Thread that receives the responses from the stream server
|
| Note : ~
|
| Return : TBX_RESULT_OK if the function succeeded
| Other error code if the function could not complete properly.
|
*------------------------------------------------------------------------------------------------------------------------------*/
static TBX_RESULT VoipStreamServerReceiveThread()
{
TBX_RESULT result;
PVOIP_CLI_CONTEXT pCliContext;
STREAMSERVER_MSG Message;
STREAMSERVER_MSG OutMessage;
TBX_STREAM_SERVER_HANDLE hStreamServer;
PVOIP_STREAM_SERVER_CONTEXT pStreamServerContext;
PVOIP_STREAM_SERVER_PROMPT_CONTEXT pStreamServerPromptContext;
/* Initialize local variables */
pCliContext = &g_pContext->CliContext;
pStreamServerContext = &g_pContext->StreamServerContext;
TBX_SEM_GET( pStreamServerContext->StreamServerSem, TBX_SEM_WAIT_FOREVER );
pStreamServerContext->fRecvThreadRunning = TBX_TRUE;
TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "Stream server receive thread started...\n" );
/* Force server availability update to immediately get the availability of the stream server */
StreamServerForceAvailabilityUpdate( pStreamServerContext->hStreamServerLib );
while( g_fContinue == TBX_TRUE )
{
/* Wait for a message from a stream server... */
TBX_SEM_GIV( pStreamServerContext->StreamServerSem );
result = StreamServerLibRead
(
pStreamServerContext->hStreamServerLib,
&Message,
0xFFFFFFFF,
&hStreamServer,
NULL
);
TBX_SEM_GET( pStreamServerContext->StreamServerSem, TBX_SEM_WAIT_FOREVER );
if( g_fContinue == TBX_FALSE )
{
break;
}
/* Was the receive successful and the message from our stream server? */
if( TBX_RESULT_SUCCESS( result ) && (hStreamServer == pStreamServerContext->hStreamServer) )
{
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: Received message type %d from stream server, context 0x%08X\n",
(int)Message.Header.MessageType,
(int)Message.Header.un32UserContext );
/* Validate this is an expected stream server response */
switch( Message.Header.MessageType )
{
case STREAMSERVER_MSG_ID_EVT_SERVER_AVAILABILITY:
{
TBX_BOOL fServerAvailable;
fServerAvailable = Message.EvtServerAvailbility.fIpAddress0Available || Message.EvtServerAvailbility.fIpAddress1Available;
if( pStreamServerContext->fServerAvailable != fServerAvailable )
{
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: State is now %s\n",
fServerAvailable ? "available" : "unavailable" );
if( fServerAvailable )
{
/* Server was unavailable, now available. We must re-synchronize */
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: resynchronization starting...\n" );
/* Build the "list playing prompts" message... */
memset( &OutMessage.ReqListPlayingPrompts, 0, sizeof(OutMessage.ReqListPlayingPrompts) );
OutMessage.Header.MessageType = STREAMSERVER_MSG_ID_REQ_LIST_PLAYING_PROMPTS;
OutMessage.Header.un32UserContext = 0; /* Don't care */
OutMessage.ReqListPlayingPrompts.fCurrentAppOnly = TBX_TRUE;
result = StreamServerLibCommandSend
(
pStreamServerContext->hStreamServerLib,
&OutMessage,
pStreamServerContext->hStreamServer
);
if( TBX_RESULT_SUCCESS(result) )
{
/* Server is available. Resynch starting. */
pStreamServerContext->fServerAvailable = TBX_TRUE;
pStreamServerContext->fResyncRunning = TBX_TRUE;
}
else
{
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: resynchronization FAILED (failed to send ListPrompts message).\n" );
}
}
else
{
/* Mark every prompts has not synched yet... */
pStreamServerPromptContext = TBXPoolOfBuffersFirst( pStreamServerContext->hPoolOfPrompts );
while( pStreamServerPromptContext )
{
pStreamServerPromptContext->fSynched = TBX_FALSE;
pStreamServerPromptContext = TBXPoolOfBuffersNext( pStreamServerContext->hPoolOfPrompts, pStreamServerPromptContext );
}
/* Server is no more available. We will stop accepting calls */
pStreamServerContext->fServerAvailable = TBX_FALSE;
pStreamServerContext->fResyncRunning = TBX_FALSE;
}
}
} break;
case STREAMSERVER_MSG_ID_RSP_LIST_PLAYING_PROMPTS:
{
/* This is a response from "list playing prompts" */
if( pStreamServerContext->fResyncRunning )
{
if( Message.RspListPlayingPrompts.un32NbPrompts == 0 )
{
/* End of listing */
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: resynchronization finished.\n" );
/* Any non-synched resource means it is not playing anymore on the server */
pStreamServerPromptContext = TBXPoolOfBuffersFirst( pStreamServerContext->hPoolOfPrompts );
while( pStreamServerPromptContext )
{
if( pStreamServerPromptContext->fSynched )
{
/* This context has already been "synched" */
}
else
{
pStreamServerPromptContext->fSynched = TBX_TRUE;
if( pStreamServerPromptContext->fStarting || pStreamServerPromptContext->fPlaying )
{
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: restarting playback after resync for prompt 0x%08X because server stopped play while it was unavailable.\n",
pStreamServerPromptContext->un32PromptId );
/* The state machine expects the channel to still be playing, restart playback */
VoipStreamServerStartPlayInternal( pStreamServerPromptContext );
}
else if( pStreamServerPromptContext->fStopping )
{
/* The state machine expects the "DONE" response. Simulate that */
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: Simulating RSP_DONE for prompt 0x%08X because server stopped play while it was unavailable.\n",
pStreamServerPromptContext->un32PromptId );
pStreamServerPromptContext->fStarting = TBX_FALSE;
pStreamServerPromptContext->fPlaying = TBX_FALSE;
pStreamServerPromptContext->fStopping = TBX_FALSE;
}
}
pStreamServerPromptContext = TBXPoolOfBuffersNext( pStreamServerContext->hPoolOfPrompts, pStreamServerPromptContext );
}
/* Resynchronization done */
pStreamServerContext->fResyncRunning = TBX_FALSE;
}
else
{
/* Retrieve the prompt context */
pStreamServerPromptContext = TBXPoolOfBuffersFind(
pStreamServerContext->hPoolOfPrompts,
Message.RspListPlayingPrompts.un32UserContext);
if( pStreamServerPromptContext )
{
if( pStreamServerPromptContext->fSynched )
{
/* No need to resync */
}
else
{
pStreamServerPromptContext->fSynched = TBX_TRUE;
/* Validate that our state matches the stream server's */
if( pStreamServerPromptContext->fStarting )
{
/* Current app is waiting for the "started" event, that we probably missed
because the stream server was disconnected. Simulate that we received it */
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: Simulating RSP_STARTED for prompt 0x%08X because server started play while it was unavailable.\n",
pStreamServerPromptContext->un32PromptId );
pStreamServerPromptContext->fStarting = TBX_FALSE;
pStreamServerPromptContext->fPlaying = TBX_TRUE;
pStreamServerPromptContext->fStopping = TBX_FALSE;
}
else if( pStreamServerPromptContext->fPlaying )
{
/* Current app expects the call to be playing, which is in fact the case!
Keep it like this! */
}
else
{
/* Current app expects the call to be stopping or be already stopped.
Stop this playback on the server */
TbxCliToolsLogPrint(
pCliContext->hCliTools,
TRACE_LEVEL_1,
NULL,
"Stream server: Stopping play ctx 0x%08X on stream server because current app stopped it while server was unavailable.\n",
Message.RspListPlayingPrompts.un32UserContext );
memset( &OutMessage.ReqStop, 0, sizeof(OutMessage.ReqStop) );
OutMessage.Header.MessageType = STREAMSERVER_MSG_ID_REQ_STOP;
OutMessage.Header.un32UserContext = Message.RspListPlayingPrompts.un32UserContext;
StreamServerLibCommandSend
(
pStreamServerContext->hStreamServerLib,
&OutMessage,
pStreamServerContext->hStreamServer
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -