/*========================================================================== * * 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 devicePair(aID,info); std::pair 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, ¶m ) ); } 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; }