//#################################################################################
//
// BASE CLASS OF YOUR DLL interface
//
//#################################################################################

#include "stdafx.h"

#include "SCR.h"
#include "SND.h"
#include "sndld_s.h"	// for SND_pstGetEventGroupLinkTable...
#include "sndld_hy.h"   // for SND_fn_czGetProjectTitle...
#include "snddbg.h"	// for SND_fn_pstGetSelectedResource && SND_fn_bDoesSupervisaterSelectResource
#include "sndres.h"	// for tdstBlockResourceMem type use


#include "acp_base.h" // for CPA_Tooldllb class definition
#include "incITF.h" // for CPA_Tooldllb class definition

#include "SNinterf.hpp"
#include "TSNEvent.h"

#include "SIF.h" // Sound info server..
//#include "Sifloads.h" //for SIF_fn_pstGetSoundInfosDescriptor

#include "x:\cpa\main\inc\_editid.h" //Object type names..

/*


#include "ITF/cpasaveo.hpp" // For TSN_Event&SIF_InfoValue  class definition
#include "LST/cpalist.hpp" // for the CPA_List defined in the SIF_InfoType object  


#include "ITF/CPAProj.hpp" // for M_GetMainWnd()





//static CList<CPA_DLLBase*,CPA_DLLBase*> g_oListOfInstances;	//private internal

#define C_lEDST_Active      1
#define C_lEDST_Inactive	0
*/


// the DLL global definition
tdstDLLIdentity		g_stSNDEDITIdentity;

SNDEDIT_Interface* g_poSNDEDITInterface=NULL; 




//--------------------------------------------------------------------------------
// CONSTRUCTOR.
// You must put here all your DLL interface definitions.
//--------------------------------------------------------------------------------
SNDEDIT_Interface::SNDEDIT_Interface(void)
{
    SetEditorInfo( "Sound", "Frédéric Décréau", "v6.0.0", "","");

	// ************************** private internal
	m_p_stDLLIdentity = &g_stSNDEDITIdentity;

    // Name of your .INI file.
//    m_stBaseDLLDefinition.p_cIniName = NULL;

    // Does your DLL can output in main game view ?
	m_stBaseDLLDefinition.bCanOutputIn3DView = FALSE;

    // Does your DLL can be refresh by engine ?
	m_stBaseDLLDefinition.bCanBeRefreshedByEngine = FALSE;
	m_bEditorEnabled=FALSE;
	m_uiTimerId=NULL;
}


SNDEDIT_Interface::~SNDEDIT_Interface(void)
{
	POSITION Pos;
	TSN_Event *pEvent;

	// delete events:
	Pos=NULL;
	while (pEvent=m_EdiEventList.GetNextElement(Pos)) delete pEvent;
	fn_vDestroyResList();
	TSN_fn_bDesInitSoundInfos();
}

void SNDEDIT_Interface::fn_vJustAfterRegistered(void)
{

	int iTypeNum;
	int iNbTypes,iNbInfoTypes;
	CString *pa_csTypes;

	//*******************************************************
	//*			 Register the CPA_SaveObject types			*
	//*******************************************************

	// Number of CPA_SaveObject types: 1 for sound events + 1 for each info type:
	iNbInfoTypes=SIF_fn_iGetSoundInfosCount();
	iNbTypes=iNbInfoTypes+1; 

	pa_csTypes= new CString[iNbTypes];  
	
	for (iTypeNum=0;iTypeNum<iNbInfoTypes;iTypeNum++)
		pa_csTypes[iTypeNum]=CString("SIF_")+SIF_fn_czGetSoundInfoNameForType(iTypeNum);
	pa_csTypes[iNbInfoTypes]=C_szSoundEventTypeName;
	fn_vRegisterObjectsType(pa_csTypes, iNbTypes);

	delete[] pa_csTypes;


}



void SNDEDIT_Interface::fn_vConstruct(void)
{
		ASSERT(g_poSNDEDITInterface==NULL);
		g_poSNDEDITInterface=this;

}



