/* ////////////////////////////////////////////////////////// // 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 +-------+-->||<--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*/