GF_Err gf_sm_dump(GF_SceneManager *ctx, char *rad_name, Bool is_final_name, GF_SceneDumpFormat dump_mode)
{
	GF_Err e;
	GF_List *sample_list;
	Bool first_par;
	u32 i, j, indent, num_scene, num_od, first_bifs, num_tracks;
	Double time;
	GF_SceneDumper *dumper;
	GF_StreamContext *sc;
	GF_AUContext *au;
	Bool no_root_found = 1;

	sample_list = gf_list_new();

	num_scene = num_od = 0;
	num_tracks = 0;
	indent = 0;
	dumper = gf_sm_dumper_new(ctx->scene_graph, rad_name, is_final_name, ' ', dump_mode);
	e = GF_OK;
	/*configure all systems streams we're dumping*/
	i=0;
	while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) {

		switch (sc->streamType) {
		case GF_STREAM_SCENE:
			num_scene ++;
			num_tracks ++;
			break;
		case GF_STREAM_OD:
			num_od ++;
			num_tracks ++;
			break;
		default:
			continue;
		}

		j=0;
		while ((au = (GF_AUContext*)gf_list_enum(sc->AUs, &j))) {
			ReorderAUContext(sample_list, au, dumper->LSRDump);
			if (dumper->dump_mode==GF_SM_DUMP_SVG) break;
		}
		if (dumper->dump_mode==GF_SM_DUMP_SVG) break;
	}
	first_bifs = (num_scene==1) ? 1 : 0;
	num_scene = (num_scene>1) ? 1 : 0;
	num_od = (num_od>1) ? 1 : 0;

	gf_dump_setup(dumper, (GF_Descriptor *) ctx->root_od);

#ifndef GPAC_DISABLE_SVG
	if (dumper->dump_mode==GF_SM_DUMP_SVG) {
		au = (GF_AUContext*)gf_list_get(sample_list, 0);
		GF_Command *com = NULL;
		if (au) com = (GF_Command*)gf_list_get(au->commands, 0);
		if (!au) {
			gf_dump_svg_element(dumper, dumper->sg->RootNode, NULL, 1);
		} else if (!com || (com->tag!=GF_SG_LSR_NEW_SCENE) || !com->node) {
			e = GF_NOT_SUPPORTED;
		} else {
			gf_dump_svg_element(dumper, com->node, NULL, 1);
		}
		gf_dump_finalize(dumper, (GF_Descriptor *) ctx->root_od);
		gf_sm_dumper_del(dumper);
		gf_list_del(sample_list);
		return e;
	}
#endif

	time = dumper->LSRDump ? -1 : 0;
	first_par = 0;

	while (gf_list_count(sample_list)) {
		au = (GF_AUContext*)gf_list_get(sample_list, 0);
		gf_list_rem(sample_list, 0);

		if (!dumper->XMLDump) {

			if (!first_bifs || (au->owner->streamType != GF_STREAM_SCENE) ) {
				if (au->flags & GF_SM_AU_RAP) gf_fprintf(dumper->trace, "RAP ");
				gf_fprintf(dumper->trace, "AT "LLD" ", au->timing);
				if ( (au->owner->streamType==GF_STREAM_OD && num_od) || (au->owner->streamType==GF_STREAM_SCENE && num_scene)) {
					gf_fprintf(dumper->trace, "IN %d ", au->owner->ESID);
				}
				gf_fprintf(dumper->trace, "{\n");
				indent++;
			}

			switch (au->owner->streamType) {
			case GF_STREAM_OD:
				if (dumper->LSRDump) {
					dump_od_to_saf(dumper, au, indent);
				} else {
#ifndef GPAC_DISABLE_OD_DUMP
					e = gf_odf_dump_com_list(au->commands, dumper->trace, indent+1, 0);
#endif
				}
				break;
			case GF_STREAM_SCENE:
				e = gf_sm_dump_command_list(dumper, au->commands, indent, first_bifs);
				break;
			}
			if (first_bifs) {
				first_bifs = 0;
				gf_fprintf(dumper->trace, "\n");

			} else {
				indent--;
				gf_fprintf(dumper->trace, "}\n\n");
			}
		}
		else {
			if (dumper->LSRDump) {
/*				if (time != au->timing_sec) {
					time = au->timing_sec;
				}
*/
			} else if (!time && !num_scene && first_bifs) {
			} else if (num_scene || num_od) {
				if (!first_par) {
					first_par = 1;
					indent += 1;
				} else {
					gf_fprintf(dumper->trace, " </par>\n");
				}
				gf_fprintf(dumper->trace, " <par begin=\"%g\" atES_ID=\"es%d\" isRAP=\"%s\">\n", au->timing_sec, au->owner->ESID, (au->flags & GF_SM_AU_RAP) ? "yes" : "no");
			} else if (au->timing_sec>time) {
				if (!first_par) {
					first_par = 1;
					indent += 1;
				} else {
					gf_fprintf(dumper->trace, " </par>\n");
				}
				gf_fprintf(dumper->trace, "<par begin=\"%g\">\n", au->timing_sec);
			}
			switch (au->owner->streamType) {
			case GF_STREAM_OD:
				if (dumper->LSRDump) {
					dump_od_to_saf(dumper, au, indent+1);
				} else {
#ifndef GPAC_DISABLE_OD_DUMP
					e = gf_odf_dump_com_list(au->commands, dumper->trace, indent+1, 1);
#endif
				}
				break;
			case GF_STREAM_SCENE:
				if (gf_list_count(au->commands)) {
					if (dumper->LSRDump)
						gf_sm_dump_saf_hdr(dumper, "sceneUnit", au->timing, au->flags & GF_SM_AU_RAP);

					e = gf_sm_dump_command_list(dumper, au->commands, indent+1, first_bifs);
					first_bifs = 0;
					no_root_found = 0;

					if (dumper->LSRDump)
						gf_fprintf(dumper->trace, "</saf:sceneUnit>\n");
				}
				break;
			}
			time = au->timing_sec;
		}
		if (dumper->X3DDump || (dumper->dump_mode==GF_SM_DUMP_VRML)) break;
	}