void SNDEDIT_Interface::fn_vLevelChanges (void)
{
	SCR_tdst_Link_Table *p_stTable;
	SCR_tdst_Link_Value	*p_stValue;
	unsigned int uiPos;
	CString csName,csTemp;
	
	SCR_tdst_Anl_Callback *pCallback;
	SCR_tdpfn_Anl_Callback pOldSndResM_CB;
	SCR_tdpfn_Anl_Callback pOldSndEventM_CB;
	
	static BOOL bFirstLevelChange=TRUE;
	
	if (bFirstLevelChange)
	{
		// Set the script callback fot the editor event:
		SCR_fn_v_RdL0_RegisterCallback("SndEventE",TSN_Event::m_fn_eLoad,SCR_CRC_c_RdL0_ForSection);
		bFirstLevelChange=FALSE;
	}
	else
	{
		AfxMessageBox(" Sound Editor Error: Second level Change not implemented yet!");
		return;
	}

	// Add a message in the status bar:
	M_GetMainWnd()->UpdateStatus("Loading sound data",C_STATUSPANE_INFOS,C_STATUS_NORMAL);
	
	// Save and delete script callbacks on SndResourceM and SndEventM:

	pCallback=SCR_fnp_st_RdL0_GetRegisterCallback("SndResourceM",SCR_CRC_c_RdL0_ForSection);
	pOldSndResM_CB=pCallback->pfn_eCallback;
	pCallback=SCR_fnp_st_RdL0_GetRegisterCallback("SndEventM",SCR_CRC_c_RdL0_ForSection);
	pOldSndEventM_CB=pCallback->pfn_eCallback;

	SCR_fn_v_RdL0_DeleteRegisterCallback("SndResourceM",SCR_CRC_c_RdL0_ForSection, SCR_CDR_c_RdL0_Match);
	SCR_fn_v_RdL0_DeleteRegisterCallback("SndEventM",SCR_CRC_c_RdL0_ForSection, SCR_CDR_c_RdL0_Match);


	csName=SND_fn_czGetProjectTitle();
	csName+=".sif";
	TSN_fn_bInitSoundInfos(csName);



	// Scan event groups:

	// Get first list element: 
	uiPos = 0;
	p_stTable=SND_pstGetEventGroupLinkTable();
	SCR_M_DyAr_GetNextElement(SCR_tdst_Link_Value,uiPos,p_stValue,
		SCR_M_st_Link_GetDynamicArray(p_stTable));

	while(p_stValue) // p_sValue is NULL at the end of the array 
	{
		if(SCR_M_e_Link_GetState(p_stValue) != SCR_ELS_Link_Initialized) continue;
		
		// Get event group name:
		csName=SCR_M_p_sz_Link_GetKey(p_stValue);	

		// Update status bar:
		csTemp.Format("Loading sound bank: %s",csName);
		M_GetMainWnd()->UpdateStatus((char*)(LPCTSTR)csTemp,C_STATUSPANE_INFOS,C_STATUS_NORMAL);

		csName+=".csb";
		SCR_fnp_st_RdL0_AnalyseSection((char*)(LPCTSTR)csName, SCR_CDF_uw_Anl_Normal);

		uiPos++;
		SCR_M_DyAr_GetNextElement(SCR_tdst_Link_Value,uiPos,p_stValue, 
					SCR_M_st_Link_GetDynamicArray(SND_pstGetEventGroupLinkTable()));
	}

	// Reset the script callbacks we deleted:
	unsigned char ucOldMemLevel = SCR_fn_uc_Mem_GetCurrentLevel();
	SCR_fn_v_Mem_SetCurrentLevel(0);
	SCR_fn_v_RdL0_RegisterCallback("SndResourceM",pOldSndResM_CB,SCR_CRC_c_RdL0_ForSection);
	SCR_fn_v_RdL0_RegisterCallback("SndEventM",pOldSndEventM_CB,SCR_CRC_c_RdL0_ForSection);
	SCR_fn_v_Mem_SetCurrentLevel(ucOldMemLevel);




	// Sound load finished:
	M_GetMainWnd()->UpdateStatus("",C_STATUSPANE_INFOS,C_STATUS_NORMAL);
};

void SNDEDIT_Interface::fn_vBeforeEngine()
{
	if (!m_bEditorEnabled)	return; 

	ASSERT(m_uiTimerId==NULL);
	m_uiTimerId=timeSetEvent(10,10,m_fn_vTimerProc,NULL,TIME_ONESHOT);
	ASSERT(m_uiTimerId!=NULL);
}

