#include <windows.h>
#include <mmsystem.h>

#include "SNDinc.H"

#if defined(_DLL_COMPILATION_MODE)
#include "snddll.h"
#else
#endif

//#include "sndmixer.h"

//#define GESTION_PAN

#ifndef DISABLE_WAVE

static MIXERCAPS   mixerCapsSample;
static HMIXER      hMixerSample;
static UINT        mixerIdentifierSample;
static UINT        uiNbrMixersSample;
static DWORD       dwNbrAudioLinesSample;

static MIXERLINE   mixerLineSample;
static MIXERLINECONTROLS mixerLineControlsSample;
static MIXERCONTROL    mixerControlSample;
static MIXERCONTROLDETAILS mixerControlDetailsSample;
static MIXERCONTROLDETAILS_UNSIGNED valeurSample;
static BOOL SampleControlAvailable = FALSE;

int SND_fn_iMixerInitSample(HWAVEOUT hWave)
{
	uiNbrMixersSample = mixerGetNumDevs(); //OK
	if (uiNbrMixersSample == 0)
	{
		SND_fn_vDisplayError(E_uwSndMixerNoMixer,"");
		return 1;
	}

	if (hWave != NULL)
	{
		if(mixerGetID((HMIXEROBJ)hWave,&mixerIdentifierSample,MIXER_OBJECTF_HWAVEOUT) !=MMSYSERR_NOERROR)
		{//On prend le premier par defaut
			if(mixerGetID((HMIXEROBJ)0,&mixerIdentifierSample,MIXER_OBJECTF_MIXER) !=MMSYSERR_NOERROR)
			{	
		    SND_fn_vDisplayError(E_uwSndMixerNoMixer,"");
		    return 1;
			}
		}
	}
	else
	{//On prend le premier par defaut
		if(mixerGetID((HMIXEROBJ)0,&mixerIdentifierSample,MIXER_OBJECTF_MIXER) !=MMSYSERR_NOERROR)
		{
		  SND_fn_vDisplayError(E_uwSndMixerNoId,"");
		  return 1;
		}
	}


	if(mixerOpen(&hMixerSample,mixerIdentifierSample,0,0,MIXER_OBJECTF_MIXER/* MIXER_OBJECTF_HWAVEOUT*/) != MMSYSERR_NOERROR)
	{
		SND_fn_vDisplayError(E_uwSndMixerOpen,"");
		return 1;
	}

	if(mixerGetDevCaps((UINT)hMixerSample,&mixerCapsSample,sizeof(MIXERCAPS)) != MMSYSERR_NOERROR)
	{
		SND_fn_vDisplayError(E_uwSndMixerCapacities,"");
		return 1;
	}

	dwNbrAudioLinesSample = mixerCapsSample.cDestinations;


//==================
// MIXERLINE SAMPLE
//==================

	mixerLineSample.cbStruct = sizeof(MIXERLINE);
	mixerLineSample.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
	if (mixerGetLineInfo((HMIXEROBJ)hMixerSample,&mixerLineSample,MIXER_GETLINEINFOF_COMPONENTTYPE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
  {
	  //return MIXER_ERR_GETLINEINFOSAMPLE;
    SampleControlAvailable = FALSE;
  }
  else
  {
	  SampleControlAvailable = TRUE;
  }

//=========================
// MIXERLINECONTROL SAMPLE
//=========================
	mixerLineControlsSample.cbStruct = sizeof(MIXERLINECONTROLS);
	mixerLineControlsSample.dwLineID = mixerLineSample.dwLineID;
	mixerLineControlsSample.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
	mixerLineControlsSample.cControls = 1;
	mixerLineControlsSample.cbmxctrl  = sizeof(MIXERCONTROL);
	mixerLineControlsSample.pamxctrl =(MIXERCONTROL *) &mixerControlSample;
	if(mixerGetLineControls((HMIXEROBJ)hMixerSample,&mixerLineControlsSample,MIXER_GETLINECONTROLSF_ONEBYTYPE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
  {
    //return MIXER_ERR_GETLINECONTROLSSAMPLE;
		SampleControlAvailable = FALSE;
  }
	else
  {
		SampleControlAvailable = TRUE;
	}


//================================
// MIXERLINECONTROLDETAILS SAMPLE
//================================
	mixerControlDetailsSample.cbStruct = sizeof(MIXERCONTROLDETAILS); 
	mixerControlDetailsSample.dwControlID = mixerControlSample.dwControlID;
	mixerControlDetailsSample.cChannels = 1/*mixerLineSample.cChannels*/;
	mixerControlDetailsSample.cMultipleItems = mixerControlSample.cMultipleItems;
	mixerControlDetailsSample.cbDetails =sizeof(MIXERCONTROLDETAILS_UNSIGNED);
	mixerControlDetailsSample.paDetails= &valeurSample; 

	return 0;
}

#endif

DWORD SND_fn_dwGetSampleMax(void)
{
#ifndef DISABLE_WAVE
  return mixerControlSample.Bounds.dwMaximum;
#else
  return 0;
#endif
}
DWORD SND_fn_dwGetSampleMin(void)
{
#ifndef DISABLE_WAVE
  return mixerControlSample.Bounds.dwMinimum; 
#else
  return 0;
#endif
}

//==================================
// Get sample value
//==================================
// retourne la valeur du mixer 
// sample en %
//
//==================================
DWORD SND_fn_dwGetSampleValue(void)
{
#ifndef DISABLE_WAVE
  DWORD inc;
  DWORD result;

  if (SampleControlAvailable)
  {
    inc = (SND_fn_dwGetSampleMax()-SND_fn_dwGetSampleMin())/100;
    
    if(mixerGetControlDetails((HMIXEROBJ)hMixerSample,&mixerControlDetailsSample,MIXER_GETCONTROLDETAILSF_VALUE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
    {
      return 1;
    }

    result = (valeurSample.dwValue - SND_fn_dwGetSampleMin())/inc;

    //snd_assert(result>=0);
    snd_assert(result<=100);

    return result;
  }
  else
#endif
    return 0;
}


//==================================
// Set sample value
// en %
//
//==================================
void SND_fn_vSetSampleValue(DWORD val)
{
#ifndef DISABLE_WAVE
  DWORD inc;

  if (SampleControlAvailable)
  {
  //snd_assert(val>=0);
    snd_assert(val<=100);

    inc = (SND_fn_dwGetSampleMax() - SND_fn_dwGetSampleMin())/100;
    val = (val* inc) + SND_fn_dwGetSampleMin();

    snd_assert(val >= SND_fn_dwGetSampleMin());
    snd_assert(val <= SND_fn_dwGetSampleMax());

    valeurSample.dwValue = val;
 
    if(mixerSetControlDetails((HMIXEROBJ)hMixerSample,&mixerControlDetailsSample,MIXER_SETCONTROLDETAILSF_VALUE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
    {
    //return 1;
    }
  }
#endif
}

BOOL SND_fn_bIsSampleControlAvailable(void)
{
#ifndef DISABLE_WAVE
  return SampleControlAvailable;
#else
  return FALSE;
#endif
}


int SND_fn_iMixerDesInitSample(void)
{         
#ifndef DISABLE_WAVE
  if(mixerClose(hMixerSample) != MMSYSERR_NOERROR)
  {
    SND_fn_vDisplayError(E_uwSndMixerDesinit,"");
    return 1;
  }
#endif
  return 0;
}
