aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/PS3/Network/SonyVoiceChat.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/PS3/Network/SonyVoiceChat.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.Client/PS3/Network/SonyVoiceChat.cpp')
-rw-r--r--Minecraft.Client/PS3/Network/SonyVoiceChat.cpp764
1 files changed, 764 insertions, 0 deletions
diff --git a/Minecraft.Client/PS3/Network/SonyVoiceChat.cpp b/Minecraft.Client/PS3/Network/SonyVoiceChat.cpp
new file mode 100644
index 00000000..721ddf26
--- /dev/null
+++ b/Minecraft.Client/PS3/Network/SonyVoiceChat.cpp
@@ -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();
+}