//==========================================================================;
//
//  cpl.c
//
//  Copyright (c) 1991-1993 Microsoft Corporation.  All Rights Reserved.
//
//  Description:
//
//
//  History:
//      07/94        VijR (Vij Rajarajan);
//
//      10/95        R Jernigan - removed link to Adv tab's treeview control
//
//==========================================================================;
#include "mmcpl.h"
#include <windowsx.h>
#include <mmsystem.h>
#include <dbt.h>
#include <ks.h>
#include <ksmedia.h>
#include <mmddkp.h>
#include <mmreg.h>
#include <msacm.h>
#include <msacmdrv.h>
#include <msacmdlg.h>
#include <stdlib.h>
#include "gfxui.h"
#include "drivers.h"
#include "advaudio.h"
#include "roland.h"

#include <objbase.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <initguid.h>
#include <devguid.h>

#define WM_ACMMAP_ACM_NOTIFY        (WM_USER + 100)

#include <memory.h>
#include <commctrl.h>
#include <prsht.h>
#include <regstr.h>
#include "trayvol.h"

#include "utils.h"
#include "medhelp.h"

/*
 ***************************************************************
 * Defines
 ***************************************************************
 */

#ifndef DRV_F_ADD
#define DRV_F_ADD              0x00000000         // TODO: Should be in MMDDK.H
#define DRV_F_REMOVE           0x00000001
#define DRV_F_CHANGE           0x00000002
#define DRV_F_PROP_INSTR       0x00000004
#define DRV_F_NEWDEFAULTS      0x00000008
#define DRV_F_PARAM_IS_DEVNODE 0x10000000
#endif

#ifndef ACMHELPMSGCONTEXTMENU                                  // TODO: Should
#define ACMHELPMSGCONTEXTMENU   TEXT("acmchoose_contextmenu")  // be in MSACM.H
#define ACMHELPMSGCONTEXTHELP   TEXT("acmchoose_contexthelp")
#endif

#ifndef ACMFORMATCHOOSE_STYLEF_CONTEXTHELP    // TODO: Should be in MSACM.H
#define ACMFORMATCHOOSE_STYLEF_CONTEXTHELP    0x00000080L
#endif

/*
 ***************************************************************
 * Globals
 ***************************************************************
 */

BOOL        gfLoadedACM;
UINT        giDevChange = 0;
WNDPROC     gfnPSProc = NULL;
HWND        ghDlg;

/*
 ***************************************************************
 *  Typedefs
 ***************************************************************
 */
typedef struct tACMDRIVERSETTINGS
    {
    HACMDRIVERID        hadid;
    DWORD               fdwSupport;
    DWORD               dwPriority;
    } ACMDRIVERSETTINGS, FAR *LPACMDRIVERSETTINGS;

typedef struct _CplCodecInfo
    {
    TCHAR szDesc[128];
    ACMDRIVERSETTINGS ads;
    HICON hIcon;
    BOOL  fMadeIcon;
    }CPLCODECINFO, * PCPLCODECINFO;



/*
 ***************************************************************
 * File Globals
 ***************************************************************
 */
static CONST TCHAR      aszFormatNumber[]       = TEXT("%lu");

//
//  These hold Window Message IDs for the two messages sent from the
//  Customize dialog (acmFormatChoose) for context-sensitive help.
//
UINT guCustomizeContextMenu = WM_NULL;
UINT guCustomizeContextHelp = WM_NULL;
BOOL fHaveStartedAudioDialog = FALSE;


/*
 ***************************************************************
 * extern
 ***************************************************************
 */

//
//  this string variable must be large enough to hold the IDS_TXT_DISABLED
//  resource string.. for USA, this is '(disabled)'--which is 11 bytes
//  including the NULL terminator.
//
TCHAR gszDevEnabled[256];
TCHAR gszDevDisabled[256];

/*
 ***************************************************************
 * Prototypes
 ***************************************************************
 */

BOOL PASCAL DoACMPropCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
BOOL PASCAL DoAudioCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
BOOL PASCAL CustomizeDialog(HWND hDlg, LPTSTR szNewFormat, DWORD cbSize);
void DoAdvancedSetup(HWND hwnd);

void WAVEOUTInit(HWND hDlg, PAUDIODLGINFO pai);
void WAVEINInit(HWND hDlg, PAUDIODLGINFO pai);


PCPLCODECINFO acmFindCodecInfo         (WORD, WORD);
BOOL CALLBACK acmFindCodecInfoCallback (HACMDRIVERID, DWORD_PTR, DWORD);
void          acmFreeCodecInfo         (PCPLCODECINFO);

UINT          acmCountCodecs           (void);
BOOL CALLBACK acmCountCodecsEnum       (HACMDRIVERID, DWORD_PTR, DWORD);


#ifndef ACM_DRIVERREMOVEF_UNINSTALL
#define ACM_DRIVERREMOVEF_UNINSTALL 0x00000001L
#endif

/*
 ***************************************************************
 ***************************************************************
 */

void acmDeleteCodec (WORD wMid, WORD wPid)
{
    PCPLCODECINFO pci;

    if ((pci = acmFindCodecInfo (wMid, wPid)) != NULL)
    {
        acmDriverRemove (pci->ads.hadid, ACM_DRIVERREMOVEF_UNINSTALL);
        acmFreeCodecInfo (pci);
    }
}




//--------------------------------------------------------------------------;
//
//  INT_PTR DlgProcACMAboutBox
//
//  Description:
//
//
//  Arguments:
//
//  Return (BOOL):
//
//
//  History:
//      11/16/92    cjp     [curtisp]
//
//--------------------------------------------------------------------------;

INT_PTR CALLBACK DlgProcACMAboutBox
(
    HWND                hwnd,
    UINT                uMsg,
    WPARAM              wParam,
    LPARAM              lParam
)
{
    TCHAR               ach[80];
    TCHAR               szFormat[80];
    LPACMDRIVERDETAILS  padd;
    DWORD               dw1;
    DWORD               dw2;
    UINT                uCmdId;

    switch (uMsg)
    {
        case WM_INITDIALOG:
        {
            padd = (LPACMDRIVERDETAILSW)lParam;

            if (NULL == padd)
            {
                DPF(0, "!DlgProcACMAboutBox: NULL driver details passed!");
                return (TRUE);
            }

            //
            //  fill in all the static text controls with the long info
            //  returned from the driver
            //
            LoadString(ghInstance, IDS_ABOUT_TITLE, szFormat, sizeof(szFormat)/sizeof(TCHAR));
            wsprintf(ach, szFormat, (LPTSTR)padd->szShortName);
            SetWindowText(hwnd, ach);

            //
            //  if the driver supplies an icon, then use it..
            //
            if (NULL != padd->hicon)
            {
                Static_SetIcon(GetDlgItem(hwnd, IDD_ABOUT_ICON_DRIVER), padd->hicon);
            }

            SetDlgItemText(hwnd, IDD_ABOUT_TXT_DESCRIPTION, padd->szLongName);

            dw1 = padd->vdwACM;
            dw2 = padd->vdwDriver;
            LoadString(ghInstance, IDS_ABOUT_VERSION, szFormat, sizeof(szFormat)/sizeof(TCHAR));
            wsprintf(ach, szFormat, HIWORD(dw2) >> 8, (BYTE)HIWORD(dw2), HIWORD(dw1) >> 8, (BYTE)HIWORD(dw1));
            SetDlgItemText(hwnd,IDD_ABOUT_TXT_VERSION, ach);
            SetDlgItemText(hwnd, IDD_ABOUT_TXT_COPYRIGHT, padd->szCopyright);
            SetDlgItemText(hwnd, IDD_ABOUT_TXT_LICENSING, padd->szLicensing);
            SetDlgItemText(hwnd, IDD_ABOUT_TXT_FEATURES, padd->szFeatures);
            return (TRUE);
        }
        break;

        case WM_COMMAND:
        {
            uCmdId = GET_WM_COMMAND_ID(wParam,lParam);

            if ((uCmdId == IDOK) || (uCmdId == IDCANCEL))
            EndDialog(hwnd, wParam == uCmdId);
            return (TRUE);
        }
        break;

    }

    return (FALSE);
} // DlgProcACMAboutBox()


