//  DEBUGING for SOUNDxD

#include <windows.h>
#include <winuser.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>

#include "resource.h"

#include "SNDinc.h"

#include "snddll.h"

#include "snddbg.h"
#include "sndplay.h"
#include "sndvect.h"
#include "sndres.h"
#include "sndini.h"
#include "sndtheme.h"
#include "sndvirt.h"
#include "sndevent.h"

#ifdef SUPERVISATER

static HINSTANCE hSupervisaterDLL=NULL;
static HANDLE hSupervisaterThread=NULL;
static HANDLE hMutex=NULL;
static DWORD dwSupervisaterThreadId=0;
static HWND hwndMain=NULL,hwndSupervisater=NULL,hwndHistoric=NULL,hwndVisuSnd=NULL,hwndDiversSnd=NULL,hwndVisuVirt=NULL;
static SndBool bSupervisaterActive=FALSE;

#define GOTO_BYEBYE 2
#define GOTO_SUPERVISATER 3
#define GOTO_HISTORIC 4
#define GOTO_VISUSND 5
#define GOTO_DIVERS 6
#define GOTO_VISUVIRT 7

/************ pour objet states ******************************************/
//-------- infos pour supervisater
typedef struct dbgMICRO_DESCRIPTION_ *pdbgMICRO_DESCRIPTION;

SNDLST2_M_DynamicUseListOf(pdbgMICRO_DESCRIPTION);

typedef struct dbgMICRO_DESCRIPTION_{
	long	Id;
	long	sndId;
	MicroParam par;
	SNDLST2_M_DynamicElementDeclaration(pdbgMICRO_DESCRIPTION)
}dbgMICRO_DESCRIPTION;

typedef struct dbgLISTE_MICRO_{
	SNDLST2_M_DynamicAnchorDeclaration(pdbgMICRO_DESCRIPTION) pList;
}dbgLISTE_MICRO;

//-------stockage des associations
typedef struct dbgSND_tdstEvtStruct_ *pdbgSND_tdstEvtStruct;
SNDLST2_M_DynamicUseListOf(pdbgSND_tdstEvtStruct);
typedef struct dbgSND_tdstEvtStruct_
{
	SND_tdstBlockEvent *evt_pstPtr;
	tdxId				evt_Id;
	tdeTypeEvent		evt_eType;
	long asso;
	SNDLST2_M_DynamicElementDeclaration(pdbgSND_tdstEvtStruct)
} dbgSND_tdstEvtStruct;
typedef struct dbgLISTE_EVT_{
	SNDLST2_M_DynamicAnchorDeclaration(pdbgSND_tdstEvtStruct) pList;
} dbgLISTE_EVT;

typedef struct dbgSND_tdstObjectStruct_ *pdbgSND_tdstObjectStruct;
SNDLST2_M_DynamicUseListOf(pdbgSND_tdstObjectStruct);
typedef struct dbgSND_tdstObjectStruct_
{
	//long asso;		//id de l'asso SOUND3D
	long indice;	//id de l'objet
	SoundParam par;
	dbgLISTE_EVT evts;
	SNDLST2_M_DynamicElementDeclaration(pdbgSND_tdstObjectStruct)
} dbgSND_tdstObjectStruct;
typedef struct dbgLISTE_OBJECT_{
	SNDLST2_M_DynamicAnchorDeclaration(pdbgSND_tdstObjectStruct) pList;
} dbgLISTE_OBJECT;

//variables
static dbgLISTE_MICRO dbg_micros;//liste des micros (utiliser pas SynchroSonore)
static dbgLISTE_OBJECT dbg_objects;	  //description des associations courantes
static BOOL dbg_micros_init=FALSE;
static BOOL dbg_objects_init=FALSE;

static BOOL delete_objects=FALSE;

//resource view-list
typedef struct {
	char name[20];
	int	width;
	int id_col;
} info_column;
#define NB_MICRO_COLUMN 10
static info_column micro_column[NB_MICRO_COLUMN]
={{"Micro ID",60},{"X:",60},{"Y:",60},{"Z:",60},{"NX:",60},{"NY:",60},{"NZ:",60},{"TX:",60},{"TY:",60},{"TZ:",60},};
#define MIC_COL_ID 0
#define MIC_COL_X 1
#define MIC_COL_Y 2
#define MIC_COL_Z 3
#define MIC_COL_DNX 4
#define MIC_COL_DNY 5
#define MIC_COL_DNZ 6
#define MIC_COL_DTX 7
#define MIC_COL_DTY 8
#define MIC_COL_DTZ 9
#define NB_OBJECT_COLUMN 7
static info_column object_column[NB_OBJECT_COLUMN]
={{"Object ID",60},{"X:",60},{"Y:",60},{"Extra:",60},{"Z:",60},{"D:",80},{"Evts:ptr(Id)-asso",200}};
#define OBJ_COL_ID 0
#define OBJ_COL_X 1
#define OBJ_COL_Y 2
#define OBJ_COL_Z 3
#define OBJ_COL_EXTRA 4
#define OBJ_COL_DIST 5
#define OBJ_COL_EVTS 6

/*************** pour historic *************************/
#define TAILLE_HISTORIC 256

typedef struct {
	SYSTEMTIME time;
	SND_tdstBlockEvent *evt_pstPtr;
	tdxId				evt_Id;
	tdeTypeEvent		evt_eType;
	tdstBlockResourceMem	*res_pstPtr;
	long obj;
	long type_obj;
	long asso;
	char info[80];
} historic_element;

static historic_element historic[TAILLE_HISTORIC];

static int next_element=0;
static tdstBlockResourceMem *res_for_editor=NULL;
static BOOL historic_init=FALSE;//FALSE tant que le tableau n'a pas été initialisé

//resource view-list
#define NB_HISTORIC_COLUMN 6
static info_column historic_column[NB_HISTORIC_COLUMN]
={{"Time",80},{"Obj[ptr(type)]:",80},{"Evt[type(EdID)ptr]:",120},{"Rsv[name(EdId)ptr]:",160},{"Vol",40},{"Info:",160}};
#define HIS_COL_TIME 0
#define HIS_COL_OBJ 1
#define HIS_COL_EVT 2
#define HIS_COL_RSV 3
#define HIS_COL_VOL 4
#define HIS_COL_INFO 5

static BOOL filtre_evt=FALSE,filtre_obj=FALSE,filtre_type=FALSE;
static long filtre_evtval,filtre_objval,filtre_typeval;
static BOOL most_recent=FALSE;
static BOOL last_event_only=FALSE,last_res_only=FALSE;
static long nb_most_recent=10;
static long actual_most_recent=0;
static BOOL flagDebugBreak=FALSE;

typedef struct dbgEVENT_YET_DISPLAYED_ *pdbgEVENT_YET_DISPLAYED;
typedef struct dbgRES_YET_DISPLAYED_ *pdbgRES_YET_DISPLAYED;

SNDLST2_M_DynamicUseListOf(pdbgEVENT_YET_DISPLAYED);
SNDLST2_M_DynamicUseListOf(pdbgRES_YET_DISPLAYED);

typedef struct dbgEVENT_YET_DISPLAYED_{
	SND_tdstBlockEvent* evt;
	SNDLST2_M_DynamicElementDeclaration(pdbgEVENT_YET_DISPLAYED)
}dbgEVENT_YET_DISPLAYED;
typedef struct dbgRES_YET_DISPLAYED_{
	tdstBlockResourceMem* res;
	SNDLST2_M_DynamicElementDeclaration(pdbgRES_YET_DISPLAYED)
}dbgRES_YET_DISPLAYED;

typedef struct dbgLISTE_YET_DISPLAYED_{
	SNDLST2_M_DynamicAnchorDeclaration(pdbgEVENT_YET_DISPLAYED) pListEvent;
	SNDLST2_M_DynamicAnchorDeclaration(pdbgRES_YET_DISPLAYED) pListRes;
}dbgLISTE_YET_DISPLAYED;

dbgLISTE_YET_DISPLAYED DisplayList;

/***************** pour visuSND *****************************************/
//resource view-list
#define NB_VISUSND_COLUMN 8
static info_column visusnd_column[NB_VISUSND_COLUMN]
={{"Id",60},{"Rsv:",60},{"ID Rsv:",60},{"P:",20},{"Vol:",40},{"Pan:",40},{"Space:",40},{"Freq:",40}};
#define VISUSND_COL_ID 0
#define VISUSND_COL_RES 1
#define VISUSND_COL_RESID 2
#define VISUSND_COL_PAUSE 3
#define VISUSND_COL_VOL 4
#define VISUSND_COL_PAN 5
#define VISUSND_COL_SPACE 6
#define VISUSND_COL_FREQ 7

typedef struct dbgVISUSND_ELEMENT_ *pdbgVISUSND_ELEMENT;

SNDLST2_M_DynamicUseListOf(pdbgVISUSND_ELEMENT);

typedef struct dbgVISUSND_ELEMENT_{
	long	id;
	tdstBlockResourceMem    *res_pstPtr;
	tdxId					res_Id;
	SoundParam par;
	SndBool		bPaused;
	SNDLST2_M_DynamicElementDeclaration(pdbgVISUSND_ELEMENT)
}dbgVISUSND_ELEMENT;

typedef struct dbgVISUSND_LISTE_{
	SNDLST2_M_DynamicAnchorDeclaration(pdbgVISUSND_ELEMENT) pList;
}dbgVISUSND_LISTE;

static dbgVISUSND_LISTE dbg_visusnd;
static BOOL dbg_visusnd_init=FALSE;

/***************** pour diversSND *****************************************/
//resource view-list
typedef struct dbgVOLUMELINE_DESCRIPTION_ *pdbgVOLUMELINE_DESCRIPTION;

SNDLST2_M_DynamicUseListOf(pdbgVOLUMELINE_DESCRIPTION);

typedef struct dbgVOLUMELINE_DESCRIPTION_{
	long	id;
	long	vol;
	SNDLST2_M_DynamicElementDeclaration(pdbgVOLUMELINE_DESCRIPTION)
}dbgVOLUMELINE_DESCRIPTION;

typedef struct dbgLISTE_VOLUMELINE_{
	SNDLST2_M_DynamicAnchorDeclaration(pdbgVOLUMELINE_DESCRIPTION) pList;
}dbgVOLUMELINE_MICRO;

static dbgVOLUMELINE_MICRO dbgVolumeLineSnd;
static BOOL dbgVolumeLineInit=FALSE;

#define NB_DIVERS_COLUMN 2
static info_column diverssnd_column[NB_DIVERS_COLUMN]
={{"Id",60},{"Vol:",60}};
#define DIVERSSND_COL_ID 0
#define DIVERSSND_COL_VOL 1

//************************ pour VisuVirt ********************************
#define NB_VV_COLUMN 8
static info_column vv_column[NB_VV_COLUMN]
={{"Id Voie",60},{"Paused",40},{"Res (Grp:Id (Ptr))",100},{"Loop",40},{"Norme:",60},{"Instance:",60},{"Voie audible:",80},{"Voie hard:",80}};
#define VV_COL_ID 0
#define VV_COL_PAUSE 1
#define VV_COL_RES 2
#define VV_COL_LOOP 3
#define VV_COL_NORME 4
#define VV_COL_INSTANCE 5
#define VV_COL_VA 6
#define VV_COL_VH 7

