first commit
This commit is contained in:
764
Minecraft.Client/PS3/Network/SonyVoiceChat.cpp
Normal file
764
Minecraft.Client/PS3/Network/SonyVoiceChat.cpp
Normal file
@@ -0,0 +1,764 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* SCE CONFIDENTIAL
|
||||
PlayStation(R)3 Programmer Tool Runtime Library 430.001
|
||||
* Copyright (C) 2008 Sony Computer Entertainment Inc.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
#include "SonyVoiceChat.h"
|
||||
#include <arpa/inet.h> /* inet_ntoa() */
|
||||
|
||||
/* for displaying extra information */
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
#define AVC2_GAME_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef AVC2_GAME_DEBUG
|
||||
#define INF(...) printf( "INF:" __VA_ARGS__ )
|
||||
#define ERR(...) printf( "ERR:" __VA_ARGS__ )
|
||||
#else
|
||||
#define INF(...)
|
||||
#define ERR(...)
|
||||
#endif
|
||||
|
||||
#define UNUSED_VARIABLE(x) (void)(x)
|
||||
|
||||
//#define DISABLE_VOICE_CHAT
|
||||
|
||||
static CellSysutilAvc2InitParam g_chat_avc2param;
|
||||
|
||||
EAVCEvent SonyVoiceChat::sm_event = AVC_EVENT_EPSILON;
|
||||
EAVCState SonyVoiceChat::sm_state = AVC_STATE_IDLE;
|
||||
SQRNetworkManager_PS3* SonyVoiceChat::sm_pNetworkManager;
|
||||
bool SonyVoiceChat::sm_bEnabled = true;
|
||||
uint8_t SonyVoiceChat::sm_micStatus = CELL_AVC2_MIC_STATUS_UNKNOWN;
|
||||
bool SonyVoiceChat::sm_bLoaded = false;
|
||||
bool SonyVoiceChat::sm_bUnloading = false;
|
||||
unordered_map<SceNpMatching2RoomMemberId, bool> SonyVoiceChat::sm_bTalkingMap;
|
||||
bool SonyVoiceChat::sm_bCanStart = false;
|
||||
bool SonyVoiceChat::sm_isChatRestricted = false;
|
||||
int SonyVoiceChat::sm_currentBitrate = 28000;
|
||||
|
||||
void SonyVoiceChat::init( SQRNetworkManager_PS3* pNetMan )
|
||||
{
|
||||
if(sm_state != AVC_STATE_IDLE)
|
||||
return;
|
||||
|
||||
sm_pNetworkManager = pNetMan;
|
||||
setState(AVC_STATE_CHAT_INIT);
|
||||
ProfileManager.GetChatAndContentRestrictions(0,false,&sm_isChatRestricted,NULL,NULL);
|
||||
}
|
||||
|
||||
void SonyVoiceChat::shutdown()
|
||||
{
|
||||
if( sm_state == AVC_STATE_IDLE ||
|
||||
sm_state == AVC_STATE_CHAT_LEAVE ||
|
||||
sm_state == AVC_STATE_CHAT_UNLOAD ||
|
||||
sm_state == AVC_STATE_CHAT_RESET )
|
||||
{
|
||||
// we're either shut down already, or in the process
|
||||
return;
|
||||
}
|
||||
|
||||
setEvent(AVC_EVENT_EXIT_GAME);
|
||||
}
|
||||
|
||||
void SonyVoiceChat::setEnabled( bool bEnabled )
|
||||
{
|
||||
if(sm_bEnabled != bEnabled)
|
||||
{
|
||||
if(sm_bCanStart)
|
||||
{
|
||||
if(bEnabled)
|
||||
startStream();
|
||||
else
|
||||
stopStream();
|
||||
}
|
||||
sm_bEnabled = bEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int SonyVoiceChat::eventcb_load(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
UNUSED_VARIABLE( event_param );
|
||||
UNUSED_VARIABLE( userdata );
|
||||
|
||||
if( event_id == CELL_AVC2_EVENT_LOAD_SUCCEEDED )
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_LOAD_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setEvent(AVC_EVENT_CHAT_LOAD_SUCCEEDED);
|
||||
sm_bLoaded = true;
|
||||
|
||||
// set the packet contention value here
|
||||
CellSysutilAvc2Attribute attr;
|
||||
memset( &attr, 0x00, sizeof(attr) );
|
||||
attr.attr_id = CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_PACKET_CONTENTION;
|
||||
attr.attr_param.int_param = 3;
|
||||
int ret = cellSysutilAvc2SetAttribute(&attr);
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
app.DebugPrintf("CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_PACKET_CONTENTION failed !!! 0x%08x\n", ret);
|
||||
}
|
||||
|
||||
}
|
||||
else /* if( event_id == CELL_AVC2_EVENT_LOAD_FAILED ) */
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_LOAD_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setEvent(AVC_EVENT_CHAT_LOAD_FAILED);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::eventcb_join(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
UNUSED_VARIABLE( event_param );
|
||||
UNUSED_VARIABLE( userdata );
|
||||
|
||||
if( event_id == CELL_AVC2_EVENT_JOIN_SUCCEEDED )
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_JOIN_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setEvent(AVC_EVENT_CHAT_JOIN_SUCCEEDED);
|
||||
}
|
||||
else /* if( event_id == CELL_AVC2_EVENT_JOIN_FAILED ) */
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_JOIN_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setEvent(AVC_EVENT_ERROR);
|
||||
}
|
||||
sm_bTalkingMap.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::eventcb_leave( CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
UNUSED_VARIABLE( event_param );
|
||||
UNUSED_VARIABLE( userdata );
|
||||
|
||||
if( event_id == CELL_AVC2_EVENT_LEAVE_SUCCEEDED )
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_LEAVE_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setState(AVC_STATE_CHAT_LEAVE);
|
||||
setEvent(AVC_EVENT_CHAT_LEAVE_SUCCEEDED);
|
||||
}
|
||||
else /* if( event_id == CELL_AVC2_EVENT_LEAVE_FAILED ) */
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_LEAVE_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setState(AVC_STATE_CHAT_LEAVE);
|
||||
setEvent(AVC_EVENT_ERROR);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::eventcb_unload(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
UNUSED_VARIABLE( event_param );
|
||||
UNUSED_VARIABLE( userdata );
|
||||
|
||||
if( event_id == CELL_AVC2_EVENT_UNLOAD_SUCCEEDED )
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_UNLOAD_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setEvent(AVC_EVENT_CHAT_UNLOAD_SUCCEEDED);
|
||||
sm_bLoaded = false;
|
||||
sm_bUnloading = false;
|
||||
}
|
||||
else /* if( event_id == CELL_AVC2_EVENT_UNLOAD_FAILED ) */
|
||||
{
|
||||
INF( "<AVC CB>CELL_AVC2_EVENT_UNLOAD_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
|
||||
setEvent(AVC_EVENT_ERROR);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::eventcb_voiceDetected(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
|
||||
{
|
||||
UNUSED_VARIABLE( userdata );
|
||||
|
||||
// To the upper 32 bits, the room member ID of the player is passed.
|
||||
// In the lower 32 bits, a value of 0 (mute) or a value between 1 (low volume)
|
||||
// and 10 (high volume) is passed as the audio signal value when the notification
|
||||
// method is the level method, or a value of 1 (start of speaking) or 0 (end of speaking)
|
||||
// is stored when the notification method is the trigger method.
|
||||
|
||||
SceNpMatching2RoomMemberId roomMemberID = (SceNpMatching2RoomMemberId)(event_param >> 32);
|
||||
uint32_t volume = (uint32_t)(event_param & 0xffffffff);
|
||||
|
||||
// The precision of voice detection is not very high. Since the audio signal values may
|
||||
// always be relatively high depending on the audio input device and the noise level in the
|
||||
// room, you should set a large reference value for determining whether or not a player is
|
||||
// speaking. Relatively good results can be obtained when an audio signal value of at
|
||||
// least 9 is used to determine if a player is speaking.
|
||||
bool bTalking = false;
|
||||
if(volume >= 9)
|
||||
bTalking = true;
|
||||
|
||||
sm_bTalkingMap[roomMemberID] = bTalking;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
/* Callback function for handling AV Chat2 Utility events */
|
||||
void SonyVoiceChat::eventcb( CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
|
||||
{
|
||||
static struct _cb_func_tbl
|
||||
{
|
||||
CellSysutilAvc2EventId event;
|
||||
int (*func)( CellSysutilAvc2EventId event_id,
|
||||
CellSysutilAvc2EventParam event_param,
|
||||
void *userdata );
|
||||
} event_tbl[] =
|
||||
{
|
||||
{ CELL_AVC2_EVENT_LOAD_SUCCEEDED, eventcb_load },
|
||||
{ CELL_AVC2_EVENT_LOAD_FAILED, eventcb_load },
|
||||
{ CELL_AVC2_EVENT_JOIN_SUCCEEDED, eventcb_join },
|
||||
{ CELL_AVC2_EVENT_JOIN_FAILED, eventcb_join },
|
||||
{ CELL_AVC2_EVENT_LEAVE_SUCCEEDED, eventcb_leave },
|
||||
{ CELL_AVC2_EVENT_LEAVE_FAILED, eventcb_leave },
|
||||
{ CELL_AVC2_EVENT_UNLOAD_SUCCEEDED, eventcb_unload },
|
||||
{ CELL_AVC2_EVENT_UNLOAD_FAILED, eventcb_unload },
|
||||
{ CELL_AVC2_EVENT_SYSTEM_NEW_MEMBER_JOINED, NULL },
|
||||
{ CELL_AVC2_EVENT_SYSTEM_MEMBER_LEFT, NULL },
|
||||
{ CELL_AVC2_EVENT_SYSTEM_SESSION_ESTABLISHED, NULL },
|
||||
{ CELL_AVC2_EVENT_SYSTEM_SESSION_CANNOT_ESTABLISHED,NULL },
|
||||
{ CELL_AVC2_EVENT_SYSTEM_SESSION_DISCONNECTED, NULL },
|
||||
{ CELL_AVC2_EVENT_SYSTEM_VOICE_DETECTED, eventcb_voiceDetected },
|
||||
|
||||
};
|
||||
|
||||
int ret = 0;
|
||||
for( unsigned int i=0; i<sizeof(event_tbl)/sizeof(struct _cb_func_tbl) ; ++i )
|
||||
{
|
||||
if( event_tbl[ i ].event == event_id && event_tbl[ i ].func )
|
||||
{
|
||||
ret = (*event_tbl[ i ].func)( event_id, event_param, userdata );
|
||||
if( ret < 0 )
|
||||
{
|
||||
ERR("ret=0x%x\n", ret );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SonyVoiceChat::load()
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
INF("----------------------------\n");
|
||||
INF("| cellSysutilAvc2LoadAsync |\n");
|
||||
INF("----------------------------\n");
|
||||
ret = cellSysutilAvc2LoadAsync( sm_pNetworkManager->m_matchingContext,
|
||||
SYS_MEMORY_CONTAINER_ID_INVALID,
|
||||
eventcb,
|
||||
NULL,
|
||||
&g_chat_avc2param );
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2LoadAsync: ret=0x%x\n", ret );
|
||||
setEvent(AVC_EVENT_ERROR);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::join()
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
INF("---------------------------------------------------\n");
|
||||
INF("| cellSysutilAvc2JoinChatRequest \n");
|
||||
INF("---------------------------------------------------\n");
|
||||
ret = cellSysutilAvc2JoinChatRequest( &sm_pNetworkManager->m_room );
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2JoinChatRequest: ret=0x%x\n", ret );
|
||||
setEvent(AVC_EVENT_ERROR);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::leave()
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
INF("-----------------------------------\n");
|
||||
INF("| cellSysutilAvc2LeaveChatRequest |\n");
|
||||
INF("-----------------------------------\n");
|
||||
ret = cellSysutilAvc2LeaveChatRequest();
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2LeaveChatRequest() = 0x%x\n", ret );
|
||||
setEvent(AVC_EVENT_ERROR);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::unload()
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
INF("------------------------------\n");
|
||||
INF("| cellSysutilAvc2UnloadAsync |\n");
|
||||
INF("------------------------------\n");
|
||||
|
||||
ret = cellSysutilAvc2UnloadAsync();
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvcUnloadAsync() = 0x%x\n", ret );
|
||||
setEvent(AVC_EVENT_ERROR);
|
||||
return ret;
|
||||
}
|
||||
sm_bUnloading = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::start()
|
||||
{
|
||||
sm_bCanStart = (sm_isChatRestricted == false);
|
||||
|
||||
int ret = CELL_OK;
|
||||
if(sm_bEnabled)
|
||||
ret = startStream();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::stop()
|
||||
{
|
||||
sm_bCanStart = false;
|
||||
|
||||
int ret = CELL_OK;
|
||||
if(sm_bEnabled)
|
||||
ret = stopStream();
|
||||
|
||||
setEvent(AVC_EVENT_CHAT_SESSION_STOPPED);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::startStream()
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
INF("---------------------------------\n");
|
||||
INF("| cellSysutilAvc2StartStreaming |\n");
|
||||
INF("---------------------------------\n");
|
||||
ret = cellSysutilAvc2StartStreaming();
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2StartStreaming: ret=0x%x\n", ret );
|
||||
}
|
||||
|
||||
ret = cellSysutilAvc2StartVoiceDetection();
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2StartVoiceDetection: ret=0x%x\n", ret );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::stopStream()
|
||||
{
|
||||
int ret = cellSysutilAvc2StopVoiceDetection();
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2StopVoiceDetection: ret=0x%x\n", ret );
|
||||
}
|
||||
|
||||
INF("--------------------------------\n");
|
||||
INF("| cellSysutilAvc2StopStreaming |\n");
|
||||
INF("--------------------------------\n");
|
||||
ret = cellSysutilAvc2StopStreaming();
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2StopStreaming: ret=0x%x\n", ret );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::initialize(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Must use cellSysutilAvc2InitParam() for clearing CellSysutilAvc2InitParam struct*/
|
||||
ret = cellSysutilAvc2InitParam(CELL_SYSUTIL_AVC2_INIT_PARAM_VERSION, &g_chat_avc2param);
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR( "cellSysutilAvc2InitParam failed (0x%x)\n", ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setting application specific parameters */
|
||||
g_chat_avc2param.media_type = CELL_SYSUTIL_AVC2_VOICE_CHAT;
|
||||
g_chat_avc2param.max_players = AVC2_PARAM_DEFAULT_MAX_PLAYERS;
|
||||
g_chat_avc2param.voice_param.voice_quality = CELL_SYSUTIL_AVC2_VOICE_QUALITY_NORMAL;
|
||||
g_chat_avc2param.voice_param.max_speakers = AVC2_PARAM_DEFAULT_MAX_SPEAKERS;
|
||||
g_chat_avc2param.spu_load_average = 50;
|
||||
g_chat_avc2param.streaming_mode.mode = CELL_SYSUTIL_AVC2_STREAMING_MODE_NORMAL;
|
||||
|
||||
setEvent(AVC_EVENT_CHAT_INIT_SUCCEEDED);
|
||||
setState(AVC_STATE_CHAT_INIT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SonyVoiceChat::finalize(void)
|
||||
{
|
||||
setEvent(AVC_EVENT_CHAT_FINALIZE_SUCCEEDED);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void SonyVoiceChat::tick()
|
||||
{
|
||||
#ifdef DISABLE_VOICE_CHAT
|
||||
return;
|
||||
#endif
|
||||
|
||||
static state_transition_table tbl[] =
|
||||
{
|
||||
/* now state event func after the transition state */
|
||||
{ AVC_STATE_CHAT_INIT, AVC_EVENT_EPSILON, initialize, AVC_STATE_CHAT_INIT },
|
||||
{ AVC_STATE_CHAT_INIT, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_INIT, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_INIT, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_INIT, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_INIT, AVC_EVENT_CHAT_INIT_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_LOAD },
|
||||
{ AVC_STATE_CHAT_INIT, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
|
||||
{ AVC_STATE_CHAT_LOAD, AVC_EVENT_EPSILON, load, AVC_STATE_CHAT_LOAD },
|
||||
{ AVC_STATE_CHAT_LOAD, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_LOAD, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_LOAD, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_LOAD, AVC_EVENT_CHAT_LOAD_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_JOIN },
|
||||
{ AVC_STATE_CHAT_LOAD, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
|
||||
{ AVC_STATE_CHAT_JOIN, AVC_EVENT_EPSILON, join, AVC_STATE_CHAT_JOIN },
|
||||
{ AVC_STATE_CHAT_JOIN, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
|
||||
{ AVC_STATE_CHAT_JOIN, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
|
||||
{ AVC_STATE_CHAT_JOIN, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
|
||||
{ AVC_STATE_CHAT_JOIN, AVC_EVENT_CHAT_JOIN_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_SESSION_PROCESSING },
|
||||
{ AVC_STATE_CHAT_JOIN, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
|
||||
|
||||
{ AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_EPSILON, start, AVC_STATE_CHAT_SESSION_PROCESSING },
|
||||
{ AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_EXIT_GAME, stop, AVC_STATE_CHAT_SESSION_PROCESSING },
|
||||
{ AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_ERROR, stop, AVC_STATE_CHAT_SESSION_PROCESSING },
|
||||
{ AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_LAN_DISCONNECT, stop, AVC_STATE_CHAT_SESSION_PROCESSING },
|
||||
{ AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_CHAT_SESSION_STOPPED, invoke_epsilon_event, AVC_STATE_CHAT_LEAVE },
|
||||
{ AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,stop, AVC_STATE_CHAT_SESSION_PROCESSING },
|
||||
|
||||
{ AVC_STATE_CHAT_LEAVE, AVC_EVENT_EPSILON, leave, AVC_STATE_CHAT_LEAVE },
|
||||
{ AVC_STATE_CHAT_LEAVE, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
|
||||
{ AVC_STATE_CHAT_LEAVE, AVC_EVENT_CHAT_LEAVE_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
|
||||
|
||||
{ AVC_STATE_CHAT_UNLOAD, AVC_EVENT_EPSILON, unload, AVC_STATE_CHAT_UNLOAD },
|
||||
{ AVC_STATE_CHAT_UNLOAD, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_UNLOAD, AVC_EVENT_CHAT_UNLOAD_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
|
||||
|
||||
{ AVC_STATE_CHAT_RESET, AVC_EVENT_EPSILON, finalize, AVC_STATE_CHAT_RESET },
|
||||
{ AVC_STATE_CHAT_RESET, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_LEAVE },
|
||||
{ AVC_STATE_CHAT_RESET, AVC_EVENT_CHAT_FINALIZE_SUCCEEDED, invoke_epsilon_event, AVC_STATE_IDLE },
|
||||
|
||||
};
|
||||
do_state_transition( &tbl[0], sizeof( tbl ) / sizeof( state_transition_table ) );
|
||||
|
||||
setBitRate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SonyVoiceChat::do_state_transition( state_transition_table *tbl, int tbl_size )
|
||||
{
|
||||
int ret = CELL_OK;
|
||||
|
||||
// if( sm_event == AVC_EVENT_LAN_DISCONNECT ||
|
||||
// sm_event == AVC_EVENT_EXIT_GAME ||
|
||||
// sm_event == AVC_EVENT_ERROR ||
|
||||
// sm_event == AVC_EVENT_FATAL_ERROR )
|
||||
// {
|
||||
// g_gamedata.finalize = 1;
|
||||
// }
|
||||
// if( sm_event == AVC_EVENT_FATAL_ERROR )
|
||||
// {
|
||||
// g_gamedata.exit = true;
|
||||
// }
|
||||
bool bCalledFunc = false;
|
||||
for( int i = 0; i < tbl_size; i++ )
|
||||
{
|
||||
if( sm_state == ( tbl + i )->state )
|
||||
{
|
||||
if( sm_event == ( tbl + i )->event )
|
||||
{
|
||||
sm_event = AVC_EVENT_NON;
|
||||
ret = (*( tbl + i )->func)();
|
||||
bCalledFunc = true;
|
||||
if( ret != CELL_OK )
|
||||
{
|
||||
ERR("ret = 0x%x\n", ret );
|
||||
}
|
||||
|
||||
setState(( tbl + i )->new_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bCalledFunc == false)
|
||||
{
|
||||
assert( (sm_event == AVC_EVENT_NON) ||
|
||||
(sm_state == AVC_STATE_IDLE && sm_event == AVC_EVENT_EPSILON) );
|
||||
}
|
||||
}
|
||||
|
||||
int SonyVoiceChat::invoke_epsilon_event(void)
|
||||
{
|
||||
setEvent(AVC_EVENT_EPSILON);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
bool SonyVoiceChat::hasMicConnected(const SceNpMatching2RoomMemberId *players_id)
|
||||
{
|
||||
CellSysutilAvc2PlayerInfo players_info;
|
||||
int err = cellSysutilAvc2GetPlayerInfo(players_id, &players_info);
|
||||
if(err == CELL_OK)
|
||||
{
|
||||
if(players_info.connected && players_info.joined)
|
||||
{
|
||||
if(players_info.mic_attached == CELL_AVC2_MIC_STATUS_ATTACHED_ON)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SonyVoiceChat::mute( bool bMute )
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
int err = cellSysutilAvc2SetVoiceMuting(bMute);
|
||||
assert(err == CELL_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void SonyVoiceChat::mutePlayer( const SceNpMatching2RoomMemberId member_id, bool bMute ) /*Turn chat audio from a specified player on or off */
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
int err = cellSysutilAvc2SetPlayerVoiceMuting(member_id, bMute);
|
||||
assert(err == CELL_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void SonyVoiceChat::muteLocalPlayer( bool bMute ) /*Turn microphone input on or off */
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
int err = cellSysutilAvc2SetVoiceMuting(bMute);
|
||||
assert(err == CELL_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SonyVoiceChat::isMuted()
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
uint8_t bMute;
|
||||
int err = cellSysutilAvc2GetVoiceMuting(&bMute);
|
||||
assert(err == CELL_OK);
|
||||
return bMute;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SonyVoiceChat::isMutedPlayer( const SceNpMatching2RoomMemberId member_id)
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
uint8_t bMute;
|
||||
int err = cellSysutilAvc2GetPlayerVoiceMuting(member_id, &bMute);
|
||||
assert(err == CELL_OK);
|
||||
return bMute;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SonyVoiceChat::isMutedLocalPlayer()
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
uint8_t bMute;
|
||||
int err = cellSysutilAvc2GetVoiceMuting(&bMute);
|
||||
assert(err == CELL_OK);
|
||||
return bMute;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SonyVoiceChat::setVolume( float vol )
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
// The volume level can be set to a value in the range 0.0 to 40.0.
|
||||
// Volume levels are linear values such that if 1.0 is specified, the
|
||||
// volume level will be 1 times the reference power (0dB), and if 0.5
|
||||
// is specified, the volume level will be 0.5 times the reference power
|
||||
// (-6dB). If 0.0 is specified, chat audio will no longer be audible.
|
||||
|
||||
int err =cellSysutilAvc2SetSpeakerVolumeLevel(vol * 40.0f);
|
||||
assert(err==CELL_OK);
|
||||
}
|
||||
}
|
||||
|
||||
float SonyVoiceChat::getVolume()
|
||||
{
|
||||
if(sm_bLoaded && !sm_bUnloading)
|
||||
{
|
||||
float vol;
|
||||
int err = cellSysutilAvc2GetSpeakerVolumeLevel(&vol);
|
||||
assert(err == CELL_OK);
|
||||
return (vol / 40.0f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SonyVoiceChat::isTalking( SceNpMatching2RoomMemberId* players_id )
|
||||
{
|
||||
AUTO_VAR(it, sm_bTalkingMap.find(*players_id));
|
||||
if (it != sm_bTalkingMap.end() )
|
||||
return it->second;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SonyVoiceChat::setBitRate()
|
||||
{
|
||||
if(sm_state != AVC_STATE_CHAT_SESSION_PROCESSING)
|
||||
return;
|
||||
|
||||
int numPlayers = sm_pNetworkManager->GetPlayerCount();
|
||||
// This internal attribute represents the maximum voice bit rate. attr_param
|
||||
// is an integer value. The units are bps, and the specifiable values are
|
||||
// 4000, 8000, 16000, 20000, 24000, and 28000. The initial value is 28000.
|
||||
|
||||
static int bitRates[8] = { 28000, 28000,
|
||||
28000, 28000,
|
||||
24000, 20000,
|
||||
16000, 16000};
|
||||
int bitRate = bitRates[numPlayers-1];
|
||||
if(bitRate == sm_currentBitrate)
|
||||
return;
|
||||
|
||||
CellSysutilAvc2Attribute attr;
|
||||
memset( &attr, 0x00, sizeof(attr) );
|
||||
attr.attr_id = CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_MAX_BITRATE;
|
||||
attr.attr_param.int_param = bitRate;
|
||||
int ret = cellSysutilAvc2SetAttribute(&attr);
|
||||
if( ret == CELL_OK )
|
||||
{
|
||||
sm_currentBitrate = bitRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("SonyVoiceChat::setBitRate failed !!! 0x%08x\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CASE_STR_VALUE(s) case s: return #s;
|
||||
|
||||
const char* getStateString(EAVCState state)
|
||||
{
|
||||
|
||||
switch(state)
|
||||
{
|
||||
|
||||
CASE_STR_VALUE(AVC_STATE_IDLE);
|
||||
CASE_STR_VALUE(AVC_STATE_CHAT_INIT)
|
||||
CASE_STR_VALUE(AVC_STATE_CHAT_LOAD);
|
||||
CASE_STR_VALUE(AVC_STATE_CHAT_JOIN);
|
||||
CASE_STR_VALUE(AVC_STATE_CHAT_SESSION_PROCESSING);
|
||||
CASE_STR_VALUE(AVC_STATE_CHAT_LEAVE);
|
||||
CASE_STR_VALUE(AVC_STATE_CHAT_RESET);
|
||||
CASE_STR_VALUE(AVC_STATE_CHAT_UNLOAD);
|
||||
CASE_STR_VALUE(AVC_STATE_EXIT);
|
||||
default:
|
||||
return "unknown state";
|
||||
}
|
||||
}
|
||||
|
||||
const char* getEventString(EAVCEvent state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
CASE_STR_VALUE(AVC_EVENT_NON);
|
||||
CASE_STR_VALUE(AVC_EVENT_EPSILON);
|
||||
CASE_STR_VALUE(AVC_EVENT_LAN_DISCONNECT);
|
||||
CASE_STR_VALUE(AVC_EVENT_ONLINE);
|
||||
CASE_STR_VALUE(AVC_EVENT_OFFLINE);
|
||||
CASE_STR_VALUE(AVC_EVENT_EXIT_GAME);
|
||||
CASE_STR_VALUE(AVC_EVENT_ROOM_CREATE);
|
||||
CASE_STR_VALUE(AVC_EVENT_ROOM_SEARCH);
|
||||
CASE_STR_VALUE(AVC_EVENT_ERROR);
|
||||
CASE_STR_VALUE(AVC_EVENT_FATAL_ERROR);
|
||||
CASE_STR_VALUE(AVC_EVENT_NETDIALOG_FINISHED);
|
||||
CASE_STR_VALUE(AVC_EVENT_NETDIALOG_UNLOADED);
|
||||
CASE_STR_VALUE(AVC_EVENT_NP2_INIT_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_NP2_FINALIZE_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_NP2_START_CONTEXT_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_NP2_STOP_CONTEXT_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT);
|
||||
CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_MEMBER_LEFT);
|
||||
CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_MEMBER_JOINED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_LOAD_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_LOAD_FAILED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_JOIN_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_JOIN_FAILED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_LEAVE_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_LEAVE_FAILED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_UNLOAD_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_UNLOAD_FAILED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_INIT_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_FINALIZE_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CHAT_SESSION_STOPPED);
|
||||
CASE_STR_VALUE(AVC_EVENT_CREATE_JOIN_ROOM_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_SEARCH_ROOM_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_JOIN_ROOM_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_LEAVE_ROOM_SUCCEEDED);
|
||||
CASE_STR_VALUE(AVC_EVENT_SIGNALING_ESTABLISHED);
|
||||
CASE_STR_VALUE(AVC_EVENT_SIGNALING_DEAD);
|
||||
CASE_STR_VALUE(AVC_EVENT_UI_CLOSE_SUCCEEDED);
|
||||
default:
|
||||
return "unknown event";
|
||||
}
|
||||
}
|
||||
|
||||
void SonyVoiceChat::printStateAndEvent()
|
||||
{
|
||||
app.DebugPrintf("============== State %20s, Event %20s\n", getStateString(sm_state), getEventString(sm_event));
|
||||
}
|
||||
|
||||
|
||||
void SonyVoiceChat::setEvent( EAVCEvent event )
|
||||
{
|
||||
sm_event = event;
|
||||
printStateAndEvent();
|
||||
}
|
||||
|
||||
void SonyVoiceChat::setState( EAVCState state )
|
||||
{
|
||||
sm_state = state;
|
||||
printStateAndEvent();
|
||||
}
|
||||
Reference in New Issue
Block a user