void SNDEDIT_Interface::fn_vBeforeEditor()
{
	char szPath[MAX_PATH];

	MMRESULT mReturn;
	if (!m_bEditorEnabled)	return; 

	ASSERT(m_uiTimerId!=NULL);
	mReturn=timeKillEvent(m_uiTimerId);
	ASSERT(mReturn==TIMERR_NOERROR);
	m_uiTimerId=NULL;

	// Record modified resources: 
	IResource IRes;
	LPDISPATCH lpDispatch;
	POSITION Pos;
	tdstBlockResourceMem* pResM;

	if (m_ModifiedResList.IsEmpty()) return;

	Pos=NULL;
	while (pResM=m_ModifiedResList.GetNextElement(Pos))
	{
		// Find corresponding resource in editor:
		lpDispatch=m_IEditor.FindResFromEditorId(pResM->Id);
		if (lpDispatch!=NULL)
		{
			IRes.AttachDispatch(lpDispatch);
			// Change the volume in the editor:
			IRes.SetVolume(pResM->ucVolume);
			IRes.DetachDispatch();
		}
	}

	// Open the sound project:
	
	GetTempPath(MAX_PATH,szPath);
	strcat(szPath,"\\");
	strcat(szPath,"TSltemp.tmp");
	SCR_fn_v_SvL1_RegisterNotify(szPath,mfn_vNotificationCallback,NULL,SCR_EA_Ntfy_AddOrRebuildSection);
	m_ModifiedResList.RemoveAll();
}

void CALLBACK EXPORT SNDEDIT_Interface::m_fn_vTimerProc(
							UINT uID,      // event ID
						   UINT nMsg,      // Reserved
						   DWORD dwUser,    // user data
						   DWORD dw1,DWORD dw2   // Reserved
						)
{
	IResource IRes;

	tdstBlockResourceMem* pResM;
	long lTemp;
	POSITION Pos=NULL;
	
	BOOL bKeyPressed=FALSE;
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeUp)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=1;
	}
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeDown)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=-1;
	}
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeUpFast)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=10;
	}
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeDownFast)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=-10;
	}


	if (!bKeyPressed) goto procend_label;
	if (!SND_fn_bDoesSupervisaterSelectResource()) goto procend_label;

	pResM=SND_fn_pstGetSelectedResource();
	if (pResM==NULL) goto procend_label;
	
	// Compute new volume and check bounds: 
	lTemp+=(long)pResM->ucVolume;
	if ((lTemp<0)||(lTemp>127)) goto procend_label;

	// Change the volume in the game:
	pResM->ucVolume=(unsigned char)lTemp;
	if (g_poSNDEDITInterface->m_ModifiedResList.Find(pResM)==NULL)
		g_poSNDEDITInterface->m_ModifiedResList.AddTail(pResM);


procend_label:

	//resend the timer:
	if (g_poSNDEDITInterface->m_uiTimerId!=NULL)
	{
		g_poSNDEDITInterface->m_uiTimerId=timeSetEvent(10,10,m_fn_vTimerProc,NULL,TIME_ONESHOT);
		ASSERT(g_poSNDEDITInterface->m_uiTimerId!=NULL);
	}
	

}


BOOL SNDEDIT_Interface::fn_bLoadBaseObject(CPA_BaseObject *p_oObject)
{
	TSN_Event *pEvent=(TSN_Event *)p_oObject;
	return	(pEvent->fn_bEngineLoad());
}


BOOL SNDEDIT_Interface::fn_bDefineSubMenu(EDT_SubMenu *_pSubMenu)
{
	switch(_pSubMenu->GetSubMenuType())
	{
	case C_SubMenuEditor:
		break;
	case C_SubMenuTool: //AddAnEntry  args: Owner,Text,Id,_bCheck,_bEnable.
		_pSubMenu->AddAnEntry(this,"Enable Sound Mixing",1,m_bEditorEnabled,TRUE);
		break;
	}
	return TRUE;
}



