/*
//////////////////////////////////////////////////////////
//  Module SNDTHEME:gestion des ressources THEME (melodies dynamigues
//////////////////////////////////////////////////////////
*/
 
#include "SNDinc.h"
 
#include "sndres.h"
#include "sndtheme.h"
#include "sndplay.h"
 
#ifndef NO_ACP_SOUND
#ifndef DISABLE_THEME
 
/*-----variavles locales*/
typedef struct active_theme_ active_theme;
struct active_theme_{
    SndBool_field_decl(bActive);            /*TRUE if voice is valid (themebeeing played)*/
    SndBool_field_decl(bSleeping);          /*TRUE when Outro has been played*/
    SndBool_field_decl(bTransAsked);        /*TRUE if transition to a new THEME asked*/
    SndBool_field_decl(bTransiting);        /*TRUE if transition if currently running (it no more impossible to avoid playing the future new theme)*/
    SndBool_field_decl(bOutroAsked);        /*TRUE if transition if currently running (it no more impossible to avoid playing the future new theme)*/
 
    tduRefRes       uCurrentThemeRes;   /*THEME ressource currently played*/
 
	hThemePart		hLoopingPart;		/*re-loop for 2° level loop (if any)*/
	long			lLoopingPartIndice;	/*indice of this part*/
	long			lNbLoopLeft;		/*number of loop remaining (set to NbLoops at first run)*/
 
	unsigned long	ulNbLoopDone;		/*number of main-loop*/

    hThemePart		hCurrentPart;		/*current part (the one mixed)*/
	long			lCurrentPartIndice;	/*indice of this part*/
    long            lVoice;             /*SNDPLAY voice associated with this theme*/
	hThemePart		hNextPart;			/*expected res-part (call to SetNextTransition); can be cancelled with a nex call to SetNextTransition*/
    long			lNextPartIndice;	/*indice od this part*/
    tduRefRes       uNextRes;			/*res for this part*/

 
    tduRefRes       uAskedThemeRes;     /*THEME asked for a transition (if any)*/
    tduRefRes       uGoingToThemeRes;   /*first resource part associated with this expected theme (INVALID_RES if theme is finishing)*/
    tdstThemePart   *pTransitingPart;   /*ptr onto part played just before uGoingToThemeRes part*/

    SND_td_pfn_vSoundCallback   pfnFctCallback;	/*client callback function; to be called on transitions*/
    long                        lParCallback;	/*parameter to be used with pfnFctCallback*/
    SndBool                     *pbValid;
 
	SoundParam		*pstParam;			/*current SoundParam for the Theme (last call to SetParamTheme)*/
	long			lSizeParam;			/*size of this SoundParam*/
};
 
static active_theme    g_stTheme;	/*current active THEME; there could be only 1 active THEME*/
 
static SndBool         g_bWorkingTheme=FALSE;	/*TRUE when a THEME is playing*/
 
