//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
#pragma once
#include "ChatClient.h"
#include "ChatPerformance.h"
#include "ChatDiagnostics.h"
#if TV_API
namespace Microsoft {
namespace Xbox {
namespace GameChat {
#define STATISTICS_SERVICE_GUID "7492baca-c1b4-440d-a391-b7ef364a8d40"
///
/// The chat session period in milliseconds.
/// This defines how big the chat capture buffers will be.
/// Larger buffers adds latency
///
public enum class ChatSessionPeriod
{
///
/// Sets the chat session period to 20 milliseconds
///
ChatPeriodOf20Milliseconds,
///
/// Sets the chat session period to 40 milliseconds
///
ChatPeriodOf40Milliseconds,
///
/// Sets the chat session period to 80 milliseconds
///
ChatPeriodOf80Milliseconds
};
public ref class ChatManager sealed
{
public:
///
/// Creates the chat manager class using a default ChatSession period of 40 milliseconds
///
ChatManager();
///
/// To shutdown the ChatManager, simple set ChatManager^ to nullptr.
/// This will automatically shutdown the local chat session.
/// It is best to simply tear down and rebuild the whole ChatManger class,
/// otherwise every API would have to do checks against throw if not initialized.
///
virtual ~ChatManager();
///
/// Creates the chat manager class using the specified ChatSession period
///
///
/// The chat session period in milliseconds.
/// This defines how big the chat capture buffers will be.
/// Larger buffers adds latency
///
ChatManager(
_In_ ChatSessionPeriod chatSessionPeriod
);
///
/// Set various chat manager options.
/// If this is not called, defaults values are used.
/// It function can be called at any time to change the previously set options
///
property ChatManagerSettings^ ChatSettings { ChatManagerSettings^ get(); }
///
/// This event is triggered when the chat manager has a debug message.
/// The game can optionally listen to this event to debug failures and behavior
///
event Windows::Foundation::EventHandler^ OnDebugMessage;
///
/// This event is triggered when the chat manager has a network packet ready to send out.
/// The ChatPacketEventArgs provide context on the packet buffer, who the packet is for, and options around how to packet is to be sent.
/// The packets are opaque to the game.
/// When the chat message is received by the remote console, it must call ProcessIncomingChatMessage() to so the chat manager can process the message.
/// The game is required to listen to this event.
/// When handling this event, you will need to have a thread safe network layer as this event will be called from
/// an internal worker thread that is real time priority by default.
/// The chat packet must be serviced as quickly as possible since this thread is real time priority by default.
/// The chat packet should also be sent to the remote console as quickly as possible to reduce latency.
///
event Windows::Foundation::EventHandler^ OnOutgoingChatPacketReady;
///
/// This delegate compares 2 uniqueRemoteConsoleIdentifiers. They are Platform::Object^ and can be cast or unboxed to most types.
/// What exactly you use doesn't matter, but optimally it would be something that uniquely identifies a console on in the session.
/// A Windows::Xbox::Networking::SecureDeviceAssociation^ is perfect to use if you have access to it.
/// This delegate is not optional and must return true if the uniqueRemoteConsoleIdentifier1 matches uuniqueRemoteConsoleIdentifier2
///
event CompareUniqueConsoleIdentifiersHandler^ OnCompareUniqueConsoleIdentifiers;
///
/// This delegate is called prior to encoding captured audio buffer.
/// This allows titles to apply sound effects to the capture stream
/// To use, register for this delegate and set ChatManagerSettings::PreEncodeCallbackEnabled to true
///
event ProcessAudioBufferHandler^ OnPreEncodeAudioBuffer;
///
/// This delegate is called after decoding a remote audio buffer.
/// This allows titles to apply sound effects to a remote user's audio mix
/// To use, register for this delegate and set ChatManagerSettings::PostDecodeCallbackEnabled to true
///
event ProcessAudioBufferHandler^ OnPostDecodeAudioBuffer;
///
/// Processes incoming chat messages from remote consoles.
/// It must call ProcessIncomingChatMessage() to so the chat manager can process the message.
///
///
/// The incoming chat packet inside an IBuffer.
/// This is how you would convert from byte array to a IBuffer^
///
/// Windows::Storage::Streams::IBuffer^ destBuffer = ref new Windows::Storage::Streams::Buffer( sourceByteBufferSize );
/// byte* destBufferBytes = nullptr;
/// GetBufferBytes( destBuffer, &destBufferBytes );
/// errno_t err = memcpy_s( destBufferBytes, destBuffer->Capacity, sourceByteBuffer, sourceByteBufferSize );
/// THROW_HR_IF(err != 0, E_FAIL);
/// destBuffer->Length = sourceByteBufferSize;
///
///
/// uniqueRemoteConsoleIdentifier is a Platform::Object^ and can be cast or unboxed to most types.
/// What exactly you use doesn't matter, but optimally it would be something that uniquely identifies a console on in the session.
/// A Windows::Xbox::Networking::SecureDeviceAssociation^ is perfect to use if you have access to it.
///
/// This is how you would convert from an int to a Platform::Object^
/// Platform::Object obj = (Object^)5;
///
///
/// The chat message type that was processed. This can be used to track down networking issues, but typically can be ignored
///
Microsoft::Xbox::GameChat::ChatMessageType ProcessIncomingChatMessage(
_In_ Windows::Storage::Streams::IBuffer^ chatPacket,
_In_ Platform::Object^ uniqueRemoteConsoleIdentifier
);
///
/// This causes existing local users to be resent to a new remote console connection.
///
///
/// uniqueRemoteConsoleIdentifier is a Platform::Object^ and can be cast or unboxed to most types.
/// What exactly you use doesn't matter, but optimally it would be something that uniquely identifies a console on in the session.
/// A Windows::Xbox::Networking::SecureDeviceAssociation^ is perfect to use if you have access to it.
///
/// This is how you would convert from an int to a Platform::Object^
/// Platform::Object obj = (Object^)5;
///
void HandleNewRemoteConsole(
_In_ Platform::Object^ uniqueRemoteConsoleIdentifier
);
///
/// Adds a local user to the chat channel.
/// Note that this user should have expressed intent to play prior to calling this, because the user may
/// have been signed in due to Kinect automatically but may not want to play or take up a chat slot.
/// This will automatically serialize the local user to a packet that can be sent to all connected consoles.
///
/// The index of the chat channel
/// The user to add to the chat channel
Windows::Foundation::IAsyncAction^
AddLocalUserToChatChannelAsync(
_In_ uint8 channelIndex,
_In_ Windows::Xbox::System::IUser^ user
);
///
/// Adds a local user to the chat channel.
/// Note that this user should have expressed intent to play prior to calling this, because the user may
/// have been signed in due to Kinect automatically but may not want to play or take up a chat slot.
/// This will automatically serialize the local user to a packet that can be sent to all connected consoles.
///
/// The index of the chat channel
/// The user to add to the chat channel
Windows::Foundation::IAsyncAction^
AddLocalUsersToChatChannelAsync(
_In_ uint8 channelIndex,
_In_ Windows::Foundation::Collections::IVectorView^ users
);
///
/// Adds a remote user to the chat channel.
/// This will automatically create a packet to inform the all connected consoles that this player should be removed.
///
/// The index of the chat channel
/// The user to remove to the chat channel
Windows::Foundation::IAsyncAction^
RemoveLocalUserFromChatChannelAsync(
_In_ uint8 channelIndex,
_In_ Windows::Xbox::System::IUser^ user
);
///
/// Remove all remote users that are attached to remote console.
/// This is typically called when a connection to a remote console is destroyed
///
/// A consoleId of the remote console
Windows::Foundation::IAsyncAction^
RemoveRemoteConsoleAsync(
_In_ Platform::Object^ uniqueRemoteConsoleIdentifier
);
///
/// Returns a list of ChatUser objects.
/// The ChatUser object contains metadata about the user such as if they are talking
///
/// A list of ChatUser objects
Windows::Foundation::Collections::IVectorView^ GetChatUsers();
///
/// Mutes the user from all channels.
/// If you mute a local user, it stops capturing packets from the capture source
/// but does not stop you from receiving packets.
///
/// The user to mute
void MuteUserFromAllChannels( ChatUser^ user );
///
/// Mutes the user from all channels. And sets permanent mute flag
///
/// The user to mute
void MuteUserFromAllChannelsPermanently( ChatUser^ user );
///
/// Unmute a specific user from all channels.
///
/// The user to unmute
void UnmuteUserFromAllChannels( ChatUser^ user );
///
/// Mute all users in the chat session
///
void MuteAllUsersFromAllChannels();
///
/// Unmute all users in the chat session
///
void UnmuteAllUsersFromAllChannels();
///
/// Mute non-friend chat user with a poor reputation.
///
/// The user to mute if they fail a reputation check
Windows::Foundation::IAsyncAction^
MuteUserIfReputationIsBadAsync(
_In_ Microsoft::Xbox::GameChat::ChatUser^ user
);
///
/// Indicates if the the title has mic focus
///
property bool HasMicFocus { bool get(); }
///
/// Returns the ChatPerformanceCounters object.
/// The ChatPerformanceCounters object contains performance data for profiling.
/// See ChatManagerSettings::PerformanceCountersEnabled to enable/disable collection of performance data.
///
property Microsoft::Xbox::GameChat::ChatPerformanceCounters^ ChatPerformanceCounters { Microsoft::Xbox::GameChat::ChatPerformanceCounters^ get(); }
internal:
std::shared_ptr GetChatDiagnostics() { return m_chatDiagnostics; };
bool DoesAudioDeviceCollectionsMatchExclusiveDevices(
_In_ Windows::Foundation::Collections::IVectorView< Windows::Xbox::System::IAudioDeviceInfo^ >^ audioDevices1,
_In_ Windows::Foundation::Collections::IVectorView< Windows::Xbox::System::IAudioDeviceInfo^ >^ audioDevices2
);
///
/// Internal event handler
///
void OnDebugMessageHandler(
_In_ Microsoft::Xbox::GameChat::DebugMessageEventArgs^ args
);
///
/// Internal event handler
///
void OnChatPacketReadyHandler(
_In_ Microsoft::Xbox::GameChat::ChatPacketEventArgs^ args
);
///
/// Internal event handler
///
void OnChatSessionStateChangedHandler(
_In_ Windows::Xbox::Chat::IChatSessionState^ chatSessionState
);
///
/// Internal event handler
///
void OnRemoteUserReadyToAddHandler(
_In_ uint8 channelIndex,
_In_ Windows::Xbox::System::IUser^ remoteUser,
_In_ Platform::Object^ remoteUniqueConsoleIdentifier,
_In_ bool hasAddedRemoteUserToLocalChatSession
);
///
/// Internal event handler
///
void OnRemoteUserReadyToRemoveHandler(
_In_ uint8 channelIndex,
_In_ Platform::String^ remoteXboxUserId
);
///
/// Internal event handler
///
bool OnCompareUniqueConsoleIdentifiersHandler(
_In_ Platform::Object^ uniqueRemoteConsoleIdentifier1,
_In_ Platform::Object^ uniqueRemoteConsoleIdentifier2
);
///
/// Internal event handler
///
Windows::Storage::Streams::IBuffer^ OnPreEncodeAudioBufferHandler(
_In_ Windows::Storage::Streams::IBuffer^ buffer,
_In_ Windows::Xbox::Chat::IFormat^ audioFormat,
_In_ Windows::Foundation::Collections::IVectorView^ chatUsers
);
///
/// Internal event handler
///
Windows::Storage::Streams::IBuffer^ OnPostDecodeAudioBufferHandler(
_In_ Windows::Storage::Streams::IBuffer^ buffer,
_In_ Windows::Xbox::Chat::IFormat^ audioFormat,
_In_ Windows::Foundation::Collections::IVectorView^ chatUsers
);
///
/// Internal event handler
///
void OnChatManagerSettingsChangedHandler();
private:
///
/// Internal helper function to initialize the chat manager class using the specified ChatSession period
///
///
/// A ChatSessionPeriod enum which represents the chat session period in milliseconds.
/// This defines how big the chat capture buffers will be
///
void Initialize(
_In_ ChatSessionPeriod chatSessionPeriod
);
///
/// Internal helper function to send all local users to a remote console
///
void SendLocalUsersToRemoteConsole( _In_ Platform::Object^ remoteUniqueConsoleIdentifier );
///
/// Internal helper function to log a comment
///
void LogComment(
_In_ Platform::String^ message
);
///
/// Internal helper function to log a comment with an error string
///
void LogCommentWithError(
_In_ Platform::String^ message,
_In_ HRESULT hr
);
///
/// Internal helper function to log a formated comment
///
void LogCommentFormat(
_In_ LPCWSTR strMsg, ...
);
///
/// Helper function to convert from ChatSessionPeriod to uint32 milliseconds
///
/// Returns a uint32 milliseconds
uint32 ConvertChatSessionPeriodToMilliseconds( _In_ ChatSessionPeriod chatSessionPeriod );
///
/// Helper function to compare lists of audio devices to mismatches
///
bool ChatManager::DoAudioDeviceCollectionsMatch(
_In_ Windows::Foundation::Collections::IVectorView< Windows::Xbox::System::IAudioDeviceInfo^ >^ audioDevices1,
_In_ Windows::Foundation::Collections::IVectorView< Windows::Xbox::System::IAudioDeviceInfo^ >^ audioDevices2
);
private:
std::shared_ptr m_factoryCache;
ChatClient^ m_chatClient;
ChatAudioThread^ m_chatAudioThread;
ChatNetwork^ m_chatNetwork;
ChatManagerSettings^ m_chatManagerSettings;
Platform::WeakReference m_chatManagerEventHandler;
std::shared_ptr m_chatDiagnostics;
std::map m_socialRelationships;
};
}}}
#endif