|
|
/*****************************************************************************
* * Component: sndvol32.exe * File: choice.c * Purpose: properties dialog box code * * Copyright (c) 1985-1999 Microsoft Corporation * *****************************************************************************/
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <commctrl.h>
#include "volids.h"
#include "volumei.h"
#include "utils.h"
typedef struct t_DEVICEPROP { BOOL fMixer; // is mixer
UINT uDeviceID; // device ID
DWORD dwPlayback; // mixerline representing playback
DWORD dwRecording; // mixerline representing recording
MIXERCAPS mxcaps; } DEVICEPROP, *PDEVICEPROP;
typedef struct t_PRIVPROP { PMIXUIDIALOG pmxud; // app instance data
PDEVICEPROP adp; // array of allocated device props
PDEVICEPROP pdpCurSel; // current device selection
DWORD dwDestSel; // last destination selection
PVOLCTRLDESC avcd; DWORD cvcd; // in/out params
UINT uDeviceID; BOOL fMixer; DWORD dwDestination; DWORD dwStyle; } PRIVPROP, *PPRIVPROP;
#define PROPATOM TEXT("privprop")
const TCHAR gszPropAtom[] = PROPATOM; #define SETPROP(x,y) SetProp((x), gszPropAtom, (HANDLE)(y))
#define GETPROP(x) (PPRIVPROP)GetProp((x), gszPropAtom)
#define REMOVEPROP(x) RemoveProp(x,gszPropAtom)
void SetCheckState (HWND hwndLV, int nItem, BOOL bCheck) { LVITEM item; int nCheck = bCheck ? 2 : 1; // one based index
ZeroMemory (&item, sizeof (item)); item.mask = LVIF_STATE; item.iItem = nItem; item.stateMask = LVIS_STATEIMAGEMASK; item.state = INDEXTOSTATEIMAGEMASK (nCheck); ListView_SetItem (hwndLV, &item); }
void EnableOk( HWND hwnd, BOOL fEnable) { HWND hOk, hCancel; BOOL fWasEnabled; hOk = GetDlgItem(hwnd,IDOK); hCancel = GetDlgItem(hwnd,IDCANCEL); fWasEnabled = IsWindowEnabled(hOk);
if (!fEnable && fWasEnabled) { Button_SetStyle(hOk, BS_PUSHBUTTON, TRUE); SendMessage(hwnd, DM_SETDEFID, IDCANCEL, 0L); EnableWindow(hOk, FALSE); } else if (fEnable && !fWasEnabled) { EnableWindow(hOk, TRUE); Button_SetStyle(hCancel, BS_PUSHBUTTON, TRUE); SendMessage(hwnd, DM_SETDEFID, IDOK, 0L); } }
void Properties_GroupEnable( HWND hwnd, const int ids[], int cids, BOOL fEnable) { int i; for (i = 0; i < cids; i++) EnableWindow(GetDlgItem(hwnd, ids[i]), fEnable); } void Properties_Enable_Prop_Volumes( HWND hwnd, BOOL fEnable) { const int ids[] = { IDC_PROP_VOLUMES, IDC_PROP_PLAYBACK, IDC_PROP_RECORDING, IDC_PROP_OTHER, IDC_PROP_OTHERLIST }; if (!fEnable) ComboBox_SetCurSel(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), -1); Properties_GroupEnable(hwnd, ids, SIZEOF(ids), fEnable); }
void Properties_Enable_PROP_DEVICELIST( HWND hwnd, BOOL fEnable) { const int ids[] = { IDC_PROP_TXT1, IDC_PROP_DEVICELIST, }; if (!fEnable) ComboBox_SetCurSel(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), -1); Properties_GroupEnable(hwnd, ids, SIZEOF(ids), fEnable); }
void Properties_Enable_PROP_VOLUMELIST( HWND hwnd, BOOL fEnable) { const int ids[] = { IDC_PROP_TXT2, IDC_PROP_VOLUMELIST, }; Properties_GroupEnable(hwnd, ids, SIZEOF(ids), fEnable); }
void Properties_CommitState( PPRIVPROP ppr, HWND hlb) { DWORD i; DWORD cItems = ListView_GetItemCount(hlb); if (!ppr->avcd) return; for (i=0;i<cItems;i++) { LV_ITEM lvi; lvi.iItem = i; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM; if (ListView_GetItem(hlb, &lvi)) { ppr->avcd[lvi.lParam].dwSupport = (ListView_GetCheckState (hlb, i))?0:VCD_SUPPORTF_HIDDEN; } } Volume_GetSetRegistryLineStates(ppr->pdpCurSel->mxcaps.szPname , ppr->avcd[0].szShortName , ppr->avcd , ppr->cvcd , SET );
Mixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd);
GlobalFreePtr(ppr->avcd); ppr->avcd = NULL; ppr->cvcd = 0L; }
/*
* Init the destination type groupbox * * */ BOOL Properties_Init_Prop_Volumes( PPRIVPROP ppr, HWND hwnd) { HWND hPlay = GetDlgItem(hwnd, IDC_PROP_PLAYBACK); HWND hRec = GetDlgItem(hwnd, IDC_PROP_RECORDING); HWND hOther = GetDlgItem(hwnd, IDC_PROP_OTHER); HWND hOtherList = GetDlgItem(hwnd, IDC_PROP_OTHERLIST); DWORD iDest, cDest; BOOL fPlay = FALSE, fRec = FALSE; if (!ppr->pdpCurSel->fMixer) return FALSE;
ComboBox_ResetContent(hOtherList);
cDest = ppr->pdpCurSel->mxcaps.cDestinations; EnableWindow(hPlay, FALSE); EnableWindow(hRec, FALSE); EnableWindow(hOther, FALSE); for (iDest = 0; iDest < cDest; iDest++) { MIXERLINE mlDst; int imx; mlDst.cbStruct = sizeof ( mlDst ); mlDst.dwDestination = iDest;
if (mixerGetLineInfo((HMIXEROBJ)UIntToPtr(ppr->pdpCurSel->uDeviceID) , &mlDst , MIXER_GETLINEINFOF_DESTINATION) != MMSYSERR_NOERROR) continue;
//
// Conditionally enable selections. The first type for Play and
// Record are the default Playback and Recording radiobuttons.
// The next occurence of the same type is heaped into the Other
// category.
//
if (mlDst.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS && !fPlay) { EnableWindow(hPlay, TRUE);
if (iDest == ppr->dwDestSel) CheckRadioButton(hwnd, IDC_PROP_PLAYBACK, IDC_PROP_OTHER , IDC_PROP_PLAYBACK); ppr->pdpCurSel->dwPlayback = iDest; fPlay = TRUE; } else if (mlDst.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_WAVEIN && !fRec) { EnableWindow(hRec, TRUE);
if (iDest == ppr->dwDestSel) CheckRadioButton(hwnd, IDC_PROP_PLAYBACK, IDC_PROP_OTHER , IDC_PROP_RECORDING); ppr->pdpCurSel->dwRecording = iDest; fRec = TRUE; } else { EnableWindow(hOther, TRUE); imx = ComboBox_AddString(hOtherList, mlDst.szName); ComboBox_SetItemData(hOtherList, imx, iDest);
if (iDest == ppr->dwDestSel) { CheckRadioButton(hwnd, IDC_PROP_PLAYBACK, IDC_PROP_OTHER , IDC_PROP_OTHER); ComboBox_SetCurSel(hOtherList, imx); } } }
//
// Disable the "other" drop down if its not selected
//
if (!IsDlgButtonChecked(hwnd, IDC_PROP_OTHER)) { ComboBox_SetCurSel(hOtherList, 0); EnableWindow(hOtherList, FALSE); } return TRUE; } BOOL Properties_Init_PROP_VOLUMELIST( PPRIVPROP ppr, HWND hwnd) { HWND hlb = GetDlgItem(hwnd, IDC_PROP_VOLUMELIST); LV_COLUMN col = {LVCF_FMT | LVCF_WIDTH, LVCFMT_LEFT}; RECT rc; BOOL fSet = FALSE; PVOLCTRLDESC avcd = NULL; DWORD cvcd = 0L; DWORD ivcd; int ilvi; LV_ITEM lvi; ListView_DeleteAllItems(hlb); ListView_SetExtendedListViewStyleEx (hlb, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); ZeroMemory (&lvi, sizeof (lvi));
GetClientRect(hlb, &rc); col.cx = rc.right - 2 * GetSystemMetrics(SM_CXEDGE); ListView_InsertColumn(hlb, 0, &col);
if (ppr->avcd) { if (ppr->pdpCurSel->fMixer) Mixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd); // else
// Nonmixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd);
GlobalFreePtr(ppr->avcd); ppr->avcd = NULL; ppr->cvcd = 0L; } if (ppr->pdpCurSel->fMixer) { HMIXER hmx; MMRESULT mmr;
//
// Mixer API's are much more efficient with mixer handle...
//
mmr = mixerOpen(&hmx , ppr->pdpCurSel->uDeviceID , 0L , 0L , MIXER_OBJECTF_MIXER);
if(MMSYSERR_NOERROR == mmr) { avcd = Mixer_CreateVolumeDescription((HMIXEROBJ)hmx , ppr->dwDestSel , &cvcd);
mixerClose(hmx); } else { avcd = Mixer_CreateVolumeDescription((HMIXEROBJ)UIntToPtr(ppr->pdpCurSel->uDeviceID) , ppr->dwDestSel , &cvcd); } } else { avcd = Nonmixer_CreateVolumeDescription(ppr->dwDestSel , &cvcd);
}
if (avcd) { BOOL fFirstRun; //
// Restore hidden state
//
fFirstRun = !Volume_GetSetRegistryLineStates(ppr->pdpCurSel->mxcaps.szPname , avcd[0].szShortName , avcd , cvcd , GET );
if (fFirstRun) { for (ivcd = 0; ivcd < cvcd; ivcd++) { if (!(avcd[ivcd].dwSupport & VCD_SUPPORTF_DEFAULT)) avcd[ivcd].dwSupport |= VCD_SUPPORTF_HIDDEN; } Volume_GetSetRegistryLineStates(ppr->pdpCurSel->mxcaps.szPname , avcd[0].szShortName , avcd , cvcd , SET); } for (ivcd = 0, ilvi = 0; ivcd < cvcd; ivcd++) { if (!(avcd[ivcd].dwSupport & VCD_SUPPORTF_VISIBLE)) continue;
lvi.iItem = ilvi; lvi.iSubItem = 0; lvi.mask = LVIF_TEXT|LVIF_PARAM; lvi.lParam = ivcd; lvi.pszText = avcd[ivcd].szName;
ListView_InsertItem(hlb, &lvi); if (!(avcd[ivcd].dwSupport & VCD_SUPPORTF_HIDDEN)) { fSet = TRUE; SetCheckState (hlb, ilvi, TRUE); } ilvi++;
} ppr->avcd = avcd; ppr->cvcd = cvcd; } ListView_SetItemState(hlb, 0, TRUE, LVIS_FOCUSED);
EnableOk(hwnd, fSet); return TRUE; }
/*
* Init the list of devices. * * */ BOOL Properties_Init_PROP_DEVICELIST( PPRIVPROP ppr, HWND hwnd) { HWND hlb = GetDlgItem(hwnd, IDC_PROP_DEVICELIST); int iMixer; int cValidMixers = 0; int cMixers;
cMixers = mixerGetNumDevs(); if (!cMixers) return FALSE;
ppr->adp = (PDEVICEPROP)GlobalAllocPtr(GHND,cMixers * sizeof(DEVICEPROP)); if (ppr->adp == NULL) return FALSE; for (iMixer = 0; iMixer < cMixers; iMixer++) { int imx; MIXERCAPS* pmxcaps = &ppr->adp[iMixer].mxcaps; MMRESULT mmr; mmr = mixerGetDevCaps(iMixer, pmxcaps, sizeof(MIXERCAPS));
if (mmr != MMSYSERR_NOERROR) continue;
cValidMixers++; imx = ComboBox_AddString(hlb, pmxcaps->szPname); ppr->adp[iMixer].uDeviceID = iMixer; ppr->adp[iMixer].fMixer = TRUE; ComboBox_SetItemData(hlb, imx, &ppr->adp[iMixer]); } if (cValidMixers == 0) return FALSE;
return TRUE; }
BOOL Properties_OnCommand( HWND hwnd, int id, HWND hctl, UINT unotify) { PPRIVPROP ppr = GETPROP(hwnd); if (!ppr) return FALSE;
switch (id) { case IDC_PROP_DEVICELIST: if (unotify == CBN_SELCHANGE) { int imx; PDEVICEPROP pdp; imx = ComboBox_GetCurSel(hctl); pdp = (PDEVICEPROP)ComboBox_GetItemData(hctl, imx);
if (pdp == ppr->pdpCurSel) break;
ppr->pdpCurSel = pdp; if (ppr->pdpCurSel->fMixer) Properties_Init_Prop_Volumes(ppr, hwnd); else Properties_Enable_Prop_Volumes(hwnd, FALSE); Properties_Init_PROP_VOLUMELIST(ppr, hwnd); } break; case IDC_PROP_PLAYBACK: EnableWindow(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), FALSE); if (ppr->dwDestSel == ppr->pdpCurSel->dwPlayback) break; ppr->dwDestSel = ppr->pdpCurSel->dwPlayback; Properties_Init_PROP_VOLUMELIST(ppr, hwnd); break; case IDC_PROP_RECORDING: EnableWindow(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), FALSE); if (ppr->dwDestSel == ppr->pdpCurSel->dwRecording) break; ppr->dwDestSel = ppr->pdpCurSel->dwRecording; Properties_Init_PROP_VOLUMELIST(ppr, hwnd); break; case IDC_PROP_OTHER: { HWND hol; DWORD dwSel; hol = GetDlgItem(hwnd, IDC_PROP_OTHERLIST); EnableWindow(hol, TRUE); ComboBox_SetCurSel(hol, 0); dwSel = (DWORD)ComboBox_GetItemData(hol, 0); if (ppr->dwDestSel == dwSel) break;
ppr->dwDestSel = dwSel; Properties_Init_PROP_VOLUMELIST(ppr, hwnd); break; } case IDC_PROP_OTHERLIST: if (unotify == CBN_SELCHANGE) { int idst; DWORD dwSel; idst = ComboBox_GetCurSel(hctl); dwSel = (DWORD)ComboBox_GetItemData(hctl, idst); if (ppr->dwDestSel == dwSel) break; ppr->dwDestSel = dwSel; Properties_Init_PROP_VOLUMELIST(ppr, hwnd); } break; case IDOK: //
// Save out to registry for restaring.
//
Properties_CommitState(ppr, GetDlgItem(hwnd, IDC_PROP_VOLUMELIST));
ppr->uDeviceID = ppr->pdpCurSel->uDeviceID; ppr->fMixer = TRUE; ppr->dwDestination = ppr->dwDestSel; EndDialog(hwnd, TRUE); break; case IDCANCEL: Mixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd); if (ppr->avcd) { GlobalFreePtr(ppr->avcd); ppr->avcd = NULL; ppr->cvcd = 0L; } EndDialog(hwnd, FALSE); break; } return FALSE; }
/*
* Initialize the dialog * * */ BOOL Properties_OnInitDialog( HWND hwnd, HWND hwndFocus, LPARAM lParam) { PPRIVPROP ppr; BOOL fEnable = TRUE; HWND hlv; SETPROP(hwnd, (PPRIVPROP)lParam); ppr = GETPROP(hwnd); if (!ppr) fEnable = FALSE; if (fEnable) fEnable = Properties_Init_PROP_DEVICELIST(ppr, hwnd);
hlv = GetDlgItem(hwnd, IDC_PROP_VOLUMELIST); if (!fEnable) { //
// Bad state, disable everything except cancel
//
Properties_Enable_PROP_DEVICELIST(hwnd, FALSE); Properties_Enable_Prop_Volumes(hwnd, FALSE); Properties_Enable_PROP_VOLUMELIST(hwnd, FALSE); EnableOk(hwnd, FALSE); return FALSE; } else { int i; PDEVICEPROP pdp; HWND hdl;
//
// make intial device selection
//
hdl = GetDlgItem(hwnd, IDC_PROP_DEVICELIST);
ppr->dwDestSel = 0; ComboBox_SetCurSel(hdl, 0); ppr->pdpCurSel = (PDEVICEPROP)ComboBox_GetItemData(hdl, 0); i = ComboBox_GetCount(hdl); for (; i > 0 ; i-- ) { pdp = (PDEVICEPROP)ComboBox_GetItemData(hdl,i-1); //
// if things match up, then set the init data
//
if (pdp->uDeviceID == ppr->uDeviceID && pdp->fMixer == ppr->fMixer) { ppr->pdpCurSel = pdp; ComboBox_SetCurSel(hdl, i-1); ppr->dwDestSel = ppr->dwDestination; break; } } }
Properties_Init_Prop_Volumes(ppr, hwnd); Properties_Init_PROP_VOLUMELIST(ppr, hwnd); return FALSE; }
INT_PTR CALLBACK Properties_Proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { extern TCHAR gszHelpFileName[]; #include "helpids.h"
static const DWORD aHelpIds[] = { IDC_PROP_TXT1, IDH_SNDVOL32_SELECT_DEVICE, IDC_PROP_DEVICELIST, IDH_SNDVOL32_SELECT_DEVICE, IDC_PROP_VOLUMES, IDH_SNDVOL32_SELECT_SOUND, IDC_PROP_PLAYBACK, IDH_SNDVOL32_SELECT_SOUND, IDC_PROP_RECORDING, IDH_SNDVOL32_SELECT_SOUND, IDC_PROP_OTHER, IDH_SNDVOL32_SELECT_SOUND, IDC_PROP_OTHERLIST, IDH_SNDVOL32_SELECT_SOUND, IDC_PROP_TXT2, IDH_SNDVOL32_VOLCONTROL, IDC_PROP_VOLUMELIST, IDH_SNDVOL32_VOLCONTROL, 0, 0 }; switch (msg) { case WM_CONTEXTMENU: WinHelp((HWND)wparam, gszHelpFileName, HELP_CONTEXTMENU, (UINT_PTR)(LPSTR)aHelpIds); break; case WM_HELP: { LPHELPINFO lphi = (LPVOID) lparam; WinHelp (lphi->hItemHandle, gszHelpFileName, HELP_WM_HELP, (UINT_PTR) (LPSTR) aHelpIds); return TRUE; } case WM_INITDIALOG: HANDLE_WM_INITDIALOG(hwnd, wparam, lparam, Properties_OnInitDialog); return TRUE; case WM_COMMAND: HANDLE_WM_COMMAND(hwnd, wparam, lparam, Properties_OnCommand); break;
case WM_CLOSE: EndDialog(hwnd, FALSE); break;
case WM_DESTROY: { PPRIVPROP ppr = GETPROP(hwnd); if (ppr) { if (ppr->adp) { GlobalFreePtr(ppr->adp); ppr->adp = NULL; } REMOVEPROP(hwnd); } break; }
case WM_NOTIFY: { NMHDR FAR* lpnm = (NMHDR FAR *)lparam; if ((LVN_ITEMCHANGED == lpnm->code) && hwnd) { HWND hwndLV = GetDlgItem (hwnd, IDC_PROP_VOLUMELIST); if (hwndLV) { int nItems = ListView_GetItemCount (hwndLV); int indx;
for (indx = 0; indx < nItems; indx++) if (ListView_GetCheckState (hwndLV, indx)) break;
EnableOk (hwnd, nItems != indx); } } break; } } return FALSE; }
BOOL Properties( PMIXUIDIALOG pmxud, HWND hwnd) { INT_PTR iret; PRIVPROP pr;
ZeroMemory(&pr, sizeof(pr)); pr.dwDestination = pmxud->iDest; pr.uDeviceID = pmxud->mxid; pr.fMixer = pmxud->dwFlags & MXUD_FLAGSF_MIXER; pr.dwStyle = pmxud->dwStyle; pr.pmxud = pmxud;
iret = DialogBoxParam(pmxud->hInstance , MAKEINTRESOURCE(IDD_PROPERTIES) , hwnd , Properties_Proc , (LPARAM)(LPVOID)&pr );
if (iret == TRUE) { pmxud->mxid = pr.uDeviceID; pmxud->iDest = pr.dwDestination; pmxud->dwFlags &= ~MXUD_FLAGSF_MIXER; pmxud->dwFlags |= (pr.fMixer)?MXUD_FLAGSF_MIXER:0L; pmxud->dwStyle = pr.dwStyle; }
return (iret == -1) ? FALSE : TRUE; }
|