Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
148 lines
7.8 KiB
Plaintext
148 lines
7.8 KiB
Plaintext
//-----------------------------------------------------------------------------
|
|
//
|
|
// Sample Name: VoiceConnect Sample
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
Description
|
|
===========
|
|
VoiceConnect shows how to network other players using DirectPlay to
|
|
start a DirectPlay Voice chat session. After joining or creating a
|
|
session, the players may use computer microphone to talk to one other.
|
|
Other players may join the game in progress at any time.
|
|
|
|
Path
|
|
====
|
|
Source: DXSDK\Samples\Multimedia\DirectPlay\VoiceConnect
|
|
|
|
Executable: DXSDK\Samples\Multimedia\DirectPlay\Bin
|
|
|
|
User's Guide
|
|
============
|
|
Refer to User's Guide section of the SimplePeer sample for information
|
|
on how to connect. After connecting, the host will be presented with a
|
|
dialog to select the voice codec to use. Typical voice applications will
|
|
what automatically select one, or present this to the user in some other
|
|
fashion. Once the chat session has begin, any client may alter the playback
|
|
or capture settings by clicking on "Setup".
|
|
|
|
Programming Notes
|
|
=================
|
|
The VoiceConnect sample is very similar in form to the SimplePeer sample. For
|
|
detailed programming notes on the basics this sample, refer to Programming
|
|
Notes section of the SimplePeer sample.
|
|
|
|
The VoiceConnect differs by letting clients use DirectPlay Voice to talk
|
|
to each other using a computer microphone. Here's how this is done:
|
|
|
|
* Initialize DirectPlayVoice. See NetVoice.cpp
|
|
Before using voice you need a to establish a DirectPlay Voice session.
|
|
So after the DirectPlay session as been created, we call
|
|
CNetVoice::Init(). In this simple sample, we this when
|
|
the main dialog is initializes. This does the following:
|
|
|
|
- Tests the audio setup with DirectPlay Voice.
|
|
See VoiceSessionTestAudioSetup() in NetVoice.cpp.
|
|
1. Creates a IDirectPlayVoiceTest with CoCreateInstance()
|
|
2. Calls IDirectPlayVoiceTest::CheckAudioSetup() with the
|
|
DVFLAGS_QUERYONLY flag. This will return DVERR_RUNSETUP
|
|
if the setup wizard needs to be run. If it happens then
|
|
we call IDirectPlayVoiceTest::CheckAudioSetup() without
|
|
the DVFLAGS_QUERYONLY flag. This will run the dialog
|
|
based DirectPlay Voice setup wizard. If it returns success
|
|
then we can continue on, otherwise handle the error in
|
|
some fashion.
|
|
3. Release the IDirectPlayVoiceTest
|
|
|
|
- If hosting, then we create the voice session:
|
|
See VoiceSessionCreate() in NetVoice.cpp
|
|
1. Create a IDirectPlayVoiceServer with CoCreateInstance().
|
|
Keep this interface around since we'll need it later on.
|
|
2. Call IDirectPlayVoiceServer::Initialize to register the
|
|
voice server message handler. We also pass in the
|
|
DirectPlay interface here.
|
|
3. Fill out a DVSESSIONDESC struct with the session type, and
|
|
the desired voice codec.
|
|
4. Call IDirectPlayVoiceServer::StartSession() passing in
|
|
the DVSESSIONDESC struct.
|
|
|
|
- If either hosting or joining, then connect to the session.
|
|
See VoiceSessionConnect() in NetVoice.cpp
|
|
|
|
1. Create a IDirectPlayVoiceClient with CoCreateInstance()
|
|
Keep this interface around since we'll need it later on.
|
|
2. Call IDirectPlayVoiceClient::Initialize to register the
|
|
voice client message handler. We also pass in the
|
|
DirectPlay interface here.
|
|
3. Fill out a DVSOUNDDEVICECONFIG struct with the guids
|
|
for the DirectSound playback and capture devices.
|
|
3. Fill out a DVCLIENTCONFIG struct. This struct is
|
|
filled out when with setup dlg. More complex apps
|
|
may want to do this a different way. See VoiceConfigDlgProc()
|
|
in VoiceConnect.cpp.
|
|
4. Call IDirectPlayVoiceClient::Connect() with the
|
|
DVSOUNDDEVICECONFIG struct and the DVCLIENTCONFIG struct.
|
|
5. Call IDirectPlayVoiceClient::SetTransmitTargets()
|
|
to the desired default target. This sample sets the
|
|
target to DVID_ALLPLAYERS.
|
|
6. Call IDirectPlayVoiceClient::GetSoundDeviceConfig() and
|
|
check for DVSOUNDCONFIG_HALFDUPLEX to figure out if this
|
|
client is in half-duplex mode. In half-duplex mode, the
|
|
client can not talk, but only listen.
|
|
|
|
* Handle voice client messages. See DirectPlayVoiceClientMessageHandler
|
|
- Upon DVMSGID_CREATEVOICEPLAYER:
|
|
1. Since DPN_MSGID_CREATE_PLAYER set a player context, and that message
|
|
is guaranteed to be processed first. We call GetPlayerContext()
|
|
to get the player's context value and cast the pointer into a
|
|
player struct. We enter a global CS lock here and everytime
|
|
we access a player struct. This is needed to make the struct
|
|
thread safe, since the same player struct may be accessed by
|
|
multiple threads at the same time.
|
|
2. Now that we have the player's struct we addref it. This
|
|
extra count will be for voice layer. Upon DVMSGID_DELETEVOICEPLAYER
|
|
we will release it. This ensures that any voice messages
|
|
that come in will be working with a valid player struct.
|
|
3. We check the DVMSG_CREATEVOICEPLAYER for DVPLAYERCAPS_HALFDUPLEX
|
|
to see if this player is in half-duplex mode. If so, then
|
|
we store that value in the player's struct. Later
|
|
we will update the UI according. See DisplayPlayersInChat()
|
|
for how this is done.
|
|
4. Similar to DirectPlay, DirectPlay Voice stores
|
|
context values for each voice player. So in this sample we
|
|
store the same value in both locations by setting
|
|
pCreateVoicePlayerMsg->pvPlayerContext.
|
|
- Upon DVMSGID_DELETEVOICEPLAYER:
|
|
1. We update the UI accordingly if the local player isn't going away.
|
|
2. We release the player's struct since we addref'ed it
|
|
in DVMSGID_CREATEVOICEPLAYER
|
|
- Upon DVMSGID_HOSTMIGRATED:
|
|
1. If DVMSG_HOSTMIGRATED has a non-NULL pdvServerInterface, then
|
|
we have become the new host. The sample updates the UI to
|
|
show this.
|
|
- Upon DVMSGID_GAINFOCUS and DVMSGID_LOSTFOCUS:
|
|
This means that the app has gained or lost focus. Apps that
|
|
have lost focus can not talk. When focus is re-gained they can.
|
|
In this sample, it updates the UI accordingly.
|
|
- Upon DVMSGID_RECORDSTART
|
|
DVMSGID_RECORDSTOP,
|
|
DVMSGID_PLAYERVOICESTART,
|
|
DVMSGID_PLAYERVOICESTOP:
|
|
These message lets us know when talking has stopped or started for
|
|
the local client, and for remove clients. This sample handles
|
|
these messages by updating the UI accordingly.
|
|
|
|
* Clean up DirectPlay Voice. See bottom of CNetVoice::Free in NetVoice.cpp
|
|
1. Disconnect from the voice session. See VoiceSessionDisconnect()
|
|
- Calls IDirectPlayVoiceClient::Disconnect()
|
|
- Releases the IDirectPlayVoiceClient
|
|
2. Destroy the voice session if this is the host. See VoiceSessionDestroy()
|
|
- Calls IDirectPlayVoiceServer::StopSession()
|
|
- Releases the IDirectPlayVoiceServer
|
|
|
|
|
|
|