//--------------------------------------------------------------------------;
//
//  void ControlAboutDriver
//
//  Description:
//
//
//  Arguments:
//      HWND hwnd:
//
//      LPACMDRIVERSETTINGS pads:
//
//  Return (void):
//
//  History:
//      09/08/93    cjp     [curtisp]
//
//--------------------------------------------------------------------------;

STATIC void  ControlAboutDriver
(
    HWND                    hwnd,
    LPACMDRIVERSETTINGS     pads
)
{
    PACMDRIVERDETAILSW   padd;
    MMRESULT             mmr;

    if (NULL == pads)
    {
        return;
    }

    //
    //  if the driver returns MMSYSERR_NOTSUPPORTED, then we need to
    //  display the info--otherwise, it supposedly displayed a dialog
    //  (or had a critical error?)
    //
    mmr = (MMRESULT)acmDriverMessage((HACMDRIVER)pads->hadid, ACMDM_DRIVER_ABOUT, (LPARAM)hwnd, 0L);

    if ((MMRESULT)MMSYSERR_NOTSUPPORTED != mmr)
    {
        return;
    }

    //
    //  alloc some zero-init'd memory to hold the about box info
    //
    padd = (PACMDRIVERDETAILS)LocalAlloc(LPTR, sizeof(*padd));
    if (NULL == padd)
    {
        DPF("!PACMDRIVERDETAILSA LocalAlloc failed");
        return;
    }
    //
    //  get info and bring up a generic about box...
    //
    padd->cbStruct = sizeof(*padd);
    mmr = (MMRESULT)acmDriverDetails(pads->hadid, padd, 0L);
    if (MMSYSERR_NOERROR == mmr)
    {
        DialogBoxParam(ghInstance, MAKEINTRESOURCE(DLG_ABOUT_MSACM), hwnd, DlgProcACMAboutBox, (LPARAM)(LPVOID)padd);
    }

    LocalFree((HLOCAL)padd);
} // ControlAboutDriver()


//--------------------------------------------------------------------------;
//
//  BOOL ControlConfigureDriver
//
//  Description:
//
//
//  Arguments:
//      HWND hwnd:
//
//      LPACMDRIVERSETTINGS pads:
//
//  Return (BOOL):
//
//  History:
//      06/15/93    cjp     [curtisp]
//
//--------------------------------------------------------------------------;

STATIC BOOL  ControlConfigureDriver
(
    HWND                    hwnd,
    LPACMDRIVERSETTINGS     pads
)
{
    if (NULL == pads)
    {
        return (FALSE);
    }

    if (acmDriverMessage((HACMDRIVER)pads->hadid,DRV_CONFIGURE,(LPARAM)hwnd,0L) == DRVCNF_RESTART)
    {
        DisplayMessage(hwnd, IDS_CHANGESAVED, IDS_RESTART, MB_OK);
    }

    return (TRUE);
} // ControlConfigureDriver()




STATIC void CommitCodecChanges(LPACMDRIVERSETTINGS pads)
{
    MMRESULT            mmr;
    BOOL                fDisabled;
    DWORD               fdwPriority;

    mmr = (MMRESULT)acmDriverPriority(NULL, 0L, ACM_DRIVERPRIORITYF_BEGIN);
    if (MMSYSERR_NOERROR != mmr)
    {
        DPF(0, "!ControlApplySettings: acmDriverPriority(end) failed! mmr=%u", mmr);
        return;
    }

    fDisabled = (0 != (ACMDRIVERDETAILS_SUPPORTF_DISABLED & pads->fdwSupport));

    fdwPriority = fDisabled ? ACM_DRIVERPRIORITYF_DISABLE : ACM_DRIVERPRIORITYF_ENABLE;

    mmr = (MMRESULT)acmDriverPriority(pads->hadid, pads->dwPriority, fdwPriority);
    if (MMSYSERR_NOERROR != mmr)
    {
        DPF(0, "!ControlApplySettings: acmDriverPriority(%.04Xh, %lu, %.08lXh) failed! mmr=%u",
        pads->hadid, pads->dwPriority, fdwPriority, mmr);
    }

    mmr = (MMRESULT)acmDriverPriority(NULL, 0L, ACM_DRIVERPRIORITYF_END);
}


const static DWORD aACMDlgHelpIds[] = {  // Context Help IDs
    ID_DEV_SETTINGS,              IDH_MMCPL_DEVPROP_SETTINGS,
    IDD_CPL_BTN_ABOUT,            IDH_MMCPL_DEVPROP_ABOUT,
    IDC_ENABLE,                   IDH_MMCPL_DEVPROP_ENABLE,
    IDC_DISABLE,                  IDH_MMCPL_DEVPROP_DISABLE,
    IDC_DEV_ICON,                 NO_HELP,
    IDC_DEV_DESC,                 NO_HELP,
    IDC_DEV_STATUS,               NO_HELP,
    IDD_PRIORITY_TXT_FROMTO,      IDH_MMCPL_DEVPROP_CHANGE_PRI,
    IDD_PRIORITY_COMBO_PRIORITY,  IDH_MMCPL_DEVPROP_CHANGE_PRI,

    0, 0
};