typedef struct dbgVISUVIRT_ELEMENT_ *pdbgVISUVIRT_ELEMENT;

SNDLST2_M_DynamicUseListOf(pdbgVISUVIRT_ELEMENT);

typedef struct dbgVISUVIRT_ELEMENT_{
	p_virtual_voice	id;//pointeur à ne pas utiliser; les champs sont copiés ci dessous
	SndReal rNorme;
	long	lInstance;
	p_audible_voice audible;
	long	lVoice;
	SndBool	bPaused;
	long	lResId;
	long	lResRef;
	SndBool	bLoop;
	//--- pour affichage
	SndBool bDisplayed;
	SndBool bStillActive;
	SNDLST2_M_DynamicElementDeclaration(pdbgVISUVIRT_ELEMENT)
}dbgVISUVIRT_ELEMENT;

typedef struct dbgVISUVIRT_LISTE_{
	SNDLST2_M_DynamicAnchorDeclaration(pdbgVISUVIRT_ELEMENT) pList;
	long	iIdModule;
	char	szDescription[128];
}dbgVISUVIRT_LISTE;

static dbgVISUVIRT_LISTE *p_vv_list;

static int iCurrentVirtModule=-1;
static int iNbVirtModule=0;

BOOL topmost=FALSE;

void SND_CALL dbgSND_fn_vKillEventToObjectPrivate(long indice,long asso);


SndReal dbg_calcul_pseudo_d(SndReal a,SndReal b)
{
    SndReal aa,bb;
	aa=abs(a);bb=abs(b);

    if (aa<bb)
        return (bb+(aa>>1));
    else
        return (aa+(bb>>1));
}

SndReal dbgSND_fn_rPseudoNormeVectorSnd(SndVector *v)
{
    SndReal dx,dy,dz;

    dx=abs(v->x);
    dy=abs(v->y);
    dz=abs(v->z);

    return dbg_calcul_pseudo_d(dbg_calcul_pseudo_d(dx,dy),dz);
}

/************ pour objet states ******************************************/
void refresh_liste()
{
	LV_FINDINFO lvf;
	int i,iFind;
	pdbgMICRO_DESCRIPTION pdbgMicro;
	pdbgSND_tdstObjectStruct pdbgObj;
	pdbgSND_tdstEvtStruct pevt;
	char texte[80],texte2[256];
	HWND hwnd;
	SndVector vect;

	if (hwndSupervisater)
	{
		if (!hMutex || (WaitForSingleObject(hMutex,0)==WAIT_OBJECT_0))
		{

			SNDLST2_M_DynamicForEachElementOf(&dbg_micros.pList,pdbgMicro,i)
			{		
				hwnd=GetDlgItem(hwndSupervisater,IDC_LISTMICRO);
				memset(&lvf,0,sizeof(LV_FINDINFO));
				lvf.flags=LVFI_PARAM;
				lvf.lParam=pdbgMicro->Id;
				iFind=ListView_FindItem(hwnd,-1,&lvf);

				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.pos.x));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_X].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.pos.y));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_Y].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.pos.z));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_Z].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.dirnor.x));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_DNX].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.dirnor.y));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_DNY].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.dirnor.z));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_DNZ].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.dirtan.x));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_DTX].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.dirtan.y));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_DTY].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgMicro->par.dirtan.z));
 				ListView_SetItemText(hwnd,iFind,micro_column[MIC_COL_DTZ].id_col,texte);
			}

			////
			SNDLST2_M_DynamicForEachElementOf(&dbg_objects.pList,pdbgObj,i)
			{
				memset(&lvf,0,sizeof(LV_FINDINFO));
				lvf.flags=LVFI_PARAM;
				lvf.lParam=pdbgObj->indice;
				iFind=ListView_FindItem(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),-1,&lvf);

				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgObj->par.Pos.x));
 				ListView_SetItemText(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),iFind,object_column[OBJ_COL_X].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgObj->par.Pos.y));
 				ListView_SetItemText(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),iFind,object_column[OBJ_COL_Y].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgObj->par.Pos.z));
 				ListView_SetItemText(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),iFind,object_column[OBJ_COL_Z].id_col,texte);
				sprintf(texte,"%6.3f",M_RealToDoubleSnd(pdbgObj->par.Freq));
 				ListView_SetItemText(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),iFind,object_column[OBJ_COL_EXTRA].id_col,texte);

				texte2[0]=0;
				SNDLST2_M_DynamicForEachElementOf(&dbg_micros.pList,pdbgMicro,i)
				{
					vect.x=pdbgObj->par.Pos.x-pdbgMicro->par.pos.x;
					vect.y=pdbgObj->par.Pos.y-pdbgMicro->par.pos.y;
					vect.z=pdbgObj->par.Pos.z-pdbgMicro->par.pos.z;
					sprintf(texte,"%6.3f-",M_RealToDoubleSnd(dbgSND_fn_rPseudoNormeVectorSnd(&vect)));
					strncat(texte2,texte,sizeof(texte2)-1-strlen(texte2));
				}
 				ListView_SetItemText(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),iFind,object_column[OBJ_COL_DIST].id_col,texte2);

				texte2[0]=0;
				SNDLST2_M_DynamicForEachElementOf(&pdbgObj->evts.pList,pevt,i)
				{
					sprintf(texte,"[%x(%x)-%x]-",pevt->evt_pstPtr,pevt->evt_Id,pevt->asso);
					strncat(texte2,texte,sizeof(texte2)-1-strlen(texte2));
				}
 				ListView_SetItemText(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),iFind,object_column[OBJ_COL_EVTS].id_col,texte2);
			}

			if (hMutex) ReleaseMutex(hMutex);
		}
	}
}


BOOL CALLBACK SupervisaterCallback(HWND hdwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	LV_COLUMN lvc;
	LV_ITEM lvi;
	int i,iIns;
	pdbgMICRO_DESCRIPTION pdbgMicro;
	pdbgSND_tdstObjectStruct obj,objnext;
	char texte[80];
	static BOOL auto_refresh=FALSE;

    switch (msg)                           
    {
        case WM_INITDIALOG:
			hwndSupervisater=hdwnd;
			
			for (i=0;i<NB_MICRO_COLUMN;i++)
			{
				memset(&lvc,0,sizeof(lvc));
				lvc.pszText=micro_column[i].name;
				lvc.iSubItem=i-1;
				lvc.cx=micro_column[i].width;
				lvc.mask=LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH; 
				micro_column[i].id_col=ListView_InsertColumn(GetDlgItem(hdwnd,IDC_LISTMICRO),i,&lvc);
			}
			for (i=0;i<NB_OBJECT_COLUMN;i++)
			{
				memset(&lvc,0,sizeof(lvc));
				lvc.pszText=object_column[i].name;
				lvc.cx=object_column[i].width;
				lvc.iSubItem=i-1;
				lvc.mask=LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH; 
				object_column[i].id_col=ListView_InsertColumn(GetDlgItem(hdwnd,IDC_LISTOBJECT),i,&lvc);
			}

			if (hMutex) WaitForSingleObject(hMutex,INFINITE);

			SNDLST2_M_DynamicForEachElementOf(&dbg_micros.pList,pdbgMicro,i)
			{		
				//raj liste
				memset(&lvi,0,sizeof(lvi));
				lvi.mask=LVIF_TEXT|LVIF_PARAM; 
				lvi.iItem=0; 
				lvi.iSubItem=0;
				sprintf(texte,"0x%x",pdbgMicro->Id);
				lvi.pszText=texte;
				lvi.lParam=pdbgMicro->Id;
 				iIns=ListView_InsertItem(GetDlgItem(hwndSupervisater,IDC_LISTMICRO),&lvi);
			}

			SNDLST2_M_DynamicForEachElementOf(&dbg_objects.pList,obj,i)
			{		
				//raj liste
				memset(&lvi,0,sizeof(lvi));
				lvi.mask=LVIF_TEXT|LVIF_PARAM; 
				lvi.iItem=0; 
				lvi.iSubItem=0;
				sprintf(texte,"0x%x",obj->indice);
				lvi.pszText=texte;
				lvi.lParam=obj->indice;
 				iIns=ListView_InsertItem(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),&lvi);
			}

			SendDlgItemMessage(hdwnd,IDC_DELETEOBJECTS,BM_SETCHECK,delete_objects?BST_CHECKED:BST_UNCHECKED,0);

			if (hMutex) ReleaseMutex(hMutex);
			break;
		case WM_TIMER:
			refresh_liste();
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {    
			case IDC_TOPMOST:
				topmost=!topmost;
				SetWindowText(GetDlgItem(hdwnd,IDC_TOPMOST),topmost ? "Go to back-ground" : "Go to Fore-Ground");
				SetWindowPos(hdwnd,topmost ? HWND_TOPMOST : HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
				break;
			case IDC_DELETEOBJECTS:
				if (SendDlgItemMessage(hdwnd,IDC_DELETEOBJECTS,BM_GETCHECK,0,0)==BST_CHECKED)
				{
					if (!delete_objects)
					{
						delete_objects=TRUE;
						SNDLST2_M_DynamicForEachMovingElementOf(&dbg_objects.pList,obj,objnext,i)
						{
							dbgSND_fn_vKillEventToObjectPrivate(obj->indice,(long)NULL);
						}
					}
				}
				else
					delete_objects=FALSE;
				break;
			case IDC_REFRESH:
				if (auto_refresh)
				{
					auto_refresh=FALSE;
					KillTimer(hdwnd,0);
				}

				refresh_liste();
				break;
			case IDC_AUTOREFRESH:
				if (!auto_refresh)
				{
					auto_refresh=TRUE;
					SetTimer(hdwnd,0,100,NULL);
				}
				break;
			case IDC_HISTORIC:
                EndDialog(hdwnd,GOTO_HISTORIC);
				break;
			case IDC_RESOURCES:
                EndDialog(hdwnd,GOTO_VISUSND);
				break;
			case IDC_INFORMATIONS:
                EndDialog(hdwnd,GOTO_DIVERS);
				return 1;
			case IDC_VISUVIRT:
                EndDialog(hdwnd,GOTO_VISUVIRT);
				return 1;
			case IDC_CLOSE:
                EndDialog(hdwnd,GOTO_BYEBYE);
				break;
            case IDCANCEL:
                EndDialog(hdwnd,0);
                return 1;
            }
			break;
        case WM_DESTROY:
		case WM_QUIT:
			hwndSupervisater=NULL;
            EndDialog(hdwnd,0);
            return 0;
    }
    return 0;
}