/*
For the current part 
!if bActive==FALSE ->theme is not active
 
!if bActive=TRUE, uCurentThemeRes is currently beeing played 
!
!+if bTransiting==FALSE
!!    if lCurrentParInidce==-1, intro is currently beeing played
!!    otherwise, part ulCureentPartIndice is currently beeing played
!!otherwise
!!    transiting to new theme uGoingToThemeRes
!  
!uCurrentRes=low-level resource associated with ulCureentPartIndice
!lVoice=low-level voice associated
 
For the expected part 
!if bActive=TRUE, we plan to next part, or the appropiate bridge, or first part of next theme
!
!+if bTansiting==TRUE
!!+  if uGoingToThemeRes=INVALID,
!!!     we will stop
!!!  otherwise
!!!     1° part of theme uGoingToThemeRes will be played
!!
!!
!!otherwise
!!+if bTransAsked==TRUE 
!!!      
 
 
Evtx: jouer la theme x
Theme1:2 parts A et B bouclantes;bridge In I;bridge out vers theme 2=O1;vers theme 3=O3;defaut O
Theme2:3 parts a,b,c bouclantes;bridge In ?;pas de bridge out par defaut;bridge out vers themes ?
Theme3:n parts r,s... ;bridge In ?;bridge vers theme 2 O2
 
 
                    |   Evt1|                 Evt3 Evt2     |           |
                    |     ! |                   !   !       |           |
                    |   0 ! |<---- them 1 ------+---+-------|<--theme2->| 0
                    |     ! |                   !   !       |           |
                    |     ! | I . A . B . A . B ! B ! B . O1| a . b . c |
                    |     ! |   .   .   .   .   !   !   .   |   .   .   |
bActive             |  F  ! | T . T . T . T . T ! T ! T . T | T . T . T | F
lCurrentTheme       |  x  ! | 1 . 1 . 1 . 1 . 1 ! 1 ! 1 . 1 | 2 . 2 . 2 | x
lCurrentPartIndice  |  x  ! | -1. 0 . 1 . 0 . 1 ! 1 ! 1 . x | 0 . 1 . 2 | x
lNextPartIndice     |  x  ! | 0 . 1 . 0 . 1 . 0 ! x ! x . x | 1 . 2 . x | x
bTransAsked         |  x  ! | F . F . F . F . F ! T ! T . F | F . F . F | x
uThemeAsked         |  x  ! | x . x . x . x . x ! 3 ! 2 . x | x . x . x | x
bTransiting         |  x  ! | F . F . F . F . F ! F ! F . T | F . F . T | x
uGoingToThemeRes    |  x  ! | x . x . x . x . x ! x ! x . 2 | x . x .INV| x
                          P-1,0 S1  S0  S1  S0  SO2 SO1 Sa  Sb  Sc  SI
                          p-1   p0  p1  p0  p1          pO1 pa  pb  pc
 
                    |   Evt1|          Evt3    Evt2 |       |
                    |     ! |           !       !   |       |
                    |   0 ! |<--- them1 +-------+-->|<them3>|<--theme 2...
                    |     ! |           !       !   |       |
                    |     ! | I . A . B ! B . O3! O3| r . O2| a . b
                    |     ! |   .   .   !   .   !   |   .   |
bActive             |  F  ! | T . T . T ! T . T ! T | T . T | T . T ...
lCurrentTheme       |  x  ! | 1 . 1 . 1 ! 1 . 1 ! 1 | 3 . 3 | 2 . 2 ...
lCurrentPartIndice  |  x  ! | -1. 0 . 1 ! 1 . x ! x | 0 . x | 0 . 1 ...
lNextPartIndice     |  x  ! | 0 . 1 . 0 ! x . x ! x | 1 . x | 1 . 2 ...
bTransAsked         |  x  ! | F . F . F ! T . F ! T | T . F | F . F ...
uThemeAsked         |  x  ! | x . x . x ! 3 . x ! 2 ! 2 . x | x . x ...
bTransiting         |  x  ! | F . F . F ! F . T ! T | F . T | F . F ...
uGoingToThemeRes    |  x  ! | x . x . x ! x . 3 ! 3 | x . 2 | x . x ...
                          PI,A  SB  SA  SO3 Sr  x   SO2 Sa  Sb  Sc  SI
                          pI    pA  pB      p03     pr  pO2 pa  pb  pc
                            
 
                    |   Evt1|  Evt3         |      
                    |     ! |   !           |      
                    |   0 ! |<--+-them1---->|<-----them3...
                    |     ! |   !           |       
                    |     ! | I ! I . A . O3| r . s
                    |     ! |   !   .       !               
bActive             |  F  ! | T ! T . T . T | T . T ...
lCurrentTheme       |  x  ! | 1 ! 1 . 1 . 1 | 3 . 3 ...
lCurrentPartIndice  |  x  ! | -1! -1. 0 . x | 0 . 1 ...
lNextPartIndice     |  x  ! | 0 ! 0 . x . x | 1 . 2 ...
bTransAsked         |  x  ! | F ! T . T . F | F . F ...
uThemeAsked         |  x  ! | x ! 3 . 3 . x ! x . x ...
bTransiting         |  x  ! | F ! F . F . T | F . F ...
uGoingToThemeRes    |  x  ! | x ! x . x . 3 | x . x ...
                          PI,A  x   S03 Sr  Sr 
                          p-1       pA  pO3 pr  ps
 
 
                    |   Evt1|           |      
                    |     ! |           |      
                    |   0 ! |<-them1--->| 0
                    |     ! |           |       
                    |     ! | I . A . O | 
                    |     ! |   .       !               
bActive             |  F  ! | T . T . T | F...
lCurrentTheme       |  x  ! | 1 . 1 . 1 | x...
lCurrentPartIndice  |  x  ! | -1. 0 . x | x...
lNextPartIndice     |  x  ! | 0 . x . x | x...
bTransAsked         |  x  ! | F . F . F | x...
uThemeAsked         |  x  ! | x . x . x ! x...
bTransiting         |  x  ! | F . F . T | x...
uGoingToThemeRes    |  x  ! | x . x .INV| x...
                          PI,A  SO  SINV
                          pI    pA  pO
*/
 
