1 /* 2 * PROJECT: ReactOS Multimedia Control Panel 3 * FILE: dll/cpl/mmsys/sounds.c 4 * PURPOSE: ReactOS Multimedia Control Panel 5 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com> 6 * Johannes Anderwald <janderwald@reactos.com> 7 * Dmitry Chapyshev <dmitry@reactos.org> 8 * Victor Martinez Calvo <victor.martinez@reactos.org> 9 * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 10 */ 11 12 #include "mmsys.h" 13 14 #include <commdlg.h> 15 #include <windowsx.h> 16 #include <strsafe.h> 17 18 #include <debug.h> 19 20 struct __APP_MAP__; 21 22 typedef struct __LABEL_MAP__ 23 { 24 TCHAR * szName; 25 TCHAR * szDesc; 26 TCHAR * szIcon; 27 struct __APP_MAP__ * AppMap; 28 struct __LABEL_MAP__ * Next; 29 } LABEL_MAP, *PLABEL_MAP; 30 31 typedef struct __APP_MAP__ 32 { 33 TCHAR szName[MAX_PATH]; 34 TCHAR szDesc[MAX_PATH]; 35 TCHAR szIcon[MAX_PATH]; 36 37 struct __APP_MAP__ *Next; 38 PLABEL_MAP LabelMap; 39 } APP_MAP, *PAPP_MAP; 40 41 typedef struct __LABEL_CONTEXT__ 42 { 43 PLABEL_MAP LabelMap; 44 PAPP_MAP AppMap; 45 TCHAR szValue[MAX_PATH]; 46 struct __LABEL_CONTEXT__ *Next; 47 } LABEL_CONTEXT, *PLABEL_CONTEXT; 48 49 typedef struct __SOUND_SCHEME_CONTEXT__ 50 { 51 TCHAR szName[MAX_PATH]; 52 TCHAR szDesc[MAX_PATH]; 53 PLABEL_CONTEXT LabelContext; 54 } SOUND_SCHEME_CONTEXT, *PSOUND_SCHEME_CONTEXT; 55 56 static PLABEL_MAP s_Map = NULL; 57 static PAPP_MAP s_App = NULL; 58 59 TCHAR szDefault[MAX_PATH]; 60 61 /* A filter string is a list separated by NULL and ends with double NULLs. */ 62 LPWSTR MakeFilter(LPWSTR psz) 63 { 64 WCHAR *pch; 65 66 ASSERT(psz[0] != UNICODE_NULL && 67 psz[wcslen(psz) - 1] == L'|'); 68 for (pch = psz; *pch != UNICODE_NULL; pch++) 69 { 70 /* replace vertical bar with NULL */ 71 if (*pch == L'|') 72 { 73 *pch = UNICODE_NULL; 74 } 75 } 76 return psz; 77 } 78 79 PLABEL_MAP FindLabel(PAPP_MAP pAppMap, TCHAR * szName) 80 { 81 PLABEL_MAP pMap = s_Map; 82 83 while (pMap) 84 { 85 ASSERT(pMap); 86 ASSERT(pMap->szName); 87 if (!_tcscmp(pMap->szName, szName)) 88 return pMap; 89 90 pMap = pMap->Next; 91 } 92 93 pMap = pAppMap->LabelMap; 94 95 while (pMap) 96 { 97 ASSERT(pMap); 98 ASSERT(pMap->szName); 99 if (!_tcscmp(pMap->szName, szName)) 100 return pMap; 101 102 pMap = pMap->Next; 103 } 104 105 pMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_MAP)); 106 if (!pMap) 107 return NULL; 108 109 pMap->szName = pMap->szDesc = _tcsdup(szName); 110 if (!pMap->szName) 111 { 112 HeapFree(GetProcessHeap(), 0, pMap); 113 return NULL; 114 } 115 116 pMap->AppMap = pAppMap; 117 pMap->Next = s_Map; 118 s_Map = pMap; 119 120 return pMap; 121 } 122 123 124 VOID RemoveLabel(PLABEL_MAP pMap) 125 { 126 PLABEL_MAP pCurMap = s_Map; 127 128 if (pCurMap == pMap) 129 { 130 s_Map = s_Map->Next; 131 return; 132 } 133 134 while (pCurMap) 135 { 136 if (pCurMap->Next == pMap) 137 { 138 pCurMap->Next = pCurMap->Next->Next; 139 return; 140 } 141 pCurMap = pCurMap->Next; 142 } 143 } 144 145 146 PAPP_MAP FindApp(TCHAR * szName) 147 { 148 PAPP_MAP pMap = s_App; 149 150 while (pMap) 151 { 152 if (!_tcscmp(pMap->szName, szName)) 153 return pMap; 154 155 pMap = pMap->Next; 156 157 } 158 return NULL; 159 } 160 161 162 PLABEL_CONTEXT FindLabelContext(PSOUND_SCHEME_CONTEXT pSoundScheme, TCHAR * AppName, TCHAR * LabelName) 163 { 164 PLABEL_CONTEXT pLabelContext; 165 166 pLabelContext = pSoundScheme->LabelContext; 167 168 while (pLabelContext) 169 { 170 ASSERT(pLabelContext->AppMap); 171 ASSERT(pLabelContext->LabelMap); 172 173 if (!_tcsicmp(pLabelContext->AppMap->szName, AppName) && !_tcsicmp(pLabelContext->LabelMap->szName, LabelName)) 174 { 175 return pLabelContext; 176 } 177 pLabelContext = pLabelContext->Next; 178 } 179 180 pLabelContext = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_CONTEXT)); 181 if (!pLabelContext) 182 return NULL; 183 184 pLabelContext->AppMap = FindApp(AppName); 185 pLabelContext->LabelMap = FindLabel(pLabelContext->AppMap, LabelName); 186 ASSERT(pLabelContext->AppMap); 187 ASSERT(pLabelContext->LabelMap); 188 pLabelContext->szValue[0] = _T('\0'); 189 pLabelContext->Next = pSoundScheme->LabelContext; 190 pSoundScheme->LabelContext = pLabelContext; 191 192 return pLabelContext; 193 } 194 195 196 BOOL 197 LoadEventLabel(HKEY hKey, TCHAR * szSubKey) 198 { 199 HKEY hSubKey; 200 DWORD cbValue; 201 TCHAR szDesc[MAX_PATH]; 202 TCHAR szData[MAX_PATH]; 203 PLABEL_MAP pMap; 204 205 if (RegOpenKeyEx(hKey, 206 szSubKey, 207 0, 208 KEY_READ, 209 &hSubKey) != ERROR_SUCCESS) 210 { 211 return FALSE; 212 } 213 214 cbValue = sizeof(szDesc); 215 if (RegQueryValueEx(hSubKey, 216 NULL, 217 NULL, 218 NULL, 219 (LPBYTE)szDesc, 220 &cbValue) != ERROR_SUCCESS) 221 { 222 RegCloseKey(hSubKey); 223 return FALSE; 224 } 225 226 cbValue = sizeof(szData); 227 if (RegQueryValueEx(hSubKey, 228 _T("DispFileName"), 229 NULL, 230 NULL, 231 (LPBYTE)szData, 232 &cbValue) != ERROR_SUCCESS) 233 { 234 RegCloseKey(hSubKey); 235 return FALSE; 236 } 237 238 pMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_MAP)); 239 if (!pMap) 240 { 241 return FALSE; 242 } 243 pMap->szName = _tcsdup(szSubKey); 244 pMap->szDesc = _tcsdup(szDesc); 245 pMap->szIcon = _tcsdup(szData); 246 247 if (s_Map) 248 { 249 pMap->Next = s_Map; 250 s_Map = pMap; 251 } 252 else 253 { 254 s_Map = pMap; 255 s_Map->Next = 0; 256 } 257 return TRUE; 258 } 259 260 261 BOOL 262 LoadEventLabels() 263 { 264 HKEY hSubKey; 265 DWORD dwCurKey; 266 TCHAR szName[MAX_PATH]; 267 DWORD dwName; 268 DWORD dwResult; 269 DWORD dwCount; 270 if (RegOpenKeyEx(HKEY_CURRENT_USER, 271 _T("AppEvents\\EventLabels"), 272 0, 273 KEY_READ, 274 &hSubKey) != ERROR_SUCCESS) 275 { 276 return FALSE; 277 } 278 279 dwCurKey = 0; 280 dwCount = 0; 281 do 282 { 283 dwName = _countof(szName); 284 dwResult = RegEnumKeyEx(hSubKey, 285 dwCurKey, 286 szName, 287 &dwName, 288 NULL, 289 NULL, 290 NULL, 291 NULL); 292 293 if (dwResult == ERROR_SUCCESS) 294 { 295 if (LoadEventLabel(hSubKey, szName)) 296 { 297 dwCount++; 298 } 299 } 300 dwCurKey++; 301 302 } while (dwResult == ERROR_SUCCESS); 303 304 RegCloseKey(hSubKey); 305 return (dwCount != 0); 306 } 307 308 309 BOOL 310 AddSoundProfile(HWND hwndDlg, HKEY hKey, TCHAR * szSubKey, BOOL SetDefault) 311 { 312 HKEY hSubKey; 313 TCHAR szValue[MAX_PATH]; 314 DWORD cbValue, dwResult; 315 LRESULT lResult; 316 PSOUND_SCHEME_CONTEXT pScheme; 317 318 if (RegOpenKeyEx(hKey, 319 szSubKey, 320 0, 321 KEY_READ, 322 &hSubKey) != ERROR_SUCCESS) 323 { 324 return FALSE; 325 } 326 327 cbValue = sizeof(szValue); 328 dwResult = RegQueryValueEx(hSubKey, 329 NULL, 330 NULL, 331 NULL, 332 (LPBYTE)szValue, 333 &cbValue); 334 RegCloseKey(hSubKey); 335 336 if (dwResult != ERROR_SUCCESS) 337 return FALSE; 338 339 /* Try to add the new profile */ 340 lResult = ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), szValue); 341 if (lResult == CB_ERR) 342 return FALSE; 343 344 /* Allocate the profile scheme buffer */ 345 pScheme = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOUND_SCHEME_CONTEXT)); 346 if (pScheme == NULL) 347 { 348 /* We failed to allocate the buffer, no need to keep a dangling string in the combobox */ 349 ComboBox_DeleteString(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult); 350 return FALSE; 351 } 352 353 StringCchCopy(pScheme->szDesc, MAX_PATH, szValue); 354 StringCchCopy(pScheme->szName, MAX_PATH, szSubKey); 355 356 /* Associate the value with the item in the combobox */ 357 ComboBox_SetItemData(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult, pScheme); 358 359 /* Optionally, select the profile */ 360 if (SetDefault) 361 { 362 ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult); 363 } 364 365 return TRUE; 366 } 367 368 369 DWORD 370 EnumerateSoundProfiles(HWND hwndDlg, HKEY hKey) 371 { 372 HKEY hSubKey; 373 DWORD dwName, dwCurKey, dwResult, dwNumSchemes; 374 DWORD cbDefault; 375 TCHAR szName[MAX_PATH]; 376 377 cbDefault = sizeof(szDefault); 378 if (RegQueryValueEx(hKey, 379 NULL, 380 NULL, 381 NULL, 382 (LPBYTE)szDefault, 383 &cbDefault) != ERROR_SUCCESS) 384 { 385 return FALSE; 386 } 387 388 389 390 if (RegOpenKeyEx(hKey, 391 _T("Names"), 392 0, 393 KEY_READ, 394 &hSubKey) != ERROR_SUCCESS) 395 { 396 return FALSE; 397 } 398 399 dwNumSchemes = 0; 400 dwCurKey = 0; 401 do 402 { 403 dwName = _countof(szName); 404 dwResult = RegEnumKeyEx(hSubKey, 405 dwCurKey, 406 szName, 407 &dwName, 408 NULL, 409 NULL, 410 NULL, 411 NULL); 412 413 if (dwResult == ERROR_SUCCESS) 414 { 415 if (AddSoundProfile(hwndDlg, hSubKey, szName, (!_tcsicmp(szName, szDefault)))) 416 { 417 dwNumSchemes++; 418 } 419 } 420 421 dwCurKey++; 422 } while (dwResult == ERROR_SUCCESS); 423 424 RegCloseKey(hSubKey); 425 return dwNumSchemes; 426 } 427 428 429 PSOUND_SCHEME_CONTEXT FindSoundProfile(HWND hwndDlg, TCHAR * szName) 430 { 431 LRESULT lCount, lIndex, lResult; 432 PSOUND_SCHEME_CONTEXT pScheme; 433 434 lCount = ComboBox_GetCount(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME)); 435 if (lCount == CB_ERR) 436 { 437 return NULL; 438 } 439 440 for(lIndex = 0; lIndex < lCount; lIndex++) 441 { 442 lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lIndex); 443 if (lResult == CB_ERR) 444 { 445 continue; 446 } 447 448 pScheme = (PSOUND_SCHEME_CONTEXT)lResult; 449 if (!_tcsicmp(pScheme->szName, szName)) 450 { 451 return pScheme; 452 } 453 } 454 return NULL; 455 } 456 457 458 BOOL 459 ImportSoundLabel(HWND hwndDlg, HKEY hKey, TCHAR * szProfile, TCHAR * szLabelName, TCHAR * szAppName, PAPP_MAP AppMap, PLABEL_MAP LabelMap) 460 { 461 HKEY hSubKey; 462 TCHAR szValue[MAX_PATH]; 463 TCHAR szBuffer[MAX_PATH]; 464 DWORD cbValue, cchLength; 465 PSOUND_SCHEME_CONTEXT pScheme; 466 PLABEL_CONTEXT pLabelContext; 467 BOOL bCurrentProfile, bActiveProfile; 468 469 //MessageBox(hwndDlg, szProfile, szLabelName, MB_OK); 470 471 bCurrentProfile = !_tcsicmp(szProfile, _T(".Current")); 472 bActiveProfile = !_tcsicmp(szProfile, szDefault); 473 474 if (RegOpenKeyEx(hKey, 475 szProfile, 476 0, 477 KEY_READ, 478 &hSubKey) != ERROR_SUCCESS) 479 { 480 return FALSE; 481 } 482 483 cbValue = sizeof(szValue); 484 if (RegQueryValueEx(hSubKey, 485 NULL, 486 NULL, 487 NULL, 488 (LPBYTE)szValue, 489 &cbValue) != ERROR_SUCCESS) 490 { 491 return FALSE; 492 } 493 494 if (bCurrentProfile) 495 pScheme = FindSoundProfile(hwndDlg, szDefault); 496 else 497 pScheme = FindSoundProfile(hwndDlg, szProfile); 498 499 if (!pScheme) 500 { 501 //MessageBox(hwndDlg, szProfile, _T("no profile!!"), MB_OK); 502 return FALSE; 503 } 504 pLabelContext = FindLabelContext(pScheme, AppMap->szName, LabelMap->szName); 505 506 cchLength = ExpandEnvironmentStrings(szValue, szBuffer, _countof(szBuffer)); 507 if (cchLength == 0 || cchLength > _countof(szBuffer)) 508 { 509 /* fixme */ 510 return FALSE; 511 } 512 513 if (bCurrentProfile) 514 _tcscpy(pLabelContext->szValue, szBuffer); 515 else if (!bActiveProfile) 516 _tcscpy(pLabelContext->szValue, szBuffer); 517 518 return TRUE; 519 } 520 521 522 DWORD 523 ImportSoundEntry(HWND hwndDlg, HKEY hKey, TCHAR * szLabelName, TCHAR * szAppName, PAPP_MAP pAppMap) 524 { 525 HKEY hSubKey; 526 DWORD dwNumProfiles; 527 DWORD dwCurKey; 528 DWORD dwResult; 529 DWORD dwProfile; 530 TCHAR szProfile[MAX_PATH]; 531 PLABEL_MAP pLabel; 532 533 if (RegOpenKeyEx(hKey, 534 szLabelName, 535 0, 536 KEY_READ, 537 &hSubKey) != ERROR_SUCCESS) 538 { 539 return FALSE; 540 } 541 pLabel = FindLabel(pAppMap, szLabelName); 542 543 ASSERT(pLabel); 544 RemoveLabel(pLabel); 545 546 pLabel->AppMap = pAppMap; 547 pLabel->Next = pAppMap->LabelMap; 548 pAppMap->LabelMap = pLabel; 549 550 dwNumProfiles = 0; 551 dwCurKey = 0; 552 do 553 { 554 dwProfile = _countof(szProfile); 555 dwResult = RegEnumKeyEx(hSubKey, 556 dwCurKey, 557 szProfile, 558 &dwProfile, 559 NULL, 560 NULL, 561 NULL, 562 NULL); 563 564 if (dwResult == ERROR_SUCCESS) 565 { 566 if (ImportSoundLabel(hwndDlg, hSubKey, szProfile, szLabelName, szAppName, pAppMap, pLabel)) 567 { 568 dwNumProfiles++; 569 } 570 } 571 572 dwCurKey++; 573 } while (dwResult == ERROR_SUCCESS); 574 575 RegCloseKey(hSubKey); 576 577 return dwNumProfiles; 578 } 579 580 581 DWORD 582 ImportAppProfile(HWND hwndDlg, HKEY hKey, TCHAR * szAppName) 583 { 584 HKEY hSubKey; 585 TCHAR szDefault[MAX_PATH]; 586 DWORD cbValue; 587 DWORD dwCurKey; 588 DWORD dwResult; 589 DWORD dwNumEntry; 590 DWORD dwName; 591 TCHAR szName[MAX_PATH]; 592 TCHAR szIcon[MAX_PATH]; 593 PAPP_MAP AppMap; 594 595 //MessageBox(hwndDlg, szAppName, _T("Importing...\n"), MB_OK); 596 597 AppMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APP_MAP)); 598 if (!AppMap) 599 return 0; 600 601 if (RegOpenKeyEx(hKey, 602 szAppName, 603 0, 604 KEY_READ, 605 &hSubKey) != ERROR_SUCCESS) 606 { 607 HeapFree(GetProcessHeap(), 0, AppMap); 608 return 0; 609 } 610 611 cbValue = sizeof(szDefault); 612 if (RegQueryValueEx(hSubKey, 613 NULL, 614 NULL, 615 NULL, 616 (LPBYTE)szDefault, 617 &cbValue) != ERROR_SUCCESS) 618 { 619 RegCloseKey(hSubKey); 620 HeapFree(GetProcessHeap(), 0, AppMap); 621 return 0; 622 } 623 624 cbValue = sizeof(szIcon); 625 if (RegQueryValueEx(hSubKey, 626 _T("DispFileName"), 627 NULL, 628 NULL, 629 (LPBYTE)szIcon, 630 &cbValue) != ERROR_SUCCESS) 631 { 632 szIcon[0] = _T('\0'); 633 } 634 635 /* initialize app map */ 636 _tcscpy(AppMap->szName, szAppName); 637 _tcscpy(AppMap->szDesc, szDefault); 638 _tcscpy(AppMap->szIcon, szIcon); 639 640 AppMap->Next = s_App; 641 s_App = AppMap; 642 643 644 dwCurKey = 0; 645 dwNumEntry = 0; 646 do 647 { 648 dwName = _countof(szName); 649 dwResult = RegEnumKeyEx(hSubKey, 650 dwCurKey, 651 szName, 652 &dwName, 653 NULL, 654 NULL, 655 NULL, 656 NULL); 657 if (dwResult == ERROR_SUCCESS) 658 { 659 if (ImportSoundEntry(hwndDlg, hSubKey, szName, szAppName, AppMap)) 660 { 661 dwNumEntry++; 662 } 663 } 664 dwCurKey++; 665 } while (dwResult == ERROR_SUCCESS); 666 667 RegCloseKey(hSubKey); 668 return dwNumEntry; 669 } 670 671 672 BOOL 673 ImportSoundProfiles(HWND hwndDlg, HKEY hKey) 674 { 675 DWORD dwCurKey; 676 DWORD dwResult; 677 DWORD dwNumApps; 678 TCHAR szName[MAX_PATH]; 679 HKEY hSubKey; 680 681 if (RegOpenKeyEx(hKey, 682 _T("Apps"), 683 0, 684 KEY_READ, 685 &hSubKey) != ERROR_SUCCESS) 686 { 687 return FALSE; 688 } 689 690 dwNumApps = 0; 691 dwCurKey = 0; 692 do 693 { 694 dwResult = RegEnumKey(hSubKey, 695 dwCurKey, 696 szName, 697 _countof(szName)); 698 699 if (dwResult == ERROR_SUCCESS) 700 { 701 if (ImportAppProfile(hwndDlg, hSubKey, szName)) 702 { 703 dwNumApps++; 704 } 705 } 706 dwCurKey++; 707 } while (dwResult == ERROR_SUCCESS); 708 709 RegCloseKey(hSubKey); 710 711 return (dwNumApps != 0); 712 } 713 714 715 BOOL 716 LoadSoundProfiles(HWND hwndDlg) 717 { 718 HKEY hSubKey; 719 DWORD dwNumSchemes; 720 721 if (RegOpenKeyEx(HKEY_CURRENT_USER, 722 _T("AppEvents\\Schemes"), 723 0, 724 KEY_READ, 725 &hSubKey) != ERROR_SUCCESS) 726 { 727 return FALSE; 728 } 729 730 dwNumSchemes = EnumerateSoundProfiles(hwndDlg, hSubKey); 731 732 733 if (dwNumSchemes) 734 { 735 //MessageBox(hwndDlg, _T("importing sound profiles..."), NULL, MB_OK); 736 ImportSoundProfiles(hwndDlg, hSubKey); 737 } 738 739 RegCloseKey(hSubKey); 740 return FALSE; 741 } 742 743 744 BOOL 745 LoadSoundFiles(HWND hwndDlg) 746 { 747 TCHAR szList[256]; 748 WCHAR szPath[MAX_PATH]; 749 WCHAR * ptr; 750 WIN32_FIND_DATAW FileData; 751 HANDLE hFile; 752 LRESULT lResult; 753 UINT length; 754 755 /* Add no sound listview item */ 756 if (LoadString(hApplet, IDS_NO_SOUND, szList, _countof(szList))) 757 { 758 szList[_countof(szList) - 1] = TEXT('\0'); 759 ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_LIST), szList); 760 } 761 762 /* Load sound files */ 763 length = GetWindowsDirectoryW(szPath, MAX_PATH); 764 if (length == 0 || length >= MAX_PATH - 9) 765 { 766 return FALSE; 767 } 768 if (szPath[length-1] != L'\\') 769 { 770 szPath[length] = L'\\'; 771 length++; 772 } 773 wcscpy(&szPath[length], L"media\\*"); 774 length += 7; 775 776 hFile = FindFirstFileW(szPath, &FileData); 777 if (hFile == INVALID_HANDLE_VALUE) 778 { 779 return FALSE; 780 } 781 782 do 783 { 784 if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 785 continue; 786 787 ptr = wcsrchr(FileData.cFileName, L'\\'); 788 if (ptr) 789 { 790 ptr++; 791 } 792 else 793 { 794 ptr = FileData.cFileName; 795 } 796 lResult = SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_ADDSTRING, (WPARAM)0, (LPARAM)ptr); 797 if (lResult != CB_ERR) 798 { 799 wcscpy(&szPath[length-1], FileData.cFileName); 800 SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)_wcsdup(szPath)); 801 } 802 } while (FindNextFileW(hFile, &FileData) != 0); 803 804 FindClose(hFile); 805 return TRUE; 806 } 807 808 809 BOOL 810 ShowSoundScheme(HWND hwndDlg) 811 { 812 LRESULT lIndex; 813 PSOUND_SCHEME_CONTEXT pScheme; 814 PAPP_MAP pAppMap; 815 LV_ITEM listItem; 816 LV_COLUMN dummy; 817 HWND hDlgCtrl, hList; 818 RECT rect; 819 int ItemIndex; 820 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME); 821 hList = GetDlgItem(hwndDlg, IDC_SCHEME_LIST); 822 823 lIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, (WPARAM)0, (LPARAM)0); 824 if (lIndex == CB_ERR) 825 { 826 return FALSE; 827 } 828 829 lIndex = SendMessage(hDlgCtrl, CB_GETITEMDATA, (WPARAM)lIndex, (LPARAM)0); 830 if (lIndex == CB_ERR) 831 { 832 return FALSE; 833 } 834 pScheme = (PSOUND_SCHEME_CONTEXT)lIndex; 835 836 _tcscpy(szDefault, pScheme->szName); 837 838 /* add column for app */ 839 GetClientRect(hList, &rect); 840 ZeroMemory(&dummy, sizeof(dummy)); 841 dummy.mask = LVCF_WIDTH; 842 dummy.iSubItem = 0; 843 dummy.cx = rect.right - rect.left - GetSystemMetrics(SM_CXVSCROLL); 844 (void)ListView_InsertColumn(hList, 0, &dummy); 845 ItemIndex = 0; 846 847 pAppMap = s_App; 848 while (pAppMap) 849 { 850 PLABEL_MAP pLabelMap = pAppMap->LabelMap; 851 while (pLabelMap) 852 { 853 ZeroMemory(&listItem, sizeof(listItem)); 854 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; 855 listItem.pszText = pLabelMap->szDesc; 856 listItem.lParam = (LPARAM)FindLabelContext(pScheme, pAppMap->szName, pLabelMap->szName); 857 listItem.iItem = ItemIndex; 858 listItem.iImage = -1; 859 (void)ListView_InsertItem(hList, &listItem); 860 ItemIndex++; 861 862 pLabelMap = pLabelMap->Next; 863 } 864 pAppMap = pAppMap->Next; 865 } 866 return TRUE; 867 } 868 869 870 BOOL 871 ApplyChanges(HWND hwndDlg) 872 { 873 HKEY hKey, hSubKey; 874 LRESULT lIndex; 875 PSOUND_SCHEME_CONTEXT pScheme; 876 HWND hDlgCtrl; 877 PLABEL_CONTEXT pLabelContext; 878 TCHAR Buffer[100]; 879 880 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME); 881 882 lIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, (WPARAM)0, (LPARAM)0); 883 if (lIndex == CB_ERR) 884 { 885 return FALSE; 886 } 887 888 lIndex = SendMessage(hDlgCtrl, CB_GETITEMDATA, (WPARAM)lIndex, (LPARAM)0); 889 if (lIndex == CB_ERR) 890 { 891 return FALSE; 892 } 893 pScheme = (PSOUND_SCHEME_CONTEXT)lIndex; 894 895 if (RegOpenKeyEx(HKEY_CURRENT_USER, 896 _T("AppEvents\\Schemes"), 897 0, 898 KEY_WRITE, 899 &hKey) != ERROR_SUCCESS) 900 { 901 return FALSE; 902 } 903 904 RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)pScheme->szName, (_tcslen(pScheme->szName) +1) * sizeof(TCHAR)); 905 RegCloseKey(hKey); 906 907 if (RegOpenKeyEx(HKEY_CURRENT_USER, 908 _T("AppEvents\\Schemes\\Apps"), 909 0, 910 KEY_WRITE, 911 &hKey) != ERROR_SUCCESS) 912 { 913 return FALSE; 914 } 915 916 pLabelContext = pScheme->LabelContext; 917 918 while (pLabelContext) 919 { 920 _stprintf(Buffer, _T("%s\\%s\\.Current"), pLabelContext->AppMap->szName, pLabelContext->LabelMap->szName); 921 922 if (RegOpenKeyEx(hKey, Buffer, 0, KEY_WRITE, &hSubKey) == ERROR_SUCCESS) 923 { 924 RegSetValueEx(hSubKey, NULL, 0, REG_EXPAND_SZ, (LPBYTE)pLabelContext->szValue, (_tcslen(pLabelContext->szValue) +1) * sizeof(TCHAR)); 925 RegCloseKey(hSubKey); 926 } 927 928 pLabelContext = pLabelContext->Next; 929 } 930 RegCloseKey(hKey); 931 932 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)PSNRET_NOERROR); 933 return TRUE; 934 } 935 936 937 /* Sounds property page dialog callback */ 938 INT_PTR 939 CALLBACK 940 SoundsDlgProc(HWND hwndDlg, 941 UINT uMsg, 942 WPARAM wParam, 943 LPARAM lParam) 944 { 945 OPENFILENAMEW ofn; 946 WCHAR filename[MAX_PATH]; 947 WCHAR szFilter[256], szTitle[256]; 948 LPWSTR pFileName; 949 LRESULT lResult; 950 951 switch (uMsg) 952 { 953 case WM_INITDIALOG: 954 { 955 UINT NumWavOut = waveOutGetNumDevs(); 956 957 SendMessage(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), 958 BM_SETIMAGE,(WPARAM)IMAGE_ICON, 959 (LPARAM)(HANDLE)LoadIcon(hApplet, MAKEINTRESOURCE(IDI_PLAY_ICON))); 960 961 LoadEventLabels(); 962 LoadSoundProfiles(hwndDlg); 963 LoadSoundFiles(hwndDlg); 964 ShowSoundScheme(hwndDlg); 965 966 if (!NumWavOut) 967 { 968 EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), FALSE); 969 EnableWindow(GetDlgItem(hwndDlg, IDC_SAVEAS_BTN), FALSE); 970 EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE_BTN), FALSE); 971 EnableWindow(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), FALSE); 972 } 973 974 if (wParam == (WPARAM)GetDlgItem(hwndDlg, IDC_SOUND_SCHEME)) 975 return TRUE; 976 SetFocus(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME)); 977 return FALSE; 978 } 979 case WM_COMMAND: 980 { 981 switch (LOWORD(wParam)) 982 { 983 case IDC_BROWSE_SOUND: 984 { 985 ZeroMemory(&ofn, sizeof(ofn)); 986 ofn.lStructSize = sizeof(ofn); 987 ofn.hwndOwner = hwndDlg; 988 ofn.lpstrFile = filename; 989 ofn.lpstrFile[0] = L'\0'; 990 ofn.nMaxFile = _countof(filename); 991 LoadStringW(hApplet, IDS_WAVE_FILES_FILTER, szFilter, _countof(szFilter)); 992 ofn.lpstrFilter = MakeFilter(szFilter); 993 ofn.nFilterIndex = 0; 994 LoadStringW(hApplet, IDS_BROWSE_FOR_SOUND, szTitle, _countof(szTitle)); 995 ofn.lpstrTitle = szTitle; 996 ofn.lpstrInitialDir = NULL; 997 ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 998 999 if (GetOpenFileNameW(&ofn) != FALSE) 1000 { 1001 // FIXME search if list already contains that sound 1002 1003 // extract file name 1004 pFileName = wcsrchr(filename, L'\\'); 1005 ASSERT(pFileName != NULL); 1006 pFileName++; 1007 1008 // add to list 1009 lResult = SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_ADDSTRING, (WPARAM)0, (LPARAM)pFileName); 1010 if (lResult != CB_ERR) 1011 { 1012 // add path and select item 1013 SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)_wcsdup(filename)); 1014 SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0); 1015 } 1016 } 1017 break; 1018 } 1019 case IDC_PLAY_SOUND: 1020 { 1021 LRESULT lIndex; 1022 lIndex = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST)); 1023 if (lIndex == CB_ERR) 1024 { 1025 break; 1026 } 1027 1028 lIndex = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex); 1029 if (lIndex != CB_ERR) 1030 { 1031 PlaySound((TCHAR*)lIndex, NULL, SND_FILENAME); 1032 } 1033 break; 1034 } 1035 case IDC_SOUND_SCHEME: 1036 { 1037 if (HIWORD(wParam) == CBN_SELENDOK) 1038 { 1039 (void)ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_SCHEME_LIST)); 1040 ShowSoundScheme(hwndDlg); 1041 EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_LIST), FALSE); 1042 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_SOUND), FALSE); 1043 EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE); 1044 EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE_SOUND), FALSE); 1045 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 1046 } 1047 break; 1048 } 1049 case IDC_SOUND_LIST: 1050 { 1051 if (HIWORD(wParam) == CBN_SELENDOK) 1052 { 1053 PLABEL_CONTEXT pLabelContext; 1054 INT SelCount; 1055 LVITEM item; 1056 LRESULT lIndex; 1057 SelCount = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_SCHEME_LIST)); 1058 if (SelCount == -1) 1059 { 1060 break; 1061 } 1062 lIndex = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST)); 1063 if (lIndex == CB_ERR) 1064 { 1065 break; 1066 } 1067 ZeroMemory(&item, sizeof(item)); 1068 item.mask = LVIF_PARAM; 1069 item.iItem = SelCount; 1070 if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), &item)) 1071 { 1072 LRESULT lResult; 1073 pLabelContext = (PLABEL_CONTEXT)item.lParam; 1074 1075 lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex); 1076 if (lResult == CB_ERR || lResult == 0) 1077 { 1078 if (lIndex != pLabelContext->szValue[0]) 1079 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 1080 1081 pLabelContext->szValue[0] = L'\0'; 1082 break; 1083 } 1084 1085 if (_tcsicmp(pLabelContext->szValue, (TCHAR*)lResult) || (lIndex != pLabelContext->szValue[0])) 1086 { 1087 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 1088 /// 1089 /// Should store in current member 1090 /// 1091 _tcscpy(pLabelContext->szValue, (TCHAR*)lResult); 1092 } 1093 if (_tcslen((TCHAR*)lResult) && lIndex != 0) 1094 { 1095 EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), TRUE); 1096 } 1097 else 1098 { 1099 EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE); 1100 } 1101 } 1102 } 1103 break; 1104 } 1105 } 1106 break; 1107 } 1108 case WM_NOTIFY: 1109 { 1110 LVITEM item; 1111 PLABEL_CONTEXT pLabelContext; 1112 TCHAR * ptr; 1113 1114 LPNMHDR lpnm = (LPNMHDR)lParam; 1115 1116 switch(lpnm->code) 1117 { 1118 case PSN_APPLY: 1119 { 1120 ApplyChanges(hwndDlg); 1121 break; 1122 } 1123 case LVN_ITEMCHANGED: 1124 { 1125 LPNMLISTVIEW nm = (LPNMLISTVIEW)lParam; 1126 1127 if ((nm->uNewState & LVIS_SELECTED) == 0) 1128 { 1129 return FALSE; 1130 } 1131 ZeroMemory(&item, sizeof(item)); 1132 item.mask = LVIF_PARAM; 1133 item.iItem = nm->iItem; 1134 1135 if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), &item)) 1136 { 1137 LRESULT lCount, lIndex, lResult; 1138 pLabelContext = (PLABEL_CONTEXT)item.lParam; 1139 if (!pLabelContext) 1140 { 1141 return FALSE; 1142 } 1143 EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_LIST), TRUE); 1144 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_SOUND), TRUE); 1145 EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE_SOUND), TRUE); 1146 if (_tcslen(pLabelContext->szValue) == 0) 1147 { 1148 lIndex = ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), 0); 1149 EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE); 1150 break; 1151 1152 } 1153 EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), TRUE); 1154 lCount = ComboBox_GetCount(GetDlgItem(hwndDlg, IDC_SOUND_LIST)); 1155 for (lIndex = 0; lIndex < lCount; lIndex++) 1156 { 1157 lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex); 1158 if (lResult == CB_ERR || lResult == 0) 1159 continue; 1160 1161 if (!_tcscmp((TCHAR*)lResult, pLabelContext->szValue)) 1162 { 1163 ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex); 1164 return FALSE; 1165 } 1166 } 1167 ptr = _tcsrchr(pLabelContext->szValue, _T('\\')); 1168 if (ptr) 1169 { 1170 ptr++; 1171 } 1172 else 1173 { 1174 ptr = pLabelContext->szValue; 1175 } 1176 lIndex = ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_LIST), ptr); 1177 if (lIndex != CB_ERR) 1178 { 1179 ComboBox_SetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex, _tcsdup(pLabelContext->szValue)); 1180 ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex); 1181 } 1182 } 1183 break; 1184 } 1185 } 1186 } 1187 break; 1188 } 1189 1190 return FALSE; 1191 } 1192