#ifndef GPAC_DISABLE_VRML
	if (no_root_found && ctx->scene_graph->RootNode) {
		GF_Route *r;
		DumpProtos(dumper, ctx->scene_graph->protos);
		gf_dump_vrml_node(dumper, ctx->scene_graph->RootNode, 0, NULL);
		i=0;
		gf_fprintf(dumper->trace, "\n");
		while ((r = (GF_Route*)gf_list_enum(dumper->sg->Routes, &i))) {
			if (r->IS_route || (r->graph!=dumper->sg)) continue;
			e = gf_dump_vrml_route(dumper, r, 0);
			if (e) return e;
		}
	}
#endif


	/*close command*/
	if (!dumper->X3DDump && first_par) gf_fprintf(dumper->trace, " </par>\n");

	if (gf_list_count(sample_list) && (dumper->X3DDump || (dumper->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", dumper->X3DDump ? "X3D" : "VRML"));
	}

	gf_dump_finalize(dumper, (GF_Descriptor *) ctx->root_od);
	gf_sm_dumper_del(dumper);
	gf_list_del(sample_list);
	return e;
}
GF_Err gf_sm_dump(GF_SceneManager *ctx, char *rad_name, Bool is_final_name, GF_SceneDumpFormat dump_mode)
{
	GF_Err e;
	GF_List *sample_list;
	Bool first_par;
	u32 i, j, indent, num_scene, num_od, first_bifs, num_tracks;
	Double time;
	GF_SceneDumper *dumper;
	GF_StreamContext *sc;
	GF_AUContext *au;
	Bool no_root_found = 1;

	sample_list = gf_list_new();

	num_scene = num_od = 0;
	num_tracks = 0;
	indent = 0;
	dumper = gf_sm_dumper_new(ctx->scene_graph, rad_name, is_final_name, ' ', dump_mode);
	e = GF_OK;
	 
	i=0;
	while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) {

		switch (sc->streamType) {
		case GF_STREAM_SCENE:
			num_scene ++;
			num_tracks ++;
			break;
		case GF_STREAM_OD:
			num_od ++;
			num_tracks ++;
			break;
		default:
			continue;
		}

		j=0;
		while ((au = (GF_AUContext*)gf_list_enum(sc->AUs, &j))) {
			ReorderAUContext(sample_list, au, dumper->LSRDump);
			if (dumper->dump_mode==GF_SM_DUMP_SVG) break;
		}
		if (dumper->dump_mode==GF_SM_DUMP_SVG) break;
	}
	first_bifs = (num_scene==1) ? 1 : 0;
	num_scene = (num_scene>1) ? 1 : 0;
	num_od = (num_od>1) ? 1 : 0;

	gf_dump_setup(dumper, (GF_Descriptor *) ctx->root_od);

#ifndef GPAC_DISABLE_SVG
	if (dumper->dump_mode==GF_SM_DUMP_SVG) {
		au = (GF_AUContext*)gf_list_get(sample_list, 0);
		GF_Command *com = NULL;
		if (au) com = (GF_Command*)gf_list_get(au->commands, 0);
		if (!au) {
			gf_dump_svg_element(dumper, dumper->sg->RootNode, NULL, 1);
		} else if (!com || (com->tag!=GF_SG_LSR_NEW_SCENE) || !com->node) {
			e = GF_NOT_SUPPORTED;
		} else {
			gf_dump_svg_element(dumper, com->node, NULL, 1);
		}
		gf_dump_finalize(dumper, (GF_Descriptor *) ctx->root_od);
		gf_sm_dumper_del(dumper);
		gf_list_del(sample_list);
		return e;
	}
#endif

	time = dumper->LSRDump ? -1 : 0;
	first_par = 0;

	while (gf_list_count(sample_list)) {
		au = (GF_AUContext*)gf_list_get(sample_list, 0);
		gf_list_rem(sample_list, 0);

		if (!dumper->XMLDump) {

			if (!first_bifs || (au->owner->streamType != GF_STREAM_SCENE) ) {
				if (au->flags & GF_SM_AU_RAP) gf_fprintf(dumper->trace, "RAP ");
				gf_fprintf(dumper->trace, "AT "LLD" ", au->timing);
				if ( (au->owner->streamType==GF_STREAM_OD && num_od) || (au->owner->streamType==GF_STREAM_SCENE && num_scene)) {
					gf_fprintf(dumper->trace, "IN %d ", au->owner->ESID);
				}
				gf_fprintf(dumper->trace, "{\n");
				indent++;
			}

			switch (au->owner->streamType) {
			case GF_STREAM_OD:
				if (dumper->LSRDump) {
					dump_od_to_saf(dumper, au, indent);
				} else {
#ifndef GPAC_DISABLE_OD_DUMP
					e = gf_odf_dump_com_list(au->commands, dumper->trace, indent+1, 0);
#endif
				}
				break;
			case GF_STREAM_SCENE:
				e = gf_sm_dump_command_list(dumper, au->commands, indent, first_bifs);
				break;
			}
			if (first_bifs) {
				first_bifs = 0;
				gf_fprintf(dumper->trace, "\n");

			} else {
				indent--;
				gf_fprintf(dumper->trace, "}\n\n");
			}
		}
		else {
			if (dumper->LSRDump) {
 
			} else if (!time && !num_scene && first_bifs) {
			} else if (num_scene || num_od) {
				if (!first_par) {
					first_par = 1;
					indent += 1;
				} else {
					gf_fprintf(dumper->trace, " </par>\n");
				}
				gf_fprintf(dumper->trace, " <par begin=\"%g\" atES_ID=\"es%d\" isRAP=\"%s\">\n", au->timing_sec, au->owner->ESID, (au->flags & GF_SM_AU_RAP) ? "yes" : "no");
			} else if (au->timing_sec>time) {
				if (!first_par) {
					first_par = 1;
					indent += 1;
				} else {
					gf_fprintf(dumper->trace, " </par>\n");
				}
				gf_fprintf(dumper->trace, "<par begin=\"%g\">\n", au->timing_sec);
			}
			switch (au->owner->streamType) {
			case GF_STREAM_OD:
				if (dumper->LSRDump) {
					dump_od_to_saf(dumper, au, indent+1);
				} else {
#ifndef GPAC_DISABLE_OD_DUMP
					e = gf_odf_dump_com_list(au->commands, dumper->trace, indent+1, 1);
#endif
				}
				break;
			case GF_STREAM_SCENE:
				if (gf_list_count(au->commands)) {
					if (dumper->LSRDump)
						gf_sm_dump_saf_hdr(dumper, "sceneUnit", au->timing, au->flags & GF_SM_AU_RAP);

					e = gf_sm_dump_command_list(dumper, au->commands, indent+1, first_bifs);
					first_bifs = 0;
					no_root_found = 0;

					if (dumper->LSRDump)
						gf_fprintf(dumper->trace, "</saf:sceneUnit>\n");
				}
				break;
			}
			time = au->timing_sec;
		}
		if (dumper->X3DDump || (dumper->dump_mode==GF_SM_DUMP_VRML)) break;
	}

#ifndef GPAC_DISABLE_VRML
	if (no_root_found && ctx->scene_graph->RootNode) {
		GF_Route *r;
		DumpProtos(dumper, ctx->scene_graph->protos);
		gf_dump_vrml_node(dumper, ctx->scene_graph->RootNode, 0, NULL);
		i=0;
		gf_fprintf(dumper->trace, "\n");
		while ((r = (GF_Route*)gf_list_enum(dumper->sg->Routes, &i))) {
			if (r->IS_route || (r->graph!=dumper->sg)) continue;
			e = gf_dump_vrml_route(dumper, r, 0);
			if (e) return e;
		}
	}
#endif


	 
	if (!dumper->X3DDump && first_par) gf_fprintf(dumper->trace, " </par>\n");

	if (gf_list_count(sample_list) && (dumper->X3DDump || (dumper->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", dumper->X3DDump ? "X3D" : "VRML"));
	}

	gf_dump_finalize(dumper, (GF_Descriptor *) ctx->root_od);
	gf_sm_dumper_del(dumper);
	gf_list_del(sample_list);
	return e;
}