void add_evt(dbgSND_tdstObjectStruct* obj,long asso,SND_tduRefEvt evt)
{
	pdbgSND_tdstEvtStruct pevt;

	pevt=GlobalAlloc(GMEM_FIXED,sizeof(dbgSND_tdstEvtStruct));
	memset(pevt,0,sizeof(dbgSND_tdstEvtStruct));
	SNDLST2_M_DynamicInitElement(pevt);
	pevt->asso=asso;
	pevt->evt_pstPtr=evt.pstPtr;
	pevt->evt_Id=evt.pstPtr->Id;
	pevt->evt_eType=evt.pstPtr->eType;

	SNDLST2_M_DynamicAddTail(&obj->evts.pList,pevt);
}

void del_evt(dbgSND_tdstObjectStruct* obj,long asso)
{
	pdbgSND_tdstEvtStruct pevt,pevtnext;
	int i;

	SNDLST2_M_DynamicForEachMovingElementOf(&obj->evts.pList,pevt,pevtnext,i)
	{
		if ((asso==0) || (pevt->asso==asso))
		{
			SNDLST2_M_DynamicIsolate(pevt);
			GlobalFree(pevt);
		}
	}
}


/************** pour historic ***************************/
//init the display list
void init_display_liste()
{
	SNDLST2_M_DynamicInitAnchor(&DisplayList.pListEvent);
	SNDLST2_M_DynamicInitAnchor(&DisplayList.pListRes);
}
			
//desinit/purge the display list
void desinit_display_liste()
{
	pdbgEVENT_YET_DISPLAYED pEvent,pEventNext;
	pdbgRES_YET_DISPLAYED pRes,pResNext;
	int i;

	SNDLST2_M_DynamicForEachMovingElementOf(&DisplayList.pListEvent,pEvent,pEventNext,i)
	{
		SNDLST2_M_DynamicIsolate(pEvent);
		GlobalFree(pEvent);
	}
	SNDLST2_M_DynamicForEachMovingElementOf(&DisplayList.pListRes,pRes,pResNext,i)
	{
		SNDLST2_M_DynamicIsolate(pRes);
		GlobalFree(pRes);
	}
}
	
//add a event in the display list/ return FALSE if event has not been yet displayed
SndBool event_displayed(SND_tdstBlockEvent* event)	
{
	SndBool bFound=FALSE;
	pdbgEVENT_YET_DISPLAYED pEvent;
	int i;

	SNDLST2_M_DynamicForEachElementOf(&DisplayList.pListEvent,pEvent,i)
	{
		if (pEvent->evt==event)
		{
			bFound=TRUE;
			break;
		}
	}

	if (!bFound)
	{
		pEvent=GlobalAlloc(GMEM_FIXED,sizeof(dbgEVENT_YET_DISPLAYED));
		SNDLST2_M_DynamicInitElement(pEvent);
		pEvent->evt=event;
		SNDLST2_M_DynamicAddTail(&DisplayList.pListEvent,pEvent);
	}

	return bFound;
}

//add a res in the display list/ return FALSE if res has not been yet displayed
SndBool res_displayed(tdstBlockResourceMem* res)	
{
	SndBool bFound=FALSE;
	pdbgRES_YET_DISPLAYED pRes;
	int i;

	SNDLST2_M_DynamicForEachElementOf(&DisplayList.pListRes,pRes,i)
	{
		if (pRes->res==res)
		{
			bFound=TRUE;
			break;
		}
	}

	if (!bFound)
	{
		pRes=GlobalAlloc(GMEM_FIXED,sizeof(dbgRES_YET_DISPLAYED));
		SNDLST2_M_DynamicInitElement(pRes);
		pRes->res=res;
		SNDLST2_M_DynamicAddTail(&DisplayList.pListRes,pRes);
	}

	return bFound;
}

void add_histo(historic_element *hist)
{
	LV_ITEM lvi;
	int iIns;
	HWND hwnd;
	char texte[80],texte2[50];

	if (hwndHistoric)
	{
		hwnd=GetDlgItem(hwndHistoric,IDC_LISTE);
		//raj liste
		memset(&lvi,0,sizeof(lvi));
		lvi.mask=LVIF_TEXT|LVIF_PARAM; 
		lvi.iItem=0; 
		lvi.iSubItem=0;
		sprintf(texte,"%02d:%02d:%02d:%03d(%d)",hist->time.wHour,hist->time.wMinute,hist->time.wSecond,hist->time.wMilliseconds,hist);
		lvi.pszText=texte;
		lvi.lParam=(long)hist;
		if (most_recent && (actual_most_recent>nb_most_recent))
	 		ListView_DeleteItem(hwnd,0);
		else
			actual_most_recent++;

		iIns=ListView_InsertItem(hwnd,&lvi);
		sprintf(texte,"0x%x (%d)",hist->obj,hist->type_obj);
 		ListView_SetItemText(hwnd,iIns,historic_column[HIS_COL_OBJ].id_col,texte);

		switch (hist->evt_eType)
		{
		case EVT_SON_PLAY : sprintf(texte2,"PLAY");break;
		case EVT_SON_STOP : sprintf(texte2,"STOP");break;
		case EVT_SON_STOP_ALL : sprintf(texte2,"STOP_ALL");break;
		case EVT_SON_STOP_N_GO: sprintf(texte2,"STOP_N_GO");break;
		case EVT_SON_STOP_N_GO_CROSSFADE : sprintf(texte2,"STOP_N_GO_CROSSFADE");break;
		case EVT_SON_PITCH : sprintf(texte2,"XTRAPITCH");break;
		case EVT_SON_VOLUME : sprintf(texte2,"XTRAVOLUME");break;
		case EVT_SON_PAN : sprintf(texte2,"XTRAPAN");break;
		case EVT_SON_EFFET: sprintf(texte2,"EFFET");break;
		case EVT_SON_CHANGE_VOLUME: sprintf(texte2,"CHNGVOL");break;
		default: sprintf(texte2,"????");break;
		}
		sprintf(texte,"%s:(0x%x)Ox%x",texte2,hist->evt_Id,hist->evt_pstPtr);
 		ListView_SetItemText(hwnd,iIns,historic_column[HIS_COL_EVT].id_col,texte);

		if (hist->res_pstPtr)
		{
			strncpy(texte2,SND_fn_czGetResNameFromEdId(hist->res_pstPtr->Id),sizeof(texte2)-1);
			sprintf(texte,"%s (0x%x)0x%x",texte2,hist->res_pstPtr->Id,hist->res_pstPtr);
 			ListView_SetItemText(hwnd,iIns,historic_column[HIS_COL_RSV].id_col,texte);

			sprintf(texte,"%d",hist->res_pstPtr->ucVolume);
 			ListView_SetItemText(hwnd,iIns,historic_column[HIS_COL_VOL].id_col,texte);	
		}
		else
		{
 			ListView_SetItemText(hwnd,iIns,historic_column[HIS_COL_RSV].id_col,"no resource");
 			ListView_SetItemText(hwnd,iIns,historic_column[HIS_COL_VOL].id_col,"?");	
		}

		ListView_SetItemText(hwnd,iIns,historic_column[HIS_COL_INFO].id_col,hist->info);
	}
}

BOOL filtre(historic_element *hist)
{
	if (hist->time.wYear==0)
		return TRUE;
	if (filtre_evt && ((long)hist->evt_pstPtr!=filtre_evtval))
		return TRUE;
	if (filtre_obj && (hist->obj!=filtre_objval))
		return TRUE;
	if (filtre_type && (hist->evt_eType!=filtre_typeval))
		return TRUE;
	if (last_event_only && event_displayed(hist->evt_pstPtr))
		return TRUE;
	if (last_res_only && (hist->res_pstPtr!=NULL) && res_displayed(hist->res_pstPtr))
		return TRUE;
	return FALSE;
}

void refresh_historic()
{
	int i;

	//purge list of previous instance
	desinit_display_liste();

	actual_most_recent=0;
	for (i=next_element-1+TAILLE_HISTORIC;i>next_element-1;i--)
	{
		if (!filtre(&historic[i%TAILLE_HISTORIC]))
		{
			add_histo(&historic[i%TAILLE_HISTORIC]);
			//actual_most_recent++;
		}
		if ((most_recent) && (actual_most_recent>=nb_most_recent))
			break;
	}
}

void check_change(long vIDC_FILTREEVT,long vIDC_FILTREOBJ,long vIDC_FILTREEVTTYPE,long vIDC_MOSTRECENT,long vIDC_FIRSTEVENTONLY,long vIDC_FIRSTRESONLY)
{
	BOOL old_filtre_evt=filtre_evt;
	BOOL old_filtre_obj=filtre_obj;
	BOOL old_filtre_type=filtre_type;
	BOOL old_most_recent=most_recent;
	BOOL old_last_event_only=last_event_only;
	BOOL old_last_res_only=last_res_only;

	filtre_evt=(vIDC_FILTREEVT==BST_CHECKED)?TRUE:FALSE;
	filtre_obj=(vIDC_FILTREOBJ==BST_CHECKED)?TRUE:FALSE;
	filtre_type=(vIDC_FILTREEVTTYPE==BST_CHECKED)?TRUE:FALSE;
	most_recent=(vIDC_MOSTRECENT==BST_CHECKED)?TRUE:FALSE;
	last_event_only=(vIDC_FIRSTEVENTONLY==BST_CHECKED)?TRUE:FALSE;
	last_res_only=(vIDC_FIRSTRESONLY==BST_CHECKED)?TRUE:FALSE;

	if ((old_filtre_evt!=filtre_evt)
		|| (old_filtre_obj!=filtre_obj)
		|| (old_filtre_type!=filtre_type)
		|| (old_most_recent!=most_recent)
		|| (old_last_event_only!=last_event_only)
		|| (old_last_res_only!=last_res_only))
	{
			ListView_DeleteAllItems(GetDlgItem(hwndHistoric,IDC_LISTE));
			refresh_historic();
	}
}