INT_PTR CALLBACK ACMDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    NMHDR FAR   *lpnm;
    static PCPLCODECINFO pci = NULL;

    switch (uMsg)
    {
        case WM_NOTIFY:
        {
            lpnm = (NMHDR FAR *)lParam;

            switch(lpnm->code)
            {
                case PSN_KILLACTIVE:
                    FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
                break;

                case PSN_APPLY:
                    FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
                break;

                case PSN_SETACTIVE:
                    //FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
                break;

                case PSN_RESET:
                    FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
                break;
            }
        }
        break;

        case WM_INITDIALOG:
        {
            HWND hwndS = GetDlgItem(hDlg, IDC_DEV_STATUS);
            LPARAM lpUser = ((LPPROPSHEETPAGE)lParam)->lParam;

            if ((pci = acmFindCodecInfo (LOWORD(lpUser), HIWORD(lpUser))) == NULL)
            {
                FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
                break;
            }

            acmMetrics((HACMOBJ)pci->ads.hadid, ACM_METRIC_DRIVER_PRIORITY, &(pci->ads.dwPriority));
            acmMetrics((HACMOBJ)pci->ads.hadid, ACM_METRIC_DRIVER_SUPPORT, &(pci->ads.fdwSupport));


            SendDlgItemMessage(hDlg, IDC_DEV_ICON, STM_SETICON, (WPARAM)pci->hIcon, 0L);

            SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pci);
            SetWindowText(GetDlgItem(hDlg, IDC_DEV_DESC), pci->szDesc);

            LoadString (ghInstance, IDS_DEVENABLEDOK, gszDevEnabled, sizeof(gszDevEnabled)/sizeof(TCHAR));
            LoadString (ghInstance, IDS_DEVDISABLED, gszDevDisabled, sizeof(gszDevDisabled)/sizeof(TCHAR));

            if(pci->ads.fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)
            {
                SetWindowText(hwndS, gszDevDisabled);
                CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_DISABLE);
            }
            else
            {
                SetWindowText(hwndS, gszDevEnabled);
                CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_ENABLE);
            }

            EnableWindow(GetDlgItem(hDlg, ID_DEV_SETTINGS), (MMRESULT)acmDriverMessage((HACMDRIVER)pci->ads.hadid,DRV_QUERYCONFIGURE,0,0));

            FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
        }
        break;

        case WM_DESTROY:
        {
            FORWARD_WM_COMMAND(hDlg, ID_REBUILD, 0, 0, SendMessage);

            if (pci != NULL)
            {
                acmFreeCodecInfo (pci);
                pci = NULL;
            }
        }
        break;

        case WM_CONTEXTMENU:
        {
            WinHelp ((HWND) wParam, NULL, HELP_CONTEXTMENU, (UINT_PTR) (LPTSTR) aACMDlgHelpIds);
            return TRUE;
        }
        break;

        case WM_HELP:
        {
            LPHELPINFO lphi = (LPVOID) lParam;
            WinHelp (lphi->hItemHandle, NULL, HELP_WM_HELP, (UINT_PTR) (LPTSTR) aACMDlgHelpIds);
            return TRUE;
        }
        break;

        case WM_COMMAND:
        {
            HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoACMPropCommand);
        }
        break;
    }
    return FALSE;
}


BOOL PASCAL DoACMPropCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
{
    PCPLCODECINFO           pci;
    LPACMDRIVERSETTINGS     pads;
    static int              iPriority = 0;
    static BOOL             fDisabled = TRUE;
    static BOOL             fRebuild;
    HWND hwndS =            GetDlgItem(hDlg, IDC_DEV_STATUS);

    if ((pci = (PCPLCODECINFO)GetWindowLongPtr(hDlg,DWLP_USER)) == NULL)
    {
        return FALSE;
    }

    pads = &(pci->ads);

    switch (id)
    {
        case ID_APPLY:
        {
            HWND hcb = GetDlgItem(hDlg, IDD_PRIORITY_COMBO_PRIORITY);
            if ((fDisabled != Button_GetCheck(GetDlgItem(hDlg, IDC_DISABLE))) || (iPriority != ComboBox_GetCurSel(hcb)+1))
            {
                pads->fdwSupport ^= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
                fDisabled = (0 != (pads->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED));
                iPriority = pads->dwPriority  = ComboBox_GetCurSel(hcb)+1;
                CommitCodecChanges(pads);
                fRebuild = TRUE;
            }
            return TRUE;
        }

        case ID_REBUILD:
        {
            if (fRebuild && pci)
            {
                SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)0);
                fRebuild = FALSE;
            }
        }
        break;

        case ID_INIT:
        {
            TCHAR achFromTo[80];
            TCHAR ach[80];
            HWND hcb;
            UINT u;
            UINT nCodecs;

            iPriority = (int)pads->dwPriority;
            fDisabled = (0 != (pads->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED));
            fRebuild = FALSE;

            LoadString(ghInstance, IDS_PRIORITY_FROMTO, achFromTo, sizeof(achFromTo)/sizeof(TCHAR));

            wsprintf(ach, achFromTo, iPriority);
            SetDlgItemText(hDlg, IDD_PRIORITY_TXT_FROMTO, ach);

            hcb = GetDlgItem(hDlg, IDD_PRIORITY_COMBO_PRIORITY);

            nCodecs = acmCountCodecs();

            for (u = 1; u <= (UINT)nCodecs; u++)
            {
                wsprintf(ach, aszFormatNumber, (DWORD)u);
                ComboBox_AddString(hcb, ach);
            }

            ComboBox_SetCurSel(hcb, iPriority - 1);
        }
        break;

        case IDD_PRIORITY_COMBO_PRIORITY:
        {
            switch (codeNotify)
            {
                case CBN_SELCHANGE:
                {
                    PropSheet_Changed(GetParent(hDlg),hDlg);
                }
                break;
            }
        }
        break;


        case IDC_ENABLE:
        {
            SetWindowText(hwndS, gszDevEnabled);
            CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_ENABLE);
            PropSheet_Changed(GetParent(hDlg),hDlg);
        }
        break;

        case IDC_DISABLE:
        {
            SetWindowText(hwndS, gszDevDisabled);
            CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_DISABLE);
            PropSheet_Changed(GetParent(hDlg),hDlg);
        }
        break;

        case ID_DEV_SETTINGS:
        {
            ControlConfigureDriver(hDlg, pads);
        }
        break;

        case IDD_CPL_BTN_ABOUT:
        {
            ControlAboutDriver(hDlg, pads);
        }
        break;
    }

    return FALSE;
}



///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////////
// Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
///////////////////////////////////////////////////////////////////////////////////////////
DWORD GetWaveOutID(BOOL *pfPreferred)
{
    MMRESULT        mmr;
    DWORD_PTR       dwWaveID = 0;
    DWORD           dwFlags = 0;

    if (pfPreferred)
    {
        *pfPreferred = TRUE;
    }

    mmr = waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);

    if (!mmr && pfPreferred)
    {
        *pfPreferred = dwFlags & 0x00000001;
    }

    return(DWORD)(dwWaveID);
}

///////////////////////////////////////////////////////////////////////////////////////////
// Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
///////////////////////////////////////////////////////////////////////////////////////////
void SetWaveOutID(DWORD dwWaveID, BOOL fPrefOnly)
{
    MMRESULT    mmr;
    DWORD       dwParam1, dwParam2;
    DWORD       dwFlags = fPrefOnly ? 0x00000001 : 0x00000000;

    mmr = waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_PREFERRED_SET, dwWaveID, dwFlags);
}



///////////////////////////////////////////////////////////////////////////////////////////
// Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
///////////////////////////////////////////////////////////////////////////////////////////
DWORD GetWaveInID(BOOL *pfPreferred)
{
    MMRESULT        mmr;
    DWORD_PTR       dwWaveID = 0;
    DWORD           dwFlags = 0;

    if (pfPreferred)
    {
        *pfPreferred = TRUE;
    }

    mmr = waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);

    if (!mmr && pfPreferred)
    {
        *pfPreferred = dwFlags & 0x00000001;
    }

    return(DWORD)(dwWaveID);
}


///////////////////////////////////////////////////////////////////////////////////////////
// Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
///////////////////////////////////////////////////////////////////////////////////////////
void SetWaveInID(DWORD dwWaveID, BOOL fPrefOnly)
{
    MMRESULT    mmr;
    DWORD       dwParam1, dwParam2;
    DWORD       dwFlags = fPrefOnly ? 0x00000001 : 0x00000000;

    mmr = waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_PREFERRED_SET, dwWaveID, dwFlags);
}


///////////////////////////////////////////////////////////////////////////////////////////
// Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
///////////////////////////////////////////////////////////////////////////////////////////
DWORD GetMIDIOutID(void)
{
    MMRESULT        mmr;
    DWORD           dwWaveID;
    DWORD           dwFlags = 0;

    mmr = midiOutMessage(HMIDIOUT_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);

    return(dwWaveID);
}


