2 * ReactOS Sound Volume Control
3 * Copyright (C) 2004-2005 Thomas Weidenmueller
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS Sound Volume Control
22 * FILE: subsys/system/sndvol32/sndvol32.c
23 * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
27 HINSTANCE hAppInstance
;
32 PREFERENCES_CONTEXT Preferences
;
34 #define GetDialogData(hwndDlg, type) \
35 ( P##type )GetWindowLongPtr((hwndDlg), DWLP_USER)
36 #define GetWindowData(hwnd, type) \
37 ( P##type )GetWindowLongPtr((hwnd), GWL_USERDATA)
39 /******************************************************************************/
43 typedef struct _PREFERENCES_FILL_DEVICES
45 PPREFERENCES_CONTEXT PrefContext
;
48 } PREFERENCES_FILL_DEVICES
, *PPREFERENCES_FILL_DEVICES
;
51 FillDeviceComboBox(PSND_MIXER Mixer
,
57 PPREFERENCES_FILL_DEVICES FillContext
= (PPREFERENCES_FILL_DEVICES
)Context
;
59 UNREFERENCED_PARAMETER(Mixer
);
61 lres
= SendMessage(FillContext
->hComboBox
,
67 /* save the index so we don't screw stuff when the combobox is sorted... */
68 SendMessage(FillContext
->hComboBox
,
73 if (Id
== FillContext
->Selected
)
75 SendMessage(FillContext
->hComboBox
,
86 PrefDlgAddLine(PSND_MIXER Mixer
,
91 PPREFERENCES_CONTEXT PrefContext
= (PPREFERENCES_CONTEXT
)Context
;
93 UNREFERENCED_PARAMETER(Mixer
);
94 UNREFERENCED_PARAMETER(DisplayControls
);
96 switch (Line
->dwComponentType
)
98 case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
:
99 if (PrefContext
->PlaybackID
== (DWORD
)-1)
101 PrefContext
->PlaybackID
= Line
->dwLineID
;
103 if (PrefContext
->SelectedLine
== (DWORD
)-1)
105 PrefContext
->SelectedLine
= Line
->dwLineID
;
109 goto AddToOthersLines
;
113 case MIXERLINE_COMPONENTTYPE_DST_WAVEIN
:
114 if (PrefContext
->RecordingID
== (DWORD
)-1)
116 PrefContext
->RecordingID
= Line
->dwLineID
;
118 if (PrefContext
->SelectedLine
== (DWORD
)-1)
120 PrefContext
->SelectedLine
= Line
->dwLineID
;
124 goto AddToOthersLines
;
133 if (PrefContext
->SelectedLine
== (DWORD
)-1)
135 PrefContext
->SelectedLine
= Line
->dwLineID
;
139 hwndCbOthers
= GetDlgItem(PrefContext
->hwndDlg
,
142 lres
= SendMessage(hwndCbOthers
,
145 (LPARAM
)Line
->szName
);
148 SendMessage(hwndCbOthers
,
153 PrefContext
->OtherLines
++;
163 PrefDlgAddConnection(PSND_MIXER Mixer
,
168 PPREFERENCES_CONTEXT PrefContext
= (PPREFERENCES_CONTEXT
)Context
;
173 UNREFERENCED_PARAMETER(Mixer
);
174 UNREFERENCED_PARAMETER(LineID
);
176 if (Line
->cControls
!= 0)
178 hwndControls
= GetDlgItem(PrefContext
->hwndDlg
,
181 lvi
.mask
= LVIF_TEXT
| LVIF_PARAM
;
182 lvi
.iItem
= PrefContext
->tmp
++;
184 lvi
.pszText
= Line
->szName
;
185 lvi
.lParam
= (LPARAM
)Line
->dwSource
;
187 i
= SendMessage(hwndControls
,
193 TCHAR LineName
[MIXER_LONG_NAME_CHARS
];
195 BOOL SelLine
= FALSE
;
197 if (SndMixerGetLineName(PrefContext
->Mixer
,
198 PrefContext
->SelectedLine
,
200 MIXER_LONG_NAME_CHARS
,
203 LineName
[0] = TEXT('\0');
206 if (ReadLineConfig(PrefContext
->DeviceName
,
217 ListView_SetCheckState(hwndControls
,
227 UpdatePrefDlgControls(PPREFERENCES_CONTEXT Context
,
230 INT OldID
, MixerID
= 0;
233 /* select the mixer */
234 DeviceCbIndex
= SendDlgItemMessage(Context
->hwndDlg
,
239 if (DeviceCbIndex
!= CB_ERR
)
241 MixerID
= SendDlgItemMessage(Context
->hwndDlg
,
246 if (MixerID
== CB_ERR
)
252 OldID
= Context
->Selected
;
253 if (MixerID
!= OldID
&&
254 SndMixerSelect(Context
->Mixer
,
257 Context
->Selected
= SndMixerGetSelection(Context
->Mixer
);
259 /* update the controls */
260 Context
->PlaybackID
= (DWORD
)-1;
261 Context
->RecordingID
= (DWORD
)-1;
262 Context
->OtherLines
= 0;
263 Context
->SelectedLine
= (DWORD
)-1;
265 SndMixerGetProductName(Context
->Mixer
,
267 sizeof(Context
->DeviceName
) / sizeof(Context
->DeviceName
[0]));
269 if (SndMixerEnumLines(Context
->Mixer
,
275 /* enable/disable controls and make default selection */
276 EnableWindow(GetDlgItem(Context
->hwndDlg
,
278 Context
->PlaybackID
!= (DWORD
)-1);
279 CheckDlgButton(Context
->hwndDlg
,
281 (Context
->PlaybackID
!= (DWORD
)-1 && SelBox
++ == 0) ?
282 BST_CHECKED
: BST_UNCHECKED
);
284 EnableWindow(GetDlgItem(Context
->hwndDlg
,
286 Context
->RecordingID
!= (DWORD
)-1);
287 CheckDlgButton(Context
->hwndDlg
,
289 (Context
->RecordingID
!= (DWORD
)-1 && SelBox
++ == 0) ?
290 BST_CHECKED
: BST_UNCHECKED
);
292 if (Context
->OtherLines
!= 0)
294 /* select the first item in the other lines combo box by default */
295 SendDlgItemMessage(Context
->hwndDlg
,
301 EnableWindow(GetDlgItem(Context
->hwndDlg
,
304 EnableWindow(GetDlgItem(Context
->hwndDlg
,
306 Context
->OtherLines
!= 0);
307 CheckDlgButton(Context
->hwndDlg
,
309 (Context
->OtherLines
!= 0 && SelBox
++ == 0) ?
310 BST_CHECKED
: BST_UNCHECKED
);
312 /* disable the OK button if the device doesn't have any lines */
313 EnableWindow(GetDlgItem(Context
->hwndDlg
,
315 Context
->PlaybackID
!= (DWORD
)-1 ||
316 Context
->RecordingID
!= (DWORD
)-1 ||
317 Context
->OtherLines
!= 0);
319 LineID
= Context
->SelectedLine
;
323 /* update the line sources list */
324 if ((MixerID
!= OldID
&& Context
->SelectedLine
!= (DWORD
)-1) ||
325 (Context
->SelectedLine
!= LineID
&& LineID
!= (DWORD
)-1))
327 Context
->SelectedLine
= LineID
;
329 (void)ListView_DeleteAllItems(GetDlgItem(Context
->hwndDlg
,
333 SndMixerEnumConnections(Context
->Mixer
,
335 PrefDlgAddConnection
,
342 WriteLineSettings(PPREFERENCES_CONTEXT Context
, HWND hwndDlg
)
346 WCHAR LineName
[MIXER_LONG_NAME_CHARS
];
347 WCHAR DestinationName
[MIXER_LONG_NAME_CHARS
];
349 PSNDVOL_REG_LINESTATE LineStates
;
352 hwndControls
= GetDlgItem(hwndDlg
, IDC_CONTROLS
);
354 /* get list item count */
355 Count
= ListView_GetItemCount(hwndControls
);
360 if (SndMixerGetLineName(Context
->Mixer
, Context
->SelectedLine
, DestinationName
, MIXER_LONG_NAME_CHARS
, TRUE
) == -1)
362 /* failed to get destination line name */
366 /* allocate line states array */
367 LineStates
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SNDVOL_REG_LINESTATE
) * Count
);
368 if (LineStates
== NULL
)
370 /* failed to allocate line states array */
375 for(Index
= 0; Index
< Count
; Index
++)
381 ListView_GetItemText(hwndControls
, Index
, 0, LineName
, MIXER_LONG_NAME_CHARS
);
383 /* make sure it is null terminated */
384 LineName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
386 /* get check state */
387 Flags
= (ListView_GetCheckState(hwndControls
, Index
) == 0 ? 0x4 : 0);
390 wcscpy(LineStates
[Index
].LineName
, LineName
);
393 LineStates
[Index
].Flags
= Flags
;
396 /* now write the line config */
397 WriteLineConfig(Context
->DeviceName
, DestinationName
, LineStates
, sizeof(SNDVOL_REG_LINESTATE
) * Count
);
399 /* free line states */
400 HeapFree(GetProcessHeap(), 0, LineStates
);
403 static INT_PTR CALLBACK
404 DlgPreferencesProc(HWND hwndDlg
,
409 PPREFERENCES_CONTEXT Context
;
415 Context
= GetDialogData(hwndDlg
,
416 PREFERENCES_CONTEXT
);
417 switch (LOWORD(wParam
))
419 case IDC_MIXERDEVICE
:
421 if (HIWORD(wParam
) == CBN_SELCHANGE
)
423 UpdatePrefDlgControls(Context
,
431 if (HIWORD(wParam
) == CBN_SELCHANGE
)
436 Index
= SendDlgItemMessage(hwndDlg
,
443 LineID
= SendDlgItemMessage(hwndDlg
,
448 if (LineID
!= CB_ERR
)
450 UpdatePrefDlgControls(Context
,
460 UpdatePrefDlgControls(Context
,
461 Context
->PlaybackID
);
462 EnableWindow(GetDlgItem(hwndDlg
,
470 UpdatePrefDlgControls(Context
,
471 Context
->RecordingID
);
472 EnableWindow(GetDlgItem(hwndDlg
,
483 EnableWindow(GetDlgItem(hwndDlg
,
487 LineCbIndex
= SendDlgItemMessage(hwndDlg
,
492 if (LineCbIndex
!= CB_ERR
)
494 LineID
= SendDlgItemMessage(hwndDlg
,
499 if (LineID
!= CB_ERR
)
501 UpdatePrefDlgControls(Context
,
510 /* write line settings */
511 WriteLineSettings(Context
, hwndDlg
);
527 PREFERENCES_FILL_DEVICES FillDevContext
;
532 SetWindowLongPtr(hwndDlg
,
535 Context
= (PPREFERENCES_CONTEXT
)((LONG_PTR
)lParam
);
536 Context
->hwndDlg
= hwndDlg
;
537 Context
->Mixer
= SndMixerCreate(hwndDlg
);
538 Context
->Selected
= (UINT
)-1;
540 FillDevContext
.PrefContext
= Context
;
541 FillDevContext
.hComboBox
= GetDlgItem(hwndDlg
,
543 FillDevContext
.Selected
= SndMixerGetSelection(Context
->Mixer
);
544 SndMixerEnumProducts(Context
->Mixer
,
548 /* initialize the list view control */
549 hwndControls
= GetDlgItem(hwndDlg
,
551 (void)ListView_SetExtendedListViewStyle(hwndControls
,
554 GetClientRect(hwndControls
,
556 lvc
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
557 lvc
.pszText
= TEXT("");
558 lvc
.cx
= rcClient
.right
;
559 SendMessage(hwndControls
,
564 /* update all controls */
565 UpdatePrefDlgControls(Context
,
566 (DWORD
)Context
->SelectedLine
);
577 case WM_SYSCOLORCHANGE
:
581 /* Forward WM_SYSCOLORCHANGE */
582 hwndControls
= GetDlgItem(hwndDlg
, IDC_CONTROLS
);
583 SendMessage(hwndControls
, WM_SYSCOLORCHANGE
, 0, 0);
592 /******************************************************************************/
595 DeleteMixerWindowControls(PMIXER_WINDOW MixerWindow
)
599 for(Index
= 0; Index
< MixerWindow
->WindowCount
; Index
++)
601 /* destroys the window */
602 DestroyWindow(MixerWindow
->Window
[Index
]);
606 HeapFree(GetProcessHeap(), 0, MixerWindow
->Window
);
609 MixerWindow
->Window
= NULL
;
610 MixerWindow
->WindowCount
= 0;
614 RebuildMixerWindowControls(PPREFERENCES_CONTEXT PrefContext
)
616 /* delete existing mixer controls */
617 DeleteMixerWindowControls(PrefContext
->MixerWindow
);
619 /* load new mixer controls */
620 LoadDialogCtrls(PrefContext
);
628 SetVolumeCallback(PSND_MIXER Mixer
, DWORD LineID
, LPMIXERLINE Line
, PVOID Ctx
)
630 UINT ControlCount
= 0, Index
;
631 LPMIXERCONTROL Control
= NULL
;
632 MIXERCONTROLDETAILS_UNSIGNED uDetails
;
633 MIXERCONTROLDETAILS_BOOLEAN bDetails
;
634 PSET_VOLUME_CONTEXT Context
= (PSET_VOLUME_CONTEXT
)Ctx
;
636 /* check if the line name is equal */
637 if (wcsicmp(Line
->szName
, Context
->LineName
))
644 if (SndMixerQueryControls(Mixer
, &ControlCount
, Line
, &Control
) == FALSE
)
646 /* failed to query for controls */
650 /* now go through all controls and compare control ids */
651 for(Index
= 0; Index
< ControlCount
; Index
++)
653 if (Context
->bVertical
)
655 if ((Control
[Index
].dwControlType
& MIXERCONTROL_CT_CLASS_MASK
) == MIXERCONTROL_CT_CLASS_FADER
)
657 /* FIXME: give me granularity */
658 DWORD Step
= 0x10000 / 5;
661 uDetails
.dwValue
= 0x10000 - Step
* Context
->SliderPos
;
664 SndMixerSetVolumeControlDetails(Preferences
.MixerWindow
->Mixer
, Control
[Index
].dwControlID
, sizeof(MIXERCONTROLDETAILS_UNSIGNED
), (LPVOID
)&uDetails
);
670 else if (Context
->bSwitch
)
672 if ((Control
[Index
].dwControlType
& MIXERCONTROL_CT_CLASS_MASK
) == MIXERCONTROL_CT_CLASS_SWITCH
)
675 bDetails
.fValue
= Context
->SliderPos
;
678 SndMixerSetVolumeControlDetails(Preferences
.MixerWindow
->Mixer
, Control
[Index
].dwControlID
, sizeof(MIXERCONTROLDETAILS_BOOLEAN
), (LPVOID
)&bDetails
);
686 /* FIXME: implement left - right channel switch support */
692 HeapFree(GetProcessHeap(), 0, Control
);
702 MixerControlChangeCallback(PSND_MIXER Mixer
, DWORD LineID
, LPMIXERLINE Line
, PVOID Context
)
704 UINT ControlCount
= 0, Index
;
705 LPMIXERCONTROL Control
= NULL
;
707 /* check if the line has controls */
708 if (Line
->cControls
== 0)
715 if (SndMixerQueryControls(Mixer
, &ControlCount
, Line
, &Control
) == FALSE
)
717 /* failed to query for controls */
721 /* now go through all controls and compare control ids */
722 for(Index
= 0; Index
< ControlCount
; Index
++)
724 if (Control
[Index
].dwControlID
== PtrToUlong(Context
))
726 if ((Control
[Index
].dwControlType
& MIXERCONTROL_CT_CLASS_MASK
) == MIXERCONTROL_CT_CLASS_SWITCH
)
728 MIXERCONTROLDETAILS_BOOLEAN Details
;
730 /* get volume control details */
731 if (SndMixerGetVolumeControlDetails(Preferences
.MixerWindow
->Mixer
, Control
[Index
].dwControlID
, sizeof(MIXERCONTROLDETAILS_BOOLEAN
), (LPVOID
)&Details
) != -1)
733 /* update dialog control */
734 UpdateDialogLineSwitchControl(&Preferences
, Line
, Details
.fValue
);
737 else if ((Control
[Index
].dwControlType
& MIXERCONTROL_CT_CLASS_MASK
) == MIXERCONTROL_CT_CLASS_FADER
)
739 MIXERCONTROLDETAILS_UNSIGNED Details
;
741 /* get volume control details */
742 if (SndMixerGetVolumeControlDetails(Preferences
.MixerWindow
->Mixer
, Control
[Index
].dwControlID
, sizeof(MIXERCONTROLDETAILS_UNSIGNED
), (LPVOID
)&Details
) != -1)
744 /* update dialog control */
746 DWORD Step
= 0x10000 / 5;
748 /* FIXME: give me granularity */
749 Position
= 5 - (Details
.dwValue
/ Step
);
751 /* update volume control slider */
752 UpdateDialogLineSliderControl(&Preferences
, Line
, Control
[Index
].dwControlID
, IDC_LINE_SLIDER_VERT
, Position
);
760 HeapFree(GetProcessHeap(), 0, Control
);
768 static LRESULT CALLBACK
769 MainWindowProc(HWND hwnd
,
774 PMIXER_WINDOW MixerWindow
;
775 DWORD CtrlID
, LineOffset
;
777 SET_VOLUME_CONTEXT Context
;
783 MixerWindow
= GetWindowData(hwnd
,
786 switch (LOWORD(wParam
))
790 PREFERENCES_CONTEXT Pref
;
792 Pref
.MixerWindow
= MixerWindow
;
794 Pref
.SelectedLine
= Preferences
.SelectedLine
;
796 if (DialogBoxParam(hAppInstance
,
797 MAKEINTRESOURCE(IDD_PREFERENCES
),
800 (LPARAM
)&Pref
) == IDOK
)
803 TCHAR szProduct
[MAXPNAMELEN
];
805 /* get mixer product name */
806 if (SndMixerGetProductName(MixerWindow
->Mixer
,
808 sizeof(szProduct
) / sizeof(szProduct
[0])) == -1)
810 /* failed to get name */
811 szProduct
[0] = L
'\0';
816 wcscpy(Preferences
.DeviceName
, szProduct
);
819 /* destroy old status bar */
820 DestroyWindow(MixerWindow
->hStatusBar
);
823 Preferences
.SelectedLine
= Pref
.SelectedLine
;
825 /* destroy old mixer */
826 SndMixerDestroy(Preferences
.MixerWindow
->Mixer
);
828 /* use new selected mixer */
829 Preferences
.MixerWindow
->Mixer
= Pref
.Mixer
;
831 /* rebuild dialog controls */
832 RebuildMixerWindowControls(&Preferences
);
834 /* create status window */
835 MixerWindow
->hStatusBar
= CreateStatusWindow(WS_VISIBLE
| WS_CHILD
| WS_CLIPSIBLINGS
,
841 if (MixerWindow
->hStatusBar
)
843 SendMessage(MixerWindow
->hStatusBar
,
860 HICON hAppIcon
= (HICON
)GetClassLongPtrW(hwnd
,
872 CtrlID
= LOWORD(wParam
);
874 /* check if the message is from the line switch */
875 if (HIWORD(wParam
) == BN_CLICKED
&& (CtrlID
% IDC_LINE_SWITCH
== 0))
877 /* compute line offset */
878 LineOffset
= CtrlID
/ IDC_LINE_SWITCH
;
880 /* compute window id of line name static control */
881 CtrlID
= LineOffset
* IDC_LINE_NAME
;
884 if (GetDlgItemTextW(hwnd
, CtrlID
, Context
.LineName
, MIXER_LONG_NAME_CHARS
) != 0)
887 Context
.SliderPos
= SendMessage((HWND
)lParam
, BM_GETCHECK
, 0, 0);
888 Context
.bVertical
= FALSE
;
889 Context
.bSwitch
= TRUE
;
892 SndMixerEnumConnections(Preferences
.MixerWindow
->Mixer
, Preferences
.SelectedLine
, SetVolumeCallback
, (LPVOID
)&Context
);
901 case MM_MIXM_LINE_CHANGE
:
903 DPRINT("MM_MIXM_LINE_CHANGE\n");
907 case MM_MIXM_CONTROL_CHANGE
:
909 DPRINT("MM_MIXM_CONTROL_CHANGE\n");
911 /* get mixer window */
912 MixerWindow
= GetWindowData(hwnd
,
917 assert(MixerWindow
->Mixer
->hmx
== (HMIXER
)wParam
);
919 SndMixerEnumConnections(MixerWindow
->Mixer
, Preferences
.SelectedLine
, MixerControlChangeCallback
, (PVOID
)lParam
);
925 if (LOWORD(wParam
) == TB_THUMBTRACK
)
927 /* get dialog item ctrl */
928 CtrlID
= GetDlgCtrlID((HWND
)lParam
);
931 LineOffset
= CtrlID
/ IDC_LINE_SLIDER_VERT
;
933 /* compute window id of line name static control */
934 CtrlID
= LineOffset
* IDC_LINE_NAME
;
937 if (GetDlgItemTextW(hwnd
, CtrlID
, Context
.LineName
, MIXER_LONG_NAME_CHARS
) != 0)
940 Context
.SliderPos
= HIWORD(wParam
);
941 Context
.bVertical
= TRUE
;
942 Context
.bSwitch
= FALSE
;
945 SndMixerEnumConnections(Preferences
.MixerWindow
->Mixer
, Preferences
.SelectedLine
, SetVolumeCallback
, (LPVOID
)&Context
);
955 MixerWindow
= ((LPCREATESTRUCT
)lParam
)->lpCreateParams
;
956 SetWindowLongPtr(hwnd
,
958 (LONG_PTR
)MixerWindow
);
959 MixerWindow
->hWnd
= hwnd
;
960 MixerWindow
->Mixer
= SndMixerCreate(MixerWindow
->hWnd
);
961 if (MixerWindow
->Mixer
!= NULL
)
963 TCHAR szProduct
[MAXPNAMELEN
];
965 /* get mixer product name */
966 if (SndMixerGetProductName(MixerWindow
->Mixer
,
968 sizeof(szProduct
) / sizeof(szProduct
[0])) == -1)
970 /* failed to get name */
971 szProduct
[0] = L
'\0';
975 /* initialize perferences */
976 ZeroMemory(&Preferences
, sizeof(Preferences
));
979 Preferences
.Mixer
= MixerWindow
->Mixer
;
981 /* store mixer window */
982 Preferences
.MixerWindow
= MixerWindow
;
984 /* first destination line id */
985 Preferences
.SelectedLine
= 0xFFFF0000;
988 wcscpy(Preferences
.DeviceName
, szProduct
);
990 if (!RebuildMixerWindowControls(&Preferences
))
992 DPRINT("Rebuilding mixer window controls failed!\n");
993 SndMixerDestroy(MixerWindow
->Mixer
);
994 MixerWindow
->Mixer
= NULL
;
998 /* create status window */
999 MixerWindow
->hStatusBar
= CreateStatusWindow(WS_VISIBLE
| WS_CHILD
| WS_CLIPSIBLINGS
,
1003 if (MixerWindow
->hStatusBar
)
1005 SendMessage(MixerWindow
->hStatusBar
,
1016 MixerWindow
= GetWindowData(hwnd
,
1018 if (MixerWindow
->Mixer
!= NULL
)
1020 SndMixerDestroy(MixerWindow
->Mixer
);
1033 Result
= DefWindowProc(hwnd
,
1045 RegisterApplicationClasses(VOID
)
1049 wc
.cbSize
= sizeof(WNDCLASSEX
);
1050 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1051 wc
.lpfnWndProc
= MainWindowProc
;
1053 wc
.cbWndExtra
= sizeof(PMIXER_WINDOW
);
1054 wc
.hInstance
= hAppInstance
;
1055 wc
.hIcon
= LoadIcon(hAppInstance
,
1056 MAKEINTRESOURCE(IDI_MAINAPP
));
1057 wc
.hCursor
= LoadCursor(NULL
,
1059 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1060 wc
.lpszMenuName
= NULL
;
1061 wc
.lpszClassName
= SZ_APP_CLASS
;
1063 MainWindowClass
= RegisterClassEx(&wc
);
1065 return MainWindowClass
!= 0;
1069 UnregisterApplicationClasses(VOID
)
1071 UnregisterClass(SZ_APP_CLASS
,
1076 CreateApplicationWindow(VOID
)
1080 PMIXER_WINDOW MixerWindow
= HeapAlloc(hAppHeap
,
1082 sizeof(MIXER_WINDOW
));
1083 if (MixerWindow
== NULL
)
1088 if (mixerGetNumDevs() > 0)
1090 hWnd
= CreateWindowEx(WS_EX_WINDOWEDGE
| WS_EX_CONTROLPARENT
,
1093 WS_DLGFRAME
| WS_CAPTION
| WS_MINIMIZEBOX
| WS_SYSMENU
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| WS_VISIBLE
,
1096 LoadMenu(hAppInstance
,
1097 MAKEINTRESOURCE(IDM_MAINMENU
)),
1103 LPTSTR lpErrMessage
;
1106 * no mixer devices are available!
1110 if (AllocAndLoadString(&lpErrMessage
,
1112 IDS_NOMIXERDEVICES
))
1117 MB_ICONINFORMATION
);
1118 LocalFree(lpErrMessage
);
1133 _tWinMain(HINSTANCE hInstance
,
1134 HINSTANCE hPrevInstance
,
1140 INITCOMMONCONTROLSEX Controls
;
1142 UNREFERENCED_PARAMETER(hPrevInstance
);
1143 UNREFERENCED_PARAMETER(lpszCmdLine
);
1144 UNREFERENCED_PARAMETER(nCmdShow
);
1146 hAppInstance
= hInstance
;
1147 hAppHeap
= GetProcessHeap();
1149 if (InitAppConfig())
1151 /* load the application title */
1152 if (!AllocAndLoadString(&lpAppTitle
,
1159 Controls
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
1160 Controls
.dwICC
= ICC_BAR_CLASSES
| ICC_STANDARD_CLASSES
;
1162 InitCommonControlsEx(&Controls
);
1164 if (RegisterApplicationClasses())
1166 hMainWnd
= CreateApplicationWindow();
1167 if (hMainWnd
!= NULL
)
1170 while ((bRet
=GetMessage(&Msg
,
1177 TranslateMessage(&Msg
);
1178 DispatchMessage(&Msg
);
1182 DestroyWindow(hMainWnd
);
1187 DPRINT("Failed to create application window (LastError: %d)!\n", GetLastError());
1190 UnregisterApplicationClasses();
1194 DPRINT("Failed to register application classes (LastError: %d)!\n", GetLastError());
1197 if (lpAppTitle
!= NULL
)
1199 LocalFree(lpAppTitle
);
1206 DPRINT("Unable to open the Volume Control registry key!\n");