> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Utilisation de l'API C++ de Game Chat 2

> Procédure pas à pas de l'API C++ de Game Chat 2 sur XBOX GDK, couvrant l'initialisation, l'ajout d'utilisateurs, la configuration des canaux de chat et les modèles de gestion des erreurs.

Cette rubrique présente une brève procédure pas à pas d'utilisation de l'API C++ de Game Chat 2 pour ajouter une communication vocale et textuelle à votre jeu.

## Prérequis

Game Chat 2 exige que votre projet ait été configuré pour le GDK. Pour savoir comment effectuer cette configuration, consultez [Prise en main du Microsoft Game Development Kit](https://learn.microsoft.com/gaming/gdk/docs/services/gdk-dev/get-started/get-started-home).

La compilation de Game Chat 2 nécessite l'inclusion de l'en-tête principal *GameChat2.h*.
Pour que l'édition des liens réussisse, votre projet doit également inclure *GameChat2Impl.h* dans au moins une unité de compilation (nous recommandons un en-tête précompilé commun, car ces implémentations de fonctions stub sont petites et faciles à générer « inline » pour le compilateur).

L'interface de Game Chat 2 n'impose pas à un projet de choisir entre une compilation en C++/CX et une compilation en C++ traditionnel. Elle peut être utilisée avec l'un ou l'autre. L'implémentation ne lève pas non plus d'exceptions pour signaler les erreurs non fatales. Vous pouvez donc l'utiliser facilement dans des projets sans exceptions, si vous le souhaitez. L'implémentation lève toutefois des exceptions pour signaler les erreurs fatales. (Pour plus de détails, consultez la section [Modèle de défaillance](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/using-game-chat-2.md#FAILURE_MODEL) plus loin dans cette rubrique.)

## Initialisation

Commencez à interagir avec la bibliothèque en initialisant l'instance singleton de Game Chat 2 avec des paramètres qui s'appliquent pendant toute la durée de l'initialisation du singleton. L'instance singleton est initialisée en appelant [chat\_manager::initialize](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_initialize.md), comme indiqué ci-dessous.

```cpp theme={null}
chat_manager::singleton_instance().initialize(...);
```

> [!NOTE]
>
> Vous devez vous inscrire aux événements de suspension et de reprise via `RegisterAppStateChangeNotification`. Lors de la suspension, vous devez nettoyer Game Chat 2 avec [chat\_manager::cleanup()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_cleanup.md). Lors de la reprise, vous devez réinitialiser Game Chat 2. Il risque de planter si vous tentez de l'utiliser au-delà d'un cycle de suspension/reprise.

## Configuration des utilisateurs

### Ajout d'utilisateurs à votre titre Microsoft Game Development Kit (GDK)

Avant d'ajouter des utilisateurs à l'instance de Game Chat 2, assurez-vous qu'ils ont été ajoutés au titre GDK.
Cela s'effectue à l'aide de l'[API XUserAddAsync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuseraddasync.md). Pour plus d'informations sur l'utilisation de cette API, consultez [Identité utilisateur et XUser](https://docs.xbox.com/fr/build/core-features/common/user/player-identity-xuser.md).

Une fois que vous disposez du `XUserHandle` de l'utilisateur que vous souhaitez ajouter à Game Chat 2, vous devez obtenir l'ID d'utilisateur XBOX (XUID) de l'utilisateur à l'aide de l'[API XUserGetId](https://docs.xbox.com/fr/reference/system/xuser/functions/xusergetid.md).
L'utilisateur doit être en ligne, et vous devez avoir son consentement pour cette étape.

[XUserGetId](https://docs.xbox.com/fr/reference/system/xuser/functions/xusergetid.md) fournit le XUID sous la forme d'un `uint64_t`. Vous devez convertir le XUID en `std::wstring` pour l'utiliser avec Game Chat 2.

Voici un exemple de code qui montre comment ajouter un utilisateur à Game Chat 2 une fois que vous disposez d'un `XUserHandle`.
\[!NOTE] Sachez que l'appel de [XUserResolveIssueWithUiAsync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuserresolveissuewithuiasync.md) affiche une boîte de dialogue système.

```cpp theme={null}
HRESULT
AddChatUserFromXUserHandle(
    _In_ XUserHandle user,
    _In_ XTaskQueueHandle queueHandle,
    _Outptr_result_maybenull_ Xs::game_chat_2::chat_user** chatUser
    )
{
    *chatUser = nullptr;
    uint64_t xuid;
    HRESULT hr = XUserGetId(user, &xuid);
    if (hr == E_GAMEUSER_RESOLVE_USER_ISSUE_REQUIRED)
    {
        XAsyncBlock* asyncBlock = new (std::nothrow) XAsyncBlock;
        if (asyncBlock != nullptr)
        {
            ZeroMemory(asyncBlock, sizeof(*asyncBlock));
            asyncBlock->queue = queueHandle;
            hr = XUserResolveIssueWithUiAsync(user, nullptr, asyncBlock);
            if (SUCCEEDED(hr))
            {
                hr = XAsyncGetStatus(asyncBlock, true);
                if (SUCCEEDED(hr))
                {
                    hr = XUserGetId(user, &xuid);
                }
            }
            delete asyncBlock;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }

    if (SUCCEEDED(hr))
    {
        try
        {
            std::wstring xuidString = std::to_wstring(xuid);

            // If the user has already been added, this will return the existing user.
            *chatUser = Xs::game_chat_2::chat_manager::singleton_instance().add_local_user(xuidString.c_str());
        }
        catch (const std::bad_alloc&)
        {
            hr = E_OUTOFMEMORY;
        }
    }

    return hr;
}
```

### Ajout d'utilisateurs à Game Chat 2

Une fois l'instance initialisée, vous devez ajouter les utilisateurs locaux à l'instance de Game Chat 2 à l'aide de [chat\_manager::add\_local\_user](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_add_local_user.md). Dans cet exemple, l'utilisateur A représente un utilisateur local.

```cpp theme={null}
chat_user* chatUserA = chat_manager::singleton_instance().add_local_user(<user_a_xuid>);
```

Ajoutez ensuite les utilisateurs distants ainsi que les identificateurs qui représentent le « point de terminaison » distant sur lequel se trouve chaque utilisateur.
Un *point de terminaison* est une instance de l'application qui s'exécute sur un appareil distant.

Dans cet exemple, l'utilisateur B se trouve sur le point de terminaison X. Les utilisateurs C et D se trouvent sur le point de terminaison Y.
L'identificateur « 1 » est attribué arbitrairement au point de terminaison X, et l'identificateur « 2 » au point de terminaison Y.

Informez Game Chat 2 des utilisateurs distants à l'aide des appels suivants.

```cpp theme={null}
chat_user* chatUserB = chat_manager::singleton_instance().add_remote_user(<user_b_xuid>, 1);
chat_user* chatUserC = chat_manager::singleton_instance().add_remote_user(<user_c_xuid>, 2);
chat_user* chatUserD = chat_manager::singleton_instance().add_remote_user(<user_d_xuid>, 2);
```

Configurez ensuite la relation de communication entre chaque utilisateur distant et l'utilisateur local.
Dans cet exemple, supposons que les utilisateurs A et B font partie de la même équipe. La communication bidirectionnelle est autorisée.
`c_communicationRelationshipSendAndReceiveAll` est une constante définie dans *GameChat2.h* pour représenter la communication bidirectionnelle.

Définissez la relation de l'utilisateur A avec l'utilisateur B à l'aide de [chat\_user\_local::set\_communication\_relationship](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_communication_relationship.md).

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserB, c_communicationRelationshipSendAndReceiveAll);
```

Supposons que les utilisateurs C et D sont des « spectateurs » et doivent pouvoir écouter l'utilisateur A, mais pas parler.
`c_communicationRelationshipSendAll` est une constante définie dans *GameChat2.h* pour représenter cette communication unidirectionnelle.

Définissez les relations comme suit.

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserC, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserD, c_communicationRelationshipSendAll);
```

Pour des exemples de paramètres de relation pour les quatre utilisateurs locaux, consultez la section [Scénarios](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/using-game-chat-2.md#scenarios) plus loin dans cette rubrique.

Si, à un moment donné, des utilisateurs distants ont été ajoutés à l'instance singleton sans avoir été configurés pour communiquer avec des utilisateurs locaux, ce n'est pas un problème.
Cela peut se produire dans les scénarios où les utilisateurs constituent des équipes ou peuvent changer librement de canal vocal.

Game Chat 2 ne met en cache des informations (par exemple, les relations de confidentialité et la réputation) que pour les utilisateurs qui ont été ajoutés à l'instance ; il est donc utile d'informer Game Chat 2 de tous les utilisateurs possibles, même s'ils ne peuvent parler à aucun utilisateur local à un moment donné.

Enfin, supposons que l'utilisateur D a quitté la partie et doit être retiré de l'instance locale de Game Chat 2.
Cela peut être effectué à l'aide de [chat\_manager::remove\_user](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_remove_user.md), comme indiqué ci-dessous.

```cpp theme={null}
chat_manager::singleton_instance().remove_user(chatUserD);
```

L'appel de `chat_manager::remove_user()` peut invalider l'objet utilisateur. Si vous utilisez la [manipulation audio en temps réel](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/real-time-audio-manipulation.md), consultez [Durée de vie des utilisateurs du chat](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/real-time-audio-manipulation.md#chat-user-lifetimes) pour plus d'informations. Sinon, l'objet utilisateur est invalidé immédiatement lors de l'appel de `chat_manager::remove_user()`. Une restriction subtile concernant le moment où les utilisateurs peuvent être retirés est détaillée dans la section [Traitement des changements d'état](#processing-state-changes) plus loin dans cette rubrique.

## Traitement des trames de données

Game Chat 2 ne dispose pas de sa propre couche de transport. Celle-ci doit être fournie par l'application.
Ce branchement est géré par les appels réguliers et fréquents de l'application à la paire de méthodes [chat\_manager::start\_processing\_data\_frames()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_start_processing_data_frames.md) et [chat\_manager::finish\_processing\_data\_frames()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_finish_processing_data_frames.md). C'est au moyen de ces méthodes que Game Chat 2 fournit les données sortantes à l'application.

Ces méthodes sont conçues pour s'exécuter rapidement. Elles peuvent être interrogées fréquemment sur un thread réseau dédié.
Cela offre un emplacement pratique pour récupérer toutes les données en file d'attente sans se soucier de l'imprévisibilité de la synchronisation réseau ou de la complexité des rappels multithread.

Lorsque `chat_manager::start_processing_data_frames()` est appelée, toutes les données en file d'attente sont présentées dans un tableau de pointeurs vers des structures [game\_chat\_data\_frame](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_data_frame.md).
Les applications doivent parcourir le tableau, inspecter les points de terminaison cibles et utiliser leur couche réseau pour transmettre les données aux instances distantes appropriées de l'application.

Une fois toutes les structures [game\_chat\_data\_frame](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_data_frame.md) du tableau traitées, le tableau doit être renvoyé à Game Chat 2 pour libérer les ressources en appelant `chat_manager:finish_processing_data_frames()`.
C'est ce qu'illustre l'exemple suivant.

```cpp theme={null}
uint32_t dataFrameCount;
game_chat_data_frame_array dataFrames;
chat_manager::singleton_instance().start_processing_data_frames(&dataFrameCount, &dataFrames);
for (uint32_t dataFrameIndex = 0; dataFrameIndex < dataFrameCount; ++dataFrameIndex)
{
    game_chat_data_frame const* dataFrame = dataFrames[dataFrameIndex];

    // Title-written function responsible for sending packet to remote instances of GameChat 2.
    HandleOutgoingDataFrame(
        dataFrame->packet_byte_count,
        dataFrame->packet_buffer,
        dataFrame->target_endpoint_identifier_count,
        dataFrame->target_endpoint_identifiers,
        dataFrame->transport_requirement
        );
}
chat_manager::singleton_instance().finish_processing_data_frames(dataFrames);
```

Plus les trames de données sont traitées fréquemment, plus la latence audio perçue par l'utilisateur est faible.
L'audio est regroupé en trames de données de 40 ms. Il s'agit de la période d'interrogation suggérée.

## Traitement des changements d'état

Game Chat 2 fournit des mises à jour à l'application, comme les messages texte reçus, au moyen des appels réguliers et fréquents de l'application à la paire de méthodes [chat\_manager::start\_processing\_state\_changes()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_start_processing_state_changes.md) et [chat\_manager::finish\_processing\_state\_changes()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_finish_processing_state_changes.md).
Ces méthodes s'exécutent rapidement, de sorte qu'elles peuvent être appelées à chaque trame graphique dans votre boucle de rendu de l'interface utilisateur.
Cela offre un emplacement pratique pour récupérer toutes les modifications en file d'attente sans se soucier de l'imprévisibilité de la synchronisation réseau ou de la complexité des rappels multithread.

Lorsque `chat_manager::start_processing_state_changes()` est appelée, toutes les mises à jour en file d'attente sont présentées dans un tableau de pointeurs vers des structures [game\_chat\_state\_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_state_change.md).
Les applications doivent parcourir le tableau, inspecter la structure de base pour déterminer son type plus spécifique, convertir la structure de base vers le type détaillé correspondant, puis traiter la mise à jour de manière appropriée.

Une fois tous les objets [game\_chat\_state\_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_state_change.md) actuellement disponibles du tableau traités, le tableau doit être renvoyé à Game Chat 2 pour libérer les ressources en appelant `chat_manager::finish_processing_state_changes()`.
C'est ce qu'illustre l'exemple suivant.

```cpp theme={null}
uint32_t stateChangeCount;
game_chat_state_change_array gameChatStateChanges;
chat_manager::singleton_instance().start_processing_state_changes(&stateChangeCount, &gameChatStateChanges);

std::list<Xs::game_chat_2::chat_user*> usersWithPrivilegeIssues;
std::list<Xs::game_chat_2::chat_user*> usersWithPrivilegeCheckIssues;
for (uint32_t stateChangeIndex = 0; stateChangeIndex < stateChangeCount; ++stateChangeIndex)
{
    switch (gameChatStateChanges[stateChangeIndex]->state_change_type)
    {
        case game_chat_state_change_type::text_chat_received:
        {
            HandleTextChatReceived(static_cast<const game_chat_text_chat_received_state_change*>(gameChatStateChanges[stateChangeIndex]));
            break;
        }

        case Xs::game_chat_2::game_chat_state_change_type::transcribed_chat_received:
        {
            HandleTranscribedChatReceived(static_cast<const Xs::game_chat_2::game_chat_transcribed_chat_received_state_change*>(gameChatStateChanges[stateChangeIndex]));
            break;
        }
        case Xs::game_chat_2::game_chat_state_change_type::communication_relationship_adjuster_changed:
        {
            HandleAdjusterChangedStateReceived(static_cast<const Xs::game_chat_2::game_chat_communication_relationship_adjuster_changed_state_change*>(gameChatStateChanges[stateChangeIndex]), usersWithPrivilegeIssues, usersWithPrivilegeCheckIssues);
            break;
        }

        ...
    }
}
chat_manager::singleton_instance().finish_processing_state_changes(gameChatStateChanges);
```

Comme `chat_manager::remove_user()` invalide immédiatement la mémoire associée à un objet utilisateur, et que les changements d'état peuvent contenir des pointeurs vers des objets utilisateur, `chat_manager::remove_user()` ne doit pas être appelée pendant le traitement des changements d'état.

## Chat textuel

Pour envoyer un message de chat textuel, utilisez [chat\_user::chat\_user\_local::send\_chat\_text()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_send_chat_text.md).
C'est ce qu'illustre l'exemple suivant.

```cpp theme={null}
chatUserA->local()->send_chat_text(L"Hello");
```

Game Chat 2 génère une trame de données contenant ce message. Les points de terminaison cibles de la trame de données sont ceux associés aux utilisateurs qui ont été configurés pour recevoir du texte de l'utilisateur local.
Lorsque les données sont traitées par les points de terminaison distants, le message est exposé via [game\_chat\_text\_chat\_received\_state\_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_text_chat_received_state_change.md).

Comme pour le chat vocal, les restrictions de privilèges et de confidentialité sont respectées pour le chat textuel.
Si une paire d'utilisateurs a été configurée pour autoriser le chat textuel, mais que des restrictions de privilèges ou de confidentialité interdisent cette communication, le message texte est abandonné.

## Accessibilité

L'accessibilité exige la prise en charge de la saisie et de l'affichage du chat textuel.

La saisie de texte est requise car, même sur les plateformes ou dans les genres de jeux qui n'ont historiquement pas fait un usage répandu du clavier physique, les utilisateurs peuvent configurer le système pour utiliser des technologies d'assistance de synthèse vocale.

De même, l'affichage du texte est requis, car les utilisateurs peuvent configurer le système pour utiliser la reconnaissance vocale.

Ces préférences peuvent être détectées sur les utilisateurs locaux en appelant respectivement les méthodes [chat\_user::chat\_user\_local::text\_to\_speech\_conversion\_preference\_enabled()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_text_to_speech_conversion_preference_enabled.md) et [chat\_user::chat\_user\_local::speech\_to\_text\_conversion\_preference\_enabled()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_speech_to_text_conversion_preference_enabled.md). Nous vous recommandons d'activer le texte de manière conditionnelle, en fonction des préférences de l'utilisateur.

### Synthèse vocale

Lorsqu'un utilisateur a activé la synthèse vocale, [chat\_user::chat\_user\_local::text\_to\_speech\_conversion\_preference\_enabled()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_text_to_speech_conversion_preference_enabled.md) renvoie `true`. Lorsque cet état est détecté, l'application doit fournir une méthode de saisie de texte.

Une fois que vous disposez de la saisie de texte fournie par un clavier réel ou virtuel, transmettez la chaîne à la méthode [chat\_user::chat\_user\_local::synthesize\_text\_to\_speech()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_synthesize_text_to_speech.md). Game Chat 2 détecte et synthétise des données audio basées sur la chaîne et sur la préférence de voix d'accessibilité de l'utilisateur.
C'est ce qu'illustre l'exemple suivant.

```cpp theme={null}
chat_userA->local()->synthesize_text_to_speech(L"Hello");
```

L'audio synthétisé dans le cadre de cette opération est transmis à tous les utilisateurs qui ont été configurés pour recevoir l'audio de cet utilisateur local.
Si `chat_user::chat_user_local::synthesize_text_to_speech()` est appelée pour un utilisateur qui n'a pas activé la synthèse vocale, Game Chat 2 n'effectue aucune action.

### Reconnaissance vocale

Lorsqu'un utilisateur a activé la reconnaissance vocale, [chat\_user::chat\_user\_local::speech\_to\_text\_conversion\_preference\_enabled()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_speech_to_text_conversion_preference_enabled.md) renvoie `true`. Lorsque cet état est détecté, l'application doit être prête à fournir une interface utilisateur associée aux messages de chat transcrits. Game Chat 2 transcrit automatiquement l'audio de chaque utilisateur distant et l'expose via une structure [game\_chat\_transcribed\_chat\_received\_state\_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_transcribed_chat_received_state_change.md).

### Considérations relatives aux performances de la reconnaissance vocale

Lorsque la reconnaissance vocale est activée, l'instance de Game Chat 2 de chaque appareil distant établit une connexion WebSocket avec le point de terminaison des services vocaux.
Chaque client Game Chat 2 distant charge l'audio vers le point de terminaison des services vocaux via ce WebSocket. Le point de terminaison des services vocaux renvoie de temps à autre un message de transcription à l'appareil distant.
L'appareil distant envoie ensuite le message de transcription (c'est-à-dire un message texte) à l'appareil local. Le message transcrit est transmis par Game Chat 2 à l'application pour qu'elle l'affiche.

Par conséquent, le principal coût en performances de la reconnaissance vocale est l'utilisation du réseau.
La majeure partie du trafic réseau correspond au chargement de l'audio encodé.
Le WebSocket charge l'audio déjà encodé par Game Chat 2 dans le chemin de chat vocal « normal ». L'application contrôle le débit binaire via [chat\_manager::set\_audio\_encoding\_bitrate](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_set_audio_encoding_bitrate.md).

## Interface utilisateur

Partout où une interface utilisateur est présentée aux utilisateurs, en particulier dans une liste de gamertags comme un tableau des scores, nous vous recommandons d'afficher également des icônes de micro coupé ou de prise de parole pour informer l'utilisateur.
Pour ce faire, appelez [chat\_user::chat\_indicator()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/methods/chat_user_chat_indicator.md) afin de récupérer une énumération [game\_chat\_user\_chat\_indicator](https://docs.xbox.com/fr/reference/chat/gamechat2/enums/game_chat_user_chat_indicator.md) qui représente l'état instantané actuel du chat pour cet utilisateur. L'exemple suivant montre comment récupérer la valeur de l'indicateur d'un objet [chat\_user](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user.md) pointé par la variable `chatUserA` afin de déterminer une valeur de constante d'icône particulière à affecter à une variable `iconToShow`.

```cpp theme={null}
switch (chatUserA->chat_indicator())
{
   case game_chat_user_chat_indicator::silent:
   {
       iconToShow = Icon_InactiveSpeaker;
       break;
   }

   case game_chat_user_chat_indicator::talking:
   {
       iconToShow = Icon_ActiveSpeaker;
       break;
   }

   case game_chat_user_chat_indicator::local_microphone_muted:
   {
       iconToShow = Icon_MutedSpeaker;
       break;
   }
   ...
}
```

La valeur signalée par [chat\_user::chat\_indicator()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/methods/chat_user_chat_indicator.md) est appelée à changer fréquemment, par exemple lorsque les joueurs commencent et arrêtent de parler.
Elle est donc conçue pour permettre aux applications de l'interroger à chaque trame d'interface utilisateur.

## Coupure du son

La méthode [chat\_user::chat\_user\_local::set\_microphone\_muted()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_microphone_muted.md) permet de modifier l'état de coupure du microphone d'un utilisateur local. Lorsque le microphone est coupé, aucun audio n'est capturé à partir de ce microphone. Si l'utilisateur se trouve sur un appareil partagé, comme Kinect, l'état de coupure s'applique à tous les utilisateurs.

La méthode [chat\_user::chat\_user\_local::microphone\_muted()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_microphone_muted.md) permet de récupérer l'état de coupure du microphone d'un utilisateur local. Cette méthode indique uniquement si le microphone de l'utilisateur local a été coupé de manière logicielle via un appel à `chat_user::chat_user_local::set_microphone_muted()`. Elle ne reflète pas une coupure contrôlée par le matériel, par exemple via un bouton du casque de l'utilisateur.

Il n'existe aucune méthode permettant de récupérer l'état de coupure matérielle de l'appareil audio d'un utilisateur via Game Chat 2.

La méthode [chat\_user::chat\_user\_local::set\_remote\_user\_muted()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_remote_user_muted.md) permet de modifier l'état de coupure d'un utilisateur distant vis-à-vis d'un utilisateur local particulier. Lorsque l'utilisateur distant est rendu muet, l'utilisateur local n'entend aucun audio et ne reçoit aucun message texte de sa part.

## Coupure automatique en cas de mauvaise réputation

En règle générale, les utilisateurs distants ne sont pas rendus muets au départ.
Game Chat 2 démarre les utilisateurs à l'état muet lorsque :

1. L'utilisateur distant n'est pas ami avec l'utilisateur local.
2. L'utilisateur distant présente un indicateur de mauvaise réputation.

Lorsque des utilisateurs sont rendus muets en raison de cette opération, `chat_user::chat_indicator()` renvoie `game_chat_user_chat_indicator::reputation_restricted`.
Cet état est remplacé par le premier appel à `chat_user::chat_user_local::set_remote_user_muted()` qui inclut l'utilisateur distant comme utilisateur cible.

## Privilèges et confidentialité

En plus de la relation de communication configurée par le jeu, Game Chat 2 applique les restrictions de privilèges et de confidentialité.
Game Chat 2 effectue les recherches de restrictions de privilèges et de confidentialité lors du premier ajout d'un utilisateur. La méthode `chat_user::chat_indicator()` de l'utilisateur renvoie toujours `game_chat_user_chat_indicator::silent` jusqu'à ce que ces opérations soient terminées.

Si la communication avec un utilisateur est affectée par une restriction de privilèges ou de confidentialité, la méthode `chat_user::chat_indicator()` de l'utilisateur renvoie `game_chat_user_chat_indicator::platform_restricted`.
Les restrictions de communication de la plateforme s'appliquent à la fois au chat vocal et au chat textuel. Il n'existe aucun cas où le chat textuel serait bloqué par une restriction de la plateforme sans que le chat vocal le soit, ou inversement.

[chat\_user::chat\_user\_local::get\_effective\_communication\_relationship()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_get_effective_communication_relationship.md) permet de déterminer si des utilisateurs ne peuvent pas communiquer parce que les opérations de privilèges et de confidentialité ne sont pas terminées.
Elle renvoie la relation de communication appliquée par Game Chat 2 sous la forme de [game\_chat\_communication\_relationship\_flags](https://docs.xbox.com/fr/reference/chat/gamechat2/enums/game_chat_communication_relationship_flags.md), ainsi que la raison pour laquelle cette relation peut différer de la relation configurée, sous la forme d'une énumération [game\_chat\_communication\_relationship\_adjuster](https://docs.xbox.com/fr/reference/chat/gamechat2/enums/game_chat_communication_relationship_adjuster.md).

Par exemple, si les opérations de recherche sont toujours en cours, la valeur de [game\_chat\_communication\_relationship\_adjuster](https://docs.xbox.com/fr/reference/chat/gamechat2/enums/game_chat_communication_relationship_adjuster.md) sera `game_chat_communication_relationship_adjuster::initializing`.
Cette méthode ne doit pas être utilisée pour influencer l'interface utilisateur. (Pour plus d'informations, consultez la section [Interface utilisateur](#ui) plus haut dans cette rubrique.)

Si Game Chat 2 rencontre un problème de privilèges, celui-ci est signalé dans le changement d'état [communication\_relationship\_adjuster\_changed](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_stream_state_change.md).

Si Game Chat 2 ne parvient pas à récupérer les privilèges de l'utilisateur pour une raison irrémédiable, cela est signalé sous la forme d'un ajusteur `game_chat_communication_relationship_adjuster::privilege_check_failure`.

Si Game Chat 2 ne parvient pas à récupérer les privilèges de l'utilisateur pour une raison que l'utilisateur pourrait résoudre, cela est signalé sous la forme d'un ajusteur `game_chat_communication_relationship_adjuster::resolve_user_issue`.

S'il manque à l'utilisateur des privilèges qui pourraient être résolus au moyen d'une interface utilisateur, cela est signalé sous la forme d'un ajusteur `game_chat_communication_relationship_adjuster::privilege`.

Dans ces cas, la communication est restreinte.

Voici un exemple montrant comment vérifier si un utilisateur rencontre l'un des problèmes courants suivants.

1. Les utilisateurs doivent donner leur consentement aux services XBOX pour que Game Chat 2 puisse vérifier les privilèges.
2. Le compte de l'utilisateur est configuré pour refuser des privilèges (par exemple, s'il s'agit d'un compte enfant qui ne peut donc pas utiliser le chat).

```cpp theme={null}
void
HandleAdjusterChangedStateReceived (
    _In_ const Xs::game_chat_2::game_chat_communication_relationship_adjuster_changed_state_change* adjusterChange,
    _Inout_ std::list<Xs::game_chat_2::chat_user*>& usersWithPrivilegeIssues,
    _Inout_ std::list<Xs::game_chat_2::chat_user*>& usersWithPrivilegeCheckIssues
    )
{
    Xs::game_chat_2::game_chat_communication_relationship_flags communicationRelationship;
    Xs::game_chat_2::game_chat_communication_relationship_adjuster communicationRelationshipAdjuster;
    adjusterChange->local_user->local()->get_effective_communication_relationship(
        adjusterChange->target_user,
        &communicationRelationship,
        &communicationRelationshipAdjuster);

    if (communicationRelationshipAdjuster == Xs::game_chat_2::game_chat_communication_relationship_adjuster::privilege)
    {
        // The local user has privilege issues.
        usersWithPrivilegeIssues.push_back(adjusterChange->local_user);
    }
    else if (communicationRelationshipAdjuster == Xs::game_chat_2::game_chat_communication_relationship_adjuster::resolve_user_issue)
    {
        // The local user has an issue checking privileges.
        usersWithPrivilegeCheckIssues.push_back(adjusterChange->local_user);
    }
}
```

Pour les problèmes signalés avec l'ajusteur `game_chat_communication_relationship_adjuster::privilege`, vous pouvez appeler [XUserResolvePrivilegeWithUiAsync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuserresolveprivilegewithuiasync.md) avec `XUserPrivilegeOptions::None` et `XUserPrivilege::Communications` pour tenter de résoudre le problème.

Pour les problèmes signalés avec l'ajusteur `game_chat_communication_relationship_adjuster::resolve_user_issue`, vous pouvez appeler [XUserResolveIssueWithUiAsync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuserresolveissuewithuiasync.md) avec `nullptr` comme URL pour tenter de résoudre le problème.

Nous vous recommandons d'afficher une interface utilisateur indiquant l'existence d'un problème de privilèges. Laissez l'utilisateur décider s'il souhaite tenter de résoudre le problème, au moyen d'un bouton ou d'une option de menu.

L'utilisateur peut ne pas être en mesure ou ne pas souhaiter résoudre le problème.
Si l'utilisateur résout le problème, la résolution prendra effet la prochaine fois que l'utilisateur sera ajouté à Game Chat 2.

> [!NOTE]
>
> [chat\_manager::remove\_user()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_remove_user.md) ne doit pas être appelée pendant le traitement des changements d'état (c'est-à-dire après l'appel de [chat\_manager::start\_processing\_state\_changes()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_start_processing_state_changes.md) et avant l'appel correspondant de [chat\_manager::finish\_processing\_state\_changes()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_finish_processing_state_changes.md)). L'appel de `chat_manager::remove_user()` pendant le traitement des changements d'état peut invalider la mémoire associée à l'utilisateur retiré.
> Si vous voyez un ajusteur `game_chat_communication_relationship_adjuster::privilege` et souhaitez essayer de résoudre les privilèges de l'utilisateur, vous devez attendre la fin du traitement des changements d'état pour le faire.

Pour obtenir le `XUserHandle` à partir d'un XUID, ce qui est nécessaire pour appeler `XUserResolvePrivilegeWithUiAsync`, vous pouvez utiliser l'API [XUserFindUserById](https://docs.xbox.com/fr/reference/system/xuser/functions/xuserfinduserbyid.md) pour obtenir un nouveau `XUserHandle`. Vous pouvez également conserver celui que vous avez obtenu avec [XUserAddAsync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuseraddasync.md) et suivre le XUID qui lui correspond.

Voici un exemple montrant comment résoudre ces problèmes.

```cpp theme={null}
// If we got an Xs::game_chat_2::game_chat_communication_relationship_adjuster::resolve_user_issue,
// we need to try and fix our issue, if we haven't already, and then remove and re-add that user.
for (Xs::game_chat_2::chat_user* localUser : usersWithPrivilegeCheckIssues)
{
    auto asyncBlock = std::make_unique<XAsyncBlock>();
    ZeroMemory(asyncBlock.get(), sizeof(*asyncBlock));
    asyncBlock->queue = g_asyncQueue;

    XUserHandle userHandle;
    hr = XUserFindUserById(localUser->local()->xbox_user_id(), &userHandle);
    if (SUCCEEDED(hr))
    {
        hr = XUserResolveIssueWithUiAsync(
            userHandle,
            nullptr,
            asyncBlock.get());
        if (SUCCEEDED(hr))
        {
            hr = XAsyncGetStatus(asyncBlock.get(), true);
            if (SUCCEEDED(hr))
            {
                // Remove and re-add the user after fixing the privileges.
                // Users must not be removed while processing state changes.
            }
            asyncBlock.release();
        }
    }
}

// If we got an Xs::game_chat_2::game_chat_communication_relationship_adjuster::resolve_user_privilege,
// we need to try and resolve the privileges, if we haven't already, and then remove and re-add that user.
for (Xs::game_chat_2::chat_user* localUser : usersWithPrivilegeIssues)
{
    auto asyncBlock = std::make_unique<XAsyncBlock>();
    ZeroMemory(asyncBlock.get(), sizeof(*asyncBlock));
    asyncBlock->queue = g_asyncQueue;

    XUserHandle userHandle;
    hr = XUserFindUserById(localUser->local()->xbox_user_id(), &userHandle);
    if (SUCCEEDED(hr))
    {
        hr = XUserResolvePrivilegeWithUiAsync(
            userHandle,
            XUserPrivilegeOptions::None,
            XUserPrivilege::Communications,
            asyncBlock.get());
        if (SUCCEEDED(hr))
        {
            hr = XAsyncGetStatus(asyncBlock.get(), true);
            if (SUCCEEDED(hr))
            {
                // Remove and re-add the user after fixing the privileges.
                // Users must not be removed while processing state changes.
            }
            asyncBlock.release();
        }
    }
}
```

## Nettoyage

Lorsque l'application n'a plus besoin des communications via Game Chat 2, vous devez appeler [chat\_manager::cleanup()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_cleanup.md).
Cela permet à Game Chat 2 de récupérer les ressources qui ont été allouées à la gestion des communications.

## Modèle de défaillance

L'implémentation de Game Chat 2 ne lève pas d'exceptions pour signaler les erreurs non fatales. Vous pouvez donc l'utiliser facilement dans des projets sans exceptions, si vous le souhaitez.
Game Chat 2 lève toutefois des exceptions pour vous informer des erreurs fatales.

Ces erreurs résultent d'une mauvaise utilisation de l'API, comme l'ajout d'un utilisateur à l'instance de Game Chat avant l'initialisation de celle-ci ou l'accès à un objet utilisateur après son retrait de l'instance de Game Chat 2.

Ces erreurs sont censées être détectées tôt dans le développement et peuvent être corrigées en modifiant le modèle utilisé pour interagir avec Game Chat 2.
Lorsqu'une telle erreur se produit, une indication de sa cause est affichée dans le débogueur avant que l'exception soit levée.

## Configuration des scénarios courants

### Appuyer pour parler

La fonctionnalité Appuyer pour parler doit être implémentée à l'aide de [chat\_user::chat\_user\_local::set\_microphone\_muted()](https://docs.xbox.com/fr/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_microphone_muted.md).
Appelez `set_microphone_muted(false)` pour autoriser la parole et `set_microphone_muted(true)` pour la restreindre.
Cette méthode offre la réponse la plus rapide de Game Chat 2.

### Équipes

Supposons que les utilisateurs A et B font partie de l'équipe bleue, et les utilisateurs C et D de l'équipe rouge.
Chaque utilisateur se trouve dans une instance distincte de l'application.

Sur l'appareil de l'utilisateur A :

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserB, c_communicationRelationshipSendAndReceiveAll);
chatUserA->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
chatUserA->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

Sur l'appareil de l'utilisateur B :

```cpp theme={null}
chatUserB->local()->set_communication_relationship(chatUserA, c_communicationRelationshipSendAndReceiveAll);
chatUserB->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
chatUserB->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

Sur l'appareil de l'utilisateur C :

```cpp theme={null}
chatUserC->local()->set_communication_relationship(chatUserA, game_chat_communication_relationship_flags::none);
chatUserC->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserC->local()->set_communication_relationship(chatUserD, c_communicationRelationshipSendAndReceiveAll);
```

Sur l'appareil de l'utilisateur D :

```cpp theme={null}
chatUserD->local()->set_communication_relationship(chatUserA, game_chat_communication_relationship_flags::none);
chatUserD->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserD->local()->set_communication_relationship(chatUserC, c_communicationRelationshipSendAndReceiveAll);
```

### Diffusion

Supposons que l'utilisateur A est le chef et donne des ordres. Les utilisateurs B, C et D peuvent uniquement écouter.
Chaque joueur se trouve sur un appareil distinct.

Sur l'appareil de l'utilisateur A :

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserB, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserC, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserD, c_communicationRelationshipSendAll);
```

Sur l'appareil de l'utilisateur B :

```cpp theme={null}
chatUserB->local()->set_communication_relationship(chatUserA, c_communicationRelationshipReceiveAll);
chatUserB->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
chatUserB->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

Sur l'appareil de l'utilisateur C :

```cpp theme={null}
chatUserC->local()->set_communication_relationship(chatUserA, c_communicationRelationshipReceiveAll);
chatUserC->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserC->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

Sur l'appareil de l'utilisateur D :

```cpp theme={null}
chatUserD->local()->set_communication_relationship(chatUserA, c_communicationRelationshipReceiveAll);
chatUserD->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserD->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
```

## Documentation de référence de l'API

* [Gamechat2 (sommaire de l'API)](https://docs.xbox.com/fr/reference/chat/gamechat2/gamechat2_members.md)
  * Structures
    * [game\_chat\_data\_frame](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_data_frame.md)
    * [game\_chat\_state\_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_state_change.md)
    * [game\_chat\_text\_chat\_received\_state\_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_text_chat_received_state_change.md)
    * [game\_chat\_transcribed\_chat\_received\_state\_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_transcribed_chat_received_state_change.md)
    * [communication\_relationship\_adjuster\_changed](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_stream_state_change.md)
* [xuser (sommaire de l'API)](https://docs.xbox.com/fr/reference/system/xuser/xuser_members.md)
  * Fonctions
    * [xuseraddasync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuseraddasync.md)
    * [xusergetid](https://docs.xbox.com/fr/reference/system/xuser/functions/xusergetid.md)
    * [XUserResolveIssueWithUiAsync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuserresolveissuewithuiasync.md)
    * [XUserResolvePrivilegeWithUiAsync](https://docs.xbox.com/fr/reference/system/xuser/functions/xuserresolveprivilegewithuiasync.md)
    * [XUserFindUserById](https://docs.xbox.com/fr/reference/system/xuser/functions/xuserfinduserbyid.md)

## Voir aussi

[Présentation de Game Chat 2](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/game-chat-2-intro.md)

[Manipulation audio en temps réel](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/real-time-audio-manipulation.md)

[Sommaire de l'API (GameChat2)](https://docs.xbox.com/fr/reference/chat/gamechat2/gamechat2_members.md)

[Microsoft Game Development Kit](https://docs.xbox.com/fr/services/playfab/sdks/platforms/gdk.md)


## Related topics

- [Présentation de Game Chat 2](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/game-chat-2-intro.md)
- [game_chat_data_frame](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_data_frame.md)
- [game_chat_state_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_state_change.md)
- [game_chat_text_chat_received_state_change](https://docs.xbox.com/fr/reference/chat/gamechat2/structs/game_chat_text_chat_received_state_change.md)
- [Vue d'ensemble de Game Chat 2](https://docs.xbox.com/fr/services/xbox-services/multiplayer/chat/game-chat2/game-chat-2-overview.md)
