Files
reman3/Rayman_X/cpa/tempgrp/SND/src/Win95/sndcd.c
2024-09-18 02:33:44 +08:00

2426 lines
69 KiB
C
Raw Blame History

/*
MODULE DE GESTION DU CD
pour WIN95 en mode MCI
UBI SOUND STUDIOS
Olivier Amiaud
*/
/*****************************************************************************
Prototype de la fonction de gestion d'erreur
void SND_fn_vDisplayError(unsigned short uwErrNum,char *message)
Liste des erreurs
-----------------
E_uwSndCDLoadTrack
E_uwSndCDStatus
E_uwSndCDSet
E_uwSndCDPlay
E_uwSndCDStop
E_uwSndCDNotifyFailure
E_uwSndCDNotifyAborted
E_uwSndCDNotifySuperseded
E_uwSndCDCreateThread
E_uwSndCDClose
E_uwSndCDFade
******************************************************************************/
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <process.h>
#include "SNDinc.h"
#include "sndres.h"
#include "sndwin95.h"
//#include "sndmusct.h"
#include "sndCD.h"
#if defined(_DLL_COMPILATION_MODE)
#include "SNDDLL.h"
#endif
#include "sndthrd.h"
//#include "snderr.h"
//#include "sndmem.h"
#ifndef DISABLE_CD
//#define CD_MCI
//----------------------------------
//- Partie concernant le CD mixer -
//----------------------------------
static MIXERCAPS mixerCapsCD;
static HMIXER hMixerCD;
static UINT mixerIdentifierCD;
static UINT uiNbrMixersCD;
static DWORD dwNbrAudioLinesCD;
static MIXERLINE mixerLineCD;
static MIXERLINECONTROLS mixerLineControlsCD;
static MIXERCONTROL mixerControlCD;
static MIXERCONTROLDETAILS mixerControlDetailsCD;
static MIXERCONTROLDETAILS_UNSIGNED valeurCD;
static BOOL CDControlAvailable = FALSE;
//----------------------------------
//- Partie concernant le CD driver -
//----------------------------------
#define MSG_ERR_CD "CD Device Error"
#define MSG_ERR_CD_FILE "CD File Error"
#define MSG_ERR_CD_NOT_READY "CD Not Ready"
#define MSG_ERR_BAD_CD_ID_TRACK "Bad CD Track Number"
#define SND_CD_NOT_IN_CD_PLAYER 10
#define SND_CD_NOT_THE_GOOD_ONE_AND_NOT_AUDIO 11
#define SND_CD_NOT_THE_GOOD_ONE_BUT_AUDIO 12
#define SND_CD_USED_BY_A_PROGRAM 13
#define FADE_AND_STOP_CD 12
#define NB_MAX_CD_TRACKS 20
#define NB_CD_TRACKS 12
#define OFFSET_CD_VOICE 0x3000
#define MASK_OFFSET_CD_VOICE 0x0FFF
#define NO_CD_VOICE 0x127
#define CD_UNAVAILABLE 0x0004
#define CD_STATE_NORMAL 1
#define CD_STATE_USED 2
#define CD_STATE_ALL_TRACKS 3
#define CD_STATE_UNUSED 4
#define TIMER_CD 34
#define VOL_MAX_CD 60
#define SND_MAKE_TMSF(t,m,s,f) ((DWORD)t)|(((DWORD)m)<<8)|(((DWORD)s)<<16)|(((DWORD)f)<<24)
#define SND_TMSF_T(tmsf) ((BYTE)(tmsf))
#define SND_TMSF_M(tmsf) ((BYTE)(((WORD)(tmsf)) >> 8))
#define SND_TMSF_S(tmsf) ((BYTE)((tmsf)>>16))
#define SND_TMSF_F(tmsf) ((BYTE)((tmsf)>>24))
#define SND_TMSF_MS(tmsf) \
((((((((tmsf & 0xff00) >> 8) * 60) + ((tmsf & 0xff0000) >> 16)) * 75) + ((tmsf & 0xff000000)>>24)) * 1000) / 75)
// VARIABLES GLOBALES EXTERNES
// TYPEDEF LOCAUX
// Definition ensemble des pistes du jeu
typedef struct _tdstCDTrack
{
SndBool bLoop;
int iNbLoops;
DWORD tmsfStartTrack;
DWORD tmsfEndTrack;
DWORD dwStartingFrame;
DWORD dwEndingFrame;
DWORD dwStartLoopingFrame;
DWORD dwEndLoopingFrame;
tduRefRes uCDTrack;
} tdstCDTrack;
// Definition piste active a l'instant t
typedef struct _tdstActiveCDTrack
{
SndBool bActive;
SndBool bPaused; // le CD a <20>t<EFBFBD> mi sen pause
long lPausePos; // Postition physique de la pause
SndBool bLoop;
int iNbLoops;
long lVoice;
long lIndexVoice;
unsigned long ulTrackLengthInMs;
SoundParam * pstSoundParam;
long lPrio;
SND_td_pfn_vSoundCallback pfnSoundCallback;
long lParSoundCallback;
} tdstActiveCDTrack;
// Definition data necessaire au driver
typedef struct _stCDDriver
{
SndBool bCdDriverOk;
SndBool bRequestCdDriver;
unsigned char ucState;
MCIDEVICEID uiCdDeviceId;
long lNbCdTracks;
int iLastCDVolume;
} tdstCDDriver;
// -------------------------------------------
// VARIABLES GLOBALES LOCALES
static SndBool bCDFadeIn = FALSE;
static UINT uiTimerCDFadeIn;// Gestion du fade-in
static unsigned long ulCountDownFadeIn;
static unsigned long ulTimerPeriodFadeIn;
static long lNbIterFadeIn;
static SndBool bCDFadeOut= FALSE;
static UINT uiTimerCDFadeOut;// Gestion du fade-out
static unsigned long ulCountDownFadeOut;
static unsigned long ulTimerPeriodFadeOut;
static long lNbIterFadeOut;
static unsigned char ucFacteurVolume;// Volume global CD
// Pistes CD du jeu et piste active
static tdstCDTrack stCDTracks[NB_MAX_CD_TRACKS];
static tdstActiveCDTrack stActiveCDTrack;
static tdstCDDriver stCDDriver;// CD driver
static int iNbCdTracks;
static char texte_erreur[1024];
// -------------------------------------------
// HANDLE ET ID DE THREADS ET FENETRES
static HWND hSndCdWnd;// handle de la fenetre de gestion de messages du CD
static DWORD dwCDThreadId;
static HANDLE hCDThread=NULL;
static HANDLE hCDThreadCallBack;
static DWORD dwCDThreadIdCallBack;
//********************************************************************** BIDOUILLE CD PLAYER
// -------------------------------------------
// VARIABLES CONCERNANT LA GESTION DES THREADS
UINT SND_PLAYCD_MSG;
UINT SND_STOPCD_MSG;
UINT SND_LOADCD_MSG;
UINT SND_PAUSECD_MSG;
UINT SND_RESUMECD_MSG;
UINT SND_NEXTTRACKCD_MSG;
UINT SND_DESINITCD_MSG;
UINT SND_RELEASECD_MSG;
UINT SND_RESTORECD_MSG;
UINT SND_GETPOSCD_MSG;
static DWORD dw_a5_Params[5];
static DWORD dw_a2_threadParams[2];
#endif //DISABLE_CD
// -------------------------------------------
// PROTOTYPES DES FONCTIONS LOCALES
SndBool SND_fn_bLoadCDTrack(tdstBlockResourceMem * pstPtr,int);
SndBool SND_fn_bUnloadCDTrack(int i);
SndBool SND_fn_bMediaPresent(void);
long SND_fn_lGetActiveCdTrack(void);
long SND_fn_lGetCurrentCdMode(void);
long SND_fn_lGetCDLength(void);
long SND_fn_lGetCdTrack(tdxId Id);
long SND_fn_lGetCurrentCdPosition(void);
void SND_fn_vCloseCDDoor(void);
int SND_fn_iMixerInitCD(void);
int SND_fn_iMixerDesInitCD(void);
DWORD SND_fn_dwGetCDMax(void);
DWORD SND_fn_dwGetCDMin(void);
DWORD SND_fn_dwGetCDValue(void);
void SND_fn_vSetCDValue(DWORD val);
void SND_CALL SND_fn_vReleaseDriverCDThread();
void SND_CALL SND_fn_vRestoreDriverCDThread();
// prototypes des fonctions appelees par le thread
int SND_fn_iInitCDThread();
SndBool SND_fn_bLoadCDTrackThread(tdstBlockResourceMem * pstPtr,int numTrack);
void SND_fn_vDesInitCDThread(void);
long SND_fn_lPlayCDThread(tduRefRes res,SoundParam *par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback);
void SND_fn_vStopCDThread(long voice);
long SND_fn_lNextCDTrackThread();
void SND_fn_vPauseCDThread(long voice);
void SND_fn_vResumeCDThread(long voice);
SndReal SND_CALL SND_fn_rGetPosCDThread(long voice);
LRESULT CALLBACK SND_fn_vCdMSG(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
//#ifdef CD_MCI
//-----------------------------------------------------------
// ConvertRsvDiskToMem
//
// But : Convertir un BlockResourceDisk en Mem
// Entr<74>es : reference au structs ressources mem et disk
// Sorties : neant
//------------------------------------------------------------
void SND_CALL SND_fn_vConvertResDiskToMemCD(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem,void * ptrBegin)
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
mem->Id=disk->Id;
mem->eType=disk->eType;
mem->eStorage=disk->eStorage;
mem->ucVolume=disk->ucVolume;
mem->bIsLoaded=TRUE;
//partie sp<73>cifique au type de ressource
mem->uRes.stCD.bVolable = disk->uRes.stCD.bVolable;
mem->uRes.stCD.wTrackId = disk->uRes.stCD.wTrackId;
mem->uRes.stCD.bLoop = disk->uRes.stCD.bLoop;
mem->uRes.stCD.ulStartingFrame = disk->uRes.stCD.ulStartingFrame;
mem->uRes.stCD.ulEndingFrame = disk->uRes.stCD.ulEndingFrame;
if (mem->uRes.stCD.bLoop)
{
mem->uRes.stCD.ulStartLoop = disk->uRes.stCD.ulStartLoop;
mem->uRes.stCD.ulEndLoop = disk->uRes.stCD.ulEndLoop;
mem->uRes.stCD.iNbLoops = disk->uRes.stCD.iNbLoops;
}
else
{
mem->uRes.stCD.ulStartLoop = mem->uRes.stCD.ulEndLoop = 0;
mem->uRes.stCD.iNbLoops = 0;
}
if (stCDDriver.bCdDriverOk)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
dw_a5_Params[0] = (DWORD)mem;
dw_a5_Params[1] = (DWORD)iNbCdTracks++;
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_LOADCD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDLoadTrack,"PostThreadMessage Load Track");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
}
#endif //DISABLE_CD
}
SndBool SND_CALL SND_fn_bLoadResScriptCd(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem)
{
#ifndef DISABLE_CD
SND_fn_vConvertResDiskToMemCD(disk,mem,NULL);
return TRUE;
#else //DISABLE_CD
return FALSE;
#endif //DISABLE_CD
}
SndBool SND_CALL SND_fn_bLoadResBinaryCd(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem,char *pDataBloc)
{
#ifndef DISABLE_CD
SND_fn_vConvertResDiskToMemCD(disk,mem,NULL);
#endif //DISABLE_CD
return FALSE;
}
#ifndef DISABLE_CD
//-----------------------------------------------------------
// SND_fn_bMediaPresent
//
// But : Dire si le CD est dans le lecteur
// Entr<74>es : neant
// Sorties : True,False
//------------------------------------------------------------
SndBool SND_fn_bMediaPresent()
{
MCI_STATUS_PARMS status;
MCIERROR mciReturn;
// Mode actuel de la piste
status.dwItem = MCI_STATUS_MEDIA_PRESENT;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0);
}
return(status.dwReturn);
}
//-----------------------------------------------------------
// SND_fn_lGetTypeCd(short Id)
//
// But : Donne le type d'une piste du CDROM
// Entr<74>es : Id de la piste a tester
// Sorties : Type (MCI_CDA_TRACK_AUDIO ou MCI_CDA_TRACK_OTHER ou 0)
//------------------------------------------------------------
long SND_fn_lGetTypeCdTrack(short Id)
{
MCI_STATUS_PARMS status;
MCIERROR mciReturn;
// Mode actuel de la piste
status.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
status.dwTrack = Id;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM|MCI_TRACK,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0);
}
return(status.dwReturn);
}
//-----------------------------------------------------------
// SND_fn_lGetNbCdTracks()
//
// But : Donne le nombre de pistes du CD
// Entr<74>es : neant
// Sorties : nb pistes
//------------------------------------------------------------
long SND_fn_lGetNbCdTracks()
{
MCI_STATUS_PARMS status;
MCIERROR mciReturn;
status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0);
}
return(status.dwReturn);
}
//-----------------------------------------------------------
// SND_fn_lTimerIn()
//
// But : Callback de gestion du temps pour les fade-in.
// Entr<74>es : neant
// Sorties : neant
//------------------------------------------------------------
void CALLBACK SND_fn_lCDTimerIn(UINT IDEvent,UINT msg,DWORD par,DWORD dw1,DWORD dw2)
{
if (!stActiveCDTrack.bPaused && stActiveCDTrack.bActive)
if (bCDFadeIn)
{
if (lNbIterFadeIn--)
SND_fn_vSetCDValue(ucFacteurVolume++);
else
{
bCDFadeIn = FALSE;
ulCountDownFadeIn = 0;
}
}
}
//-----------------------------------------------------------
// SND_fn_lTimerOut()
//
// But : Callback de gestion du temps pour les fade-in.
// Entr<74>es : neant
// Sorties : neant
//------------------------------------------------------------
void CALLBACK SND_fn_lCDTimerOut(UINT IDEvent,UINT msg,DWORD par,DWORD dw1,DWORD dw2)
{
unsigned long ulRealTime = 0;
if (!stActiveCDTrack.bPaused && stActiveCDTrack.bActive)
if (bCDFadeOut)
{
ulCountDownFadeOut += ulTimerPeriodFadeOut;
ulRealTime = stActiveCDTrack.ulTrackLengthInMs - lNbIterFadeOut * ulTimerPeriodFadeOut;
if (ulCountDownFadeOut > ulRealTime)
{
SND_fn_vSetCDValue(ucFacteurVolume);
if (ucFacteurVolume-- == 0)
{
bCDFadeOut = FALSE;
ulCountDownFadeOut = 0;
if (par == FADE_AND_STOP_CD)
{
SND_fn_vStopCD(0);
PostMessage(hSndCdWnd,MM_MCINOTIFY,MCI_NOTIFY_SUCCESSFUL,0);
}
}
}
}
}
//-----------------------------------------------------------
// SND_fn_iCdThreadCallBack
//
// But : Proc<6F>dure de la thread qui contient la fenetre qui traite les messages MCI
// Entr<74>es : void * : param<61>tre inutilis<69>
// Sorties : void
//------------------------------------------------------------
int WINAPI SND_fn_iCDThreadCallBack(long arglist)
{
long * pArg = (void *)arglist;
SND_td_pfn_vSoundCallback pfnCallback = (SND_td_pfn_vSoundCallback)pArg[0];
long lParCallback = pArg[1];
SND_fn_vEnterCriticalSectionThreadSnd();
if (pfnCallback != NULL)
(*pfnCallback)(lParCallback);
SND_fn_vQuitCriticalSectionThreadSnd();
return (0);
}
//-----------------------------------------------------------
// SND_fn_vCdMSG
//
// But : Effectuer la gestion des messages du CD
// Entr<74>es : Messages et leurs parametres
// Sorties : Ok ou Failed
//------------------------------------------------------------
LRESULT CALLBACK SND_fn_vCdMSG(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
char texte[256];
long current_mode;
SECURITY_ATTRIBUTES sa;
switch(message)
{
case WM_CREATE : break;
case WM_COMMAND : break;
case WM_TIMER : break;
case MM_MCINOTIFY :
switch (wParam)
{
case MCI_NOTIFY_FAILURE:
sprintf(texte,"MM_MCINOTIFY FAILURE wpar=%d lpar=%d",wParam,lParam);
SND_fn_vDisplayError(E_uwSndCDNotifyFailure,texte);
break;
case MCI_NOTIFY_ABORTED:
//sprintf(texte,"MM_MCINOTIFY ABORTED wpar=%d lpar=%d",wParam,lParam);
//SND_fn_vDisplayError(E_uwSndCDNotifyAborted,texte);
break;
case MCI_NOTIFY_SUPERSEDED:
sprintf(texte,"MM_MCINOTIFY SUPERSEDED wpar=%d lpar=%d",wParam,lParam);
SND_fn_vDisplayError(E_uwSndCDNotifySuperseded,texte);
break;
case MCI_NOTIFY_SUCCESSFUL:
current_mode = SND_fn_lGetCurrentCdMode();
switch (current_mode)
{
case MCI_MODE_STOP :
if (!stActiveCDTrack.bPaused)
{
if ((stActiveCDTrack.bLoop)&&(stActiveCDTrack.iNbLoops--))
{
SND_fn_lPlayCDThread( stCDTracks[stActiveCDTrack.lVoice].uCDTrack,
stActiveCDTrack.pstSoundParam,
stActiveCDTrack.lPrio,
stActiveCDTrack.pfnSoundCallback,
stActiveCDTrack.lParSoundCallback);
}
else
{
if (uiTimerCDFadeIn)
timeKillEvent(uiTimerCDFadeIn);
if (uiTimerCDFadeOut)
timeKillEvent(uiTimerCDFadeOut);
stActiveCDTrack.bPaused = FALSE;
stActiveCDTrack.bActive = FALSE;
stActiveCDTrack.bLoop = FALSE;
stActiveCDTrack.lVoice = NO_CD_VOICE;
stActiveCDTrack.pstSoundParam = NULL;
stActiveCDTrack.lPrio = 0;
if (stActiveCDTrack.pfnSoundCallback)
{
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
dw_a2_threadParams[0] = (DWORD)stActiveCDTrack.pfnSoundCallback;
dw_a2_threadParams[1] = (DWORD)stActiveCDTrack.lParSoundCallback;
if (!(hCDThreadCallBack = CreateThread(&sa,0,(LPTHREAD_START_ROUTINE)SND_fn_iCDThreadCallBack,(LPVOID)dw_a2_threadParams,0,&dwCDThreadIdCallBack)))
SND_fn_vDisplayError(E_uwSndCDCreateThread,"");
stActiveCDTrack.pfnSoundCallback = NULL;
stActiveCDTrack.lParSoundCallback = 0;
}
}
}
break;
case MCI_MODE_PAUSE : break;
case MCI_MODE_PLAY : break;
case MCI_MODE_NOT_READY : break;
default : break;
}
break;
}
return 0;
case WM_DESTROY:
if (uiTimerCDFadeIn)
timeKillEvent(uiTimerCDFadeIn);
if (uiTimerCDFadeOut)
timeKillEvent(uiTimerCDFadeOut);
PostQuitMessage(0);
break;
default: return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}
//-----------------------------------------------------------
// SND_fn_iErreurInit
//
// But : Initialisation de la fenetre de dialogue
// des erreurs a l'init du driver Midi
// Entr<74>es : constantes numero d'erreur
// Sorties : code de retour de la boite de dialogue
//------------------------------------------------------------
/*
int SND_CALL SND_fn_iErreurInitCD()
{
int ret;
ret=Erm_fn_iMessageBox(hwndMainSnd,"Insert a CD or\nClose the application using your CD and try again ...\nelse you'll not be able to hear any music","CD-Driver Problem",MB_ABORTRETRYIGNORE|MB_TOPMOST);
switch (ret)
{
case IDABORT:
return INIT_FAILED;
case IDIGNORE:
return INIT_IGNORE;
case IDRETRY:
return INIT_RETRY;
default:
return INIT_IGNORE;
}
}
*/
//-----------------------------------------------------------
// SND_fn_iCdThreadProc
//
// But : Proc<6F>dure de la thread qui contient la fenetre qui traite les messages MCI
// Entr<74>es : void * : param<61>tre inutilis<69>
// Sorties : void
//------------------------------------------------------------
int __stdcall SND_fn_iCDThreadProc(HANDLE arglist)
{
MSG msg;
WNDCLASS wcCdWndClass;
DWORD * pdwParams;
PeekMessage(&msg,NULL,0,0,PM_NOREMOVE);
if (SND_fn_iInitCDThread() == C_INIT_FAILED)
{
stCDDriver.bCdDriverOk = FALSE;
stCDDriver.ucState = CD_STATE_USED;
ExitThread(C_INIT_FAILED);
}
//definit la window-classe
wcCdWndClass.hInstance = SND_hGlobalInst;
wcCdWndClass.lpszClassName = "SoundAcpCd";
wcCdWndClass.lpfnWndProc = SND_fn_vCdMSG;//fonction associ<63>e <20> la fonction
wcCdWndClass.style=0;
wcCdWndClass.hIcon=0;
wcCdWndClass.hCursor=0;
wcCdWndClass.lpszMenuName='\0';
wcCdWndClass.cbClsExtra=0;
wcCdWndClass.cbWndExtra=0;
wcCdWndClass.hbrBackground=0;
//enregistrement de la classe CdWnd
if (!RegisterClass(&wcCdWndClass))
SND_fn_vDisplayError(E_uwSndCDRegisterWndClass,"");
SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
//cr<63>ation de la fenetre cd
hSndCdWnd = CreateWindow(wcCdWndClass.lpszClassName,"CdWindow",WS_OVERLAPPEDWINDOW,0,0,0,0,HWND_DESKTOP,NULL,SND_hGlobalInst,NULL);
// synchro d'initialisation du thread et de la pompe a messages quand tout c'est bien pass<73>
SetEvent(arglist);
while (GetMessage(&msg,NULL,0,0))
{
if (msg.message == SND_PLAYCD_MSG)
{
pdwParams = (DWORD *)msg.wParam;
pdwParams[0] = SND_fn_lPlayCDThread(*(tduRefRes *)pdwParams[0],(SoundParam *)pdwParams[1],(long)pdwParams[2] ,(SND_td_pfn_vSoundCallback)pdwParams[3] ,(long)pdwParams[4] );
// on debloque le thread appelant
SetEvent((HANDLE)msg.lParam);
}
else
if (msg.message == SND_STOPCD_MSG)
{
pdwParams = (DWORD *)msg.wParam;
SND_fn_vStopCDThread((long)pdwParams[0]);
// on debloque le thread appelant
SetEvent((HANDLE)msg.lParam);
}
else
if (msg.message == SND_LOADCD_MSG)
{
pdwParams = (DWORD *)msg.wParam;
pdwParams[0] = SND_fn_bLoadCDTrackThread((tdstBlockResourceMem *)pdwParams[0],(int)pdwParams[1]);
// on debloque le thread appelant
SetEvent((HANDLE)msg.lParam);
}
else
if (msg.message == SND_PAUSECD_MSG)
{
pdwParams = (DWORD *)msg.wParam;
SND_fn_vPauseCDThread((long)pdwParams[0]);
SetEvent((HANDLE)msg.lParam);
}
else
if (msg.message == SND_RESUMECD_MSG)
{
pdwParams = (DWORD *)msg.wParam;
SND_fn_vResumeCDThread((long)pdwParams[0]);
SetEvent((HANDLE)msg.lParam);
}
else
if (msg.message == SND_NEXTTRACKCD_MSG)
{
pdwParams = (DWORD *)msg.wParam;
pdwParams[0] = SND_fn_lNextCDTrackThread();
// on debloque le thread appelant
SetEvent((HANDLE)msg.lParam);
}
else
if (msg.message == SND_DESINITCD_MSG)
{
SND_fn_vDesInitCDThread();
SetEvent((HANDLE)msg.lParam);
ExitThread(0);
}
else
if (msg.message == SND_RELEASECD_MSG)
{
SND_fn_vReleaseDriverCDThread();
SetEvent((HANDLE)msg.lParam);
}
else
if (msg.message == SND_RESTORECD_MSG)
{
SND_fn_vRestoreDriverCDThread();
SetEvent((HANDLE)msg.lParam);
}
if (msg.message == SND_GETPOSCD_MSG)
{
pdwParams = (DWORD *)msg.wParam;
pdwParams[0] = (DWORD) SND_fn_rGetPosCDThread((long)pdwParams[0]);
// on debloque le thread appelant
SetEvent((HANDLE)msg.lParam);
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
#endif //DISABLE_CD
//-----------------------------------------------------------
// SND_fn_iInitCd
//
// But : Realiser l'init bas niveau du driver midi
// Entr<74>es : neant
// Sorties : C_INIT_OK ou C_INIT_FAILED
//------------------------------------------------------------
int SND_CALL SND_fn_iInitCD(SND_tdstInitStruct *pInitStruct)
{
#ifndef DISABLE_CD
DWORD dwExitCode = 0;
HANDLE hEventSynchro;
HANDLE hHandlesForWait[2];
SECURITY_ATTRIBUTES sa;
#if defined(_DLL_COMPILATION_MODE)
SND_DllInitEntryPoints_StaticFunctions((HMODULE)pInitStruct->hProcessInstance );
#endif
stCDDriver.bCdDriverOk = CD_UNAVAILABLE;
uiTimerCDFadeIn = uiTimerCDFadeOut = 0;
// Init toutes pistes CD
//init de hwndSnd et hinst ,et SND_hResourceHandle:
hwndMainSnd=pInitStruct->hMainWindow;
SND_hGlobalInst=pInitStruct->hProcessInstance;
if (SND_g_hResourceHandle==NULL)
SND_g_hResourceHandle=SND_hGlobalInst;
// on init les points d'entree fonctions externes DLL
#ifdef _DLL_COMPILATION_MODE
SND_DllInitEntryPoints_StaticFunctions((HMODULE)SND_hGlobalInst);
#endif
// on enregistre les differents types de messages recus par le thread
SND_PLAYCD_MSG = RegisterWindowMessage("PlayCd");
SND_STOPCD_MSG = RegisterWindowMessage("StopCd");
SND_LOADCD_MSG = RegisterWindowMessage("LoadCd");
SND_PAUSECD_MSG = RegisterWindowMessage("PauseCd");
SND_RESUMECD_MSG = RegisterWindowMessage("ResumeCd");
SND_NEXTTRACKCD_MSG = RegisterWindowMessage("NextTrackCd");
SND_DESINITCD_MSG = RegisterWindowMessage("DesinitCd");
SND_RELEASECD_MSG = RegisterWindowMessage("ReleaseCd");
SND_RESTORECD_MSG = RegisterWindowMessage("RestoreCd");
SND_GETPOSCD_MSG = RegisterWindowMessage("GetPosCd");
// on cree le thread de gestion CD l'ID du thread est dwCDThreadId
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
while (TRUE)
{
if (!(hCDThread = CreateThread(&sa,0,(LPTHREAD_START_ROUTINE)SND_fn_iCDThreadProc,hEventSynchro,0,&dwCDThreadId)))
{
SND_fn_vDisplayError(E_uwSndCDCreateThread,"");
return C_INIT_FAILED;
}
else
{
hHandlesForWait[0] = hEventSynchro;
hHandlesForWait[1] = hCDThread;
// on attend la synchronisation d'init., l'attente se termine quand un des deux events arrive
WaitForMultipleObjects(2,hHandlesForWait,FALSE,INFINITE);
GetExitCodeThread(hCDThread,&dwExitCode);
if (dwExitCode == STILL_ACTIVE)
{
stCDDriver.bCdDriverOk = TRUE;
CloseHandle(hEventSynchro);
return C_INIT_OK;
}
else
{
if (dwExitCode == C_INIT_FAILED)
{
CloseHandle(hCDThread);
hCDThread=NULL;
switch (SND_fn_iErreurInit(0))
{
case INIT_IGNORE:
// on joue sans CD
CloseHandle(hEventSynchro);
return C_INIT_FAILED;
case INIT_RETRY:
// on reinit jusqu'a appli utilisatrice libere driver
break;
case INIT_FAILED:
// on sort du program
stCDDriver.bCdDriverOk = FALSE;
CloseHandle(hEventSynchro);
exit(0);
}
}
}
}
}
return C_INIT_OK;
#else
return C_INIT_FAILED;
#endif //DISABLE_CD
}
#ifndef DISABLE_CD
//-----------------------------------------------------------
// SND_fn_iInitCdThread
//
// But : Realiser l'init bas niveau du driver midi
// Entr<74>es : neant
// Sorties : C_INIT_OK ou C_INIT_FAILED
//------------------------------------------------------------
int SND_fn_iInitCDThread()
{
int i;
MCI_OPEN_PARMS open;
MCI_SET_PARMS set;
MCIERROR mciReturn;
MCI_SYSINFO_PARMS sysinfo;
long lOpeningMode = 0;
stCDDriver.bCdDriverOk = CD_UNAVAILABLE;
uiTimerCDFadeIn = uiTimerCDFadeOut = 0;
// Init toutes pistes CD
for (i=0;i<NB_MAX_CD_TRACKS;i++)
{
stCDTracks[i].bLoop = FALSE;
stCDTracks[i].tmsfStartTrack = 0;
stCDTracks[i].tmsfEndTrack = 0;
stCDTracks[i].dwStartingFrame = 0;
stCDTracks[i].dwEndingFrame = 0;
stCDTracks[i].dwStartLoopingFrame = 0;
stCDTracks[i].dwEndLoopingFrame = 0;
stCDTracks[i].uCDTrack.Id = 0;
}
// Init piste CD active
stActiveCDTrack.bPaused = FALSE;
stActiveCDTrack.bActive = FALSE;
stActiveCDTrack.bLoop = FALSE;
stActiveCDTrack.lVoice = NO_CD_VOICE;
stActiveCDTrack.pfnSoundCallback= NULL;
stActiveCDTrack.lParSoundCallback= 0;
stActiveCDTrack.pstSoundParam = NULL;
stActiveCDTrack.lPrio = 0;
iNbCdTracks = 0;
open.lpstrDeviceType=(LPCSTR)(MCI_DEVTYPE_CD_AUDIO);
do
{
stCDDriver.bCdDriverOk = FALSE;
if (mciReturn=mciSendCommand((DWORD)NULL,MCI_OPEN,MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,(DWORD)(LPVOID)&open))
{
return C_INIT_FAILED;
}
else
stCDDriver.bCdDriverOk = TRUE;
} while (!stCDDriver.bCdDriverOk);
if (stCDDriver.bCdDriverOk)
{
stCDDriver.uiCdDeviceId = open.wDeviceID;
lOpeningMode = SND_fn_lGetCurrentCdMode();
switch (lOpeningMode)
{
// MCI_OPEN : un CD est en train d'etre jou<6F>
case MCI_OPEN : break;
// MCI_MODE_NOT_READY : aucun player CD actif
case MCI_MODE_NOT_READY: break;
// MCI_MODE_PAUSE : un player CD est actif
case MCI_MODE_PAUSE: break;
// MCI_MODE_PLAY : un player CD est actif
case MCI_MODE_PLAY: break;
// MCI_MODE_STOP : un player CD est actif
case MCI_MODE_STOP: break;
// MCI_MODE_OPEN : la porte du lecteur CD est ouverte
case MCI_MODE_OPEN: SND_fn_vCloseCDDoor();break;
// MCI_MODE_RECORD : peu probable
case MCI_MODE_RECORD: break;
// MCI_MODE_SEEK : un player CD est actif
case MCI_MODE_SEEK : break;
default : SND_fn_vDisplayError(E_uwSndSystemError,"SND_fn_lGetCurrentCdMode returns unknown value");
}
// Le CD est pr<70>sent ou pas dans le lecteur
if (!SND_fn_bMediaPresent())
return C_INIT_FAILED;
// Un CD est present, on teste sa validite, en fonction du nombre de tracks
#ifdef _RIGHT_CD_NB_TRACKS
while ((stCDDriver.lNbCdTracks=SND_fn_lGetNbCdTracks()) != NB_CD_TRACKS)
{
// Le CD contient au moins une piste audio
if (stCDDriver.lNbCdTracks)
mciReturn = SND_fn_iErreurInit(SND_CD_NOT_THE_GOOD_ONE_BUT_AUDIO);
else
mciReturn = SND_fn_iErreurInit(SND_CD_NOT_THE_GOOD_ONE_AND_NOT_AUDIO);
switch (mciReturn)
{
// on joue ce CD dans l'ordre des tracks au premier evenement PLAY
case INIT_PLAY:
stCDDriver.ucState = CD_STATE_ALL_TRACKS;
goto INIT_CD_OK;
// on joue ce CD comme si c'etait le bon
case INIT_PLAYASIF:
stCDDriver.ucState = CD_STATE_NORMAL;
goto INIT_CD_OK;
// on continue sans musique CD
case INIT_IGNORE:
stCDDriver.ucState = CD_STATE_UNUSED;
stCDDriver.bCdDriverOk = FALSE;
return C_INIT_FAILED;
// on sort du programme
case INIT_FAILED:
stCDDriver.bCdDriverOk = FALSE;
return C_INIT_FAILED;
// on reessaye jusqu'a avoir le bon CD
case INIT_RETRY:
break;
default:
SND_fn_vDisplayError(E_uwSndResourceMissing,"");
return C_INIT_FAILED;
}
}
INIT_CD_OK :
#else
// on initialise le nombre de piste du CD
stCDDriver.lNbCdTracks = SND_fn_lGetNbCdTracks();
stCDDriver.ucState = CD_STATE_NORMAL;
#endif
stCDDriver.bCdDriverOk = TRUE;
// Set the time format to track/minute/second/frame (TMSF).
set.dwTimeFormat=MCI_FORMAT_TMSF;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_SET,MCI_SET_TIME_FORMAT,(DWORD)(LPVOID)&set))
{
stCDDriver.bCdDriverOk = FALSE;
}
}
// Demande du nom d'installation du driver CD
sysinfo.lpstrReturn = texte_erreur;
sysinfo.dwRetSize = 1024;
sysinfo.wDeviceType = MCI_DEVTYPE_CD_AUDIO;
if (mciReturn = mciSendCommand(stCDDriver.uiCdDeviceId, MCI_SYSINFO, MCI_SYSINFO_INSTALLNAME , (DWORD) (LPMCI_SYSINFO_PARMS) &sysinfo))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndResourceMissing,texte_erreur);
}
if (!SND_fn_iMixerInitCD())
{
// On sauve l'ancienne valeur du volume CD
stCDDriver.iLastCDVolume = SND_fn_dwGetCDValue();
ucFacteurVolume = stCDDriver.iLastCDVolume;
SND_fn_vSetCDValue(ucFacteurVolume);
}
return C_INIT_OK;
}
#endif //DISABLE_CD
//-----------------------------------------------------------
// SND_fn_iTestInitCd
//
// But : Verifier l'etat d'init du driver midi
// Entr<74>es : neant
// Sorties : True ou False suivant l'etat
//------------------------------------------------------------
SndBool SND_CALL SND_fn_bTestInitCD(void)
{
#ifndef DISABLE_CD
return (stCDDriver.bCdDriverOk);
#else
return FALSE;
#endif //DISABLE_CD
}
//-----------------------------------------------------------
// SND_fn_iDesInitCd
//
// But : Realiser la desnit bas niveau du driver midi
// Entr<74>es : neant
// Sorties : neant
//------------------------------------------------------------
void SND_CALL SND_fn_vDesInitCD(void)
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
if (hCDThread)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_DESINITCD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDClose,"PostThreadMessage Desinit");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
CloseHandle(hCDThread);
}
#endif //DISABLE_CD
}
#ifndef DISABLE_CD
//-----------------------------------------------------------
// SND_fn_iDesInitCdThread
//
// But : Realiser la desnit bas niveau du driver midi
// Entr<74>es : neant
// Sorties : neant
//------------------------------------------------------------
void SND_fn_vDesInitCDThread(void)
{
int i;
MCIERROR mciReturn;
for (i=0;i<iNbCdTracks;i++)
{
SND_fn_bUnloadCDTrack(i);
}
// Desinit toutes pistes CD
for (i=0;i<NB_MAX_CD_TRACKS;i++)
{
stCDTracks[i].tmsfStartTrack = 0;
stCDTracks[i].tmsfEndTrack = 0;
stCDTracks[i].dwStartingFrame = 0;
stCDTracks[i].dwEndingFrame = 0;
stCDTracks[i].dwStartLoopingFrame = 0;
stCDTracks[i].dwEndLoopingFrame = 0;
}
// Desinit piste CD active
stActiveCDTrack.bPaused = FALSE;
stActiveCDTrack.bActive = FALSE;
stActiveCDTrack.bLoop = FALSE;
stActiveCDTrack.lVoice = NO_CD_VOICE;
stActiveCDTrack.pfnSoundCallback= NULL;
stActiveCDTrack.lParSoundCallback=0;
stActiveCDTrack.pstSoundParam = NULL;
stActiveCDTrack.lPrio = 0;
if (stCDDriver.bCdDriverOk)
{
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_CLOSE,MCI_WAIT,(DWORD)NULL))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDClose,texte_erreur);
}
// On restaure l'ancienne valeur du volume CD
SND_fn_vSetCDValue(stCDDriver.iLastCDVolume);
SND_fn_iMixerDesInitCD();
}
stCDDriver.bCdDriverOk = FALSE;
DestroyWindow(hSndCdWnd);
}
#endif //DISABLE_CD
//-----------------------------------------------------------
// SND_fn_vRemoveCallbackCd
//
// But : Remettre a zero la callback de la ressource
// joue sur la voie voice
// Entr<74>es : voie jouee
// Sorties : neant
//------------------------------------------------------------
void SND_CALL SND_fn_vRemoveCallbackCD(long voice)
{
#ifndef DISABLE_CD
stActiveCDTrack.pfnSoundCallback= NULL;
stActiveCDTrack.lParSoundCallback= 0;
#endif //DISABLE_CD
}
//-----------------------------------------------------------
// SND_fn_bSetParamCd
//
// But : Faire varier en temps reel les parametres
// de la ressource midi
// Entr<74>es : voie jouee, parametres sonores
// Sorties : TRUE si maj possible FALSE sinon
//------------------------------------------------------------
SndBool SND_CALL SND_fn_bSetParamCD(long voice,SoundParam *par)
{
#ifndef DISABLE_CD
return (stActiveCDTrack.bActive);
#else
return FALSE;
#endif //DISABLE_CD
}
//-----------------------------------------------------------
// SND_fn_bTestIsPlayingCd
//
// But : Une ressource midi est-elle active
// Entr<74>es : voie jouee
// Sorties : Activite midi si voie bonne, FALSE sinon
//------------------------------------------------------------
SndBool SND_CALL SND_fn_bTestIsPlayingCD(long voice)
{
#ifndef DISABLE_CD
return (stActiveCDTrack.bActive);
#else
return FALSE;
#endif //DISABLE_CD
}
#ifndef DISABLE_CD
int nbCalled = 0;
//-----------------------------------------------------------
// SND_fn_lGetCurrentMode
//
// But : Renvoie la callback midi
// Entr<74>es : neant
// Sorties : Mode du device correspondant a la voie
//------------------------------------------------------------
void SND_fn_vCloseCDDoor()
{
MCI_SET_PARMS set;
MCIERROR mciReturn;
if (mciReturn = mciSendCommand(stCDDriver.uiCdDeviceId,MCI_SET,MCI_WAIT|MCI_SET_DOOR_CLOSED,(DWORD)(LPVOID)&set))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDSet,texte_erreur);
}
}
//-----------------------------------------------------------
// SND_fn_lGetCdTrack
//
// But : Renvoie la voie bas niveau sur laquelle
// est chargee une ressource
// Entr<74>es : Id de la ressource
// Sorties : voie bas niveau si resource chargee, NO_CD_VOICE sinon
//------------------------------------------------------------
long SND_fn_lGetCdTrack(tdxId Id)
{
int i = 0;
while ( (stCDTracks[i].uCDTrack.pstPtr) &&
(stCDTracks[i].uCDTrack.pstPtr->Id != Id) &&
(++i < NB_MAX_CD_TRACKS));
if ((i == NB_MAX_CD_TRACKS) || ((!i)&&(!stCDTracks[i].uCDTrack.pstPtr)))
return (NO_CD_VOICE);
else
return (i);
}
//-----------------------------------------------------------
// SND_fn_lGetActiveTrack
//
// But : Renvoie la voie active
// Entr<74>es : neant
// Sorties : voie bas niveau active, NO_CD_VOICE sinon
//------------------------------------------------------------
long SND_fn_lGetActiveCdTrack()
{
return (stActiveCDTrack.lVoice);
}
//-----------------------------------------------------------
// SND_fn_lGetCurrentMode
//
// But : Renvoie la callback midi
// Entr<74>es : neant
// Sorties : Mode du device correspondant a la voie
//------------------------------------------------------------
long SND_fn_lGetCurrentCdMode()
{
MCI_STATUS_PARMS status;
MCIERROR mciReturn;
if (stCDDriver.bCdDriverOk)
{
// Mode actuel de la piste
status.dwItem = MCI_STATUS_MODE;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0);
}
return(status.dwReturn);
}
else
return (0);
}
//-----------------------------------------------------------
// SND_fn_lGetCDLength
//
// But : Renvoie la longueur totale d'un CD
// Entr<74>es : neant
// Sorties : longueur totale du CD
//------------------------------------------------------------
long SND_fn_lGetCDLength()
{
MCI_STATUS_PARMS status;
MCIERROR mciReturn;
if (stCDDriver.bCdDriverOk)
{
// Mode actuel de la piste
status.dwItem = MCI_STATUS_LENGTH;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0);
}
return(status.dwReturn);
}
else
return (0);
}
//-----------------------------------------------------------
// SND_fn_l_GetCurrentPosition
//
// But : Renvoie la position courante de lecture
// de la voie active
// Entr<74>es : neant
// Sorties : position en millisecondes
//------------------------------------------------------------
long SND_fn_lGetCurrentCdPosition()
{
MCI_STATUS_PARMS status;
MCIERROR mciReturn;
// Mode actuel de la piste
status.dwItem = MCI_STATUS_MODE;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0);
}
if ((status.dwReturn == MCI_MODE_PLAY)||(status.dwReturn == MCI_MODE_STOP))
{
// Si la piste est en mode play ou en pause
status.dwItem = MCI_STATUS_POSITION;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0);
}
return (status.dwReturn);
}
else return (0);
}
//-----------------------------------------------------------
// SND_ulGetCDTrackLengthInMs
//
// But : Calcule la duree exacte de la piste en millisecondes
// Entr<74>es : La voie active
// Sorties : La position en tmsf
//------------------------
unsigned long SND_fn_ulGetCDTrackLengthInMs(unsigned long ulVoice)
{
unsigned long ulTrackLength = 0, debut = 0, fin = 0, ulRealLength;
unsigned long debutLoop = 0, finLoop = 0;
debut = SND_TMSF_MS(stCDTracks[ulVoice].dwStartingFrame);
fin = SND_TMSF_MS(stCDTracks[ulVoice].dwEndingFrame);
debutLoop = SND_TMSF_MS(stCDTracks[ulVoice].dwStartLoopingFrame);
finLoop = SND_TMSF_MS(stCDTracks[ulVoice].dwEndLoopingFrame);
ulTrackLength = SND_TMSF_MS(stCDTracks[ulVoice].tmsfEndTrack);
if (fin)
if (debut)
ulRealLength = fin - debut;
else
ulRealLength = fin;
else
if (debut)
ulRealLength = ulTrackLength - debut;
else
ulRealLength = ulTrackLength;
if (stActiveCDTrack.bLoop && stActiveCDTrack.iNbLoops > 0)
{
if (debutLoop && finLoop)
ulRealLength += (stActiveCDTrack.iNbLoops) * (finLoop - debutLoop);
else
if (debutLoop)
ulRealLength += (stActiveCDTrack.iNbLoops) * (fin - debutLoop);
else
ulRealLength += (stActiveCDTrack.iNbLoops) * (finLoop - debut);
}
return (ulRealLength);
}
//-----------------------------------------------------------
// SND_fn_ulInitFadeCD
//
// But : Initialise les variables de fading
// Entr<74>es :
// Sorties :
//------------------------
void SND_fn_ulInitFadeCD( unsigned long ulFadeInDuration,
unsigned long ulFadeOutDuration)
{
lNbIterFadeIn = VOL_MAX_CD;
lNbIterFadeOut = VOL_MAX_CD;
if (ulFadeInDuration+ulFadeOutDuration < stActiveCDTrack.ulTrackLengthInMs)
{
bCDFadeIn = (SndBool)ulFadeInDuration;
bCDFadeOut = (SndBool)ulFadeOutDuration;
if (bCDFadeIn)
{
ulTimerPeriodFadeIn = ulFadeInDuration / lNbIterFadeIn;
ulCountDownFadeIn = 0;
ucFacteurVolume = 0;
// init du timer cross-fade
uiTimerCDFadeIn = timeSetEvent(ulTimerPeriodFadeIn,10,(LPTIMECALLBACK)SND_fn_lCDTimerIn,(DWORD)0,TIME_PERIODIC);
}
if (bCDFadeOut)
{
ulTimerPeriodFadeOut = ulFadeOutDuration / lNbIterFadeIn;
ulCountDownFadeOut = 0;
if (!bCDFadeIn)
{
ucFacteurVolume = VOL_MAX_CD;
}
// init du timer cross-fade
uiTimerCDFadeOut = timeSetEvent(ulTimerPeriodFadeOut,10,(LPTIMECALLBACK)SND_fn_lCDTimerOut,(DWORD)0,TIME_PERIODIC);
}
SND_fn_vSetCDValue(ucFacteurVolume);
}
else
{
SND_fn_vSetCDValue(VOL_MAX_CD);
SND_fn_vDisplayError(E_uwSndCDFade,"Bad Fading Parameters");
}
}
//-----------------------------------------------------------
// SND_fn_dwCalculateFrom
//
// But : Calcule le point de depart du play
// Entr<74>es : La voie active
// Sorties : La position en tmsf
//------------------------------------------------------------
DWORD SND_fn_dwCalculateFrom(long lVoice)
{
DWORD dwFrom = 0;
tdstCDTrack * pstActiveCDTrack = &stCDTracks[lVoice];
// ce n'est pas le premier tour de boucle
if (stActiveCDTrack.iNbLoops < pstActiveCDTrack->iNbLoops)
{
// le debut de boucle est different de zero
if (pstActiveCDTrack->dwStartLoopingFrame)
dwFrom = pstActiveCDTrack->dwStartLoopingFrame;
else
// le debut de boucle est egal a zero
if (pstActiveCDTrack->dwStartingFrame)
dwFrom = pstActiveCDTrack->dwStartingFrame;
}
else
// premier tour
if (pstActiveCDTrack->dwStartingFrame)
dwFrom = pstActiveCDTrack->dwStartingFrame;
dwFrom |= pstActiveCDTrack->tmsfStartTrack;
return dwFrom;
}
//-----------------------------------------------------------
// SND_fn_dwCalculateTo
//
// But :
// But : Calcule le point de fin du play
// Entr<74>es : La voie active
// Sorties : La position en tmsf
//------------------------------------------------------------
DWORD SND_fn_dwCalculateTo(long lVoice)
{
DWORD dwTo = 0;
tdstCDTrack * pstActiveCDTrack = &stCDTracks[lVoice];
// cas du dernier tour de boucle, l'indice est a zero
if (!stActiveCDTrack.iNbLoops)
{
// on finit la lecture soit sur la fin de trame, soit sur la fin de piste
if (pstActiveCDTrack->dwEndingFrame)
dwTo = pstActiveCDTrack->dwEndingFrame;
else
dwTo = pstActiveCDTrack->tmsfEndTrack;
}
else
// cas des n-1 premiers tours, on boucle sur la fin de bouclage
if (pstActiveCDTrack->dwEndLoopingFrame)
dwTo = pstActiveCDTrack->dwEndLoopingFrame;
else
// pas de fin de bouclage, on boucle sur la fin de trame ou de piste
if (pstActiveCDTrack->dwEndingFrame)
dwTo = pstActiveCDTrack->dwEndingFrame;
else
dwTo = pstActiveCDTrack->tmsfEndTrack;
dwTo |= pstActiveCDTrack->tmsfStartTrack;
return dwTo;
}
#endif //DISABLE_CD
//-----------------------------------------------------------
// SND_fn_lPlayCD
//
// But : Joue la ressource CD res
// Entr<74>es : La ressource, parametres son, la priorite et
// la callback
// Sorties : voie allouee pour jouee la ressource
//------------------------------------------------------------
long SND_CALL SND_fn_lPlayCD(tduRefRes res,SoundParam *par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback)
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
if (stCDDriver.bCdDriverOk)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
dw_a5_Params[0] = (DWORD)&res;
dw_a5_Params[1] = (DWORD)par;
dw_a5_Params[2] = (DWORD)prio;
dw_a5_Params[3] = (DWORD)fn_callback;
dw_a5_Params[4] = (DWORD)par_callback;
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_PLAYCD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDPlay,"PostThreadMessage");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
// dans ce cas, on retourne le numero de voie dans dw_a5_Params[0]
return (dw_a5_Params[0] | OFFSET_CD_VOICE);
}
else
#endif //DISABLE_CD
return (C_PLAY_FAILED);
}
#ifndef DISABLE_CD
//-----------------------------------------------------------
// SND_fn_lPlayCD
//
// But : Joue la ressource CD res
// Entr<74>es : La ressource, parametres son, la priorite et
// la callback
// Sorties : voie allouee pour jouee la ressource
//------------------------------------------------------------
long SND_fn_lPlayCDThread(tduRefRes res,SoundParam *par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback)
{
MCIERROR mciReturn;
long lVoice = 0,lIndexVoice;
MCI_PLAY_PARMS play;
if (stCDDriver.bCdDriverOk)
{
// ceci correspond au premier play d'une piste bouclante
if (stActiveCDTrack.lVoice == NO_CD_VOICE)
{
lVoice = SND_fn_lGetCdTrack(res.pstPtr->Id);
debut:
lIndexVoice = SND_fn_lGetCdTrack(res.pstPtr->Id);
// on recharge la ressource au cas ou elle aurait ete modifi<66>e par l'editeur
if (!SND_fn_bLoadCDTrackThread(res.pstPtr,lIndexVoice))
return (C_PLAY_FAILED);
stActiveCDTrack.bLoop = stCDTracks[lIndexVoice].bLoop;
stActiveCDTrack.iNbLoops = stCDTracks[lIndexVoice].iNbLoops;
stActiveCDTrack.lIndexVoice = lIndexVoice;
stActiveCDTrack.lVoice = lVoice;
stActiveCDTrack.bActive = TRUE;
stActiveCDTrack.bPaused = FALSE;
stActiveCDTrack.lPrio = prio;
stActiveCDTrack.pstSoundParam = par;
stActiveCDTrack.pfnSoundCallback=fn_callback;
stActiveCDTrack.lParSoundCallback=par_callback;
stActiveCDTrack.ulTrackLengthInMs = SND_fn_ulGetCDTrackLengthInMs(lIndexVoice);
}
else
{
// on a un ressource bouclante qui en est a son deuxieme tout minimum
if ((stActiveCDTrack.bActive && stActiveCDTrack.bLoop)&&
(stActiveCDTrack.iNbLoops != stCDTracks[stActiveCDTrack.lIndexVoice].iNbLoops))
lVoice = stActiveCDTrack.lVoice;
// on a une ressource pas bouclante mais il y a eu un play sans stop de la ressource precedente
else
{
// on doit reallouer la meme voix pour la ressource suivante
lVoice = stActiveCDTrack.lVoice;
SND_fn_vStopCDThread(stActiveCDTrack.lVoice);
goto debut;
}
}
play.dwCallback = (DWORD)hSndCdWnd;
if (stCDDriver.ucState == CD_STATE_ALL_TRACKS)
{
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_PLAY,MCI_NOTIFY,(DWORD)(LPVOID)&play))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDPlay,texte_erreur);
return (C_PLAY_FAILED);
}
}
else
{
play.dwFrom = SND_fn_dwCalculateFrom(stActiveCDTrack.lIndexVoice);
play.dwTo = SND_fn_dwCalculateTo(stActiveCDTrack.lIndexVoice);
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_PLAY,MCI_FROM|MCI_TO|MCI_NOTIFY,(DWORD)(LPVOID)&play))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDPlay,texte_erreur);
return (C_PLAY_FAILED);
}
}
return (lVoice | OFFSET_CD_VOICE);
}
else
return (C_PLAY_FAILED);
}
//-----------------------------------------------------------
// SND_fn_lPlayCDWithFade
//
// But : Joue la ressource CD res avec un fade
// Entr<74>es : La ressource, parametres son, la priorite et
// la callback
// Sorties : voie allouee pour jouee la ressource
//------------------------------------------------------------
long SND_CALL SND_fn_lPlayCDWithFade(tduRefRes res,SoundParam *par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback,unsigned long ulFadeIn,unsigned long ulFadeOut)
{
long result;
result = SND_fn_lPlayCD(res,par,prio,fn_callback,par_callback);
SND_fn_ulInitFadeCD(ulFadeIn,ulFadeOut);
return (result);
}
#endif //DISABLE_CD
//-----------------------------------------------------------
// SND_fn_vStopCd
//
// But : Stopper une voie
// Entr<74>es : la voie a stopper
// Sorties : neant
//------------------------------------------------------------
void SND_CALL SND_fn_vStopCD(long voice)
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
dw_a5_Params[0] = (DWORD)voice;
if (stCDDriver.bCdDriverOk)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_STOPCD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDStop,"PostThreadMessage Resume");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
}
#endif //DISABLE_CD
}
#ifndef DISABLE_CD
//-----------------------------------------------------------
// SND_fn_vStopCdThread
//
// But : Stopper une voie
// Entr<74>es : la voie a stopper
// Sorties : neant
//------------------------------------------------------------
void SND_fn_vStopCDThread(long voice)
{
MCIERROR mciReturn;
MCI_GENERIC_PARMS stop;
SECURITY_ATTRIBUTES sa;
long lRealVoice = voice & MASK_OFFSET_CD_VOICE;
if ((stCDDriver.bCdDriverOk) && (lRealVoice < NB_MAX_CD_TRACKS))
{
stop.dwCallback = (DWORD)hSndCdWnd;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STOP,MCI_WAIT,(DWORD)NULL))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStop,texte_erreur);
}
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
dw_a2_threadParams[0] = (DWORD)stActiveCDTrack.pfnSoundCallback;
dw_a2_threadParams[1] = (DWORD)stActiveCDTrack.lParSoundCallback;
if (!(hCDThreadCallBack = CreateThread(&sa,0,(LPTHREAD_START_ROUTINE)SND_fn_iCDThreadCallBack,(LPVOID)dw_a2_threadParams,0,&dwCDThreadIdCallBack)))
SND_fn_vDisplayError(E_uwSndCDCreateThread,"");
// Desinit piste CD active
stActiveCDTrack.bPaused = FALSE;
stActiveCDTrack.bActive = FALSE;
stActiveCDTrack.bLoop = FALSE;
stActiveCDTrack.lVoice = NO_CD_VOICE;
stActiveCDTrack.pstSoundParam = NULL;
stActiveCDTrack.lPrio = 0;
}
}
//-----------------------------------------------------------
// SND_fn_vStopCdWithFade
//
// But : Stopper une voie en faisant un fade
// Entr<74>es : la voie a stopper
// Sorties : neant
//------------------------------------------------------------
void SND_CALL SND_fn_vStopCDWithFade(long voice,unsigned long ulFadeOutDuration)
{
lNbIterFadeOut = SND_fn_dwGetCDValue();
bCDFadeOut = (SndBool)ulFadeOutDuration;
if (lNbIterFadeOut)
ulTimerPeriodFadeOut = ulFadeOutDuration / lNbIterFadeOut;
else
ulTimerPeriodFadeOut = 100;
ulCountDownFadeOut = 0;
// Si le timer etait deja programme pour un fade out alors, on le reprogramme
// on passe un parametre special pour la callback FADE_AND_STOP_CD
if (uiTimerCDFadeOut != 0)
timeKillEvent(uiTimerCDFadeOut);
uiTimerCDFadeOut = timeSetEvent(ulTimerPeriodFadeOut,10,(LPTIMECALLBACK)SND_fn_lCDTimerOut,(DWORD)FADE_AND_STOP_CD,TIME_PERIODIC);
stActiveCDTrack.ulTrackLengthInMs = ulFadeOutDuration;
}
#endif //DISABLE_CD
//-----------------------------------------------------------
// SND_fn_vPauseCd
//
// But : Pauser une voie
// Entr<74>es : la voie a pauser
// Sorties : true,false
//------------------------------------------------------------
void SND_CALL SND_fn_vPauseCD(long voice)
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
dw_a5_Params[0] = (DWORD)voice;
if (stCDDriver.bCdDriverOk)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_PAUSECD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDPlay,"PostThreadMessage Pause");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
}
#endif //DISABLE_CD
}
#ifndef DISABLE_CD
//-----------------------------------------------------------
// SND_fn_vPauseCdThread
//
// But : Pauser une voie
// Entr<74>es : la voie a pauser
// Sorties : true,false
//------------------------------------------------------------
void SND_fn_vPauseCDThread(long voice)
{
MCIERROR mciReturn;
MCI_GENERIC_PARMS pause;
if (stCDDriver.bCdDriverOk)
{
pause.dwCallback = (DWORD)hSndCdWnd;
// if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STOP,MCI_NOTIFY,(DWORD)&pause))
// on sauve la position avant la pause
stActiveCDTrack.lPausePos = SND_fn_lGetCurrentCdPosition();
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_PAUSE,MCI_WAIT,(DWORD)&pause))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStop,texte_erreur);
return;
}
stActiveCDTrack.bPaused = TRUE;
}
}
#endif //DISABLE_CD
//-----------------------------------------------------------
// SND_fn_vResumeCd
//
// But : Resumer une voie
// Entr<74>es : la voie a resumer
// Sorties : True,false
//------------------------------------------------------------
void SND_CALL SND_fn_vResumeCD(long voice)
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
dw_a5_Params[0] = (DWORD)voice;
if (stCDDriver.bCdDriverOk)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_RESUMECD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDPlay,"PostThreadMessage Resume");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
}
#endif //DISABLE_CD
}
#ifndef DISABLE_CD
//-----------------------------------------------------------
// SND_fn_vResumeCd
//
// But : Resumer une voie
// Entr<74>es : la voie a resumer
// Sorties : True,false
//------------------------------------------------------------
void SND_fn_vResumeCDThread(long voice)
{
MCIERROR mciReturn;
MCI_PLAY_PARMS playresume;
if (stCDDriver.bCdDriverOk)
{
playresume.dwCallback = (DWORD)hSndCdWnd;
if (stActiveCDTrack.bPaused)
if (stCDDriver.ucState == CD_STATE_ALL_TRACKS)
{
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_PLAY,MCI_NOTIFY,(DWORD)(LPVOID)&playresume))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDPlay,texte_erreur);
return;
}
}
else
{
playresume.dwTo = SND_fn_dwCalculateTo(stActiveCDTrack.lVoice);
// on restaure la position sauve lors du pause
playresume.dwFrom = stActiveCDTrack.lPausePos;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_PLAY,MCI_FROM|MCI_TO|MCI_NOTIFY,(DWORD)(LPVOID)&playresume))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDPlay,texte_erreur);
return;
}
/*
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_RESUME,MCI_NOTIFY,(DWORD)(LPVOID)&playresume))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDPlay,texte_erreur);
}*/
}
stActiveCDTrack.bPaused = FALSE;
}
}
//-----------------------------------------------------------
// SND_fn_vNextCDTrack
//
// But : passe a la voie suivante
// Entr<74>es : neant
// Sorties : Id de la track suivante
//------------------------------------------------------------
long SND_CALL SND_fn_lNextCDTrack()
{
HANDLE hEventSynchro;
if (stCDDriver.bCdDriverOk)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_NEXTTRACKCD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDPlay,"PostThreadMessage");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
// dans ce cas, on retourne le numero de voie dans dw_a5_Params[0]
return (dw_a5_Params[0]);
}
else
return (0);
}
//-----------------------------------------------------------
// SND_fn_vNextCDTrack
//
// But : passe a la voie suivante
// Entr<74>es : neant
// Sorties : Id de la track suivante
//------------------------------------------------------------
long SND_fn_lNextCDTrackThread()
{
MCIERROR mciReturn;
MCI_SEEK_PARMS seek;
MCI_STATUS_PARMS status;
MCI_PLAY_PARMS play;
DWORD dwTrackNumber;
if (stCDDriver.bCdDriverOk)
{
status.dwItem = MCI_STATUS_CURRENT_TRACK;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)(LPVOID)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
return (0L);
}
seek.dwCallback = (DWORD)hSndCdWnd;
dwTrackNumber = (status.dwReturn+1) % SND_fn_lGetNbCdTracks();
seek.dwTo = MCI_MAKE_TMSF(dwTrackNumber,0,0,0);
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_SEEK,MCI_TO|MCI_NOTIFY,(DWORD)&seek))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDSeek,texte_erreur);
return (0L);
}
play.dwCallback = (DWORD)hSndCdWnd;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_PLAY,MCI_NOTIFY,(DWORD)&play))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDPlay,texte_erreur);
return (0L);
}
return (dwTrackNumber);
}
else
return (0L);
}
//-----------------------------------------------------------
// SND_fn_bLoadCdTrack
//
// But : Charge une ressource CD, a partir du block ressource
// au depart ou lorsqu'elle est modifi<66>e
// Entr<74>es : Le block ressource et le nom du fichier midi
// Sorties : true,false
//------------------------------------------------------------
SndBool SND_fn_bLoadCDTrack(tdstBlockResourceMem * pstPtr,int numTrack)
{
HANDLE hEventSynchro;
if (stCDDriver.bCdDriverOk)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
dw_a5_Params[0] = (DWORD)pstPtr;
dw_a5_Params[1] = (DWORD)numTrack;
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_LOADCD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDLoadTrack,"PostThreadMessage");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
// dans ce cas, on retourne le numero de voie dans dw_a5_Params[0]
return (dw_a5_Params[0]);
}
else
return (FALSE);
}
//-----------------------------------------------------------
// SND_fn_bLoadCdTrackThread
//
// But : Charge une ressource CD, a partir du block ressource
// au depart ou lorsqu'elle est modifi<66>e
// Entr<74>es : Le block ressource et le nom du fichier midi
// Sorties : true,false
//------------------------------------------------------------
SndBool SND_fn_bLoadCDTrackThread(tdstBlockResourceMem * pstPtr,int numTrack)
{
MCI_STATUS_PARMS status;
MCIERROR mciReturn;
DWORD dwS,dwSL,dwFL,dwF;
status.dwTrack = pstPtr->uRes.stCD.wTrackId;
if (stCDDriver.lNbCdTracks >= (long)status.dwTrack)
{
//-----------------------------------------------------------------
// Calcul du debut et de la fin de la piste stockes dans stCDTrack
//-----------------------------------------------------------------
stCDTracks[numTrack].tmsfStartTrack = SND_MAKE_TMSF(status.dwTrack,0,0,0);
status.dwCallback = status.dwReturn = 0;
status.dwItem = MCI_STATUS_LENGTH;
if (mciReturn=mciSendCommand(stCDDriver.uiCdDeviceId,MCI_STATUS,MCI_STATUS_ITEM|MCI_TRACK,(DWORD) (LPMCI_STATUS_PARMS)&status))
{
mciGetErrorString(mciReturn,texte_erreur,sizeof(texte_erreur));
SND_fn_vDisplayError(E_uwSndCDStatus,texte_erreur);
}
else
stCDTracks[numTrack].tmsfEndTrack = status.dwReturn << 8 | status.dwTrack;
//-----------------------------------------------------------------
// Sauvegarde des bornes du play global
//-----------------------------------------------------------------
if (pstPtr->uRes.stCD.ulStartingFrame)
stCDTracks[numTrack].dwStartingFrame = pstPtr->uRes.stCD.ulStartingFrame | stCDTracks[numTrack].tmsfStartTrack;
else
stCDTracks[numTrack].dwStartingFrame = stCDTracks[numTrack].tmsfStartTrack;
if (pstPtr->uRes.stCD.ulEndingFrame)
stCDTracks[numTrack].dwEndingFrame = pstPtr->uRes.stCD.ulEndingFrame | stCDTracks[numTrack].tmsfStartTrack;
else
stCDTracks[numTrack].dwEndingFrame = stCDTracks[numTrack].tmsfEndTrack;
stCDTracks[numTrack].dwStartLoopingFrame = pstPtr->uRes.stCD.ulStartLoop | stCDTracks[numTrack].tmsfStartTrack;
stCDTracks[numTrack].dwEndLoopingFrame = pstPtr->uRes.stCD.ulEndLoop | stCDTracks[numTrack].tmsfStartTrack;
dwS = SND_TMSF_MS(stCDTracks[numTrack].dwStartingFrame);
dwSL = SND_TMSF_MS(stCDTracks[numTrack].dwStartLoopingFrame);
dwFL = SND_TMSF_MS(stCDTracks[numTrack].dwEndLoopingFrame);
dwF = SND_TMSF_MS(stCDTracks[numTrack].dwEndingFrame);
if ((dwSL < dwS)||(dwSL > dwFL))
stCDTracks[numTrack].dwStartLoopingFrame = 0;
if ((dwFL < dwSL)||(dwFL > dwF))
stCDTracks[numTrack].dwEndLoopingFrame = 0;
//-----------------------------------------------------------------
// Sauvegarde des parametres utiles a la gestion de la piste active
//-----------------------------------------------------------------
// on sauve une reference a la ressource dans la liste des piste midi
stCDTracks[numTrack].uCDTrack.pstPtr = pstPtr;
stCDTracks[numTrack].bLoop = pstPtr->uRes.stCD.bLoop;
stCDTracks[numTrack].iNbLoops = pstPtr->uRes.stCD.iNbLoops;
return TRUE;
}
else
{
//SND_fn_vDisplayError(E_uwSndCDNbTracks,MSG_ERR_BAD_CD_ID_TRACK);
return FALSE;
}
}
//-----------------------------------------------------------
// SND_fn_bUnloadCdTrack
//
// But : Decharge une piste midi, a partir de la voie
// Entr<74>es : La voie a decharger
// Sorties : true,false
//------------------------------------------------------------
SndBool SND_fn_bUnloadCDTrack(int i)
{
return TRUE;
}
#endif //DISABLE_CD
//#endif //CD_MCI
//waitforsingleobject
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
// GESTION DU MIXER CD
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
int SND_fn_iMixerInitCD()
{
#ifndef DISABLE_CD
uiNbrMixersCD = mixerGetNumDevs(); //OK
if (uiNbrMixersCD == 0)
{
SND_fn_vDisplayError(E_uwSndMixerNoMixer,"");
return 1;
}
if(mixerGetID((HMIXEROBJ)0,&mixerIdentifierCD,MIXER_OBJECTF_MIXER) !=MMSYSERR_NOERROR)
{
SND_fn_vDisplayError(E_uwSndMixerNoId,"");
return 1;
}
if(mixerOpen(&hMixerCD,mixerIdentifierCD,0,0,MIXER_OBJECTF_MIXER/* MIXER_OBJECTF_HWAVEOUT*/) != MMSYSERR_NOERROR)
{
SND_fn_vDisplayError(E_uwSndMixerOpen,"");
return 1;
}
if(mixerGetDevCaps((UINT)hMixerCD,&mixerCapsCD,sizeof(MIXERCAPS)) != MMSYSERR_NOERROR)
{
SND_fn_vDisplayError(E_uwSndMixerCapacities,"");
return 1;
}
dwNbrAudioLinesCD = mixerCapsCD.cDestinations;
//==============
// MIXERLINE CD
//==============
mixerLineCD.cbStruct = sizeof(MIXERLINE);
mixerLineCD.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
if (mixerGetLineInfo((HMIXEROBJ)hMixerCD,&mixerLineCD,MIXER_GETLINEINFOF_COMPONENTTYPE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
{
//return MIXER_ERR_GETLINEINFOCD;
CDControlAvailable = FALSE;
}
else
{
CDControlAvailable = TRUE;
}
//=====================
// MIXERLINECONTROL CD
//=====================
mixerLineControlsCD.cbStruct = sizeof(MIXERLINECONTROLS);
mixerLineControlsCD.dwLineID = mixerLineCD.dwLineID;
mixerLineControlsCD.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mixerLineControlsCD.cControls = 1;
mixerLineControlsCD.cbmxctrl = sizeof(MIXERCONTROL);
mixerLineControlsCD.pamxctrl =(MIXERCONTROL *) &mixerControlCD;
if(mixerGetLineControls((HMIXEROBJ)hMixerCD,&mixerLineControlsCD,MIXER_GETLINECONTROLSF_ONEBYTYPE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
{
// return MIXER_ERR_GETLINECONTROLSCD;
CDControlAvailable = FALSE;
}
else
{
CDControlAvailable = TRUE;
}
//============================
// MIXERLINECONTROLDETAILS CD
//============================
mixerControlDetailsCD.cbStruct = sizeof(MIXERCONTROLDETAILS);
mixerControlDetailsCD.dwControlID = mixerControlCD.dwControlID;
mixerControlDetailsCD.cChannels = 1/*mixerLineCD.cChannels 1*/;
mixerControlDetailsCD.cMultipleItems = mixerControlCD.cMultipleItems;
mixerControlDetailsCD.cbDetails =sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mixerControlDetailsCD.paDetails= &valeurCD;
#endif //DISABLE_CD
return 0;
}
DWORD SND_fn_dwGetCDMax()
{
#ifndef DISABLE_CD
return mixerControlCD.Bounds.dwMaximum;
#else
return 0;
#endif //DISABLE_CD
}
DWORD SND_fn_dwGetCDMin()
{
#ifndef DISABLE_CD
return mixerControlCD.Bounds.dwMinimum;
#else
return 0;
#endif //DISABLE_CD
}
//=======================================
//void SND_fn_dwGetCDValue(DWORD val)
//=======================================
// Positionne le volume du CD en %
// val entre 0 et 100
//=======================================
DWORD SND_fn_dwGetCDValue()
{
#ifndef DISABLE_CD
DWORD inc;
DWORD result;
if (CDControlAvailable)
{
inc = (SND_fn_dwGetCDMax()-SND_fn_dwGetCDMin())/100;
if(mixerGetControlDetails((HMIXEROBJ)hMixerCD,&mixerControlDetailsCD,MIXER_GETCONTROLDETAILSF_VALUE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
return 1;
result = (valeurCD.dwValue - SND_fn_dwGetCDMin())/inc;
//snd_assert(result>=0);
snd_assert(result<=100);
return result;
}
else
#endif //DISABLE_CD
return 0;
}
//=======================================
//void SND_fn_vSetCDValue(DWORD val)
//=======================================
// Positionne le volume du CD en %
// val entre 0 et 100
//=======================================
void SND_fn_vSetCDValue(DWORD val)
{
#ifndef DISABLE_CD
// val est en pourcentage
DWORD inc;
if (CDControlAvailable)
{
//snd_assert(val>=0);
snd_assert(val<=100);
inc = (SND_fn_dwGetCDMax()-SND_fn_dwGetCDMin())/100;
val = (val* inc) + SND_fn_dwGetCDMin();
snd_assert(val>=SND_fn_dwGetCDMin());
snd_assert(val<=SND_fn_dwGetCDMax());
valeurCD.dwValue = val;
if(mixerSetControlDetails((HMIXEROBJ)hMixerCD,&mixerControlDetailsCD,MIXER_SETCONTROLDETAILSF_VALUE|MIXER_OBJECTF_HMIXER) != MMSYSERR_NOERROR)
{
//return 1;
}
}
#endif //DISABLE_CD
}
BOOL SND_fn_bIsCDControlAvailable()
{
#ifndef DISABLE_CD
return CDControlAvailable;
#else
return FALSE;
#endif //DISABLE_CD
}
int SND_fn_iMixerDesInitCD()
{
#ifndef DISABLE_CD
if(mixerClose(hMixerCD) != MMSYSERR_NOERROR)
{
SND_fn_vDisplayError(E_uwSndMixerDesinit,"");
return 1;
}
#endif //DISABLE_CD
return 0;
}
/*--------------------------------------------------
relache-reprise a chaud des drives
---------------------------------------------------------*/
#define PAUSED_BY_RESTORE_RELEASE 2
void SND_CALL SND_fn_vReleaseDriverCDThread()
{
#ifndef DISABLE_CD
// si le Cd n'est pas deja en pause, on le pause mais pause type 2
if (! stActiveCDTrack.bPaused)
{
SND_fn_vPauseCDThread(stActiveCDTrack.lVoice);
stActiveCDTrack.bPaused = (BOOL)PAUSED_BY_RESTORE_RELEASE;
}
#endif //DISABLE_CD
}
void SND_CALL SND_fn_vReleaseDriverCD()
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
if (stCDDriver.bCdDriverOk && stActiveCDTrack.bActive)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_RELEASECD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDStop,"PostThreadMessage Release");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
}
#endif //DISABLE_CD
}
void SND_CALL SND_fn_vRestoreDriverCDThread()
{
#ifndef DISABLE_CD
// si le CD etait en pause du fait du release, on le relance
// sinon, il etait en pause, on reste en pause
if (stActiveCDTrack.bPaused == (BOOL)PAUSED_BY_RESTORE_RELEASE)
SND_fn_vResumeCDThread(stActiveCDTrack.lVoice);
#endif //DISABLE_CD
}
void SND_CALL SND_fn_vRestoreDriverCD()
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
if (stCDDriver.bCdDriverOk && stActiveCDTrack.bActive)
{
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_RESTORECD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDStop,"PostThreadMessage Restore");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
}
#endif //DISABLE_CD
}
//---------------------------------------------------------
// GetPos: retourne la position "th<74>orique" de la ressource
// exprim<69> en seconde depuis le d<>but
// diff<66>rent du temps absolu (car pitch, d<>rive..)
// Entr<74>e: voie concern<72>e
// Sortie: temps en S (SndReal)
//----------------------------------------------------------
SndReal SND_CALL SND_fn_rGetPosCDThread(long voie)
{
double dfCDTrackPos = 0.0;
#ifndef DISABLE_CD
dfCDTrackPos=(double)SND_fn_lGetCurrentCdPosition(voie & MASK_OFFSET_CD_VOICE) / 1000;
#endif
return (M_DoubleToRealSnd(dfCDTrackPos));
}
//---------------------------------------------------------
// GetPos: retourne la position "th<74>orique" de la ressource
// exprim<69> en seconde depuis le d<>but
// diff<66>rent du temps absolu (car pitch, d<>rive..)
// Entr<74>e: voie concern<72>e
// Sortie: temps en S (SndReal)
//----------------------------------------------------------
SndReal SND_CALL SND_fn_rGetPosCD(long voie)
{
#ifndef DISABLE_CD
HANDLE hEventSynchro;
if (stCDDriver.bCdDriverOk && stActiveCDTrack.bActive)
{
dw_a5_Params[0] = (DWORD)voie;
hEventSynchro = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!PostThreadMessage(dwCDThreadId,(UINT)SND_GETPOSCD_MSG,(WPARAM)dw_a5_Params,(LPARAM)hEventSynchro))
SND_fn_vDisplayError(E_uwSndCDStop,"Get Pos error");
WaitForSingleObject(hEventSynchro,INFINITE);
CloseHandle(hEventSynchro);
return (dw_a5_Params[0]);
}
else
return SND_C_POS_UNKNOWN;
#endif //DISABLE_CD
return SND_C_POS_UNKNOWN;
}
//---------------------------------------------------------
// GetLength: retourne la dur<75>e "th<74>orique" de la ressource
// exprim<69> en seconde (constant pour une ressource donn<6E>e)
// Entr<74>e: voie concern<72>e
// Sortie: dur<75>e en S (SndReal)
//----------------------------------------------------------
SndReal SND_CALL SND_fn_rGetLengthCD(long voie)
{
double dfCDTrackTime = 0.0;
#ifndef DISABLE_CD
dfCDTrackTime=(double)SND_fn_ulGetCDTrackLengthInMs(voie & MASK_OFFSET_CD_VOICE) / 1000;
#endif
return (M_DoubleToRealSnd(dfCDTrackTime));
//return SND_C_POS_UNKNOWN;
}
//-------------------------------------------------
// Fonction de synchro moteur
// ne sert <20> rien pour CD
//-------------------------------------------------
void SND_CALL SND_fn_vSynchroCD(void)
{
}
SndBool SND_CALL SND_fn_bCheckVersionResourceCD(tdstBlockResourceDisk* disk)
{
return TRUE;
}
SndBool SND_CALL SND_fn_bSetResourceStaticVolumeCD(tdstBlockResourceMem* pstRes,unsigned char ucVolume)
{
pstRes->ucVolume=ucVolume;
return TRUE;
}
// Partie de gestion de player de CD ouvert en partageable