/*----update field describing next part (use current part)*/
/*	update hNextPart and lNextPartIndice */
/*	use ulCurrentPartIndice,hCurrentPart,hLoopingPart,lNbLoopLeft*/
SndBool	raj_next_part(active_theme *theme)
{
    tdstTypeThemeMem  *pstThemeRes;
	hThemePart		hPart;
	int i; 
	SndBool			bFound=FALSE;
	long			lIndicePart;
	SndBool			bMainLoopEnded=FALSE;
 
    /*---find the next part*/
	/*
	if (theme->bOutroAsked)
	{
		theme->bOutroAsked=FALSE;
		theme->uNextRes=theme->uCurrentThemeRes.pstPtr->uRes.stTheme.pstPartOutro->uRes;

		return TRUE;
	}*/

	if (theme->bTransiting)
	{
		theme->bTransiting=FALSE;

		if (theme->uGoingToThemeRes.pstPtr==SND_C_RES_FANTOME_PTR)
		{/*theme is over*/
			theme->bSleeping=TRUE;
			return FALSE;
		}

		theme->uCurrentThemeRes=theme->uGoingToThemeRes;

		if (theme->bOutroAsked)
		{/*transition outro->1°part of new theme*/
			theme->bOutroAsked=FALSE;

			theme->lNextPartIndice=0;
			theme->hNextPart=SNDLST2_M_StaticGetFirstElement(&theme->uCurrentThemeRes.pstPtr->uRes.stTheme);
			theme->uNextRes=theme->hNextPart->uRes;

			return TRUE;
		}
	}

    pstThemeRes=&(theme->uCurrentThemeRes.pstPtr->uRes.stTheme);
 
	/*is there a second level loop ending?*/
	if ((theme->hCurrentPart->bLoopEnd) && (theme->lNbLoopLeft))
	{/*there is a second level loop*/
		theme->lNbLoopLeft--;
 
		if (theme->hLoopingPart)
		{
			theme->hNextPart=theme->hLoopingPart;
			theme->lNextPartIndice=theme->lLoopingPartIndice;
			theme->uNextRes=theme->hNextPart->uRes;
		}
		else
		{
			theme->hNextPart=SNDLST2_M_StaticGetFirstElement(pstThemeRes);
			theme->lNextPartIndice=0;
			theme->uNextRes=theme->hNextPart->uRes;
		}
	}
	else
	{/*no loop*/
		if (!theme->lNbLoopLeft)
			theme->hLoopingPart=NULL;
 
		/*no more loop*/
		theme->lNextPartIndice++;
 
		/*main loop?*/
		if ((unsigned long)theme->lNextPartIndice>=theme->uCurrentThemeRes.pstPtr->uRes.stTheme.ulNbParts)
		{/*yes, main loop*/
			if (theme->uCurrentThemeRes.pstPtr->uRes.stTheme.ulNbLoops!=C_THEME_MAINLOOP_INFINITE)
			{
				theme->ulNbLoopDone++;
				if (theme->ulNbLoopDone>=theme->uCurrentThemeRes.pstPtr->uRes.stTheme.ulNbLoops)
					bMainLoopEnded=TRUE;
			}

			if (bMainLoopEnded)
			{/*end of main-loop*/
				if (theme->uCurrentThemeRes.pstPtr->uRes.stTheme.pstPartOutro)
				{
					theme->bOutroAsked=TRUE;
					theme->bTransiting=TRUE;
					theme->uNextRes=theme->uCurrentThemeRes.pstPtr->uRes.stTheme.pstPartOutro->uRes;
				}
				else
				{
					theme->bSleeping=TRUE;
					return FALSE;
				}
				theme->uGoingToThemeRes=SND_RES_FANTOME;
			}
			else
			{/*re-loop*/
				theme->lNextPartIndice=pstThemeRes->ulStartLoop;
				SNDLST2_M_StaticGetElementNumber(pstThemeRes,theme->hNextPart,theme->lNextPartIndice,i);
				theme->uNextRes=theme->hNextPart->uRes;
 
				/*retourne-t-on a l'interieur d'une boucle interne*/
				hPart=theme->hNextPart;
				bFound=FALSE;
				lIndicePart=pstThemeRes->ulStartLoop;
				while (hPart)
				{
					if (hPart->bLoopStart)
					{
						bFound=TRUE;
						theme->hLoopingPart=hPart;
						theme->lLoopingPartIndice=lIndicePart;
						theme->lNbLoopLeft=theme->hLoopingPart->lNbLoops;
						break;
					}
					hPart=SNDLST2_M_StaticGetPrevElement(hPart);
					lIndicePart--;
					if (lIndicePart<0)
						break;
					if (hPart && hPart->bLoopEnd)
						break;
				}
			}
		}
		else
		{
			theme->hNextPart=SNDLST2_M_StaticGetNextElement(theme->hNextPart);
			theme->uNextRes=theme->hNextPart->uRes;
		}
	}
 
	/*debut de rebouclage interne ?*/
	if (theme->hNextPart->bLoopStart && !theme->hLoopingPart)
	{
		theme->hLoopingPart=theme->hNextPart;
		theme->lLoopingPartIndice=theme->lNextPartIndice;
		theme->lNbLoopLeft=theme->hLoopingPart->lNbLoops;
	}
 
	return TRUE;
}
 
