/************************************************
        Managing INI files
************************************************/
#include "SNDinc.h"

#include <windows.h>

#include "sndres.h"
#include "sndspace.h"

#include "sndini.h"

#include "snddll.h"

#include "sndtest.h"

typedef SndBool (*pfnTestFct)(void);

char SND_INI_FILENAME[]="SND_CPA.INI";

//static char C_STRING_DEFAULT[]="Default";
static char C_STRING_NONE[]="None";

static char SECTION_OPTIONS[]="Options";
static char SUPERVISATER_ON_OFF[]="SUPERVISATER_ON_OFF";
static char OPTION_ON[]="ON";

#ifdef _DLL_COMPILATION_MODE
static char OPTION_OFF[]="OFF";
static char SECTION_TESTDLL[]="DLL_Test";
static char SECTION_SXDDLL[]="DLL_Sxd";
static char SECTION_CDDLL[]="DLL_Cd";
static char SECTION_MPEGDLL[]="DLL_MPEG";
static char SECTION_ADPCMDLL[]="DLL_Adpcm";
static char SECTION_RECORDDLL[]="DLL_Record";
static char SOUND_ON_OFF[]="Sound_ON_OFF";
static char MPEG_ON_OFF[]="MPEG_ON_OFF";
static char CD_ON_OFF[]="CD_ON_OFF";
static char WAV_ON_OFF[]="WAV_ON_OFF";
static char ADPCM_ON_OFF[]="ADPCM_ON_OFF";
static char RECORD_ON_OFF[]="RECORD_ON_OFF";
static char DLL_FILE[]="File%x";
static char DLL_TEST[]="Test%x";
static char DLL_DEFAULT[]="Default";
static char DLL_UNCONDITIONNAL[]="Unconditionnal";
static char DLLNAME_FORMAT[]="%s\\%s%c%c%c.dll";
#endif //_DLL_COMPILATION_MODE

static char SXD_DIST_SATUR[]="SXD_DIST_SATUR";
//static char SXD_DIST_FADE[]="SXD_DIST_FADE";
static char SXD_DIST_BACK[]="SXD_DIST_BACK";

static char szDllDirectory[256]=".";


#ifdef NO_ACP_LDBIN
#define TAG_CHARGEMENT 's'
#else
#define TAG_CHARGEMENT 'b'
#endif

//#ifdef _MSC_VER
#define TAG_COMPILATION 'v'
//#else
//#define TAG_COMPILATION 'w'
//#endif

#ifdef _DEBUG
#define TAG_MODE 'd'
#else
#define TAG_MODE 'r'
#endif

//	les options DLLs ON doivent être explicites
#ifdef _DLL_COMPILATION_MODE
//	l'option SOUND ON est implicite
static BOOL bSound_ON=TRUE;
//flag= DLL active ou non
static BOOL bMPEG_ON=FALSE;
static BOOL bCD_ON=FALSE;
static BOOL bWAV_ON=FALSE;
static BOOL bADPCM_ON=FALSE;
static BOOL bRECORD_ON=FALSE;
#endif //_DLL_COMPILATION_MODE
static BOOL bDBG_ON=FALSE;

static char ini_file[256]="";

__declspec(dllexport) BOOL SND_CALL SND_fn_bTestSoundIsOFF();
__declspec(dllexport) BOOL SND_CALL SND_fn_bTestMPEGIsOFF();
__declspec(dllexport) BOOL SND_CALL SND_fn_bTestCDIsOFF();
__declspec(dllexport) BOOL SND_CALL SND_fn_bTestWAVIsOFF();
__declspec(dllexport) BOOL SND_CALL SND_fn_bTestDBGIsOFF();
__declspec(dllexport) BOOL SND_CALL SND_fn_bTestADPCMIsOFF();
__declspec(dllexport) BOOL SND_CALL SND_fn_bTestRECORDIsOFF();


__declspec(dllexport) HMODULE SND_CALL SND_fn_vGetHModuleMpeg(void);
__declspec(dllexport) HMODULE SND_CALL SND_fn_vGetHModuleWav(void);
__declspec(dllexport) HMODULE SND_CALL SND_fn_vGetHModuleCd(void);
__declspec(dllexport) HMODULE SND_CALL SND_fn_vGetHModuleDbg(void);
__declspec(dllexport) HMODULE SND_CALL SND_fn_vGetHModuleAdpcm(void);
__declspec(dllexport) HMODULE SND_CALL SND_fn_vGetHModuleRecord(void);