void SNDEDIT_Interface::_OnSubMenuCommand(EDT_SubMenu *_pSubMenu,UINT uiMsgId)
{
	char szName[MAX_PATH],szPath[MAX_PATH];

	switch (_pSubMenu->GetSubMenuType())
	{
		case C_SubMenuEditor:
		break;

		case C_SubMenuTool:
			switch (uiMsgId)
			{
				case 1: 
					//***********************************************
					//*				Initialize sound editor			*
					//***********************************************
					
					// OLE DLL initailisation:
					if (!AfxOleInit())
					{
						AfxMessageBox("OLE Init failed. Check the OLE DLL versions.");
						return;
					}
					// Sound editor int:
					if (!m_IEditor.CreateDispatch(_T("SoundEditor.Document")))
					{
						AfxMessageBox("Could not load the sound editor");
						return;
					}
					// Open the sound project:
					
					strcpy(szName,SND_fn_czGetProjectTitle());
					strcat(szName,".lcb");
					SND_fn_vResolveFileName(szName,szPath);
					SND_fn_bGetCurrentDirectory(szName,MAX_PATH);
					strcat(szName,"\\");
					strcat(szName,szPath);
					if (!m_IEditor.OpenDocument(szName))
					{
						AfxMessageBox("Could not open the sound project");
						return;
					}

					// *** Init Sound resource mixing keys //
					m_hSoundResourceVolumeUp	= IPT_fn_hGetEntryActionHandle("SndResVolumeUp");
					m_hSoundResourceVolumeDown= IPT_fn_hGetEntryActionHandle("SndResVolumeDown");
					m_hSoundResourceVolumeUpFast= IPT_fn_hGetEntryActionHandle("SndResVolumeUpFast");
					m_hSoundResourceVolumeDownFast= IPT_fn_hGetEntryActionHandle("SndResVolumeDownFast");
					
					
					if (m_hSoundResourceVolumeUp==NULL)	return;
					if (m_hSoundResourceVolumeDown==NULL)	return;
					if (m_hSoundResourceVolumeUpFast==NULL)	return;
					if (m_hSoundResourceVolumeDownFast==NULL)	return;
					
					fn_vFillResList();
					SND_fn_vSetResNameCallback(fn_czGetResNameFromEdId);
						
					m_bEditorEnabled=TRUE;
					break;
			}
			break;
	}
}


void SNDEDIT_Interface::mfn_vNotificationCallback(SCR_tdst_File_Description *_p_stFile, char *_p_szSectionName, void *_pvData, SCR_tde_Ntfy_Action _eAction)
{
	char szName[MAX_PATH],szPath[MAX_PATH];

	switch (_eAction)
	{
		case SCR_EA_Ntfy_AddSection:
		case SCR_EA_Ntfy_ModifySection:
		case SCR_EA_Ntfy_RebuildSection:
		case SCR_EA_Ntfy_AddOrModifySection:
		case SCR_EA_Ntfy_AddOrRebuildSection:
			strcpy(szName,SND_fn_czGetProjectTitle());
			strcat(szName,".lcb");
			SND_fn_vResolveFileName(szName,szPath);
			SND_fn_bGetCurrentDirectory(szName,MAX_PATH);
			strcat(szName,"\\");
			strcat(szName,szPath);
			g_poSNDEDITInterface->m_IEditor.SaveDocument(szName);
			break;

		case SCR_EA_Ntfy_DeleteIfExists:
		case SCR_EA_Ntfy_DeleteSection:
		case SCR_EA_Ntfy_Dummy:
			break;
	}
	
}