/*--------- */
/*return TRUE if change theme by fade; FALSE if new part is chained*/
SndBool change_theme(active_theme *theme,tduRefRes new_theme)
{
	tdeTypeTransition transition;

	if (theme->bSleeping)
	{
		transition=TRANSITION_ATENDOFPART;
	}
	else
	{
		transition=theme->hCurrentPart->eTransition;
	}

	theme->bOutroAsked=FALSE;
	theme->bTransiting=TRUE;
	theme->bSleeping=FALSE;
	theme->uGoingToThemeRes=new_theme;
 
	if (!new_theme.pstPtr->uRes.stTheme.ulNbParts)
	{/*new theme is empty ->OUT*/
		theme->hNextPart=NULL;
		theme->lNextPartIndice=-1;
		theme->uNextRes=SND_RES_FANTOME;
        return FALSE;/*C_PLAY_FAILED;*/
	}
	
	/*init theme*/
	theme->hLoopingPart=NULL;
	theme->lLoopingPartIndice=-1;
	theme->lNbLoopLeft=-1;
	theme->ulNbLoopDone =0;
 
    /*---find the 1° part */
	theme->lNextPartIndice=0;
	theme->hNextPart=SNDLST2_M_StaticGetFirstElement(&new_theme.pstPtr->uRes.stTheme);
	if ((transition!=TRANSITION_OUTRO) || (!theme->uCurrentThemeRes.pstPtr->uRes.stTheme.pstPartOutro))
		theme->uNextRes=theme->hNextPart->uRes;
	else
	{
		theme->bOutroAsked=TRUE;
		theme->uNextRes=theme->uCurrentThemeRes.pstPtr->uRes.stTheme.pstPartOutro->uRes;
	}
 
	/*is it a start-loop part ?*/
	if (theme->hNextPart->bLoopStart)
	{
		theme->hLoopingPart=theme->hNextPart;
		theme->lLoopingPartIndice=theme->lNextPartIndice;
		theme->lNbLoopLeft=theme->hLoopingPart->lNbLoops;
	}

	switch (transition)
	{
		case TRANSITION_CROSSFADE:
			return TRUE;
			break;
		case TRANSITION_ATENDOFPART:
		case TRANSITION_OUTRO:
			return FALSE;
			break;
	}

	return FALSE;
}
 
/*theme_res=nouvelle ressource theme*/
void start_new_theme(active_theme *theme,tduRefRes theme_res)
{
    tdstTypeThemeMem   *pstThemeRes;
 
    pstThemeRes=&(theme_res.pstPtr->uRes.stTheme);
 
    theme->uCurrentThemeRes=theme_res;
    theme->bTransiting=FALSE;
    theme->bTransAsked=FALSE;
    theme->bOutroAsked=FALSE;
	theme->bSleeping=FALSE;
 
	if (!theme_res.pstPtr->uRes.stTheme.ulNbParts)
	{/*pas de sequence,->OUT*/
		theme->hCurrentPart=NULL;
        g_bWorkingTheme=FALSE;
        return ;/*C_PLAY_FAILED;*/
	}
	
	/*init du theme*/
	theme->hLoopingPart=NULL;
	theme->lLoopingPartIndice=-1;
	theme->lNbLoopLeft=-1;
	theme->ulNbLoopDone =0;

    /*---trouver le 1° part */
	theme->lCurrentPartIndice=0;
	theme->hCurrentPart=SNDLST2_M_StaticGetFirstElement(&theme_res.pstPtr->uRes.stTheme);
	theme->lNextPartIndice=0;
	theme->hNextPart=theme->hCurrentPart;
	theme->uNextRes=theme->hNextPart->uRes;

	/*debut de rebouclage interne ?*/
	if (theme->hCurrentPart->bLoopStart)
	{
		theme->hLoopingPart=theme->hCurrentPart;
		theme->lLoopingPartIndice=theme->lCurrentPartIndice;
		theme->lNbLoopLeft=theme->hLoopingPart->lNbLoops;
	}
 
    /*---trouver le prochain part*/
    raj_next_part(theme);
}
 
 
/*------- Fonction de transition*/
void SND_CALL fn_Transition(long par)
{
	active_theme *theme=(active_theme*)par;
	tduRefRes	NextRes;
 
    if (g_bWorkingTheme || !theme->bActive || theme->bSleeping)
        return;
 
	theme->lCurrentPartIndice=theme->lNextPartIndice;
	theme->hCurrentPart=theme->hNextPart;
 
	if (!raj_next_part(theme))
    /*if (!trans_theme(&theme))*/
    {/*le theme est mort (deriniere opart finie)*/
        //theme->bActive=FALSE;
        if (theme->pbValid!=NULL)
            theme->pbValid=FALSE;
        if (theme->pfnFctCallback!=NULL)
            (*(theme->pfnFctCallback))(theme->lParCallback);
    }
    else
    {
        /*_RPT2(_CRT_WARN,"->%d(%d)\n",theme.lCurrentPartIndice,theme.lNextPartIndice);*/
		NextRes=SND_fn_tduGetLowestResourceSnd(theme->uNextRes,theme->pstParam,TRUE);
 
        SND_fn_bSetNextTransitionSnd(theme->lVoice,NextRes);
    }
}
#endif /*DISABLE_THEME*/
 