///////////////////////////////////////////////////////////////////////////////////////////
// Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
///////////////////////////////////////////////////////////////////////////////////////////
void SetMIDIOutID(DWORD dwWaveID)
{
    MMRESULT    mmr;
    DWORD       dwParam1, dwParam2;

    mmr = midiOutMessage(HMIDIOUT_MAPPER, DRVM_MAPPER_PREFERRED_SET, dwWaveID, 0);
}




void GetPrefInfo(PAUDIODLGINFO pai, HWND hDlg )
{
    MMRESULT        mmr;

    // Load WaveOut Info
	pai->cNumOutDevs = waveOutGetNumDevs();
    pai->uPrefOut = GetWaveOutID(&pai->fPrefOnly);


    // Load WaveIn Info
    pai->cNumInDevs  = waveInGetNumDevs();
    pai->uPrefIn = GetWaveInID(NULL);


    // Load MIDI Out info
    pai->cNumMIDIOutDevs  = midiOutGetNumDevs();
    pai->uPrefMIDIOut = GetMIDIOutID();
}



STATIC void EnablePlayVolCtrls(HWND hDlg, BOOL fEnable)
{
    EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_SNDVOL) , fEnable);
    EnableWindow( GetDlgItem(hDlg, IDC_PLAYBACK_ADVSETUP) , fEnable);
}

STATIC void EnableRecVolCtrls(HWND hDlg, BOOL fEnable, BOOL fControl)
{
    EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_RECVOL) , fEnable);
    EnableWindow( GetDlgItem(hDlg, IDC_RECORD_ADVSETUP) , fControl);
}


STATIC void EnableMIDIVolCtrls(HWND hDlg, BOOL fEnable)
{
    EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_MUSICVOL) , fEnable);
}


STATIC void SetDeviceOut(PAUDIODLGINFO pai, UINT uID, HWND hDlg)
{
    BOOL    fEnabled = FALSE;
    HMIXER  hMixer = NULL;
    UINT    uMixID;

    pai->uPrefOut = uID;     // New device, lets setup buttons for this device

    if(MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(pai->uPrefOut), &uMixID, MIXER_OBJECTF_WAVEOUT))
    {
        if(MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))
        {
            fEnabled = TRUE;
            mixerClose(hMixer);
        }
	}

	EnablePlayVolCtrls(hDlg, fEnabled);
}



DWORD CountInputs(DWORD dwMixID)
{
    MIXERCAPS   mc;
    MMRESULT    mmr;
    DWORD dwCount = 0;

    mmr = mixerGetDevCaps(dwMixID, &mc, sizeof(mc));

    if (mmr == MMSYSERR_NOERROR)
    {
        MIXERLINE   mlDst;
        DWORD       dwDestination;
        DWORD       cDestinations;

        cDestinations = mc.cDestinations;

        for (dwDestination = 0; dwDestination < cDestinations; dwDestination++)
        {
            mlDst.cbStruct = sizeof ( mlDst );
            mlDst.dwDestination = dwDestination;

            if (mixerGetLineInfo(HMIXEROBJ_INDEX(dwMixID), &mlDst, MIXER_GETLINEINFOF_DESTINATION  ) == MMSYSERR_NOERROR)
            {
                if (mlDst.dwComponentType == (DWORD)MIXERLINE_COMPONENTTYPE_DST_WAVEIN ||    // needs to be a likely output destination
                    mlDst.dwComponentType == (DWORD)MIXERLINE_COMPONENTTYPE_DST_VOICEIN)
                {
                    DWORD cConnections = mlDst.cConnections;

                    dwCount += mlDst.cControls;

                    if (cConnections)
                    {
                        DWORD dwSource;

                        for (dwSource = 0; dwSource < cConnections; dwSource++)
                        {
                            mlDst.dwDestination = dwDestination;
                            mlDst.dwSource = dwSource;

                            if (mixerGetLineInfo(HMIXEROBJ_INDEX(dwMixID), &mlDst, MIXER_GETLINEINFOF_SOURCE ) == MMSYSERR_NOERROR)
                            {
                                dwCount += mlDst.cControls;
                            }
                        }
                    }
                }
            }
        }
    }

    return(dwCount);
}


STATIC void SetDeviceIn(PAUDIODLGINFO pai, UINT uID, HWND hDlg)
{
    BOOL    fEnabled = FALSE;
    BOOL    fControl = FALSE;
    HMIXER  hMixer = NULL;
    UINT    uMixID;

    pai->uPrefIn = uID;     // New device, lets setup buttons for this device

    if( (MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(pai->uPrefIn),&uMixID, MIXER_OBJECTF_WAVEIN)))
    {
        if( MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))  
        {
            if (CountInputs(uMixID))
            {
		        fEnabled = TRUE;

                // If the capture device is not GFX capable, then there are no tabs to display
                fControl = GFXUI_CheckDevice(uMixID, GFXTYPE_CAPTURE);
            }

            mixerClose(hMixer);
        }
    }

    EnableRecVolCtrls(hDlg, fEnabled, fControl);
}


STATIC void SetMIDIDeviceOut(PAUDIODLGINFO pai, UINT uID, HWND hDlg)
{
    BOOL        fEnabled = FALSE;
    HMIXER      hMixer = NULL;
    UINT        uMixID;
    MIDIOUTCAPS moc;
    MMRESULT    mmr;
    UINT        mid;

    pai->uPrefMIDIOut = uID;     // New device, lets setup buttons for this device

    if(MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(pai->uPrefMIDIOut), &uMixID, MIXER_OBJECTF_MIDIOUT))
    {
        if(MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))
        {
            fEnabled = TRUE;
            mixerClose(hMixer);
        }
    }

    EnableMIDIVolCtrls(hDlg, fEnabled);

    fEnabled = FALSE;
    mmr = midiOutGetDevCaps(pai->uPrefMIDIOut, &moc, sizeof(moc));

    if (MMSYSERR_NOERROR == mmr)
    {
        if ((moc.wMid == MM_MICROSOFT) && (moc.wPid == MM_MSFT_WDMAUDIO_MIDIOUT) && (moc.wTechnology == MOD_SWSYNTH))
        {
            fEnabled = TRUE;
        }
    }

    EnableWindow( GetDlgItem(hDlg, IDC_MUSIC_ABOUT) , fEnabled);
}


STDAPI_(void) DoRolandAbout(HWND hWnd)
{
    UINT uWaveID = 0;

    if (GetWaveID(&uWaveID) != (MMRESULT)MMSYSERR_ERROR)
    {
        WAVEOUTCAPS woc;

        if (waveOutGetDevCaps(uWaveID, &woc, sizeof(woc)) == MMSYSERR_NOERROR)
        {
            RolandProp(hWnd, ghInstance, woc.szPname);
        }
    }
}


