sfxDSProvider.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "sfx/sfxProvider.h"
  23. #include "sfx/dsound/sfxDSDevice.h"
  24. #include "core/util/safeRelease.h"
  25. #include "console/console.h"
  26. #include "core/strings/unicode.h"
  27. #include "core/util/safeDelete.h"
  28. #include "core/module.h"
  29. class SFXDSProvider : public SFXProvider
  30. {
  31. public:
  32. SFXDSProvider()
  33. : SFXProvider( "DirectSound" ) {}
  34. virtual ~SFXDSProvider();
  35. void init();
  36. protected:
  37. DSoundFNTable mDSound;
  38. struct DSDeviceInfo : SFXDeviceInfo
  39. {
  40. GUID* guid;
  41. DSCAPS caps;
  42. };
  43. static BOOL CALLBACK dsEnumProc(
  44. LPGUID lpGUID,
  45. LPCTSTR lpszDesc,
  46. LPCTSTR lpszDrvName,
  47. LPVOID lpContext );
  48. void addDeviceDesc( GUID* guid, const String& name, const String& desc );
  49. public:
  50. SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers );
  51. };
  52. MODULE_BEGIN( DirectSound )
  53. MODULE_INIT_BEFORE( SFX )
  54. MODULE_SHUTDOWN_AFTER( SFX )
  55. SFXDSProvider* mProvider;
  56. MODULE_INIT
  57. {
  58. mProvider = new SFXDSProvider;
  59. }
  60. MODULE_SHUTDOWN
  61. {
  62. delete mProvider;
  63. }
  64. MODULE_END;
  65. //------------------------------------------------------------------------------
  66. // Helper
  67. bool dsBindFunction( DLibrary *dll, void *&fnAddress, const char *name )
  68. {
  69. fnAddress = dll->bind( name );
  70. if (!fnAddress)
  71. Con::warnf( "DSound Loader: DLL bind failed for %s", name );
  72. return fnAddress != 0;
  73. }
  74. //------------------------------------------------------------------------------
  75. SFXDSProvider::~SFXDSProvider()
  76. {
  77. }
  78. void SFXDSProvider::init()
  79. {
  80. // Grab the functions we'll want from the dsound DLL.
  81. mDSound.dllRef = OsLoadLibrary( "dsound.dll" );
  82. mDSound.isLoaded = true;
  83. #define DS_FUNCTION(fn_name, fn_return, fn_args) \
  84. mDSound.isLoaded &= dsBindFunction(mDSound.dllRef, *(void**)&mDSound.fn_name, #fn_name);
  85. #include "sfx/dsound/dsFunctions.h"
  86. #undef DS_FUNCTION
  87. AssertISV( mDSound.isLoaded, "DirectSound failed to load." );
  88. // All we need to do to init is enumerate the
  89. // devices... if this fails then don't register
  90. // the provider as it's broken in some way.
  91. if ( FAILED( mDSound.DirectSoundEnumerate( dsEnumProc, (VOID*)this ) ) )
  92. {
  93. Con::errorf( "SFXDSProvider - Device enumeration failed!" );
  94. return;
  95. }
  96. // Did we get any devices?
  97. if ( mDeviceInfo.empty() )
  98. {
  99. Con::errorf( "SFXDSProvider - No valid devices found!" );
  100. return;
  101. }
  102. // Wow, we made it - register the provider.
  103. regProvider( this );
  104. }
  105. BOOL CALLBACK SFXDSProvider::dsEnumProc(
  106. LPGUID lpGUID,
  107. LPCTSTR lpszDesc,
  108. LPCTSTR lpszDrvName,
  109. LPVOID lpContext )
  110. {
  111. SFXDSProvider* provider = (SFXDSProvider*)lpContext;
  112. provider->addDeviceDesc( lpGUID, lpszDrvName, lpszDesc );
  113. return TRUE;
  114. }
  115. void SFXDSProvider::addDeviceDesc( GUID* guid, const String& name, const String& desc )
  116. {
  117. // Create a dummy device to get the caps.
  118. IDirectSound8* dsound;
  119. HRESULT hr = mDSound.DirectSoundCreate8( guid, &dsound, NULL );
  120. if ( FAILED( hr ) || !dsound )
  121. return;
  122. // Init the caps structure and have the device fill it out.
  123. DSCAPS caps;
  124. dMemset( &caps, 0, sizeof( caps ) );
  125. caps.dwSize = sizeof( caps );
  126. hr = dsound->GetCaps( &caps );
  127. // Clean up and handle errors.
  128. SAFE_RELEASE( dsound );
  129. if ( FAILED( hr ) )
  130. return;
  131. // Now, record the desc info into our own internal list.
  132. DSDeviceInfo* info = new DSDeviceInfo;
  133. info->name = desc;
  134. info->driver = name;
  135. info->hasHardware = caps.dwMaxHw3DAllBuffers > 0;
  136. info->maxBuffers = caps.dwMaxHw3DAllBuffers;
  137. info->guid = guid;
  138. info->caps = caps;
  139. mDeviceInfo.push_back( info );
  140. }
  141. SFXDevice* SFXDSProvider::createDevice( const String& deviceName, bool useHardware, S32 maxBuffers )
  142. {
  143. DSDeviceInfo* info = dynamic_cast< DSDeviceInfo* >
  144. ( _findDeviceInfo( deviceName ) );
  145. if( !info )
  146. return NULL;
  147. SFXDSDevice* device = new SFXDSDevice( this,
  148. &mDSound,
  149. info->guid,
  150. info->name,
  151. useHardware,
  152. maxBuffers );
  153. if( !device->_init() )
  154. SAFE_DELETE( device );
  155. return device;
  156. }