GF_Err gf_sm_dump_command_list(GF_SceneDumper *sdump, GF_List *comList, u32 indent, Bool skip_first_replace)
{
	GF_Err e;
	u32 i, count;
	u32 prev_ind;
#ifndef GPAC_DISABLE_VRML
	u32 remain = 0, has_scene_replace = 0;
#endif
	Bool prev_skip;

	if (!sdump || !sdump->trace|| !comList || !sdump->sg) return GF_BAD_PARAM;

	prev_skip = sdump->skip_scene_replace;
	sdump->skip_scene_replace = skip_first_replace;
	prev_ind  = sdump->indent;
	sdump->indent = indent;

	e = GF_OK;
	count = gf_list_count(comList);
	for (i=0; i<count; i++) {
		GF_Command *com = (GF_Command *) gf_list_get(comList, i);
		if (i
#ifndef GPAC_DISABLE_VRML
			&& !remain
#endif
			&& (sdump->X3DDump || (sdump->dump_mode==GF_SM_DUMP_VRML))
		) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[Scene Dump] MPEG-4 Commands found, not supported in %s - skipping\n", sdump->X3DDump ? "X3D" : "VRML"));
			break;
		}
#ifndef GPAC_DISABLE_VRML
		if (has_scene_replace && (com->tag != GF_SG_ROUTE_INSERT)) {
			has_scene_replace = 0;
			if (sdump->XMLDump) {
				sdump->indent--;
				EndElement(sdump, "Scene", 1);
				sdump->indent--;
				EndElement(sdump, "Replace", 1);
			} else {
				DUMP_IND(sdump);
				gf_fprintf(sdump->trace, "\nAT 0 {\n");
				sdump->indent++;
			}
		}
#endif

		switch (com->tag) {
#ifndef GPAC_DISABLE_VRML
		/*insert commands*/
		case GF_SG_NODE_INSERT:
			e = DumpNodeInsert(sdump, com);
			break;
		case GF_SG_INDEXED_INSERT:
			e = DumpIndexInsert(sdump, com);
			break;
		case GF_SG_ROUTE_INSERT:
			e = DumpRouteInsert(sdump, com, has_scene_replace);
			if (remain) remain--;
			break;
		/*delete commands*/
		case GF_SG_NODE_DELETE:
			e = DumpNodeDelete(sdump, com);
			break;
		case GF_SG_INDEXED_DELETE:
			e = DumpIndexDelete(sdump, com);
			break;
		case GF_SG_ROUTE_DELETE:
			e = DumpRouteDelete(sdump, com);
			break;
		/*replace commands*/
		case GF_SG_NODE_REPLACE:
			e = DumpNodeReplace(sdump, com);
			break;
		case GF_SG_FIELD_REPLACE:
			e = DumpFieldReplace(sdump, com);
			break;
		case GF_SG_INDEXED_REPLACE:
			e = DumpIndexReplace(sdump, com);
			break;
		case GF_SG_ROUTE_REPLACE:
			e = DumpRouteReplace(sdump, com);
			break;
		case GF_SG_XREPLACE:
			e = DumpXReplace(sdump, com);
			break;
		case GF_SG_SCENE_REPLACE:
			/*we don't support replace scene in conditional*/
			assert(!sdump->current_com_list);
			sdump->current_com_list = comList;
			e = DumpSceneReplace(sdump, com);
			sdump->current_com_list = NULL;
			has_scene_replace = 1;
			remain = count - i - 1;
			break;
		/*extended commands*/
		case GF_SG_PROTO_INSERT:
			e = DumpProtoInsert(sdump, com);
			break;
		case GF_SG_PROTO_DELETE_ALL:
			DUMP_IND(sdump);
			if (sdump->XMLDump) {
				gf_fprintf(sdump->trace, "<Delete extended=\"allProtos\"/>\n");
			} else {
				gf_fprintf(sdump->trace, "DELETEPROTO ALL\n");
			}
			e = GF_OK;
			break;
		case GF_SG_PROTO_DELETE:
		{
			u32 j;
			DUMP_IND(sdump);
			if (sdump->XMLDump) {
				gf_fprintf(sdump->trace, "<Delete extended=\"protos\" value=\"");
			} else {
				gf_fprintf(sdump->trace, "DELETEPROTO [");
			}
			for (j=0; j<com->del_proto_list_size; j++) {
				if (j) gf_fprintf(sdump->trace, " ");
				gf_fprintf(sdump->trace, "%d", com->del_proto_list[j]);
			}
			if (sdump->XMLDump) {
				gf_fprintf(sdump->trace, "\"/>\n");
			} else {
				gf_fprintf(sdump->trace, "]\n");
			}
			e = GF_OK;
		}
		break;
		case GF_SG_GLOBAL_QUANTIZER:
			e = DumpGlobalQP(sdump, com);
			break;
		case GF_SG_MULTIPLE_REPLACE:
			e = DumpMultipleReplace(sdump, com);
			break;
		case GF_SG_MULTIPLE_INDEXED_REPLACE:
			e = DumpMultipleIndexedReplace(sdump, com);
			break;
		case GF_SG_NODE_DELETE_EX:
			e = DumpNodeDelete(sdump, com);
			break;

#endif


#ifndef GPAC_DISABLE_SVG
		/*laser commands*/
		case GF_SG_LSR_NEW_SCENE:
			e = DumpLSRNewScene(sdump, com);
			break;
		case GF_SG_LSR_ADD:
			e = DumpLSRAddReplaceInsert(sdump, com);
			break;
		case GF_SG_LSR_CLEAN:
			//e = DumpLSRClean(sdump, com);
			break;
		case GF_SG_LSR_REPLACE:
			e = DumpLSRAddReplaceInsert(sdump, com);
			break;
		case GF_SG_LSR_DELETE:
			e = DumpLSRDelete(sdump, com);
			break;
		case GF_SG_LSR_INSERT:
			e = DumpLSRAddReplaceInsert(sdump, com);
			break;
		case GF_SG_LSR_RESTORE:
			//e = DumpLSRRestore(sdump, com);
			break;
		case GF_SG_LSR_SAVE:
			//e = DumpLSRSave(sdump, com);
			break;
		case GF_SG_LSR_SEND_EVENT:
			e = DumpLSRSendEvent(sdump, com);
			break;
		case GF_SG_LSR_ACTIVATE:
		case GF_SG_LSR_DEACTIVATE:
			e = DumpLSRActivate(sdump, com);
			break;
#endif
		}
		if (e) break;


		if (sdump->skip_scene_replace
#ifndef GPAC_DISABLE_VRML
			&& !has_scene_replace
#endif
		) {
			sdump->skip_scene_replace = 0;
			if (!sdump->XMLDump && (i+1<count)) {
				DUMP_IND(sdump);
				gf_fprintf(sdump->trace, "\nAT 0 {\n");
				sdump->indent++;
			}
		}
	}

#ifndef GPAC_DISABLE_VRML
	if (remain && !sdump->XMLDump) {
		sdump->indent--;
		DUMP_IND(sdump);
		gf_fprintf(sdump->trace, "}\n");
	}
#endif

	if (has_scene_replace && sdump->XMLDump) {
		sdump->indent--;
		if (!sdump->X3DDump) {
			EndElement(sdump, "Scene", 1);
			sdump->indent--;
			EndElement(sdump, "Replace", 1);
		}
	}

	sdump->indent = prev_ind;
	sdump->skip_scene_replace = prev_skip;
	return e;
}