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 { 15 BOOL bNoAudioOut; 16 BOOL bNoAudioIn; 17 BOOL bNoMIDIOut; 18 19 BOOL bAudioOutChanged; 20 BOOL bAudioInChanged; 21 BOOL bMIDIOutChanged; 22 23 } GLOBAL_DATA, *PGLOBAL_DATA; 24 25 VOID 26 InitAudioDlg(HWND hwnd, PGLOBAL_DATA pGlobalData) 27 { 28 WAVEOUTCAPSW waveOutputPaps; 29 WAVEINCAPS waveInputPaps; 30 MIDIOUTCAPS midiOutCaps; 31 TCHAR szNoDevices[256]; 32 UINT DevsNum; 33 UINT uIndex; 34 HWND hCB; 35 LRESULT Res; 36 37 LoadString(hApplet, IDS_NO_DEVICES, szNoDevices, _countof(szNoDevices)); 38 39 // Init sound playback devices list 40 hCB = GetDlgItem(hwnd, IDC_DEVICE_PLAY_LIST); 41 42 DevsNum = waveOutGetNumDevs(); 43 if (DevsNum < 1) 44 { 45 Res = SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM)szNoDevices); 46 SendMessage(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[MAX_PATH-1] = L'\0'; 60 RegCloseKey(hKey); 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 SendMessage(hCB, CB_SETITEMDATA, Res, (LPARAM) uIndex); 73 if (!wcsicmp(waveOutputPaps.szPname, DefaultDevice)) 74 DefaultIndex = Res; 75 } 76 } 77 SendMessage(hCB, CB_SETCURSEL, (WPARAM) DefaultIndex, 0); 78 } 79 80 // Init sound recording devices list 81 hCB = GetDlgItem(hwnd, IDC_DEVICE_REC_LIST); 82 83 DevsNum = waveInGetNumDevs(); 84 if (DevsNum < 1) 85 { 86 Res = SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM)szNoDevices); 87 SendMessage(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[MAX_PATH-1] = L'\0'; 101 RegCloseKey(hKey); 102 } 103 104 105 for (uIndex = 0; uIndex < DevsNum; uIndex++) 106 { 107 if (waveInGetDevCaps(uIndex, &waveInputPaps, sizeof(waveInputPaps))) 108 continue; 109 110 Res = SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM) waveInputPaps.szPname); 111 112 if (CB_ERR != Res) 113 { 114 SendMessage(hCB, CB_SETITEMDATA, Res, (LPARAM) uIndex); 115 if (!wcsicmp(waveInputPaps.szPname, DefaultDevice)) 116 DefaultIndex = Res; 117 } 118 } 119 SendMessage(hCB, CB_SETCURSEL, (WPARAM) DefaultIndex, 0); 120 } 121 122 // Init MIDI devices list 123 hCB = GetDlgItem(hwnd, IDC_DEVICE_MIDI_LIST); 124 125 DevsNum = midiOutGetNumDevs(); 126 if (DevsNum < 1) 127 { 128 Res = SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM)szNoDevices); 129 SendMessage(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[MAX_PATH-1] = L'\0'; 143 RegCloseKey(hKey); 144 } 145 146 for (uIndex = 0; uIndex < DevsNum; uIndex++) 147 { 148 if (midiOutGetDevCaps(uIndex, &midiOutCaps, sizeof(midiOutCaps))) 149 continue; 150 151 Res = SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM) midiOutCaps.szPname); 152 153 if (CB_ERR != Res) 154 { 155 SendMessage(hCB, CB_SETITEMDATA, Res, (LPARAM) uIndex); 156 if (!wcsicmp(midiOutCaps.szPname, DefaultDevice)) 157 DefaultIndex = Res; 158 } 159 } 160 SendMessage(hCB, CB_SETCURSEL, (WPARAM) DefaultIndex, 0); 161 } 162 } 163 164 VOID 165 UpdateRegistryString(HWND hwnd, INT ctrl, LPWSTR key, LPWSTR value) 166 { 167 HWND hwndCombo = GetDlgItem(hwnd, ctrl); 168 INT CurSel = SendMessage(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 183 if (RegCreateKeyExW(HKEY_CURRENT_USER, key, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) 184 return; 185 186 RegSetValueExW(hKey, value, 0, REG_SZ, (BYTE *)SelectedDevice, (wcslen(SelectedDevice) + 1) * sizeof(WCHAR)); 187 RegCloseKey(hKey); 188 } 189 190 VOID 191 SaveAudioDlg(HWND hwnd, PGLOBAL_DATA pGlobalData) 192 { 193 if (pGlobalData->bAudioOutChanged) 194 { 195 UpdateRegistryString(hwnd, 196 IDC_DEVICE_PLAY_LIST, 197 L"Software\\Microsoft\\Multimedia\\Sound Mapper", 198 L"Playback"); 199 } 200 201 if (pGlobalData->bAudioInChanged) 202 { 203 UpdateRegistryString(hwnd, 204 IDC_DEVICE_REC_LIST, 205 L"Software\\Microsoft\\Multimedia\\Sound Mapper", 206 L"Record"); 207 } 208 209 if (pGlobalData->bMIDIOutChanged) 210 { 211 UpdateRegistryString(hwnd, 212 IDC_DEVICE_MIDI_LIST, 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 = SendMessage(hControl, CB_GETCURSEL, 0, 0); 225 226 if (iCurSel == CB_ERR) 227 return 0; 228 229 DevNum = (UINT) SendMessage(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 */ 240 INT_PTR CALLBACK 241 AudioDlgProc(HWND hwndDlg, 242 UINT uMsg, 243 WPARAM wParam, 244 LPARAM lParam) 245 { 246 PGLOBAL_DATA pGlobalData; 247 248 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(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 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData); 258 259 if (!pGlobalData) 260 break; 261 262 InitAudioDlg(hwndDlg, pGlobalData); 263 264 if (!NumWavOut) 265 { 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); 276 } 277 278 if (pGlobalData->bNoAudioOut) 279 { 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); 283 } 284 285 if (pGlobalData->bNoAudioIn) 286 { 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); 290 } 291 292 if (pGlobalData->bNoMIDIOut) 293 { 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); 297 } 298 } 299 break; 300 301 case WM_COMMAND: 302 { 303 STARTUPINFO si; 304 PROCESS_INFORMATION pi; 305 WCHAR szPath[MAX_PATH]; 306 307 if (!pGlobalData) 308 break; 309 310 switch(LOWORD(wParam)) 311 { 312 case IDC_VOLUME1_BTN: 313 { 314 wsprintf(szPath, L"sndvol32.exe -d %d", 315 GetDevNum(GetDlgItem(hwndDlg, IDC_DEVICE_PLAY_LIST), MIXER_OBJECTF_WAVEOUT)); 316 317 ZeroMemory(&si, sizeof(si)); 318 si.cb = sizeof(si); 319 si.dwFlags = STARTF_USESHOWWINDOW; 320 si.wShowWindow = SW_SHOW; 321 322 CreateProcess(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 323 } 324 break; 325 326 case IDC_ADV2_BTN: 327 { 328 329 } 330 break; 331 332 case IDC_VOLUME2_BTN: 333 { 334 wsprintf(szPath, L"sndvol32.exe -r -d %d", 335 GetDevNum(GetDlgItem(hwndDlg, IDC_DEVICE_REC_LIST), MIXER_OBJECTF_WAVEIN)); 336 337 ZeroMemory(&si, sizeof(si)); 338 si.cb = sizeof(si); 339 si.dwFlags = STARTF_USESHOWWINDOW; 340 si.wShowWindow = SW_SHOW; 341 342 CreateProcess(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 343 } 344 break; 345 346 case IDC_ADV1_BTN: 347 { 348 349 } 350 break; 351 352 case IDC_VOLUME3_BTN: 353 { 354 wsprintf(szPath, L"sndvol32.exe -d %d", 355 GetDevNum(GetDlgItem(hwndDlg, IDC_DEVICE_MIDI_LIST), MIXER_OBJECTF_MIDIOUT)); 356 357 ZeroMemory(&si, sizeof(si)); 358 si.cb = sizeof(si); 359 si.dwFlags = STARTF_USESHOWWINDOW; 360 si.wShowWindow = SW_SHOW; 361 362 CreateProcess(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 363 } 364 break; 365 366 case IDC_ADV3_BTN: 367 { 368 369 } 370 break; 371 372 case IDC_DEVICE_PLAY_LIST: 373 { 374 if (HIWORD(wParam) == CBN_SELCHANGE) 375 { 376 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 377 pGlobalData->bAudioOutChanged = TRUE; 378 } 379 } 380 break; 381 382 case IDC_DEVICE_REC_LIST: 383 { 384 if (HIWORD(wParam) == CBN_SELCHANGE) 385 { 386 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 387 pGlobalData->bAudioInChanged = TRUE; 388 } 389 } 390 391 case IDC_DEVICE_MIDI_LIST: 392 { 393 if (HIWORD(wParam) == CBN_SELCHANGE) 394 { 395 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 396 pGlobalData->bMIDIOutChanged = TRUE; 397 } 398 } 399 break; 400 } 401 } 402 break; 403 404 case WM_DESTROY: 405 if (!pGlobalData) 406 break; 407 408 HeapFree(GetProcessHeap(), 0, pGlobalData); 409 break; 410 411 case WM_NOTIFY: 412 if (!pGlobalData) 413 break; 414 415 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY) 416 { 417 SaveAudioDlg(hwndDlg, pGlobalData); 418 } 419 return TRUE; 420 } 421 422 return FALSE; 423 } 424