the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2
3
4
5
6/* SCE CONFIDENTIAL
7PlayStation(R)3 Programmer Tool Runtime Library 430.001
8* Copyright (C) 2008 Sony Computer Entertainment Inc.
9* All Rights Reserved.
10*/
11#include "SonyVoiceChat.h"
12#include <arpa/inet.h> /* inet_ntoa() */
13
14/* for displaying extra information */
15#ifndef _CONTENT_PACKAGE
16#define AVC2_GAME_DEBUG
17#endif
18
19#ifdef AVC2_GAME_DEBUG
20#define INF(...) printf( "INF:" __VA_ARGS__ )
21#define ERR(...) printf( "ERR:" __VA_ARGS__ )
22#else
23#define INF(...)
24#define ERR(...)
25#endif
26
27#define UNUSED_VARIABLE(x) (void)(x)
28
29//#define DISABLE_VOICE_CHAT
30
31static CellSysutilAvc2InitParam g_chat_avc2param;
32
33EAVCEvent SonyVoiceChat::sm_event = AVC_EVENT_EPSILON;
34EAVCState SonyVoiceChat::sm_state = AVC_STATE_IDLE;
35SQRNetworkManager_PS3* SonyVoiceChat::sm_pNetworkManager;
36bool SonyVoiceChat::sm_bEnabled = true;
37uint8_t SonyVoiceChat::sm_micStatus = CELL_AVC2_MIC_STATUS_UNKNOWN;
38bool SonyVoiceChat::sm_bLoaded = false;
39bool SonyVoiceChat::sm_bUnloading = false;
40unordered_map<SceNpMatching2RoomMemberId, bool> SonyVoiceChat::sm_bTalkingMap;
41bool SonyVoiceChat::sm_bCanStart = false;
42bool SonyVoiceChat::sm_isChatRestricted = false;
43int SonyVoiceChat::sm_currentBitrate = 28000;
44
45void SonyVoiceChat::init( SQRNetworkManager_PS3* pNetMan )
46{
47 if(sm_state != AVC_STATE_IDLE)
48 return;
49
50 sm_pNetworkManager = pNetMan;
51 setState(AVC_STATE_CHAT_INIT);
52 ProfileManager.GetChatAndContentRestrictions(0,false,&sm_isChatRestricted,NULL,NULL);
53}
54
55void SonyVoiceChat::shutdown()
56{
57 if( sm_state == AVC_STATE_IDLE ||
58 sm_state == AVC_STATE_CHAT_LEAVE ||
59 sm_state == AVC_STATE_CHAT_UNLOAD ||
60 sm_state == AVC_STATE_CHAT_RESET )
61 {
62 // we're either shut down already, or in the process
63 return;
64 }
65
66 setEvent(AVC_EVENT_EXIT_GAME);
67}
68
69void SonyVoiceChat::setEnabled( bool bEnabled )
70{
71 if(sm_bEnabled != bEnabled)
72 {
73 if(sm_bCanStart)
74 {
75 if(bEnabled)
76 startStream();
77 else
78 stopStream();
79 }
80 sm_bEnabled = bEnabled;
81 }
82}
83
84
85int SonyVoiceChat::eventcb_load(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
86{
87 int ret = CELL_OK;
88
89 UNUSED_VARIABLE( event_param );
90 UNUSED_VARIABLE( userdata );
91
92 if( event_id == CELL_AVC2_EVENT_LOAD_SUCCEEDED )
93 {
94 INF( "<AVC CB>CELL_AVC2_EVENT_LOAD_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
95 setEvent(AVC_EVENT_CHAT_LOAD_SUCCEEDED);
96 sm_bLoaded = true;
97
98 // set the packet contention value here
99 CellSysutilAvc2Attribute attr;
100 memset( &attr, 0x00, sizeof(attr) );
101 attr.attr_id = CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_PACKET_CONTENTION;
102 attr.attr_param.int_param = 3;
103 int ret = cellSysutilAvc2SetAttribute(&attr);
104 if( ret != CELL_OK )
105 {
106 app.DebugPrintf("CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_PACKET_CONTENTION failed !!! 0x%08x\n", ret);
107 }
108
109 }
110 else /* if( event_id == CELL_AVC2_EVENT_LOAD_FAILED ) */
111 {
112 INF( "<AVC CB>CELL_AVC2_EVENT_LOAD_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
113 setEvent(AVC_EVENT_CHAT_LOAD_FAILED);
114 }
115 return ret;
116}
117
118int SonyVoiceChat::eventcb_join(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
119{
120 int ret = CELL_OK;
121
122 UNUSED_VARIABLE( event_param );
123 UNUSED_VARIABLE( userdata );
124
125 if( event_id == CELL_AVC2_EVENT_JOIN_SUCCEEDED )
126 {
127 INF( "<AVC CB>CELL_AVC2_EVENT_JOIN_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
128 setEvent(AVC_EVENT_CHAT_JOIN_SUCCEEDED);
129 }
130 else /* if( event_id == CELL_AVC2_EVENT_JOIN_FAILED ) */
131 {
132 INF( "<AVC CB>CELL_AVC2_EVENT_JOIN_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
133 setEvent(AVC_EVENT_ERROR);
134 }
135 sm_bTalkingMap.clear();
136 return ret;
137}
138
139int SonyVoiceChat::eventcb_leave( CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
140{
141 int ret = CELL_OK;
142
143 UNUSED_VARIABLE( event_param );
144 UNUSED_VARIABLE( userdata );
145
146 if( event_id == CELL_AVC2_EVENT_LEAVE_SUCCEEDED )
147 {
148 INF( "<AVC CB>CELL_AVC2_EVENT_LEAVE_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
149 setState(AVC_STATE_CHAT_LEAVE);
150 setEvent(AVC_EVENT_CHAT_LEAVE_SUCCEEDED);
151 }
152 else /* if( event_id == CELL_AVC2_EVENT_LEAVE_FAILED ) */
153 {
154 INF( "<AVC CB>CELL_AVC2_EVENT_LEAVE_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
155 setState(AVC_STATE_CHAT_LEAVE);
156 setEvent(AVC_EVENT_ERROR);
157 }
158 return ret;
159}
160
161int SonyVoiceChat::eventcb_unload(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
162{
163 int ret = CELL_OK;
164
165 UNUSED_VARIABLE( event_param );
166 UNUSED_VARIABLE( userdata );
167
168 if( event_id == CELL_AVC2_EVENT_UNLOAD_SUCCEEDED )
169 {
170 INF( "<AVC CB>CELL_AVC2_EVENT_UNLOAD_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param );
171 setEvent(AVC_EVENT_CHAT_UNLOAD_SUCCEEDED);
172 sm_bLoaded = false;
173 sm_bUnloading = false;
174 }
175 else /* if( event_id == CELL_AVC2_EVENT_UNLOAD_FAILED ) */
176 {
177 INF( "<AVC CB>CELL_AVC2_EVENT_UNLOAD_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param );
178 setEvent(AVC_EVENT_ERROR);
179 }
180 return ret;
181}
182
183int SonyVoiceChat::eventcb_voiceDetected(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
184{
185 UNUSED_VARIABLE( userdata );
186
187// To the upper 32 bits, the room member ID of the player is passed.
188// In the lower 32 bits, a value of 0 (mute) or a value between 1 (low volume)
189// and 10 (high volume) is passed as the audio signal value when the notification
190// method is the level method, or a value of 1 (start of speaking) or 0 (end of speaking)
191// is stored when the notification method is the trigger method.
192
193 SceNpMatching2RoomMemberId roomMemberID = (SceNpMatching2RoomMemberId)(event_param >> 32);
194 uint32_t volume = (uint32_t)(event_param & 0xffffffff);
195
196// The precision of voice detection is not very high. Since the audio signal values may
197// always be relatively high depending on the audio input device and the noise level in the
198// room, you should set a large reference value for determining whether or not a player is
199// speaking. Relatively good results can be obtained when an audio signal value of at
200// least 9 is used to determine if a player is speaking.
201 bool bTalking = false;
202 if(volume >= 9)
203 bTalking = true;
204
205 sm_bTalkingMap[roomMemberID] = bTalking;
206 return CELL_OK;
207}
208
209/* Callback function for handling AV Chat2 Utility events */
210void SonyVoiceChat::eventcb( CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata)
211{
212 static struct _cb_func_tbl
213 {
214 CellSysutilAvc2EventId event;
215 int (*func)( CellSysutilAvc2EventId event_id,
216 CellSysutilAvc2EventParam event_param,
217 void *userdata );
218 } event_tbl[] =
219 {
220 { CELL_AVC2_EVENT_LOAD_SUCCEEDED, eventcb_load },
221 { CELL_AVC2_EVENT_LOAD_FAILED, eventcb_load },
222 { CELL_AVC2_EVENT_JOIN_SUCCEEDED, eventcb_join },
223 { CELL_AVC2_EVENT_JOIN_FAILED, eventcb_join },
224 { CELL_AVC2_EVENT_LEAVE_SUCCEEDED, eventcb_leave },
225 { CELL_AVC2_EVENT_LEAVE_FAILED, eventcb_leave },
226 { CELL_AVC2_EVENT_UNLOAD_SUCCEEDED, eventcb_unload },
227 { CELL_AVC2_EVENT_UNLOAD_FAILED, eventcb_unload },
228 { CELL_AVC2_EVENT_SYSTEM_NEW_MEMBER_JOINED, NULL },
229 { CELL_AVC2_EVENT_SYSTEM_MEMBER_LEFT, NULL },
230 { CELL_AVC2_EVENT_SYSTEM_SESSION_ESTABLISHED, NULL },
231 { CELL_AVC2_EVENT_SYSTEM_SESSION_CANNOT_ESTABLISHED,NULL },
232 { CELL_AVC2_EVENT_SYSTEM_SESSION_DISCONNECTED, NULL },
233 { CELL_AVC2_EVENT_SYSTEM_VOICE_DETECTED, eventcb_voiceDetected },
234
235 };
236
237 int ret = 0;
238 for( unsigned int i=0; i<sizeof(event_tbl)/sizeof(struct _cb_func_tbl) ; ++i )
239 {
240 if( event_tbl[ i ].event == event_id && event_tbl[ i ].func )
241 {
242 ret = (*event_tbl[ i ].func)( event_id, event_param, userdata );
243 if( ret < 0 )
244 {
245 ERR("ret=0x%x\n", ret );
246 }
247 break;
248 }
249 }
250}
251
252int SonyVoiceChat::load()
253{
254 int ret = CELL_OK;
255 INF("----------------------------\n");
256 INF("| cellSysutilAvc2LoadAsync |\n");
257 INF("----------------------------\n");
258 ret = cellSysutilAvc2LoadAsync( sm_pNetworkManager->m_matchingContext,
259 SYS_MEMORY_CONTAINER_ID_INVALID,
260 eventcb,
261 NULL,
262 &g_chat_avc2param );
263 if( ret != CELL_OK )
264 {
265 ERR( "cellSysutilAvc2LoadAsync: ret=0x%x\n", ret );
266 setEvent(AVC_EVENT_ERROR);
267 return ret;
268 }
269 return ret;
270}
271
272int SonyVoiceChat::join()
273{
274 int ret = CELL_OK;
275
276 INF("---------------------------------------------------\n");
277 INF("| cellSysutilAvc2JoinChatRequest \n");
278 INF("---------------------------------------------------\n");
279 ret = cellSysutilAvc2JoinChatRequest( &sm_pNetworkManager->m_room );
280 if( ret != CELL_OK )
281 {
282 ERR( "cellSysutilAvc2JoinChatRequest: ret=0x%x\n", ret );
283 setEvent(AVC_EVENT_ERROR);
284 return ret;
285 }
286 return ret;
287}
288
289int SonyVoiceChat::leave()
290{
291 int ret = CELL_OK;
292
293 INF("-----------------------------------\n");
294 INF("| cellSysutilAvc2LeaveChatRequest |\n");
295 INF("-----------------------------------\n");
296 ret = cellSysutilAvc2LeaveChatRequest();
297 if( ret != CELL_OK )
298 {
299 ERR( "cellSysutilAvc2LeaveChatRequest() = 0x%x\n", ret );
300 setEvent(AVC_EVENT_ERROR);
301 return ret;
302 }
303 return ret;
304}
305
306int SonyVoiceChat::unload()
307{
308 int ret = CELL_OK;
309
310 INF("------------------------------\n");
311 INF("| cellSysutilAvc2UnloadAsync |\n");
312 INF("------------------------------\n");
313
314 ret = cellSysutilAvc2UnloadAsync();
315 if( ret != CELL_OK )
316 {
317 ERR( "cellSysutilAvcUnloadAsync() = 0x%x\n", ret );
318 setEvent(AVC_EVENT_ERROR);
319 return ret;
320 }
321 sm_bUnloading = true;
322 return ret;
323}
324
325int SonyVoiceChat::start()
326{
327 sm_bCanStart = (sm_isChatRestricted == false);
328
329 int ret = CELL_OK;
330 if(sm_bEnabled)
331 ret = startStream();
332
333 return ret;
334}
335
336int SonyVoiceChat::stop()
337{
338 sm_bCanStart = false;
339
340 int ret = CELL_OK;
341 if(sm_bEnabled)
342 ret = stopStream();
343
344 setEvent(AVC_EVENT_CHAT_SESSION_STOPPED);
345
346
347 return ret;
348}
349
350int SonyVoiceChat::startStream()
351{
352 int ret = CELL_OK;
353
354 INF("---------------------------------\n");
355 INF("| cellSysutilAvc2StartStreaming |\n");
356 INF("---------------------------------\n");
357 ret = cellSysutilAvc2StartStreaming();
358 if( ret != CELL_OK )
359 {
360 ERR( "cellSysutilAvc2StartStreaming: ret=0x%x\n", ret );
361 }
362
363 ret = cellSysutilAvc2StartVoiceDetection();
364 if( ret != CELL_OK )
365 {
366 ERR( "cellSysutilAvc2StartVoiceDetection: ret=0x%x\n", ret );
367 }
368 return ret;
369}
370
371int SonyVoiceChat::stopStream()
372{
373 int ret = cellSysutilAvc2StopVoiceDetection();
374 if( ret != CELL_OK )
375 {
376 ERR( "cellSysutilAvc2StopVoiceDetection: ret=0x%x\n", ret );
377 }
378
379 INF("--------------------------------\n");
380 INF("| cellSysutilAvc2StopStreaming |\n");
381 INF("--------------------------------\n");
382 ret = cellSysutilAvc2StopStreaming();
383 if( ret != CELL_OK )
384 {
385 ERR( "cellSysutilAvc2StopStreaming: ret=0x%x\n", ret );
386 }
387 return ret;
388}
389
390int SonyVoiceChat::initialize(void)
391{
392 int ret;
393
394 /* Must use cellSysutilAvc2InitParam() for clearing CellSysutilAvc2InitParam struct*/
395 ret = cellSysutilAvc2InitParam(CELL_SYSUTIL_AVC2_INIT_PARAM_VERSION, &g_chat_avc2param);
396 if( ret != CELL_OK )
397 {
398 ERR( "cellSysutilAvc2InitParam failed (0x%x)\n", ret );
399 return ret;
400 }
401
402 /* Setting application specific parameters */
403 g_chat_avc2param.media_type = CELL_SYSUTIL_AVC2_VOICE_CHAT;
404 g_chat_avc2param.max_players = AVC2_PARAM_DEFAULT_MAX_PLAYERS;
405 g_chat_avc2param.voice_param.voice_quality = CELL_SYSUTIL_AVC2_VOICE_QUALITY_NORMAL;
406 g_chat_avc2param.voice_param.max_speakers = AVC2_PARAM_DEFAULT_MAX_SPEAKERS;
407 g_chat_avc2param.spu_load_average = 50;
408 g_chat_avc2param.streaming_mode.mode = CELL_SYSUTIL_AVC2_STREAMING_MODE_NORMAL;
409
410 setEvent(AVC_EVENT_CHAT_INIT_SUCCEEDED);
411 setState(AVC_STATE_CHAT_INIT);
412
413 return ret;
414}
415
416int SonyVoiceChat::finalize(void)
417{
418 setEvent(AVC_EVENT_CHAT_FINALIZE_SUCCEEDED);
419 return CELL_OK;
420}
421
422void SonyVoiceChat::tick()
423{
424#ifdef DISABLE_VOICE_CHAT
425 return;
426#endif
427
428 static state_transition_table tbl[] =
429 {
430 /* now state event func after the transition state */
431 { AVC_STATE_CHAT_INIT, AVC_EVENT_EPSILON, initialize, AVC_STATE_CHAT_INIT },
432 { AVC_STATE_CHAT_INIT, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
433 { AVC_STATE_CHAT_INIT, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
434 { AVC_STATE_CHAT_INIT, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
435 { AVC_STATE_CHAT_INIT, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
436 { AVC_STATE_CHAT_INIT, AVC_EVENT_CHAT_INIT_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_LOAD },
437 { AVC_STATE_CHAT_INIT, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_RESET },
438
439 { AVC_STATE_CHAT_LOAD, AVC_EVENT_EPSILON, load, AVC_STATE_CHAT_LOAD },
440 { AVC_STATE_CHAT_LOAD, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
441 { AVC_STATE_CHAT_LOAD, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
442 { AVC_STATE_CHAT_LOAD, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
443 { AVC_STATE_CHAT_LOAD, AVC_EVENT_CHAT_LOAD_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_JOIN },
444 { AVC_STATE_CHAT_LOAD, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_RESET },
445
446 { AVC_STATE_CHAT_JOIN, AVC_EVENT_EPSILON, join, AVC_STATE_CHAT_JOIN },
447 { AVC_STATE_CHAT_JOIN, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
448 { AVC_STATE_CHAT_JOIN, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
449 { AVC_STATE_CHAT_JOIN, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
450 { AVC_STATE_CHAT_JOIN, AVC_EVENT_CHAT_JOIN_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_SESSION_PROCESSING },
451 { AVC_STATE_CHAT_JOIN, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
452
453 { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_EPSILON, start, AVC_STATE_CHAT_SESSION_PROCESSING },
454 { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_EXIT_GAME, stop, AVC_STATE_CHAT_SESSION_PROCESSING },
455 { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_ERROR, stop, AVC_STATE_CHAT_SESSION_PROCESSING },
456 { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_LAN_DISCONNECT, stop, AVC_STATE_CHAT_SESSION_PROCESSING },
457 { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_CHAT_SESSION_STOPPED, invoke_epsilon_event, AVC_STATE_CHAT_LEAVE },
458 { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,stop, AVC_STATE_CHAT_SESSION_PROCESSING },
459
460 { AVC_STATE_CHAT_LEAVE, AVC_EVENT_EPSILON, leave, AVC_STATE_CHAT_LEAVE },
461 { AVC_STATE_CHAT_LEAVE, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
462 { AVC_STATE_CHAT_LEAVE, AVC_EVENT_CHAT_LEAVE_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD },
463
464 { AVC_STATE_CHAT_UNLOAD, AVC_EVENT_EPSILON, unload, AVC_STATE_CHAT_UNLOAD },
465 { AVC_STATE_CHAT_UNLOAD, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
466 { AVC_STATE_CHAT_UNLOAD, AVC_EVENT_CHAT_UNLOAD_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_RESET },
467
468 { AVC_STATE_CHAT_RESET, AVC_EVENT_EPSILON, finalize, AVC_STATE_CHAT_RESET },
469 { AVC_STATE_CHAT_RESET, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_LEAVE },
470 { AVC_STATE_CHAT_RESET, AVC_EVENT_CHAT_FINALIZE_SUCCEEDED, invoke_epsilon_event, AVC_STATE_IDLE },
471
472 };
473 do_state_transition( &tbl[0], sizeof( tbl ) / sizeof( state_transition_table ) );
474
475 setBitRate();
476}
477
478
479
480void SonyVoiceChat::do_state_transition( state_transition_table *tbl, int tbl_size )
481{
482 int ret = CELL_OK;
483
484// if( sm_event == AVC_EVENT_LAN_DISCONNECT ||
485// sm_event == AVC_EVENT_EXIT_GAME ||
486// sm_event == AVC_EVENT_ERROR ||
487// sm_event == AVC_EVENT_FATAL_ERROR )
488// {
489// g_gamedata.finalize = 1;
490// }
491// if( sm_event == AVC_EVENT_FATAL_ERROR )
492// {
493// g_gamedata.exit = true;
494// }
495 bool bCalledFunc = false;
496 for( int i = 0; i < tbl_size; i++ )
497 {
498 if( sm_state == ( tbl + i )->state )
499 {
500 if( sm_event == ( tbl + i )->event )
501 {
502 sm_event = AVC_EVENT_NON;
503 ret = (*( tbl + i )->func)();
504 bCalledFunc = true;
505 if( ret != CELL_OK )
506 {
507 ERR("ret = 0x%x\n", ret );
508 }
509
510 setState(( tbl + i )->new_state);
511 break;
512 }
513 }
514 }
515 if(bCalledFunc == false)
516 {
517 assert( (sm_event == AVC_EVENT_NON) ||
518 (sm_state == AVC_STATE_IDLE && sm_event == AVC_EVENT_EPSILON) );
519 }
520}
521
522int SonyVoiceChat::invoke_epsilon_event(void)
523{
524 setEvent(AVC_EVENT_EPSILON);
525
526 return CELL_OK;
527}
528
529
530bool SonyVoiceChat::hasMicConnected(const SceNpMatching2RoomMemberId *players_id)
531{
532 CellSysutilAvc2PlayerInfo players_info;
533 int err = cellSysutilAvc2GetPlayerInfo(players_id, &players_info);
534 if(err == CELL_OK)
535 {
536 if(players_info.connected && players_info.joined)
537 {
538 if(players_info.mic_attached == CELL_AVC2_MIC_STATUS_ATTACHED_ON)
539 return true;
540 }
541 }
542
543 return false;
544}
545
546void SonyVoiceChat::mute( bool bMute )
547{
548 if(sm_bLoaded && !sm_bUnloading)
549 {
550 int err = cellSysutilAvc2SetVoiceMuting(bMute);
551 assert(err == CELL_OK);
552 }
553}
554
555void SonyVoiceChat::mutePlayer( const SceNpMatching2RoomMemberId member_id, bool bMute ) /*Turn chat audio from a specified player on or off */
556{
557 if(sm_bLoaded && !sm_bUnloading)
558 {
559 int err = cellSysutilAvc2SetPlayerVoiceMuting(member_id, bMute);
560 assert(err == CELL_OK);
561 }
562}
563
564void SonyVoiceChat::muteLocalPlayer( bool bMute ) /*Turn microphone input on or off */
565{
566 if(sm_bLoaded && !sm_bUnloading)
567 {
568 int err = cellSysutilAvc2SetVoiceMuting(bMute);
569 assert(err == CELL_OK);
570 }
571}
572
573
574bool SonyVoiceChat::isMuted()
575{
576 if(sm_bLoaded && !sm_bUnloading)
577 {
578 uint8_t bMute;
579 int err = cellSysutilAvc2GetVoiceMuting(&bMute);
580 assert(err == CELL_OK);
581 return bMute;
582 }
583 return false;
584}
585
586bool SonyVoiceChat::isMutedPlayer( const SceNpMatching2RoomMemberId member_id)
587{
588 if(sm_bLoaded && !sm_bUnloading)
589 {
590 uint8_t bMute;
591 int err = cellSysutilAvc2GetPlayerVoiceMuting(member_id, &bMute);
592 assert(err == CELL_OK);
593 return bMute;
594 }
595 return false;
596}
597
598bool SonyVoiceChat::isMutedLocalPlayer()
599{
600 if(sm_bLoaded && !sm_bUnloading)
601 {
602 uint8_t bMute;
603 int err = cellSysutilAvc2GetVoiceMuting(&bMute);
604 assert(err == CELL_OK);
605 return bMute;
606 }
607 return false;
608}
609
610void SonyVoiceChat::setVolume( float vol )
611{
612 if(sm_bLoaded && !sm_bUnloading)
613 {
614 // The volume level can be set to a value in the range 0.0 to 40.0.
615 // Volume levels are linear values such that if 1.0 is specified, the
616 // volume level will be 1 times the reference power (0dB), and if 0.5
617 // is specified, the volume level will be 0.5 times the reference power
618 // (-6dB). If 0.0 is specified, chat audio will no longer be audible.
619
620 int err =cellSysutilAvc2SetSpeakerVolumeLevel(vol * 40.0f);
621 assert(err==CELL_OK);
622 }
623}
624
625float SonyVoiceChat::getVolume()
626{
627 if(sm_bLoaded && !sm_bUnloading)
628 {
629 float vol;
630 int err = cellSysutilAvc2GetSpeakerVolumeLevel(&vol);
631 assert(err == CELL_OK);
632 return (vol / 40.0f);
633 }
634 return 0;
635}
636
637bool SonyVoiceChat::isTalking( SceNpMatching2RoomMemberId* players_id )
638{
639 AUTO_VAR(it, sm_bTalkingMap.find(*players_id));
640 if (it != sm_bTalkingMap.end() )
641 return it->second;
642 return false;
643}
644
645void SonyVoiceChat::setBitRate()
646{
647 if(sm_state != AVC_STATE_CHAT_SESSION_PROCESSING)
648 return;
649
650 int numPlayers = sm_pNetworkManager->GetPlayerCount();
651// This internal attribute represents the maximum voice bit rate. attr_param
652// is an integer value. The units are bps, and the specifiable values are
653// 4000, 8000, 16000, 20000, 24000, and 28000. The initial value is 28000.
654
655 static int bitRates[8] = { 28000, 28000,
656 28000, 28000,
657 24000, 20000,
658 16000, 16000};
659 int bitRate = bitRates[numPlayers-1];
660 if(bitRate == sm_currentBitrate)
661 return;
662
663 CellSysutilAvc2Attribute attr;
664 memset( &attr, 0x00, sizeof(attr) );
665 attr.attr_id = CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_MAX_BITRATE;
666 attr.attr_param.int_param = bitRate;
667 int ret = cellSysutilAvc2SetAttribute(&attr);
668 if( ret == CELL_OK )
669 {
670 sm_currentBitrate = bitRate;
671 }
672 else
673 {
674 app.DebugPrintf("SonyVoiceChat::setBitRate failed !!! 0x%08x\n", ret);
675 }
676}
677
678
679
680#define CASE_STR_VALUE(s) case s: return #s;
681
682const char* getStateString(EAVCState state)
683{
684
685 switch(state)
686 {
687
688 CASE_STR_VALUE(AVC_STATE_IDLE);
689 CASE_STR_VALUE(AVC_STATE_CHAT_INIT)
690 CASE_STR_VALUE(AVC_STATE_CHAT_LOAD);
691 CASE_STR_VALUE(AVC_STATE_CHAT_JOIN);
692 CASE_STR_VALUE(AVC_STATE_CHAT_SESSION_PROCESSING);
693 CASE_STR_VALUE(AVC_STATE_CHAT_LEAVE);
694 CASE_STR_VALUE(AVC_STATE_CHAT_RESET);
695 CASE_STR_VALUE(AVC_STATE_CHAT_UNLOAD);
696 CASE_STR_VALUE(AVC_STATE_EXIT);
697 default:
698 return "unknown state";
699 }
700}
701
702const char* getEventString(EAVCEvent state)
703{
704 switch(state)
705 {
706 CASE_STR_VALUE(AVC_EVENT_NON);
707 CASE_STR_VALUE(AVC_EVENT_EPSILON);
708 CASE_STR_VALUE(AVC_EVENT_LAN_DISCONNECT);
709 CASE_STR_VALUE(AVC_EVENT_ONLINE);
710 CASE_STR_VALUE(AVC_EVENT_OFFLINE);
711 CASE_STR_VALUE(AVC_EVENT_EXIT_GAME);
712 CASE_STR_VALUE(AVC_EVENT_ROOM_CREATE);
713 CASE_STR_VALUE(AVC_EVENT_ROOM_SEARCH);
714 CASE_STR_VALUE(AVC_EVENT_ERROR);
715 CASE_STR_VALUE(AVC_EVENT_FATAL_ERROR);
716 CASE_STR_VALUE(AVC_EVENT_NETDIALOG_FINISHED);
717 CASE_STR_VALUE(AVC_EVENT_NETDIALOG_UNLOADED);
718 CASE_STR_VALUE(AVC_EVENT_NP2_INIT_SUCCEEDED);
719 CASE_STR_VALUE(AVC_EVENT_NP2_FINALIZE_SUCCEEDED);
720 CASE_STR_VALUE(AVC_EVENT_NP2_START_CONTEXT_SUCCEEDED);
721 CASE_STR_VALUE(AVC_EVENT_NP2_STOP_CONTEXT_SUCCEEDED);
722 CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT);
723 CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_MEMBER_LEFT);
724 CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_MEMBER_JOINED);
725 CASE_STR_VALUE(AVC_EVENT_CHAT_LOAD_SUCCEEDED);
726 CASE_STR_VALUE(AVC_EVENT_CHAT_LOAD_FAILED);
727 CASE_STR_VALUE(AVC_EVENT_CHAT_JOIN_SUCCEEDED);
728 CASE_STR_VALUE(AVC_EVENT_CHAT_JOIN_FAILED);
729 CASE_STR_VALUE(AVC_EVENT_CHAT_LEAVE_SUCCEEDED);
730 CASE_STR_VALUE(AVC_EVENT_CHAT_LEAVE_FAILED);
731 CASE_STR_VALUE(AVC_EVENT_CHAT_UNLOAD_SUCCEEDED);
732 CASE_STR_VALUE(AVC_EVENT_CHAT_UNLOAD_FAILED);
733 CASE_STR_VALUE(AVC_EVENT_CHAT_INIT_SUCCEEDED);
734 CASE_STR_VALUE(AVC_EVENT_CHAT_FINALIZE_SUCCEEDED);
735 CASE_STR_VALUE(AVC_EVENT_CHAT_SESSION_STOPPED);
736 CASE_STR_VALUE(AVC_EVENT_CREATE_JOIN_ROOM_SUCCEEDED);
737 CASE_STR_VALUE(AVC_EVENT_SEARCH_ROOM_SUCCEEDED);
738 CASE_STR_VALUE(AVC_EVENT_JOIN_ROOM_SUCCEEDED);
739 CASE_STR_VALUE(AVC_EVENT_LEAVE_ROOM_SUCCEEDED);
740 CASE_STR_VALUE(AVC_EVENT_SIGNALING_ESTABLISHED);
741 CASE_STR_VALUE(AVC_EVENT_SIGNALING_DEAD);
742 CASE_STR_VALUE(AVC_EVENT_UI_CLOSE_SUCCEEDED);
743 default:
744 return "unknown event";
745 }
746}
747
748void SonyVoiceChat::printStateAndEvent()
749{
750 app.DebugPrintf("============== State %20s, Event %20s\n", getStateString(sm_state), getEventString(sm_event));
751}
752
753
754void SonyVoiceChat::setEvent( EAVCEvent event )
755{
756 sm_event = event;
757 printStateAndEvent();
758}
759
760void SonyVoiceChat::setState( EAVCState state )
761{
762 sm_state = state;
763 printStateAndEvent();
764}