views:

98

answers:

0

Here is my problem: I made a simple mixer class for my own purposes, here it goes:

struct Volume
{
DWORD left;
DWORD right;
};

CMixer::CMixer ()
{
    m_hMixer = 0;
    m_value = 0;
}

CMixer::~CMixer(void)
{
    delete [] m_value;

    if (m_hMixer)
        mixerClose (m_hMixer);
}

bool CMixer::Init( UINT type /*= MAIN*/)
{
    // get number of mixer devices on system
    if (mixerGetNumDevs() == 0)
        return false;


    // open mixer device
    if (mixerOpen (&m_hMixer, MIXER_OBJECTF_MIXER, 0, 0, MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
        return false;


    // get mixer info (like driver version, name...)
    //MIXERCAPS caps;
    //mixerGetDevCaps( (UINT)m_hMixer, &caps, sizeof(MIXERCAPS));


    // get line info (like Volume control and Recording control)
    MIXERLINE line;
    line.cbStruct = sizeof( MIXERLINE );
    line.dwSource = 0;
    line.dwDestination = 0; // usualy 0 = Volume Control, 1 = Recording control (from caps.cDestinations)

    switch (type)
    {
    case MAIN:
        mixerGetLineInfo ((HMIXEROBJ)m_hMixer, &line, MIXER_GETLINEINFOF_DESTINATION);
        break;
    case WAVE:
        mixerGetLineInfo ((HMIXEROBJ)m_hMixer, &line, MIXER_GETLINEINFOF_SOURCE);
        break;
    }


    // get specific control
    MIXERCONTROL mixerControl;
    MIXERLINECONTROLS mixerLineControl;
    mixerLineControl.cbStruct       = sizeof (MIXERLINECONTROLS);
    mixerLineControl.dwLineID       = line.dwLineID;
    mixerLineControl.dwControlType  = MIXERCONTROL_CONTROLTYPE_VOLUME;
    mixerLineControl.cControls      = 1;
    mixerLineControl.cbmxctrl       = sizeof (MIXERCONTROL);
    mixerLineControl.pamxctrl       = &mixerControl;

    if (mixerGetLineControls ((HMIXEROBJ)m_hMixer, &mixerLineControl, MIXER_GETLINECONTROLSF_ONEBYTYPE ) != MMSYSERR_NOERROR )
        return false;


    // prepare struct for getting and setting control value
    m_mixerDetails.cbStruct         = sizeof (MIXERCONTROLDETAILS);
    m_mixerDetails.dwControlID      = mixerControl.dwControlID;
    m_mixerDetails.cMultipleItems   = mixerControl.cMultipleItems;
    m_mixerDetails.cChannels        = line.cChannels;
    m_mixerDetails.cbDetails        = sizeof (MIXERCONTROLDETAILS_UNSIGNED);

    BYTE* value = new BYTE [m_mixerDetails.cbDetails * m_mixerDetails.cChannels];
    m_mixerDetails.paDetails = value;
    m_value = (MIXERCONTROLDETAILS_UNSIGNED *)value;

    return true;
}

bool CMixer::GetValue (Volume &volume)
{
    if( mixerGetControlDetails ((HMIXEROBJ)m_hMixer, &m_mixerDetails, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
        return false;

    volume.left = m_value[LEFT].dwValue;
    volume.right = m_value[RIGHT].dwValue;

    return true;
}

bool CMixer::SetValue (const Volume &volume)
{
    m_value[LEFT].dwValue = volume.left;
    m_value[RIGHT].dwValue = volume.right;

    //if (mixerSetControlDetails ((HMIXEROBJ)m_hMixer, &m_mixerDetails, MIXER_SETCONTROLDETAILSF_VALUE ) != MMSYSERR_NOERROR)
    //  return false;

    if (mixerSetControlDetails ((HMIXEROBJ)m_hMixer, &m_mixerDetails, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE ) != MMSYSERR_NOERROR)
        return false;

    return true;
}

Somewhere in code I will initialize the mixer and get the volume and remember it as a member variable and also set the new volume like this:

Volume m_volumeMain, m_volumeWave;
m_mixerMain.GetValue (m_volumeMain);

Volume volumeMain = {0, m_volumeMain.right}; // setting left channel to zero, while keeping the right channel
m_mixerMain.SetValue (volumeMain);

// set the volume back
m_mixerMain.SetValue (m_volumeMain);

That was the code. Here is the problem. After repeating the last code for couple of times the right channel will became inactive meaning if I use the multimedia keys on my keyboard it will control only left channel. I can get everything to normal if I use main volume slider inside Windows Volume control. Can anyone figure out what could be the problem?