#ifdef D_USE_LIPSYNC
 
#include "ToolsCPA.h"
 
#include "Options/Options.h"
#include "Macros.h"
 
#include "Actions/AllActs.h"
 
#include "Structur/3DOSLkTb.h"
#include "Structur/Objects.h"
#include "Structur/ErrGame.h"
#include "Structur/GameScpt.h"
#include "Structur/MemGame.h"
#include "Structur/StdObjSt.h"
#include "Structur/EngMode.h"
 
 
#include "Basic.h"
#include "Family.h"
#include "ZeMem.h"
 
#include "ObjType.h"
#include "CHLLoad.h"
 
#include "LipsSync.h"
#include "LoadLSyn.h"
/* MR0912*/
#include "LSMem.h"
 
/* For BIN*/
#include "SNA.h"
 
/* MR3006*/
tdxHandleOfLipsSynchroTable g_hLipsTable;
 
#if defined(ACTIVE_EDITOR)
SCR_tdst_Link_Table *fn_p_stGetLipsSynchroLinkTable()
{
	return &g_st3DOSLinkTable.stLipsSynchroList;
}
#endif /* ACTIVE_EDITOR */
 
 
SCR_tde_Anl_ReturnValue fn_xLoadLSGeneral(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
{
/*  SCR_tdst_Cxt_Values *p_stValues;*/
  tdxHandleOfLipsSynchroTable hLSTable;
  char szForScript[_MAX_PATH];
  char szFileName[_MAX_PATH];
  char szSectionName[_MAX_PATH];
  SND_tdstBlockEvent *p_stSndEvent;
  #if defined(ACTIVE_EDITOR)
  char a255_cLinkKey[255];
  #endif /* ACTIVE_EDITOR */
 
  switch (cType)
  {
 
  case SCR_EA_Anl_BeginSection:
	  hLSTable=fn_xAllocateLipsSynchroTable();
    /* Fix the context*/
	  SCR_M_RdL0_SetSectionLong(0,0,(long)hLSTable);
   SCR_M_RdL0_SetContextLong(0,0,(long)hLSTable);
   /* Link table*/
	strcpy(szSectionName,"*^");
	strcat(szSectionName,C_SectionA3dLSData);
	fn_v_File_ComputeFileSectionName(szSectionName,szFileName,szForScript/*+strlen(szForScript)*/);
 
 #if defined(ACTIVE_EDITOR)
	SCR_M_RdL0_ComputeOpenSectionNameR(0,a255_cLinkKey);
 
	SCR_fnp_st_Link_CreateOrGetLinkFromKey( &g_st3DOSLinkTable.stLipsSynchroList, a255_cLinkKey);
	SCR_fnp_st_Link_SetValue(&g_st3DOSLinkTable.stLipsSynchroList, a255_cLinkKey,(unsigned long)hLSTable);
 #endif /* ACTIVE_EDITOR */
 
 
	 fn_vLSResetChannelSync(hLSTable);
   break;
  case SCR_EA_Anl_Entry:
	/* Read the entries*/
	SCR_M_RdL0_GetContextLong(0,0,tdxHandleOfLipsSynchroTable,hLSTable);
	if (!stricmp(szAction,C_EntryNumberOfFrames))
	{ int i;
 
		hLSTable->lNumberOfFrames=(long)atoi(szParams[0]);
		hLSTable->p_stTable=fn_xAllocateLipsSynchroEvents(hLSTable->lNumberOfFrames);
		for (i=0;i<hLSTable->lNumberOfFrames;i++)
		{	hLSTable->p_stTable[i].ucPhoneme=255;
			hLSTable->p_stTable[i].ucIntensity=0;
			hLSTable->p_stTable[i].ucExpression=0;
		}
	}
	else if (!strcmp(szAction,C_EntryLSSpeed))
	{
		fn_vLSSetSpeed(hLSTable,(long)atoi(szParams[0]));
	}
	else if(!strcmp(szAction,C_EntryLSSound))	/* MR0107*/
	{ SCR_tdst_Cxt_Values *p_stVal;
		p_stVal = SCR_fnp_st_RdL0_AnalyseSection(szParams[0], SCR_CDF_uw_Anl_Normal);
		p_stSndEvent=(SND_tdstBlockEvent*)SCR_M_ul_RdL0_ExtractLongValue(p_stVal,0);
 
		hLSTable->p_stSndEvent=p_stSndEvent;
	}
	else if(!strcmp(szAction,C_EntryLSStopSound))	/* MR0808*/
	{
		p_stSndEvent=(SND_tdstBlockEvent*)SCR_M_ul_RdL0_ExtractLongValue(((SCR_tdst_Cxt_Values**)szParams[1])[0], 0);
 
		/* For BIN*/
		if (SNA_fn_ucGetLoadType()==SNA_SAVE_SNAPSHOT)	/* MR0912*/
			/* we save the id of the sound event and the pointer on the structure that contains the id and the pointer of the sound event*/
			SNA_fn_vWriteSoundEntryInSoundTableFile(SND_fn_ulGetEventBinIdFromPointer((SND_tdxHandleToSoundEvent)p_stSndEvent) ,(unsigned long)&(hLSTable->p_stSndEventStop));
 
		hLSTable->p_stSndEventStop=p_stSndEvent;
	}
	else if(!strcmp(szAction,C_EntryLSChannelNumber))	/* MR0207*/
	{ char sz_ForLinkTable[MAX_PATH];
	  struct tdstFamilyList_ *p_stFamily = NULL;
	  SCR_tdst_Link_Value * _p_stLinkValue;
	  short wChannelNumber = 0;
 
		SCR_M_RdL0_GetContextLong(C_ThisContext,1,struct tdstFamilyList_ *,p_stFamily);
		strcpy(sz_ForLinkTable,fn_szFindFamilyTypeNameOfFamilyType(p_stFamily->otObjectFamilyType));
		strcat(sz_ForLinkTable,"-");
		strcat(sz_ForLinkTable,szParams[0]);
 
		_p_stLinkValue = SCR_fnp_st_Link_SearchKey(&CHL_g_stLinkTable,sz_ForLinkTable);
		if(_p_stLinkValue)
		{
			wChannelNumber = (unsigned short)SCR_M_ul_Link_GetValue(_p_stLinkValue);
		}
 
		fn_vLSAddChannelSync(hLSTable,(unsigned char)wChannelNumber);
	}
	else if(!strcmp(szAction,C_EntryNumberOfActings))	/* MR2008*/
	{ int i;
		hLSTable->lNumberOfActings=(long)atoi(szParams[0]);
		hLSTable->p_stActing=fn_xAllocateActing(hLSTable->lNumberOfActings);
		for (i=0;i<hLSTable->lNumberOfActings;i++)
		{	hLSTable->p_stActing[i].hNewState=NULL;
			hLSTable->p_stActing[i].lFrameNumber=-1;
		}
	}
	break;
 
  case SCR_EA_Anl_EndSection:
    break;
  }
  return  SCR_ERV_Anl_NormalReturn;
}
 
SCR_tde_Anl_ReturnValue fn_xLoadLSData(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
{
  SCR_tdst_Cxt_Values *p_stValues;
  tdxHandleOfLipsSynchroTable hLSTable;
  char szSectionName[255];
  unsigned char ucLastPhoneme = 0,ucLastIntensity = 0,ucLastExpression = 0;
  int i;
 
  switch (cType)
  {
  case SCR_EA_Anl_BeginSection:
	strcpy(szSectionName,p_fFile->a_szFileName);
	strcat(szSectionName,"^");
	strcat(szSectionName,C_SectionA3dLSGeneral);
	p_stValues = SCR_fnp_st_RdL0_AnalyseSection(szSectionName, SCR_CDF_uw_Anl_Normal);
	hLSTable=(tdxHandleOfLipsSynchroTable)(p_stValues->a_ulValues[0]);
	SCR_M_RdL0_SetSectionLong(0,0,(long)hLSTable);
	SCR_M_RdL0_SetContextLong(0,0,(long)hLSTable);
   break;
  case SCR_EA_Anl_Entry:
	/* Read the entries*/
	SCR_M_RdL0_GetContextLong(0,0,tdxHandleOfLipsSynchroTable,hLSTable);
	if (!stricmp(szAction,C_EntryLSMouth))
		fn_vLSSetPhoneme(hLSTable,atoi(szParams[0]),(unsigned char)(szParams[1][0]-'A'));
	else if (!strcmp(szAction,C_EntryLSIntensity))
		fn_vLSSetIntensity(hLSTable,atoi(szParams[0]),(unsigned char)atoi(szParams[1]));
	else if (!strcmp(szAction,C_EntryLSExpression))
		if (!stricmp(szParams[1],"Neutral"))
			fn_vLSSetExpression(hLSTable,atoi(szParams[0]),0);
	break;
 
  case SCR_EA_Anl_EndSection:
	SCR_M_RdL0_GetContextLong(0,0,tdxHandleOfLipsSynchroTable,hLSTable);
	/* MR1908*/
	if (hLSTable->lNumberOfTexts)
		SCR_fnp_st_RdL0_AnalyseSection("*^Text", SCR_CDF_uw_Anl_Normal);
	if (hLSTable->lNumberOfActings)
		SCR_fnp_st_RdL0_AnalyseSection("*^Acting", SCR_CDF_uw_Anl_Normal);
	for (i=0;i<fn_lLSGetNumberOfFrame(hLSTable);i++)
		if (fn_ucLSGetPhoneme(hLSTable,i)==255)
		{	fn_vLSSetPhoneme(hLSTable,i,ucLastPhoneme);
			fn_vLSSetIntensity(hLSTable,i,ucLastIntensity);
			fn_vLSSetExpression(hLSTable,i,ucLastExpression);
		}
		else
		{	ucLastPhoneme=fn_ucLSGetPhoneme(hLSTable,i);
			ucLastIntensity=fn_ucLSGetIntensity(hLSTable,i);
			ucLastExpression=fn_ucLSGetExpression(hLSTable,i);
		}
    break;
  }
  return  SCR_ERV_Anl_NormalReturn;
}
 
SCR_tde_Anl_ReturnValue fn_xLoadLSTextDial(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
{
  SCR_tdst_Cxt_Values *p_stValues;
  tdxHandleOfLipsSynchroTable hLSTable;
  char szSectionName[255];
  static int i=0;
  struct tdstDialText_ *p_stText;
 
  switch (cType)
  {
  case SCR_EA_Anl_Entry:
	/* Read the entries*/
	SCR_M_RdL0_GetContextLong(0,0,tdxHandleOfLipsSynchroTable,hLSTable);
	if (!stricmp(szAction,C_EntryDisplayText))
	{
		strcpy(szSectionName,fn_szGetSyncLipsDataPath());
		strcat(szSectionName,"\\Text\\");
		strcat(szSectionName,szParams[1]);
		p_stValues = SCR_fnp_st_RdL0_AnalyseSection(szSectionName, SCR_CDF_uw_Anl_Normal);
		p_stText=(struct tdstDialText_ *)(p_stValues->a_ulValues[0]);
		memcpy(&(hLSTable->p_stDialTexts[i]),p_stText,sizeof(struct tdstDialText_));
        MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeLipSynchro , 0 );
		TMP_M_Free(p_stText);
		hLSTable->p_stDialTexts[i].lFrameNumber=atoi(szParams[0]);
		i++;
	}
	break;
    case SCR_EA_Anl_EndSection:
		i=0;
	break;
  }
  return  SCR_ERV_Anl_NormalReturn;
}
 
SCR_tde_Anl_ReturnValue fn_xLoadLSActing(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
{
  SCR_tdst_Cxt_Values *p_stValues;
  tdxHandleOfLipsSynchroTable hLSTable;
  char szSectionName[255];
  static int i=0;
  struct tdstActing_ *p_stActing;
 
  switch (cType)
  {
  case SCR_EA_Anl_Entry:
	/* Read the entries*/
	SCR_M_RdL0_GetContextLong(0,0,tdxHandleOfLipsSynchroTable,hLSTable);
	if (!stricmp(szAction,C_EntryActingFlag))
	{
		strcpy(szSectionName,fn_szGetSyncLipsDataPath());
		strcat(szSectionName,"\\Acting\\");
		strcat(szSectionName,szParams[1]);
		p_stValues = SCR_fnp_st_RdL0_AnalyseSection(szSectionName, SCR_CDF_uw_Anl_Normal);
		p_stActing=(struct tdstActing_ *)(p_stValues->a_ulValues[0]);
		memcpy(&(hLSTable->p_stActing[i]),p_stActing,sizeof(struct tdstActing_));
        MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeLipSynchro , 0 );
		TMP_M_Free(p_stActing);
		hLSTable->p_stActing[i].lFrameNumber=atoi(szParams[0]);
		i++;
	}
	break;
    case SCR_EA_Anl_EndSection:
		i=0;
	break;
  }
  return  SCR_ERV_Anl_NormalReturn;
}
 
SCR_tde_Anl_ReturnValue fn_xLoadTextDial(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
/* read the DIA files*/
{
  static int i=0;
  struct tdstDialText_ *p_stText;
 
  switch (cType)
  { case SCR_EA_Anl_BeginSection:
      MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeLipSynchro , 0 );
	  p_stText=TMP_M_p_Malloc(sizeof(struct tdstDialText_));
    /* Fix the context*/
	  SCR_M_RdL0_SetSectionLong(0,0,(long)p_stText);
      SCR_M_RdL0_SetContextLong(0,0,(long)p_stText);
	break;
    case SCR_EA_Anl_Entry:
	/* Read the entries*/
	SCR_M_RdL0_GetContextLong(0,0,struct tdstDialText_ *,p_stText);
	if (!stricmp(szAction,C_EntryPosition))
	{
  p_stText->xPosX=(MTH_tdxReal)atof(szParams[0]);
		p_stText->xPosY=(MTH_tdxReal)atof(szParams[1]);
	}
	break;
  }
  return  SCR_ERV_Anl_NormalReturn;
}
/* End MR1908*/
 
SCR_tde_Anl_ReturnValue fn_xLoadActing(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
/* read the ACT files*/
{
  struct tdstActing_ *p_stActing;
 
  switch (cType)
  { case SCR_EA_Anl_BeginSection:
      MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeLipSynchro , 0 );
	  p_stActing=TMP_M_p_Malloc(sizeof(struct tdstActing_));
    /* Fix the context*/
	  SCR_M_RdL0_SetSectionLong(0,0,(long)p_stActing);
      SCR_M_RdL0_SetContextLong(0,0,(long)p_stActing);
	break;
    case SCR_EA_Anl_Entry:
	/* Read the entries*/
	SCR_M_RdL0_GetContextLong(0,0,struct tdstActing_ *,p_stActing);
	if (!stricmp(szAction,C_EntryNewState))
	{ char szSectionName[255];
	  SCR_tdst_Link_Value * _p_stLinkValue;
 
		strcpy(szSectionName,fn_szGetFamiliesDataPath());
		strcat(szSectionName,"\\");	strcat(szSectionName,szParams[0]);
		_p_stLinkValue = SCR_fnp_st_Link_SearchKey(&g_st3DOSLinkTable.stState,szSectionName);
		p_stActing->hNewState = (tdxHandleToState)SCR_M_ul_Link_GetValue(_p_stLinkValue);
	}
	break;
  }
  return  SCR_ERV_Anl_NormalReturn;
}
 
void fn_vLipsSynchroLoadInit()
{
	SCR_fn_v_RdL0_RegisterCallback(C_SectionA3dLSGeneral, fn_xLoadLSGeneral, SCR_CRC_c_RdL0_ForSection);
	SCR_fn_v_RdL0_RegisterCallback(C_SectionA3dLSData, fn_xLoadLSData, SCR_CRC_c_RdL0_ForSection);
	/* MR1908*/
	SCR_fn_v_RdL0_RegisterCallback(C_SectionTextDial, fn_xLoadLSTextDial, SCR_CRC_c_RdL0_ForSection);
	SCR_fn_v_RdL0_RegisterCallback(C_SectionLSActing, fn_xLoadLSActing, SCR_CRC_c_RdL0_ForSection);
	SCR_fn_v_RdL0_RegisterCallback(C_SectionDialogue, fn_xLoadTextDial, SCR_CRC_c_RdL0_ForSection);
	SCR_fn_v_RdL0_RegisterCallback(C_SectionActing, fn_xLoadActing, SCR_CRC_c_RdL0_ForSection);
}
 
 
#endif /* D_USE_LIPSYNC*/
 
