GF_SceneDumper *gf_sm_dumper_new(GF_SceneGraph *graph, char *_rad_name, Bool is_final_name, char indent_char, GF_SceneDumpFormat dump_mode)
{
	GF_SceneDumper *tmp;
	if (!graph) return NULL;
	GF_SAFEALLOC(tmp, GF_SceneDumper);
	if (!tmp) return NULL;

	/*store original*/
	tmp->dump_mode = dump_mode;

#ifndef GPAC_DISABLE_SVG
	if ((graph->RootNode && (graph->RootNode->sgprivate->tag>=GF_NODE_RANGE_LAST_VRML) )
	        || (dump_mode==GF_SM_DUMP_LASER) || (dump_mode==GF_SM_DUMP_SVG)) {
		tmp->XMLDump = GF_TRUE;
		if (dump_mode==GF_SM_DUMP_LASER) {
			tmp->LSRDump = GF_TRUE;
		}
		if (_rad_name) {
			const char* ext_name = tmp->LSRDump ? ".xsr" : ".svg";
			tmp->filename = (char *)gf_malloc(strlen(_rad_name) + strlen(ext_name) + 1);
			strcpy(tmp->filename, _rad_name);
			if (!is_final_name) strcat(tmp->filename, ext_name);
			tmp->trace = gf_fopen(tmp->filename, "wt");
			if (!tmp->trace) {
				gf_free(tmp);
				return NULL;
			}
		} else {
			tmp->trace = stdout;
		}
	} else
#endif
	{

		if (dump_mode==GF_SM_DUMP_AUTO_TXT) {
			if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) {
				dump_mode = GF_SM_DUMP_BT;
			} else if (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_X3D) {
				dump_mode = GF_SM_DUMP_X3D_VRML;
			}
		}
		else if (dump_mode==GF_SM_DUMP_AUTO_XML) {
			if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) {
				dump_mode = GF_SM_DUMP_XMTA;
			} else {
				dump_mode = GF_SM_DUMP_X3D_XML;
			}
		}

		if (_rad_name) {
			const char* ext_name;
			switch (dump_mode) {
			case GF_SM_DUMP_X3D_XML:
				ext_name = ".x3d";
				tmp->XMLDump = GF_TRUE;
				tmp->X3DDump = GF_TRUE;
				break;
			case GF_SM_DUMP_XMTA:
				ext_name = ".xmt";
				tmp->XMLDump = GF_TRUE;
				break;
			case GF_SM_DUMP_X3D_VRML:
				ext_name = ".x3dv";
				tmp->X3DDump = GF_TRUE;
				break;
			case GF_SM_DUMP_VRML:
				ext_name = ".wrl";
				break;
			default:
				ext_name = ".bt";
				break;
			}

			tmp->filename = (char *)gf_malloc(strlen(_rad_name ? _rad_name : "") + strlen(ext_name) + 1);
			strcpy(tmp->filename, _rad_name ? _rad_name : "");
			if (!is_final_name) strcat(tmp->filename, ext_name);
			tmp->trace = gf_fopen(tmp->filename, "wt");
			if (!tmp->trace) {
				gf_free(tmp);
				return NULL;
			}
		} else {
			tmp->trace = stdout;
			switch (dump_mode) {
			case GF_SM_DUMP_X3D_XML:
				tmp->XMLDump = GF_TRUE;
				tmp->X3DDump = GF_TRUE;
				break;
			case GF_SM_DUMP_XMTA:
				tmp->XMLDump = GF_TRUE;
				break;
			case GF_SM_DUMP_X3D_VRML:
				tmp->X3DDump = GF_TRUE;
				break;
			default:
				break;
			}
		}
	}
	tmp->ind_char = indent_char;
	tmp->dump_nodes = gf_list_new();
	tmp->mem_def_nodes = gf_list_new();
	tmp->inserted_routes = gf_list_new();
	tmp->sg = graph;
	return tmp;
}
GF_SceneDumper *gf_sm_dumper_new(GF_SceneGraph *graph, char *_rad_name, Bool is_final_name, char indent_char, GF_SceneDumpFormat dump_mode)
{
	GF_SceneDumper *tmp;
	if (!graph) return NULL;
	GF_SAFEALLOC(tmp, GF_SceneDumper);
	if (!tmp) return NULL;

	 
	tmp->dump_mode = dump_mode;

#ifndef GPAC_DISABLE_SVG
	if ((graph->RootNode && (graph->RootNode->sgprivate->tag>=GF_NODE_RANGE_LAST_VRML) )
	        || (dump_mode==GF_SM_DUMP_LASER) || (dump_mode==GF_SM_DUMP_SVG)) {
		tmp->XMLDump = GF_TRUE;
		if (dump_mode==GF_SM_DUMP_LASER) {
			tmp->LSRDump = GF_TRUE;
		}
		if (_rad_name) {
			const char* ext_name = tmp->LSRDump ? ".xsr" : ".svg";
			tmp->filename = (char *)gf_malloc(strlen(_rad_name) + strlen(ext_name) + 1);
			strcpy(tmp->filename, _rad_name);
			if (!is_final_name) strcat(tmp->filename, ext_name);
			tmp->trace = gf_fopen(tmp->filename, "wt");
			if (!tmp->trace) {
				gf_free(tmp);
				return NULL;
			}
		} else {
			tmp->trace = stdout;
		}
	} else
#endif
	{

		if (dump_mode==GF_SM_DUMP_AUTO_TXT) {
			if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) {
				dump_mode = GF_SM_DUMP_BT;
			} else if (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_X3D) {
				dump_mode = GF_SM_DUMP_X3D_VRML;
			}
		}
		else if (dump_mode==GF_SM_DUMP_AUTO_XML) {
			if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) {
				dump_mode = GF_SM_DUMP_XMTA;
			} else {
				dump_mode = GF_SM_DUMP_X3D_XML;
			}
		}

		if (_rad_name) {
			const char* ext_name;
			switch (dump_mode) {
			case GF_SM_DUMP_X3D_XML:
				ext_name = ".x3d";
				tmp->XMLDump = GF_TRUE;
				tmp->X3DDump = GF_TRUE;
				break;
			case GF_SM_DUMP_XMTA:
				ext_name = ".xmt";
				tmp->XMLDump = GF_TRUE;
				break;
			case GF_SM_DUMP_X3D_VRML:
				ext_name = ".x3dv";
				tmp->X3DDump = GF_TRUE;
				break;
			case GF_SM_DUMP_VRML:
				ext_name = ".wrl";
				break;
			default:
				ext_name = ".bt";
				break;
			}

			tmp->filename = (char *)gf_malloc(strlen(_rad_name ? _rad_name : "") + strlen(ext_name) + 1);
			strcpy(tmp->filename, _rad_name ? _rad_name : "");
			if (!is_final_name) strcat(tmp->filename, ext_name);
			tmp->trace = gf_fopen(tmp->filename, "wt");
			if (!tmp->trace) {
				gf_free(tmp);
				return NULL;
			}
		} else {
			tmp->trace = stdout;
			switch (dump_mode) {
			case GF_SM_DUMP_X3D_XML:
				tmp->XMLDump = GF_TRUE;
				tmp->X3DDump = GF_TRUE;
				break;
			case GF_SM_DUMP_XMTA:
				tmp->XMLDump = GF_TRUE;
				break;
			case GF_SM_DUMP_X3D_VRML:
				tmp->X3DDump = GF_TRUE;
				break;
			default:
				break;
			}
		}
	}
	tmp->ind_char = indent_char;
	tmp->dump_nodes = gf_list_new();
	tmp->mem_def_nodes = gf_list_new();
	tmp->inserted_routes = gf_list_new();
	tmp->sg = graph;
	return tmp;
}