/* OLD FUNCTIONS:




BOOL SNDEDIT_Interface::fn_bDefineSubMenu(EDT_SubMenu *_pSubMenu)
{
	switch(_pSubMenu->GetSubMenuType())
	{
	case C_SubMenuEditor:
	if (!fn_bIsCurrentEditor())
		_pSubMenu->AddAnEntry(this, "Sound Editor", C_uiOpenID, FALSE);
	else
		_pSubMenu->AddAnEntry(this, "Sound Editor", C_uiCloseID, TRUE);
		break;
	case C_SubMenuTool:
		if (fn_bIsCurrentEditor())
		{
			_pSubMenu->AddAnEntry(this,"Save sound data",1,FALSE);
			_pSubMenu->AddAnEntry(this,"Dump sound events in map",2,FALSE);
			_pSubMenu->AddAnEntry(this,"Check sample<->resource coherence",3,FALSE);
			_pSubMenu->AddAnEntry(this,"Load all sound banks",4,FALSE);
		}
		break;
	}
	return TRUE;
}



void SNDEDIT_Interface::_OnSubMenuCommand(EDT_SubMenu *_pSubMenu,UINT uiMsgId)
{
	CString csDataPath;
	CString csLCBName,csSITName;
	POSITION Pos;
	SND_EventGroup *pGroup;
	
	switch (_pSubMenu->GetSubMenuType())
	{
		case C_SubMenuEditor:
		switch (uiMsgId)
		{
			case C_uiOpenID:
				if (!fn_bIsCurrentEditor())
					GetMainWorld()->fn_bActivateEditor(this, NULL);
				break;

			case C_uiCloseID:
				if (fn_bIsCurrentEditor())
					GetMainWorld()->fn_bCloseEditor(this);
				break;
		}
		break;

		case C_SubMenuTool:
			switch (uiMsgId)
			{
				case 1: // Save Sound data:
					// Get the lcb name:
					csLCBName="ed_main.lcb";
					csSITName="ed_main.sit";

					csDataPath=m_Editor.m_fn_csGetSoundDirectory();
					csLCBName=csDataPath+"ed_main.lcb";
					m_Editor.m_fn_bSaveData((char*)(LPCTSTR)csLCBName);
					break;
				case 2: // Dump events in map:
					m_Editor.m_fn_vDumpEventsInMap();
					break;
				case 3: //Check sample<->resource coherence:
					m_Editor.m_fn_vCheckSampleResCoherence();
					break;
				case 4: //Load all sound banks:
					Pos=NULL;
					while (pGroup=m_Editor.m_fn_poGetEventGroupList()->GetNextElement(Pos))
						if (!pGroup->fn_bIsLoaded()) pGroup->fn_bLoadData();
					break;
			}
			break;
	}
}






void CALLBACK EXPORT SNDEDIT_Interface::m_fn_vTimerProc(HWND hWnd,      // handle of CWnd that called SetTimer
						   UINT nMsg,      // WM_TIMER
						   UINT nIDEvent,   // timer identification
						   DWORD dwTime    // system time
						)
{
	SND_ResourceView *pResView;
	SND_EdiRes* pRes;
	static SND_EdiRes* s_pEditedRes=NULL;
	tdstBlockResourceMem* pResM;
	long lTemp;
	unsigned long ulEvtGrpId;
	POSITION Pos=NULL;
	
	BOOL bKeyPressed=FALSE;
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeUp)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=1;
	}
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeDown)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=-1;
	}
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeUpFast)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=10;
	}
	if (IPT_fn_bIsJustValidated(g_poSNDEDITInterface->m_hSoundResourceVolumeDownFast)==IPT_C_TRUE)
	{
		bKeyPressed=TRUE;
		lTemp=-10;
	}

	if (bKeyPressed)
	{
		if (SND_fn_bDoesSupervisaterSelectResource())
		{
			pResM=SND_fn_pstGetSelectedResource();
			if (pResM==NULL) return;
			if ((s_pEditedRes==NULL)||(s_pEditedRes->GetStruct()!=pResM))
			{ // selected resource changed: get new corresponding editor res:
				ulEvtGrpId=HIWORD(pResM->Id); // Get event group id:
				// Get corresponding event group:
				SND_EventGroup* pGroup;
				Pos=NULL;
				while(pGroup=g_poSNDEDITInterface->m_Editor.m_fn_poGetEventGroupList()->GetNextElement(Pos))
					if (pGroup->fn_ulGetId()==ulEvtGrpId) break;
				if (pGroup==NULL) return; // event group not found;
				// Load event group if not yet loaded:
				if (!pGroup->fn_bIsLoaded()) pGroup->fn_bLoadData();
				// find resource in the group:
				Pos=NULL;
				while(s_pEditedRes=pGroup->m_ResList.GetNextElement(Pos))
					if (s_pEditedRes->GetStruct()==pResM) break;
				if (s_pEditedRes==NULL) return;
			}
							// Add ltemp to this resource's volume:
				lTemp+=(long)s_pEditedRes->m_oBRDisk.ucVolume;
				if ((lTemp>=0)&&(lTemp<=127))
				{
					s_pEditedRes->m_oBRDisk.ucVolume=(unsigned char)lTemp;
					s_pEditedRes->GetStruct()->ucVolume=(unsigned char)lTemp;
					s_pEditedRes->m_pGroup->fn_vNotifyRebuild();
					MessageBeep(MB_ICONEXCLAMATION);
					pResView=(SND_ResourceView *)g_poSNDEDITInterface->m_pSplitFrame->m_fn_p_oGetPane(2);
					pResView->OnUpdate(0,0,0);
				}

		}
		else 
		{
			pResView=(SND_ResourceView *)g_poSNDEDITInterface->m_pSplitFrame->m_fn_p_oGetPane(2);
			while (pRes=pResView->m_EditedResList.GetNextElement(Pos))
			{
				// Add ltemp to this resource's volume:
				lTemp+=(long)pRes->m_oBRDisk.ucVolume;
				if ((lTemp>=0)&&(lTemp<=127))
				{
					pRes->m_oBRDisk.ucVolume=(unsigned char)lTemp;
					pRes->GetStruct()->ucVolume=(unsigned char)lTemp;
					pRes->m_pGroup->fn_vNotifyRebuild();
					MessageBeep(MB_ICONEXCLAMATION);
					pResView->OnUpdate(0,0,0);
				}
			}
		}
}
*/


