2025-04-27 07:49:33 -04:00

376 lines
10 KiB
C++

/*==========================================================================
*
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
*
* File: dsplays.cpp
* Content:
* This module contains the implementation of the
* CDirectSoundPlaybackSubSystem.
*
* History:
* Date By Reason
* ==== == ======
* 07/16/99 rodtoll Created
* 07/30/99 rodtoll Updated to allow creation with a GUID
* 09/20/99 rodtoll Added memory allocation failure checks
* 10/05/99 rodtoll Added DPF_MODNAMEs
*
***************************************************************************/
#include "stdafx.h"
#include "dsplays.h"
#include "dsplayd.h"
#include "dsutils.h"
#include "dndbg.h"
#include "OSInd.h"
// DSCEnumParam
//
// This structure is used when enumerating the available DirectSound
// Devices. The enumeration function adds to the maps this structure points
// to.
//
struct DSEnumParam
{
CDirectSoundPlaybackSubSystem::DSMap *m_dsMap;
CDirectSoundPlaybackSubSystem::DeviceMap *m_deviceMap;
ARDID m_nextID;
};
#undef DPF_MODNAME
#define DPF_MODNAME "DSSSEnum"
// DSSSEnum
//
// This function is used to enumerate the available DirectSound devices
// in a system. It fills the device map with a list of information about the
// available devices in the DirectSound subsystem. It is also responsible for
// assigning ARDID's to individual devices.
//
// Parameters / Return Values:
// See documentation for DirectSoundEnumerate
//
BOOL CALLBACK DSSSEnum(
LPGUID lpGUID,
LPCTSTR lpszDesc,
LPCTSTR lpszDrvName,
LPVOID lpContext
) {
// Ignore the default device, it's always there
if( lpGUID == NULL )
{
DPFX(DPFPREP, DVF_INFOLEVEL, "DSSSEnum: Ignore default" );
return TRUE;
}
// Ignore entries with NULL descriptions or driver
// names
if( lpszDesc == NULL || lpszDrvName == NULL )
{
DPFX(DPFPREP, DVF_INFOLEVEL, "DSSSEnum: Ignoring invalid" );
return TRUE;
}
DSEnumParam *params = (DSEnumParam *) lpContext;
// Create and fill the device info for this device
ARDeviceInfo *info = new ARDeviceInfo;
ARDID aID;
if( info == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc failure for new device record" );
return TRUE;
}
info->m_deviceName = lpszDesc;
info->m_emulated = false;
// Assign device the next ARDID
aID = params->m_nextID;
std::pair<const ARDID,ARDeviceInfo *> devicePair(aID,info);
std::pair<const ARDID,GUID> dsPair(aID,*lpGUID);
// Add the device to the device map
params->m_deviceMap->insert( devicePair );
params->m_dsMap->insert( dsPair );
// Increment the ARDID so next device gets next id
params->m_nextID++;
return TRUE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackSubSystem::CDirectSoundPlaybackSubSystem"
// CDirectSoundPlaybackSubSystem
//
// This is the constructor for the CDirectSoundPlaybackSubSystem
// object. It is responsible for building the list of available
// devices for the DirectSound sub-system as well as determining
// if DirectSound is available on the system. If DirectSound
// is not available on the system the object's valid flag will be marked
// as false. The DirectSound subsystem is also considered to be
// invalid if there are no available devices.
//
// Parameters:
// N/A
//
// Returns:
// N/A
//
CDirectSoundPlaybackSubSystem::CDirectSoundPlaybackSubSystem(): CAudioPlaybackSubSystem()
{
DSEnumParam param;
param.m_dsMap = &m_dsMap;
param.m_deviceMap = &m_deviceMap;
param.m_nextID = 0;
// Enumerate the available devices
try
{
DSCHECK( DirectSoundEnumerate( DSSSEnum, &param ) );
}
catch( DirectSoundException &dse )
{
DPFX(DPFPREP, DVF_INFOLEVEL, "DSSS: Unable to list" );
DPFX(DPFPREP, DVF_ERRORLEVEL, dse.what() );
CleanupDeviceMap();
m_valid = false;
return;
}
// Mark as invalid if there are no devices
if( GetNumDevices() == 0 )
{
m_valid = false;
return;
}
m_valid = true;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackSubSystem::CleanupDeviceMap"
// CleanupDeviceMap
//
// This is a utility function, responsible for cleaning up the
// memory in the device map contained in this object.
//
// Parameters:
// N/A
//
// Returns:
// N/A
//
void CDirectSoundPlaybackSubSystem::CleanupDeviceMap()
{
DeviceMapIterator deviceIterator;
deviceIterator = m_deviceMap.begin();
while( deviceIterator != m_deviceMap.end() )
{
delete (*deviceIterator).second;
deviceIterator++;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackSubSystem::~CDirectSoundPlaybackSubSystem"
// CDirectSoundPlaybackSubSystem Destructor
//
// This is the destructor for the CDirectSoundPlaybackSubSystem
// class. It cleans up the memory used by the device map.
//
// Parameters:
// N/A
//
// Returns:
// N/A
//
CDirectSoundPlaybackSubSystem::~CDirectSoundPlaybackSubSystem()
{
CleanupDeviceMap();
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackSubSystem::IsValidDevice"
// IsValidDevice
//
// This function allows the user to query this object to determine
// if the specified ARDID is valid for this subsystem. If it is,
// the function returns true, otherwise it returns false.
//
// Parameters:
// ARDID deviceID -
// The ARDID for the device you wish to check for.
//
// Returns:
// bool -
// Returns true if the device is available in this subsystem
//
bool CDirectSoundPlaybackSubSystem::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 "CDirectSoundPlaybackSubSystem::CreateDevice"
// CreateDevice
//
// This function acts as a class factory, creating CDirectSoundPlaybackDevice
// objects for devices. It allocates and constructs with the appropriate
// parameters the object and then returns a CAudioPlaybackDevice pointer
// to the new object. The created object is now owned by the caller of the
// function and must be destroyed BEFORE destroying the subsystem object.
//
// Parameters:
// ARDID deviceID -
// Specifies the device the user wishes to create an object for.
//
// Returns:
// CAudioPlaybackDevice * -
// A CAudioPLaybackDevice pointer to a newly created CDirectSoundPlaybackDevice
// object representing the specified device. If the device ID is not valid
// for this subsystem NULL is returned.
//
CAudioPlaybackDevice *CDirectSoundPlaybackSubSystem::CreateDevice( ARDID deviceID )
{
// If the device is valid, create an object
if( IsValidDevice( deviceID ) )
{
DeviceMapIterator deviceIterator;
DSMapIterator dsIterator;
GUID tmpGUID;
// Find the device information structure and the
// GUID of the device to create in the device map
deviceIterator = m_deviceMap.find( deviceID );
dsIterator = m_dsMap.find( deviceID );
BFC_ASSERT( deviceIterator != m_deviceMap.end() );
BFC_ASSERT( dsIterator != m_dsMap.end() );
tmpGUID = (*dsIterator).second;
// Construct the object
return new CDirectSoundPlaybackDevice( tmpGUID, deviceID, false, this );
}
// If the device is not valid, return NULL
else
{
return NULL;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackSubSystem::GetDeviceInfo"
// GetDeviceInfo
//
// This function fills the specified structure with information about the device
// specified in the deviceID parameter, if it is valid for this subsystem. If it
// is not valid for this subsystem then the function returns false.
//
// Parameters:
// ARDID deviceID -
// The device for which we wish to retrieve information
//
// ARDeviceInfo &device -
// The structure to fill with details about the device
//
// Returns:
// bool -
// true if the device is valid and the device structure has been filled with
// the details, false if the device is not valid.
//
bool CDirectSoundPlaybackSubSystem::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 "CDirectSoundPlaybackSubSystem::GetNumDevices"
// GetNumDevices
//
// This function returns the number of devices supported by this playback subsystem.
//
// Parameters:
// N/A
//
// Returns:
// unsigned int - The number of devices supported by this subsystem.
//
unsigned int CDirectSoundPlaybackSubSystem::GetNumDevices()
{
return m_deviceMap.size();
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackSubSystem::GetSubSystemName"
// GetSubSystemName
//
// This function returns a string describing the type of playback subsystem
// implemented by this object. In this case it always returns
// "DirectSound".
//
// Parameters:
// N/A
//
// Returns:
// const TCHAR * - "DirectSound"
//
const TCHAR *CDirectSoundPlaybackSubSystem::GetSubSystemName()
{
return _T("DirectSound");
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackSubSystem::CreateDevice"
CAudioPlaybackDevice *CDirectSoundPlaybackSubSystem::CreateDevice( LPGUID lpGUID )
{
if( lpGUID == NULL )
{
return CreateDevice( (ARDID) 0 );
}
DSMapIterator dsIterator = m_dsMap.begin();
while( dsIterator != m_dsMap.end() )
{
if( (*dsIterator).second == *lpGUID )
{
return CreateDevice( (*dsIterator).first );
}
dsIterator++;
}
return NULL;
}