//// 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