windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dvoice/dxvhelp/dxvhelp.cpp
2020-09-26 16:20:57 +08:00

597 lines
15 KiB
C++

/*==========================================================================
*
* Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
*
* File: dvretro.c
* Content: Retrofit functions
* History:
*
* Date By Reason
* ==== == ======
* 08/12/99 rodtoll created it
* 08/19/99 rodtoll Updated lobby launching to support retrofit
* 08/20/99 rodtoll Modified to respond to shutdown request and
* do proper lobby launch when in client mode.
* 08/25/99 rodtoll Updated to use new GUID based compression selection
* 09/14/99 rodtoll Updated for new Init call and SoundDeviceInfo usage.
* 09/27(8)/99 rodtoll Updated with new interface
* 09/28/99 rodtoll Updated for structure changes.
* 09/29/99 rodtoll Updated for async enum, fixed bug with lobby launch
* 10/15/99 rodtoll Massive code cleanup. Split into multiple files
* rodtoll Minor fix, event was being released twice
* 10/20/99 rodtoll Fixed name info for helper app
* 11/02/99 rodtoll Bug #116677 - Can't use lobby clients that don't hang around
* 11/04/99 pnewson Bug #115297 - launch device test if required
* 11/12/99 rodtoll Added support for the new waveIN/waveOut flags and the
* echo suppression flag. (Can specify them on command-line)
* 12/01/99 rodtoll Bug #115783 - Regardless of device specified always adjusts volume
* for default. Modified dpvhelp to allow user to select play/record
* devices by using /SS switch.
* 12/07/99 rodtoll Bug #122628 Make error messages silent when running in silent mode
* rodtoll Bug #122979 Make invisible to end user
* Now app must be run with /A to show an interface.
* Also, unless /A or /L or /W are specified, the app will exit immediately.
* Command-line help removed.
* Auto-registration code removed for public version of app.
* 02/15/2000 rodtoll Bug #132715 Voice is not working after rejoining the session
* 03/03/2000 rodtoll Updated to handle alternative gamevoice build.
* 06/28/2000 rodtoll Prefix Bug #38033
*
***************************************************************************/
#include "dxvhelppch.h"
#define MAX_LOADSTRING 100
#define DPVHELP_WINDOWTITLE _T("DirectPlay Voice Chat")
#define DPVHELP_WINDOWCLASS _T("DPVHELP")
#define DPVHELP_PRIVATE_APPNAME _T("DirectPlay Voice Chat (Retrofit)")
#define DPVHELP_PRIVATE_DESC _T("DirectPlay Voice Chat (Retrofit)")
#define DPVHELP_PRIVATE_EXENAME _T("dpvhelp.exe")
#define DPVHELP_PRIVATE_COMMANDLINE _T("/L /S /SC03")
#define DPVHELP_PRIVATE_FLAGS 0x80000002
#undef DPF_MODNAME
#define DPF_MODNAME "InitializeRunTime"
void InitializeRunTime( PDXVHELP_RTINFO prtInfo )
{
prtInfo->hReceiveEvent = NULL;
prtInfo->hThreadDone = CreateEvent( NULL, TRUE, FALSE, NULL );
prtInfo->hShutdown = CreateEvent( NULL, TRUE, FALSE, NULL );
prtInfo->hGo = CreateEvent( NULL, FALSE, FALSE, NULL );
prtInfo->hMainDialog = NULL;
prtInfo->dpidLocalPlayer = 0xFFFFFFFF;
prtInfo->lVolumeHeight = 0;
prtInfo->hInst = NULL;
prtInfo->hMainWnd = NULL;
prtInfo->dwNumClients = 0;
prtInfo->lpdpLobby = NULL;
prtInfo->lpdvClient = NULL;
prtInfo->lpdvServer = NULL;
prtInfo->lpdpDirectPlay = NULL;
prtInfo->hLobbyEvent = NULL;
}
#undef DPF_MODNAME
#define DPF_MODNAME "FreeRunTime"
void FreeRunTime( PDXVHELP_RTINFO prtInfo )
{
CloseHandle( prtInfo->hThreadDone );
CloseHandle( prtInfo->hShutdown );
CloseHandle( prtInfo->hGo );
}
#undef DPF_MODNAME
#define DPF_MODNAME "SetDefaultParameters"
void SetDefaultParameters( PDXVHELP_PARAMETERS pParameters )
{
pParameters->fHost = FALSE;
pParameters->fLobbyLaunched = FALSE;
pParameters->fSilent = TRUE;
pParameters->dwSessionType = DVSESSIONTYPE_PEER;
pParameters->guidCT = DPVCTGUID_DEFAULT;
pParameters->lpszConnectAddress[0] = 0;
pParameters->fAGC = TRUE;
pParameters->fAdvancedUI = FALSE;
pParameters->fWaitForSettings = FALSE;
pParameters->lRecordVolume = DSBVOLUME_MAX;
pParameters->fRegister = FALSE;
pParameters->fUnRegister = FALSE;
pParameters->fKill = FALSE;
pParameters->fIgnoreLobbyDestroy = FALSE;
pParameters->fAllowWaveOut = FALSE;
pParameters->fForceWaveOut = FALSE;
pParameters->fAllowWaveIn = FALSE;
pParameters->fForceWaveIn = FALSE;
pParameters->fEchoSuppression = FALSE;
pParameters->fAutoSelectMic = TRUE;
pParameters->guidPlaybackDevice = DSDEVID_DefaultVoicePlayback;
pParameters->guidRecordDevice = DSDEVID_DefaultVoiceCapture;
pParameters->fSelectCards = FALSE;
pParameters->fStrictFocus = FALSE;
pParameters->fDisableFocus = FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "ProcessCommandLine"
BOOL ProcessCommandLine( PSTR pstrCommandLine, PDXVHELP_PARAMETERS pParameters )
{
PSTR pNextToken = NULL;
pNextToken = _tcstok( pstrCommandLine, _T(" ") );
while( pNextToken != NULL )
{
if( _tcsicmp( pNextToken, _T("/A") ) == 0 )
{
pParameters->fAdvancedUI = TRUE;
pParameters->fSilent = FALSE;
}
else if( _tcsicmp( pNextToken, _T("/ES" ) ) == 0 )
{
pParameters->fEchoSuppression = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/WOF") ) == 0 )
{
pParameters->fForceWaveOut = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/NAS") ) == 0 )
{
pParameters->fAutoSelectMic = FALSE;
}
else if( _tcsicmp( pNextToken, _T("/WOA") ) == 0 )
{
pParameters->fAllowWaveOut = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/WIF") ) == 0 )
{
pParameters->fForceWaveIn = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/WIA") ) == 0 )
{
pParameters->fAllowWaveIn = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/ES") ) == 0 )
{
pParameters->fEchoSuppression = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/W") ) == 0 )
{
pParameters->fLobbyLaunched = TRUE;
pParameters->fWaitForSettings = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/L") ) == 0 )
{
pParameters->fLobbyLaunched = TRUE;
pParameters->fWaitForSettings = FALSE;
}
else if( _tcsicmp( pNextToken, _T("/R") ) == 0 )
{
pParameters->fRegister = TRUE;
return FALSE;
}
else if( _tcsicmp( pNextToken, _T("/U") ) == 0 )
{
pParameters->fUnRegister = TRUE;
return FALSE;
}
else if( _tcsicmp( pNextToken, _T("/S") ) == 0 )
{
pParameters->fSilent = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/K") ) == 0 )
{
pParameters->fKill = TRUE;
return FALSE;
}
else if( _tcsicmp( pNextToken, _T("/I") ) == 0 )
{
pParameters->fIgnoreLobbyDestroy = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/GSM") ) == 0 )
{
pParameters->guidCT = DPVCTGUID_GSM;
}
else if( _tcsicmp( pNextToken, _T("/SC03" ) ) == 0 )
{
pParameters->guidCT = DPVCTGUID_SC03;
}
else if( _tcsicmp( pNextToken, _T("/SC06" ) ) == 0 )
{
pParameters->guidCT = DPVCTGUID_SC06;
}
else if( _tcsicmp( pNextToken, _T("/VR12" ) ) == 0 )
{
pParameters->guidCT = DPVCTGUID_VR12;
}
else if( _tcsicmp( pNextToken, _T("/ADPCM" ) ) == 0 )
{
pParameters->guidCT = DPVCTGUID_ADPCM;
}
else if( _tcsicmp( pNextToken, _T("/NONE" ) ) == 0 )
{
pParameters->guidCT = DPVCTGUID_NONE;
}
else if( _tcsicmp( pNextToken, _T("/TRUE" ) ) == 0 )
{
pParameters->guidCT = DPVCTGUID_TRUESPEECH;
}
else if( _tcsicmp( pNextToken, _T("/SS") ) == 0 )
{
pParameters->fSelectCards = TRUE;
}
else if( _tcsicmp( pNextToken, _T("/FS") ) == 0 )
{
pParameters->fStrictFocus = TRUE;
}
else if( _tcsicmp( pNextToken, _T( "/FD" ) ) == 0 )
{
pParameters->fDisableFocus = TRUE;
}
else
{
return FALSE;
}
pNextToken = _tcstok( NULL, _T(" ") );
}
if( !pParameters->fAdvancedUI && !pParameters->fLobbyLaunched )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Can only run in test mode and lobby mode" );
return FALSE;
}
return TRUE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "RegisterApplication"
void RegisterApplication()
{
HRESULT hr;
BOOL fFailed = FALSE;
hr = DPVDX_DP_RegisterApplication( DPVHELP_PRIVATE_APPNAME, DPVHELP_PRIVATE_APPID, DPVHELP_PRIVATE_EXENAME,
DPVHELP_PRIVATE_COMMANDLINE, DPVHELP_PRIVATE_DESC, DPVHELP_PRIVATE_FLAGS );
if( FAILED( hr ) )
{
DPVDX_DPERRDisplay( hr, _T("Unable to register private application"), FALSE );
MessageBox( NULL, _T("Registered Application"), DPVHELP_WINDOWTITLE, MB_OK );
}
if( !fFailed )
{
MessageBox( NULL, _T("Registered Application"), DPVHELP_WINDOWTITLE, MB_OK );
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "UnRegisterApplication"
void UnRegisterApplication()
{
HRESULT hr;
BOOL fFailed = FALSE;
hr = DPVDX_DP_UnRegisterApplication( DPVHELP_PRIVATE_APPID );
if( FAILED( hr ) )
{
DPVDX_DPERRDisplay( hr, _T("Unable to un-register private application"), FALSE );
fFailed = TRUE;
}
if( !fFailed )
{
MessageBox( NULL, _T("Un-Registered Application"), DPVHELP_WINDOWTITLE, MB_OK );
}
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
#undef DPF_MODNAME
#define DPF_MODNAME "MainWindowProc"
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
switch (message)
{
case WM_SHOWWINDOW:
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
#undef DPF_MODNAME
#define DPF_MODNAME "MyRegisterClass"
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0; // CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)MainWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX);
wcex.hCursor = NULL; // LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL; //(LPCSTR)IDC_TESTWIN;
wcex.lpszClassName = DPVHELP_WINDOWCLASS;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_DIRECTX);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
#undef DPF_MODNAME
#define DPF_MODNAME "CreateHiddenMainWindow"
HWND CreateHiddenMainWindow(HINSTANCE hInstance, int nCmdShow )
{
HRESULT hr;
HWND hWnd;
hWnd = CreateWindow(DPVHELP_WINDOWCLASS, DPVHELP_WINDOWTITLE, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
hr = GetLastError();
return NULL;
}
ShowWindow(hWnd, SW_HIDE);
UpdateWindow(hWnd);
return hWnd;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CheckFullDuplex"
BOOL CheckFullDuplex( PDXVHELP_PARAMETERS pParameters )
{
PDIRECTPLAYVOICETEST lpdvSetup;
HRESULT hr;
hr = CoCreateInstance( DPVOICE_CLSID_DPVOICE, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayVoiceTest, (void **) &lpdvSetup );
if( FAILED( hr ) )
{
DPVDX_DVERRDisplay( hr, _T("Create of setup interface failed"), pParameters->fSilent );
return FALSE;
}
hr = lpdvSetup->CheckAudioSetup( &pParameters->guidPlaybackDevice, &pParameters->guidRecordDevice, NULL, DVFLAGS_QUERYONLY );
if( FAILED( hr ) )
{
if( pParameters->fSilent )
{
lpdvSetup->Release();
return FALSE;
}
hr = lpdvSetup->CheckAudioSetup( &pParameters->guidPlaybackDevice, &pParameters->guidRecordDevice, NULL, 0 );
lpdvSetup->Release();
if( FAILED( hr ) )
{
return FALSE;
}
}
else
{
lpdvSetup->Release();
}
return TRUE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "WinMain"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DWORD dwThreadID;
DXVHELP_RTINFO rtInfo;
BOOL bGotMsg = FALSE;
MSG msg;
HRESULT hr;
INITCOMMONCONTROLSEX InitCC = {0};
BOOL bOK = FALSE;
BOOL fRunTimeInit = FALSE;
// Initialize COM
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
if( FAILED( hr ) )
{
return FALSE;
}
if( !DNOSIndirectionInit() )
{
CoUninitialize();
return FALSE;
}
// Setup default parameters
SetDefaultParameters( &rtInfo.dxvParameters );
// Process the command-line
//
// If this function returns false, we are to exit
if( !ProcessCommandLine( lpCmdLine, &rtInfo.dxvParameters ) )
{
if( rtInfo.dxvParameters.fRegister )
{
RegisterApplication();
}
else if( rtInfo.dxvParameters.fUnRegister )
{
UnRegisterApplication();
}
goto EXIT;
}
// Load common-controls
InitCC.dwSize = sizeof InitCC;
bOK = InitCommonControlsEx(&InitCC);
// Register Window Class
MyRegisterClass(hInstance);
// Initialize Events
InitializeRunTime( &rtInfo );
fRunTimeInit = TRUE;
if( rtInfo.dxvParameters.fLobbyLaunched )
{
SetEvent( rtInfo.hGo );
}
// Perform application initialization:
rtInfo.hMainWnd = CreateHiddenMainWindow(hInstance, nCmdShow);
if( rtInfo.hMainWnd == NULL )
{
goto EXIT;
}
rtInfo.hInst = hInstance;
// If user wants to select the soundcard
if( rtInfo.dxvParameters.fSelectCards )
{
GetCardSettings( rtInfo.hInst, NULL, &rtInfo.dxvParameters.guidPlaybackDevice, &rtInfo.dxvParameters.guidRecordDevice );
}
if( !CheckFullDuplex( &rtInfo.dxvParameters ) )
{
goto EXIT;
}
// Startup thread which handles connects etc.
VoiceManager_Start( &rtInfo );
// Display Dialog if Required
if( !rtInfo.dxvParameters.fSilent )
{
MainDialog_Create( &rtInfo );
}
while( MsgWaitForMultipleObjects( 1, &rtInfo.hThreadDone, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0 )
{
bGotMsg = TRUE;
while( bGotMsg )
{
bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
if( bGotMsg )
{
if( rtInfo.hMainDialog == NULL || !IsDialogMessage(rtInfo.hMainDialog,&msg) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
}
VoiceManager_Stop( &rtInfo );
EXIT:
if( fRunTimeInit )
{
FreeRunTime( &rtInfo );
}
DNOSIndirectionDeinit();
CoUninitialize();
return 0;
}