HMODULE SND_CALL SND_fn_vGetHModuleDbg(void)
{
        return SND_hDbgModule;
}

HMODULE SND_CALL SND_fn_vGetHModuleMpeg(void)
{
        return SND_hMpegModule;
}

HMODULE SND_CALL SND_fn_vGetHModuleWav(void)
{
        return SND_hWavModule;
}

HMODULE SND_CALL SND_fn_vGetHModuleCd(void)
{
        return SND_hCdModule;
}

HMODULE SND_CALL SND_fn_vGetHModuleAdpcm(void)
{
        return SND_hAdpcmModule;
}

HMODULE SND_CALL SND_fn_vGetHModuleRecord(void)
{
        return SND_hRecordModule;
}

#ifdef _DLL_COMPILATION_MODE
//chargelment d'une DLL par interprétation d'une section
HMODULE LoadDLL(char* nom_section,HMODULE* hModule,int nbModule)
{
    char texte[256];
        char file[256];
        char key_name[256];
        pfnTestFct pfTest=NULL; 
        int iDLL;
        BOOL bMoreDLL;
        int i;
        HMODULE hTmp;
		DWORD err;

        GetPrivateProfileString(nom_section,DLL_UNCONDITIONNAL,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);
        if (strcmp(texte,C_STRING_NONE)!=0)
        {//dll unconditionnal
                sprintf(file,DLLNAME_FORMAT,szDllDirectory,texte,TAG_CHARGEMENT,TAG_COMPILATION,TAG_MODE);
                if (!(hTmp=LoadLibrary(file)))
                        SND_fn_vDisplayError(E_uwSndDLLCannotLoadDLL,file);
                return hTmp;
        }
        else
        {//pas de unconditionnal
                iDLL=0;bMoreDLL=TRUE;
                while (bMoreDLL)
                {
                        sprintf(key_name,DLL_TEST,iDLL);
                        GetPrivateProfileString(nom_section,key_name,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);
                        if (strcmp(texte,C_STRING_NONE)!=0)
                        {//nouveau test
                                //recherche de la fonction dans les modules de test
                                for (i=0;i<nbModule;i++)
                                        if ((pfTest=(pfnTestFct)GetProcAddress(hModule[i],texte))!=NULL) break;
                                //test
                                if (pfTest)
                                {
                                        if ((*pfTest)())
                                        {
                                                sprintf(key_name,DLL_FILE,iDLL);
                                                GetPrivateProfileString(nom_section,key_name,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);
                                                bMoreDLL=FALSE;
                                        }
                                }
                                else
                                {
                                        SND_fn_vDisplayError(E_uwSndDLLCannotFindFunction,texte);
                                }
                                iDLL++;
                        }
                        else
                        {
                                GetPrivateProfileString(nom_section,DLL_DEFAULT,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);
                                bMoreDLL=FALSE;
                        }
                }
                if (strcmp(texte,C_STRING_NONE)!=0)
                {//chargement de la dll
                        sprintf(file,DLLNAME_FORMAT,szDllDirectory,texte,TAG_CHARGEMENT,TAG_COMPILATION,TAG_MODE);
                        if (!(hTmp=LoadLibrary(file)))
						{
							err=GetLastError();
                            SND_fn_vDisplayError(E_uwSndDLLCannotLoadDLL,file);
						}
                        return hTmp;
                }
        }

        return NULL;
}
#endif

void SND_fn_vGetSxdDistanceOptions(RollOffParam *rolloff)
{
	float d_dist_sat,d_dist_back;
	char texte[256];

	GetPrivateProfileString(SECTION_OPTIONS,SXD_DIST_SATUR,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);
	if (strcmp(texte,C_STRING_NONE)==0)
		rolloff->rDistSatur=C_ROLLOFFPARAM_DEFAULT;
	else
	{
		sscanf(texte,"%f",&d_dist_sat);
		rolloff->rDistSatur=M_DoubleToRealSnd(d_dist_sat);
	}

	GetPrivateProfileString(SECTION_OPTIONS,SXD_DIST_BACK,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);
	if (strcmp(texte,C_STRING_NONE)==0)
		rolloff->rDistBackGround=C_ROLLOFFPARAM_DEFAULT;
	else
	{
		sscanf(texte,"%f",&d_dist_back);
		rolloff->rDistBackGround=M_DoubleToRealSnd(d_dist_back);
	}
}