STATIC void SetPrefInfo(PAUDIODLGINFO pai, HWND hDlg )
{
    HWND    hwndCBPlay   = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
    HWND    hwndCBRec    = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
    HWND    hwndCBMIDI   = GetDlgItem(hDlg, IDC_MUSIC_CB_PLAY);
    HKEY    hkeyAcm;
    UINT    item, deviceID;
    TCHAR   szPref[MAXSTR];

    pai->fPrefOnly = Button_GetCheck(GetDlgItem(hDlg, IDC_AUDIO_PREF));

    item = (UINT)ComboBox_GetCurSel(hwndCBPlay);

    if (item != CB_ERR)
    {
        deviceID = (UINT)ComboBox_GetItemData(hwndCBPlay, item);

        if(deviceID != pai->uPrefOut)             // Make sure device changed
        {
            SetDeviceOut(pai, deviceID, hDlg);    // Configure controls for this device
        }
    }

    item = (UINT)ComboBox_GetCurSel(hwndCBRec);

    if (item != CB_ERR)
    {
        deviceID = (UINT)ComboBox_GetItemData(hwndCBRec, item);

        if( deviceID != pai->uPrefIn )            // Make sure device changed
        {
            SetDeviceIn(pai, deviceID, hDlg);     // Configure controls for this device
        }
    }

    item = (UINT)ComboBox_GetCurSel(hwndCBMIDI);

    if (item != CB_ERR)
    {
        deviceID = (UINT)ComboBox_GetItemData(hwndCBMIDI, item);

        if(deviceID != pai->uPrefMIDIOut)         // Make sure device changed
        {
            SetMIDIDeviceOut(pai, deviceID, hDlg);    // Configure controls for this device
        }
    }

    SetWaveOutID(pai->uPrefOut, pai->fPrefOnly);
    SetWaveInID(pai->uPrefIn, pai->fPrefOnly);
    SetMIDIOutID(pai->uPrefMIDIOut);

    WAVEOUTInit(hDlg, pai);
    WAVEINInit(hDlg, pai);

    //  MIDI Devices are not remapped...
}



STATIC void MSACM_NotifyMapper(void)
{
    waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, DRV_F_NEWDEFAULTS);
    waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, DRV_F_NEWDEFAULTS);
    midiOutMessage(HMIDIOUT_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, DRV_F_NEWDEFAULTS);
}