/*---------------------------------------------------------------------*/
/*  pour debogage*/
/*  Retourne FALSE si theme non actif*/
/*  sinon: id_part=indice de la part en cours (0 à N)*/
/*      id_bridge=indice du bridge en cours*/
/*          THEMEPOSITION_BRIDGEIN si bridge in en cours*/
/*          THEMEPOSITION_NOBRIDGE si pas de bridge en cours*/
/*---------------------------------------------------------------------*/
SndBool SND_fn_bGetThemePosition(tduRefRes *current_theme,long* id_part,long* id_loop)
{
#ifndef DISABLE_THEME
	active_theme *theme=&g_stTheme;
 
    if (!theme->bActive)
        return FALSE;
 
	*current_theme=theme->uCurrentThemeRes;
	*id_part=theme->lCurrentPartIndice;
	*id_loop=theme->lNbLoopLeft;
	return TRUE;
#else
    return FALSE;
#endif
}
 
/*---------------------------------------------------------------------*/
/*  pour debogage*/
/*  Retourne FALSE si aucune transition demandee*/
/*  sinon: id_part=indice de la part en cours (0 à N)*/
/*      id_bridge=indice du bridge en cours*/
/*          THEMEPOSITION_BRIDGEIN si bridge in en cours*/
/*          THEMEPOSITION_NOBRIDGE si pas de bridge en cours*/
/*---------------------------------------------------------------------*/
SndBool SND_fn_bGetAskedTheme(tduRefRes *asked_theme,SndBool *transiting)
{
#ifndef DISABLE_THEME
	active_theme *theme=&g_stTheme;
 
    if (!theme->bActive || !theme->bTransAsked)
        return FALSE;
	
    *asked_theme=theme->uAskedThemeRes;
	*transiting=theme->bTransiting;
 
    return TRUE;
#else
	return FALSE;
#endif
}
 
/*-----------------------------------------------------*/
 
/*---------------------------------------------------------------------*/
/*  InitTheme: init theme module capabilities*/
/*---------------------------------------------------------------------*/
void SND_fn_vInitTheme(void)
{
#ifndef DISABLE_THEME
	active_theme *theme=&g_stTheme;
 
	theme->pstParam=NULL;
	theme->lSizeParam=0;
    theme->bActive=FALSE;
#endif
}
        
void SND_fn_vDesInitTheme(void)
{
}
 
/*---------------------------------------------------------------------*/
/*  ConvertResDiskToMemThjeme: gen_re une blockresourcemem valide*/
/*  Entrees:disk=block ressource disk à exploiter*/
/*      mem=block resource mem à initialiser*/
/*      ptrBegin=non exploite*/
/*  Sortie:neant*/
/*---------------------------------------------------------------------*/
void SND_fn_vConvertResDiskToMemTheme(tdstBlockResourceDisk* disk
                                      ,tdstBlockResourceMem *mem
                                      ,void* ptrBegin)
{
#ifndef DISABLE_THEME
    mem->Id=disk->Id;
    mem->eType=disk->eType;
    mem->eStorage=disk->eStorage;
    mem->ucVolume=disk->ucVolume;
    mem->bIsLoaded=TRUE;
 
    /*partie specifique au type de ressource*/
    mem->uRes.stTheme.ulStartLoop = disk->uRes.stTheme.ulStartLoop;
    mem->uRes.stTheme.ulNbParts= disk->uRes.stTheme.ulNbParts;
    mem->uRes.stTheme.ulNbLoops= disk->uRes.stTheme.ulNbLoops;
    mem->uRes.stTheme.rFadeDuration= disk->uRes.stTheme.rFadeDuration;
 
    /*SNDLST2_M_StaticInitAnchor(&(mem->uRes.stTheme));*/
    /*pResMem->uRes.stTheme will be initialized by Script library*/
#endif
}
 