BOOL CALLBACK HistoricCallback(HWND hdwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	LV_COLUMN lvc;
	int i;
	static int prev_n=0;
	SYSTEMTIME cur_time;
	FILETIME cur_filetime,filetime;
	char texte[80];
	LPNMHDR	nmhdr;
	NM_LISTVIEW *nm;

    switch (msg)                           
    {
        case WM_INITDIALOG:
			hwndHistoric=hdwnd;

			init_display_liste();
			
			for (i=0;i<NB_HISTORIC_COLUMN;i++)
			{
				memset(&lvc,0,sizeof(lvc));
				lvc.pszText=historic_column[i].name;
				lvc.iSubItem=i-1;
				lvc.cx=historic_column[i].width;
				lvc.mask=LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH; 
				historic_column[i].id_col=ListView_InsertColumn(GetDlgItem(hdwnd,IDC_LISTE),i,&lvc);
			}

			for (i=0;i<TAILLE_HISTORIC;i++)
				if (!filtre(&historic[i]))
					add_histo(&historic[i]);

			SendDlgItemMessage(hdwnd,IDC_DELETEOBJECTS,BM_SETCHECK,delete_objects?BST_CHECKED:BST_UNCHECKED,0);

			if (hMutex) ReleaseMutex(hMutex);

			SendDlgItemMessage(hdwnd,IDC_FILTREEVT,BM_SETCHECK,filtre_evt?BST_CHECKED:BST_UNCHECKED,0);
			SendDlgItemMessage(hdwnd,IDC_FILTREOBJ,BM_SETCHECK,filtre_obj?BST_CHECKED:BST_UNCHECKED,0);
			SendDlgItemMessage(hdwnd,IDC_FILTREEVTTYPE,BM_SETCHECK,filtre_type?BST_CHECKED:BST_UNCHECKED,0);
			SendDlgItemMessage(hdwnd,IDC_MOSTRECENT,BM_SETCHECK,most_recent?BST_CHECKED:BST_UNCHECKED,0);
			SendDlgItemMessage(hdwnd,IDC_FIRSTEVENTONLY,BM_SETCHECK,last_event_only?BST_CHECKED:BST_UNCHECKED,0);
			SendDlgItemMessage(hdwnd,IDC_FIRSTRESONLY,BM_SETCHECK,last_res_only?BST_CHECKED:BST_UNCHECKED,0);
			sprintf(texte,"0x%x",filtre_evtval);
			SetDlgItemText(hdwnd,IDC_FILTREEVTVAL,texte);
			sprintf(texte,"0x%x",filtre_objval);
			SetDlgItemText(hdwnd,IDC_FILTREOBJVAL,texte);
			sprintf(texte,"0x%x",filtre_typeval);
			SetDlgItemText(hdwnd,IDC_FILTREEVTTYPEVAL,texte);
			sprintf(texte,"%d",nb_most_recent);
			SetDlgItemText(hdwnd,IDC_NBMOSTRECENT,texte);

			SetTimer(hdwnd,1,1000,NULL);
			break;
		case WM_TIMER:
			GetLocalTime(&cur_time);
			sprintf(texte,"%02d:%02d:%02d:%03d",cur_time.wHour,cur_time.wMinute,cur_time.wSecond,cur_time.wMilliseconds);
			SetDlgItemText(hdwnd,IDC_CURRENTTIME,texte);
			break;
		case WM_NOTIFY:
			switch (LOWORD(wParam))
			{
			case IDC_LISTE:
				nmhdr=(LPNMHDR)lParam;
				switch (nmhdr->code)
				{
				case LVN_ITEMCHANGED:
					nm=(NM_LISTVIEW*)lParam;

					if (nm->uNewState & LVIS_SELECTED)
					{
						if (nm->lParam != (long)NULL)
							res_for_editor=((historic_element*)(nm->lParam))->res_pstPtr;
						else
							res_for_editor=NULL;

						if (!res_for_editor)
							sprintf(texte,"none");
						else
							sprintf(texte,"%40s (EdId=0x%d; ptr=0x%d)",SND_fn_czGetResNameFromEdId(res_for_editor->Id),res_for_editor->Id,res_for_editor);

						SetDlgItemText(hdwnd,IDC_SELECTEDRESOURCE,texte);
					}
					break;
				}
				break;
			}
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {    
			case IDC_TOPMOST:
				topmost=!topmost;
				SetWindowText(GetDlgItem(hdwnd,IDC_TOPMOST),topmost ? "Go to back-ground" : "Go to Fore-Ground");
				SetWindowPos(hdwnd,topmost ? HWND_TOPMOST : HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
				break;
			case IDC_FILTREEVT:
			case IDC_FILTREOBJ:
			case IDC_FILTREEVTTYPE:
			case IDC_MOSTRECENT:
			case IDC_FIRSTEVENTONLY:
			case IDC_FIRSTRESONLY:
				GetDlgItemText(hdwnd,IDC_FILTREEVTVAL,texte,sizeof(texte));
				sscanf(texte,"%x",&filtre_evtval);
				sprintf(texte,"%x",filtre_evtval);
				SetDlgItemText(hdwnd,IDC_FILTREEVTVAL,texte);
				GetDlgItemText(hdwnd,IDC_FILTREOBJVAL,texte,sizeof(texte));
				sscanf(texte,"%x",&filtre_objval);
				sprintf(texte,"%x",filtre_objval);
				SetDlgItemText(hdwnd,IDC_FILTREOBJVAL,texte);
				GetDlgItemText(hdwnd,IDC_FILTREEVTTYPEVAL,texte,sizeof(texte));
				sscanf(texte,"%x",&filtre_typeval);
				sprintf(texte,"%x",filtre_typeval);
				SetDlgItemText(hdwnd,IDC_FILTREEVTTYPEVAL,texte);
				GetDlgItemText(hdwnd,IDC_NBMOSTRECENT,texte,sizeof(texte));
				sscanf(texte,"%d",&filtre_typeval);
				sprintf(texte,"%d",filtre_typeval);
				SetDlgItemText(hdwnd,IDC_NBMOSTRECENT,texte);
				sscanf(texte,"%d",&nb_most_recent);
				check_change(
					SendDlgItemMessage(hdwnd,IDC_FILTREEVT,BM_GETCHECK,0,0)
					,SendDlgItemMessage(hdwnd,IDC_FILTREOBJ,BM_GETCHECK,0,0)
					,SendDlgItemMessage(hdwnd,IDC_FILTREEVTTYPE,BM_GETCHECK,0,0)
					,SendDlgItemMessage(hdwnd,IDC_MOSTRECENT,BM_GETCHECK,0,0)
					,SendDlgItemMessage(hdwnd,IDC_FIRSTEVENTONLY,BM_GETCHECK,0,0)
					,SendDlgItemMessage(hdwnd,IDC_FIRSTRESONLY,BM_GETCHECK,0,0)
					);
				break;		
			case IDC_DEBUGBREAK:
				if (SendDlgItemMessage(hdwnd,IDC_FILTREEVT,BM_GETCHECK,0,0)==BST_CHECKED)
					flagDebugBreak=TRUE;
				else
					flagDebugBreak=FALSE;
				break;
			case IDC_PURGETOTALE:
				memset(historic,0,sizeof(historic));
				ListView_DeleteAllItems(GetDlgItem(hdwnd,IDC_LISTE));
				refresh_historic();
				break;
			case IDC_PURGE20:
				ListView_DeleteAllItems(GetDlgItem(hdwnd,IDC_LISTE));
				GetLocalTime(&cur_time);
				SystemTimeToFileTime(&cur_time,&cur_filetime);
				for (i=0;i<TAILLE_HISTORIC;i++)
				{
					SystemTimeToFileTime(&historic[i].time,&filetime);
					filetime.dwLowDateTime+=200000000;
					if (filetime.dwLowDateTime<200000000)
						filetime.dwHighDateTime++;
					if (CompareFileTime(&filetime,&cur_filetime)==-1)
						memset(&historic[i],0,sizeof(historic[i]));
				}
				refresh_historic();
				break;
			case IDC_SUPERVISATER:
                EndDialog(hdwnd,GOTO_SUPERVISATER);
				return 1;
			case IDC_RESOURCES:
                EndDialog(hdwnd,GOTO_VISUSND);
				break;
			case IDC_INFORMATIONS:
                EndDialog(hdwnd,GOTO_DIVERS);
				return 1;
			case IDC_VISUVIRT:
                EndDialog(hdwnd,GOTO_VISUVIRT);
				break;
			case IDC_CLOSE:
                EndDialog(hdwnd,GOTO_BYEBYE);
				return 1;
            case IDCANCEL:
                EndDialog(hdwnd,0);
                return 1;
            }
			break;
        case WM_DESTROY:
		case WM_QUIT:
            EndDialog(hdwnd,0);
            return 0;
    }
    return 0;
}


/************* pour visusnd ****************************/
void refresh_liste_visusnd()
{
	LV_FINDINFO lvf;
	int i,iFind;
	pdbgVISUSND_ELEMENT pdbgVisuSnd;
	char texte[80];
	HWND hwnd;

	if (hwndVisuSnd)
	{
		if (!hMutex || (WaitForSingleObject(hMutex,0)==WAIT_OBJECT_0))
		{

			SNDLST2_M_DynamicForEachElementOf(&dbg_visusnd.pList,pdbgVisuSnd,i)
			{		
				hwnd=GetDlgItem(hwndVisuSnd,IDC_LISTE);
				memset(&lvf,0,sizeof(LV_FINDINFO));
				lvf.flags=LVFI_PARAM;
				lvf.lParam=pdbgVisuSnd->id;
				iFind=ListView_FindItem(hwnd,-1,&lvf);

				sprintf(texte,"%x",pdbgVisuSnd->res_pstPtr);
 				ListView_SetItemText(hwnd,iFind,visusnd_column[VISUSND_COL_RES].id_col,texte);
				sprintf(texte,"%x",(pdbgVisuSnd->res_pstPtr!=NULL)?pdbgVisuSnd->res_Id:-1);
 				ListView_SetItemText(hwnd,iFind,visusnd_column[VISUSND_COL_RESID].id_col,texte);
				sprintf(texte,"%d",pdbgVisuSnd->par.ucVol);
 				ListView_SetItemText(hwnd,iFind,visusnd_column[VISUSND_COL_PAUSE].id_col,texte);
				strcpy(texte,pdbgVisuSnd->bPaused?"P":" ");
 				ListView_SetItemText(hwnd,iFind,visusnd_column[VISUSND_COL_VOL].id_col,texte);
				sprintf(texte,"%d",pdbgVisuSnd->par.ucPan);
 				ListView_SetItemText(hwnd,iFind,visusnd_column[VISUSND_COL_PAN].id_col,texte);
				sprintf(texte,"%d",pdbgVisuSnd->par.ucSpace);
 				ListView_SetItemText(hwnd,iFind,visusnd_column[VISUSND_COL_SPACE].id_col,texte);
				sprintf(texte,"%3.2f",M_RealToDoubleSnd(pdbgVisuSnd->par.Freq));
 				ListView_SetItemText(hwnd,iFind,visusnd_column[VISUSND_COL_FREQ].id_col,texte);
			}

			if (hMutex) ReleaseMutex(hMutex);
		}
	}
}

BOOL CALLBACK VisuSndCallback(HWND hdwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	LV_COLUMN lvc;
	LV_ITEM lvi;
	int i,iIns;
	pdbgVISUSND_ELEMENT pdbgVisuSnd;
	char texte[80];
	static BOOL auto_refresh=FALSE;

    switch (msg)                           
    {
        case WM_INITDIALOG:
			if (hMutex) WaitForSingleObject(hMutex,INFINITE);

			hwndVisuSnd=hdwnd;
			
			for (i=0;i<NB_VISUSND_COLUMN;i++)
			{
				memset(&lvc,0,sizeof(lvc));
				lvc.pszText=visusnd_column[i].name;
				lvc.iSubItem=i-1;
				lvc.cx=micro_column[i].width;
				lvc.mask=LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH; 
				visusnd_column[i].id_col=ListView_InsertColumn(GetDlgItem(hdwnd,IDC_LISTE),i,&lvc);
			}

			SNDLST2_M_DynamicForEachElementOf(&dbg_visusnd.pList,pdbgVisuSnd,i)
			{		
				//raj liste
				memset(&lvi,0,sizeof(lvi));
				lvi.mask=LVIF_TEXT|LVIF_PARAM; 
				lvi.iItem=0; 
				lvi.iSubItem=0;
				sprintf(texte,"0x%x",pdbgVisuSnd->id);
				lvi.pszText=texte;
				lvi.lParam=pdbgVisuSnd->id;
 				iIns=ListView_InsertItem(GetDlgItem(hwndVisuSnd,IDC_LISTE),&lvi);
			}

			if (hMutex) ReleaseMutex(hMutex);
			break;
		case WM_TIMER:
			refresh_liste_visusnd();
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {       
			case IDC_TOPMOST:
				topmost=!topmost;
				SetWindowText(GetDlgItem(hdwnd,IDC_TOPMOST),topmost ? "Go to back-ground" : "Go to Fore-Ground");
				SetWindowPos(hdwnd,topmost ? HWND_TOPMOST : HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
				break;
			case IDC_REFRESH:
				if (auto_refresh)
				{
					auto_refresh=FALSE;
					KillTimer(hdwnd,0);
				}

				refresh_liste_visusnd();
				break;
			case IDC_AUTOREFRESH:
				if (!auto_refresh)
				{
					auto_refresh=TRUE;
					SetTimer(hdwnd,0,100,NULL);
				}
				break;
			case IDC_HISTORIC:
                EndDialog(hdwnd,GOTO_HISTORIC);
				break;
			case IDC_SUPERVISATER:
                EndDialog(hdwnd,GOTO_SUPERVISATER);
				return 1;
			case IDC_INFORMATIONS:
                EndDialog(hdwnd,GOTO_DIVERS);
				return 1;
			case IDC_CLOSE:
                EndDialog(hdwnd,GOTO_BYEBYE);
				break;
            case IDCANCEL:
                EndDialog(hdwnd,0);
                return 1;
			case IDC_VISUVIRT:
                EndDialog(hdwnd,GOTO_VISUVIRT);
				break;
            }
			break;
        case WM_DESTROY:
		case WM_QUIT:
            EndDialog(hdwnd,0);
            return 0;
    }
    return 0;
}

//*********************** voies virtuelles
void refresh_liste_virt()
{
	pdbgVISUVIRT_ELEMENT dbgv,dbgvnext;
	int iDel,iIns,iFind,i;
	LV_FINDINFO lvf;
	LV_ITEM lvi;
	char texte[80];
	SND_tdhVirtualModule p_virtual_module;
	HWND hwnd;

	if (hMutex) WaitForSingleObject(hMutex,INFINITE);

	p_virtual_module=(SND_tdhVirtualModule)p_vv_list[iCurrentVirtModule].iIdModule;

	sprintf(texte,"%d/%d",SNDLST2_M_DynamicGetNumberOfElements(&p_virtual_module->virtual_voices.pList),p_virtual_module->g_lNbSxdAudible);
	SetDlgItemText(hwndVisuVirt,IDC_NBVOIX,texte);

	hwnd=GetDlgItem(hwndVisuVirt,IDC_LISTVV);

	//2:raj de anciennes lignes et ajoûts des nouvelles
	SNDLST2_M_DynamicForEachMovingElementOf(&p_vv_list[iCurrentVirtModule].pList,dbgv,dbgvnext,i)
	{//pour chacune voies actuelle
		if (!dbgv->bStillActive)
		{//voie détruite->effacer la ligne
			memset(&lvf,0,sizeof(LV_FINDINFO));
			lvf.flags=LVFI_PARAM;
			lvf.lParam=(long)dbgv;
			iFind=ListView_FindItem(hwnd,-1,&lvf);
			if (iFind!=-1)
				iDel=ListView_DeleteItem(hwnd,iFind);

			SNDLST2_M_DynamicIsolate(dbgv);
			GlobalFree(dbgv);
		}
		else
		{
			if (!dbgv->bDisplayed)
			{
				memset(&lvi,0,sizeof(lvi));
				lvi.mask=LVIF_TEXT|LVIF_PARAM; 
				lvi.iItem=0; 
				lvi.iSubItem=0;
				sprintf(texte,"0x%x",dbgv);
				lvi.pszText=texte;
				lvi.lParam=(long)dbgv;
 				iIns=ListView_InsertItem(hwnd,&lvi);

				dbgv->bDisplayed=TRUE;
			}

			memset(&lvf,0,sizeof(LV_FINDINFO));
			lvf.flags=LVFI_PARAM;
			lvf.lParam=(long)dbgv;
			iFind=ListView_FindItem(hwnd,-1,&lvf);

			sprintf(texte,"%f",M_RealToDoubleSnd(dbgv->rNorme));
			ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_NORME].id_col,texte);
			sprintf(texte,"%s",dbgv->bPaused?"P":" ");
			ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_PAUSE].id_col,texte);
			sprintf(texte,"%d:%d (0x%x)",(dbgv->lResId>>16)&0xFFFF,dbgv->lResId&0xFFFF,dbgv->lResRef);
			ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_RES].id_col,texte);
			sprintf(texte,"%s",dbgv->bLoop?"Loop":" ");
			ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_LOOP].id_col,texte);
			sprintf(texte,"%d",dbgv->lInstance);
			ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_INSTANCE].id_col,texte);
			if (dbgv->audible)
			{
				sprintf(texte,"0x%x",dbgv->audible);
				ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VA].id_col,texte);
				sprintf(texte,"0x%x",dbgv->lVoice);
				ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VH].id_col,texte);
			}
			else
			{
				sprintf(texte," ");
				ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VA].id_col,texte);
				sprintf(texte," ");
				ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VH].id_col,texte);
			}
		}
	}

	if (hMutex) ReleaseMutex(hMutex);
}

