bool FOnlineVoiceImpl::UnmuteRemoteTalker(uint8 LocalUserNum, const FUniqueNetId& PlayerId, bool bIsSystemWide)
{
	uint32 Return = E_FAIL;
	if (LocalUserNum >= 0 && LocalUserNum < MAX_LOCAL_PLAYERS)
	{
		// Skip this if the session isn't active
		if (SessionInt && SessionInt->GetNumSessions() > 0 &&
			// Or if voice is disabled
			VoiceEngine != NULL)
		{
			// Find the specified talker
			FRemoteTalker* Talker = FindRemoteTalker(PlayerId);
			if (Talker != NULL)
			{
				// Remove them from the mute list
				MuteList.RemoveSingleSwap((const FUniqueNetIdString&)PlayerId);
				UE_LOG(LogVoice, Log, TEXT("Unmuting remote talker (%s)"), *PlayerId.ToDebugString());
			}
			else
			{
				UE_LOG(LogVoice, Warning, TEXT("Unknown remote talker (%s) specified to UnmuteRemoteTalker()"), *PlayerId.ToDebugString());
			}
		}
	}
	else
	{
		UE_LOG(LogVoice, Warning, TEXT("Invalid user specified in UnmuteRemoteTalker(%d)"), LocalUserNum);
	}

	return Return == S_OK;
}
bool FOnlineVoiceSteam::UnregisterRemoteTalker(const FUniqueNetId& UniqueId) 
{
	uint32 Return = E_FAIL;
	if (SteamSubsystem)
	{
		// Skip this if the session isn't active
		if (SessionInt && SessionInt->GetNumSessions() > 0 &&
			// Or when voice is disabled
			VoiceEngine.IsValid())
		{
			// Make sure the talker is valid
			if (FindRemoteTalker(UniqueId) != NULL)
			{
				// Find them in the talkers array and remove them
				for (int32 Index = 0; Index < RemoteTalkers.Num(); Index++)
				{
					const FRemoteTalker& Talker = RemoteTalkers[Index];
					// Is this the remote talker?
					if (*Talker.TalkerId == UniqueId)
					{
						// Going to remove the talker, so if they were talking recently make sure to indicate they've stopped
						if (OnPlayerTalkingStateChangedDelegates.IsBound() && (Talker.bIsTalking || Talker.bWasTalking))
						{
							OnPlayerTalkingStateChangedDelegates.Broadcast(Talker.TalkerId.ToSharedRef(), false);
						}

						RemoteTalkers.RemoveAtSwap(Index);
						break;
					}
				}
				// Remove them from voice engine
				Return = VoiceEngine->UnregisterRemoteTalker(UniqueId);
				UE_LOG(LogVoice, Log, TEXT("UnregisterRemoteTalker(%s) returned 0x%08X"), *UniqueId.ToDebugString(), Return);
			}
			else
			{
				UE_LOG(LogVoice, Verbose, TEXT("Unknown remote talker (%s) specified to UnregisterRemoteTalker()"), *UniqueId.ToDebugString());
			}
		}
	}
	return Return == S_OK;
}
bool FOnlineVoiceSteam::RegisterRemoteTalker(const FUniqueNetId& UniqueId) 
{
	uint32 Return = E_FAIL;
	if (SteamSubsystem)
	{
		// Skip this if the session isn't active
		if (SessionInt && SessionInt->GetNumSessions() > 0 &&
			// Or when voice is disabled
			VoiceEngine.IsValid())
		{
			// See if this talker has already been registered or not
			FRemoteTalker* Talker = FindRemoteTalker(UniqueId);
			if (Talker == NULL)
			{
				// Add a new talker to our list
				int32 AddIndex = RemoteTalkers.AddZeroed();
				Talker = &RemoteTalkers[AddIndex];
				// Copy the UniqueId
				const FUniqueNetIdSteam& UniqueIdSteam = (const FUniqueNetIdSteam&)UniqueId;
				Talker->TalkerId = MakeShareable(new FUniqueNetIdSteam(UniqueIdSteam));
				// Register the remote talker locally
				Return = VoiceEngine->RegisterRemoteTalker(UniqueId);
				UE_LOG(LogVoice, Log, TEXT("RegisterRemoteTalker(%s) returned 0x%08X"),
					*UniqueId.ToDebugString(), Return);
			}
			else
			{
				UE_LOG(LogVoice, Verbose, TEXT("Remote talker %s is being re-registered"), *UniqueId.ToDebugString());
				Return = S_OK;
			}
			
			// Update muting all of the local talkers with this remote talker
			ProcessMuteChangeNotification();
			// Now start processing the remote voices
			Return = VoiceEngine->StartRemoteVoiceProcessing(UniqueId);
			UE_LOG(LogVoice, Log, TEXT("StartRemoteVoiceProcessing(%s) returned 0x%08X"), *UniqueId.ToDebugString(), Return);
		}
	}
	return Return == S_OK;
}
bool FOnlineVoiceImpl::RegisterRemoteTalker(const FUniqueNetId& UniqueId) 
{
	uint32 Return = E_FAIL;
	if (OnlineSubsystem)
	{
		// Skip this if the session isn't active
		if (SessionInt && SessionInt->GetNumSessions() > 0 &&
			// Or when voice is disabled
			VoiceEngine != NULL)
		{
			// See if this talker has already been registered or not
			FRemoteTalker* Talker = FindRemoteTalker(UniqueId);
			if (Talker == NULL)
			{
				// Add a new talker to our list
				int32 AddIndex = RemoteTalkers.AddZeroed();
				Talker = &RemoteTalkers[AddIndex];
				// Copy the UniqueId
				const FUniqueNetIdString& UniqueIdStr = (const FUniqueNetIdString&)UniqueId;
				Talker->TalkerId = MakeShareable(new FUniqueNetIdString(UniqueIdStr));
				// Register the remote talker locally
				Return = VoiceEngine->RegisterRemoteTalker(UniqueId);
				UE_LOG(LogVoice, Log, TEXT("RegisterRemoteTalker(%s) returned 0x%08X"),
					*UniqueId.ToDebugString(), Return);
			}
			else
			{
				UE_LOG(LogVoice, Warning, TEXT("Remote talker %s is being re-registered"), *UniqueId.ToDebugString());
				Return = S_OK;
			}
			
			// @todo ONLINE Mute List update

			// Now start processing the remote voices
			Return = VoiceEngine->StartRemoteVoiceProcessing(UniqueId);
			UE_LOG(LogVoice, Log, TEXT("StartRemoteVoiceProcessing(%s) returned 0x%08X"), *UniqueId.ToDebugString(), Return);
		}
	}
	return Return == S_OK;
}
bool FOnlineVoiceSteam::MuteRemoteTalker(uint8 LocalUserNum, const FUniqueNetId& PlayerId, bool bIsSystemWide)
{
	uint32 Return = E_FAIL;
	if (LocalUserNum >= 0 && LocalUserNum < MAX_LOCAL_PLAYERS)
	{
		if (bIsSystemWide)
		{
			SystemMuteList.AddUnique((const FUniqueNetIdSteam&)PlayerId);
			ProcessMuteChangeNotification();
		}
		else
		{
			// Skip this if the session isn't active
			if (SessionInt && SessionInt->GetNumSessions() > 0 &&
				// Or if voice is disabled
					VoiceEngine.IsValid())
			{
				// Find the specified talker
				FRemoteTalker* Talker = FindRemoteTalker(PlayerId);
				if (Talker != NULL)
				{
					MuteList.AddUnique((const FUniqueNetIdSteam&)PlayerId);
					Return = S_OK;
					UE_LOG(LogVoice, Log, TEXT("Muting remote talker (%s)"), *PlayerId.ToDebugString());
				}
				else
				{
					UE_LOG(LogVoice, Verbose, TEXT("Unknown remote talker (%s) specified to MuteRemoteTalker()"), *PlayerId.ToDebugString());
				}
			}
		}
	}
	else
	{
		UE_LOG(LogVoice, Warning, TEXT("Invalid user specified in MuteRemoteTalker(%d)"), LocalUserNum);
	}

	return Return == S_OK;
}