#ifndef NO_ACP_SCRIPT
SndBool SND_fn_bLoadResScriptTheme(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem)
{
        SND_fn_vConvertResDiskToMemTheme(disk,mem,NULL);
        return TRUE;
}
#endif
 
#ifndef NO_ACP_LDBIN
SndBool SND_fn_bLoadResBinaryTheme(tdstBlockResourceDisk *_pBRDisk,tdstBlockResourceMem *_pBRMem,char *pDataBloc)
{
#ifndef DISABLE_THEME
    /*convert Binary reference to Mem reference*/
    tdstThemePart *pPartArray,*pPart;
 
    int iPos;
 
    /* Convert the ulDataOffset member to a pointer:*/
    pPartArray=(tdstThemePart *)(pDataBloc + _pBRDisk->ulDataOffset);
 
    /* Set pointers to part list:*/
    SNDLST2_M_StaticSetFirstElement(&_pBRMem->uRes.stTheme,pPartArray);
    SNDLST2_M_StaticSetNumberOfElements(&_pBRMem->uRes.stTheme, _pBRDisk->uRes.stTheme.ulNbParts);  
        
	/* scan parts:*/
    SNDLST2_M_StaticForEachElementOf( &_pBRMem->uRes.stTheme, pPart, iPos)
    {
        pPart->uRes.pstPtr=SND_fn_pGetBinRes(pPart->uRes.Id);
    }

	/*part outro is at the end of pPartArray*/
	if (_pBRDisk->uRes.stTheme.lOffsetPartOutro!=C_THEME_NO_PARTOUTRO)
	{
		_pBRMem->uRes.stTheme.pstPartOutro=(tdstThemePartOutro*)((char*)pPartArray+_pBRDisk->uRes.stTheme.lOffsetPartOutro);
		_pBRMem->uRes.stTheme.pstPartOutro->uRes.pstPtr=SND_fn_pGetBinRes(_pBRMem->uRes.stTheme.pstPartOutro->uRes.Id);
	}
	else
		_pBRMem->uRes.stTheme.pstPartOutro=NULL;
 
    SND_fn_vConvertResDiskToMemTheme(_pBRDisk,_pBRMem,NULL);
    return TRUE;
#else
	return FALSE;
#endif
}
#endif /*NO_ACP_LDBIN*/
 
 
 
void SND_fn_vUnLoadResTheme(tdstBlockResourceMem* mem)
{
}
 
SndBool fn_bCheckTheme(tduRefRes theme_res)
{
	hThemePart part;
	int i,level_loop;
 
	if (theme_res.pstPtr->uRes.stTheme.ulStartLoop>=theme_res.pstPtr->uRes.stTheme.ulNbParts)
	{
		snd_assert(0);
		return FALSE;
	}
	
	#ifdef SNDLST2_StaticIsOptimised
	if ((long)theme_res.pstPtr->uRes.stTheme.ulNbParts!=SNDLST2_M_StaticGetNumberOfElements(&theme_res.pstPtr->uRes.stTheme))
	{
		snd_assert(0);
		return FALSE;
	}
	#endif
 
	level_loop=0;
	SNDLST2_M_StaticForEachElementOf(&theme_res.pstPtr->uRes.stTheme,part,i)
	{
		if (part->bLoopStart) 
			level_loop++;
 
		if (level_loop>1)
		{/*only one level of looping*/
			snd_assert(0);
			return FALSE;
		}
 
		if (part->bLoopEnd)
			level_loop--;
 
		if (level_loop<0)
		{/*more endloop than begin loop*/
			snd_assert(0);
			return FALSE;
		}
	}
	if (level_loop!=0)
	{/*endloop missing*/
		snd_assert(0);
		return FALSE;
	}
 
	return TRUE;
}
 