SndBool SND_fn_bSupervisaterOptions(void)
{
	char texte[256];

	GetPrivateProfileString(SECTION_OPTIONS,SUPERVISATER_ON_OFF,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);
    if (strcmp(texte,OPTION_ON)==0)
		return TRUE;
	else
		return FALSE;
}

void SND_fn_vInitOptions(SND_tdstInitStruct *pInitStruct)
{
		char texte[256];
        char file[256];
        //liste des DLL de test
        #define NB_DLLTEST_MAX 10
		//SndReal dist_sat=0,dist_back=0;
		RollOffParam rolloff;
#ifdef _DLL_COMPILATION_MODE
        HMODULE hDLLTest[NB_DLLTEST_MAX];
        BOOL bMoreDLL;
        char key_name[256];
        int iDLLTest;
        int i;
#endif

        strncpy(szDllDirectory,SND_fn_szGetSoftDirectory(),sizeof(szDllDirectory)-1);

        strncpy(ini_file,szDllDirectory,sizeof(ini_file)-1);
        strncat(ini_file,"\\",sizeof(ini_file)-strlen(ini_file)-1);
        strncat(ini_file,SND_INI_FILENAME,sizeof(ini_file)-strlen(ini_file)-1);

        if (!SND_fn_bTestSnd_Win32())
                SND_fn_vDisplayError(E_uwSndInitNotDoneError,"Windows needed");

		GetPrivateProfileString(NULL,NULL,C_STRING_NONE,texte,sizeof(texte)-1,ini_file);

#ifdef _DLL_COMPILATION_MODE
		//en mode DLL, l'absence de ficheir INI est grave (Warning)
		//en mode statique, l'absence de fichier INI est bénine
		if ((texte[0]==0) || (strcmp(texte,C_STRING_NONE)==0))
		{
			sprintf(texte,"The INI file doesn't exist (%s)",ini_file);
			SND_fn_vDisplayError(E_uwSndINIFileNotFound,texte);
		}

        //lecture des options
        GetPrivateProfileString(SECTION_OPTIONS,SOUND_ON_OFF,C_STRING_NONE,texte,sizeof(texte),ini_file);
        if (strcmp(texte,OPTION_OFF)==0)
        {
                bSound_ON=FALSE;
                bADPCM_ON=FALSE;
                bMPEG_ON=FALSE;
                bCD_ON=FALSE;
                bWAV_ON=FALSE;
                bRECORD_ON=FALSE;
                bDBG_ON=FALSE;
        }
		else
		{
			GetPrivateProfileString(SECTION_OPTIONS,MPEG_ON_OFF,C_STRING_NONE,texte,sizeof(texte),ini_file);
			if (strcmp(texte,OPTION_ON)==0)
					bMPEG_ON=TRUE;
			GetPrivateProfileString(SECTION_OPTIONS,CD_ON_OFF,C_STRING_NONE,texte,sizeof(texte),ini_file);
			if (strcmp(texte,OPTION_ON)==0)
					bCD_ON=TRUE;
			GetPrivateProfileString(SECTION_OPTIONS,WAV_ON_OFF,C_STRING_NONE,texte,sizeof(texte),ini_file);
			if (strcmp(texte,OPTION_ON)==0)
					bWAV_ON=TRUE;
			GetPrivateProfileString(SECTION_OPTIONS,ADPCM_ON_OFF,C_STRING_NONE,texte,sizeof(texte),ini_file);
			if (strcmp(texte,OPTION_ON)==0)
					bADPCM_ON=TRUE;
			GetPrivateProfileString(SECTION_OPTIONS,RECORD_ON_OFF,C_STRING_NONE,texte,sizeof(texte),ini_file);
			if (strcmp(texte,OPTION_ON)==0)
					bRECORD_ON=TRUE;
		}
        //chargement des DLL test
        iDLLTest=0;bMoreDLL=TRUE;
        hDLLTest[iDLLTest++]=pInitStruct->hProcessInstance;
        while (bMoreDLL && (iDLLTest<NB_DLLTEST_MAX))
        {
                sprintf(key_name,DLL_FILE,iDLLTest-1);
                GetPrivateProfileString(SECTION_TESTDLL,key_name,C_STRING_NONE,texte,sizeof(texte),ini_file);
                if (strcmp(texte,C_STRING_NONE)!=0)
                {
                        sprintf(file,DLLNAME_FORMAT,szDllDirectory,texte,TAG_CHARGEMENT,TAG_COMPILATION,TAG_MODE);
                        if (!(hDLLTest[iDLLTest]=LoadLibrary(file)))
                                SND_fn_vDisplayError(E_uwSndDLLCannotLoadDLL,file);

                        iDLLTest++;
                }
                else
                        bMoreDLL=FALSE;
        }

        //chargement de la DLL WAV
        if (bWAV_ON)
                SND_hWavModule=LoadDLL(SECTION_SXDDLL,hDLLTest,iDLLTest);
        else
                SND_hWavModule=NULL;

        //chargement de la DLL CD
        if (bCD_ON)
                SND_hCdModule=LoadDLL(SECTION_CDDLL,hDLLTest,iDLLTest);
        else
                SND_hCdModule=NULL;

        //chargement de la DLL MPEG
        if (bMPEG_ON)
                SND_hMpegModule=LoadDLL(SECTION_MPEGDLL,hDLLTest,iDLLTest);
        else
                SND_hMpegModule=NULL;

        //chargement de la DLL ADPCM
        if (bADPCM_ON)
                SND_hAdpcmModule=LoadDLL(SECTION_ADPCMDLL,hDLLTest,iDLLTest);
        else
                SND_hAdpcmModule=NULL;

        //chargement de la DLL RECORD
        if (bRECORD_ON)
                SND_hRecordModule=LoadDLL(SECTION_RECORDDLL,hDLLTest,iDLLTest);
        else
                SND_hRecordModule=NULL;


        //init des pointeurs
        SND_DllInitEntryPoints_WavFunctions(SND_hWavModule);
        SND_DllInitEntryPoints_CdFunctions(SND_hCdModule);
        SND_DllInitEntryPoints_MpegFunctions(SND_hMpegModule);
        SND_DllInitEntryPoints_AdpcmFunctions(SND_hAdpcmModule);
#ifdef USE_RECORD_MODULE
        SND_DllInitEntryPoints_RecordFunctions(SND_hRecordModule);
#endif

        //dechargement des DLLs de test
        for (i=1;i<iDLLTest;i++)
                FreeLibrary(hDLLTest[i]);
#endif	//DLL_COMPILATION

		//init des options pour SXD
		SND_fn_vGetSxdDistanceOptions(&rolloff);
		SND_fn_vSetDefaultRollOff(&rolloff);
		//SND_fn_vSetDistanceForVolume(&dist_sat,&dist_back);

		GetPrivateProfileString(SECTION_OPTIONS,SUPERVISATER_ON_OFF,C_STRING_NONE,texte,sizeof(texte),ini_file);
	    if (strcmp(texte,OPTION_ON)==0)
				bDBG_ON=TRUE;

        //chargement de la DLL Supervisater(DBG)
        if (bDBG_ON)
		{
			strncpy(file,szDllDirectory,sizeof(file));
			strncat(file,"\\SNDdbgV.DLL",sizeof(file)-strlen(file)-1);
			SND_hDbgModule=LoadLibrary(file);
		}
        else
            SND_hDbgModule=NULL;

		SND_DllInitEntryPoints_DbgFunctions(SND_hDbgModule);

        if (bDBG_ON)
			SND_fn_vSetSupervisaterActive();
}

