[PSDK][REACTOS] Fix definitions and usage of DWLP_MSGRESULT, DWLP_DLGPROC, and DWLP_USER
[reactos.git] / dll / cpl / mmsys / sounds.c
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 }