STATIC void WAVEOUTInit(HWND hDlg, PAUDIODLGINFO pai)
{
    HWND        hwndCBPlay = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
    MMRESULT    mr;
    UINT        device;
    TCHAR       szNoAudio[128];

    szNoAudio[0] = TEXT('\0');

    ComboBox_ResetContent(hwndCBPlay);

    if (pai->cNumOutDevs == 0)
    {
        LoadString (ghInstance, IDS_NOAUDIOPLAY, szNoAudio, sizeof(szNoAudio)/sizeof(TCHAR));
        ComboBox_AddString(hwndCBPlay, szNoAudio);
        ComboBox_SetItemData(hwndCBPlay, 0, (LPARAM)-1);
        ComboBox_SetCurSel(hwndCBPlay, 0);
        EnableWindow( hwndCBPlay, FALSE );
        EnablePlayVolCtrls(hDlg, FALSE);
	}
    else
    {
        EnableWindow( hwndCBPlay, TRUE );

        for (device = 0; device < pai->cNumOutDevs; device++)
        {
            WAVEOUTCAPS     woc;
            int newItem;

            woc.szPname[0]  = TEXT('\0');

            if (waveOutGetDevCapsW(device, &woc, sizeof(woc)))
            {
                continue;
            }

            woc.szPname[sizeof(woc.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');

            newItem = ComboBox_AddString(hwndCBPlay, woc.szPname);

            if (newItem != CB_ERR && newItem != CB_ERRSPACE)
            {
                ComboBox_SetItemData(hwndCBPlay, newItem, (LPARAM)device);

                if (device == pai->uPrefOut)
                {
                    ComboBox_SetCurSel(hwndCBPlay, newItem);
                    SetDeviceOut(pai, device, hDlg);
                }
            }
        }
    }
}

STATIC void WAVEINInit(HWND hDlg, PAUDIODLGINFO pai)
{
    HWND        hwndCBRec = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
    MMRESULT    mr;
    UINT        device;
    TCHAR       szNoAudio[128];

    ComboBox_ResetContent(hwndCBRec);

    if (pai->cNumInDevs == 0)
    {
        LoadString (ghInstance, IDS_NOAUDIOREC, szNoAudio, sizeof(szNoAudio)/sizeof(TCHAR));
        ComboBox_AddString(hwndCBRec, szNoAudio);
        ComboBox_SetItemData(hwndCBRec, 0, (LPARAM)-1);
        ComboBox_SetCurSel(hwndCBRec, 0);
        EnableWindow( hwndCBRec, FALSE );
        EnableRecVolCtrls(hDlg, FALSE, FALSE);
    }
    else
    {
        EnableWindow( hwndCBRec, TRUE );

        for (device = 0; device < pai->cNumInDevs; device++)
        {
            WAVEINCAPSW     wic;
            int newItem;

            wic.szPname[0]  = TEXT('\0');

            if (waveInGetDevCapsW(device, &wic, sizeof(wic)))
            {
                continue;
            }

            wic.szPname[sizeof(wic.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');

            newItem = ComboBox_AddString(hwndCBRec, wic.szPname);

            if (newItem != CB_ERR && newItem != CB_ERRSPACE)
            {
                ComboBox_SetItemData(hwndCBRec, newItem, (LPARAM)device);

                if (device == pai->uPrefIn)
                {
                    ComboBox_SetCurSel(hwndCBRec, newItem);
                    SetDeviceIn(pai, device, hDlg);
                }
            }
        }
    }
}


STATIC void MIDIInit(HWND hDlg, PAUDIODLGINFO pai)
{
    HWND        hwnd  = GetDlgItem(hDlg, IDC_MUSIC_CB_PLAY);
    MMRESULT    mr;
    UINT        device;
    TCHAR       szNoAudio[128];

    ComboBox_ResetContent(hwnd);

    szNoAudio[0] = TEXT('\0');

    EnableWindow( GetDlgItem(hDlg, IDC_MUSIC_ABOUT) , FALSE);

    if (pai->cNumMIDIOutDevs == 0)
    {
        LoadString (ghInstance, IDS_NOMIDIPLAY, szNoAudio, sizeof(szNoAudio)/sizeof(TCHAR));
        ComboBox_AddString(hwnd, szNoAudio);
        ComboBox_SetItemData(hwnd, 0, (LPARAM)-1);
        ComboBox_SetCurSel(hwnd, 0);
        EnableWindow( hwnd, FALSE );
        EnableMIDIVolCtrls(hDlg, FALSE);
    }
    else
    {
        EnableWindow( hwnd, TRUE );
        for (device = 0; device < pai->cNumMIDIOutDevs; device++)
        {
            MIDIOUTCAPS moc;
            int newItem;

            moc.szPname[0]  = TEXT('\0');

            if (midiOutGetDevCapsW(device, &moc, sizeof(moc)))
            {
                continue;
            }

            moc.szPname[sizeof(moc.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');

            newItem = ComboBox_AddString(hwnd, moc.szPname);

            if (newItem != CB_ERR && newItem != CB_ERRSPACE)
            {
                ComboBox_SetItemData(hwnd, newItem, (LPARAM)device);

                if (device == pai->uPrefMIDIOut)
                {
                    ComboBox_SetCurSel(hwnd, newItem);
                    SetMIDIDeviceOut(pai, device, hDlg);
                }
            }
        }
    }
}



STATIC void AudioDlgInit(HWND hDlg)
{
    PAUDIODLGINFO pai = (PAUDIODLGINFO)LocalAlloc(LPTR, sizeof(AUDIODLGINFO));

	if (!pai) return;

    //
    //  Register context-sensitive help messages from the Customize dialog.
    //
    guCustomizeContextMenu = RegisterWindowMessage( ACMHELPMSGCONTEXTMENU );
    guCustomizeContextHelp = RegisterWindowMessage( ACMHELPMSGCONTEXTHELP );

    SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pai);

    GetPrefInfo(pai, hDlg);
    CheckDlgButton(hDlg, IDC_AUDIO_PREF, pai->fPrefOnly);

    WAVEOUTInit(hDlg, pai);
    WAVEINInit(hDlg, pai);
    MIDIInit(hDlg, pai);

    if (!(pai->cNumInDevs || pai->cNumOutDevs || pai->cNumMIDIOutDevs))
    {
        CheckDlgButton(hDlg, IDC_AUDIO_PREF, FALSE);
        EnableWindow(GetDlgItem(hDlg, IDC_AUDIO_PREF), FALSE);
    }

}


const static DWORD aAudioHelpIds[] = {  // Context Help IDs
    IDC_GROUPBOX,            IDH_COMM_GROUPBOX,
    IDI_SPEAKERICON,         IDH_COMM_GROUPBOX,
    IDC_ICON_6,              IDH_COMM_GROUPBOX,
    IDC_TEXT_4,              IDH_AUDIO_PLAY_PREFER_DEV,
    IDC_AUDIO_CB_PLAY,       IDH_AUDIO_PLAY_PREFER_DEV,
    IDC_LAUNCH_SNDVOL,       IDH_AUDIO_PLAY_VOL,
    IDC_PLAYBACK_ADVSETUP,   IDH_ADV_AUDIO_PLAY_PROP,

    IDC_GROUPBOX_2,          IDH_COMM_GROUPBOX,
    IDI_RECORDICON,          IDH_COMM_GROUPBOX,
    IDC_ICON_7,              IDH_COMM_GROUPBOX,
    IDC_TEXT_8,              IDH_AUDIO_REC_PREFER_DEV,
    IDC_AUDIO_CB_REC,        IDH_AUDIO_REC_PREFER_DEV,
    IDC_LAUNCH_RECVOL,       IDH_AUDIO_REC_VOL,
    IDC_RECORD_ADVSETUP,     IDH_ADV_AUDIO_REC_PROP,

    IDC_GROUPBOX_3,          IDH_COMM_GROUPBOX,
    IDI_MUSICICON,           IDH_COMM_GROUPBOX,
    IDC_ICON_8,              IDH_COMM_GROUPBOX,
    IDC_TEXT_9,              IDH_MIDI_SINGLE_INST_BUTTON,
    IDC_MUSIC_CB_PLAY,       IDH_MIDI_SINGLE_INST_BUTTON,
    IDC_LAUNCH_MUSICVOL,     IDH_AUDIO_MIDI_VOL,
    IDC_MUSIC_ABOUT,         IDH_ABOUT,

    IDC_AUDIO_PREF,          IDH_AUDIO_USE_PREF_ONLY,

    0, 0
};

const static DWORD aCustomizeHelpIds[] = {
    IDD_ACMFORMATCHOOSE_CMB_FORMAT,     IDH_AUDIO_CUST_ATTRIB,
    IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,  IDH_AUDIO_CUST_FORMAT,
    IDD_ACMFORMATCHOOSE_CMB_CUSTOM,     IDH_AUDIO_CUST_NAME,
    IDD_ACMFORMATCHOOSE_BTN_DELNAME,    IDH_AUDIO_CUST_REMOVE,
    IDD_ACMFORMATCHOOSE_BTN_SETNAME,    IDH_AUDIO_CUST_SAVEAS,

    0, 0
};



void WinMMDeviceChange(HWND hDlg)
{
    PAUDIODLGINFO pai = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);

//    MSACM_NotifyMapper();

    GetPrefInfo(pai, hDlg);
    CheckDlgButton(hDlg, IDC_AUDIO_PREF, pai->fPrefOnly);

    WAVEOUTInit(hDlg, pai);
    WAVEINInit(hDlg, pai);
    MIDIInit(hDlg, pai);

    if (!(pai->cNumInDevs || pai->cNumOutDevs || pai->cNumMIDIOutDevs))
    {
        CheckDlgButton(hDlg, IDC_AUDIO_PREF, FALSE);
        EnableWindow(GetDlgItem(hDlg, IDC_AUDIO_PREF), FALSE);
    }
}



LRESULT CALLBACK AudioTabProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    if (iMsg == giDevChange)
    {
        WinMMDeviceChange(ghDlg);
    }

    return CallWindowProc(gfnPSProc,hwnd,iMsg,wParam,lParam);
}


void InitDeviceChange(HWND hDlg)
{
    gfnPSProc = (WNDPROC) SetWindowLongPtr(GetParent(hDlg),GWLP_WNDPROC,(LONG_PTR)AudioTabProc);
    giDevChange = RegisterWindowMessage(TEXT("winmm_devicechange"));
}

void UninitDeviceChange(HWND hDlg)
{
    SetWindowLongPtr(GetParent(hDlg),GWLP_WNDPROC,(LONG_PTR)gfnPSProc);
}




BOOL CALLBACK AudioDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
                                LPARAM lParam)
{
    NMHDR FAR   *lpnm;
    PAUDIODLGINFO pai;

    switch (uMsg)
    {
        case WM_NOTIFY:
        {
            lpnm = (NMHDR FAR *)lParam;
            switch(lpnm->code)
            {
                case PSN_KILLACTIVE:
                    FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
                break;

                case PSN_APPLY:
                    FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
                break;

                case PSN_SETACTIVE:
                    FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
                break;

                case PSN_RESET:
                    FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
                break;
            }
        }
        break;

        case WM_INITDIALOG:
        {
            ghDlg = hDlg;

            InitDeviceChange(hDlg);

            if (!gfLoadedACM)
            {
                if (LoadACM())
                {
                    gfLoadedACM = TRUE;
                }
                else
                {
                    DPF("****Load ACM failed**\r\n");
                    ASSERT(FALSE);
                    ErrorBox(hDlg, IDS_CANTLOADACM, NULL);
                    ExitThread(0);
                }
            }

            AudioDlgInit(hDlg);
        }
        break;

        case WM_DESTROY:
        {
            UninitDeviceChange(hDlg);

            pai = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);

            LocalFree((HLOCAL)pai);

            if (gfLoadedACM)
            {
                if (!FreeACM())
                {
                    DPF("****Free ACM failed**\r\n");
                    ASSERT(FALSE);
                }

                gfLoadedACM = FALSE;
            }
        }
        break;

        case WM_CONTEXTMENU:
        {
            WinHelp ((HWND) wParam, NULL, HELP_CONTEXTMENU, (UINT_PTR) (LPTSTR) aAudioHelpIds);
            return TRUE;
        }
        break;

        case WM_HELP:
        {
            LPHELPINFO lphi = (LPVOID) lParam;
            WinHelp (lphi->hItemHandle, NULL, HELP_WM_HELP, (UINT_PTR) (LPTSTR) aAudioHelpIds);
            return TRUE;
        }
        break;

        case WM_COMMAND:
        {
            HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoAudioCommand);
        }
        break;

        default:
        {
            //
            //  Handle context-sensitive help messages from Customize dlg.
            //
            if( uMsg == guCustomizeContextMenu )
            {
                WinHelp( (HWND)wParam, NULL, HELP_CONTEXTMENU, (UINT_PTR)(LPTSTR)aCustomizeHelpIds );
            }
            else if( uMsg == guCustomizeContextHelp )
            {
                WinHelp( ((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (UINT_PTR)(LPTSTR)aCustomizeHelpIds);
            }
        }
        break;
    }
    return FALSE;
}

void ErrorMsgBox(HWND hDlg, UINT uTitle, UINT uMessage)
{
    TCHAR szMsg[MAXSTR];
    TCHAR szTitle[MAXSTR];

    LoadString(ghInstance, IDS_ERROR_TITLE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
    LoadString(ghInstance, IDS_ERROR_NOSNDVOL, szMsg, sizeof(szMsg)/sizeof(TCHAR));
    MessageBox(hDlg, szMsg,szTitle,MB_OK);
}


void LaunchPlaybackVolume(HWND hDlg)
{
    HWND    hwndCBPlay  = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
    UINT    item;

    item = (UINT)ComboBox_GetCurSel(hwndCBPlay);

    if (item != CB_ERR)
    {
        TCHAR szCmd[MAXSTR];
        UINT uDeviceID;
        MMRESULT mmr;

        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        memset(&si, 0, sizeof(si));
        si.cb = sizeof(si);
        si.wShowWindow = SW_SHOW;
        si.dwFlags = STARTF_USESHOWWINDOW;

        uDeviceID = (UINT)ComboBox_GetItemData(hwndCBPlay, item);
        mmr = mixerGetID(HMIXEROBJ_INDEX(uDeviceID), &uDeviceID, MIXER_OBJECTF_WAVEOUT);

        if (mmr == MMSYSERR_NOERROR)
        {
            wsprintf(szCmd,TEXT("sndvol32.exe -D %d"),uDeviceID);

            if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
            {
                ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOSNDVOL);
            }
        }
        else
        {
            ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOMIXER);
        }
    }
}


void LaunchRecordVolume(HWND hDlg)
{
    HWND    hwndCBRec  = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
    UINT    item;

    item = (UINT)ComboBox_GetCurSel(hwndCBRec);

    if (item != CB_ERR)
    {
        TCHAR szCmd[MAXSTR];
        UINT uDeviceID;
        MMRESULT mmr;
        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        memset(&si, 0, sizeof(si));
        si.cb = sizeof(si);
        si.wShowWindow = SW_SHOW;
        si.dwFlags = STARTF_USESHOWWINDOW;

        uDeviceID = (UINT)ComboBox_GetItemData(hwndCBRec, item);

        mmr = mixerGetID(HMIXEROBJ_INDEX(uDeviceID), &uDeviceID, MIXER_OBJECTF_WAVEIN);

        if (mmr == MMSYSERR_NOERROR)
        {
            wsprintf(szCmd,TEXT("sndvol32.exe -R -D %d"),uDeviceID);

            if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
            {
                ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOSNDVOL);
            }
        }
        else
        {
            ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOMIXER);
        }
    }
}

