457 lines
13 KiB
C++
457 lines
13 KiB
C++
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dscrecs.cpp
|
|
* Content:
|
|
* This module contains the implementation of the
|
|
* DirectSoundCaptureRecordSubSystem.
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 07/16/99 rodtoll Created
|
|
* 07/30/99 rodtoll Updated to allow creation w/GUID
|
|
* 09/20/99 rodtoll Added memory allocation failure checks
|
|
* 10/05/99 rodtoll Added DPF_MODNAMEs
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
#include "dscrecs.h"
|
|
#include "dscrecd.h"
|
|
#include "wiutils.h"
|
|
#include "dsutils.h"
|
|
#include "dndbg.h"
|
|
|
|
typedef HRESULT (WINAPI *DSCENUM)(LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext);
|
|
|
|
|
|
// DSCEnumParam
|
|
//
|
|
// This structure is used when enumerating the available DirectSoundCapture
|
|
// Devices. The enumeration function adds to the maps this structure points
|
|
// to.
|
|
//
|
|
struct DSCEnumParam
|
|
{
|
|
CDirectSoundCaptureRecordSubSystem::DSCMap *m_dscMap;
|
|
// Map of ARDID <--> (GUID,waveINID)
|
|
CDirectSoundCaptureRecordSubSystem::DeviceMap *m_deviceMap;
|
|
// Map of ARDID <--> ARDeviceInfo *
|
|
ARDID m_nextID; // The ID the current device
|
|
// will have
|
|
};
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DSCCEnum"
|
|
// DSCCEnum
|
|
//
|
|
// This function is used to enumerate the available DirectSoundCapture devices
|
|
// in a system. It is used to fill a list of information about the available
|
|
// devices in the DirectSoundCapture subsystem. It is also responsible for
|
|
// assigning ARDID's to individual devices.
|
|
//
|
|
// Parameters / Return Values:
|
|
// See documentation for DirectSoundCaptureEnumerate
|
|
//
|
|
BOOL CALLBACK DSCSSEnum(
|
|
LPGUID lpGUID,
|
|
LPCTSTR lpszDesc,
|
|
LPCTSTR lpszDrvName,
|
|
LPVOID lpContext
|
|
) {
|
|
BFC_STRING tmpString;
|
|
|
|
// Ignore the default device
|
|
if( lpGUID == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "DSCSSEnum: Ignore default" );
|
|
return TRUE;
|
|
}
|
|
|
|
// Check to ensure driver / descriptions are not NULL
|
|
if( lpszDesc == NULL || lpszDrvName == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "DSCSSEnum: Ignoring invalid" );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DSCEnumParam *params = (DSCEnumParam *) lpContext;
|
|
|
|
ARDeviceInfo *info = new ARDeviceInfo; // New Device Record
|
|
|
|
if( info == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "DSCSSEnum: Alloc failure" );
|
|
return TRUE;
|
|
}
|
|
|
|
unsigned int deviceID;
|
|
ARDID aID;
|
|
|
|
info->m_deviceName = lpszDesc; // fill in new record
|
|
info->m_emulated = false; // fill in new record
|
|
|
|
aID = params->m_nextID; // asign next available ARDID to this
|
|
// device
|
|
|
|
// Attempt to read the waveIN device ID from the lpszDrvName which usually
|
|
// takes the form waveIN <waveIN ID>. If that's not possible fill in
|
|
// waveIN ID for this device to equal the ARDID for the device
|
|
//
|
|
if( _stscanf( lpszDrvName, "WaveIn %u", &deviceID ) != 1 )
|
|
{
|
|
tmpString = "DSCSSEnum: Device: ";
|
|
tmpString += lpszDrvName;
|
|
tmpString += " Desc: ";
|
|
tmpString += lpszDesc;
|
|
tmpString += " (Can't map)";
|
|
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, BFC_STRING_TOLPSTR( tmpString ) );
|
|
deviceID = aID;
|
|
}
|
|
|
|
// Create records to add to the lists
|
|
std::pair<const ARDID,ARDeviceInfo *> devicePair(aID,info);
|
|
std::pair<const ARDID,CDirectSoundCaptureRecordSubSystem::DSCPair> dscPair(aID,CDirectSoundCaptureRecordSubSystem::DSCPair(*lpGUID,deviceID));
|
|
|
|
// Insert the new record into the lists
|
|
params->m_deviceMap->insert( devicePair );
|
|
params->m_dscMap->insert( dscPair );
|
|
|
|
// Increment the ARDID
|
|
params->m_nextID++;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::CDirectSoundCaptureRecordSubSystem"
|
|
// CDirectSoundCaptureRecordSubSystem
|
|
//
|
|
// This is the constructor for the CDirectSoundCaptureRecordSubSystem
|
|
// object. It is responsible for building the list of available
|
|
// devices for the DirectSoundCapture sub-system as well as determining
|
|
// if DirectSoundCapture is available on the system. If DirectSoundCapture
|
|
// is not available on the system the object's valid flag will be marked
|
|
// as false. The DirectSoundCapture subsystem is also considered to be
|
|
// invalid if there are no available devices.
|
|
//
|
|
// This function does not link to any DirectSoundCapture functions,
|
|
// the DSOUND.DLL available on the system is checked to see if it
|
|
// supports the DirectSoundCapture interfaces. This eliminates need
|
|
// to link to newer DirectSound DLL. (Which is not available on NT).
|
|
//
|
|
// Parameters:
|
|
// N/A
|
|
//
|
|
// Returns:
|
|
// N/A
|
|
//
|
|
CDirectSoundCaptureRecordSubSystem::CDirectSoundCaptureRecordSubSystem()
|
|
{
|
|
BFC_STRING format;
|
|
DSCENUM enumFunc;
|
|
|
|
m_dsDLL = NULL;
|
|
|
|
// Attempt to load the directsound DLL
|
|
m_dsDLL = LoadLibrary( _T("DSOUND.DLL") );
|
|
|
|
// If it couldn't be loaded, this sub system is not supported
|
|
// on this system.
|
|
if( m_dsDLL == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "DSCSS: Unable to load DirectSound" );
|
|
m_valid = false;
|
|
return;
|
|
}
|
|
|
|
// Attempt to get the DirectSoundCaptureEnumerateA function from the
|
|
// DSOUND.DLL. If it's not available then this class assumes it's
|
|
// not supported on this system.
|
|
enumFunc = (DSCENUM) GetProcAddress( m_dsDLL, "DirectSoundCaptureEnumerateA" );
|
|
|
|
if( enumFunc == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "DSCSS: No proc" );
|
|
m_valid = false;
|
|
FreeLibrary( m_dsDLL );
|
|
return;
|
|
}
|
|
|
|
DSCEnumParam param;
|
|
|
|
// Setup the class for the enumeration of available devices.
|
|
param.m_dscMap = &m_dscMap;
|
|
param.m_deviceMap = &m_deviceMap;
|
|
param.m_nextID = 0;
|
|
|
|
// Attempt the enumeration using the enumeration function
|
|
// above using the function pointer provided by GetProcAddress
|
|
try
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "DSCSS: Start" );
|
|
DSCHECK( (*enumFunc)( DSCSSEnum ,¶m) );
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "DSCSS: Done" );
|
|
}
|
|
catch( DirectSoundException &dse )
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "DSCSS: Unable to list" );
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, dse.what() );
|
|
CleanupDeviceMap();
|
|
FreeLibrary( m_dsDLL );
|
|
m_valid = false;
|
|
return;
|
|
}
|
|
|
|
// It is also considered an error if there are no devices available
|
|
if( GetNumDevices() == 0 )
|
|
{
|
|
m_valid = false;
|
|
return;
|
|
}
|
|
|
|
m_valid = true;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::CleanupDeviceMap"
|
|
// CleanupDeviceMap
|
|
//
|
|
// This utility function is used to free the memory associated with the
|
|
// device map within this class.
|
|
//
|
|
// Parameters:
|
|
// N/A
|
|
//
|
|
// Returns:
|
|
// N/A
|
|
//
|
|
void CDirectSoundCaptureRecordSubSystem::CleanupDeviceMap()
|
|
{
|
|
DeviceMapIterator deviceIterator;
|
|
|
|
deviceIterator = m_deviceMap.begin();
|
|
|
|
while( deviceIterator != m_deviceMap.end() )
|
|
{
|
|
delete (*deviceIterator).second;
|
|
deviceIterator++;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::~CDirectSoundCaptureRecordSubSystem"
|
|
// CDirectSoundCaptureRecordSubSystem Destructor
|
|
//
|
|
// This is the destructor for the CDirectSoundCaptureRecordSubSystem
|
|
// class. It frees any memory associated with this subsystem and
|
|
// will unload the directsound DLL if it was loaded by the class.
|
|
//
|
|
// Parameters:
|
|
// N/A
|
|
//
|
|
// Returns:
|
|
// N/A
|
|
//
|
|
CDirectSoundCaptureRecordSubSystem::~CDirectSoundCaptureRecordSubSystem()
|
|
{
|
|
if( m_valid )
|
|
{
|
|
if( m_dsDLL != NULL )
|
|
FreeLibrary( m_dsDLL );
|
|
}
|
|
|
|
CleanupDeviceMap();
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::IsValid"
|
|
// IsValid
|
|
//
|
|
// This function returns the value of this object's valid flag.
|
|
// The valid flag is true if the DirectSoundCapture subsystem
|
|
// is available on this system, false otherwise.
|
|
//
|
|
// Parameters:
|
|
// N/A
|
|
//
|
|
// Returns:
|
|
// bool - value of valid flag.
|
|
//
|
|
bool CDirectSoundCaptureRecordSubSystem::IsValid()
|
|
{
|
|
return m_valid;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::IsValidDevice"
|
|
// IsValidDevice
|
|
//
|
|
// This function allows the caller to ask the DirectSoundCapture subsystem
|
|
// if the specified ARDID is available on this subsystem.
|
|
//
|
|
// Parameters:
|
|
// ARDID deviceID - The ID of the device we want to check
|
|
//
|
|
// Returns:
|
|
// bool - true if the specified device is a valid device in the DirectSoundCapture
|
|
// subsystem, false otherwise.
|
|
//
|
|
bool CDirectSoundCaptureRecordSubSystem::IsValidDevice( ARDID deviceID )
|
|
{
|
|
DeviceMapIterator deviceIterator;
|
|
|
|
deviceIterator = m_deviceMap.begin();
|
|
|
|
if( deviceIterator != m_deviceMap.end() )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::CreateDevice"
|
|
// CreateDevice
|
|
//
|
|
// This function creates an object to represent the device specified by the
|
|
// deviceID parameter. It returns a CAudioRecordDevice * to the object.
|
|
// The object returned is owned by the caller, therefore it must be freed
|
|
// by the process calling this function.
|
|
//
|
|
// Parameters:
|
|
// ARDID deviceID - The identifier of the device for which the user wants
|
|
// to create an object to represent.
|
|
//
|
|
// Returns:
|
|
// CAudioRecordDevice * - A CAudioRecordDevice pointer to a newly allocated
|
|
// and constructed CDirectSoundCaptureRecordDevice,
|
|
// or NULL on failure.
|
|
//
|
|
CAudioRecordDevice *CDirectSoundCaptureRecordSubSystem::CreateDevice( ARDID deviceID )
|
|
{
|
|
if( IsValidDevice( deviceID ) )
|
|
{
|
|
DeviceMapIterator deviceIterator;
|
|
DSCMapIterator dcsIterator;
|
|
GUID tmpGUID;
|
|
|
|
deviceIterator = m_deviceMap.find( deviceID );
|
|
dcsIterator = m_dscMap.find( deviceID );
|
|
|
|
DNASSERT( deviceIterator != m_deviceMap.end() );
|
|
DNASSERT( dcsIterator != m_dscMap.end() );
|
|
|
|
tmpGUID = (*dcsIterator).second.first;
|
|
|
|
// Create the object with the appropriate parameters
|
|
return new CDirectSoundCaptureRecordDevice( tmpGUID, (*dcsIterator).second.second, deviceID, false );
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::GetDeviceInfo"
|
|
// GetDeviceInfo
|
|
//
|
|
// This function retrieves the ARDeviceInfo structure for the specified device identifier.
|
|
//
|
|
// Parameters:
|
|
// ARDID deviceID -
|
|
// The device identifier for the device you wish to retrieve information about
|
|
//
|
|
// ARDeviceInfo &device -
|
|
// A ARDeviceINfo structure which will be filled with the details of the specified
|
|
// device on success.
|
|
//
|
|
// Returns:
|
|
// bool - true if the specified device was valid and information was returned, false
|
|
// otherwise.
|
|
//
|
|
bool CDirectSoundCaptureRecordSubSystem::GetDeviceInfo( ARDID deviceID, ARDeviceInfo &device )
|
|
{
|
|
DeviceMapIterator deviceIterator;
|
|
|
|
deviceIterator = m_deviceMap.find(deviceID);
|
|
|
|
if( deviceIterator != m_deviceMap.end() )
|
|
{
|
|
device = *((*deviceIterator).second);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::GetNumDevices"
|
|
// GetNumDevices
|
|
//
|
|
// This function returns the number of valid devices detected in the DirectSoundCapture
|
|
// subsystem.
|
|
//
|
|
// Parameters:
|
|
// N/A
|
|
//
|
|
// Returns:
|
|
// unsigned int - Number of devices available in the DirectSOundCapture subsystem.
|
|
unsigned int CDirectSoundCaptureRecordSubSystem::GetNumDevices()
|
|
{
|
|
return m_deviceMap.size();
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::GetSubSystemName"
|
|
// GetSubSystemName
|
|
//
|
|
// This function returns the string name which identifies the sub system
|
|
// this class is implementing. In this case it will always return
|
|
// the string "DirectSoundCapture".
|
|
//
|
|
// Parameters:
|
|
// N/A
|
|
//
|
|
// Returns:
|
|
// const TCHAR * = "DirectSoundCapture"
|
|
//
|
|
const TCHAR *CDirectSoundCaptureRecordSubSystem::GetSubSystemName()
|
|
{
|
|
return _T("DirectSoundCapture");
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDirectSoundCaptureRecordSubSystem::CreateDevice"
|
|
CAudioRecordDevice *CDirectSoundCaptureRecordSubSystem::CreateDevice( LPGUID lpGUID )
|
|
{
|
|
if( lpGUID == NULL )
|
|
{
|
|
return CreateDevice( (ARDID) 0 );
|
|
}
|
|
|
|
DSCMapIterator dsIterator = m_dscMap.begin();
|
|
|
|
while( dsIterator != m_dscMap.end() )
|
|
{
|
|
if( (*dsIterator).second.first == *lpGUID )
|
|
{
|
|
return CreateDevice( (*dsIterator).first );
|
|
}
|
|
|
|
dsIterator++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|