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>
13 typedef struct _GLOBAL_DATA
19 BOOL bAudioOutChanged
;
23 } GLOBAL_DATA
, *PGLOBAL_DATA
;
26 InitAudioDlg(HWND hwnd
, PGLOBAL_DATA pGlobalData
)
28 WAVEOUTCAPSW waveOutputPaps
;
29 WAVEINCAPSW waveInputPaps
;
30 MIDIOUTCAPSW midiOutCaps
;
31 WCHAR szNoDevices
[256];
37 LoadStringW(hApplet
, IDS_NO_DEVICES
, szNoDevices
, _countof(szNoDevices
));
39 // Init sound playback devices list
40 hCB
= GetDlgItem(hwnd
, IDC_DEVICE_PLAY_LIST
);
42 DevsNum
= waveOutGetNumDevs();
45 Res
= SendMessageW(hCB
, CB_ADDSTRING
, 0, (LPARAM
)szNoDevices
);
46 SendMessageW(hCB
, CB_SETCURSEL
, (WPARAM
)Res
, 0);
47 pGlobalData
->bNoAudioOut
= TRUE
;
51 WCHAR DefaultDevice
[MAX_PATH
] = {0};
53 DWORD dwSize
= sizeof(DefaultDevice
);
54 UINT DefaultIndex
= 0;
56 if (RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Multimedia\\Sound Mapper", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
58 RegQueryValueExW(hKey
, L
"Playback", NULL
, NULL
, (LPBYTE
)DefaultDevice
, &dwSize
);
59 DefaultDevice
[_countof(DefaultDevice
) - 1] = UNICODE_NULL
;
63 for (uIndex
= 0; uIndex
< DevsNum
; uIndex
++)
65 if (waveOutGetDevCapsW(uIndex
, &waveOutputPaps
, sizeof(waveOutputPaps
)))
68 Res
= SendMessageW(hCB
, CB_ADDSTRING
, 0, (LPARAM
)waveOutputPaps
.szPname
);
72 SendMessageW(hCB
, CB_SETITEMDATA
, Res
, (LPARAM
)uIndex
);
73 if (!_wcsicmp(waveOutputPaps
.szPname
, DefaultDevice
))
77 SendMessageW(hCB
, CB_SETCURSEL
, (WPARAM
)DefaultIndex
, 0);
80 // Init sound recording devices list
81 hCB
= GetDlgItem(hwnd
, IDC_DEVICE_REC_LIST
);
83 DevsNum
= waveInGetNumDevs();
86 Res
= SendMessageW(hCB
, CB_ADDSTRING
, 0, (LPARAM
)szNoDevices
);
87 SendMessageW(hCB
, CB_SETCURSEL
, (WPARAM
)Res
, 0);
88 pGlobalData
->bNoAudioIn
= TRUE
;
92 WCHAR DefaultDevice
[MAX_PATH
] = {0};
94 DWORD dwSize
= sizeof(DefaultDevice
);
95 UINT DefaultIndex
= 0;
97 if (RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Multimedia\\Sound Mapper", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
99 RegQueryValueExW(hKey
, L
"Record", NULL
, NULL
, (LPBYTE
)DefaultDevice
, &dwSize
);
100 DefaultDevice
[_countof(DefaultDevice
) - 1] = UNICODE_NULL
;
105 for (uIndex
= 0; uIndex
< DevsNum
; uIndex
++)
107 if (waveInGetDevCapsW(uIndex
, &waveInputPaps
, sizeof(waveInputPaps
)))
110 Res
= SendMessageW(hCB
, CB_ADDSTRING
, 0, (LPARAM
)waveInputPaps
.szPname
);
114 SendMessageW(hCB
, CB_SETITEMDATA
, Res
, (LPARAM
)uIndex
);
115 if (!_wcsicmp(waveInputPaps
.szPname
, DefaultDevice
))
119 SendMessageW(hCB
, CB_SETCURSEL
, (WPARAM
)DefaultIndex
, 0);
122 // Init MIDI devices list
123 hCB
= GetDlgItem(hwnd
, IDC_DEVICE_MIDI_LIST
);
125 DevsNum
= midiOutGetNumDevs();
128 Res
= SendMessageW(hCB
, CB_ADDSTRING
, 0, (LPARAM
)szNoDevices
);
129 SendMessageW(hCB
, CB_SETCURSEL
, (WPARAM
)Res
, 0);
130 pGlobalData
->bNoMIDIOut
= TRUE
;
134 WCHAR DefaultDevice
[MAX_PATH
] = {0};
136 DWORD dwSize
= sizeof(DefaultDevice
);
137 UINT DefaultIndex
= 0;
139 if (RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
141 RegQueryValueExW(hKey
, L
"szPname", NULL
, NULL
, (LPBYTE
)DefaultDevice
, &dwSize
);
142 DefaultDevice
[_countof(DefaultDevice
) - 1] = UNICODE_NULL
;
146 for (uIndex
= 0; uIndex
< DevsNum
; uIndex
++)
148 if (midiOutGetDevCapsW(uIndex
, &midiOutCaps
, sizeof(midiOutCaps
)))
151 Res
= SendMessageW(hCB
, CB_ADDSTRING
, 0, (LPARAM
)midiOutCaps
.szPname
);
155 SendMessageW(hCB
, CB_SETITEMDATA
, Res
, (LPARAM
)uIndex
);
156 if (!_wcsicmp(midiOutCaps
.szPname
, DefaultDevice
))
160 SendMessageW(hCB
, CB_SETCURSEL
, (WPARAM
)DefaultIndex
, 0);
165 UpdateRegistryString(HWND hwnd
, INT ctrl
, LPCWSTR key
, LPCWSTR value
)
167 HWND hwndCombo
= GetDlgItem(hwnd
, ctrl
);
168 INT CurSel
= SendMessageW(hwndCombo
, CB_GETCURSEL
, 0, 0);
170 WCHAR SelectedDevice
[MAX_PATH
] = {0};
173 if (CurSel
== CB_ERR
)
176 TextLen
= SendMessageW(hwndCombo
, CB_GETLBTEXTLEN
, CurSel
, 0) + 1;
178 if (TextLen
> _countof(SelectedDevice
))
181 SendMessageW(hwndCombo
, CB_GETLBTEXT
, CurSel
, (LPARAM
)SelectedDevice
);
183 if (RegCreateKeyExW(HKEY_CURRENT_USER
, key
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
186 RegSetValueExW(hKey
, value
, 0, REG_SZ
, (BYTE
*)SelectedDevice
, (wcslen(SelectedDevice
) + 1) * sizeof(WCHAR
));
191 SaveAudioDlg(HWND hwnd
, PGLOBAL_DATA pGlobalData
)
193 if (pGlobalData
->bAudioOutChanged
)
195 UpdateRegistryString(hwnd
,
196 IDC_DEVICE_PLAY_LIST
,
197 L
"Software\\Microsoft\\Multimedia\\Sound Mapper",
201 if (pGlobalData
->bAudioInChanged
)
203 UpdateRegistryString(hwnd
,
205 L
"Software\\Microsoft\\Multimedia\\Sound Mapper",
209 if (pGlobalData
->bMIDIOutChanged
)
211 UpdateRegistryString(hwnd
,
212 IDC_DEVICE_MIDI_LIST
,
213 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap",
219 GetDevNum(HWND hControl
, DWORD Id
)
224 iCurSel
= SendMessageW(hControl
, CB_GETCURSEL
, 0, 0);
226 if (iCurSel
== CB_ERR
)
229 DevNum
= (UINT
)SendMessageW(hControl
, CB_GETITEMDATA
, iCurSel
, 0);
230 if (DevNum
== (UINT
) CB_ERR
)
233 if (mixerGetID((HMIXEROBJ
)IntToPtr(DevNum
), &DevNum
, Id
) != MMSYSERR_NOERROR
)
239 /* Audio property page dialog callback */
241 AudioDlgProc(HWND hwndDlg
,
246 PGLOBAL_DATA pGlobalData
;
248 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
254 UINT NumWavOut
= waveOutGetNumDevs();
256 pGlobalData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(GLOBAL_DATA
));
257 SetWindowLongPtrW(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
262 InitAudioDlg(hwndDlg
, pGlobalData
);
266 EnableWindow(GetDlgItem(hwndDlg
, IDC_DEVICE_PLAY_LIST
), FALSE
);
267 EnableWindow(GetDlgItem(hwndDlg
, IDC_DEVICE_REC_LIST
), FALSE
);
268 EnableWindow(GetDlgItem(hwndDlg
, IDC_DEVICE_MIDI_LIST
), FALSE
);
269 EnableWindow(GetDlgItem(hwndDlg
, IDC_DEFAULT_DEV_CHECKBOX
), FALSE
);
270 EnableWindow(GetDlgItem(hwndDlg
, IDC_VOLUME1_BTN
), FALSE
);
271 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADV2_BTN
), FALSE
);
272 EnableWindow(GetDlgItem(hwndDlg
, IDC_VOLUME2_BTN
), FALSE
);
273 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADV1_BTN
), FALSE
);
274 EnableWindow(GetDlgItem(hwndDlg
, IDC_VOLUME3_BTN
), FALSE
);
275 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADV3_BTN
), FALSE
);
278 if (pGlobalData
->bNoAudioOut
)
280 EnableWindow(GetDlgItem(hwndDlg
, IDC_DEVICE_PLAY_LIST
), FALSE
);
281 EnableWindow(GetDlgItem(hwndDlg
, IDC_VOLUME1_BTN
), FALSE
);
282 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADV2_BTN
), FALSE
);
285 if (pGlobalData
->bNoAudioIn
)
287 EnableWindow(GetDlgItem(hwndDlg
, IDC_DEVICE_REC_LIST
), FALSE
);
288 EnableWindow(GetDlgItem(hwndDlg
, IDC_VOLUME2_BTN
), FALSE
);
289 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADV1_BTN
), FALSE
);
292 if (pGlobalData
->bNoMIDIOut
)
294 EnableWindow(GetDlgItem(hwndDlg
, IDC_DEVICE_MIDI_LIST
), FALSE
);
295 EnableWindow(GetDlgItem(hwndDlg
, IDC_VOLUME3_BTN
), FALSE
);
296 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADV3_BTN
), FALSE
);
304 PROCESS_INFORMATION pi
;
305 WCHAR szPath
[MAX_PATH
];
310 switch (LOWORD(wParam
))
312 case IDC_VOLUME1_BTN
:
314 StringCchPrintfW(szPath
, _countof(szPath
), L
"sndvol32.exe -d %d",
315 GetDevNum(GetDlgItem(hwndDlg
, IDC_DEVICE_PLAY_LIST
), MIXER_OBJECTF_WAVEOUT
));
317 ZeroMemory(&si
, sizeof(si
));
319 si
.dwFlags
= STARTF_USESHOWWINDOW
;
320 si
.wShowWindow
= SW_SHOW
;
322 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
324 CloseHandle(pi
.hProcess
);
325 CloseHandle(pi
.hThread
);
336 case IDC_VOLUME2_BTN
:
338 StringCchPrintfW(szPath
, _countof(szPath
), L
"sndvol32.exe -r -d %d",
339 GetDevNum(GetDlgItem(hwndDlg
, IDC_DEVICE_REC_LIST
), MIXER_OBJECTF_WAVEIN
));
341 ZeroMemory(&si
, sizeof(si
));
343 si
.dwFlags
= STARTF_USESHOWWINDOW
;
344 si
.wShowWindow
= SW_SHOW
;
346 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
348 CloseHandle(pi
.hProcess
);
349 CloseHandle(pi
.hThread
);
360 case IDC_VOLUME3_BTN
:
362 StringCchPrintfW(szPath
, _countof(szPath
), L
"sndvol32.exe -d %d",
363 GetDevNum(GetDlgItem(hwndDlg
, IDC_DEVICE_MIDI_LIST
), MIXER_OBJECTF_MIDIOUT
));
365 ZeroMemory(&si
, sizeof(si
));
367 si
.dwFlags
= STARTF_USESHOWWINDOW
;
368 si
.wShowWindow
= SW_SHOW
;
370 if (CreateProcessW(NULL
, szPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
372 CloseHandle(pi
.hProcess
);
373 CloseHandle(pi
.hThread
);
384 case IDC_DEVICE_PLAY_LIST
:
386 if (HIWORD(wParam
) == CBN_SELCHANGE
)
388 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
389 pGlobalData
->bAudioOutChanged
= TRUE
;
394 case IDC_DEVICE_REC_LIST
:
396 if (HIWORD(wParam
) == CBN_SELCHANGE
)
398 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
399 pGlobalData
->bAudioInChanged
= TRUE
;
403 case IDC_DEVICE_MIDI_LIST
:
405 if (HIWORD(wParam
) == CBN_SELCHANGE
)
407 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
408 pGlobalData
->bMIDIOutChanged
= TRUE
;
420 HeapFree(GetProcessHeap(), 0, pGlobalData
);
427 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
429 SaveAudioDlg(hwndDlg
, pGlobalData
);