void LaunchMIDIVolume(HWND hDlg)
{
    HWND    hwndCBMIDI  = GetDlgItem(hDlg, IDC_MUSIC_CB_PLAY);
    UINT    item;

    item = (UINT)ComboBox_GetCurSel(hwndCBMIDI);

    if (item != CB_ERR)
    {
        TCHAR szCmd[MAXSTR];
        DWORD dwDeviceID;
        MMRESULT mmr;
        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        memset(&si, 0, sizeof(si));
        si.cb = sizeof(si);
        si.wShowWindow = SW_SHOW;
        si.dwFlags = STARTF_USESHOWWINDOW;

        dwDeviceID = (UINT)ComboBox_GetItemData(hwndCBMIDI, item);

        mmr = mixerGetID(HMIXEROBJ_INDEX(dwDeviceID), &dwDeviceID, MIXER_OBJECTF_MIDIOUT);

        if (mmr == MMSYSERR_NOERROR)
        {
            wsprintf(szCmd,TEXT("sndvol32.exe -D %d"),dwDeviceID);

            if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
            {
                ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOSNDVOL);
            }
        }
        else
        {
            ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOMIXER);
        }
    }
}

BOOL PASCAL DoAudioCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
{
    PAUDIODLGINFO pai = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);

    if (!gfLoadedACM)
    {
        return FALSE;
    }

    switch (id)
    {
        case ID_APPLY:
        {
            SetPrefInfo(pai, hDlg);
        }
        break;

        case IDC_AUDIO_CB_PLAY:
        case IDC_AUDIO_CB_REC:
        case IDC_MUSIC_CB_PLAY:
        {
            switch (codeNotify)
            {
                case CBN_SELCHANGE:
                {
                    PropSheet_Changed(GetParent(hDlg),hDlg);

                    if ((id ==  IDC_AUDIO_CB_PLAY) || (id ==  IDC_AUDIO_CB_REC) || id == IDC_MUSIC_CB_PLAY)
                    {
                        int iIndex;
                        AUDIODLGINFO aiTmp;
                        PAUDIODLGINFO paiTmp = &aiTmp;

                        iIndex = ComboBox_GetCurSel(hwndCtl);

                        if (iIndex != CB_ERR)
                        {
                            if (id == IDC_AUDIO_CB_PLAY)
                            {
                                paiTmp->uPrefOut = (UINT)ComboBox_GetItemData(hwndCtl, iIndex);
                                SetDeviceOut(paiTmp, paiTmp->uPrefOut, hDlg);
                            }
                            else if (id == IDC_AUDIO_CB_REC)
                            {
                                paiTmp->uPrefIn = (UINT)ComboBox_GetItemData(hwndCtl, iIndex);
                                SetDeviceIn(paiTmp, paiTmp->uPrefIn, hDlg);
                            }
                            else if (id == IDC_MUSIC_CB_PLAY)
                            {
                                paiTmp->uPrefMIDIOut = (UINT)ComboBox_GetItemData(hwndCtl, iIndex);
                                SetMIDIDeviceOut(paiTmp, paiTmp->uPrefMIDIOut, hDlg);
                            }
                        }
                    }
                }
                break;
            }
        }
        break;


        case IDC_AUDIO_PREF:
        {
            PropSheet_Changed(GetParent(hDlg),hDlg);
        }
        break;

        case IDC_MUSIC_ABOUT:
        {
            DoRolandAbout(hDlg);
        }
        break;

        case IDC_LAUNCH_SNDVOL:
        {
            LaunchPlaybackVolume(hDlg);
        }
        break;

        case IDC_LAUNCH_RECVOL:
        {
            LaunchRecordVolume(hDlg);
        }
        break;

        case IDC_LAUNCH_MUSICVOL:
        {
            LaunchMIDIVolume(hDlg);
        }
        break;

        case IDC_PLAYBACK_ADVSETUP:
        {
            HWND    hwndCBPlay  = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
            DWORD   dwDeviceID;
            UINT    u;
            TCHAR   szPrefOut[MAXSTR];

            u = (UINT)ComboBox_GetCurSel(hwndCBPlay);

            if (u != CB_ERR)
            {
                ComboBox_GetLBText(hwndCBPlay, u, (LPARAM)(LPVOID)szPrefOut);
                dwDeviceID = (DWORD)ComboBox_GetItemData(hwndCBPlay, u);
                AdvancedAudio(hDlg,  ghInstance, gszWindowsHlp, dwDeviceID, szPrefOut, FALSE);
            }
        }
        break;

        case IDC_RECORD_ADVSETUP:
        {
            HWND    hwndCBRec  = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
            DWORD   dwDeviceID;
            UINT    u;
            TCHAR   szPrefIn[MAXSTR];

            u = (UINT)ComboBox_GetCurSel(hwndCBRec);

            if (u != CB_ERR)
            {
                ComboBox_GetLBText(hwndCBRec, u, (LPARAM)(LPVOID)szPrefIn);
                dwDeviceID = (DWORD)ComboBox_GetItemData(hwndCBRec, u);
                AdvancedAudio(hDlg,  ghInstance, gszWindowsHlp, dwDeviceID, szPrefIn, TRUE);
            }
        }
        break;
    }

    return FALSE;
}



