/*
* PROJECT: ReactOS Multimedia Control Panel
- * FILE: dll/cpl/mmsys/mmsys.c
+ * FILE: dll/cpl/mmsys/volume.c
* PURPOSE: ReactOS Multimedia Control Panel
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* Johannes Anderwald <janderwald@reactos.com>
#include <shellapi.h>
-#define VOLUME_DIVIDER 0xFFF
typedef struct _IMGINFO
{
HMIXER hMixer;
HICON hIconMuted;
HICON hIconUnMuted;
+ HICON hIconNoHW;
LONG muteVal;
DWORD muteControlID;
DWORD volumeControlID;
+ DWORD volumeChannels;
DWORD volumeMinimum;
DWORD volumeMaximum;
- DWORD volumeValue;
+ DWORD volumeStep;
+
+ DWORD maxVolume;
+ PMIXERCONTROLDETAILS_UNSIGNED volumeInitValues;
+ PMIXERCONTROLDETAILS_UNSIGNED volumeCurrentValues;
} GLOBAL_DATA, *PGLOBAL_DATA;
!= MMSYSERR_NOERROR)
return;
+ pGlobalData->volumeChannels = mxln.cChannels;
+
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
mxlc.dwLineID = mxln.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
pGlobalData->volumeMinimum = mxc.Bounds.dwMinimum;
pGlobalData->volumeMaximum = mxc.Bounds.dwMaximum;
pGlobalData->volumeControlID = mxc.dwControlID;
+ pGlobalData->volumeStep = (pGlobalData->volumeMaximum - pGlobalData->volumeMinimum) / (VOLUME_MAX - VOLUME_MIN);
+
+ pGlobalData->volumeInitValues = HeapAlloc(GetProcessHeap(),
+ 0,
+ mxln.cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED));
+ if (pGlobalData->volumeInitValues == NULL)
+ return;
+
+ pGlobalData->volumeCurrentValues = HeapAlloc(GetProcessHeap(),
+ 0,
+ mxln.cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED));
+ if (pGlobalData->volumeCurrentValues == NULL)
+ return;
}
VOID
GetVolumeValue(PGLOBAL_DATA pGlobalData)
{
- MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
MIXERCONTROLDETAILS mxcd;
+ DWORD i;
if (pGlobalData->hMixer == NULL)
return;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pGlobalData->volumeControlID;
- mxcd.cChannels = 1;
+ mxcd.cChannels = pGlobalData->volumeChannels;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
- mxcd.paDetails = &mxcdVolume;
+ mxcd.paDetails = pGlobalData->volumeInitValues;
if (mixerGetControlDetails((HMIXEROBJ)pGlobalData->hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE)
!= MMSYSERR_NOERROR)
return;
- pGlobalData->volumeValue = mxcdVolume.dwValue;
+ pGlobalData->maxVolume = 0;
+ for (i = 0; i < pGlobalData->volumeChannels; i++)
+ {
+ pGlobalData->volumeCurrentValues[i].dwValue = pGlobalData->volumeInitValues[i].dwValue;
+
+ if (pGlobalData->volumeInitValues[i].dwValue > pGlobalData->maxVolume)
+ pGlobalData->maxVolume = pGlobalData->volumeInitValues[i].dwValue;
+ }
}
VOID
-SetVolumeValue(PGLOBAL_DATA pGlobalData){
- MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
+SetVolumeValue(PGLOBAL_DATA pGlobalData,
+ DWORD dwPosition)
+{
MIXERCONTROLDETAILS mxcd;
+ DWORD dwVolume, i;
if (pGlobalData->hMixer == NULL)
return;
- mxcdVolume.dwValue = pGlobalData->volumeValue;
+ if (dwPosition == VOLUME_MIN)
+ dwVolume = pGlobalData->volumeMinimum;
+ else if (dwPosition == VOLUME_MAX)
+ dwVolume = pGlobalData->volumeMaximum;
+ else
+ dwVolume = (dwPosition * pGlobalData->volumeStep) + pGlobalData->volumeMinimum;
+
+ for (i = 0; i < pGlobalData->volumeChannels; i++)
+ {
+ if (pGlobalData->volumeInitValues[i].dwValue == pGlobalData->maxVolume)
+ {
+ pGlobalData->volumeCurrentValues[i].dwValue = dwVolume;
+ }
+ else
+ {
+ pGlobalData->volumeCurrentValues[i].dwValue =
+ pGlobalData->volumeInitValues[i].dwValue * dwVolume / pGlobalData-> maxVolume;
+ }
+ }
+
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pGlobalData->volumeControlID;
- mxcd.cChannels = 1;
+ mxcd.cChannels = pGlobalData->volumeChannels;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
- mxcd.paDetails = &mxcdVolume;
+ mxcd.paDetails = pGlobalData->volumeCurrentValues;
if (mixerSetControlDetails((HMIXEROBJ)pGlobalData->hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE)
!= MMSYSERR_NOERROR)
return;
+}
- pGlobalData->volumeValue = mxcdVolume.dwValue;
+
+static
+VOID
+SetSystrayVolumeIconState(BOOL bEnabled)
+{
+ HWND hwndTaskBar;
+
+ hwndTaskBar = FindWindowW(L"SystemTray_Main", NULL);
+ if (hwndTaskBar == NULL)
+ return;
+
+ SendMessageW(hwndTaskBar, WM_USER + 220, 4, bEnabled);
}
+static
+BOOL
+GetSystrayVolumeIconState(VOID)
+{
+ HWND hwndTaskBar;
+
+ hwndTaskBar = FindWindowW(L"SystemTray_Main", NULL);
+ if (hwndTaskBar == NULL)
+ {
+ return FALSE;
+ }
+
+ return (BOOL)SendMessageW(hwndTaskBar, WM_USER + 221, 4, 0);
+}
VOID
InitVolumeControls(HWND hwndDlg, PGLOBAL_DATA pGlobalData)
{
UINT NumMixers;
MIXERCAPS mxc;
+ TCHAR szNoDevices[256];
+
+ CheckDlgButton(hwndDlg,
+ IDC_ICON_IN_TASKBAR,
+ GetSystrayVolumeIconState() ? BST_CHECKED : BST_UNCHECKED);
+
+ LoadString(hApplet, IDS_NO_DEVICES, szNoDevices, _countof(szNoDevices));
NumMixers = mixerGetNumDevs();
if (!NumMixers)
{
EnableWindow(GetDlgItem(hwndDlg, IDC_VOLUME_TRACKBAR), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_MUTE_CHECKBOX), FALSE);
- EnableWindow(GetDlgItem(hwndDlg, IDC_ICON_IN_TASKBAR), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_ADVANCED_BTN), FALSE);
- EnableWindow(GetDlgItem(hwndDlg, IDC_SPEAKER_SET_BTN), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_SPEAKER_VOL_BTN), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_ADVANCED2_BTN), FALSE);
- SendDlgItemMessage(hwndDlg, IDC_MUTE_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pGlobalData->hIconMuted);
+ SendDlgItemMessage(hwndDlg, IDC_MUTE_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pGlobalData->hIconNoHW);
+ SetDlgItemText(hwndDlg, IDC_DEVICE_NAME, szNoDevices);
return;
}
GetVolumeValue(pGlobalData);
SendDlgItemMessage(hwndDlg, IDC_DEVICE_NAME, WM_SETTEXT, 0, (LPARAM)mxc.szPname);
- SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETRANGE, (WPARAM)TRUE,
- (LPARAM)MAKELONG(pGlobalData->volumeMinimum, pGlobalData->volumeMaximum/VOLUME_DIVIDER));
- SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETPAGESIZE, (WPARAM)FALSE, (LPARAM)1);
- SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETSEL, (WPARAM)FALSE,
- (LPARAM)MAKELONG(pGlobalData->volumeMinimum, pGlobalData->volumeValue/VOLUME_DIVIDER));
- SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pGlobalData->volumeValue/VOLUME_DIVIDER);
+ SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(VOLUME_MIN, VOLUME_MAX));
+ SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETTICFREQ, VOLUME_TICFREQ, 0);
+ SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETPAGESIZE, 0, VOLUME_PAGESIZE);
+ SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(pGlobalData->maxVolume - pGlobalData->volumeMinimum) / pGlobalData->volumeStep);
}
+VOID
+SaveData(HWND hwndDlg)
+{
+ BOOL bShowIcon;
+
+ bShowIcon = (IsDlgButtonChecked(hwndDlg, IDC_ICON_IN_TASKBAR) == BST_CHECKED);
+
+ SetSystrayVolumeIconState(!bShowIcon);
+}
VOID
LaunchSoundControl(HWND hwndDlg)
pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
-
-
switch(uMsg)
{
case MM_MIXM_LINE_CHANGE:
case MM_MIXM_CONTROL_CHANGE:
{
GetVolumeValue(pGlobalData);
- SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETSEL, (WPARAM)FALSE, (LPARAM)MAKELONG(pGlobalData->volumeMinimum, pGlobalData->volumeValue/VOLUME_DIVIDER));
- SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pGlobalData->volumeValue/VOLUME_DIVIDER);
+ SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(pGlobalData->maxVolume - pGlobalData->volumeMinimum) / pGlobalData->volumeStep);
break;
}
case WM_INITDIALOG:
pGlobalData->hIconUnMuted = LoadImage(hApplet, MAKEINTRESOURCE(IDI_CPLICON), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
pGlobalData->hIconMuted = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MUTED_ICON), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
+ pGlobalData->hIconNoHW = LoadImage(hApplet, MAKEINTRESOURCE(IDI_NO_HW), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
InitImageInfo(&ImgInfo);
InitVolumeControls(hwndDlg, pGlobalData);
switch (LOWORD(wParam))
{
case IDC_MUTE_CHECKBOX:
- SwitchMuteState(pGlobalData);
- if (pGlobalData->muteVal)
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ SwitchMuteState(pGlobalData);
+ if (pGlobalData->muteVal)
{
- SendDlgItemMessage(hwndDlg, IDC_MUTE_CHECKBOX, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
SendDlgItemMessage(hwndDlg, IDC_MUTE_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pGlobalData->hIconMuted);
}
else
{
- SendDlgItemMessage(hwndDlg, IDC_MUTE_CHECKBOX, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
SendDlgItemMessage(hwndDlg, IDC_MUTE_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pGlobalData->hIconUnMuted);
}
+
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ }
+ break;
+
+ case IDC_ICON_IN_TASKBAR:
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ }
break;
+
case IDC_ADVANCED_BTN:
LaunchSoundControl(hwndDlg);
break;
+
+ case IDC_SPEAKER_VOL_BTN:
+ SpeakerVolume(hwndDlg);
+ break;
}
break;
}
HWND hVolumeTrackbar = GetDlgItem(hwndDlg, IDC_VOLUME_TRACKBAR);
if (hVolumeTrackbar == (HWND)lParam)
{
- pGlobalData->volumeValue = (DWORD)SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_GETPOS, 0, 0)*VOLUME_DIVIDER;
- SetVolumeValue(pGlobalData);
- SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_SETSEL, (WPARAM)TRUE,
- (LPARAM)MAKELONG(pGlobalData->volumeMinimum, pGlobalData->volumeValue/VOLUME_DIVIDER));
+ switch (LOWORD(wParam))
+ {
+ case TB_THUMBPOSITION:
+ break;
+
+ case TB_ENDTRACK:
+ PlaySound((LPCTSTR)SND_ALIAS_SYSTEMDEFAULT, NULL, SND_ALIAS_ID | SND_ASYNC);
+ break;
+
+ default:
+ SetVolumeValue(pGlobalData,
+ (DWORD)SendDlgItemMessage(hwndDlg, IDC_VOLUME_TRACKBAR, TBM_GETPOS, 0, 0));
+ break;
+ }
}
break;
}
case WM_DESTROY:
- mixerClose(pGlobalData->hMixer);
- DestroyIcon(pGlobalData->hIconMuted);
- DestroyIcon(pGlobalData->hIconUnMuted);
- HeapFree(GetProcessHeap(), 0, pGlobalData);
+ if (pGlobalData)
+ {
+ if (pGlobalData->volumeInitValues)
+ HeapFree(GetProcessHeap(), 0, pGlobalData->volumeInitValues);
+
+ if (pGlobalData->volumeCurrentValues)
+ HeapFree(GetProcessHeap(), 0, pGlobalData->volumeCurrentValues);
+
+ mixerClose(pGlobalData->hMixer);
+ DestroyIcon(pGlobalData->hIconMuted);
+ DestroyIcon(pGlobalData->hIconUnMuted);
+ DestroyIcon(pGlobalData->hIconNoHW);
+ HeapFree(GetProcessHeap(), 0, pGlobalData);
+ }
break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
+ {
+ SaveData(hwndDlg);
+ }
+ return TRUE;
}
return FALSE;