Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save sathyarajshetigar/30de50a2b7da315e1a6ae118b995d0f3 to your computer and use it in GitHub Desktop.

Select an option

Save sathyarajshetigar/30de50a2b7da315e1a6ae118b995d0f3 to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using IjsUiFramework;
using UnityEngine;
using UnityEngine.Android;
using VivoxUnity;
[System.Serializable]
public class VivoxConfig
{
[SerializeField]
private string _server = "https://GETFROMPORTAL.www.vivox.com/api2";
[SerializeField]
private string _domain = "GET VALUE FROM VIVOX DEVELOPER PORTAL";
[SerializeField]
private string _tokenIssuer = "GET VALUE FROM VIVOX DEVELOPER PORTAL";
[SerializeField]
private string _tokenKey = "GET VALUE FROM VIVOX DEVELOPER PORTAL";
public Uri serverURI => new Uri(_server);
public string server => _server;
public string domain => _domain;
public string tokenIssuer => _tokenIssuer;
public string tokenKey => _tokenKey;
public VivoxConfig(string server, string domain, string tokenIssuer, string tokenKey)
{
_server = server;
_domain = domain;
_tokenIssuer = tokenIssuer;
_tokenKey = tokenKey;
}
}
public class VivoxVoiceManager : MonoBehaviour
{
#region Enums
/// <summary>
/// Defines properties that can change. Used by the functions that subscribe to the OnAfterTYPEValueUpdated functions.
/// </summary>
public enum ChangedProperty
{
None,
Speaking,
Typing,
Muted
}
public enum ChatCapability
{
TextOnly,
AudioOnly,
TextAndAudio
};
public enum MatchStatus
{
Open,
Closed
}
#endregion
#region Delegates/Events
public delegate void ParticipantValueChangedHandler(string username, ChannelId channel, bool value);
public static event ParticipantValueChangedHandler OnSpeechDetectedEvent;
public static event ParticipantValueChangedHandler OnAudioEnergyChangedEvent;
public delegate void ParticipantStatusChangedHandler(string username, ChannelId channel, IParticipant participant);
public static event ParticipantStatusChangedHandler OnParticipantAddedEvent;
public static event ParticipantStatusChangedHandler OnParticipantRemovedEvent;
public delegate void ChannelTextMessageChangedHandler(string sender, IChannelTextMessage channelTextMessage);
public static event ChannelTextMessageChangedHandler OnTextMessageLogReceivedEvent;
public delegate void SessionArchiveMessageChangedHandler(string sender, ISessionArchiveMessage channelTextMessage);
public static event SessionArchiveMessageChangedHandler OnSessionArchiveMessageReceivedEvent;
public delegate void LoginStatusChangedHandler();
public static event LoginStatusChangedHandler OnUserLoggedInEvent;
public static event LoginStatusChangedHandler OnUserLoggedOutEvent;
#endregion
#region Member Variables
private VivoxConfig _config;
private TimeSpan _tokenExpiration = TimeSpan.FromSeconds(90);
private Client _client = new Client();
private AccountId _accountId;
private bool PermissionsDenied;
private IParticipant _localParticipant;
IChannelSession channelSession;
// Check to see if we're about to be destroyed.
private static object m_Lock = new object();
private static VivoxVoiceManager m_Instance;
/// <summary>
/// Access singleton instance through this propriety.
/// </summary>
public static VivoxVoiceManager Instance
{
get
{
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (VivoxVoiceManager)FindObjectOfType(typeof(VivoxVoiceManager));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<VivoxVoiceManager>();
singletonObject.name = typeof(VivoxVoiceManager).ToString() + " (Singleton)";
}
}
// Make instance persistent even if its already in the scene
DontDestroyOnLoad(m_Instance.gameObject);
return m_Instance;
}
}
}
public LoginState LoginState { get; private set; }
public ILoginSession loginSession;
public VivoxUnity.IReadOnlyDictionary<ChannelId, IChannelSession> ActiveChannels => loginSession?.ChannelSessions;
public IAudioDevices AudioInputDevices => _client.AudioInputDevices;
public IAudioDevices AudioOutputDevices => _client.AudioOutputDevices;
#endregion
#region Properties
/// <summary>
/// Retrieves the first instance of a session that is transmitting.
/// </summary>
public IChannelSession TransmittingSession
{
get
{
if (_client == null)
throw new NullReferenceException("client");
return _client.GetLoginSession(_accountId).ChannelSessions.FirstOrDefault(x => true);
}
set
{
if (value != null)
{
//value.IsTransmittingSession = true;
}
}
}
public IParticipant localParticipant => _localParticipant;
public bool isInitialized => _client?.Initialized ?? false;
public bool hasMicPermission
{
get
{
#if UNITY_ANDROID
return Permission.HasUserAuthorizedPermission(Permission.Microphone);
#elif UNITY_IOS
// return Application.HasUserAuthorization(UserAuthorization.Microphone);
//https://github.com/zhao1289/unityruntimepermissionplugin
PermissionSelf result = PermissionPluginForIOS.CheckPermission(PermissionType.Microphone);
Game.Log($"hasMicPermission {result}");
return result == PermissionSelf.Granted;
#else
return false;
#endif
}
}
#endregion
private void Awake()
{
if (m_Instance != null && m_Instance != this)
{
Game.Log("Multiple VivoxVoiceManager detected in the scene. Only one VivoxVoiceManager can exist at a time. The duplicate VivoxVoiceManager will be destroyed.");
Destroy(this);
return;
}
GameData gameData = GameSkinData.gameSkin.currentGameData;
_config = new VivoxConfig("https://mt2p.www.vivox.com/api2", "mt2p.vivox.com", "arvind2023-sk14", "WkGJPfylAz8bLmsSUhqGMa6rTCLvVwxV");
//_config = new VivoxConfig("https://mt2p.www.vivox.com/api2", "mt2p.vivox.com", "arvind1748-bu79", "Aa5lFVCEKl66hUyv6ceGacH1DT6EguYL");
//_config = new VivoxConfig("https://mt1s.www.vivox.com/api2", "mt1s.vivox.com", "arvind1748-bu79-dev", "java456"); // sandbox - Business
//_config = new VivoxConfig("https://mt1p.www.vivox.com/api2", "mt1p.vivox.com", "arvind1748-ba20", "yBs0f0plJz7XirNnu1sc0za0WXKNFs9B");
//_config = new VivoxConfig("https://mt1s.www.vivox.com/api2", "mt1s.vivox.com", "arvind1748-ba20-dev", "buzz086"); // sandBox
//_config = new VivoxConfig("https://vdx5.www.vivox.com/api2", "vdx5.vivox.com", "arvind1748-ba40-dev", "maze382"); // battleship
//_config = new VivoxConfig(gameData.vivoxServer, gameData.vivoxDomain, gameData.vivoxTokenIssuer, gameData.vivoxTokenKey);
#if UNITY_ANDROID && !UNITY_EDITOR
// Initialize the VivoxNative module
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject appContext = activity.Call<AndroidJavaObject>("getApplicationContext");
AndroidJavaClass pluginClass = new AndroidJavaClass("com.vivox.vivoxnative.VivoxNative");
pluginClass.CallStatic("init", appContext);
#endif
}
public SkyjoGameManager SkyjoGame;
/// <summary>
/// Init Vivxo when private game starts
/// </summary>
public void Init(SkyjoGameManager skyjoGame)
{
Game.Log($"Vivox Init......................");
#if UNITY_EDITOR
return;
#endif
SkyjoGame = skyjoGame;
InitService();
LoginToVivoxService();
mutedWhenPaused = false;
}
private void InitService()
{
if (_config.serverURI.ToString() == "https://GETFROMPORTAL.www.vivox.com/api2" ||
_config.domain == "GET VALUE FROM VIVOX DEVELOPER PORTAL" ||
_config.tokenKey == "GET VALUE FROM VIVOX DEVELOPER PORTAL" ||
_config.tokenIssuer == "GET VALUE FROM VIVOX DEVELOPER PORTAL")
{
Game.Log("Vivox. The default VivoxVoiceServer values (Server, Domain, TokenIssuer, and TokenKey) must be replaced with application specific issuer and key values from your developer account.");
}
_client?.Uninitialize();
if (_client == null)
_client = new Client();
_client?.Initialize();
}
//public BankruptGameManager mGame;
/// <summary>
/// Check for permission before starting the game and get the permission if not granted
/// </summary>
public void CheckForPermission()
{
Game.Log($"CheckForPermission hasMicPermission {hasMicPermission}");
#if UNITY_ANDROID
if (!hasMicPermission)
{
//mGame.OnShowVoiceChatPermissionDialog();
//DialogBox.Show(Game.GetLocTxt(LKeys.ALERT), Game.GetLocTxt(LKeys.MICPER), Game.GetLocTxt(LKeys.ALLOW), Game.GetLocTxt(LKeys.CANCEL), (allow, cancel) =>
//{
// if (allow)
// {
// Permission.RequestUserPermission(Permission.Microphone);
// }
//});
}
#elif UNITY_IOS
PermissionSelf result = PermissionPluginForIOS.CheckPermission(PermissionType.Microphone);
if (result == PermissionSelf.ShouldAsk)
{
//mGame.ShowEnableChat();
//DialogBox.Show(Game.GetLocTxt(LKeys.ALERT), Game.GetLocTxt(LKeys.MICPER), Game.GetLocTxt(LKeys.ALLOW), Game.GetLocTxt(LKeys.CANCEL), (allow, cancel) =>
//{
// if (allow)
// {
//PermissionSelf res = PermissionPluginForIOS.RequestPermission(PermissionType.Microphone);
//Game.Log($"Res {res}");
//if (res == PermissionSelf.Denied)
// DialogBox.ShowToastMessage(Game.GetLocTxt(LKeys.ALLOWLATER));
// }
//});
}
#endif
}
private AndroidPermissionsUsageExample ChatCallBack;
public void AllowChat_iOS(AndroidPermissionsUsageExample callback)
{
ChatCallBack = callback;
#if UNITY_IOS
PermissionSelf res = PermissionPluginForIOS.RequestPermission(PermissionType.Microphone);
Debug.Log("Result: " + res);
StartCoroutine(CheckAfterAWhile());
#endif
}
#if UNITY_IOS
IEnumerator CheckAfterAWhile()
{
yield return new WaitForSeconds(1f);
PermissionSelf res = PermissionPluginForIOS.CheckPermission(PermissionType.Microphone);
if (res == PermissionSelf.Granted)
{
Debug.Log("Granted Voice chat");
ChatCallBack.SkyjoGame.OnGrantedPermission();
}
else if (res == PermissionSelf.Denied)
{
Debug.Log("Denied Voice chat");
ChatCallBack.SkyjoGame.OnUserDeniedPermission();
}
}
#endif
//System.Collections.IEnumerator ICheckForIOSPermission()
//{
// yield return Application.RequestUserAuthorization(UserAuthorization.Microphone);
// if (Application.HasUserAuthorization(UserAuthorization.Microphone))
// {
// Game.Log("Authorized");
// }
// else
// {
// Game.Log("Not Authorized");
// }
//}
private void LoginToVivoxService()
{
if (hasMicPermission)
{
// The user authorized use of the microphone.
TryLogin();
}
else
{
Game.Log("No mic permission");
Client.Cleanup();
_client?.Uninitialize();
_client = null;
}
//else
//{
// // Check if the users has already denied permissions
// if (PermissionsDenied)
// {
// PermissionsDenied = false;
// TryLogin();
// }
// else
// {
// PermissionsDenied = true;
// CheckForPermission();
// }
//}
}
private void TryLogin()
{
Login(PlayerProfile.playFabID, PlayerProfile.playFabID, (success) =>
{
Game.roomName = SkyjoGame.Photon.GetRoomName();// PhotonNetwork.room.Name;//.Photon.GetRoomName();
Game.Log($"Vivox. LoginCallback succes? {success} roomName {Game.roomName}");
if (success && !string.IsNullOrEmpty(Game.roomName))
JoinChannel(Game.roomName, ChannelType.NonPositional);
});
}
private void OnApplicationQuit()
{
// Needed to add this to prevent some unsuccessful uninit, we can revisit to do better -carlo
Client.Cleanup();
Game.Log("Vivox. Uninitializing client.");
_client?.Uninitialize();
_client = null;
}
int backgroundTaskID = -1;
bool mutedWhenPaused = false;
void OnApplicationPause(bool paused)
{
// Start the counter on pause
if (paused)
{
// Start a task that invokes once every second (1000 milliseconds)
//backgroundTaskID = Vuopaja.TaskInvoker.StartTask(1000, (_) =>
//{
// if (!PhotonManager.instance.inRoom)
// {
// Game.Log($"Logged out from vivox because player was disconnected from photon");
// try
// {
// Game.Log("Uninitializing client.");
// Logout();
// Client.Cleanup();
// _client?.Uninitialize();
// _client = null;
// }
// catch (Exception)
// {
// }
// }
//}, null);
//if (AudioInputDevices != null && AudioInputDevices.Muted == false)
//{
// mutedWhenPaused = true;
// ToggleMuteLocalPlayer(true);
//}
}
else
{
//if (AudioInputDevices != null && AudioInputDevices.Muted == true && mutedWhenPaused)
//{
// mutedWhenPaused = false;
// ToggleMuteLocalPlayer(false);
//}
//if (backgroundTaskID != -1)
// Vuopaja.TaskInvoker.StopTask(backgroundTaskID);
}
}
private void OnDestroy()
{
try
{
if (isInitialized)
Client.Cleanup();
Game.Log("Vivox. Uninitializing client.");
_client?.Uninitialize();
_client = null;
}
catch (Exception)
{
}
}
private void Login(string displayName = null, string uniqueID = null, Action<bool> callback = null)
{
Game.Log($"Vivox Login as {displayName} size {displayName.Length}");
//for proto purposes only, need to get a real token from server eventually
if (_client != null)
{
_accountId = new AccountId(_config.tokenIssuer, uniqueID, _config.domain, displayName);
loginSession = _client.GetLoginSession(_accountId);
loginSession.PropertyChanged += OnLoginSessionPropertyChanged;
loginSession.BeginLogin(_config.serverURI, loginSession.GetLoginToken(_config.tokenKey, _tokenExpiration), SubscriptionMode.Accept, null, null, null, ar =>
{
try
{
loginSession.EndLogin(ar);
callback?.Invoke(true);
}
catch (Exception e)
{
// Handle error
Game.Log(e.Message);
// Unbind if we failed to login.
loginSession.PropertyChanged -= OnLoginSessionPropertyChanged;
callback?.Invoke(false);
return;
}
});
}
}
/// <summary>
/// Logout when photon is disconneted. Dont leave the connection alive after the game is over
/// </summary>
public void Logout()
{
try
{
Debug.Log("Trying to log out");
if (loginSession != null && LoginState != LoginState.LoggedOut && LoginState != LoginState.LoggingOut)
{
OnUserLoggedOutEvent?.Invoke();
if (loginSession != null)
{
loginSession.PropertyChanged -= OnLoginSessionPropertyChanged;
loginSession.Logout();
Client.Cleanup();
_client?.Uninitialize();
_client = null;
Game.Log("Log out successful. Should be able to init again.");
}
}
}
catch (Exception e)
{
Game.Log("Caught an exception: " + e.ToString());
}
}
private void JoinChannel(string channelName, ChannelType channelType, Channel3DProperties properties = null)
{
Game.Log($"Vivox JoinChannel name {channelName}");
if (LoginState == LoginState.LoggedIn)
{
ChannelId channelId = new ChannelId(_config.tokenIssuer, channelName, _config.domain, channelType, properties);
channelSession = loginSession.GetChannelSession(channelId);
channelSession.PropertyChanged += OnChannelPropertyChanged;
channelSession.Participants.AfterKeyAdded += OnParticipantAdded;
channelSession.Participants.BeforeKeyRemoved += OnParticipantRemoved;
channelSession.Participants.AfterValueUpdated += OnParticipantValueUpdated;
channelSession.MessageLog.AfterItemAdded += OnMessageLogRecieved;
channelSession.SessionArchive.AfterItemAdded += OnSessionArchiveAdded;
channelSession.BeginConnect(true, false, true, channelSession.GetConnectToken(_config.tokenKey, _tokenExpiration), ar =>
{
try
{
channelSession.EndConnect(ar);
CacheAlreadyJoinedPlayers();
}
catch (Exception e)
{
// Handle error
Game.Log($"Vivox. Could not connect to voice channel: {e.Message}", LogType.Error);
return;
}
});
//channelSession.BeginConnect(chatCapability != ChatCapability.TextOnly, chatCapability != ChatCapability.AudioOnly, transmitPolicy, channelSession.GetConnectToken(_tokenKey, _tokenExpiration), ar =>
//{
// try
// {
// channelSession.EndConnect(ar);
// }
// catch (Exception e)
// {
// // Handle error
// Game.Log($"Could not connect to voice channel: {e.Message}", LogType.Error);
// return;
// }
//});
}
else
{
Game.Log("Vivox. Cannot join a channel when not logged in.", LogType.Error);
}
}
private void SendTextMessage(string messageToSend, ChannelId channel)
{
if (string.IsNullOrEmpty(messageToSend))
{
Game.Log("Vivox. Enter a valid message to send", LogType.Error);
return;
}
var channelSession = loginSession.GetChannelSession(channel);
channelSession.BeginSendText(messageToSend, ar =>
{
try
{
channelSession.EndSendText(ar);
}
catch (Exception e)
{
Game.Log($"Vivox. SendTextMessage failed with exception {e.Message}");
}
});
}
private void SendMatchStatusMessage(MatchStatus status, string playerIp, ChannelId channelId)
{
if (ChannelId.IsNullOrEmpty(channelId))
{
throw new ArgumentException(string.Format("{0} is null", channelId));
}
if (string.IsNullOrEmpty(playerIp))
{
throw new ArgumentException(string.Format("{0} cannot be empty", playerIp));
}
SendTextMessage(string.Format($"<{status.ToString()}>{_accountId.DisplayName}:{playerIp}"), channelId);
}
public void RunArchiveQueryInChannel(ChannelId channelId, DateTime? timeStart, DateTime? timeEnd,
string searchText = null, uint max = 50, string afterId = null, string beforeId = null, int firstMessageIndex = -1)
{
IChannelSession channelSession = loginSession.GetChannelSession(channelId);
var channelName = channelId.Name;
var senderName = _accountId.Name;
channelSession.BeginSessionArchiveQuery(timeStart, timeEnd, searchText, _accountId, max, afterId, beforeId, firstMessageIndex, ar =>
{
try
{
channelSession.EndSessionArchiveQuery(ar);
}
catch (Exception e)
{
// Handle error
Game.Log($"Vivox. Failed to get archive query for channel: {e.Message}", LogType.Error);
return;
}
Debug.Log(channelName + ": " + senderName + ": ");
});
}
private void DisconnectAllChannels()
{
if (ActiveChannels?.Count > 0)
{
foreach (var channelSession in ActiveChannels)
{
channelSession?.Disconnect();
}
}
}
#region Vivox Callbacks
private void OnMessageLogRecieved(object sender, QueueItemAddedEventArgs<IChannelTextMessage> textMessage)
{
Game.Log("Vivox. OnMessageLogRecieved");
ValidateArgs(new object[] { sender, textMessage });
IChannelTextMessage channelTextMessage = textMessage.Value;
Game.Log(channelTextMessage.Message);
OnTextMessageLogReceivedEvent?.Invoke(channelTextMessage.Sender.DisplayName, channelTextMessage);
}
private void OnSessionArchiveAdded(object sender, QueueItemAddedEventArgs<ISessionArchiveMessage> archiveMessage)
{
Game.Log("Vivox. OnSessionArchiveAdded");
ValidateArgs(new object[] { sender, archiveMessage });
ISessionArchiveMessage sessionArchiveMessage = archiveMessage.Value;
OnSessionArchiveMessageReceivedEvent?.Invoke(sessionArchiveMessage.Sender.DisplayName, sessionArchiveMessage);
}
private void OnLoginSessionPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
if (propertyChangedEventArgs.PropertyName != "State")
{
return;
}
var loginSession = (ILoginSession)sender;
LoginState = loginSession.State;
Game.Log("Vivox. Detecting login session change");
switch (LoginState)
{
case LoginState.LoggingIn:
{
Game.Log("Vivox. Logging in");
break;
}
case LoginState.LoggedIn:
{
Game.Log($"Vivox. Connected to voice server and logged in");
OnUserLoggedInEvent?.Invoke();
break;
}
case LoginState.LoggingOut:
{
Game.Log("Vivox. Logging out");
break;
}
case LoginState.LoggedOut:
{
Game.Log("Vivox. Logged out");
this.loginSession.PropertyChanged -= OnLoginSessionPropertyChanged;
break;
}
default:
break;
}
}
private void OnParticipantAdded(object sender, KeyEventArg<string> keyEventArg)
{
Game.Log($"Vivox. OnParticipantAdded sender {sender} Key {keyEventArg.Key}");
ValidateArgs(new object[] { sender, keyEventArg });
// INFO: sender is the dictionary that changed and trigger the event. Need to cast it back to access it.
var source = (VivoxUnity.IReadOnlyDictionary<string, IParticipant>)sender;
// Look up the participant via the key.
var participant = source[keyEventArg.Key];
var username = participant.Account.Name;
var channel = participant.ParentChannelSession.Key;
var channelSession = participant.ParentChannelSession;
Game.Log($"Vivox. OnParticipantAdded username {username}");
if (username.Equals(SystemInfo.deviceUniqueIdentifier))
_localParticipant = participant;
int playerIndex = SkyjoGame._players.FindIndex(p => p.playfabId == participant.Account.DisplayName);
SkyjoGame.CacheParticipant(playerIndex, participant);
// Trigger callback
OnParticipantAddedEvent?.Invoke(username, channel, participant);
}
private void OnParticipantRemoved(object sender, KeyEventArg<string> keyEventArg)
{
Game.Log($"Vivox. OnParticipantRemoved sender {sender}");
ValidateArgs(new object[] { sender, keyEventArg });
// INFO: sender is the dictionary that changed and trigger the event. Need to cast it back to access it.
var source = (VivoxUnity.IReadOnlyDictionary<string, IParticipant>)sender;
// Look up the participant via the key.
var participant = source[keyEventArg.Key];
var username = participant.Account.Name;
var channel = participant.ParentChannelSession.Key;
var channelSession = participant.ParentChannelSession;
Game.Log($"Vivox. OnParticipantRemoved participant {participant} IsSelf {participant.IsSelf}");
if (participant.IsSelf)
{
Game.Log($"Vivox. Unsubscribing from: {channelSession.Key.Name}");
// Now that we are disconnected, unsubscribe.
channelSession.PropertyChanged -= OnChannelPropertyChanged;
channelSession.Participants.AfterKeyAdded -= OnParticipantAdded;
channelSession.Participants.BeforeKeyRemoved -= OnParticipantRemoved;
channelSession.Participants.AfterValueUpdated -= OnParticipantValueUpdated;
channelSession.MessageLog.AfterItemAdded -= OnMessageLogRecieved;
channelSession.SessionArchive.AfterItemAdded -= OnSessionArchiveAdded;
// Remove session.
var user = _client.GetLoginSession(_accountId);
user.DeleteChannelSession(channelSession.Channel);
}
// Trigger callback
OnParticipantRemovedEvent?.Invoke(username, channel, participant);
}
private static void ValidateArgs(object[] objs)
{
foreach (var obj in objs)
{
if (obj == null)
throw new ArgumentNullException(obj.GetType().ToString(), "Specify a non-null/non-empty argument.");
}
}
private void OnParticipantValueUpdated(object sender, ValueEventArg<string, IParticipant> valueEventArg)
{
#if !UNITY_EDITOR
// Game.Log($"Vivox. OnSpeechDetectedEvent: ParticipantId {valueEventArg.Value.ParticipantId} DisplayName {valueEventArg.Value.Account.DisplayName} Name {valueEventArg.Value.Account.Name}");
#endif
// Game.Log($"OnParticipantValueUpdated sender {sender} PropertyName{valueEventArg.PropertyName}");
ValidateArgs(new object[] { sender, valueEventArg });
var source = (VivoxUnity.IReadOnlyDictionary<string, IParticipant>)sender;
// Look up the participant via the key.
var participant = source[valueEventArg.Key];
string username = valueEventArg.Value.Account.Name;
ChannelId channel = valueEventArg.Value.ParentChannelSession.Key;
string property = valueEventArg.PropertyName;
switch (property)
{
case "SpeechDetected":
{
// Game.Log($"OnSpeechDetectedEvent");
OnSpeechDetectedEvent?.Invoke(username, channel, valueEventArg.Value.SpeechDetected);
break;
}
case "AudioEnergy":
{
break;
}
default:
break;
}
}
private void OnChannelPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
Game.Log($"Vivox. OnChannelPropertyChanged sender {sender} PropertyName {propertyChangedEventArgs.PropertyName}");
ValidateArgs(new object[] { sender, propertyChangedEventArgs });
//if (_client == null)
// throw new InvalidClient("Invalid client.");
var channelSession = (IChannelSession)sender;
// IF the channel has removed audio, make sure all the VAD indicators aren't showing speaking.
if (propertyChangedEventArgs.PropertyName == "AudioState" && channelSession.AudioState == VivoxUnity.ConnectionState.Disconnected)
{
Game.Log($"Vivox. Audio disconnected from: {channelSession.Key.Name}");
foreach (var participant in channelSession.Participants)
{
OnSpeechDetectedEvent?.Invoke(participant.Account.Name, channelSession.Channel, false);
}
}
// IF the channel has fully disconnected, unsubscribe and remove.
if ((propertyChangedEventArgs.PropertyName == "AudioState" || propertyChangedEventArgs.PropertyName == "TextState") &&
channelSession.AudioState == VivoxUnity.ConnectionState.Disconnected &&
channelSession.TextState == VivoxUnity.ConnectionState.Disconnected)
{
Game.Log($"Vivox. Unsubscribing from: {channelSession.Key.Name}");
// Now that we are disconnected, unsubscribe.
channelSession.PropertyChanged -= OnChannelPropertyChanged;
channelSession.Participants.AfterKeyAdded -= OnParticipantAdded;
channelSession.Participants.BeforeKeyRemoved -= OnParticipantRemoved;
channelSession.Participants.AfterValueUpdated -= OnParticipantValueUpdated;
channelSession.MessageLog.AfterItemAdded -= OnMessageLogRecieved;
channelSession.SessionArchive.AfterItemAdded -= OnSessionArchiveAdded;
// Remove session.
var user = _client.GetLoginSession(_accountId);
user.DeleteChannelSession(channelSession.Channel);
}
if (propertyChangedEventArgs.PropertyName == "SessionArchiveResult")
{
// TODO Let's flesh out the expected behaviour when this occurs. Adding this as a placeholder for now.
Game.Log("Session archive result change detected!");
}
}
#endregion
public void ToggleMuteLocalPlayer(bool mute)
{
try
{
AudioInputDevices.Muted = mute;
}
catch (Exception)
{
}
}
public bool IsLocalPlayerMuted()
{
return AudioInputDevices.Muted;
}
public void ToggleMutePlayer(IParticipant participant, int playerID, bool mute)
{
try
{
if (participant != null)
participant.LocalMute = mute;
else
{
// DialogBox.ShowToastMessage($"participant is null {playerID}");
Game.Log($"Vivox. participant is null.........");
}
}
catch (Exception)
{
}
}
private void CacheAlreadyJoinedPlayers()
{
int participantsCount = channelSession?.Participants.Count ?? 0;
Game.Log($"Vivox. CacheAlreadyJoinedPlayers count {participantsCount}");
if (participantsCount > 0 && channelSession != null)
{
foreach (IParticipant participant in channelSession.Participants)
{
Game.Log($"Vivox. CacheAlreadyJoinedPlayers name {participant.Account.DisplayName}");
//CYAPlayer player = CYAGame.Players.Find(p => p.PlayfabID == participant.Account.DisplayName);
//player.CacheParticipant(participant);
//SkipBoGameManager.instance.FindUIPlayerWithPlayfabID(participant.Account.Name)?.CacheVivoxPlayer(participant);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment