Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
wsnd.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * sound card detection on Windows.
25  */
26 
27 #include "precompiled.h"
28 #include "lib/sysdep/snd.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string>
33 #include <set>
34 
35 #include "lib/file/file_system.h"
39 #include "lib/sysdep/os/win/wmi.h"
40 
41 
42 static bool IsOpenAlDllName(const Path::String& name)
43 {
44  // (matches "*oal.dll" and "*OpenAL*", as with OpenAL router's search)
45  return name.find(L"oal.dll") != Path::String::npos || name.find(L"OpenAL") != Path::String::npos;
46 }
47 
48 // ensures each OpenAL DLL is only listed once (even if present in several
49 // directories on our search path).
50 typedef std::set<Path::String> StringSet;
51 
52 // find all OpenAL DLLs in a dir.
53 // call in library search order (exe dir, then win sys dir); otherwise,
54 // DLLs in the executable's starting directory hide those of the
55 // same name in the system directory.
56 static void add_oal_dlls_in_dir(const OsPath& path, StringSet& dlls, VersionList& versionList)
57 {
58  CFileInfos files;
59  (void)GetDirectoryEntries(path, &files, 0);
60  for(size_t i = 0; i < files.size(); i++)
61  {
62  const Path::String name = files[i].Name().string();
63  if(!IsOpenAlDllName(name))
64  continue;
65 
66  // already in StringSet (i.e. has already been wdll_ver_list_add-ed)
67  std::pair<StringSet::iterator, bool> ret = dlls.insert(name);
68  if(!ret.second) // insert failed - element already there
69  continue;
70 
71  wdll_ver_Append(path / name, versionList);
72  }
73 }
74 
75 
76 //-----------------------------------------------------------------------------
77 // DirectSound driver version
78 
79 // we've seen audio problems caused by buggy DirectSound drivers (because
80 // OpenAL can use them in its implementation), so their version should be
81 // retrieved as well. the only way I know of is to enumerate all DS devices.
82 //
83 // unfortunately this fails with Vista's DS emulation - it returns some
84 // GUID crap as the module name. to avoidc crashing when attempting to get
85 // the version info for that bogus driver path, we'll skip this code there.
86 // (delay-loading dsound.dll eliminates any overhead)
87 
89 
90 // store sound card name and path to DirectSound driver.
91 // called for each DirectSound driver, but aborts after first valid driver.
92 static BOOL CALLBACK DirectSoundCallback(void* guid, const wchar_t* UNUSED(description),
93  const wchar_t* module, void* UNUSED(cbData))
94 {
95  // skip first dummy entry (description == "Primary Sound Driver")
96  if(guid == NULL)
97  return TRUE; // continue calling
98 
99  // note: $system\\drivers is not in LoadLibrary's search list,
100  // so we have to give the full pathname.
101  directSoundDriverPath = wutil_SystemPath()/"drivers" / module;
102 
103  // we assume the first "driver name" (sound card) is the one we want;
104  // stick with that and stop calling.
105  return FALSE;
106 }
107 
109 {
110 #define DS_OK 0
111  typedef BOOL (CALLBACK* LPDSENUMCALLBACKW)(void*, const wchar_t*, const wchar_t*, void*);
112  HMODULE hDsoundDll = LoadLibraryW(L"dsound.dll");
113  WUTIL_FUNC(pDirectSoundEnumerateW, HRESULT, (LPDSENUMCALLBACKW, void*));
114  WUTIL_IMPORT(hDsoundDll, DirectSoundEnumerateW, pDirectSoundEnumerateW);
115  if(pDirectSoundEnumerateW)
116  {
117  HRESULT ret = pDirectSoundEnumerateW(DirectSoundCallback, (void*)0);
118  ENSURE(ret == DS_OK);
119  }
120  FreeLibrary(hDsoundDll);
121 
122  return directSoundDriverPath;
123 }
124 
125 //-----------------------------------------------------------------------------
126 
128 {
129  WmiInstances instances;
130  RETURN_STATUS_IF_ERR(wmi_GetClassInstances(L"Win32_SoundDevice", instances));
131  std::set<std::wstring> names; // get rid of duplicate "High Definition Audio Device" entries
132  for(WmiInstances::iterator it = instances.begin(); it != instances.end(); ++it)
133  {
134  if((*it)[L"Availability"].intVal != 8) // not offline
135  names.insert(std::wstring((*it)[L"ProductName"].bstrVal));
136  }
137  wchar_t* pos = snd_card;
138  for(std::set<std::wstring>::const_iterator it = names.begin(); it != names.end(); ++it)
139  {
140  const int ret = swprintf_s(pos, SND_CARD_LEN-(pos-snd_card), L"%ls; ", it->c_str());
141  if(ret > 0)
142  pos += ret;
143  }
144 
145  // find all DLLs related to OpenAL and retrieve their versions.
146  VersionList versionList;
149  StringSet dlls; // ensures uniqueness
150  (void)add_oal_dlls_in_dir(wutil_ExecutablePath(), dlls, versionList);
151  (void)add_oal_dlls_in_dir(wutil_SystemPath(), dlls, versionList);
152  wcscpy_s(snd_drv_ver, SND_DRV_VER_LEN, versionList.c_str());
153 
154  return INFO::OK;
155 }
static BOOL CALLBACK DirectSoundCallback(void *guid, const wchar_t *description, const wchar_t *module, void *cbData)
Definition: wsnd.cpp:92
#define WUTIL_IMPORT(hModule, procName, varName)
Definition: wutil.h:55
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
const Status OK
Definition: status.h:386
const size_t SND_CARD_LEN
Definition: snd.h:30
#define WUTIL_FUNC(varName, ret, params)
Definition: wutil.h:44
Status GetDirectoryEntries(const OsPath &path, CFileInfos *files, DirectoryNames *subdirectoryNames)
Definition: file_system.cpp:87
int swprintf_s(wchar_t *buf, size_t max_chars, const wchar_t *fmt,...) WPRINTF_ARGS(3)
std::set< Path::String > StringSet
Definition: wsnd.cpp:50
int BOOL
Definition: wgl.h:51
std::vector< WmiInstance > WmiInstances
Definition: wmi.h:42
int wcscpy_s(wchar_t *dst, size_t max_dst_chars, const wchar_t *src)
size_t wversion_Number()
Definition: wversion.cpp:65
const size_t SND_DRV_VER_LEN
Definition: snd.h:36
#define DS_OK
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
#define CALLBACK
Definition: wgl.h:39
void wdll_ver_Append(const OsPath &pathname, VersionList &list)
Read DLL version information and append it to a string.
Definition: wdll_ver.cpp:85
Definition: path.h:75
Status wmi_GetClassInstances(const wchar_t *className, WmiInstances &instances)
get all instances of the requested class.
Definition: wmi.cpp:106
std::wstring String
Definition: path.h:78
static bool IsOpenAlDllName(const Path::String &name)
Definition: wsnd.cpp:42
i64 Status
Error handling system.
Definition: status.h:171
static void add_oal_dlls_in_dir(const OsPath &path, StringSet &dlls, VersionList &versionList)
Definition: wsnd.cpp:56
wchar_t snd_drv_ver[SND_DRV_VER_LEN]
sound driver identification and version.
Definition: snd.cpp:36
wchar_t snd_card[SND_CARD_LEN]
description of sound card.
Definition: snd.cpp:35
std::wstring VersionList
Definition: wdll_ver.h:32
const OsPath & wutil_ExecutablePath()
Definition: wutil.cpp:263
const OsPath & wutil_SystemPath()
Definition: wutil.cpp:258
Status win_get_snd_info()
Definition: wsnd.cpp:127
std::vector< CFileInfo > CFileInfos
Definition: file_system.h:76
static const OsPath & GetDirectSoundDriverPath()
Definition: wsnd.cpp:108
static OsPath directSoundDriverPath
Definition: wsnd.cpp:88
const size_t WVERSION_VISTA
Definition: wversion.h:35
#define RETURN_STATUS_IF_ERR(expression)
Definition: status.h:276