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