void raj_soundparam_theme(active_theme* theme,SoundParam* par)
{
	int size;
 
	if (par)
		size=SND_M_lGetSizeOfSoundParam(par);
	else
		size=0;
 
	if (size)
	{
		if (size!=theme->lSizeParam)
		{
			if (theme->pstParam)
				theme->pstParam=SND_fn_pvReAllocSndEx(E_ucSndBlockMain,theme->pstParam,size);
			else
				theme->pstParam=SND_fn_pvMallocSndEx(E_ucSndBlockMain,size);
		}
		theme->lSizeParam=size;
		memcpy(theme->pstParam,par,size);
	}
	else
	{
		if (theme->pstParam)
		{
			SND_fn_vFreeSndEx(E_ucSndBlockMain,theme->pstParam);
			theme->pstParam=NULL;
			theme->lSizeParam=0;
		}
	}
}
 
/*---------------------------------------------------------------------*/
/*  PlayTheme: joue une ressource theme*/
/*  Entrees:canal=canal souhaite (pour le cas où on veut plusieurs themes simultanement)*/
/*      num_res=ressource de type theme à jouer*/
/*      par=parametres au lancement*/
/*      prio=priorite*/
/*      fn_callback=fonction de callback à appeler à a fin de a ressource*/
/*      par_callback=parametre à transmettre à la callback*/
/*      active=flag à mettre à FALSE si la voie retourner s'invalide*/
/*  Sortie:voie/canal associe à la ressource*/
/*---------------------------------------------------------------------*/
long SND_fn_lPlayTheme(long canal,tduRefRes theme_res,SoundParam* par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback,SndBool* valid)
{
#ifndef DISABLE_THEME
    tdstTypeThemeMem   *pstThemeRes;
    SoundParam		*pstSoundPar;
	active_theme	*theme=&g_stTheme;
	tduRefRes		FirstRes,NextRes;
#ifdef NB_MICRO_MAX
    SoundParam		stSoundPar;
#endif
 
    snd_assert(canal==C_PLAY_FAILED);/*on ne tolere qu'un seul theme pour l'instant*/
	snd_assert(fn_bCheckTheme(theme_res));
 
	/*raj soundparam*/
	raj_soundparam_theme(theme,par);
 
    if (((theme->bActive) && (theme_res.pstPtr==theme->uCurrentThemeRes.pstPtr) && !theme->bTransiting)
		|| (theme->bTransiting && theme->uGoingToThemeRes.pstPtr!=NULL))
	{/*--------- si theme cible et theme source sont identique, on ne fait rien*/
		return (long)theme;
	}
 
	/*en mettant g_bWorkingTheme à TRUE, on empeche l'occurence de la fonction de Callback*/
	/*	->il faut absolument qu'un PlayTransition ou SetNextTransition soit fait*/
    g_bWorkingTheme=TRUE;
 
#ifdef NB_MICRO_MAX
	pstSoundPar=&stSoundPar;
#else
	pstSoundPar=SND_fn_pCreateSoundParam(par->iNbLinks);
#endif
	memcpy(pstSoundPar,par,SND_M_lGetSizeOfSoundParam(par));
 
    pstThemeRes=&(theme_res.pstPtr->uRes.stTheme);
 
    if (theme->bActive)
    {/*------------transition theme à theme*/
		if (change_theme(theme,theme_res))
		{/*fade transition*/
			NextRes=SND_fn_tduGetLowestResourceSnd(theme->uNextRes,theme->pstParam,TRUE);
			SND_fn_bDoTransitionWithFadeSnd(theme->lVoice,NextRes);
		}
		else
		{/*end-of-part transition*/
			NextRes=SND_fn_tduGetLowestResourceSnd(theme->uNextRes,theme->pstParam,TRUE);
			SND_fn_bSetNextTransitionSnd(theme->lVoice,NextRes);
		}
    }
    else
    {/*------------debut d'un theme (aucun theme actif avant)*/
        start_new_theme(theme,theme_res);
    
        theme->pbValid=valid;
        theme->pfnFctCallback=fn_callback;
        theme->lParCallback=par_callback;
 
        /*---lancer la 1° part*/
		/*part params are modified by Theme static params*/
		pstSoundPar->ucVol=(unsigned char)(((long)pstSoundPar->ucVol*theme_res.pstPtr->ucVolume)>>7);
		pstSoundPar->iFlags|=C_SOUNDPARAM_COEF_VOL;
 
		FirstRes=SND_fn_tduGetLowestResourceSnd(theme->hCurrentPart->uRes,pstSoundPar,TRUE);
		NextRes=SND_fn_tduGetLowestResourceSnd(theme->uNextRes,pstSoundPar,TRUE);
 
        theme->lVoice=SND_fn_lPlayTransitionSnd(FirstRes,NextRes,fn_Transition,(long)theme,pstSoundPar);
    }/*if (theme->bActive)*/
 
    if (!theme->bActive)
    {
        if (theme->lVoice!=C_PLAY_FAILED)
        {
            theme->bActive=TRUE;
            *valid=TRUE;
        }
        else
            *valid=FALSE;
    }
 
#ifndef NB_MICRO_MAX
    SND_fn_vDestroySoundParam(pstSoundPar);
#endif
 
    g_bWorkingTheme=FALSE;
 
    if (theme->bActive)
        return (long)theme;
    else
#endif
        return C_PLAY_FAILED;
}
 