BOOL CALLBACK VisuVirtCallback(HWND hdwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	LV_COLUMN lvc;
	int i,j;
	pdbgVISUVIRT_ELEMENT dbgv,dbgvnext;
	char texte[128];
	long ret;

    switch (msg)                           
    {
        case WM_INITDIALOG:
			hwndVisuVirt=hdwnd;
			
			if (hMutex) WaitForSingleObject(hMutex,INFINITE);

			for (i=0;i<NB_VV_COLUMN;i++)
			{
				memset(&lvc,0,sizeof(lvc));
				lvc.pszText=vv_column[i].name;
				lvc.iSubItem=i-1;
				lvc.cx=vv_column[i].width;
				lvc.mask=LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH; 
				vv_column[i].id_col=ListView_InsertColumn(GetDlgItem(hdwnd,IDC_LISTVV),i,&lvc);
			}

			//init de vv_list
			ret=SendDlgItemMessage(hdwnd,IDC_LISTEMODULE,CB_RESETCONTENT,0,0);
			for (i=0;i<iNbVirtModule;i++)
			{
				SNDLST2_M_DynamicInitAnchor(&p_vv_list[i].pList);
				ret=SendDlgItemMessage(hdwnd,IDC_LISTEMODULE,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)p_vv_list[i].szDescription);
			}

			iCurrentVirtModule=iNbVirtModule-1;
			if (iCurrentVirtModule>=0)
			{
				ret=SendDlgItemMessage(hdwnd,IDC_LISTEMODULE,CB_SELECTSTRING,0,(LPARAM)(LPCTSTR)p_vv_list[iCurrentVirtModule].szDescription);
				SetDlgItemText(hdwnd,IDC_NBVOIX,"?");
			}

			if (hMutex) ReleaseMutex(hMutex);

			SetTimer(hdwnd,0,100,NULL);

			break;
		case WM_TIMER:
			refresh_liste_virt();
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {       
			case IDC_TOPMOST:
				topmost=!topmost;
				SetWindowText(GetDlgItem(hdwnd,IDC_TOPMOST),topmost ? "Go to back-ground" : "Go to Fore-Ground");
				SetWindowPos(hdwnd,topmost ? HWND_TOPMOST : HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
				break;
			case IDC_HISTORIC:
                EndDialog(hdwnd,GOTO_HISTORIC);
				break;
			case IDC_RESOURCES:
                EndDialog(hdwnd,GOTO_VISUSND);
				break;
			case IDC_INFORMATIONS:
                EndDialog(hdwnd,GOTO_DIVERS);
				return 1;
			case IDC_VISUVIRT:
                EndDialog(hdwnd,GOTO_VISUVIRT);
				return 1;
			case IDC_CLOSE:
                EndDialog(hdwnd,GOTO_BYEBYE);
				break;
            case IDCANCEL:
                EndDialog(hdwnd,0);
                return 1;
			case IDC_LISTEMODULE:
				SendDlgItemMessage(hdwnd,IDC_LISTEMODULE,CB_GETLBTEXT,(WPARAM)SendDlgItemMessage(hdwnd,IDC_LISTEMODULE,CB_GETCURSEL,0,0),(LPARAM)texte);

				if (hMutex) WaitForSingleObject(hMutex,INFINITE);

				for (i=0;i<iNbVirtModule;i++)
				{
					if (!strcmp(p_vv_list[i].szDescription,texte) && (i!=iCurrentVirtModule))
					{
						SNDLST2_M_DynamicForEachMovingElementOf(&p_vv_list[iCurrentVirtModule].pList,dbgv,dbgvnext,j)
						{
							SNDLST2_M_DynamicIsolate(dbgv);
							GlobalFree(dbgv);
						}

						iCurrentVirtModule=i;

						ListView_DeleteAllItems(GetDlgItem(hdwnd,IDC_LISTVV));

						SetDlgItemText(hdwnd,IDC_NBVOIX,"?");
					}
				}

				if (hMutex) ReleaseMutex(hMutex);

				break;
            }
			break;
        case WM_DESTROY:
		case WM_QUIT:
			//desinit de vv_list
			if (hMutex) WaitForSingleObject(hMutex,INFINITE);

			for (i=0;i<iNbVirtModule;i++)
			{
				SNDLST2_M_DynamicForEachMovingElementOf(&p_vv_list[i].pList,dbgv,dbgvnext,j)
				{
					SNDLST2_M_DynamicIsolate(dbgv);
					GlobalFree(dbgv);
				}
			}

			if (hMutex) ReleaseMutex(hMutex);

			hwndVisuVirt=NULL;
            EndDialog(hdwnd,0);
            return 0;
    }
    return 0;
}

//obsolète
void SND_CALL dbgSND_fn_vRajListesSxdVirtual(void* VV,void* VA,void* VD)
{
}

void SND_CALL dbgSND_fn_vInitListesSxdVirtual(long virtual_module,char* descrpition)
{
	if (hMutex) WaitForSingleObject(hMutex,INFINITE);

	if (iNbVirtModule)
		p_vv_list=GlobalReAlloc(p_vv_list,(iNbVirtModule+1)*sizeof(*p_vv_list),GMEM_MOVEABLE);
	else
		p_vv_list=GlobalAlloc(GMEM_FIXED,sizeof(*p_vv_list));

	p_vv_list[iNbVirtModule].iIdModule=virtual_module;
	strncpy(p_vv_list[iNbVirtModule].szDescription,descrpition,sizeof(p_vv_list[iNbVirtModule].szDescription)-1);

	iNbVirtModule++;

	if (hMutex) ReleaseMutex(hMutex);
}