BOOL PASCAL CustomizeDialog(HWND hDlg, LPTSTR szNewFormat, DWORD cbSize)
{
    BOOL                fRet = FALSE;  // assume the worse
    ACMFORMATCHOOSE     cwf;
    LRESULT             lr;
    DWORD               dwMaxFormatSize;
    PWAVEFORMATEX       spWaveFormat;
    TCHAR               szCustomize[64];

    lr = acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,(LPVOID)&dwMaxFormatSize);

    if (lr != 0)
    {
        goto CustomizeOut;
    }

    /* This LocalAlloc is freed in WAVE.C: DestroyWave() */
    spWaveFormat = (PWAVEFORMATEX)LocalAlloc(LPTR, (UINT)dwMaxFormatSize);

    _fmemset(&cwf, 0, sizeof(cwf));

     LoadString(ghInstance, IDS_CUSTOMIZE, szCustomize, sizeof(szCustomize)/sizeof(TCHAR));
    cwf.cbStruct    = sizeof(cwf);
    cwf.hwndOwner   = hDlg;
    cwf.fdwStyle    = ACMFORMATCHOOSE_STYLEF_CONTEXTHELP;
    cwf.fdwEnum     = ACM_FORMATENUMF_INPUT;
    cwf.pszTitle    = (LPTSTR)szCustomize;
    cwf.pwfx        = (LPWAVEFORMATEX)spWaveFormat;
    cwf.cbwfx       = dwMaxFormatSize;

    cwf.pszName =     szNewFormat;
    cwf.cchName = cbSize;

    lr = acmFormatChooseW(&cwf);
    if (lr == MMSYSERR_NOERROR)
    {
        fRet = TRUE;
    }
#ifdef DEBUG
    else
    {
        TCHAR a[200];
        wsprintf(a,TEXT("MSACMCPL: acmFormatChoose failed (lr=%u).\n"),lr);
        OutputDebugString(a);
    }
#endif

CustomizeOut:
    return fRet;                // return our result
} /* NewSndDialog() */


///////////////////////////////////////////////////////////////////////////////

void acmFreeCodecInfo (PCPLCODECINFO pcci)
{
    if (pcci->fMadeIcon && pcci->hIcon)
    {
        DestroyIcon (pcci->hIcon);
        pcci->hIcon = NULL;
        pcci->fMadeIcon = FALSE;
    }

   LocalFree ((HANDLE)pcci);
}


typedef struct // FindCodecData
    {
    BOOL              fFound;
    ACMDRIVERDETAILSW add;
    WORD              wMid, wPid;
    HACMDRIVERID      hadid;
    DWORD             fdwSupport;
    } FindCodecData;

PCPLCODECINFO acmFindCodecInfo (WORD wMidMatch, WORD wPidMatch)
{
    MMRESULT      mmr;
    FindCodecData fcd;
    PCPLCODECINFO pcci;

    fcd.fFound = FALSE;
    fcd.wMid = wMidMatch;
    fcd.wPid = wPidMatch;
//  fcd.add is filled in by acmFindCodecCallback during the following enum:

    mmr = (MMRESULT)acmDriverEnum (acmFindCodecInfoCallback,
             (DWORD_PTR)&fcd,   // (data passed as arg2 to callback)
             ACM_DRIVERENUMF_NOLOCAL |
             ACM_DRIVERENUMF_DISABLED);

    if (MMSYSERR_NOERROR != mmr)
    {
        return NULL;
    }

    if (!fcd.fFound)
    {
        return NULL;
    }

     // Congratulations--we found a matching ACM driver.  Now
     // we need to create a CPLCODECINFO structure to describe it,
     // so the rest of the code in this file will work without
     // mods.  <<sigh>>  A CPLCODECINFO structure doesn't have
     // anything special--it's just a place to track info about
     // an ACM driver.  The most important thing is the HACMDRIVERID.
     //
    if ((pcci = (PCPLCODECINFO)LocalAlloc(LPTR, sizeof(CPLCODECINFO))) == NULL)
    {
        return NULL;
    }

    lstrcpy (pcci->szDesc, fcd.add.szLongName);
    pcci->ads.hadid = fcd.hadid;
    pcci->ads.fdwSupport = fcd.fdwSupport;

    pcci->fMadeIcon = FALSE;

    if ((pcci->hIcon = fcd.add.hicon) == NULL)
    {
       int cxIcon, cyIcon;
       cxIcon = (int)GetSystemMetrics (SM_CXICON);
       cyIcon = (int)GetSystemMetrics (SM_CYICON);
       pcci->hIcon = LoadImage (myInstance,
                MAKEINTRESOURCE( IDI_ACM ),
                IMAGE_ICON, cxIcon, cyIcon, LR_DEFAULTCOLOR);
       pcci->fMadeIcon = TRUE;
    }

    acmMetrics ((HACMOBJ)pcci->ads.hadid,
        ACM_METRIC_DRIVER_PRIORITY,
        &(pcci->ads.dwPriority));

    return pcci;
}



BOOL CALLBACK acmFindCodecInfoCallback (HACMDRIVERID hadid,
                    DWORD_PTR dwUser,
                    DWORD fdwSupport)
{
    FindCodecData *pfcd;

        // dwUser is really a pointer to a FindCodecData
        // structure, supplied by the guy who called acmDriverEnum.
        //
    if ((pfcd = (FindCodecData *)dwUser) == NULL)
    {
        return FALSE;
    }

        // No details?  Try the next driver.
        //
    pfcd->add.cbStruct = sizeof(pfcd->add);
    if (acmDriverDetailsW (hadid, &pfcd->add, 0L) != MMSYSERR_NOERROR)
    {
        return TRUE;
    }

        // Great.  Now see if the driver we found matches
        // pfcd->wMid/wPad; if so we're done, else keep searching.
        //
    if ((pfcd->wMid == pfcd->add.wMid) && (pfcd->wPid == pfcd->add.wPid) )
    {
        pfcd->hadid = hadid;
        pfcd->fFound = TRUE;
        pfcd->fdwSupport = fdwSupport;
        return FALSE; // found it! leave pfcd->add intact and leave.
    }

    return TRUE; // not the right driver--keep looking
}


UINT acmCountCodecs (void)
{
    MMRESULT      mmr;
    UINT          nCodecs = 0;

    mmr = (MMRESULT)acmDriverEnum (acmCountCodecsEnum,
             (DWORD_PTR)&nCodecs,
             ACM_DRIVERENUMF_NOLOCAL |
             ACM_DRIVERENUMF_DISABLED);

    if (MMSYSERR_NOERROR != mmr)
    {
        return 0;
    }

    return nCodecs;
}



BOOL CALLBACK acmCountCodecsEnum (HACMDRIVERID hadid,
                  DWORD_PTR dwUser,
                  DWORD fdwSupport)
{
    UINT *pnCodecs;

        // dwUser is really a pointer to a UINT being used to
        // count the number of codecs we encounter.
        //
    if ((pnCodecs = (UINT *)dwUser) == NULL)
    {
        return FALSE;
    }

    ++ (*pnCodecs);

    return TRUE; // keep counting
}