/*
const char * SNDEDIT_Interface::fn_czGetResNameFromEdId(unsigned long _ulId)
{
	if (g_poSNDEDITInterface->m_bEditorEnabled==FALSE) return "";
		
	IResource IRes;
	LPDISPATCH lpDispatch;
	CString csName;

	// Find corresponding resource in editor:
	lpDispatch=g_poSNDEDITInterface->m_IEditor.FindResFromEditorId(_ulId);
	if (lpDispatch==NULL) return "Unknown Id";

	IRes.AttachDispatch(lpDispatch);
	csName=IRes.GetName();
	IRes.DetachDispatch();

	return csName;
}
*/


const char * SNDEDIT_Interface::fn_czGetResNameFromEdId(unsigned long _ulId)
{
	short wEventGroupId,wResId;
	POSITION Pos;
	TSN_ResList *pResList;
	TSN_Res *pRes;


	wEventGroupId=HIWORD(_ulId);
	wResId=LOWORD(_ulId);
	
	if (g_poSNDEDITInterface->m_bEditorEnabled==FALSE) return "";
		
	Pos=NULL;
	while (pResList=g_poSNDEDITInterface->m_ResListList.GetNextElement(Pos))
		if (pResList->m_wId==wEventGroupId) break;
	if (pResList==NULL) return "Unknown Id";

	Pos=NULL;
	while (pRes=pResList->m_ResList.GetNextElement(Pos))
		if (pRes->m_wId==wResId) break;
	if (pRes==NULL) return "Unknown Id";

	return pRes->m_csName;
}


void SNDEDIT_Interface::fn_vFillResList()
{
	IEventGroups IGroups;
	IEventGroup IGroup;
	IResources IResList;
	TSN_ResList *pResList;
	TSN_Res *pRes;
	IResource IRes;
	int iNbGroups,iGroupNum,iNbRes,iResNum;

	
	IGroups.AttachDispatch(m_IEditor.GetEventGroups());
	iNbGroups=IGroups.GetCount();

	for (iGroupNum=0;iGroupNum<iNbGroups;iGroupNum++)
	{
		IGroup.AttachDispatch(IGroups.Item(iGroupNum));
		
		pResList=new TSN_ResList();
		pResList->m_csName=IGroup.GetName();
		pResList->m_wId=(short)IGroup.GetId();
		m_ResListList.AddTail(pResList);
		
		IResList.AttachDispatch(IGroup.GetResources());
		iNbRes=IResList.GetCount();
		
		for (iResNum=0;iResNum<iNbRes;iResNum++)
		{
			IRes.AttachDispatch(IResList.Item(iResNum));
			pRes=new TSN_Res();
			pRes->m_csName=IRes.GetName();
			pRes->m_wId=(short)IRes.GetId();

			pResList->m_ResList.AddTail(pRes);
			IRes.DetachDispatch();
		}// end group scan


		
		IGroup.DetachDispatch();
	}// end group scan



}

void SNDEDIT_Interface::fn_vDestroyResList()
{
	POSITION Pos,SubPos;
	TSN_ResList *pResList;
	TSN_Res *pRes;


	
		
	Pos=NULL;
	while (pResList=m_ResListList.GetNextElement(Pos))
	{
		SubPos=NULL;
		while (pRes=pResList->m_ResList.GetNextElement(SubPos)) delete pRes;
		delete pResList;
	}
}