void SND_CALL dbgSND_fn_vRajListesSxdVirtual2(SND_tdhVirtualModule p_virtual_module)
{
	virtual_voice_list* VV=&p_virtual_module->virtual_voices;
	audible_voice_list* VA=&p_virtual_module->audible_voices;
	dead_voice_list* VD=&p_virtual_module->dead_voices;
	p_virtual_voice v;
	pdbgVISUVIRT_ELEMENT dbgv,dbgvnext;
	SndBool bFound;
	int i,j;
	int id_module;

	if (hwndVisuVirt)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		/*zz
		hwnd=GetDlgItem(hwndVisuVirt,IDC_LISTVV);
		*/

		//recherche du bon module
		bFound=FALSE;
		for (id_module=0;id_module<iNbVirtModule;id_module++)
		{
			if (p_vv_list[id_module].iIdModule==(long)p_virtual_module)
			{
				bFound=TRUE;
				break;
			}
		}

		if (bFound && id_module==iCurrentVirtModule)
		{
			/*zz
			sprintf(texte,"%d/%d",SNDLST2_M_DynamicGetNumberOfElements(&p_virtual_module->virtual_voices.pList),p_virtual_module->g_lNbSxdAudible);
			SetDlgItemText(hwndVisuVirt,IDC_NBVOIX,texte);
			*/

			//1:élimination des lignes obsolètes
			SNDLST2_M_DynamicForEachMovingElementOf(&p_vv_list[id_module].pList,dbgv,dbgvnext,i)
			{
				bFound=FALSE;
				SNDLST2_M_DynamicForEachElementOf(&VV->pList,v,j)
				{
					if (v==dbgv->id)
					{
						bFound=TRUE;
						break;
					}
				}
				if (!bFound)
				{//to be destroyed
					/*zz
					memset(&lvf,0,sizeof(LV_FINDINFO));
					lvf.flags=LVFI_PARAM;
					lvf.lParam=(long)dbgv;
					iFind=ListView_FindItem(hwnd,-1,&lvf);
					if (iFind!=-1)
						iDel=ListView_DeleteItem(hwnd,iFind);

					SNDLST2_M_DynamicIsolate(dbgv);
					GlobalFree(dbgv);
					*/
					dbgv->bStillActive=FALSE;
				}
			}
			//2:raj de anciennes lignes et ajoûts des nouvelles
			SNDLST2_M_DynamicForEachElementOf(&VV->pList,v,i)
			{//pour chacune voies actuelle
				bFound=FALSE;
				SNDLST2_M_DynamicForEachElementOf(&p_vv_list[id_module].pList,dbgv,j)
				{//vette voix éxistait-elle déjà
					if ((dbgv->id==v) && (dbgv->bStillActive))
					{
						bFound=TRUE;
						break;
					}
				}
				if (!bFound)
				{
					dbgv=GlobalAlloc(GMEM_FIXED,sizeof(*dbgv));
					SNDLST2_M_DynamicInitElement(dbgv);
					SNDLST2_M_DynamicAddTail(&p_vv_list[id_module].pList,dbgv);

					dbgv->bDisplayed=FALSE;
					dbgv->bStillActive=TRUE;
/*zz
					memset(&lvi,0,sizeof(lvi));
					lvi.mask=LVIF_TEXT|LVIF_PARAM; 
					lvi.iItem=0; 
					lvi.iSubItem=0;
					sprintf(texte,"0x%x",dbgv);
					lvi.pszText=texte;
					lvi.lParam=(long)dbgv;
 					iIns=ListView_InsertItem(hwnd,&lvi);
					*/
				}
				dbgv->id=v;
				dbgv->rNorme=v->rNorme;
				dbgv->lInstance=v->lInstance;
				dbgv->audible=v->audible;
				dbgv->lVoice=v->lVoice;
				dbgv->bPaused=v->bPaused;
				dbgv->lResId=v->tduRes.pstPtr->Id;
				dbgv->lResRef=(long)v->tduRes.pstPtr;
				dbgv->bLoop=v->tduRes.pstPtr->uRes.stSample.bLoop;

				/*zz
				memset(&lvf,0,sizeof(LV_FINDINFO));
				lvf.flags=LVFI_PARAM;
				lvf.lParam=(long)dbgv;
				iFind=ListView_FindItem(hwnd,-1,&lvf);

				sprintf(texte,"%f",M_RealToDoubleSnd(dbgv->rNorme));
				ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_NORME].id_col,texte);
				sprintf(texte,"%s",dbgv->bPaused?"P":" ");
				ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_PAUSE].id_col,texte);
				sprintf(texte,"%d",dbgv->lInstance);
				ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_INSTANCE].id_col,texte);
				if (dbgv->audible)
				{
					sprintf(texte,"0x%x",dbgv->audible);
					ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VA].id_col,texte);
					sprintf(texte,"0x%x",dbgv->lVoice);
					ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VH].id_col,texte);
				}
				else
				{
					sprintf(texte," ");
					ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VA].id_col,texte);
					sprintf(texte," ");
					ListView_SetItemText(hwnd,iFind,vv_column[VV_COL_VH].id_col,texte);
				}
				*/
			}
		}//if bFound

		if (hMutex) ReleaseMutex(hMutex);
	}
}


//*********** info divers
void refresh_theme()
{
	tduRefRes current_theme,asked_theme;
	long id_part,id_loop;
	char texte[256];
	SndBool transiting;

	if (dbgSND_fn_bGetThemePosition(&current_theme,&id_part,&id_loop))
	{
		sprintf(texte,"0x%x (%x)",current_theme.pstPtr,current_theme.pstPtr->Id);
		SetDlgItemText(hwndDiversSnd,IDC_CURRENT_THEME,texte);
		sprintf(texte,"%x",id_part);
		SetDlgItemText(hwndDiversSnd,IDC_CURRENT_PART,texte);

		sprintf(texte," %d loops left",id_loop);
		SetDlgItemText(hwndDiversSnd,IDC_CURRENT_BRIDGE,texte);

		if (dbgSND_fn_bGetAskedTheme(&asked_theme,&transiting))
		{
			sprintf(texte,"0x%x (%x)",asked_theme.pstPtr,asked_theme.pstPtr->Id);
			SetDlgItemText(hwndDiversSnd,IDC_ASKED_THEME,texte);
			if (transiting) 
				sprintf(texte,"transiting");
			else
				sprintf(texte,"waiting before transition");
			SetDlgItemText(hwndDiversSnd,IDC_STATE_THEME,texte);
		}

	}
	else
	{
		SetDlgItemText(hwndDiversSnd,IDC_CURRENT_THEME,"none");
		SetDlgItemText(hwndDiversSnd,IDC_CURRENT_PART,"none");
		SetDlgItemText(hwndDiversSnd,IDC_CURRENT_BRIDGE,"none");
	}
}