void SND_fn_vDesInitOptions(void)
{
#ifdef _DLL_COMPILATION_MODE
        if (SND_hWavModule) FreeLibrary(SND_hWavModule);
        if (SND_hCdModule) FreeLibrary(SND_hCdModule);
        if (SND_hMpegModule) FreeLibrary(SND_hMpegModule);
        if (SND_hDbgModule) FreeLibrary(SND_hDbgModule);
        if (SND_hAdpcmModule) FreeLibrary(SND_hAdpcmModule);
        if (SND_hRecordModule) FreeLibrary(SND_hRecordModule);
#endif
}

// SND_fn_bGetOptions:extrait une info du fichier INI
//	Entrées:sction:nom de la section (chapitre)
//		key=key_name
//		value=poiteur où mettre la valeur de la key
//		size_value=nombre d'octets que value peut recevoir
//	Sortie:TRUE si valeur pour la key
SndBool SND_CALL SND_fn_bGetOptions(char* section,char* key,char* value,int size_value)
{
	GetPrivateProfileString(section,key,C_STRING_NONE,value,size_value,ini_file);

	if (strcmp(value,C_STRING_NONE)==0)
		return FALSE;
	else
		return TRUE;
}

void SND_CALL SND_fn_vSetOptions(char* section,char* key,char* value)
{
	WritePrivateProfileString(section,key,value,ini_file);
}

//pour compatibilité ascendante
SndBool SND_CALL SND_fn_bCanSetOptions(void)
{
	return TRUE;
}

