ReactOS  0.4.15-dev-5488-ge316d61
audio.c
Go to the documentation of this file.
1 /*
2  *
3  * PROJECT: ReactOS Multimedia Control Panel
4  * FILE: dll/cpl/mmsys/audio.c
5  * PURPOSE: ReactOS Multimedia Control Panel
6  * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
7  * Johannes Anderwald <janderwald@reactos.com>
8  * Dmitry Chapyshev <dmitry@reactos.org>
9  */
10 
11 #include "mmsys.h"
12 
13 typedef struct _GLOBAL_DATA
14 {
18 
22 
24 
25 VOID
27 {
28  WAVEOUTCAPSW waveOutputPaps;
29  WAVEINCAPSW waveInputPaps;
30  MIDIOUTCAPSW midiOutCaps;
31  WCHAR szNoDevices[256];
32  UINT DevsNum;
33  UINT uIndex;
34  HWND hCB;
35  LRESULT Res;
36 
37  LoadStringW(hApplet, IDS_NO_DEVICES, szNoDevices, _countof(szNoDevices));
38 
39  // Init sound playback devices list
41 
42  DevsNum = waveOutGetNumDevs();
43  if (DevsNum < 1)
44  {
45  Res = SendMessageW(hCB, CB_ADDSTRING, 0, (LPARAM)szNoDevices);
46  SendMessageW(hCB, CB_SETCURSEL, (WPARAM)Res, 0);
47  pGlobalData->bNoAudioOut = TRUE;
48  }
49  else
50  {
51  WCHAR DefaultDevice[MAX_PATH] = {0};
52  HKEY hKey;
53  DWORD dwSize = sizeof(DefaultDevice);
54  UINT DefaultIndex = 0;
55 
56  if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Multimedia\\Sound Mapper", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
57  {
58  RegQueryValueExW(hKey, L"Playback", NULL, NULL, (LPBYTE)DefaultDevice, &dwSize);
59  DefaultDevice[_countof(DefaultDevice) - 1] = UNICODE_NULL;
61  }
62 
63  for (uIndex = 0; uIndex < DevsNum; uIndex++)
64  {
65  if (waveOutGetDevCapsW(uIndex, &waveOutputPaps, sizeof(waveOutputPaps)))
66  continue;
67 
68  Res = SendMessageW(hCB, CB_ADDSTRING, 0, (LPARAM)waveOutputPaps.szPname);
69 
70  if (CB_ERR != Res)
71  {
72  SendMessageW(hCB, CB_SETITEMDATA, Res, (LPARAM)uIndex);
73  if (!_wcsicmp(waveOutputPaps.szPname, DefaultDevice))
74  DefaultIndex = Res;
75  }
76  }
77  SendMessageW(hCB, CB_SETCURSEL, (WPARAM)DefaultIndex, 0);
78  }
79 
80  // Init sound recording devices list
82 
83  DevsNum = waveInGetNumDevs();
84  if (DevsNum < 1)
85  {
86  Res = SendMessageW(hCB, CB_ADDSTRING, 0, (LPARAM)szNoDevices);
87  SendMessageW(hCB, CB_SETCURSEL, (WPARAM)Res, 0);
88  pGlobalData->bNoAudioIn = TRUE;
89  }
90  else
91  {
92  WCHAR DefaultDevice[MAX_PATH] = {0};
93  HKEY hKey;
94  DWORD dwSize = sizeof(DefaultDevice);
95  UINT DefaultIndex = 0;
96 
97  if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Multimedia\\Sound Mapper", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
98  {
99  RegQueryValueExW(hKey, L"Record", NULL, NULL, (LPBYTE)DefaultDevice, &dwSize);
100  DefaultDevice[_countof(DefaultDevice) - 1] = UNICODE_NULL;
101  RegCloseKey(hKey);
102  }
103 
104 
105  for (uIndex = 0; uIndex < DevsNum; uIndex++)
106  {
107  if (waveInGetDevCapsW(uIndex, &waveInputPaps, sizeof(waveInputPaps)))
108  continue;
109 
110  Res = SendMessageW(hCB, CB_ADDSTRING, 0, (LPARAM)waveInputPaps.szPname);
111 
112  if (CB_ERR != Res)
113  {
114  SendMessageW(hCB, CB_SETITEMDATA, Res, (LPARAM)uIndex);
115  if (!_wcsicmp(waveInputPaps.szPname, DefaultDevice))
116  DefaultIndex = Res;
117  }
118  }
119  SendMessageW(hCB, CB_SETCURSEL, (WPARAM)DefaultIndex, 0);
120  }
121 
122  // Init MIDI devices list
124 
125  DevsNum = midiOutGetNumDevs();
126  if (DevsNum < 1)
127  {
128  Res = SendMessageW(hCB, CB_ADDSTRING, 0, (LPARAM)szNoDevices);
129  SendMessageW(hCB, CB_SETCURSEL, (WPARAM)Res, 0);
130  pGlobalData->bNoMIDIOut = TRUE;
131  }
132  else
133  {
134  WCHAR DefaultDevice[MAX_PATH] = {0};
135  HKEY hKey;
136  DWORD dwSize = sizeof(DefaultDevice);
137  UINT DefaultIndex = 0;
138 
139  if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
140  {
141  RegQueryValueExW(hKey, L"szPname", NULL, NULL, (LPBYTE)DefaultDevice, &dwSize);
142  DefaultDevice[_countof(DefaultDevice) - 1] = UNICODE_NULL;
143  RegCloseKey(hKey);
144  }
145 
146  for (uIndex = 0; uIndex < DevsNum; uIndex++)
147  {
148  if (midiOutGetDevCapsW(uIndex, &midiOutCaps, sizeof(midiOutCaps)))
149  continue;
150 
151  Res = SendMessageW(hCB, CB_ADDSTRING, 0, (LPARAM)midiOutCaps.szPname);
152 
153  if (CB_ERR != Res)
154  {
155  SendMessageW(hCB, CB_SETITEMDATA, Res, (LPARAM)uIndex);
156  if (!_wcsicmp(midiOutCaps.szPname, DefaultDevice))
157  DefaultIndex = Res;
158  }
159  }
160  SendMessageW(hCB, CB_SETCURSEL, (WPARAM)DefaultIndex, 0);
161  }
162 }
163 
164 VOID
166 {
167  HWND hwndCombo = GetDlgItem(hwnd, ctrl);
168  INT CurSel = SendMessageW(hwndCombo, CB_GETCURSEL, 0, 0);
169  UINT TextLen;
170  WCHAR SelectedDevice[MAX_PATH] = {0};
171  HKEY hKey;
172 
173  if (CurSel == CB_ERR)
174  return;
175 
176  TextLen = SendMessageW(hwndCombo, CB_GETLBTEXTLEN, CurSel, 0) + 1;
177 
178  if (TextLen > _countof(SelectedDevice))
179  return;
180 
181  SendMessageW(hwndCombo, CB_GETLBTEXT, CurSel, (LPARAM)SelectedDevice);
182 
184  return;
185 
186  RegSetValueExW(hKey, value, 0, REG_SZ, (BYTE*)SelectedDevice, (wcslen(SelectedDevice) + 1) * sizeof(WCHAR));
187  RegCloseKey(hKey);
188 }
189 
190 VOID
192 {
193  if (pGlobalData->bAudioOutChanged)
194  {
197  L"Software\\Microsoft\\Multimedia\\Sound Mapper",
198  L"Playback");
199  }
200 
201  if (pGlobalData->bAudioInChanged)
202  {
205  L"Software\\Microsoft\\Multimedia\\Sound Mapper",
206  L"Record");
207  }
208 
209  if (pGlobalData->bMIDIOutChanged)
210  {
213  L"Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap",
214  L"szPname");
215  }
216 }
217 
218 static UINT
219 GetDevNum(HWND hControl, DWORD Id)
220 {
221  int iCurSel;
222  UINT DevNum;
223 
224  iCurSel = SendMessageW(hControl, CB_GETCURSEL, 0, 0);
225 
226  if (iCurSel == CB_ERR)
227  return 0;
228 
229  DevNum = (UINT)SendMessageW(hControl, CB_GETITEMDATA, iCurSel, 0);
230  if (DevNum == (UINT) CB_ERR)
231  return 0;
232 
233  if (mixerGetID((HMIXEROBJ)IntToPtr(DevNum), &DevNum, Id) != MMSYSERR_NOERROR)
234  return 0;
235 
236  return DevNum;
237 }
238 
239 /* Audio property page dialog callback */
242  UINT uMsg,
243  WPARAM wParam,
244  LPARAM lParam)
245 {
246  PGLOBAL_DATA pGlobalData;
247 
248  pGlobalData = (PGLOBAL_DATA)GetWindowLongPtrW(hwndDlg, DWLP_USER);
249 
250  switch (uMsg)
251  {
252  case WM_INITDIALOG:
253  {
254  UINT NumWavOut = waveOutGetNumDevs();
255 
256  pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA));
257  SetWindowLongPtrW(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
258 
259  if (!pGlobalData)
260  break;
261 
262  InitAudioDlg(hwndDlg, pGlobalData);
263 
264  if (!NumWavOut)
265  {
276  }
277 
278  if (pGlobalData->bNoAudioOut)
279  {
283  }
284 
285  if (pGlobalData->bNoAudioIn)
286  {
290  }
291 
292  if (pGlobalData->bNoMIDIOut)
293  {
297  }
298  }
299  break;
300 
301  case WM_COMMAND:
302  {
303  STARTUPINFOW si;
306 
307  if (!pGlobalData)
308  break;
309 
310  switch (LOWORD(wParam))
311  {
312  case IDC_VOLUME1_BTN:
313  {
314  StringCchPrintfW(szPath, _countof(szPath), L"sndvol32.exe -d %d",
316 
317  ZeroMemory(&si, sizeof(si));
318  si.cb = sizeof(si);
320  si.wShowWindow = SW_SHOW;
321 
322  if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
323  {
324  CloseHandle(pi.hProcess);
325  CloseHandle(pi.hThread);
326  }
327  }
328  break;
329 
330  case IDC_ADV2_BTN:
331  {
332 
333  }
334  break;
335 
336  case IDC_VOLUME2_BTN:
337  {
338  StringCchPrintfW(szPath, _countof(szPath), L"sndvol32.exe -r -d %d",
340 
341  ZeroMemory(&si, sizeof(si));
342  si.cb = sizeof(si);
344  si.wShowWindow = SW_SHOW;
345 
346  if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
347  {
348  CloseHandle(pi.hProcess);
349  CloseHandle(pi.hThread);
350  }
351  }
352  break;
353 
354  case IDC_ADV1_BTN:
355  {
356 
357  }
358  break;
359 
360  case IDC_VOLUME3_BTN:
361  {
362  StringCchPrintfW(szPath, _countof(szPath), L"sndvol32.exe -d %d",
364 
365  ZeroMemory(&si, sizeof(si));
366  si.cb = sizeof(si);
368  si.wShowWindow = SW_SHOW;
369 
370  if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
371  {
372  CloseHandle(pi.hProcess);
373  CloseHandle(pi.hThread);
374  }
375  }
376  break;
377 
378  case IDC_ADV3_BTN:
379  {
380 
381  }
382  break;
383 
385  {
386  if (HIWORD(wParam) == CBN_SELCHANGE)
387  {
388  PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
389  pGlobalData->bAudioOutChanged = TRUE;
390  }
391  }
392  break;
393 
394  case IDC_DEVICE_REC_LIST:
395  {
396  if (HIWORD(wParam) == CBN_SELCHANGE)
397  {
398  PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
399  pGlobalData->bAudioInChanged = TRUE;
400  }
401  }
402 
404  {
405  if (HIWORD(wParam) == CBN_SELCHANGE)
406  {
407  PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
408  pGlobalData->bMIDIOutChanged = TRUE;
409  }
410  }
411  break;
412  }
413  }
414  break;
415 
416  case WM_DESTROY:
417  if (!pGlobalData)
418  break;
419 
420  HeapFree(GetProcessHeap(), 0, pGlobalData);
421  break;
422 
423  case WM_NOTIFY:
424  if (!pGlobalData)
425  break;
426 
427  if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
428  {
429  SaveAudioDlg(hwndDlg, pGlobalData);
430  }
431  return TRUE;
432  }
433 
434  return FALSE;
435 }
BOOL bAudioInChanged
Definition: audio.c:20
#define CB_SETITEMDATA
Definition: winuser.h:1956
#define CB_GETLBTEXTLEN
Definition: winuser.h:1943
Definition: pdh_main.c:93
#define CloseHandle
Definition: compat.h:739
#define IDC_DEVICE_MIDI_LIST
Definition: resource.h:44
struct _GLOBAL_DATA * PGLOBAL_DATA
#define ERROR_SUCCESS
Definition: deptool.c:10
INT_PTR CALLBACK AudioDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: audio.c:241
WCHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1060
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
#define CB_GETLBTEXT
Definition: winuser.h:1942
#define CB_GETITEMDATA
Definition: winuser.h:1940
#define HKEY_CURRENT_USER
Definition: winreg.h:11
BOOL bNoAudioOut
Definition: audio.c:15
#define CALLBACK
Definition: compat.h:35
#define IDC_VOLUME1_BTN
Definition: resource.h:55
#define ZeroMemory
Definition: winbase.h:1670
HINSTANCE hApplet
Definition: access.c:17
UINT_PTR WPARAM
Definition: windef.h:207
BOOL bMIDIOutChanged
Definition: audio.c:21
#define GetWindowLongPtrW
Definition: winuser.h:4819
#define PSN_APPLY
Definition: prsht.h:117
int32_t INT_PTR
Definition: typedefs.h:64
#define MIXER_OBJECTF_MIDIOUT
Definition: mmsystem.h:306
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int32_t INT
Definition: typedefs.h:58
#define CB_GETCURSEL
Definition: winuser.h:1933
VOID InitAudioDlg(HWND hwnd, PGLOBAL_DATA pGlobalData)
Definition: audio.c:26
WPARAM wParam
Definition: combotst.c:138
#define IDC_ADV2_BTN
Definition: resource.h:56
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1091
DWORD Id
UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSize)
Definition: winmm.c:2576
VOID SaveAudioDlg(HWND hwnd, PGLOBAL_DATA pGlobalData)
Definition: audio.c:191
struct _GLOBAL_DATA GLOBAL_DATA
#define L(x)
Definition: ntvdm.h:50
unsigned char * LPBYTE
Definition: typedefs.h:53
UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps, UINT uSize)
Definition: winmm.c:2176
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
#define IDC_DEVICE_REC_LIST
Definition: resource.h:43
#define CB_ADDSTRING
Definition: winuser.h:1926
static UINT GetDevNum(HWND hControl, DWORD Id)
Definition: audio.c:219
LONG_PTR LPARAM
Definition: windef.h:208
UINT WINAPI waveOutGetNumDevs(void)
Definition: winmm.c:2140
#define STARTF_USESHOWWINDOW
Definition: winbase.h:491
#define SW_SHOW
Definition: winuser.h:769
BOOL bNoAudioIn
Definition: audio.c:16
VOID UpdateRegistryString(HWND hwnd, INT ctrl, LPWSTR key, LPWSTR value)
Definition: audio.c:165
#define IDC_DEFAULT_DEV_CHECKBOX
Definition: resource.h:41
#define CB_ERR
Definition: winuser.h:2425
#define WM_DESTROY
Definition: winuser.h:1599
#define ctrl
Definition: input.c:1757
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4594
#define IntToPtr(i)
Definition: basetsd.h:89
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_WRITE
Definition: nt_native.h:1031
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4899
WCHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1126
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:736
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
DWORD cb
Definition: winbase.h:852
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4120
#define MIXER_OBJECTF_WAVEIN
Definition: mmsystem.h:304
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define PropSheet_Changed(d, w)
Definition: prsht.h:344
static refpint_t pi[]
Definition: server.c:96
#define _countof(array)
Definition: sndvol32.h:68
#define MAX_PATH
Definition: compat.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IDS_NO_DEVICES
Definition: resource.h:91
WCHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1039
#define DWLP_USER
Definition: winuser.h:866
WORD wShowWindow
Definition: winbase.h:864
#define CB_SETCURSEL
Definition: winuser.h:1951
#define MIXER_OBJECTF_WAVEOUT
Definition: mmsystem.h:302
#define WM_COMMAND
Definition: winuser.h:1730
Definition: inflate.c:139
unsigned char BYTE
Definition: xxhash.c:193
BOOL WINAPI EnableWindow(_In_ HWND, _In_ BOOL)
HWND WINAPI GetParent(_In_ HWND)
#define IDC_DEVICE_PLAY_LIST
Definition: resource.h:42
FxAutoRegKey hKey
LPCWSTR szPath
Definition: env.c:37
#define IDC_VOLUME3_BTN
Definition: resource.h:59
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
UINT WINAPI midiOutGetDevCapsW(UINT_PTR uDeviceID, LPMIDIOUTCAPSW lpCaps, UINT uSize)
Definition: winmm.c:817
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
#define IDC_VOLUME2_BTN
Definition: resource.h:57
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define CBN_SELCHANGE
Definition: winuser.h:1969
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define IDC_ADV1_BTN
Definition: resource.h:58
#define HIWORD(l)
Definition: typedefs.h:247
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3356
UINT WINAPI waveInGetNumDevs(void)
Definition: winmm.c:2568
#define SetWindowLongPtrW
Definition: winuser.h:5336
DWORD dwFlags
Definition: winbase.h:863
WCHAR * LPWSTR
Definition: xmlstorage.h:184
LONG_PTR LRESULT
Definition: windef.h:209
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4022
#define WM_INITDIALOG
Definition: winuser.h:1729
LPARAM lParam
Definition: combotst.c:139
UINT WINAPI mixerGetID(HMIXEROBJ hmix, LPUINT lpid, DWORD fdwID)
Definition: winmm.c:407
#define LOWORD(l)
Definition: pedump.c:82
UINT WINAPI midiOutGetNumDevs(void)
Definition: winmm.c:809
#define HeapFree(x, y, z)
Definition: compat.h:735
#define RegCloseKey(hKey)
Definition: registry.h:47
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
BOOL bAudioOutChanged
Definition: audio.c:19
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
BOOL bNoMIDIOut
Definition: audio.c:17
#define WM_NOTIFY
Definition: richedit.h:61
#define IDC_ADV3_BTN
Definition: resource.h:60
Definition: copy.c:22
#define REG_SZ
Definition: layer.c:22