BOOL CALLBACK DiversCallback(HWND hdwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	LV_COLUMN lvc;
	LV_ITEM lvi;
	int i,iIns;
	pdbgVOLUMELINE_DESCRIPTION pdbgLine;
	char texte[80];
	static BOOL auto_refresh=FALSE;

    switch (msg)                           
    {
        case WM_INITDIALOG:
			if (hMutex) WaitForSingleObject(hMutex,INFINITE);

			hwndDiversSnd=hdwnd;
			
			for (i=0;i<NB_DIVERS_COLUMN;i++)
			{
				memset(&lvc,0,sizeof(lvc));
				lvc.pszText=diverssnd_column[i].name;
				lvc.iSubItem=i-1;
				lvc.cx=micro_column[i].width;
				lvc.mask=LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH; 
				diverssnd_column[i].id_col=ListView_InsertColumn(GetDlgItem(hdwnd,IDC_LISTE),i,&lvc);
			}

			SNDLST2_M_DynamicForEachElementOf(&dbgVolumeLineSnd.pList,pdbgLine,i)
			{		
				//raj liste
				memset(&lvi,0,sizeof(lvi));
				lvi.mask=LVIF_TEXT|LVIF_PARAM; 
				lvi.iItem=0; 
				lvi.iSubItem=0;
				sprintf(texte,"0x%x",pdbgLine->id);
				lvi.pszText=texte;
				lvi.lParam=pdbgLine->id;
 				iIns=ListView_InsertItem(GetDlgItem(hdwnd,IDC_LISTE),&lvi);

				sprintf(texte,"%d",pdbgLine->vol);
				ListView_SetItemText(GetDlgItem(hdwnd,IDC_LISTE),iIns,diverssnd_column[DIVERSSND_COL_VOL].id_col,texte);
			}

			if (hMutex) ReleaseMutex(hMutex);

			SetTimer(hdwnd,0,100,NULL);

			break;
		case WM_TIMER:
			refresh_theme();
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {       
			case IDC_TOPMOST:
				topmost=!topmost;
				SetWindowText(GetDlgItem(hdwnd,IDC_TOPMOST),topmost ? "Go to back-ground" : "Go to Fore-Ground");
				SetWindowPos(hdwnd,topmost ? HWND_TOPMOST : HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
				break;
			case IDC_REFRESH:
				if (auto_refresh)
				{
					auto_refresh=FALSE;
					KillTimer(hdwnd,0);
				}

				refresh_liste_visusnd();
				break;
			case IDC_AUTOREFRESH:
				if (!auto_refresh)
				{
					auto_refresh=TRUE;
					SetTimer(hdwnd,0,100,NULL);
				}
				break;
			case IDC_HISTORIC:
                EndDialog(hdwnd,GOTO_HISTORIC);
				break;
			case IDC_SUPERVISATER:
                EndDialog(hdwnd,GOTO_SUPERVISATER);
				return 1;
			case IDC_INFORMATIONS:
                EndDialog(hdwnd,GOTO_DIVERS);
				return 1;
			case IDC_VISUVIRT:
                EndDialog(hdwnd,GOTO_VISUVIRT);
				break;
			case IDC_CLOSE:
                EndDialog(hdwnd,GOTO_BYEBYE);
				break;
            case IDCANCEL:
                EndDialog(hdwnd,0);
                return 1;
            }
			break;
        case WM_DESTROY:
		case WM_QUIT:
            EndDialog(hdwnd,0);
            return 0;
    }
    return 0;
}

void SND_CALL dbgSND_fn_vSetProcessTimeSample(float ratio)
{
	char texte[256];

	if (bSupervisaterActive)
	{
		if (hwndVisuSnd)
		{
			sprintf(texte,"%d/1000",(int)(1000.0*ratio));
			SetDlgItemText(hwndVisuSnd,IDC_PROCESSTIME,texte);
		}
	}
}

void SND_CALL dbgSND_fn_vAddVoiceSample(long id,tduRefRes res,SampleParam* par)
{
	BOOL visusnd_found=FALSE;
	pdbgVISUSND_ELEMENT visusnd;
	int i,iIns;
	LV_ITEM lvi;
	char texte[80];

	if (bSupervisaterActive)
	{
		if (!dbg_visusnd_init)
		{
			dbg_visusnd_init=TRUE;
			SNDLST2_M_DynamicInitAnchor(&dbg_visusnd.pList);
		}

		SNDLST2_M_DynamicForEachElementOf(&dbg_visusnd.pList,visusnd,i)
		{
			if (visusnd->id==id) 
			{
				visusnd_found=TRUE;
				break;
			}
		}

		if (!visusnd_found)
		{
			visusnd=GlobalAlloc(GMEM_FIXED,sizeof(dbgVISUSND_ELEMENT));
			memset(visusnd,0,sizeof(dbgVISUSND_ELEMENT));
			SNDLST2_M_DynamicInitElement(visusnd);
			visusnd->id=id;
			SNDLST2_M_DynamicAddTail(&dbg_visusnd.pList,visusnd);
			//raj liste
			if (hwndVisuSnd)
			{
				memset(&lvi,0,sizeof(lvi));
				lvi.mask=LVIF_TEXT|LVIF_PARAM; 
				lvi.iItem=0; 
				lvi.iSubItem=0;
				sprintf(texte,"0x%x",visusnd->id);
				lvi.pszText=texte;
				lvi.lParam=visusnd->id;
 				iIns=ListView_InsertItem(GetDlgItem(hwndVisuSnd,IDC_LISTE),&lvi);
			}
		}

		visusnd->res_pstPtr=res.pstPtr;
		visusnd->res_Id=res.pstPtr->Id;
		memcpy(&visusnd->par,par,sizeof(SampleParam));

		if (hMutex) ReleaseMutex(hMutex);
	}
}

void SND_CALL dbgSND_fn_vSetParVoiceSample(long id,SampleParam* par)
{
	pdbgVISUSND_ELEMENT visusnd;
	int i;
	BOOL visusnd_found=FALSE;

	if (bSupervisaterActive)
	{
		SNDLST2_M_DynamicForEachElementOf(&dbg_visusnd.pList,visusnd,i)
		{
			if (visusnd->id==id) 
			{
				visusnd_found=TRUE;
				break;
			}
		}

		if (visusnd_found)
		{
			memcpy(&visusnd->par,par,sizeof(SampleParam));
		}
	}
}

void SND_CALL dbgSND_fn_vDelVoiceSample(long id)
{
	pdbgVISUSND_ELEMENT visusnd;
	BOOL visusnd_found=FALSE;
	int i,iDel,iFind;
	LV_FINDINFO lvf;

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		SNDLST2_M_DynamicForEachElementOf(&dbg_visusnd.pList,visusnd,i)
		{
			if (visusnd->id==id) 
			{
				visusnd_found=TRUE;
				break;
			}
		}

		if (visusnd_found)
		{
			if (hwndVisuSnd)
			{
				memset(&lvf,0,sizeof(LV_FINDINFO));
				lvf.flags=LVFI_PARAM;
				lvf.lParam=id;
				iDel=ListView_DeleteItem(GetDlgItem(hwndVisuSnd,IDC_LISTE)
					,iFind=ListView_FindItem(GetDlgItem(hwndVisuSnd,IDC_LISTE),-1,&lvf)
					);
			}
			SNDLST2_M_DynamicIsolate(visusnd);
			GlobalFree(visusnd);
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

void SND_CALL dbgSND_fn_vPauseVoiceSample(long id)
{
	pdbgVISUSND_ELEMENT visusnd;
	BOOL visusnd_found=FALSE;
	int i;

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		SNDLST2_M_DynamicForEachElementOf(&dbg_visusnd.pList,visusnd,i)
		{
			if (visusnd->id==id) 
			{
				visusnd_found=TRUE;
				break;
			}
		}

		if (visusnd_found)
		{
			visusnd->bPaused=TRUE;
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

void SND_CALL dbgSND_fn_vResumeVoiceSample(long id)
{
	pdbgVISUSND_ELEMENT visusnd;
	BOOL visusnd_found=FALSE;
	int i;

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		SNDLST2_M_DynamicForEachElementOf(&dbg_visusnd.pList,visusnd,i)
		{
			if (visusnd->id==id) 
			{
				visusnd_found=TRUE;
				break;
			}
		}

		if (visusnd_found)
		{
			visusnd->bPaused=FALSE;
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

//ajout d'un historic
void SND_CALL dbgSND_fn_vAddHistoric(SND_tduRefEvt evt,long indice,long type_obj,long asso,tdstBlockResourceMem* res)
{
	if (bSupervisaterActive)
	{
		if (!historic_init)
		{
			historic_init=TRUE;
			memset(historic,0,sizeof(historic));
		}

		GetLocalTime(&historic[next_element].time);
		historic[next_element].evt_pstPtr=evt.pstPtr;
		historic[next_element].evt_Id=evt.pstPtr->Id;
		historic[next_element].evt_eType=evt.pstPtr->eType;
		historic[next_element].obj=indice;
		historic[next_element].type_obj=type_obj;
		historic[next_element].asso=asso;
		historic[next_element].res_pstPtr=res;

		dbgSND_fn_vGetInfoForObjectSound(indice,type_obj,historic[next_element].info,sizeof(historic[next_element].info)-1);
		historic[next_element].info[sizeof(historic[next_element].info)-1]=0;

		if (flagDebugBreak)
		{
			if (!filtre(&historic[next_element]))
				/******* BreakPoint demandé par le SUPERVISATER ****************/
				DebugBreak();
				/******* BreakPoint demandé par le SUPERVISATER ****************/
		}
		if (!filtre(&historic[next_element]))
			add_histo(&historic[next_element]);
		next_element++;
		if (next_element>=TAILLE_HISTORIC) next_element=0;
	}
}

//ajout d'un couple evt-objet
void SND_CALL dbgSND_fn_vAddEventToObject(long indice,long type,long asso,SND_tduRefEvt evt)
{
	dbgSND_tdstObjectStruct* obj=NULL;
	int i,iIns;
	BOOL obj_found=FALSE;
	LV_ITEM lvi;
	char texte[80];
	char info[10];

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		if (!dbg_objects_init)
		{
			dbg_objects_init=TRUE;
			SNDLST2_M_DynamicInitAnchor(&dbg_objects.pList);
		}

		SNDLST2_M_DynamicForEachElementOf(&dbg_objects.pList,obj,i)
		{
			if (obj->indice==indice) 
			{
				obj_found=TRUE;
				break;
			}
		}

		if (obj_found)
		{
			add_evt(obj,asso,evt);
		}
		else
		{
			obj=GlobalAlloc(GMEM_FIXED,sizeof(dbgSND_tdstObjectStruct));
			memset(obj,0,sizeof(dbgSND_tdstObjectStruct));
			SNDLST2_M_DynamicInitElement(obj);
			obj->indice=indice;
			SNDLST2_M_DynamicInitAnchor(&obj->evts.pList);
			SNDLST2_M_DynamicAddTail(&dbg_objects.pList,obj);

			add_evt(obj,asso,evt);

			//raj liste
			if (hwndSupervisater)
			{
				memset(&lvi,0,sizeof(lvi));
				lvi.mask=LVIF_TEXT|LVIF_PARAM; 
				lvi.iItem=0; 
				lvi.iSubItem=0;
				dbgSND_fn_vGetInfoForObjectSound(indice,type,info,sizeof(info)-1);info[sizeof(info)-1]=0;
				sprintf(texte,"0x%x (%s)",obj->indice,info);
				lvi.pszText=texte;
				lvi.lParam=obj->indice;
 				iIns=ListView_InsertItem(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),&lvi);
			}
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

// destruction d'un couple evt-couple
void SND_CALL dbgSND_fn_vKillEventToObjectPrivate(long indice,long asso)
{
	dbgSND_tdstObjectStruct* obj=NULL;
	int i,iFind,iDel;
	BOOL obj_found=FALSE;
	LV_FINDINFO lvf;

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		SNDLST2_M_DynamicForEachElementOf(&dbg_objects.pList,obj,i)
		{
			if (obj->indice==indice) 
			{
				obj_found=TRUE;
				break;
			}
		}

		if (obj_found)
		{
			del_evt(obj,asso);

			if (!SNDLST2_M_DynamicGetNumberOfElements(&obj->evts.pList) && delete_objects)
			{
				//destruction
				if (hwndSupervisater)
				{
					memset(&lvf,0,sizeof(LV_FINDINFO));
					lvf.flags=LVFI_PARAM;
					lvf.lParam=indice;
					iDel=ListView_DeleteItem(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT)
						,iFind=ListView_FindItem(GetDlgItem(hwndSupervisater,IDC_LISTOBJECT),-1,&lvf)
						);
				}
				SNDLST2_M_DynamicIsolate(obj);
				GlobalFree(obj);
			}
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

void SND_CALL dbgSND_fn_vKillEventToObject(long indice,long asso)
{
	dbgSND_fn_vKillEventToObjectPrivate(indice,asso);
}


//raj des paramètres d'un couple
void SND_CALL dbgSND_fn_vSetPosObject(long indice,SoundParam* par)
{
	dbgSND_tdstObjectStruct* obj=NULL;
	int i;
	BOOL obj_found=FALSE;

	if (bSupervisaterActive)
	{
		SNDLST2_M_DynamicForEachElementOf(&dbg_objects.pList,obj,i)
		{
			if (obj->indice==indice) 
			{
				obj_found=TRUE;
				break;
			}
		}

		if (obj_found)
		{
			memcpy(&obj->par,par,sizeof(SoundParam));
		}
	}
}

//add a micro
void SND_CALL dbgSND_fn_vAddMicro(long indice)
{
	pdbgMICRO_DESCRIPTION mic;
	int iIns;
	LV_ITEM lvi;
	char texte[80];

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		if (!dbg_micros_init)
		{
			dbg_micros_init=TRUE;
			SNDLST2_M_DynamicInitAnchor(&dbg_micros.pList);
		}

		mic=GlobalAlloc(GMEM_FIXED,sizeof(dbgMICRO_DESCRIPTION));
		memset(mic,0,sizeof(dbgMICRO_DESCRIPTION));
		SNDLST2_M_DynamicInitElement(mic);
		mic->Id=indice;
		SNDLST2_M_DynamicAddTail(&dbg_micros.pList,mic);
		//raj liste
		if (hwndSupervisater)
		{
			memset(&lvi,0,sizeof(lvi));
			lvi.mask=LVIF_TEXT|LVIF_PARAM; 
			lvi.iItem=0; 
			lvi.iSubItem=0;
			sprintf(texte,"0x%x",mic->Id);
			lvi.pszText=texte;
			lvi.lParam=mic->Id;
 			iIns=ListView_InsertItem(GetDlgItem(hwndSupervisater,IDC_LISTMICRO),&lvi);
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

//destroy z micro
void SND_CALL dbgSND_fn_vKillMicro(long indice)
{
	BOOL mic_found=FALSE;
	pdbgMICRO_DESCRIPTION mic;
	int i,iDel,iFind;
	LV_FINDINFO lvf;

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		SNDLST2_M_DynamicForEachElementOf(&dbg_micros.pList,mic,i)
		{
			if (mic->Id==indice) 
			{
				mic_found=TRUE;
				break;
			}
		}

		if (mic_found)
		{
			//raj liste
			if (hwndSupervisater)
			{
				memset(&lvf,0,sizeof(LV_FINDINFO));
				lvf.flags=LVFI_PARAM;
				lvf.lParam=indice;
				iDel=ListView_DeleteItem(GetDlgItem(hwndSupervisater,IDC_LISTMICRO)
					,iFind=ListView_FindItem(GetDlgItem(hwndSupervisater,IDC_LISTMICRO),-1,&lvf)
					);
			}
			SNDLST2_M_DynamicIsolate(mic);
			GlobalFree(mic);
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

//raj micro
void SND_CALL dbgSND_fn_vSetPosMicro(long indice,MicroParam* par)
{
	BOOL mic_found=FALSE;
	pdbgMICRO_DESCRIPTION mic;
	int i;

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		SNDLST2_M_DynamicForEachElementOf(&dbg_micros.pList,mic,i)
		{
			if (mic->Id==indice) 
			{
				mic_found=TRUE;
				break;
			}
		}

		if (mic_found)
		{
			memcpy(&mic->par,par,sizeof(MicroParam));
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

//----ligne
void SND_CALL dbgSND_fn_vKillVolumeLine(long line)
{
	pdbgVOLUMELINE_DESCRIPTION dbgpvol,dbgpvolnext;
	int i;

	SNDLST2_M_DynamicForEachMovingElementOf(&dbgVolumeLineSnd.pList,dbgpvol,dbgpvolnext,i)
	{
		if (dbgpvol->id==line)
		{
			SNDLST2_M_DynamicIsolate(dbgpvol);
			GlobalFree(dbgpvol);
		}
	}
}

void SND_CALL dbgSND_fn_vAddVolumeLine(long line)
{
	int iIns;
	LV_ITEM lvi;
	LV_COLUMN lvc;
	char texte[80];
	pdbgVOLUMELINE_DESCRIPTION dbgpvol;

	if (bSupervisaterActive)
	{
		if (hMutex) WaitForSingleObject(hMutex,INFINITE);

		if (!dbgVolumeLineInit)
		{
			SNDLST2_M_DynamicInitAnchor(&dbgVolumeLineSnd.pList);
			dbgVolumeLineInit=TRUE;
		}

		dbgpvol=GlobalAlloc(GMEM_FIXED,sizeof(dbgVOLUMELINE_DESCRIPTION));
		memset(dbgpvol,0,sizeof(dbgVOLUMELINE_DESCRIPTION));
		SNDLST2_M_DynamicInitElement(dbgpvol);
		SNDLST2_M_DynamicAddTail(&dbgVolumeLineSnd.pList,dbgpvol);
		dbgpvol->id=line;
		dbgpvol->vol=127;

		//raj liste
		if (hwndDiversSnd)
		{
			memset(&lvi,0,sizeof(lvi));
			lvi.mask=LVIF_TEXT|LVIF_PARAM; 
			lvi.iItem=0; 
			lvi.iSubItem=0;
			sprintf(texte,"0x%x",line);
			lvi.pszText=texte;
			lvi.lParam=line;
 			iIns=ListView_InsertItem(GetDlgItem(hwndDiversSnd,IDC_LISTE),&lvi);

			memset(&lvc,0,sizeof(lvc));
			sprintf(texte,"%d",127);
			lvc.pszText=texte;
			lvc.cx=diverssnd_column[1].width;
			lvc.iSubItem=1;
			lvc.mask=LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH; 
			diverssnd_column[1].id_col=ListView_InsertColumn(GetDlgItem(hwndDiversSnd,IDC_LISTE),1,&lvc);
		}

		if (hMutex) ReleaseMutex(hMutex);
	}
}

void refresh_volume_line()
{
	HWND hwnd;
	int iFind,i;
	LV_FINDINFO lvf;
	char texte[256];
	pdbgVOLUMELINE_DESCRIPTION dbgpvol;

	if (hwndDiversSnd)
	{
		hwnd=GetDlgItem(hwndDiversSnd,IDC_LISTE);

		SNDLST2_M_DynamicForEachElementOf(&dbgVolumeLineSnd.pList,dbgpvol,i)
		{
			memset(&lvf,0,sizeof(LV_FINDINFO));
			lvf.flags=LVFI_PARAM;
			lvf.lParam=dbgpvol->id;
			iFind=ListView_FindItem(hwnd,-1,&lvf);
			sprintf(texte,"%d",dbgpvol->vol);
			ListView_SetItemText(hwnd,iFind,diverssnd_column[DIVERSSND_COL_VOL].id_col,texte);
		}
	}
}

void SND_CALL dbgSND_fn_vSetVolumeLine(long line,long vol)
{
	pdbgVOLUMELINE_DESCRIPTION dbgpvol;
	int i;

	SNDLST2_M_DynamicForEachElementOf(&dbgVolumeLineSnd.pList,dbgpvol,i)
	{
		if (dbgpvol->id==line)
		{
			dbgpvol->vol=vol;
		}
	}

	refresh_volume_line();
}


//---------- générales
//thread du supervisater
DWORD WINAPI SupervistareThread(DWORD par)
{
	int ret=GOTO_SUPERVISATER;

	while ((ret!=GOTO_BYEBYE) && (ret!=-1))
	{
		switch (ret)
		{
		case GOTO_SUPERVISATER:
			ret=DialogBox(hSupervisaterDLL,MAKEINTRESOURCE(IDD_SUPERVISATER),HWND_DESKTOP,(DLGPROC)SupervisaterCallback);
			hwndSupervisater=NULL;
			break;
		case GOTO_HISTORIC:
//			ret=CreateDialog(hSupervisaterDLL,MAKEINTRESOURCE(IDD_HISTORIC),HWND_DESKTOP,(DLGPROC)HistoricCallback);
			ret=DialogBox(hSupervisaterDLL,MAKEINTRESOURCE(IDD_HISTORIC),HWND_DESKTOP,(DLGPROC)HistoricCallback);
			hwndHistoric=NULL;
			break;
		case GOTO_VISUSND:
			ret=DialogBox(hSupervisaterDLL,MAKEINTRESOURCE(IDD_VISUSND),HWND_DESKTOP,(DLGPROC)VisuSndCallback);
			hwndVisuSnd=NULL;
			break;
		case GOTO_DIVERS:
			ret=DialogBox(hSupervisaterDLL,MAKEINTRESOURCE(IDD_DIVERS),HWND_DESKTOP,(DLGPROC)DiversCallback);
			hwndDiversSnd=NULL;
			break;
		case GOTO_VISUVIRT:
			ret=DialogBox(hSupervisaterDLL,MAKEINTRESOURCE(IDD_VISUVIRT),HWND_DESKTOP,(DLGPROC)VisuVirtCallback);
			hwndVisuVirt=NULL;
			break;
		default:
			ret=GOTO_BYEBYE;
			break;
		}
	}

	return 0;
}

#endif //SUPERVISATER

// lance la fenêtre de Supervisater
void SND_CALL SND_fn_vLaunchSupervisater(SND_tdstInitStruct *pInitStruct)
{
#ifdef SUPERVISATER
#if defined(_DLL_COMPILATION_MODE)
    SND_DllInitEntryPoints_StaticFunctions((HMODULE)pInitStruct->hProcessInstance );
#endif

	if (bSupervisaterActive)
	{
		if (!hSupervisaterThread)
		{
			InitCommonControls();

			hMutex=CreateMutex(NULL,FALSE,NULL);

			hwndMain=pInitStruct->hMainWindow;
			hSupervisaterDLL=SND_fn_vGetHModuleDbg();

			hSupervisaterThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SupervistareThread,NULL,0,&dwSupervisaterThreadId);
		}
	}
#endif
}

// ferme la fenêtre de Supervisater
void SND_CALL SND_fn_vKillSupervisater()
{
#ifdef SUPERVISATER
	pdbgSND_tdstObjectStruct obj,objnext;
	pdbgSND_tdstEvtStruct evt,evtnext;
	pdbgMICRO_DESCRIPTION mic,micnext;
	pdbgVISUSND_ELEMENT visu,visunext;
	pdbgVOLUMELINE_DESCRIPTION vol,volnext;
	int i,j;

	if (bSupervisaterActive)
	{
		PostThreadMessage(dwSupervisaterThreadId,WM_QUIT,0,0);
		WaitForSingleObject(hSupervisaterThread,50000);
		CloseHandle(hSupervisaterThread);
		CloseHandle(hMutex);
		hMutex=NULL;
	}

	//free memory
	SNDLST2_M_DynamicForEachMovingElementOf(&dbg_objects.pList,obj,objnext,i)
	{
		SNDLST2_M_DynamicForEachMovingElementOf(&obj->evts.pList,evt,evtnext,j)
		{
			SNDLST2_M_DynamicIsolate(evt);
			GlobalFree(evt);
		}
		SNDLST2_M_DynamicIsolate(obj);
		GlobalFree(obj);
	}
	SNDLST2_M_DynamicForEachMovingElementOf(&dbg_visusnd.pList,visu,visunext,i)
	{
		SNDLST2_M_DynamicIsolate(visu);
		GlobalFree(visu);
	}
	SNDLST2_M_DynamicForEachMovingElementOf(&dbg_micros.pList,mic,micnext,i)
	{
		SNDLST2_M_DynamicIsolate(mic);
		GlobalFree(mic);
	}
	SNDLST2_M_DynamicForEachMovingElementOf(&dbgVolumeLineSnd.pList,vol,volnext,i)
	{
		SNDLST2_M_DynamicIsolate(vol);
		GlobalFree(vol);
	}
#endif
}

void SND_CALL SND_fn_vSetSupervisaterActive(void)
{
	bSupervisaterActive=TRUE;
}

SndBool SND_CALL SND_fn_bIsSupervisaterActive(void)
{
	return bSupervisaterActive;
}

//fonctions pour éditeur
tdstBlockResourceMem* SND_CALL dbgSND_fn_pstGetSelectedResource(void)
{
	if (hwndHistoric)
		return res_for_editor;
	else
		return NULL;
}

SndBool SND_CALL dbgSND_fn_bDoesSupervisaterSelectResource(void)
{
	if (hwndHistoric)
	{
		if (SendDlgItemMessage(hwndHistoric,IDC_SELECTRESOURCE,BM_GETCHECK,0,0)==BST_CHECKED)
			return TRUE;
	}

	return FALSE;
}

void SND_CALL dbgSND_fn_vLoadBank(int iId)
{
}

void SND_CALL dbgSND_fn_vUnLoadBank(int iId)
{
}

//redfresh Supervistaer display
void SND_CALL dbgSND_fn_vRefreshSupervisater(void)
{
	if (bSupervisaterActive)
	{
		if (hwndHistoric)
		{
			ListView_DeleteAllItems(GetDlgItem(hwndHistoric,IDC_LISTE));
			refresh_historic();
		}
	}
}