SndBool SND_CALL SND_fn_bSetParamTheme(long canal,SoundParam* par)
{
#ifndef DISABLE_THEME
    SoundParam *pstSoundPar;
	active_theme *pTheme;
#ifdef NB_MICRO_MAX
    SoundParam stSoundPar;
#endif
 
	pTheme=(active_theme*)canal;
 
	/*raj soundparam*/
	raj_soundparam_theme(pTheme,par);
 
#ifdef NB_MICRO_MAX
	pstSoundPar=&stSoundPar;
#else
	pstSoundPar=SND_fn_pCreateSoundParam(par->iNbLinks);
#endif
	memcpy(pstSoundPar,par,SND_M_lGetSizeOfSoundParam(par));
 
	/*part params are modified by Theme static params*/
	pstSoundPar->ucVol=(unsigned char)(((long)pstSoundPar->ucVol*pTheme->uCurrentThemeRes.pstPtr->ucVolume)>>7);
 
    SND_fn_bSetParamTransitionSnd(pTheme->lVoice,pstSoundPar);
 
#ifndef NB_MICRO_MAX
    SND_fn_vDestroySoundParam(pstSoundPar);
#endif
 
    return pTheme->bActive;
#else
	return FALSE;
#endif
}
 
SndBool SND_CALL SND_fn_bTestIsPlayingTheme(long canal)
{
#ifndef DISABLE_THEME
	active_theme *pTheme;
 
	pTheme=(active_theme*)canal;
 
    return pTheme->bActive;
#else
	return FALSE;
#endif
}
SndBool	SND_CALL	SND_fn_bAnyPlayingTheme() 
{
#ifndef DISABLE_THEME
	return g_stTheme.bActive;
#else
	return FALSE;
#endif
}

void SND_CALL SND_fn_vStopTheme(long canal)
{
#ifndef DISABLE_THEME
	active_theme *pTheme;
 
	pTheme=(active_theme*)canal;
 
    g_bWorkingTheme=TRUE;
 
    if (pTheme->bActive)
        SND_fn_vStopTransitionSnd(pTheme->lVoice);
 
	if (pTheme->pfnFctCallback)
		(*pTheme->pfnFctCallback)(pTheme->lParCallback);
 
    pTheme->bActive=FALSE;
 
    g_bWorkingTheme=FALSE;
#endif
}
 
void SND_CALL SND_fn_vPauseTheme(long canal)
{
#ifndef DISABLE_THEME
	active_theme *pTheme;
 
	pTheme=(active_theme*)canal;
 
    if (pTheme->bActive)
         SND_fn_vPauseTransitionSnd(pTheme->lVoice);
#endif
}
 
void SND_CALL SND_fn_vResumeTheme(long canal)
{
#ifndef DISABLE_THEME
	active_theme *pTheme;
 
	pTheme=(active_theme*)canal;
 
    if (pTheme->bActive)
        SND_fn_vResumeTransitionSnd(pTheme->lVoice);
#endif
}
 
void SND_fn_vRemoveCallbackTheme(long canal)
{
}
 
/*---------------------------------------------------------*/
/*      GetPos: retourne la position "theorique" de la ressource*/
/*                      exprime en seconde depuis le debut*/
/*                      different du temps absolu (car pitch, derive..)*/
/*      Entree: voie concernee*/
/*      Sortie: temps en S (SndReal)*/
/*----------------------------------------------------------*/
SndReal SND_CALL SND_fn_rGetPosTheme(long voie)
{
        return SND_C_POS_UNKNOWN;
}
 
/*---------------------------------------------------------*/
/*      GetLength: retourne la duree "theorique" de la ressource*/
/*                      exprime en seconde (constant pour une ressource donnee)*/
/*      Entree: voie concernee*/
/*      Sortie: duree en S (SndReal)*/
/*----------------------------------------------------------*/
SndReal SND_CALL SND_fn_rGetLengthTheme(long voie)
{
        return SND_C_POS_UNKNOWN;
}

SndBool  SND_fn_bSetResourceStaticVolumeTheme(tdstBlockResourceMem* pstRes,unsigned char ucVolume)
{
	pstRes->ucVolume=ucVolume;

	return TRUE;
}

 
#endif 
/* NO_ACP_SOUND*/
 
 
