LCOV - code coverage report
Current view: top level - scene_manager - scene_dump.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1493 2030 73.5 %
Date: 2021-04-29 23:48:07 Functions: 59 62 95.2 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Management sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/scene_manager.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/utf.h>
      29             : #include <gpac/internal/scenegraph_dev.h>
      30             : #include <gpac/nodes_x3d.h>
      31             : #include <gpac/nodes_svg.h>
      32             : #include <gpac/events.h>
      33             : #include <gpac/base_coding.h>
      34             : 
      35             : #ifndef __SYMBIAN32__
      36             : #include <wchar.h>
      37             : #endif
      38             : 
      39             : #ifndef GPAC_DISABLE_SCENE_DUMP
      40             : 
      41             : /*for QP types*/
      42             : #include "../bifs/quant.h"
      43             : 
      44             : struct _scenedump
      45             : {
      46             :         /*the scene we're dumping - set at each SceneReplace or mannually*/
      47             :         GF_SceneGraph *sg;
      48             : #ifndef GPAC_DISABLE_VRML
      49             :         /*the proto we're dumping*/
      50             :         GF_Proto *current_proto;
      51             : #endif
      52             :         FILE *trace;
      53             :         u32 indent;
      54             :         char *filename;
      55             : 
      56             :         GF_SceneDumpFormat dump_mode;
      57             :         u16 CurrentESID;
      58             :         u8 ind_char;
      59             :         Bool XMLDump, X3DDump, LSRDump;
      60             : 
      61             :         GF_List *dump_nodes;
      62             : 
      63             :         /*nodes created through conditionals while parsing but not applied*/
      64             :         GF_List *mem_def_nodes;
      65             : 
      66             :         Bool skip_scene_replace;
      67             :         /*for route insert/replace in conditionals in current scene replace*/
      68             :         GF_List *current_com_list;
      69             :         GF_List *inserted_routes;
      70             : 
      71             :         Bool in_text;
      72             : };
      73             : 
      74             : static GF_Err gf_dump_vrml_route(GF_SceneDumper *sdump, GF_Route *r, u32 dump_type);
      75             : static void gf_dump_vrml_node(GF_SceneDumper *sdump, GF_Node *node, Bool in_list, char *fieldContainer);
      76             : 
      77             : #ifndef GPAC_DISABLE_SVG
      78             : void gf_dump_svg_element(GF_SceneDumper *sdump, GF_Node *n, GF_Node *parent, Bool is_root);
      79             : #endif
      80             : 
      81             : GF_EXPORT
      82          19 : GF_SceneDumper *gf_sm_dumper_new(GF_SceneGraph *graph, char *_rad_name, Bool is_final_name, char indent_char, GF_SceneDumpFormat dump_mode)
      83             : {
      84             :         GF_SceneDumper *tmp;
      85          19 :         if (!graph) return NULL;
      86          19 :         GF_SAFEALLOC(tmp, GF_SceneDumper);
      87          19 :         if (!tmp) return NULL;
      88             : 
      89             :         /*store original*/
      90          19 :         tmp->dump_mode = dump_mode;
      91             : 
      92             : #ifndef GPAC_DISABLE_SVG
      93          19 :         if ((graph->RootNode && (graph->RootNode->sgprivate->tag>=GF_NODE_RANGE_LAST_VRML) )
      94          19 :                 || (dump_mode==GF_SM_DUMP_LASER) || (dump_mode==GF_SM_DUMP_SVG)) {
      95           2 :                 tmp->XMLDump = GF_TRUE;
      96           2 :                 if (dump_mode==GF_SM_DUMP_LASER) {
      97           2 :                         tmp->LSRDump = GF_TRUE;
      98             :                 }
      99           2 :                 if (_rad_name) {
     100           2 :                         const char* ext_name = tmp->LSRDump ? ".xsr" : ".svg";
     101           2 :                         tmp->filename = (char *)gf_malloc(strlen(_rad_name) + strlen(ext_name) + 1);
     102             :                         strcpy(tmp->filename, _rad_name);
     103           2 :                         if (!is_final_name) strcat(tmp->filename, ext_name);
     104           2 :                         tmp->trace = gf_fopen(tmp->filename, "wt");
     105           2 :                         if (!tmp->trace) {
     106           0 :                                 gf_free(tmp);
     107           0 :                                 return NULL;
     108             :                         }
     109             :                 } else {
     110           0 :                         tmp->trace = stdout;
     111             :                 }
     112             :         } else
     113             : #endif
     114             :         {
     115             : 
     116          17 :                 if (dump_mode==GF_SM_DUMP_AUTO_TXT) {
     117           0 :                         if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) {
     118             :                                 dump_mode = GF_SM_DUMP_BT;
     119           0 :                         } else if (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_X3D) {
     120             :                                 dump_mode = GF_SM_DUMP_X3D_VRML;
     121             :                         }
     122             :                 }
     123          17 :                 else if (dump_mode==GF_SM_DUMP_AUTO_XML) {
     124           0 :                         if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) {
     125             :                                 dump_mode = GF_SM_DUMP_XMTA;
     126             :                         } else {
     127             :                                 dump_mode = GF_SM_DUMP_X3D_XML;
     128             :                         }
     129             :                 }
     130             : 
     131          17 :                 if (_rad_name) {
     132             :                         const char* ext_name;
     133          15 :                         switch (dump_mode) {
     134           0 :                         case GF_SM_DUMP_X3D_XML:
     135             :                                 ext_name = ".x3d";
     136           0 :                                 tmp->XMLDump = GF_TRUE;
     137           0 :                                 tmp->X3DDump = GF_TRUE;
     138           0 :                                 break;
     139           7 :                         case GF_SM_DUMP_XMTA:
     140             :                                 ext_name = ".xmt";
     141           7 :                                 tmp->XMLDump = GF_TRUE;
     142           7 :                                 break;
     143           0 :                         case GF_SM_DUMP_X3D_VRML:
     144             :                                 ext_name = ".x3dv";
     145           0 :                                 tmp->X3DDump = GF_TRUE;
     146           0 :                                 break;
     147             :                         case GF_SM_DUMP_VRML:
     148             :                                 ext_name = ".wrl";
     149             :                                 break;
     150           8 :                         default:
     151             :                                 ext_name = ".bt";
     152           8 :                                 break;
     153             :                         }
     154             : 
     155          15 :                         tmp->filename = (char *)gf_malloc(strlen(_rad_name ? _rad_name : "") + strlen(ext_name) + 1);
     156             :                         strcpy(tmp->filename, _rad_name ? _rad_name : "");
     157          15 :                         if (!is_final_name) strcat(tmp->filename, ext_name);
     158          15 :                         tmp->trace = gf_fopen(tmp->filename, "wt");
     159          15 :                         if (!tmp->trace) {
     160           0 :                                 gf_free(tmp);
     161           0 :                                 return NULL;
     162             :                         }
     163             :                 } else {
     164           2 :                         tmp->trace = stdout;
     165           2 :                         switch (dump_mode) {
     166           0 :                         case GF_SM_DUMP_X3D_XML:
     167           0 :                                 tmp->XMLDump = GF_TRUE;
     168           0 :                                 tmp->X3DDump = GF_TRUE;
     169           0 :                                 break;
     170           0 :                         case GF_SM_DUMP_XMTA:
     171           0 :                                 tmp->XMLDump = GF_TRUE;
     172           0 :                                 break;
     173           0 :                         case GF_SM_DUMP_X3D_VRML:
     174           0 :                                 tmp->X3DDump = GF_TRUE;
     175           0 :                                 break;
     176             :                         default:
     177             :                                 break;
     178             :                         }
     179             :                 }
     180             :         }
     181          19 :         tmp->ind_char = indent_char;
     182          19 :         tmp->dump_nodes = gf_list_new();
     183          19 :         tmp->mem_def_nodes = gf_list_new();
     184          19 :         tmp->inserted_routes = gf_list_new();
     185          19 :         tmp->sg = graph;
     186          19 :         return tmp;
     187             : }
     188             : 
     189             : GF_EXPORT
     190           0 : void gf_sm_dumper_set_extra_graph(GF_SceneDumper *sdump, GF_SceneGraph *extra)
     191             : {
     192           0 :         sdump->sg = extra;
     193           0 : }
     194             : 
     195             : GF_EXPORT
     196          19 : void gf_sm_dumper_del(GF_SceneDumper *sdump)
     197             : {
     198          19 :         gf_list_del(sdump->dump_nodes);
     199          38 :         while (gf_list_count(sdump->mem_def_nodes)) {
     200           0 :                 GF_Node *tmp = (GF_Node *)gf_list_get(sdump->mem_def_nodes, 0);
     201           0 :                 gf_list_rem(sdump->mem_def_nodes, 0);
     202           0 :                 gf_node_unregister(tmp, NULL);
     203             :         }
     204          19 :         gf_list_del(sdump->mem_def_nodes);
     205          19 :         gf_list_del(sdump->inserted_routes);
     206          19 :         if (sdump->trace != stdout) gf_fclose(sdump->trace);
     207          19 :         if (sdump->filename) {
     208          17 :                 gf_free(sdump->filename);
     209          17 :                 sdump->filename = NULL;
     210             :         }
     211          19 :         gf_free(sdump);
     212          19 : }
     213             : 
     214           0 : char *gf_sm_dump_get_name(GF_SceneDumper *bd)
     215             : {
     216           0 :         if (!bd) return NULL;
     217           0 :         return bd->filename;
     218             : }
     219             : 
     220          19 : static void gf_dump_setup(GF_SceneDumper *sdump, GF_Descriptor *root_od)
     221             : {
     222          19 :         if (sdump->XMLDump) {
     223           9 :                 gf_fprintf(sdump->trace, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
     224           9 :                 if (sdump->dump_mode==GF_SM_DUMP_XML) return;
     225          18 :                 gf_fprintf(sdump->trace, "<!-- %s Scene Dump -->\n",
     226             :                         (sdump->dump_mode==GF_SM_DUMP_SVG) ? "SVG" :
     227           9 :                         (sdump->dump_mode==GF_SM_DUMP_LASER) ? "LASeR" :
     228           7 :                         sdump->X3DDump ? "X3D" : "XMT-A"
     229             :                        );
     230             :         }
     231          19 :         if (sdump->dump_mode==GF_SM_DUMP_SVG) return;
     232          19 :         if (sdump->LSRDump) {
     233           2 :                 gf_fprintf(sdump->trace, "<saf:SAFSession xmlns:saf=\"urn:mpeg:mpeg4:SAF:2005\" >\n");
     234             : #ifndef GPAC_DISABLE_OD_DUMP
     235           2 :                 if (root_od) {
     236             :                         GF_ObjectDescriptor *iod = (GF_ObjectDescriptor *)root_od;
     237             :                         u32 i, count;
     238           2 :                         gf_fprintf(sdump->trace, "<saf:sceneHeader>\n");
     239           2 :                         count = gf_list_count(iod->ESDescriptors);
     240           5 :                         for (i=0; i<count; i++) {
     241             :                                 GF_LASERConfig lsrcfg;
     242           3 :                                 GF_ESD *esd = (GF_ESD *)gf_list_get(iod->ESDescriptors, i);
     243           4 :                                 if (esd->decoderConfig->streamType != GF_STREAM_SCENE) continue;
     244           2 :                                 if (esd->decoderConfig->objectTypeIndication != 0x09) continue;
     245           2 :                                 if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) continue;
     246           2 :                                 gf_odf_get_laser_config(esd->decoderConfig->decoderSpecificInfo, &lsrcfg);
     247           2 :                                 gf_odf_dump_desc((GF_Descriptor*)&lsrcfg, sdump->trace, 1, 1);
     248             :                         }
     249           2 :                         gf_fprintf(sdump->trace, "</saf:sceneHeader>\n");
     250             :                 }
     251             : #endif
     252             :                 return;
     253             :         }
     254             : 
     255          17 :         if (!sdump->X3DDump) {
     256             :                 /*setup XMT*/
     257          17 :                 if (sdump->XMLDump) {
     258           7 :                         gf_fprintf(sdump->trace, "<XMT-A xmlns=\"urn:mpeg:mpeg4:xmta:schema:2002\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:mpeg:mpeg4:xmta:schema:2002 xmt-a.xsd\">\n");
     259           7 :                         gf_fprintf(sdump->trace, " <Header>\n");
     260             : #ifndef GPAC_DISABLE_OD_DUMP
     261           7 :                         if (root_od) gf_odf_dump_desc(root_od, sdump->trace, 1, 1);
     262             : #endif
     263           7 :                         gf_fprintf(sdump->trace, " </Header>\n");
     264           7 :                         gf_fprintf(sdump->trace, " <Body>\n");
     265           7 :                         if (!root_od) {
     266           0 :                                 gf_fprintf(sdump->trace, "  <Replace>\n");
     267             :                         }
     268             :                 } else {
     269          10 :                         if (sdump->dump_mode==GF_SM_DUMP_VRML) {
     270           0 :                                 gf_fprintf(sdump->trace, "#VRML V2.0\n");
     271             :                         } else {
     272             :                                 /*dump root OD*/
     273             : #ifndef GPAC_DISABLE_OD_DUMP
     274          10 :                                 if (root_od) gf_odf_dump_desc(root_od, sdump->trace, 0, 0);
     275             : #endif
     276             :                         }
     277          10 :                         gf_fprintf(sdump->trace, "\n");
     278             :                 }
     279             :         } else {
     280           0 :                 if (sdump->XMLDump) {
     281           0 :                         gf_fprintf(sdump->trace, "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n");
     282           0 :                         gf_fprintf(sdump->trace, "<X3D xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.0.xsd\" version=\"3.0\">\n");
     283           0 :                         gf_fprintf(sdump->trace, "<head>\n");
     284           0 :                         gf_fprintf(sdump->trace, "<meta content=\"X3D File Converted/Dumped by GPAC Version %s - %s\" name=\"generator\"/>\n", gf_gpac_version(), gf_gpac_copyright() );
     285           0 :                         gf_fprintf(sdump->trace, "</head>\n");
     286           0 :                         gf_fprintf(sdump->trace, " <Scene>\n");
     287             :                 } else {
     288           0 :                         gf_fprintf(sdump->trace, "#X3D V3.0\n\n");
     289             :                 }
     290             :         }
     291             : }
     292             : 
     293          19 : static void gf_dump_finalize(GF_SceneDumper *sdump, GF_Descriptor *root_od)
     294             : {
     295          19 :         if (sdump->dump_mode==GF_SM_DUMP_SVG) return;
     296             : 
     297          19 :         if (sdump->LSRDump) {
     298           2 :                 gf_fprintf(sdump->trace, "<saf:endOfSAFSession/>\n</saf:SAFSession>\n");
     299           2 :                 return;
     300             :         }
     301          17 :         if (!sdump->XMLDump) return;
     302             : 
     303           7 :         if (!sdump->X3DDump) {
     304           7 :                 if (!root_od) {
     305           0 :                         gf_fprintf(sdump->trace, "  </Replace>\n");
     306             :                 }
     307           7 :                 gf_fprintf(sdump->trace, " </Body>\n");
     308           7 :                 gf_fprintf(sdump->trace, "</XMT-A>\n");
     309             :         } else {
     310           0 :                 gf_fprintf(sdump->trace, " </Scene>\n");
     311           0 :                 gf_fprintf(sdump->trace, "</X3D>\n");
     312             :         }
     313             : }
     314             : 
     315         535 : static Bool gf_dump_vrml_is_def_node(GF_SceneDumper *sdump, GF_Node *node)
     316             : {
     317         535 :         s32 i = gf_list_find(sdump->dump_nodes, node);
     318         535 :         if (i>=0) return 0;
     319         472 :         gf_list_add(sdump->dump_nodes, node);
     320             :         return 1;
     321             : }
     322             : 
     323             : static GF_Node *gf_dump_find_node(GF_SceneDumper *sdump, u32 ID)
     324             : {
     325         144 :         GF_Node *ret = gf_sg_find_node(sdump->sg, ID);
     326         144 :         if (ret) return ret;
     327             :         return NULL;
     328             : }
     329             : 
     330             : #define DUMP_IND(sdump) \
     331             :         if (sdump->trace) {          \
     332             :                 u32 z;  \
     333             :                 for (z=0; z<sdump->indent; z++) gf_fprintf(sdump->trace, "%c", sdump->ind_char);  \
     334             :         }
     335             : 
     336             : 
     337        1466 : static void StartElement(GF_SceneDumper *sdump, const char *name)
     338             : {
     339        1466 :         if (!sdump->trace) return;
     340       10957 :         DUMP_IND(sdump);
     341        1466 :         if (!sdump->XMLDump) {
     342          26 :                 gf_fprintf(sdump->trace, "%s {\n", name);
     343             :         } else {
     344        1440 :                 gf_fprintf(sdump->trace, "<%s", name);
     345             :         }
     346             : }
     347             : 
     348        1613 : static void EndElementHeader(GF_SceneDumper *sdump, Bool has_sub_el)
     349             : {
     350        2222 :         if (!sdump->trace) return;
     351        2222 :         if (sdump->XMLDump) {
     352         857 :                 if (has_sub_el) {
     353        1041 :                         gf_fprintf(sdump->trace, ">\n");
     354             :                 } else {
     355         399 :                         gf_fprintf(sdump->trace, "/>\n");
     356             :                 }
     357             :         }
     358             : }
     359             : 
     360        1766 : static void EndElement(GF_SceneDumper *sdump, const char *name, Bool had_sub_el)
     361             : {
     362        1766 :         if (!sdump->trace) return;
     363        1766 :         if (!sdump->XMLDump) {
     364        1536 :                 DUMP_IND(sdump);
     365         356 :                 gf_fprintf(sdump->trace, "}\n");
     366             :         } else {
     367        1410 :                 if (had_sub_el) {
     368        7585 :                         DUMP_IND(sdump);
     369        1041 :                         gf_fprintf(sdump->trace, "</%s>\n", name);
     370             :                 }
     371             :         }
     372             : }
     373             : 
     374        2334 : static void StartAttribute(GF_SceneDumper *sdump, const char *name)
     375             : {
     376        2334 :         if (!sdump->trace) return;
     377        2334 :         if (!sdump->XMLDump) {
     378        7073 :                 DUMP_IND(sdump);
     379        1161 :                 gf_fprintf(sdump->trace, "%s ", name);
     380             :         } else {
     381        1173 :                 gf_fprintf(sdump->trace, " %s=\"", name);
     382             :         }
     383             : }
     384             : 
     385        2334 : static void EndAttribute(GF_SceneDumper *sdump)
     386             : {
     387        2334 :         if (!sdump->trace) return;
     388        2334 :         if (!sdump->XMLDump) {
     389        1161 :                 gf_fprintf(sdump->trace, "\n");
     390             :         } else {
     391        1173 :                 gf_fprintf(sdump->trace, "\"");
     392             :         }
     393             : }
     394             : 
     395             : 
     396         189 : static void StartList(GF_SceneDumper *sdump, const char *name)
     397             : {
     398         189 :         if (!sdump->trace) return;
     399         902 :         DUMP_IND(sdump);
     400         189 :         if (!sdump->XMLDump) {
     401          92 :                 if (name)
     402          92 :                         gf_fprintf(sdump->trace, "%s [\n", name);
     403             :                 else
     404           0 :                         gf_fprintf(sdump->trace, "[\n");
     405             :         } else {
     406          97 :                 gf_fprintf(sdump->trace, "<%s>\n", name);
     407             :         }
     408             : }
     409             : 
     410         190 : static void EndList(GF_SceneDumper *sdump, const char *name)
     411             : {
     412         190 :         if (!sdump->trace) return;
     413         904 :         DUMP_IND(sdump);
     414         190 :         if (!sdump->XMLDump) {
     415          93 :                 gf_fprintf(sdump->trace, "]\n");
     416             :         } else {
     417          97 :                 gf_fprintf(sdump->trace, "</%s>\n", name);
     418             :         }
     419             : }
     420             : 
     421             : 
     422         140 : static void scene_dump_utf_string(GF_SceneDumper *sdump, Bool escape_xml, char *str)
     423             : {
     424             :         size_t _len;
     425             :         u32 len, i;
     426             :         u16 *uniLine;
     427         140 :         if (!str) return;
     428         140 :         len = (u32) strlen(str);
     429         140 :         if (!len) return;
     430         140 :         uniLine = (u16*)gf_malloc(sizeof(u16) * len*4);
     431         140 :         _len = gf_utf8_mbstowcs(uniLine, len, (const char **) &str);
     432         140 :         if (_len != (size_t) (-1)) {
     433         140 :                 len = (u32) _len;
     434       39299 :                 for (i=0; i<len; i++) {
     435             :                         //if (uniLine[i] == (u16) '\"') gf_fprintf(sdump->trace, "\\");
     436       39299 :                         switch (uniLine[i]) {
     437           0 :                         case '\'':
     438           0 :                                 if (escape_xml) gf_fprintf(sdump->trace, "&apos;");
     439           0 :                                 else gf_fprintf(sdump->trace, "'");
     440             :                                 break;
     441           0 :                         case '\"':
     442           0 :                                 if (escape_xml) gf_fprintf(sdump->trace, "&quot;");
     443           0 :                                 else gf_fprintf(sdump->trace, "\"");
     444             :                                 break;
     445           0 :                         case '&':
     446           0 :                                 gf_fprintf(sdump->trace, "&amp;");
     447             :                                 break;
     448           0 :                         case '>':
     449           0 :                                 gf_fprintf(sdump->trace, "&gt;");
     450             :                                 break;
     451           0 :                         case '<':
     452           0 :                                 gf_fprintf(sdump->trace, "&lt;");
     453             :                                 break;
     454             :                         case '\r':
     455             :                         case '\n':
     456             :                                 /* Does nothing : gf_fprintf(sdump->trace, "");, fflush instead ?*/
     457             :                                 break;
     458       39285 :                         default:
     459       39285 :                                 if (uniLine[i]<128) {
     460       39285 :                                         gf_fprintf(sdump->trace, "%c", (u8) uniLine[i]);
     461             :                                 } else {
     462           0 :                                         gf_fprintf(sdump->trace, "&#%d;", uniLine[i]);
     463             :                                 }
     464             :                                 break;
     465             :                         }
     466             :                 }
     467             :         }
     468         140 :         gf_free(uniLine);
     469             : }
     470             : 
     471             : #ifndef GPAC_DISABLE_VRML
     472             : 
     473         857 : static void scene_dump_vrml_id(GF_SceneDumper *sdump, GF_Node *node)
     474             : {
     475             :         u32 id;
     476             :         const char *node_name;
     477         857 :         if (!sdump->trace) return;
     478             :         /*FIXME - optimize id/name fetch*/
     479         857 :         node_name = gf_node_get_name_and_id(node, &id);
     480         857 :         if (node_name)
     481         301 :                 gf_fprintf(sdump->trace, "%s", node_name);
     482             :         else
     483         556 :                 gf_fprintf(sdump->trace, "N%d", id - 1);
     484             : }
     485             : 
     486          27 : static Bool scene_dump_vrml_find_route_name(GF_SceneDumper *sdump, u32 ID, const char **outName)
     487             : {
     488             :         GF_Route *r;
     489             :         u32 i;
     490             :         GF_Command *com;
     491          27 :         r = gf_sg_route_find(sdump->sg, ID);
     492          27 :         if (r) {
     493           0 :                 (*outName) = r->name;
     494           0 :                 return 1;
     495             :         }
     496             : 
     497          27 :         i=0;
     498          54 :         while ((com = (GF_Command *)gf_list_enum(sdump->inserted_routes, &i))) {
     499          27 :                 if (com->tag == GF_SG_ROUTE_INSERT) {
     500          27 :                         if (com->RouteID==ID) {
     501          27 :                                 (*outName) = com->def_name;
     502          27 :                                 return 1;
     503             :                         }
     504             :                 }
     505             :         }
     506           0 :         if (!sdump->current_com_list) return 0;
     507           0 :         i=1;
     508           0 :         while ((com = (GF_Command *)gf_list_enum(sdump->current_com_list, &i))) {
     509           0 :                 if ((com->tag == GF_SG_ROUTE_INSERT) || (com->tag == GF_SG_ROUTE_REPLACE)) {
     510           0 :                         if (com->RouteID==ID) {
     511           0 :                                 (*outName) = com->def_name;
     512           0 :                                 return 1;
     513             :                         }
     514             :                 } else return 0;
     515             :         }
     516             :         return 0;
     517             : }
     518             : 
     519          27 : static void scene_dump_vrml_route_id(GF_SceneDumper *sdump, u32 routeID, char *rName)
     520             : {
     521          27 :         if (!sdump->trace) return;
     522          27 :         if (!rName) scene_dump_vrml_find_route_name(sdump, routeID, (const char **) &rName);
     523             : 
     524          27 :         if (rName)
     525           9 :                 gf_fprintf(sdump->trace, "%s", rName);
     526             :         else
     527          18 :                 gf_fprintf(sdump->trace, "R%d", routeID - 1);
     528             : }
     529             : 
     530             : 
     531        5310 : static void gf_dump_vrml_sffield(GF_SceneDumper *sdump, u32 type, void *ptr, Bool is_mf, GF_Node *node)
     532             : {
     533        5310 :         switch (type) {
     534         280 :         case GF_SG_VRML_SFBOOL:
     535         280 :                 gf_fprintf(sdump->trace, "%s", * ((SFBool *)ptr) ? "true" : "false");
     536         280 :                 break;
     537         999 :         case GF_SG_VRML_SFINT32:
     538         999 :                 gf_fprintf(sdump->trace, "%d", * ((SFInt32 *)ptr) );
     539         999 :                 break;
     540        1774 :         case GF_SG_VRML_SFFLOAT:
     541        1774 :                 gf_fprintf(sdump->trace, "%g", FIX2FLT( * ((SFFloat *)ptr) ) );
     542        1774 :                 break;
     543           0 :         case GF_SG_VRML_SFDOUBLE:
     544           0 :                 gf_fprintf(sdump->trace, "%g", * ((SFDouble *)ptr) );
     545           0 :                 break;
     546           9 :         case GF_SG_VRML_SFTIME:
     547           9 :                 gf_fprintf(sdump->trace, "%g", * ((SFTime *)ptr) );
     548           9 :                 break;
     549         462 :         case GF_SG_VRML_SFCOLOR:
     550         462 :                 gf_fprintf(sdump->trace, "%g %g %g", FIX2FLT( ((SFColor *)ptr)->red ), FIX2FLT( ((SFColor *)ptr)->green ), FIX2FLT( ((SFColor *)ptr)->blue ));
     551         462 :                 break;
     552           0 :         case GF_SG_VRML_SFCOLORRGBA:
     553           0 :                 gf_fprintf(sdump->trace, "%g %g %g %g", FIX2FLT( ((SFColorRGBA *)ptr)->red ), FIX2FLT( ((SFColorRGBA *)ptr)->green ), FIX2FLT( ((SFColorRGBA *)ptr)->blue ), FIX2FLT( ((SFColorRGBA *)ptr)->alpha ));
     554           0 :                 break;
     555        1040 :         case GF_SG_VRML_SFVEC2F:
     556        1040 :                 gf_fprintf(sdump->trace, "%g %g", FIX2FLT( ((SFVec2f *)ptr)->x ), FIX2FLT( ((SFVec2f *)ptr)->y ));
     557        1040 :                 break;
     558           0 :         case GF_SG_VRML_SFVEC2D:
     559           0 :                 gf_fprintf(sdump->trace, "%g %g", ((SFVec2d *)ptr)->x, ((SFVec2d *)ptr)->y);
     560           0 :                 break;
     561         397 :         case GF_SG_VRML_SFVEC3F:
     562         397 :                 gf_fprintf(sdump->trace, "%g %g %g", FIX2FLT( ((SFVec3f *)ptr)->x ), FIX2FLT( ((SFVec3f *)ptr)->y ), FIX2FLT( ((SFVec3f *)ptr)->z ));
     563         397 :                 break;
     564           0 :         case GF_SG_VRML_SFVEC3D:
     565           0 :                 gf_fprintf(sdump->trace, "%g %g %g", ((SFVec3d *)ptr)->x, ((SFVec3d *)ptr)->y, ((SFVec3d *)ptr)->z);
     566           0 :                 break;
     567          19 :         case GF_SG_VRML_SFROTATION:
     568          19 :                 gf_fprintf(sdump->trace, "%g %g %g %g", FIX2FLT( ((SFRotation *)ptr)->x ), FIX2FLT( ((SFRotation *)ptr)->y ), FIX2FLT( ((SFRotation *)ptr)->z ), FIX2FLT( ((SFRotation *)ptr)->q ) );
     569          19 :                 break;
     570             : 
     571           0 :         case GF_SG_VRML_SFATTRREF:
     572             :         {
     573             :                 SFAttrRef *ar = (SFAttrRef *)ptr;
     574           0 :                 if (ar->node) {
     575             :                         GF_FieldInfo pinfo;
     576           0 :                         gf_node_get_field(ar->node, ar->fieldIndex, &pinfo);
     577           0 :                         scene_dump_vrml_id(sdump, ar->node);
     578           0 :                         gf_fprintf(sdump->trace, ".%s", pinfo.name);
     579             :                 }
     580             :         }
     581             :         break;
     582           9 :         case GF_SG_VRML_SFSCRIPT:
     583             :         {
     584             :                 u32 len, i;
     585             :                 char *str;
     586           9 :                 str = (char*)((SFScript *)ptr)->script_text;
     587           9 :                 len = (u32)strlen(str);
     588             : 
     589           9 :                 if (!sdump->XMLDump) {
     590           4 :                         gf_fprintf(sdump->trace, "\"%s\"", str);
     591             :                 }
     592             :                 else {
     593             :                         size_t _len;
     594             :                         u16 *uniLine;
     595             : 
     596           5 :                         uniLine = (u16*)gf_malloc(sizeof(short) * (len + 1));
     597           5 :                         _len = gf_utf8_mbstowcs(uniLine, len, (const char **)&str);
     598             : 
     599           5 :                         if (_len != (size_t)-1) {
     600           5 :                                 len = (u32)_len;
     601             : 
     602        5394 :                                 for (i = 0; i<len; i++) {
     603             : 
     604        5389 :                                         switch (uniLine[i]) {
     605          20 :                                         case '&':
     606          20 :                                                 gf_fprintf(sdump->trace, "&amp;");
     607          20 :                                                 break;
     608          35 :                                         case '<':
     609          35 :                                                 gf_fprintf(sdump->trace, "&lt;");
     610          35 :                                                 break;
     611          60 :                                         case '>':
     612          60 :                                                 gf_fprintf(sdump->trace, "&gt;");
     613          60 :                                                 break;
     614          30 :                                         case '\'':
     615             :                                         case '"':
     616          30 :                                                 gf_fprintf(sdump->trace, "&apos;");
     617          30 :                                                 break;
     618             :                                         case 0:
     619             :                                                 break;
     620             :                                                 /*FIXME: how the heck can we preserve newlines and spaces of JavaScript in
     621             :                                                 an XML attribute in any viewer ? */
     622        5244 :                                         default:
     623        5244 :                                                 if (uniLine[i]<128) {
     624        5244 :                                                         gf_fprintf(sdump->trace, "%c", (u8)uniLine[i]);
     625             :                                                 }
     626             :                                                 else {
     627           0 :                                                         gf_fprintf(sdump->trace, "&#%d;", uniLine[i]);
     628             :                                                 }
     629             :                                                 break;
     630             :                                         }
     631             :                         }
     632             :                 }
     633           5 :                         gf_free(uniLine);
     634             :         }
     635           9 :                 DUMP_IND(sdump);
     636             :         }
     637           9 :         break;
     638             : 
     639         251 :         case GF_SG_VRML_SFSTRING:
     640             :         {
     641             :                 char *str;
     642         251 :                 if (sdump->XMLDump) {
     643         117 :                         if (is_mf) gf_fprintf(sdump->trace, sdump->X3DDump ? "\"" : "&quot;");
     644             :                 } else {
     645         134 :                         gf_fprintf(sdump->trace, "\"");
     646             :                 }
     647             :                 /*dump in unicode*/
     648         251 :                 str = ((SFString *)ptr)->buffer;
     649             : 
     650         251 :                 if (node && (gf_node_get_tag(node)==TAG_MPEG4_BitWrapper)) {
     651           9 :                         u32 bufsize = 50+ ((M_BitWrapper*)node)->buffer_len * 2;
     652           9 :                         str = gf_malloc(sizeof(char)* bufsize);
     653           9 :                         if (str) {
     654             :                                 s32 res;
     655             :                                 strcpy(str, "data:application/octet-string;base64,");
     656           9 :                                 res = gf_base64_encode(((M_BitWrapper*)node)->buffer.buffer, ((M_BitWrapper*)node)->buffer_len, str+37, bufsize-37);
     657           9 :                                 if (res<0) {
     658           0 :                                         gf_free(str);
     659             :                                         str = NULL;
     660             :                                 } else {
     661           9 :                                         str[res+37] = 0;
     662             :                                 }
     663             :                         }
     664             :                 }
     665         251 :                 if (str && str[0]) {
     666         239 :                         if (sdump->XMLDump) {
     667         112 :                                 scene_dump_utf_string(sdump, 1, str);
     668         127 :                         } else if (!strchr(str, '\"')) {
     669         127 :                                 gf_fprintf(sdump->trace, "%s", str);
     670             :                         } else {
     671           0 :                                 u32 i, len = (u32)strlen(str);
     672           0 :                                 for (i=0; i<len; i++) {
     673           0 :                                         if (str[i]=='\"') gf_fputc('\\', sdump->trace);
     674           0 :                                         gf_fputc(str[i], sdump->trace);
     675             :                                 }
     676             :                         }
     677             :                 }
     678         251 :                 if (node && (gf_node_get_tag(node)==TAG_MPEG4_BitWrapper)) {
     679           9 :                         if (str) gf_free(str);
     680             :                 }
     681             : 
     682         251 :                 if (sdump->XMLDump) {
     683         117 :                         if (is_mf) gf_fprintf(sdump->trace, sdump->X3DDump ? "\"" : "&quot;");
     684             :                 } else {
     685         134 :                         gf_fprintf(sdump->trace, "\"");
     686             :                 }
     687             :         }
     688             :         break;
     689             : 
     690          61 :         case GF_SG_VRML_SFURL:
     691          61 :                 if (((SFURL *)ptr)->url) {
     692             : #if 0
     693             :                         u32 len;
     694             :                         char *str;
     695             :                         short uniLine[5000];
     696             :                         str = ((SFURL *)ptr)->url;
     697             :                         len = gf_utf8_mbstowcs(uniLine, 5000, (const char **) &str);
     698             :                         if (len != (size_t) -1) {
     699             :                                 gf_fprintf(sdump->trace, sdump->XMLDump ? (sdump->X3DDump ?  "'" : "&quot;") : "\"");
     700             :                                 fwprintf(sdump->trace, (unsigned short *) uniLine);
     701             :                                 gf_fprintf(sdump->trace, sdump->XMLDump ? (sdump->X3DDump ?  "'" : "&quot;") : "\"");
     702             :                         }
     703             : #else
     704          18 :                         gf_fprintf(sdump->trace, sdump->XMLDump ? (sdump->X3DDump ?  "'" : "&quot;") : "\"");
     705          18 :                         gf_fprintf(sdump->trace, "%s", ((SFURL *)ptr)->url);
     706          18 :                         gf_fprintf(sdump->trace, sdump->XMLDump ? (sdump->X3DDump ?  "'" : "&quot;") : "\"");
     707             : #endif
     708             :                 } else {
     709          43 :                         if (sdump->XMLDump) {
     710          22 :                                 gf_fprintf(sdump->trace, "&quot;od://od%d&quot;", ((SFURL *)ptr)->OD_ID);
     711             :                         } else {
     712          21 :                                 gf_fprintf(sdump->trace, "od:%d", ((SFURL *)ptr)->OD_ID);
     713             :                         }
     714             :                 }
     715             :                 break;
     716           9 :         case GF_SG_VRML_SFIMAGE:
     717             :         {
     718             :                 u32 i, count;
     719             :                 SFImage *img = (SFImage *)ptr;
     720           9 :                 gf_fprintf(sdump->trace, "%d %d %d", img->width, img->height, img->numComponents);
     721           9 :                 count = img->width * img->height * img->numComponents;
     722         162 :                 for (i=0; i<count; ) {
     723         144 :                         switch (img->numComponents) {
     724         144 :                         case 1:
     725         144 :                                 gf_fprintf(sdump->trace, " 0x%02X", img->pixels[i]);
     726         144 :                                 i++;
     727         144 :                                 break;
     728           0 :                         case 2:
     729           0 :                                 gf_fprintf(sdump->trace, " 0x%02X%02X", img->pixels[i], img->pixels[i+1]);
     730           0 :                                 i+=2;
     731           0 :                                 break;
     732           0 :                         case 3:
     733           0 :                                 gf_fprintf(sdump->trace, " 0x%02X%02X%02X", img->pixels[i], img->pixels[i+1], img->pixels[i+2]);
     734           0 :                                 i+=3;
     735           0 :                                 break;
     736           0 :                         case 4:
     737           0 :                                 gf_fprintf(sdump->trace, " 0x%02X%02X%02X%02X", img->pixels[i], img->pixels[i+1], img->pixels[i+2], img->pixels[i+3]);
     738           0 :                                 i+=4;
     739           0 :                                 break;
     740             :                         }
     741             :                 }
     742             :         }
     743             :         break;
     744             :         }
     745        5310 : }
     746             : 
     747             : 
     748         245 : static void gf_dump_vrml_simple_field(GF_SceneDumper *sdump, GF_FieldInfo field, GF_Node *parent)
     749             : {
     750             :         u32 i, sf_type;
     751             :         GF_ChildNodeItem *list;
     752             :         void *slot_ptr;
     753             : 
     754         245 :         switch (field.fieldType) {
     755           0 :         case GF_SG_VRML_SFNODE:
     756             :                 assert ( *(GF_Node **)field.far_ptr);
     757           0 :                 gf_dump_vrml_node(sdump, *(GF_Node **)field.far_ptr, 0, NULL);
     758           0 :                 return;
     759           0 :         case GF_SG_VRML_MFNODE:
     760           0 :                 list = * ((GF_ChildNodeItem **) field.far_ptr);
     761             :                 assert( list );
     762           0 :                 sdump->indent++;
     763           0 :                 while (list) {
     764           0 :                         gf_dump_vrml_node(sdump, list->node, 1, NULL);
     765           0 :                         list = list->next;
     766             :                 }
     767           0 :                 sdump->indent--;
     768             :                 return;
     769             :         case GF_SG_VRML_SFCOMMANDBUFFER:
     770             :                 return;
     771             :         }
     772         245 :         if (gf_sg_vrml_is_sf_field(field.fieldType)) {
     773         245 :                 if (sdump->XMLDump) StartAttribute(sdump, "value");
     774         245 :                 gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, parent);
     775         245 :                 if (sdump->XMLDump) EndAttribute(sdump);
     776             :         } else {
     777             :                 GenMFField *mffield;
     778             :                 mffield = (GenMFField *) field.far_ptr;
     779           0 :                 sf_type = gf_sg_vrml_get_sf_type(field.fieldType);
     780           0 :                 if (!sdump->XMLDump) {
     781           0 :                         gf_fprintf(sdump->trace, "[");
     782           0 :                 } else if (sf_type==GF_SG_VRML_SFSTRING) {
     783           0 :                         gf_fprintf(sdump->trace, " value=\'");
     784             :                 } else {
     785           0 :                         StartAttribute(sdump, "value");
     786             :                 }
     787           0 :                 for (i=0; i<mffield->count; i++) {
     788           0 :                         if (i) gf_fprintf(sdump->trace, " ");
     789           0 :                         gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
     790             :                         /*this is to cope with single MFString which shall appear as SF in XMT*/
     791           0 :                         gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, 1, parent);
     792             :                 }
     793           0 :                 if (!sdump->XMLDump) {
     794           0 :                         gf_fprintf(sdump->trace, "]");
     795           0 :                 } else if (sf_type==GF_SG_VRML_SFSTRING) {
     796           0 :                         gf_fprintf(sdump->trace, "\'");
     797             :                 } else {
     798           0 :                         EndAttribute(sdump);
     799             :                 }
     800             :         }
     801             : }
     802             : 
     803        2668 : static void gf_dump_vrml_field(GF_SceneDumper *sdump, GF_Node *node, GF_FieldInfo field)
     804             : {
     805             :         u32 i, sf_type;
     806             :         Bool needs_field_container;
     807             :         GF_ChildNodeItem *list;
     808             :         void *slot_ptr;
     809             : 
     810        2668 :         switch (field.fieldType) {
     811         854 :         case GF_SG_VRML_SFNODE:
     812             :                 assert ( *(GF_Node **)field.far_ptr);
     813             : 
     814         854 :                 if (sdump->XMLDump) {
     815         444 :                         if (!sdump->X3DDump) {
     816         444 :                                 StartElement(sdump, (char *) field.name);
     817         444 :                                 EndElementHeader(sdump, 1);
     818         444 :                                 sdump->indent++;
     819             :                         }
     820             :                 } else {
     821         410 :                         StartAttribute(sdump, field.name);
     822             :                 }
     823         854 :                 gf_dump_vrml_node(sdump, *(GF_Node **)field.far_ptr, 0, NULL);
     824             : 
     825         854 :                 if (sdump->XMLDump) {
     826         444 :                         if (!sdump->X3DDump) {
     827         444 :                                 sdump->indent--;
     828         444 :                                 EndElement(sdump, (char *) field.name, 1);
     829             :                         }
     830             :                 } else {
     831         410 :                         EndAttribute(sdump);
     832             :                 }
     833        1100 :                 return;
     834         189 :         case GF_SG_VRML_MFNODE:
     835             :                 needs_field_container = 0;
     836         189 :                 if (sdump->XMLDump && sdump->X3DDump) {
     837             :                         u32 count, nb_ndt;
     838             :                         GF_FieldInfo info;
     839           0 :                         if (!strcmp(field.name, "children")) {
     840             :                                 needs_field_container = 0;
     841             :                         } else {
     842             :                                 nb_ndt = 0;
     843           0 :                                 count = gf_node_get_field_count(node);
     844           0 :                                 for (i=0; i<count; i++) {
     845           0 :                                         gf_node_get_field(node, i, &info);
     846           0 :                                         if ((info.eventType==GF_SG_EVENT_IN) || (info.eventType==GF_SG_EVENT_OUT)) continue;
     847           0 :                                         if (info.NDTtype==field.NDTtype) nb_ndt++;
     848             :                                 }
     849           0 :                                 needs_field_container = (nb_ndt>1) ? 1 : 0;
     850             :                         }
     851             :                 }
     852             : 
     853             : #ifndef GPAC_DISABLE_X3D
     854         189 :                 if (!sdump->X3DDump) {
     855         189 :                         if (gf_node_get_tag(node)==TAG_X3D_Switch) field.name = "choice";
     856             :                 }
     857             : #endif
     858         189 :                 list = * ((GF_ChildNodeItem **) field.far_ptr);
     859             :                 assert(list);
     860         189 :                 if (!sdump->XMLDump || !sdump->X3DDump) StartList(sdump, field.name);
     861         189 :                 sdump->indent++;
     862        1092 :                 while (list) {
     863         903 :                         gf_dump_vrml_node(sdump, list->node, 1, needs_field_container ? (char *) field.name : NULL);
     864         903 :                         list = list->next;
     865             :                 }
     866         189 :                 sdump->indent--;
     867         189 :                 if (!sdump->XMLDump || !sdump->X3DDump) EndList(sdump, field.name);
     868             :                 return;
     869          57 :         case GF_SG_VRML_SFCOMMANDBUFFER:
     870             :         {
     871             :                 SFCommandBuffer *cb = (SFCommandBuffer *)field.far_ptr;
     872          57 :                 StartElement(sdump, (char *) field.name);
     873          57 :                 EndElementHeader(sdump, 1);
     874          57 :                 sdump->indent++;
     875          57 :                 if (!gf_list_count(cb->commandList)) {
     876             :                         /*the arch does not allow for that (we would need a codec and so on, or decompress the command list
     877             :                         in all cases...)*/
     878           0 :                         if (sdump->trace && cb->bufferSize) {
     879           0 :                                 if (sdump->XMLDump) gf_fprintf(sdump->trace, "<!--SFCommandBuffer cannot be dumped while playing - use MP4Box instead-->\n");
     880           0 :                                 else gf_fprintf(sdump->trace, "#SFCommandBuffer cannot be dumped while playing - use MP4Box instead\n");
     881             :                         }
     882             :                 } else {
     883          57 :                         gf_sm_dump_command_list(sdump, cb->commandList, sdump->indent, 0);
     884             :                 }
     885          57 :                 sdump->indent--;
     886          57 :                 EndElement(sdump, (char *) field.name, 1);
     887             :         }
     888             :         return;
     889             : 
     890           0 :         case GF_SG_VRML_MFATTRREF:
     891           0 :                 if (sdump->XMLDump) {
     892             :                         MFAttrRef *ar = (MFAttrRef *)field.far_ptr;
     893           0 :                         StartElement(sdump, (char *) field.name);
     894           0 :                         EndElementHeader(sdump, 1);
     895           0 :                         sdump->indent++;
     896             : 
     897           0 :                         for (i=0; i<ar->count; i++) {
     898           0 :                                 if (ar->vals[i].node) {
     899             :                                         GF_FieldInfo pinfo;
     900           0 :                                         DUMP_IND(sdump);
     901           0 :                                         gf_node_get_field(ar->vals[i].node, ar->vals[i].fieldIndex, &pinfo);
     902           0 :                                         gf_fprintf(sdump->trace, "<store node=\"");
     903           0 :                                         scene_dump_vrml_id(sdump, ar->vals[i].node);
     904           0 :                                         gf_fprintf(sdump->trace, "\" field=\"%s\"/>\n", pinfo.name);
     905             :                                 }
     906             :                         }
     907             : 
     908           0 :                         sdump->indent--;
     909           0 :                         EndElement(sdump, (char *) field.name, 1);
     910             :                         return;
     911             :                 }
     912             :                 break;
     913             :         }
     914             : 
     915             : 
     916        1568 :         if (gf_sg_vrml_is_sf_field(field.fieldType)) {
     917        1114 :                 StartAttribute(sdump, field.name);
     918        1114 :                 gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, node);
     919        1114 :                 EndAttribute(sdump);
     920             :         } else {
     921             :                 GenMFField *mffield = (GenMFField *) field.far_ptr;
     922         454 :                 sf_type = gf_sg_vrml_get_sf_type(field.fieldType);
     923             : 
     924         454 :                 if (sdump->XMLDump && sdump->X3DDump) {
     925             :                         switch (sf_type) {
     926           0 :                         case GF_SG_VRML_SFSTRING:
     927             :                         case GF_SG_VRML_SFSCRIPT:
     928             :                         case GF_SG_VRML_SFURL:
     929           0 :                                 gf_fprintf(sdump->trace, " %s=\'", (char *) field.name);
     930             :                                 break;
     931           0 :                         default:
     932           0 :                                 StartAttribute(sdump, field.name);
     933             :                                 break;
     934             :                         }
     935             :                 } else {
     936         454 :                         StartAttribute(sdump, field.name);
     937             :                 }
     938             : 
     939         454 :                 if (!sdump->XMLDump) gf_fprintf(sdump->trace, "[");
     940        3747 :                 for (i=0; i<mffield->count; i++) {
     941        3747 :                         if (i) gf_fprintf(sdump->trace, " ");
     942        3747 :                         gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
     943        3747 :                         gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, 1, node);
     944             :                 }
     945         454 :                 if (!sdump->XMLDump) gf_fprintf(sdump->trace, "]");
     946             : 
     947         454 :                 if (sdump->XMLDump && sdump->X3DDump) {
     948             :                         switch (sf_type) {
     949           0 :                         case GF_SG_VRML_SFSTRING:
     950             :                         case GF_SG_VRML_SFSCRIPT:
     951             :                         case GF_SG_VRML_SFURL:
     952           0 :                                 gf_fprintf(sdump->trace, "\'");
     953             :                                 break;
     954           0 :                         default:
     955           0 :                                 EndAttribute(sdump);
     956             :                                 break;
     957             :                         }
     958             :                 } else {
     959         454 :                         EndAttribute(sdump);
     960             :                 }
     961             :         }
     962             : }
     963             : 
     964         110 : static const char *GetXMTFieldTypeName(u32 fieldType)
     965             : {
     966         110 :         switch (fieldType) {
     967             :         case GF_SG_VRML_SFBOOL:
     968             :                 return "Boolean";
     969           0 :         case GF_SG_VRML_SFINT32:
     970           0 :                 return "Integer";
     971          20 :         case GF_SG_VRML_SFCOLOR:
     972          20 :                 return "Color";
     973          20 :         case GF_SG_VRML_SFVEC2F:
     974          20 :                 return "Vector2";
     975           0 :         case GF_SG_VRML_SFIMAGE:
     976           0 :                 return "Image";
     977           5 :         case GF_SG_VRML_SFTIME:
     978           5 :                 return "Time";
     979          30 :         case GF_SG_VRML_SFFLOAT:
     980          30 :                 return "Float";
     981           0 :         case GF_SG_VRML_SFVEC3F:
     982           0 :                 return "Vector3";
     983           0 :         case GF_SG_VRML_SFROTATION:
     984           0 :                 return "Rotation";
     985           0 :         case GF_SG_VRML_SFSTRING:
     986           0 :                 return "String";
     987          15 :         case GF_SG_VRML_SFNODE:
     988          15 :                 return "Node";
     989           0 :         case GF_SG_VRML_MFBOOL:
     990           0 :                 return "Booleans";
     991           0 :         case GF_SG_VRML_MFINT32:
     992           0 :                 return "Integers";
     993           0 :         case GF_SG_VRML_MFCOLOR:
     994           0 :                 return "Colors";
     995           0 :         case GF_SG_VRML_MFVEC2F:
     996           0 :                 return "Vector2Array";
     997           0 :         case GF_SG_VRML_MFIMAGE:
     998           0 :                 return "Images";
     999           0 :         case GF_SG_VRML_MFTIME:
    1000           0 :                 return "Times";
    1001           0 :         case GF_SG_VRML_MFFLOAT:
    1002           0 :                 return "Floats";
    1003           0 :         case GF_SG_VRML_MFVEC3F:
    1004           0 :                 return "Vector3Array";
    1005           0 :         case GF_SG_VRML_MFROTATION:
    1006           0 :                 return "Rotations";
    1007           0 :         case GF_SG_VRML_MFSTRING:
    1008           0 :                 return "Strings";
    1009           0 :         case GF_SG_VRML_MFNODE:
    1010           0 :                 return "Nodes";
    1011           0 :         default:
    1012           0 :                 return "unknown";
    1013             :         }
    1014             : }
    1015         195 : static const char *GetXMTFieldTypeValueName(u32 fieldType)
    1016             : {
    1017         195 :         switch (fieldType) {
    1018             :         case GF_SG_VRML_SFBOOL:
    1019             :                 return "booleanValue";
    1020           0 :         case GF_SG_VRML_SFINT32:
    1021           0 :                 return "intValue";
    1022          50 :         case GF_SG_VRML_SFCOLOR:
    1023          50 :                 return "colorValue";
    1024          45 :         case GF_SG_VRML_SFVEC2F:
    1025          45 :                 return "vector2Value";
    1026           0 :         case GF_SG_VRML_SFIMAGE:
    1027           0 :                 return "imageValue";
    1028           0 :         case GF_SG_VRML_SFTIME:
    1029           0 :                 return "timeValue";
    1030          75 :         case GF_SG_VRML_SFFLOAT:
    1031          75 :                 return "floatValue";
    1032           0 :         case GF_SG_VRML_SFVEC3F:
    1033           0 :                 return "vector3Value";
    1034           0 :         case GF_SG_VRML_SFROTATION:
    1035           0 :                 return "rotationValue";
    1036           0 :         case GF_SG_VRML_SFSTRING:
    1037           0 :                 return "stringValue";
    1038           0 :         case GF_SG_VRML_MFBOOL:
    1039           0 :                 return "booleanArrayValue";
    1040           0 :         case GF_SG_VRML_MFINT32:
    1041           0 :                 return "intArrayValue";
    1042           0 :         case GF_SG_VRML_MFCOLOR:
    1043           0 :                 return "colorArrayValue";
    1044           0 :         case GF_SG_VRML_MFVEC2F:
    1045           0 :                 return "vector2ArrayValue";
    1046           0 :         case GF_SG_VRML_MFIMAGE:
    1047           0 :                 return "imageArrayValue";
    1048           0 :         case GF_SG_VRML_MFTIME:
    1049           0 :                 return "timeArrayValue";
    1050           0 :         case GF_SG_VRML_MFFLOAT:
    1051           0 :                 return "floatArrayValue";
    1052           0 :         case GF_SG_VRML_MFVEC3F:
    1053           0 :                 return "vector3ArrayValue";
    1054           0 :         case GF_SG_VRML_MFROTATION:
    1055           0 :                 return "rotationArrayValue";
    1056           0 :         case GF_SG_VRML_MFSTRING:
    1057           0 :                 return "stringArrayValue";
    1058           0 :         default:
    1059           0 :                 return "unknown";
    1060             :         }
    1061             : }
    1062             : 
    1063             : /*field dumping for proto declaration and Script*/
    1064         198 : static void gf_dump_vrml_dyn_field(GF_SceneDumper *sdump, GF_Node *node, GF_FieldInfo field, Bool has_sublist)
    1065             : {
    1066             :         u32 i, sf_type;
    1067             :         void *slot_ptr;
    1068             : 
    1069         198 :         if (gf_sg_vrml_is_sf_field(field.fieldType)) {
    1070         198 :                 DUMP_IND(sdump);
    1071         198 :                 if (sdump->XMLDump) {
    1072         110 :                         if (sdump->X3DDump) {
    1073           0 :                                 gf_fprintf(sdump->trace, "<field name=\"%s\" type=\"%s\" accessType=\"%s\"",
    1074             :                                         field.name, gf_sg_vrml_get_field_type_name(field.fieldType), gf_sg_vrml_get_event_type_name(field.eventType, 1));
    1075             :                         } else {
    1076         110 :                                 gf_fprintf(sdump->trace, "<field name=\"%s\" type=\"%s\" vrml97Hint=\"%s\"",
    1077             :                                         field.name, GetXMTFieldTypeName(field.fieldType), gf_sg_vrml_get_event_type_name(field.eventType, 0));
    1078             :                         }
    1079             : 
    1080         110 :                         if ((field.eventType == GF_SG_EVENT_FIELD) || (field.eventType == GF_SG_EVENT_EXPOSED_FIELD)) {
    1081          95 :                                 if (field.fieldType == GF_SG_VRML_SFNODE) {
    1082          15 :                                         if (!sdump->X3DDump) {
    1083          15 :                                                 gf_fprintf(sdump->trace, ">\n");
    1084          15 :                                                 sdump->indent++;
    1085          15 :                                                 gf_fprintf(sdump->trace, "<node>");
    1086          15 :                                                 gf_dump_vrml_node(sdump, field.far_ptr ? *(GF_Node **)field.far_ptr : NULL, 0, NULL);
    1087          15 :                                                 gf_fprintf(sdump->trace, "</node>");
    1088          15 :                                                 sdump->indent--;
    1089          15 :                                                 if (!has_sublist)
    1090          15 :                                                         gf_fprintf(sdump->trace, "</field>\n");
    1091             :                                         } else {
    1092           0 :                                                 if (field.far_ptr) {
    1093           0 :                                                         gf_fprintf(sdump->trace, ">\n");
    1094           0 :                                                         gf_dump_vrml_node(sdump, *(GF_Node **)field.far_ptr, 0, NULL);
    1095           0 :                                                         gf_fprintf(sdump->trace, "</field>\n");
    1096             :                                                 } else {
    1097           0 :                                                         gf_fprintf(sdump->trace, "/>\n");
    1098             :                                                 }
    1099             :                                         }
    1100          15 :                                         DUMP_IND(sdump);
    1101             :                                 } else {
    1102          80 :                                         if (sdump->X3DDump) {
    1103           0 :                                                 gf_fprintf(sdump->trace, " value=\"");
    1104             :                                         } else {
    1105          80 :                                                 gf_fprintf(sdump->trace, " %s=\"", GetXMTFieldTypeValueName(field.fieldType));
    1106             :                                         }
    1107          80 :                                         gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, node);
    1108          80 :                                         if (has_sublist)
    1109           0 :                                                 gf_fprintf(sdump->trace, "\">\n");
    1110             :                                         else
    1111          80 :                                                 gf_fprintf(sdump->trace, "\"/>\n");
    1112             :                                 }
    1113             :                         } else {
    1114          15 :                                 gf_fprintf(sdump->trace, "/>\n");
    1115             :                         }
    1116             :                 } else {
    1117          88 :                         gf_fprintf(sdump->trace, "%s %s %s", gf_sg_vrml_get_event_type_name(field.eventType, sdump->X3DDump), gf_sg_vrml_get_field_type_name(field.fieldType), field.name);
    1118          88 :                         if ((field.eventType==GF_SG_EVENT_FIELD) || (field.eventType==GF_SG_EVENT_EXPOSED_FIELD)) {
    1119          76 :                                 gf_fprintf(sdump->trace, " ");
    1120          76 :                                 if (field.fieldType == GF_SG_VRML_SFNODE) {
    1121          12 :                                         gf_dump_vrml_node(sdump, field.far_ptr ? *(GF_Node **)field.far_ptr : NULL, 0, NULL);
    1122             :                                 } else {
    1123          64 :                                         gf_dump_vrml_simple_field(sdump, field, node);
    1124             :                                 }
    1125             :                         }
    1126          88 :                         gf_fprintf(sdump->trace, "\n");
    1127             :                 }
    1128             :         } else {
    1129             :                 GenMFField *mffield = (GenMFField *) field.far_ptr;
    1130           0 :                 sf_type = gf_sg_vrml_get_sf_type(field.fieldType);
    1131             : 
    1132           0 :                 DUMP_IND(sdump);
    1133           0 :                 if (!sdump->XMLDump) {
    1134           0 :                         gf_fprintf(sdump->trace, "%s %s %s", gf_sg_vrml_get_event_type_name(field.eventType, sdump->X3DDump), gf_sg_vrml_get_field_type_name(field.fieldType), field.name);
    1135           0 :                         if ((field.eventType==GF_SG_EVENT_FIELD) || (field.eventType==GF_SG_EVENT_EXPOSED_FIELD)) {
    1136           0 :                                 gf_fprintf(sdump->trace, " [");
    1137             : 
    1138           0 :                                 if (sf_type == GF_SG_VRML_SFNODE) {
    1139           0 :                                         GF_ChildNodeItem *l = *(GF_ChildNodeItem **)field.far_ptr;
    1140           0 :                                         gf_fprintf(sdump->trace, "\n");
    1141           0 :                                         sdump->indent++;
    1142           0 :                                         while (l) {
    1143           0 :                                                 gf_dump_vrml_node(sdump, l->node, 1, NULL);
    1144           0 :                                                 l = l->next;
    1145             :                                         }
    1146           0 :                                         sdump->indent--;
    1147           0 :                                         DUMP_IND(sdump);
    1148             :                                 } else {
    1149           0 :                                         for (i=0; i<mffield->count; i++) {
    1150           0 :                                                 if (i) gf_fprintf(sdump->trace, " ");
    1151           0 :                                                 if (field.fieldType != GF_SG_VRML_MFNODE) {
    1152           0 :                                                         gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
    1153           0 :                                                         gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0, node);
    1154             :                                                 }
    1155             :                                         }
    1156             :                                 }
    1157           0 :                                 gf_fprintf(sdump->trace, "]");
    1158             :                         }
    1159           0 :                         gf_fprintf(sdump->trace, "\n");
    1160             :                 } else {
    1161           0 :                         if (sdump->X3DDump) {
    1162           0 :                                 gf_fprintf(sdump->trace, "<field name=\"%s\" type=\"%s\" accessType=\"%s\"",
    1163             :                                         field.name, gf_sg_vrml_get_field_type_name(field.fieldType), gf_sg_vrml_get_event_type_name(field.eventType, 1));
    1164             :                         } else {
    1165           0 :                                 gf_fprintf(sdump->trace, "<field name=\"%s\" type=\"%s\" vrml97Hint=\"%s\"",
    1166             :                                         field.name, GetXMTFieldTypeName(field.fieldType), gf_sg_vrml_get_event_type_name(field.eventType, 0));
    1167             :                         }
    1168             : 
    1169           0 :                         if ((field.eventType==GF_SG_EVENT_FIELD) || (field.eventType==GF_SG_EVENT_EXPOSED_FIELD)) {
    1170           0 :                                 if (sf_type == GF_SG_VRML_SFNODE) {
    1171           0 :                                         GF_ChildNodeItem *list = *(GF_ChildNodeItem **)field.far_ptr;
    1172           0 :                                         gf_fprintf(sdump->trace, ">\n");
    1173           0 :                                         sdump->indent++;
    1174           0 :                                         if (!sdump->X3DDump) gf_fprintf(sdump->trace, "<nodes>");
    1175           0 :                                         while (list) {
    1176           0 :                                                 gf_dump_vrml_node(sdump, list->node, 1, NULL);
    1177           0 :                                                 list = list->next;
    1178             :                                         }
    1179           0 :                                         if (!sdump->X3DDump) gf_fprintf(sdump->trace, "</nodes>");
    1180           0 :                                         sdump->indent++;
    1181           0 :                                         DUMP_IND(sdump);
    1182           0 :                                         if (!has_sublist)
    1183           0 :                                                 gf_fprintf(sdump->trace, "</field>\n");
    1184             :                                 } else {
    1185           0 :                                         if (sdump->X3DDump) {
    1186           0 :                                                 gf_fprintf(sdump->trace, " value=\"");
    1187             :                                         } else {
    1188           0 :                                                 gf_fprintf(sdump->trace, " %s=\"", GetXMTFieldTypeValueName(field.fieldType));
    1189             :                                         }
    1190           0 :                                         for (i=0; i<mffield->count; i++) {
    1191           0 :                                                 if (i) gf_fprintf(sdump->trace, " ");
    1192           0 :                                                 if (field.fieldType != GF_SG_VRML_MFNODE) {
    1193           0 :                                                         gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
    1194           0 :                                                         gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0, node);
    1195             :                                                 }
    1196             :                                         }
    1197           0 :                                         if (has_sublist)
    1198           0 :                                                 gf_fprintf(sdump->trace, "\">\n");
    1199             :                                         else
    1200           0 :                                                 gf_fprintf(sdump->trace, "\"/>\n");
    1201             :                                 }
    1202             :                         } else {
    1203           0 :                                 gf_fprintf(sdump->trace, "/>\n");
    1204             :                         }
    1205             :                 }
    1206             :         }
    1207         198 : }
    1208             : 
    1209             : 
    1210             : /*field dumping for proto instance*/
    1211         130 : static void gf_dump_vrml_proto_field(GF_SceneDumper *sdump, GF_Node *node, GF_FieldInfo field)
    1212             : {
    1213             :         u32 i, sf_type;
    1214             :         void *slot_ptr;
    1215             : 
    1216         130 :         DUMP_IND(sdump);
    1217         130 :         gf_fprintf(sdump->trace, "<fieldValue name=\"%s\" ", field.name);
    1218         130 :         if (gf_sg_vrml_is_sf_field(field.fieldType)) {
    1219         130 :                 if (field.fieldType == GF_SG_VRML_SFNODE) {
    1220          15 :                         gf_fprintf(sdump->trace, ">\n");
    1221          15 :                         sdump->indent++;
    1222          15 :                         if (!sdump->X3DDump) gf_fprintf(sdump->trace, "<node>");
    1223          15 :                         gf_dump_vrml_node(sdump, field.far_ptr ? *(GF_Node **)field.far_ptr : NULL, 0, NULL);
    1224          15 :                         if (!sdump->X3DDump) gf_fprintf(sdump->trace, "</node>");
    1225          15 :                         sdump->indent--;
    1226          15 :                         DUMP_IND(sdump);
    1227          15 :                         gf_fprintf(sdump->trace, "</fieldValue>\n");
    1228             :                 } else {
    1229         115 :                         if (sdump->X3DDump) {
    1230           0 :                                 gf_fprintf(sdump->trace, " value=\"");
    1231             :                         } else {
    1232         115 :                                 gf_fprintf(sdump->trace, " %s=\"", GetXMTFieldTypeValueName(field.fieldType));
    1233             :                         }
    1234         115 :                         gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, node);
    1235         115 :                         gf_fprintf(sdump->trace, "\"/>\n");
    1236             :                 }
    1237             :         } else {
    1238             :                 GenMFField *mffield = (GenMFField *) field.far_ptr;
    1239           0 :                 sf_type = gf_sg_vrml_get_sf_type(field.fieldType);
    1240             : 
    1241           0 :                 if ((field.eventType==GF_SG_EVENT_FIELD) || (field.eventType==GF_SG_EVENT_EXPOSED_FIELD)) {
    1242           0 :                         if (sf_type == GF_SG_VRML_SFNODE) {
    1243           0 :                                 GF_ChildNodeItem *list = *(GF_ChildNodeItem **)field.far_ptr;
    1244           0 :                                 gf_fprintf(sdump->trace, ">\n");
    1245           0 :                                 sdump->indent++;
    1246           0 :                                 if (!sdump->X3DDump) gf_fprintf(sdump->trace, "<nodes>");
    1247           0 :                                 while (list) {
    1248           0 :                                         gf_dump_vrml_node(sdump, list->node, 1, NULL);
    1249           0 :                                         list = list->next;
    1250             :                                 }
    1251           0 :                                 if (!sdump->X3DDump) gf_fprintf(sdump->trace, "</nodes>");
    1252           0 :                                 sdump->indent--;
    1253           0 :                                 DUMP_IND(sdump);
    1254           0 :                                 gf_fprintf(sdump->trace, "</fieldValue>\n");
    1255             :                         } else {
    1256           0 :                                 if (sdump->X3DDump) {
    1257           0 :                                         gf_fprintf(sdump->trace, " value=\"");
    1258             :                                 } else {
    1259           0 :                                         gf_fprintf(sdump->trace, " %s=\"", GetXMTFieldTypeValueName(field.fieldType));
    1260             :                                 }
    1261           0 :                                 for (i=0; i<mffield->count; i++) {
    1262           0 :                                         if (i) gf_fprintf(sdump->trace, " ");
    1263           0 :                                         if (field.fieldType != GF_SG_VRML_MFNODE) {
    1264           0 :                                                 gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
    1265           0 :                                                 gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0, node);
    1266             :                                         }
    1267             :                                 }
    1268           0 :                                 gf_fprintf(sdump->trace, "\"/>\n");
    1269             :                         }
    1270             :                 }
    1271             :         }
    1272         130 : }
    1273             : 
    1274         513 : static GF_Route *gf_dump_vrml_get_IS(GF_SceneDumper *sdump, GF_Node *node, GF_FieldInfo *field)
    1275             : {
    1276             :         u32 i;
    1277             :         GF_Route *r;
    1278         513 :         i=0;
    1279        5499 :         while ((r = (GF_Route*)gf_list_enum(sdump->current_proto->sub_graph->Routes, &i))) {
    1280        5184 :                 if (!r->IS_route) continue;
    1281        5184 :                 if ((r->ToNode==node) && (r->ToField.fieldIndex==field->fieldIndex)) return r;
    1282             :         }
    1283         315 :         if (!node || !node->sgprivate->interact || !node->sgprivate->interact->routes) return NULL;
    1284         144 :         i=0;
    1285         369 :         while ((r = (GF_Route*)gf_list_enum(node->sgprivate->interact->routes, &i))) {
    1286         225 :                 if (!r->IS_route) continue;
    1287         225 :                 if (r->FromField.fieldIndex == field->fieldIndex) return r;
    1288             :         }
    1289             :         return NULL;
    1290             : }
    1291             : 
    1292          99 : static void gf_dump_vrml_IS_field(GF_SceneDumper *sdump, GF_Node *node, GF_FieldInfo field, Bool isScript, Bool skip_is)
    1293             : {
    1294             :         GF_FieldInfo pfield;
    1295             : 
    1296          99 :         GF_Route *r = gf_dump_vrml_get_IS(sdump, node, &field);
    1297          99 :         if (r->FromNode) {
    1298           0 :                 pfield.fieldIndex = r->ToField.fieldIndex;
    1299           0 :                 gf_sg_proto_get_field(sdump->current_proto, NULL, &pfield);
    1300             :         } else {
    1301          99 :                 pfield.fieldIndex = r->FromField.fieldIndex;
    1302          99 :                 gf_sg_proto_get_field(sdump->current_proto, NULL, &pfield);
    1303             :         }
    1304             : 
    1305          99 :         if (!sdump->XMLDump) {
    1306          44 :                 DUMP_IND(sdump);
    1307          44 :                 if (isScript) gf_fprintf(sdump->trace, "%s %s ", gf_sg_vrml_get_event_type_name(field.eventType, sdump->X3DDump), gf_sg_vrml_get_field_type_name(field.fieldType));
    1308          44 :                 gf_fprintf(sdump->trace, "%s IS %s\n", field.name, pfield.name);
    1309             :         } else {
    1310          55 :                 if (!skip_is) {
    1311           5 :                         StartElement(sdump, "IS");
    1312           5 :                         EndElementHeader(sdump, 1);
    1313           5 :                         sdump->indent++;
    1314             :                 }
    1315          55 :                 DUMP_IND(sdump);
    1316          55 :                 gf_fprintf(sdump->trace, "<connect nodeField=\"%s\" protoField=\"%s\"/>\n", field.name, pfield.name);
    1317          55 :                 if (!skip_is) {
    1318           5 :                         sdump->indent--;
    1319           5 :                         EndElement(sdump, "IS", 1);
    1320             :                 }
    1321             :         }
    1322          99 : }
    1323             : 
    1324        1928 : static Bool scene_dump_vrml_can_dump(GF_SceneDumper *sdump, GF_Node *node)
    1325             : {
    1326             : #ifndef GPAC_DISABLE_VRML
    1327             :         u32 tag;
    1328             : 
    1329        1928 :         if (node->sgprivate->tag==TAG_ProtoNode) return 1;
    1330             : 
    1331        1892 :         if (sdump->X3DDump || (sdump->dump_mode==GF_SM_DUMP_VRML)) {
    1332           0 :                 if (node->sgprivate->tag>=GF_NODE_RANGE_FIRST_X3D) return 1;
    1333           0 :                 if (node->sgprivate->tag==TAG_MPEG4_Rectangle) return 1;
    1334           0 :                 if (node->sgprivate->tag==TAG_MPEG4_Circle) return 1;
    1335             : #ifndef GPAC_DISABLE_X3D
    1336           0 :                 tag = gf_node_x3d_type_by_class_name(gf_node_get_class_name(node));
    1337           0 :                 return tag ? 1 : 0;
    1338             : #else
    1339             :                 return 0;
    1340             : #endif
    1341             :         } else {
    1342        1892 :                 if (node->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) return 1;
    1343             : #ifndef GPAC_DISABLE_X3D
    1344           0 :                 if (node->sgprivate->tag==TAG_X3D_Rectangle2D) return 1;
    1345           0 :                 if (node->sgprivate->tag==TAG_X3D_Circle2D) return 1;
    1346             : #endif
    1347           0 :                 tag = gf_node_mpeg4_type_by_class_name(gf_node_get_class_name(node));
    1348           0 :                 return tag ? 1 : 0;
    1349             :         }
    1350             : #else
    1351             :         return 1;
    1352             : #endif
    1353             : }
    1354             : 
    1355        1998 : static void gf_dump_vrml_node(GF_SceneDumper *sdump, GF_Node *node, Bool in_list, char *fieldContainer)
    1356             : {
    1357             :         u32 i, count, to_dump, sub_el, ID;
    1358             :         u32 *def_fields;
    1359             :         Bool isDEF, isScript, isProto, hasISed;
    1360             :         char *name;
    1361             :         GF_Node *base;
    1362             :         GF_FieldInfo field, base_field;
    1363             : 
    1364        1998 :         if (!node) {
    1365          70 :                 gf_fprintf(sdump->trace, "NULL");
    1366          70 :                 return;
    1367             :         }
    1368             : 
    1369             :         /*this dumper works only for VRML like graphs*/
    1370        1928 :         if (node->sgprivate->tag>GF_NODE_RANGE_LAST_X3D) return;
    1371             : 
    1372        1928 :         if (!scene_dump_vrml_can_dump(sdump, node)) {
    1373           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[Scene Dump] node %s not part of %s standard - removing\n", gf_node_get_class_name(node), sdump->X3DDump ? "X3D" : (sdump->dump_mode==GF_SM_DUMP_VRML) ? "VRML" : "MPEG4"));
    1374           0 :                 if (!in_list) gf_fprintf(sdump->trace, "NULL");
    1375             :                 return;
    1376             :         }
    1377             : 
    1378             :         /*convert whatever possible*/
    1379        1928 :         name = (char*)gf_node_get_class_name(node);
    1380             : #ifndef GPAC_DISABLE_VRML
    1381        1928 :         if (sdump->X3DDump) {
    1382           0 :                 if (node->sgprivate->tag == TAG_MPEG4_Circle) name = "Circle2D";
    1383           0 :                 else if (node->sgprivate->tag == TAG_MPEG4_Rectangle) name = "Rectangle2D";
    1384             : #ifndef GPAC_DISABLE_X3D
    1385             :         } else {
    1386        1928 :                 if (node->sgprivate->tag == TAG_X3D_Circle2D) name = "Circle";
    1387        1928 :                 else if (node->sgprivate->tag == TAG_X3D_Rectangle2D) name = "Rectangle";
    1388             : #endif
    1389             :         }
    1390             : #endif
    1391             : 
    1392             : 
    1393             : 
    1394        1928 :         isProto = (gf_node_get_tag(node) == TAG_ProtoNode) ? 1 : 0;
    1395        1928 :         ID = gf_node_get_id(node);
    1396             :         isDEF = 0;
    1397        1928 :         if (ID) {
    1398         535 :                 isDEF = gf_dump_vrml_is_def_node(sdump, node);
    1399         535 :                 if (!isDEF) {
    1400          63 :                         if (!sdump->XMLDump) {
    1401          33 :                                 if (in_list) DUMP_IND(sdump);
    1402          33 :                                 gf_fprintf(sdump->trace, "USE ");
    1403          33 :                                 scene_dump_vrml_id(sdump, node);
    1404          33 :                                 if (in_list) gf_fprintf(sdump->trace, "\n");
    1405             :                         } else {
    1406          30 :                                 if (isProto) {
    1407           0 :                                         StartElement(sdump, "ProtoInstance");
    1408           0 :                                         StartAttribute(sdump, "name");
    1409           0 :                                         gf_fprintf(sdump->trace, "%s", name);
    1410           0 :                                         EndAttribute(sdump);
    1411             :                                 } else {
    1412          30 :                                         StartElement(sdump, name);
    1413             :                                 }
    1414          30 :                                 StartAttribute(sdump, "USE");
    1415          30 :                                 scene_dump_vrml_id(sdump, node);
    1416          30 :                                 EndAttribute(sdump);
    1417          30 :                                 EndElementHeader(sdump, 0);
    1418             :                         }
    1419             :                         return;
    1420             :                 }
    1421             :         }
    1422             : 
    1423             :         /*get all fields*/
    1424        1865 :         count = gf_node_get_field_count(node);
    1425        1865 :         def_fields = (u32*)gf_malloc(sizeof(u32) * count);
    1426             : 
    1427             :         base = NULL;
    1428        1865 :         switch (gf_node_get_tag(node)) {
    1429             : #ifndef GPAC_DISABLE_VRML
    1430             : #ifndef GPAC_DISABLE_X3D
    1431             :         case TAG_X3D_Script:
    1432             : #endif
    1433             :         case TAG_MPEG4_Script:
    1434             :                 isScript = 1;
    1435             :                 break;
    1436             : #endif
    1437             :         default:
    1438             :                 isScript = 0;
    1439             :                 break;
    1440             :         }
    1441             : 
    1442             : 
    1443             :         if (!isScript) {
    1444        1856 :                 if (isProto) {
    1445          36 :                         base = gf_sg_proto_create_instance(node->sgprivate->scenegraph, ((GF_ProtoInstance *)node)->proto_interface);
    1446             :                 } else {
    1447        1820 :                         base = gf_node_new(node->sgprivate->scenegraph, node->sgprivate->tag);
    1448             :                 }
    1449             :         }
    1450             : 
    1451        1865 :         if (base) gf_node_register(base, NULL);
    1452             : 
    1453             :         hasISed = 0;
    1454             :         to_dump = sub_el = 0;
    1455       13195 :         for (i=0; i<count; i++) {
    1456       13195 :                 if (isScript) {
    1457             :                         /*dyn script fields are complex types*/
    1458          45 :                         def_fields[i] = (i>2) ? 2 : 1;
    1459             :                 } else {
    1460       13150 :                         def_fields[i] = 0;
    1461             :                 }
    1462             : 
    1463       13195 :                 gf_node_get_field(node, i, &field);
    1464             : 
    1465       13195 :                 if (sdump->current_proto) {
    1466         414 :                         if (gf_dump_vrml_get_IS(sdump, node, &field) != NULL) {
    1467          99 :                                 def_fields[i] = 3;
    1468          99 :                                 if ((field.fieldType == GF_SG_VRML_SFNODE) || (field.fieldType == GF_SG_VRML_MFNODE))
    1469           9 :                                         def_fields[i] = sdump->XMLDump ? 4 : 3;
    1470             :                                 /*in XMT the ISed is not an attribute*/
    1471          99 :                                 if (sdump->XMLDump) sub_el++;
    1472          99 :                                 to_dump++;
    1473             :                                 hasISed = 1;
    1474          99 :                                 continue;
    1475             :                         }
    1476             :                 }
    1477             : 
    1478       13096 :                 if (!isScript && ((field.eventType == GF_SG_EVENT_IN) || (field.eventType == GF_SG_EVENT_OUT)) ) {
    1479        4064 :                         continue;
    1480             :                 }
    1481             :                 /*proto instance in XMT lists all fields as elements*/
    1482        9032 :                 if (sdump->XMLDump && isProto) {
    1483         130 :                         def_fields[i] = 2;
    1484         130 :                         to_dump++;
    1485         130 :                         sub_el++;
    1486         130 :                         continue;
    1487             :                 }
    1488        8902 :                 switch (field.fieldType) {
    1489        1675 :                 case GF_SG_VRML_SFNODE:
    1490        1675 :                         if (* (GF_Node **) field.far_ptr) {
    1491         854 :                                 def_fields[i] = 2;
    1492         854 :                                 to_dump++;
    1493         854 :                                 sub_el++;
    1494             :                         }
    1495             :                         break;
    1496         318 :                 case GF_SG_VRML_MFNODE:
    1497         318 :                         if (* (GF_ChildNodeItem**) field.far_ptr) {
    1498         186 :                                 def_fields[i] = 2;
    1499         186 :                                 to_dump++;
    1500         186 :                                 sub_el++;
    1501             :                         }
    1502             :                         break;
    1503          72 :                 case GF_SG_VRML_SFCOMMANDBUFFER:
    1504             :                 {
    1505          72 :                         SFCommandBuffer *p = (SFCommandBuffer *)field.far_ptr;
    1506          72 :                         if (p->bufferSize || gf_list_count(p->commandList)) {
    1507          57 :                                 def_fields[i] = 2;
    1508          57 :                                 to_dump++;
    1509          57 :                                 sub_el++;
    1510             :                         }
    1511             :                 }
    1512             :                 break;
    1513           0 :                 case GF_SG_VRML_MFATTRREF:
    1514             :                 {
    1515           0 :                         MFAttrRef *p = (MFAttrRef*)field.far_ptr;
    1516           0 :                         if (p->count) {
    1517           0 :                                 def_fields[i] = 2;
    1518           0 :                                 to_dump++;
    1519           0 :                                 sub_el++;
    1520             :                         }
    1521             :                 }
    1522             :                 break;
    1523        6837 :                 default:
    1524        6837 :                         if (isScript) {
    1525          36 :                                 to_dump++;
    1526             :                         } else {
    1527        6801 :                                 gf_node_get_field(base, i, &base_field);
    1528        6801 :                                 if (!gf_sg_vrml_field_equal(base_field.far_ptr, field.far_ptr, field.fieldType)) {
    1529        1551 :                                         def_fields[i] = 1;
    1530        1551 :                                         to_dump++;
    1531             :                                 }
    1532             :                         }
    1533             :                         break;
    1534             :                 }
    1535             :         }
    1536        1865 :         if (base) gf_node_unregister(base, NULL);
    1537             : 
    1538        1865 :         if (!to_dump) {
    1539         252 :                 if (in_list) DUMP_IND(sdump);
    1540         252 :                 if (!sdump->XMLDump) {
    1541         111 :                         if (isDEF) {
    1542          48 :                                 gf_fprintf(sdump->trace, "DEF ");
    1543          48 :                                 scene_dump_vrml_id(sdump, node);
    1544          48 :                                 gf_fprintf(sdump->trace, " ");
    1545             :                         }
    1546         111 :                         gf_fprintf(sdump->trace, "%s {}\n", name);
    1547             :                 } else {
    1548         141 :                         if (isDEF) {
    1549          60 :                                 if (isProto) {
    1550           0 :                                         gf_fprintf(sdump->trace, "<ProtoInstance name=\"%s\" DEF=\"", name);
    1551             :                                 } else {
    1552          60 :                                         gf_fprintf(sdump->trace, "<%s DEF=\"", name);
    1553             :                                 }
    1554          60 :                                 scene_dump_vrml_id(sdump, node);
    1555          60 :                                 gf_fprintf(sdump->trace, "\"/>\n");
    1556             :                         } else {
    1557          81 :                                 if (isProto) {
    1558           0 :                                         gf_fprintf(sdump->trace, "<ProtoInstance name=\"%s\"/>\n", name);
    1559             :                                 } else {
    1560          81 :                                         gf_fprintf(sdump->trace, "<%s/>\n", name);
    1561             :                                 }
    1562             :                         }
    1563             :                 }
    1564         252 :                 gf_free(def_fields);
    1565         252 :                 return;
    1566             :         }
    1567             : 
    1568        1613 :         if (!sdump->XMLDump) {
    1569         756 :                 if (in_list) DUMP_IND(sdump);
    1570         756 :                 if (isDEF) {
    1571         168 :                         gf_fprintf(sdump->trace, "DEF ");
    1572         168 :                         scene_dump_vrml_id(sdump, node);
    1573         168 :                         gf_fprintf(sdump->trace, " ");
    1574             :                 }
    1575         756 :                 gf_fprintf(sdump->trace, "%s {\n", name);
    1576             :         } else {
    1577         857 :                 if (isProto) {
    1578          20 :                         StartElement(sdump, "ProtoInstance");
    1579          20 :                         StartAttribute(sdump, "name");
    1580          20 :                         gf_fprintf(sdump->trace, "%s", name);
    1581          20 :                         EndAttribute(sdump);
    1582             :                 } else {
    1583         837 :                         StartElement(sdump, name);
    1584             :                 }
    1585         857 :                 if (isDEF) {
    1586         196 :                         StartAttribute(sdump, "DEF");
    1587         196 :                         scene_dump_vrml_id(sdump, node);
    1588         196 :                         EndAttribute(sdump);
    1589             :                 }
    1590             :         }
    1591             : 
    1592        1613 :         sdump->indent ++;
    1593       10879 :         for (i=0; i<count; i++) {
    1594        9266 :                 switch (def_fields[i]) {
    1595             :                 /*regular field*/
    1596        1578 :                 case 1:
    1597        1578 :                         gf_node_get_field(node, i, &field);
    1598        1578 :                         if (!isScript) {
    1599        1551 :                                 gf_dump_vrml_field(sdump, node, field);
    1600             :                         }
    1601             :                         /*special script dump case, static fields except url*/
    1602          27 :                         else if (i==1 || i==2) {
    1603          18 :                                 if (*((SFBool *)field.far_ptr)) gf_dump_vrml_field(sdump, node, field);
    1604             :                         }
    1605             :                         /*in bt first dump fields - in XMT first dump url*/
    1606           9 :                         else if (i && !sdump->XMLDump) {
    1607           0 :                                 gf_dump_vrml_dyn_field(sdump, node, field, 0);
    1608           9 :                         } else if (!i && sdump->XMLDump) {
    1609           5 :                                 gf_dump_vrml_field(sdump, node, field);
    1610             :                         }
    1611             :                         break;
    1612             :                 /*IS field*/
    1613          94 :                 case 3:
    1614          94 :                         if (sdump->XMLDump) break;
    1615          44 :                         gf_node_get_field(node, i, &field);
    1616          44 :                         gf_dump_vrml_IS_field(sdump, node, field, isScript, 0);
    1617          44 :                         def_fields[i] = 0;
    1618          44 :                         break;
    1619             :                 default:
    1620             :                         break;
    1621             :                 }
    1622          50 :         }
    1623        1613 :         if (fieldContainer) gf_fprintf(sdump->trace, " fieldContainer=\"%s\"", fieldContainer);
    1624             : 
    1625        1613 :         if (isScript) sub_el = 1;
    1626        1613 :         EndElementHeader(sdump, sub_el ? 1 : 0);
    1627             : 
    1628        1613 :         if (sub_el) {
    1629             :                 /*dump all normal IS elements for XMT*/
    1630         917 :                 if (hasISed && sdump->XMLDump) {
    1631          35 :                         StartElement(sdump, "IS");
    1632          35 :                         EndElementHeader(sdump, 1);
    1633          35 :                         sdump->indent++;
    1634             :                 }
    1635        4568 :                 for (i=0; i<count; i++) {
    1636        4568 :                         if (def_fields[i]==3) {
    1637          50 :                                 gf_node_get_field(node, i, &field);
    1638          50 :                                 gf_dump_vrml_IS_field(sdump, node, field, isScript, 1);
    1639             :                         }
    1640             :                 }
    1641         917 :                 if (hasISed && sdump->XMLDump) {
    1642          35 :                         sdump->indent--;
    1643          35 :                         EndElement(sdump, "IS", 1);
    1644             :                 }
    1645             :                 /*dump all sub elements and complex IS*/
    1646        4568 :                 for (i=0; i<count; i++) {
    1647        4568 :                         switch (def_fields[i]) {
    1648        1236 :                         case 2:
    1649        1236 :                                 gf_node_get_field(node, i, &field);
    1650        1236 :                                 if (!isScript) {
    1651        1218 :                                         if (isProto && sdump->XMLDump) {
    1652         130 :                                                 gf_dump_vrml_proto_field(sdump, node, field);
    1653             :                                         } else {
    1654        1088 :                                                 gf_dump_vrml_field(sdump, node, field);
    1655             :                                         }
    1656             :                                 } else {
    1657             : #ifndef GPAC_DISABLE_X3D
    1658             :                                         /*X3D script metadata, NOT DYN*/
    1659          18 :                                         if ((i==3) && (node->sgprivate->tag==TAG_X3D_Script) ) {
    1660           0 :                                                 if (*((GF_Node **)field.far_ptr)) gf_dump_vrml_field(sdump, node, field);
    1661             :                                         } else
    1662             : #endif
    1663             :                                         {
    1664          18 :                                                 gf_dump_vrml_dyn_field(sdump, node, field, 0);
    1665             :                                         }
    1666             :                                 }
    1667             :                                 break;
    1668           5 :                         case 4:
    1669           5 :                                 gf_node_get_field(node, i, &field);
    1670           5 :                                 gf_dump_vrml_IS_field(sdump, node, field, isScript, 0);
    1671           5 :                                 break;
    1672             :                         }
    1673             :                 }
    1674             :         }
    1675             : 
    1676             :         /*finally dump script - XMT dumping is broken!!*/
    1677        1613 :         if (isScript && !sdump->XMLDump) {
    1678           4 :                 gf_node_get_field(node, 0, &field);
    1679           4 :                 gf_dump_vrml_field(sdump, node, field);
    1680             :         }
    1681             : 
    1682        1613 :         sdump->indent --;
    1683        1613 :         if (!sdump->XMLDump && !in_list) {
    1684         426 :                 DUMP_IND(sdump);
    1685         426 :                 gf_fprintf(sdump->trace, "}");
    1686             :         } else {
    1687        1187 :                 EndElement(sdump, isProto ? "ProtoInstance" : name, sub_el);
    1688             :         }
    1689        1613 :         gf_free(def_fields);
    1690             : }
    1691             : 
    1692             : 
    1693           9 : static GF_Err DumpMultipleIndexedReplace(GF_SceneDumper *sdump, GF_Command *com)
    1694             : {
    1695             :         u32 i;
    1696             :         GF_FieldInfo field;
    1697             :         GF_CommandField *inf;
    1698           9 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    1699           9 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    1700           9 :         gf_node_get_field(com->node, inf->fieldIndex, &field);
    1701           9 :         field.fieldType = inf->fieldType;
    1702             : 
    1703           9 :         DUMP_IND(sdump);
    1704           9 :         if (sdump->XMLDump) {
    1705           5 :                 gf_fprintf(sdump->trace, "<Replace extended=\"indices\" atNode=\"");
    1706           5 :                 scene_dump_vrml_id(sdump, com->node);
    1707           5 :                 gf_fprintf(sdump->trace, "\" atField=\"%s\">\n", field.name);
    1708             :         } else {
    1709           4 :                 gf_fprintf(sdump->trace, "MULTIPLEINDREPLACE ");
    1710           4 :                 scene_dump_vrml_id(sdump, com->node);
    1711           4 :                 gf_fprintf(sdump->trace, ".%s [\n", field.name);
    1712             :         }
    1713           9 :         sdump->indent++;
    1714           9 :         i=0;
    1715          36 :         while ((inf = (GF_CommandField *) gf_list_enum(com->command_fields, &i))) {
    1716          27 :                 field.far_ptr = inf->field_ptr;
    1717             : 
    1718          27 :                 DUMP_IND(sdump);
    1719          27 :                 if (sdump->XMLDump) {
    1720          15 :                         gf_fprintf(sdump->trace, "<repValue position=\"%d\" ", inf->pos);
    1721             :                 } else {
    1722          12 :                         gf_fprintf(sdump->trace, "%d BY ", inf->pos);
    1723             :                 }
    1724          27 :                 gf_dump_vrml_simple_field(sdump, field, com->node);
    1725          27 :                 if (sdump->XMLDump) {
    1726          15 :                         gf_fprintf(sdump->trace, "/>");
    1727             :                 } else {
    1728          12 :                         gf_fprintf(sdump->trace, "\n");
    1729             :                 }
    1730             :         }
    1731           9 :         sdump->indent--;
    1732           9 :         DUMP_IND(sdump);
    1733           9 :         if (sdump->XMLDump) {
    1734           5 :                 gf_fprintf(sdump->trace, "</Replace>\n");
    1735             :         } else {
    1736           4 :                 gf_fprintf(sdump->trace, "]\n");
    1737             :         }
    1738             :         return GF_OK;
    1739             : }
    1740             : 
    1741          12 : static GF_Err DumpMultipleReplace(GF_SceneDumper *sdump, GF_Command *com)
    1742             : {
    1743             :         u32 i;
    1744             :         GF_FieldInfo info;
    1745             :         GF_CommandField *inf;
    1746          12 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    1747             : 
    1748          12 :         DUMP_IND(sdump);
    1749          12 :         if (sdump->XMLDump) {
    1750           7 :                 gf_fprintf(sdump->trace, "<Replace extended=\"fields\" atNode=\"");
    1751           7 :                 scene_dump_vrml_id(sdump, com->node);
    1752           7 :                 gf_fprintf(sdump->trace, "\">\n");
    1753             : 
    1754           7 :                 sdump->indent++;
    1755           7 :                 i=0;
    1756          24 :                 while ((inf = (GF_CommandField *) gf_list_enum(com->command_fields, &i))) {
    1757          17 :                         gf_node_get_field(com->node, inf->fieldIndex, &info);
    1758          17 :                         info.far_ptr = inf->field_ptr;
    1759             : 
    1760          17 :                         DUMP_IND(sdump);
    1761          17 :                         if (gf_sg_vrml_get_sf_type(info.fieldType) != GF_SG_VRML_SFNODE) {
    1762          10 :                                 gf_fprintf(sdump->trace, "<repField atField=\"%s\" ", info.name);
    1763          10 :                                 gf_dump_vrml_simple_field(sdump, info, com->node);
    1764          10 :                                 gf_fprintf(sdump->trace, "/>\n");
    1765             :                         } else {
    1766           7 :                                 gf_fprintf(sdump->trace, "<repField>");
    1767           7 :                                 gf_dump_vrml_field(sdump, com->node, info);
    1768           7 :                                 gf_fprintf(sdump->trace, "</repField>\n");
    1769             :                         }
    1770             :                 }
    1771           7 :                 sdump->indent--;
    1772             : 
    1773           7 :                 DUMP_IND(sdump);
    1774           7 :                 gf_fprintf(sdump->trace, "</Replace>\n");
    1775             :         } else {
    1776           5 :                 gf_fprintf(sdump->trace, "MULTIPLEREPLACE ");
    1777           5 :                 scene_dump_vrml_id(sdump, com->node);
    1778           5 :                 gf_fprintf(sdump->trace, " {\n");
    1779           5 :                 sdump->indent++;
    1780           5 :                 i=0;
    1781          18 :                 while ((inf = (GF_CommandField *) gf_list_enum(com->command_fields, &i))) {
    1782          13 :                         gf_node_get_field(com->node, inf->fieldIndex, &info);
    1783          13 :                         info.far_ptr = inf->field_ptr;
    1784          13 :                         gf_dump_vrml_field(sdump, com->node, info);
    1785             :                 }
    1786           5 :                 sdump->indent--;
    1787           5 :                 DUMP_IND(sdump);
    1788           5 :                 gf_fprintf(sdump->trace, "}\n");
    1789             :         }
    1790             :         return GF_OK;
    1791             : }
    1792             : 
    1793           9 : static GF_Err DumpGlobalQP(GF_SceneDumper *sdump, GF_Command *com)
    1794             : {
    1795             :         GF_CommandField *inf;
    1796           9 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    1797           9 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    1798             : 
    1799           9 :         DUMP_IND(sdump);
    1800           9 :         if (sdump->XMLDump) {
    1801           5 :                 gf_fprintf(sdump->trace, "<Replace extended=\"globalQuant\">\n");
    1802             :         } else {
    1803           4 :                 gf_fprintf(sdump->trace, "GLOBALQP ");
    1804             :         }
    1805           9 :         gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    1806           9 :         if (sdump->XMLDump) gf_fprintf(sdump->trace, "</Replace>\n");
    1807           4 :         else gf_fprintf(sdump->trace, "\n");
    1808             :         return GF_OK;
    1809             : }
    1810             : 
    1811          45 : static GF_Err DumpNodeInsert(GF_SceneDumper *sdump, GF_Command *com)
    1812             : {
    1813             :         GF_CommandField *inf;
    1814             :         char posname[20];
    1815          45 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    1816          45 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    1817             : 
    1818          45 :         switch (inf->pos) {
    1819             :         case 0:
    1820             :                 strcpy(posname, "BEGIN");
    1821             :                 break;
    1822             :         case -1:
    1823             :                 strcpy(posname, "END");
    1824             :                 break;
    1825           0 :         default:
    1826             :                 sprintf(posname, "%d", inf->pos);
    1827             :                 break;
    1828             :         }
    1829             : 
    1830          45 :         DUMP_IND(sdump);
    1831          45 :         if (sdump->XMLDump) {
    1832          25 :                 gf_fprintf(sdump->trace, "<Insert atNode=\"");
    1833          25 :                 scene_dump_vrml_id(sdump, com->node);
    1834          25 :                 gf_fprintf(sdump->trace, "\" position=\"%s\">", posname);
    1835             :         } else {
    1836          20 :                 if (inf->pos==-1) {
    1837          12 :                         gf_fprintf(sdump->trace, "APPEND TO ");
    1838             :                 }
    1839           8 :                 else gf_fprintf(sdump->trace, "INSERT AT ");
    1840          20 :                 scene_dump_vrml_id(sdump, com->node);
    1841          20 :                 gf_fprintf(sdump->trace, ".children");
    1842          20 :                 if (inf->pos!=-1) gf_fprintf(sdump->trace, "[%d]", inf->pos);
    1843          20 :                 gf_fprintf(sdump->trace, " ");
    1844             :         }
    1845             : 
    1846          45 :         gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    1847          45 :         if (sdump->XMLDump) gf_fprintf(sdump->trace, "</Insert>");
    1848          45 :         gf_fprintf(sdump->trace, "\n");
    1849             :         return GF_OK;
    1850             : }
    1851             : 
    1852          63 : static GF_Err DumpRouteInsert(GF_SceneDumper *sdump, GF_Command *com, Bool is_scene_replace)
    1853             : {
    1854             :         GF_Route r;
    1855             : 
    1856             :         memset(&r, 0, sizeof(GF_Route));
    1857          63 :         r.ID = com->RouteID;
    1858          63 :         r.name = com->def_name;
    1859         126 :         r.FromNode = gf_dump_find_node(sdump, com->fromNodeID);
    1860          63 :         r.FromField.fieldIndex = com->fromFieldIndex;
    1861         126 :         r.ToNode = gf_dump_find_node(sdump, com->toNodeID);
    1862          63 :         r.ToField.fieldIndex = com->toFieldIndex;
    1863             : 
    1864          63 :         gf_list_add(sdump->inserted_routes, com);
    1865             : 
    1866          63 :         if (is_scene_replace) {
    1867          54 :                 gf_dump_vrml_route(sdump, &r, 0);
    1868             :         } else {
    1869           9 :                 DUMP_IND(sdump);
    1870           9 :                 if (sdump->XMLDump) {
    1871           5 :                         gf_fprintf(sdump->trace, "<Insert>\n");
    1872             :                 } else {
    1873           4 :                         gf_fprintf(sdump->trace, "INSERT ");
    1874             :                 }
    1875           9 :                 gf_dump_vrml_route(sdump, &r, 2);
    1876           9 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, "</Insert>");
    1877             :         }
    1878          63 :         return GF_OK;
    1879             : }
    1880             : 
    1881           4 : static GF_Err DumpIndexInsert(GF_SceneDumper *sdump, GF_Command *com)
    1882             : {
    1883             :         GF_Err e;
    1884             :         GF_FieldInfo field, sffield;
    1885             :         GF_CommandField *inf;
    1886             :         char posname[20];
    1887           4 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    1888           4 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    1889             : 
    1890           4 :         switch (inf->pos) {
    1891             :         case 0:
    1892             :                 strcpy(posname, "BEGIN");
    1893             :                 break;
    1894             :         case -1:
    1895             :                 strcpy(posname, "END");
    1896             :                 break;
    1897           0 :         default:
    1898             :                 sprintf(posname, "%d", inf->pos);
    1899             :                 break;
    1900             :         }
    1901             : 
    1902           4 :         e = gf_node_get_field(com->node, inf->fieldIndex, &field);
    1903           4 :         if (e) return e;
    1904           4 :         if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM;
    1905             : 
    1906           4 :         DUMP_IND(sdump);
    1907           4 :         if (sdump->XMLDump) {
    1908           3 :                 gf_fprintf(sdump->trace, "<Insert atNode=\"");
    1909           3 :                 scene_dump_vrml_id(sdump, com->node);
    1910           3 :                 gf_fprintf(sdump->trace, "\" atField=\"%s\" position=\"%s\"", field.name, posname);
    1911             :         } else {
    1912           1 :                 if (inf->pos==-1) {
    1913           0 :                         gf_fprintf(sdump->trace, "APPEND TO ");
    1914             :                 }
    1915           1 :                 else gf_fprintf(sdump->trace, "INSERT AT ");
    1916           1 :                 scene_dump_vrml_id(sdump, com->node);
    1917           1 :                 gf_fprintf(sdump->trace, ".%s", field.name);
    1918           1 :                 if (inf->pos!=-1) gf_fprintf(sdump->trace, "[%d]", inf->pos);
    1919           1 :                 gf_fprintf(sdump->trace, " ");
    1920             :         }
    1921             : 
    1922             :         memcpy(&sffield, &field, sizeof(GF_FieldInfo));
    1923           4 :         sffield.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
    1924             : 
    1925           4 :         if (field.fieldType==GF_SG_VRML_MFNODE) {
    1926           2 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, ">\n");
    1927           2 :                 gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    1928           2 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, "</Insert>");
    1929           2 :                 gf_fprintf(sdump->trace, "\n");
    1930             :         } else {
    1931           2 :                 sffield.far_ptr = inf->field_ptr;
    1932           2 :                 gf_dump_vrml_simple_field(sdump, sffield, com->node);
    1933           2 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, "/>");
    1934           2 :                 gf_fprintf(sdump->trace, "\n");
    1935             :         }
    1936             :         return e;
    1937             : }
    1938             : 
    1939           9 : static GF_Err DumpIndexDelete(GF_SceneDumper *sdump, GF_Command *com)
    1940             : {
    1941             :         char posname[20];
    1942             :         GF_FieldInfo field;
    1943             :         GF_CommandField *inf;
    1944           9 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    1945           9 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    1946             : 
    1947           9 :         switch (inf->pos) {
    1948           0 :         case -1:
    1949           0 :                 strcpy(posname, sdump->XMLDump ? "END" : "LAST");
    1950             :                 break;
    1951             :         case 0:
    1952             :                 strcpy(posname, "BEGIN");
    1953             :                 break;
    1954           0 :         default:
    1955             :                 sprintf(posname, "%d", inf->pos);
    1956             :                 break;
    1957             :         }
    1958             : 
    1959           9 :         gf_node_get_field(com->node, inf->fieldIndex, &field);
    1960             : 
    1961           9 :         DUMP_IND(sdump);
    1962           9 :         if (sdump->XMLDump) {
    1963           5 :                 gf_fprintf(sdump->trace, "<Delete atNode=\"");
    1964           5 :                 scene_dump_vrml_id(sdump, com->node);
    1965           5 :                 gf_fprintf(sdump->trace, "\" atField=\"%s\" position=\"%s\"/>", field.name, posname);
    1966             :         } else {
    1967           4 :                 gf_fprintf(sdump->trace, "DELETE ");
    1968           4 :                 if (inf->pos==-1) gf_fprintf(sdump->trace, "%s ", posname);
    1969           4 :                 scene_dump_vrml_id(sdump, com->node);
    1970           4 :                 gf_fprintf(sdump->trace, ".%s", field.name);
    1971           4 :                 if (inf->pos!=-1) gf_fprintf(sdump->trace, "[%d]", inf->pos);
    1972           4 :                 gf_fprintf(sdump->trace, "\n");
    1973             :         }
    1974             :         return GF_OK;
    1975             : }
    1976             : 
    1977             : 
    1978          18 : static GF_Err DumpNodeDelete(GF_SceneDumper *sdump, GF_Command *com)
    1979             : {
    1980          18 :         DUMP_IND(sdump);
    1981          18 :         if (sdump->XMLDump) {
    1982          10 :                 if (com->tag==GF_SG_NODE_DELETE_EX) {
    1983           5 :                         gf_fprintf(sdump->trace, "<Delete extended=\"deleteOrder\" atNode=\"");
    1984             :                 } else {
    1985           5 :                         gf_fprintf(sdump->trace, "<Delete atNode=\"");
    1986             :                 }
    1987          10 :                 scene_dump_vrml_id(sdump, com->node);
    1988          10 :                 gf_fprintf(sdump->trace, "\"/>\n");
    1989             :         } else {
    1990           8 :                 if (com->tag==GF_SG_NODE_DELETE_EX) gf_fprintf(sdump->trace, "X");
    1991           8 :                 gf_fprintf(sdump->trace, "DELETE ");
    1992           8 :                 scene_dump_vrml_id(sdump, com->node);
    1993           8 :                 gf_fprintf(sdump->trace, "\n");
    1994             :         }
    1995          18 :         return GF_OK;
    1996             : }
    1997             : 
    1998           9 : static GF_Err DumpRouteDelete(GF_SceneDumper *sdump, GF_Command *com)
    1999             : {
    2000           9 :         DUMP_IND(sdump);
    2001           9 :         if (sdump->XMLDump) {
    2002           5 :                 gf_fprintf(sdump->trace, "<Delete atRoute=\"");
    2003           5 :                 scene_dump_vrml_route_id(sdump, com->RouteID, com->def_name);
    2004           5 :                 gf_fprintf(sdump->trace, "\"/>\n");
    2005             :         } else {
    2006           4 :                 gf_fprintf(sdump->trace, "DELETE ROUTE ");
    2007           4 :                 scene_dump_vrml_route_id(sdump, com->RouteID, com->def_name);
    2008           4 :                 gf_fprintf(sdump->trace, "\n");
    2009             :         }
    2010           9 :         return GF_OK;
    2011             : }
    2012             : 
    2013             : 
    2014             : 
    2015          45 : static GF_Err DumpNodeReplace(GF_SceneDumper *sdump, GF_Command *com)
    2016             : {
    2017             :         GF_CommandField *inf;
    2018          45 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    2019          43 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    2020          43 :         DUMP_IND(sdump);
    2021          43 :         if (sdump->XMLDump) {
    2022          25 :                 gf_fprintf(sdump->trace, "<Replace atNode=\"");
    2023          25 :                 scene_dump_vrml_id(sdump, com->node);
    2024          25 :                 gf_fprintf(sdump->trace, "\">");
    2025          25 :                 gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    2026          25 :                 gf_fprintf(sdump->trace, "</Replace>\n");
    2027             :         } else {
    2028          18 :                 gf_fprintf(sdump->trace, "REPLACE ");
    2029          18 :                 scene_dump_vrml_id(sdump, com->node);
    2030          18 :                 gf_fprintf(sdump->trace, " BY ");
    2031          18 :                 gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    2032          18 :                 gf_fprintf(sdump->trace, "\n");
    2033             :         }
    2034             :         return GF_OK;
    2035             : }
    2036             : 
    2037         133 : static GF_Err DumpFieldReplace(GF_SceneDumper *sdump, GF_Command *com)
    2038             : {
    2039             :         GF_Err e;
    2040             :         GF_FieldInfo field;
    2041             :         GF_CommandField *inf;
    2042         133 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    2043         133 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    2044             : 
    2045         133 :         e = gf_node_get_field(com->node, inf->fieldIndex, &field);
    2046             : 
    2047         133 :         DUMP_IND(sdump);
    2048         133 :         if (sdump->XMLDump) {
    2049          74 :                 gf_fprintf(sdump->trace, "<Replace atNode=\"");
    2050          74 :                 scene_dump_vrml_id(sdump, com->node);
    2051          74 :                 gf_fprintf(sdump->trace, "\" atField=\"%s\" ", field.name);
    2052             :         } else {
    2053          59 :                 gf_fprintf(sdump->trace, "REPLACE ");
    2054          59 :                 scene_dump_vrml_id(sdump, com->node);
    2055          59 :                 gf_fprintf(sdump->trace, ".%s BY ", field.name);
    2056             :         }
    2057             : 
    2058         133 :         switch (field.fieldType) {
    2059           6 :         case GF_SG_VRML_SFNODE:
    2060           6 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, ">");
    2061           6 :                 gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    2062           6 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, "</Replace>");
    2063           2 :                 else gf_fprintf(sdump->trace, "\n");
    2064             :                 break;
    2065           3 :         case GF_SG_VRML_MFNODE:
    2066             :         {
    2067             :                 GF_ChildNodeItem *tmp;
    2068           3 :                 if (sdump->XMLDump) {
    2069           2 :                         gf_fprintf(sdump->trace, ">");
    2070             :                 } else {
    2071           1 :                         gf_fprintf(sdump->trace, " [\n");
    2072             :                 }
    2073           3 :                 sdump->indent++;
    2074           3 :                 tmp = inf->node_list;
    2075           6 :                 while (tmp) {
    2076           3 :                         gf_dump_vrml_node(sdump, tmp->node, 1, NULL);
    2077           3 :                         tmp = tmp->next;
    2078             :                 }
    2079           3 :                 sdump->indent--;
    2080           3 :                 if (sdump->XMLDump) {
    2081           2 :                         gf_fprintf(sdump->trace, "</Replace>");
    2082             :                 } else {
    2083           1 :                         EndList(sdump, NULL);
    2084             :                 }
    2085             :         }
    2086             :         break;
    2087           0 :         case GF_SG_VRML_SFCOMMANDBUFFER:
    2088           0 :                 if (sdump->XMLDump) {
    2089           0 :                         SFCommandBuffer *cb = (SFCommandBuffer*)inf->field_ptr;
    2090           0 :                         gf_fprintf(sdump->trace, ">\n");
    2091           0 :                         gf_sm_dump_command_list(sdump, cb->commandList, sdump->indent+1, 0);
    2092           0 :                         DUMP_IND(sdump);
    2093           0 :                         gf_fprintf(sdump->trace, "</Replace>\n");
    2094             :                 } else {
    2095           0 :                         SFCommandBuffer *cb = (SFCommandBuffer*)inf->field_ptr;
    2096           0 :                         gf_fprintf(sdump->trace, " {\n");
    2097           0 :                         gf_sm_dump_command_list(sdump, cb->commandList, sdump->indent+1, 0);
    2098           0 :                         DUMP_IND(sdump);
    2099           0 :                         gf_fprintf(sdump->trace, "}\n");
    2100             :                 }
    2101             :                 break;
    2102         124 :         default:
    2103         124 :                 field.far_ptr = inf->field_ptr;
    2104         124 :                 gf_dump_vrml_simple_field(sdump, field, com->node);
    2105         124 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, "/>");
    2106         124 :                 gf_fprintf(sdump->trace, "\n");
    2107             :         }
    2108             :         return e;
    2109             : }
    2110             : 
    2111             : 
    2112          27 : static GF_Err DumpIndexReplace(GF_SceneDumper *sdump, GF_Command *com)
    2113             : {
    2114             :         char posname[20];
    2115             :         GF_Err e;
    2116             :         GF_FieldInfo field;
    2117             :         GF_CommandField *inf;
    2118          27 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    2119          27 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    2120             : 
    2121          27 :         e = gf_node_get_field(com->node, inf->fieldIndex, &field);
    2122          27 :         if (e) return e;
    2123          27 :         if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM;
    2124             : 
    2125          27 :         switch (inf->pos) {
    2126             :         case 0:
    2127             :                 strcpy(posname, "BEGIN");
    2128             :                 break;
    2129           0 :         case -1:
    2130           0 :                 strcpy(posname, sdump->XMLDump ? "END" : "LAST");
    2131             :                 break;
    2132           9 :         default:
    2133             :                 sprintf(posname, "%d", inf->pos);
    2134             :                 break;
    2135             :         }
    2136             : 
    2137          27 :         DUMP_IND(sdump);
    2138          27 :         if (sdump->XMLDump) {
    2139          15 :                 gf_fprintf(sdump->trace, "<Replace atNode=\"");
    2140          15 :                 scene_dump_vrml_id(sdump, com->node);
    2141          15 :                 gf_fprintf(sdump->trace, "\" atField=\"%s\" position=\"%s\"", field.name, posname);
    2142             :         } else {
    2143          12 :                 gf_fprintf(sdump->trace, "REPLACE ");
    2144          12 :                 if (inf->pos==-1) gf_fprintf(sdump->trace, "%s ", posname);
    2145          12 :                 scene_dump_vrml_id(sdump, com->node);
    2146          12 :                 gf_fprintf(sdump->trace, ".%s", field.name);
    2147          12 :                 if (inf->pos!=-1) gf_fprintf(sdump->trace, "[%d]", inf->pos);
    2148          12 :                 gf_fprintf(sdump->trace, " BY ");
    2149             :         }
    2150             : 
    2151          27 :         if (field.fieldType == GF_SG_VRML_MFNODE) {
    2152          18 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, ">\n");
    2153          18 :                 gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    2154          18 :                 gf_fprintf(sdump->trace, (sdump->XMLDump) ? "</Replace>\n" : "\n");
    2155             :         } else {
    2156           9 :                 field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
    2157           9 :                 field.far_ptr = inf->field_ptr;
    2158           9 :                 gf_dump_vrml_simple_field(sdump, field, com->node);
    2159           9 :                 gf_fprintf(sdump->trace, sdump->XMLDump ? "/>\n" : "\n");
    2160             :         }
    2161             :         return GF_OK;
    2162             : }
    2163             : 
    2164             : 
    2165          18 : static GF_Err DumpXReplace(GF_SceneDumper *sdump, GF_Command *com)
    2166             : {
    2167             :         char posname[20];
    2168             :         GF_Err e;
    2169             :         GF_FieldInfo field, idxField;
    2170             :         GF_Node *toNode, *target;
    2171             :         GF_CommandField *inf;
    2172          18 :         if (!gf_list_count(com->command_fields)) return GF_OK;
    2173          18 :         inf = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    2174             : 
    2175          18 :         e = gf_node_get_field(com->node, inf->fieldIndex, &field);
    2176          18 :         if (e) return e;
    2177             : 
    2178             :         toNode = target = NULL;
    2179             :         /*indexed replacement with index given by other node field*/
    2180          18 :         if (com->toNodeID) {
    2181           9 :                 toNode = gf_sg_find_node(com->in_scene, com->toNodeID);
    2182           9 :                 if (!toNode) return GF_NON_COMPLIANT_BITSTREAM;
    2183           9 :                 e = gf_node_get_field(toNode, com->toFieldIndex, &idxField);
    2184           9 :                 if (e) return e;
    2185             :         }
    2186             :         else {
    2187             :                 /*indexed replacement */
    2188           9 :                 if (inf->pos>=-1) {
    2189           7 :                         if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM;
    2190           0 :                         switch (inf->pos) {
    2191             :                         case 0:
    2192             :                                 strcpy(posname, "BEGIN");
    2193             :                                 break;
    2194           0 :                         case -1:
    2195           0 :                                 strcpy(posname, sdump->XMLDump ? "END" : "LAST");
    2196             :                                 break;
    2197           0 :                         default:
    2198             :                                 sprintf(posname, "%d", inf->pos);
    2199             :                                 break;
    2200             :                         }
    2201           0 :                         field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
    2202             :                 }
    2203             :         }
    2204          11 :         field.far_ptr = inf->field_ptr;
    2205             : 
    2206          11 :         DUMP_IND(sdump);
    2207          11 :         if (sdump->XMLDump) {
    2208           7 :                 gf_fprintf(sdump->trace, "<Replace atNode=\"");
    2209           7 :                 scene_dump_vrml_id(sdump, com->node);
    2210           7 :                 gf_fprintf(sdump->trace, "\" atField=\"%s\"", field.name);
    2211             : 
    2212           7 :                 if (toNode) {
    2213           5 :                         gf_fprintf(sdump->trace, " atIndexNode=\"");
    2214           5 :                         scene_dump_vrml_id(sdump, toNode);
    2215           5 :                         gf_fprintf(sdump->trace, "\" atIndexField=\"%s\"", idxField.name);
    2216             : 
    2217           5 :                         field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
    2218             :                 }
    2219           7 :                 if (com->ChildNodeTag) {
    2220             :                         GF_FieldInfo cfield;
    2221             :                         GF_Node *cnode;
    2222             : 
    2223           5 :                         if (com->ChildNodeTag>0) {
    2224           5 :                                 cnode = gf_node_new(com->in_scene, com->ChildNodeTag);
    2225             :                         } else {
    2226           0 :                                 GF_Proto *proto = gf_sg_find_proto(com->in_scene, -com->ChildNodeTag , NULL);
    2227           0 :                                 if (!proto) return GF_SG_UNKNOWN_NODE;
    2228           0 :                                 cnode = gf_sg_proto_create_instance(com->in_scene, proto);
    2229             :                         }
    2230           5 :                         if (!cnode) return GF_SG_UNKNOWN_NODE;
    2231           5 :                         gf_node_register(cnode, NULL);
    2232           5 :                         gf_node_get_field(cnode, com->child_field, &cfield);
    2233           5 :                         gf_fprintf(sdump->trace, " atChildField=\"%s\"", cfield.name);
    2234           5 :                         gf_node_unregister(cnode, NULL);
    2235             : 
    2236           5 :                         field.fieldType = cfield.fieldType;
    2237             :                 }
    2238             : 
    2239           7 :                 if (com->fromNodeID) {
    2240           2 :                         target = gf_sg_find_node(com->in_scene, com->fromNodeID);
    2241           2 :                         if (!target) return GF_NON_COMPLIANT_BITSTREAM;
    2242           2 :                         e = gf_node_get_field(target, com->fromFieldIndex, &idxField);
    2243           2 :                         if (e) return e;
    2244             : 
    2245           2 :                         gf_fprintf(sdump->trace, " fromNode=\"");
    2246           2 :                         scene_dump_vrml_id(sdump, target);
    2247           2 :                         gf_fprintf(sdump->trace, "\" fromField=\"%s\">\n", idxField.name);
    2248           2 :                         return GF_OK;
    2249             :                 } else {
    2250           5 :                         if (inf->pos>=-1) gf_fprintf(sdump->trace, " position=\"%s\"", posname);
    2251             :                 }
    2252             :         } else {
    2253           4 :                 gf_fprintf(sdump->trace, "XREPLACE ");
    2254           4 :                 if (inf->pos==-1) gf_fprintf(sdump->trace, "%s ", posname);
    2255           4 :                 scene_dump_vrml_id(sdump, com->node);
    2256           4 :                 gf_fprintf(sdump->trace, ".%s", field.name);
    2257           4 :                 if (toNode) {
    2258           4 :                         gf_fprintf(sdump->trace, "[");
    2259           4 :                         scene_dump_vrml_id(sdump, toNode);
    2260           4 :                         gf_fprintf(sdump->trace, ".%s]", idxField.name);
    2261           4 :                         field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
    2262             :                 }
    2263           0 :                 else if (inf->pos!=-1) gf_fprintf(sdump->trace, "[%d]", inf->pos);
    2264           4 :                 if (com->ChildNodeTag) {
    2265             :                         GF_FieldInfo cfield;
    2266             :                         GF_Node *cnode;
    2267           4 :                         if (com->ChildNodeTag>0) {
    2268           4 :                                 cnode = gf_node_new(com->in_scene, com->ChildNodeTag);
    2269             :                         } else {
    2270           0 :                                 GF_Proto *proto = gf_sg_find_proto(com->in_scene, -com->ChildNodeTag , NULL);
    2271           0 :                                 if (!proto) return GF_SG_UNKNOWN_NODE;
    2272           0 :                                 cnode = gf_sg_proto_create_instance(com->in_scene, proto);
    2273             :                         }
    2274           4 :                         if (!cnode) return GF_SG_UNKNOWN_NODE;
    2275           4 :                         gf_node_register(cnode, NULL);
    2276           4 :                         gf_node_get_field(cnode, com->child_field, &cfield);
    2277           4 :                         gf_fprintf(sdump->trace, ".%s", cfield.name);
    2278           4 :                         gf_node_unregister(cnode, NULL);
    2279           4 :                         field.fieldType = cfield.fieldType;
    2280             :                 }
    2281           4 :                 gf_fprintf(sdump->trace, " BY ");
    2282             :         }
    2283             : 
    2284           9 :         if (field.fieldType == GF_SG_VRML_MFNODE) {
    2285           0 :                 if (sdump->XMLDump) gf_fprintf(sdump->trace, ">\n");
    2286           0 :                 gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
    2287           0 :                 gf_fprintf(sdump->trace, (sdump->XMLDump) ? "</Replace>\n" : "\n");
    2288             :         } else {
    2289           9 :                 gf_dump_vrml_simple_field(sdump, field, com->node);
    2290           9 :                 gf_fprintf(sdump->trace, sdump->XMLDump ? "/>\n" : "\n");
    2291             :         }
    2292             :         return GF_OK;
    2293             : }
    2294             : 
    2295             : 
    2296           9 : static GF_Err DumpRouteReplace(GF_SceneDumper *sdump, GF_Command *com)
    2297             : {
    2298             :         const char *name;
    2299             :         GF_Route r2;
    2300             : 
    2301           9 :         if (!scene_dump_vrml_find_route_name(sdump, com->RouteID, &name)) return GF_BAD_PARAM;
    2302             : 
    2303             :         memset(&r2, 0, sizeof(GF_Route));
    2304          18 :         r2.FromNode = gf_dump_find_node(sdump, com->fromNodeID);
    2305           9 :         r2.FromField.fieldIndex = com->fromFieldIndex;
    2306          18 :         r2.ToNode = gf_dump_find_node(sdump, com->toNodeID);
    2307           9 :         r2.ToField.fieldIndex = com->toFieldIndex;
    2308             : 
    2309           9 :         DUMP_IND(sdump);
    2310           9 :         if (sdump->XMLDump) {
    2311           5 :                 gf_fprintf(sdump->trace, "<Replace atRoute=\"");
    2312           5 :                 scene_dump_vrml_route_id(sdump, com->RouteID, (char *) name);
    2313           5 :                 gf_fprintf(sdump->trace, "\">\n");
    2314             :         } else {
    2315           4 :                 gf_fprintf(sdump->trace, "REPLACE ROUTE ");
    2316           4 :                 scene_dump_vrml_route_id(sdump, com->RouteID, (char *) name);
    2317           4 :                 gf_fprintf(sdump->trace, " BY ");
    2318             :         }
    2319           9 :         gf_dump_vrml_route(sdump, &r2, 1);
    2320           9 :         if (sdump->XMLDump ) gf_fprintf(sdump->trace, "</Replace>");
    2321             :         return GF_OK;
    2322             : }
    2323             : 
    2324          72 : static GF_Err gf_dump_vrml_route(GF_SceneDumper *sdump, GF_Route *r, u32 dump_type)
    2325             : {
    2326             :         char toNode[512], fromNode[512];
    2327             :         const char *node_name;
    2328             :         u32 id;
    2329          72 :         if (!r->is_setup) {
    2330          72 :                 gf_node_get_field(r->FromNode, r->FromField.fieldIndex, &r->FromField);
    2331          72 :                 gf_node_get_field(r->ToNode, r->ToField.fieldIndex, &r->ToField);
    2332          72 :                 r->is_setup = 1;
    2333             :         }
    2334          72 :         if (!r->FromNode || !r->ToNode) return GF_BAD_PARAM;
    2335             : 
    2336          72 :         if (sdump->XMLDump || !dump_type) DUMP_IND(sdump);
    2337             : 
    2338          72 :         node_name = gf_node_get_name_and_id(r->FromNode, &id);
    2339          72 :         if (node_name) {
    2340             :                 const char *to_name;
    2341             :                 strcpy(fromNode, node_name);
    2342          24 :                 to_name = gf_node_get_name(r->ToNode);
    2343          24 :                 if (to_name) {
    2344             :                         strcpy(toNode, to_name);
    2345             :                 } else {
    2346             :                         char str[100];
    2347           0 :                         id = gf_node_get_id(r->ToNode);
    2348             :                         sprintf(str, "node_%d", id);
    2349             :                         strcpy(toNode, str);
    2350             :                 }
    2351             :         } else {
    2352          48 :                 sprintf(fromNode, "N%d", id-1);
    2353          48 :                 sprintf(toNode, "N%d", gf_node_get_id(r->ToNode) - 1);
    2354             :         }
    2355          72 :         if (sdump->XMLDump) {
    2356          40 :                 gf_fprintf(sdump->trace, "<ROUTE");
    2357          40 :                 if (r->ID) {
    2358           5 :                         StartAttribute(sdump, "DEF");
    2359           5 :                         scene_dump_vrml_route_id(sdump, r->ID, r->name);
    2360           5 :                         EndAttribute(sdump);
    2361             :                 }
    2362          40 :                 gf_fprintf(sdump->trace, " fromNode=\"%s\" fromField=\"%s\" toNode=\"%s\" toField=\"%s\"/>\n", fromNode, r->FromField.name, toNode, r->ToField.name);
    2363             :         } else {
    2364          32 :                 if (dump_type==2) gf_fprintf(sdump->trace, "ROUTE ");
    2365          32 :                 if (r->ID) {
    2366           4 :                         gf_fprintf(sdump->trace, "DEF ");
    2367           4 :                         scene_dump_vrml_route_id(sdump, r->ID, r->name);
    2368           4 :                         gf_fprintf(sdump->trace, " ");
    2369             :                 }
    2370          32 :                 if (dump_type==1) {
    2371           4 :                         gf_fprintf(sdump->trace, "%s.%s TO %s.%s\n", fromNode, r->FromField.name, toNode, r->ToField.name);
    2372             :                 } else {
    2373          28 :                         if (dump_type!=2) gf_fprintf(sdump->trace, "ROUTE ");
    2374          28 :                         gf_fprintf(sdump->trace, "%s.%s TO %s.%s\n", fromNode, r->FromField.name, toNode, r->ToField.name);
    2375             :                 }
    2376             :         }
    2377             :         return GF_OK;
    2378             : }
    2379             : 
    2380             : 
    2381          64 : static GF_Err DumpProtos(GF_SceneDumper *sdump, GF_List *protoList)
    2382             : {
    2383             : #ifdef GPAC_DISABLE_VRML
    2384             :         return GF_OK;
    2385             : #else
    2386             :         u32 i, j, count;
    2387             :         GF_FieldInfo field;
    2388             :         GF_Err e;
    2389             :         GF_SceneGraph *prev_sg;
    2390             :         GF_Proto *proto, *prev_proto;
    2391             : 
    2392          64 :         prev_proto = sdump->current_proto;
    2393             : 
    2394          64 :         i=0;
    2395         155 :         while ((proto = (GF_Proto*)gf_list_enum(protoList, &i))) {
    2396          27 :                 sdump->current_proto = proto;
    2397             : 
    2398          27 :                 DUMP_IND(sdump);
    2399          27 :                 if (!sdump->XMLDump) {
    2400          12 :                         gf_fprintf(sdump->trace, proto->ExternProto.count ? "EXTERNPROTO " : "PROTO ");
    2401          12 :                         gf_fprintf(sdump->trace, "%s [\n", proto->Name);
    2402             :                 } else {
    2403          15 :                         gf_fprintf(sdump->trace, "<ProtoDeclare name=\"%s\" protoID=\"%d\"", proto->Name, proto->ID);
    2404          15 :                         if (proto->ExternProto.count) {
    2405           5 :                                 gf_fprintf(sdump->trace, " locations=\"");
    2406           5 :                                 gf_dump_vrml_sffield(sdump, GF_SG_VRML_SFURL, &proto->ExternProto.vals[0], 0, NULL);
    2407           5 :                                 gf_fprintf(sdump->trace, "\"");
    2408             :                         }
    2409          15 :                         gf_fprintf(sdump->trace, ">\n");
    2410             :                 }
    2411             : 
    2412          27 :                 if (sdump->XMLDump && sdump->X3DDump) gf_fprintf(sdump->trace, "<ProtoInterface>");
    2413             : 
    2414          27 :                 sdump->indent++;
    2415          27 :                 count = gf_list_count(proto->proto_fields);
    2416         207 :                 for (j=0; j<count; j++) {
    2417         180 :                         GF_ProtoFieldInterface *pf = (GF_ProtoFieldInterface *)gf_list_get(proto->proto_fields, j);
    2418             :                         field.fieldIndex = pf->ALL_index;
    2419         180 :                         field.eventType = pf->EventType;
    2420         180 :                         field.far_ptr = pf->def_value;
    2421         180 :                         field.fieldType = pf->FieldType;
    2422         180 :                         field.name = pf->FieldName;
    2423             :                         field.NDTtype = NDT_SFWorldNode;
    2424             :                         field.on_event_in = NULL;
    2425             : 
    2426         180 :                         gf_dump_vrml_dyn_field(sdump, NULL, field, pf->QP_Type ? 1 : 0);
    2427             : 
    2428         180 :                         if (!pf->QP_Type) continue;
    2429             : 
    2430             :                         /*dump interface coding - BT/TXT extensions, not supported by any other tool*/
    2431           0 :                         sdump->indent++;
    2432           0 :                         DUMP_IND(sdump);
    2433           0 :                         if (sdump->XMLDump) {
    2434             :                                 const char *quant_catname = "unknown";
    2435             : #ifndef GPAC_DISABLE_BIFS
    2436           0 :                                 switch (pf->QP_Type) {
    2437           0 :                                 case QC_3DPOS: quant_catname = "position3D"; break;
    2438           0 :                                 case QC_2DPOS: quant_catname = "position2D"; break;
    2439           0 :                                 case QC_ORDER: quant_catname = "drawingOrder"; break;
    2440           0 :                                 case QC_COLOR: quant_catname = "color"; break;
    2441           0 :                                 case QC_TEXTURE_COORD: quant_catname = "textureCoordinate"; break;
    2442           0 :                                 case QC_ANGLE: quant_catname = "angle"; break;
    2443           0 :                                 case QC_SCALE: quant_catname = "scale"; break;
    2444           0 :                                 case QC_INTERPOL_KEYS: quant_catname = "keys"; break;
    2445           0 :                                 case QC_NORMALS: quant_catname = "normals"; break;
    2446           0 :                                 case QC_ROTATION: quant_catname = "rotations"; break;
    2447           0 :                                 case QC_SIZE_3D: quant_catname = "size3D"; break;
    2448           0 :                                 case QC_SIZE_2D: quant_catname = "size2D"; break;
    2449           0 :                                 case QC_LINEAR_SCALAR: quant_catname = "linear"; break;
    2450           0 :                                 case QC_COORD_INDEX:quant_catname = "coordIndex"; break;
    2451             :                                 }
    2452             : #endif
    2453           0 :                                 gf_fprintf(sdump->trace, "<InterfaceCodingParameters quantCategoy=\"%s\"", quant_catname);
    2454             :                         } else {
    2455           0 :                                 gf_fprintf(sdump->trace, "{QP %d", pf->QP_Type);
    2456             :                         }
    2457             : #ifndef GPAC_DISABLE_BIFS
    2458           0 :                         if (pf->QP_Type==QC_LINEAR_SCALAR) gf_fprintf(sdump->trace, sdump->XMLDump ? " nbBits=\"%d\"" : " nbBits %d", pf->NumBits);
    2459           0 :                         if (pf->hasMinMax) {
    2460           0 :                                 switch (pf->QP_Type) {
    2461           0 :                                 case QC_LINEAR_SCALAR:
    2462             :                                 case QC_COORD_INDEX:
    2463           0 :                                         if (sdump->XMLDump) {
    2464           0 :                                                 gf_fprintf(sdump->trace, " intMin=\"%d\" intMax=\"%d\"", *((SFInt32 *)pf->qp_min_value), *((SFInt32 *)pf->qp_max_value));
    2465             :                                         } else {
    2466           0 :                                                 gf_fprintf(sdump->trace, " b {%d %d}", *((SFInt32 *)pf->qp_min_value), *((SFInt32 *)pf->qp_max_value));
    2467             :                                         }
    2468             :                                         break;
    2469           0 :                                 default:
    2470           0 :                                         if (sdump->XMLDump) {
    2471           0 :                                                 gf_fprintf(sdump->trace, " floatMin=\"%g\" floatMax=\"%g\"", FIX2FLT( *((SFFloat *)pf->qp_min_value) ), FIX2FLT( *((SFFloat *)pf->qp_max_value) ));
    2472             :                                         } else {
    2473           0 :                                                 gf_fprintf(sdump->trace, " b {%g %g}", FIX2FLT( *((SFFloat *)pf->qp_min_value) ), FIX2FLT( *((SFFloat *)pf->qp_max_value) ) );
    2474             :                                         }
    2475             :                                         break;
    2476             :                                 }
    2477           0 :                         }
    2478             : #endif
    2479           0 :                         gf_fprintf(sdump->trace, sdump->XMLDump ? "/>\n" : "}\n");
    2480           0 :                         sdump->indent--;
    2481           0 :                         if (sdump->XMLDump) {
    2482           0 :                                 DUMP_IND(sdump);
    2483           0 :                                 gf_fprintf(sdump->trace, "</field>\n");
    2484             :                         }
    2485             : 
    2486             :                 }
    2487             : 
    2488          27 :                 sdump->indent--;
    2489          27 :                 DUMP_IND(sdump);
    2490          27 :                 if (!sdump->XMLDump) {
    2491          12 :                         gf_fprintf(sdump->trace, "]");
    2492          15 :                 } else if (sdump->X3DDump) gf_fprintf(sdump->trace, "</ProtoInterface>\n");
    2493             : 
    2494          27 :                 if (proto->ExternProto.count) {
    2495           9 :                         if (!sdump->XMLDump) {
    2496           4 :                                 gf_fprintf(sdump->trace, " \"");
    2497           4 :                                 gf_dump_vrml_sffield(sdump, GF_SG_VRML_SFURL, &proto->ExternProto.vals[0], 0, NULL);
    2498           4 :                                 gf_fprintf(sdump->trace, "\"\n\n");
    2499             :                         } else {
    2500           5 :                                 gf_fprintf(sdump->trace, "</ProtoDeclare>\n");
    2501             :                         }
    2502           9 :                         continue;
    2503             :                 }
    2504          18 :                 if (!sdump->XMLDump) gf_fprintf(sdump->trace, " {\n");
    2505             : 
    2506          18 :                 sdump->indent++;
    2507             : 
    2508          18 :                 if (sdump->XMLDump && sdump->X3DDump) gf_fprintf(sdump->trace, "<ProtoBody>\n");
    2509             : 
    2510          18 :                 e = DumpProtos(sdump, proto->sub_graph->protos);
    2511          18 :                 if (e) return e;
    2512             : 
    2513             :                 /*set namespace to the proto one*/
    2514          18 :                 prev_sg = sdump->sg;
    2515          18 :                 sdump->sg = gf_sg_proto_get_graph(proto);
    2516             : 
    2517          18 :                 count = gf_list_count(proto->node_code);
    2518          54 :                 for (j=0; j<count; j++) {
    2519          36 :                         GF_Node *n = (GF_Node*)gf_list_get(proto->node_code, j);
    2520          36 :                         gf_dump_vrml_node(sdump, n, 1, NULL);
    2521             :                 }
    2522          18 :                 count = gf_list_count(proto->sub_graph->Routes);
    2523         198 :                 for (j=0; j<count; j++) {
    2524         180 :                         GF_Route *r = (GF_Route *)gf_list_get(proto->sub_graph->Routes, j);
    2525         180 :                         if (r->IS_route) continue;
    2526           0 :                         gf_dump_vrml_route(sdump, r, 0);
    2527             :                 }
    2528             : 
    2529          18 :                 if (sdump->XMLDump && sdump->X3DDump) gf_fprintf(sdump->trace, "</ProtoBody>\n");
    2530             : 
    2531             :                 /*restore namespace*/
    2532          18 :                 sdump->sg = prev_sg;
    2533             : 
    2534          18 :                 sdump->indent--;
    2535          18 :                 DUMP_IND(sdump);
    2536          18 :                 if (!sdump->XMLDump) {
    2537           8 :                         gf_fprintf(sdump->trace, "}\n");
    2538             :                 } else {
    2539          10 :                         gf_fprintf(sdump->trace, "</ProtoDeclare>\n");
    2540             :                 }
    2541             :         }
    2542          64 :         sdump->current_proto = prev_proto;
    2543          64 :         return GF_OK;
    2544             : #endif
    2545             : }
    2546             : 
    2547          35 : static GF_Err DumpSceneReplace(GF_SceneDumper *sdump, GF_Command *com)
    2548             : {
    2549          35 :         if (sdump->XMLDump) {
    2550          19 :                 if (!sdump->X3DDump) {
    2551          19 :                         StartElement(sdump, "Replace");
    2552          19 :                         EndElementHeader(sdump, 1);
    2553          19 :                         sdump->indent++;
    2554             :                 }
    2555             :                 //scene tag is already dumped with X3D header
    2556          19 :                 if (!sdump->X3DDump) StartElement(sdump, "Scene");
    2557          19 :                 if (!sdump->X3DDump && com->use_names) {
    2558           0 :                         StartAttribute(sdump, "USENAMES");
    2559           0 :                         gf_fprintf(sdump->trace, "%s", com->use_names ? "true" : "false");
    2560           0 :                         EndAttribute(sdump);
    2561             :                 }
    2562          19 :                 if (!sdump->X3DDump) EndElementHeader(sdump, 1);
    2563          19 :                 sdump->indent++;
    2564             :         } else {
    2565          16 :                 if (!sdump->skip_scene_replace) {
    2566          13 :                         DUMP_IND(sdump);
    2567          13 :                         gf_fprintf(sdump->trace, "REPLACE SCENE BY ");
    2568             :                 }
    2569             :         }
    2570          35 :         DumpProtos(sdump, com->new_proto_list);
    2571          35 :         gf_dump_vrml_node(sdump, com->node, 0, NULL);
    2572          35 :         if (!sdump->XMLDump) gf_fprintf(sdump->trace, "\n\n");
    2573             : 
    2574          35 :         if (com->aggregated) {
    2575             :                 u32 i, count;
    2576           1 :                 count = gf_list_count(com->node->sgprivate->scenegraph->Routes);
    2577           1 :                 for (i=0; i<count; i++) {
    2578           0 :                         GF_Route *r = (GF_Route *)gf_list_get(com->node->sgprivate->scenegraph->Routes, i);
    2579           0 :                         if (r->IS_route) continue;
    2580           0 :                         gf_dump_vrml_route(sdump, r, 0);
    2581             :                 }
    2582             :         }
    2583             : 
    2584          35 :         return GF_OK;
    2585             : }
    2586             : 
    2587           9 : static GF_Err DumpProtoInsert(GF_SceneDumper *sdump, GF_Command *com)
    2588             : {
    2589           9 :         DUMP_IND(sdump);
    2590           9 :         if (sdump->XMLDump) {
    2591           5 :                 gf_fprintf(sdump->trace, "<Insert extended=\"proto\">\n");
    2592             :         } else {
    2593           4 :                 gf_fprintf(sdump->trace, "INSERTPROTO [\n");
    2594             :         }
    2595           9 :         sdump->indent++;
    2596           9 :         DumpProtos(sdump, com->new_proto_list);
    2597           9 :         sdump->indent--;
    2598           9 :         DUMP_IND(sdump);
    2599           9 :         if (sdump->XMLDump) {
    2600           5 :                 gf_fprintf(sdump->trace, "</Insert>\n");
    2601             :         } else {
    2602           4 :                 gf_fprintf(sdump->trace, "]\n");
    2603             :         }
    2604           9 :         return GF_OK;
    2605             : }
    2606             : 
    2607             : #endif /*GPAC_DISABLE_VRML*/
    2608             : 
    2609             : 
    2610             : #ifndef GPAC_DISABLE_SVG
    2611         256 : static char *lsr_format_node_id(GF_Node *n, u32 NodeID, char *str)
    2612             : {
    2613         256 :         if (!n) sprintf(str, "N%d", NodeID-1);
    2614             :         else {
    2615         254 :                 const char *name = gf_node_get_name_and_id(n, &NodeID);
    2616         254 :                 if (name) sprintf(str, "%s", name);
    2617         254 :                 else sprintf(str, "N%d", NodeID - 1);
    2618             :         }
    2619         256 :         return str;
    2620             : }
    2621             : 
    2622             : static char szLSRName[1024];
    2623             : 
    2624         182 : static char *sd_get_lsr_namespace(GF_SceneGraph *sg)
    2625             : {
    2626         182 :         char *lsrns = (char *) gf_sg_get_namespace_qname(sg, GF_XMLNS_LASER);
    2627         182 :         if (lsrns) {
    2628             :                 sprintf(szLSRName, "%s:", lsrns);
    2629           0 :                 return szLSRName;
    2630             :         }
    2631             :         return "";
    2632             : }
    2633             : 
    2634           2 : static GF_Err DumpLSRNewScene(GF_SceneDumper *sdump, GF_Command *com)
    2635             : {
    2636           2 :         char *lsrns = sd_get_lsr_namespace(com->in_scene);
    2637           2 :         gf_fprintf(sdump->trace, "<%sNewScene>\n", lsrns);
    2638           2 :         gf_dump_svg_element(sdump, com->node, NULL, 0);
    2639           2 :         gf_fprintf(sdump->trace, "</%sNewScene>\n", lsrns);
    2640           2 :         return GF_OK;
    2641             : }
    2642             : 
    2643          62 : static GF_Err DumpLSRAddReplaceInsert(GF_SceneDumper *sdump, GF_Command *com)
    2644             : {
    2645             :         char szID[100];
    2646             :         Bool is_text = 0;
    2647             :         GF_CommandField *f;
    2648          62 :         char *lsrns = sd_get_lsr_namespace(com->in_scene);
    2649             : 
    2650          62 :         const char *com_name = (com->tag==GF_SG_LSR_REPLACE) ? "Replace" : ( (com->tag==GF_SG_LSR_ADD) ? "Add" : "Insert" );
    2651             : 
    2652          62 :         DUMP_IND(sdump);
    2653             : 
    2654          62 :         gf_fprintf(sdump->trace, "<%s%s ref=\"%s\" ", lsrns, com_name, lsr_format_node_id(com->node, com->RouteID, szID));
    2655          62 :         f = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    2656          62 :         if (f && (f->pos>=0) ) gf_fprintf(sdump->trace, "index=\"%d\" ", f->pos);
    2657          62 :         if (f) {
    2658             :                 GF_FieldInfo info;
    2659          62 :                 if (!f->new_node && !f->node_list) {
    2660             :                         char *att_name = NULL;
    2661          52 :                         if (f->fieldType==SVG_Transform_Scale_datatype) att_name = "scale";
    2662          52 :                         else if (f->fieldType==SVG_Transform_Rotate_datatype) att_name = "rotation";
    2663          52 :                         else if (f->fieldType==SVG_Transform_Translate_datatype) att_name = "translation";
    2664          52 :                         else if (f->fieldIndex==(u32) -1) att_name = "textContent";
    2665          52 :                         else att_name = (char*) gf_svg_get_attribute_name(com->node, f->fieldIndex);
    2666             : 
    2667          52 :                         gf_fprintf(sdump->trace, "attributeName=\"%s\" ", att_name);
    2668          52 :                         if (f->field_ptr) {
    2669             :                                 char *att;
    2670          50 :                                 info.far_ptr = f->field_ptr;
    2671          50 :                                 info.fieldIndex = f->fieldIndex;
    2672          50 :                                 info.fieldType = f->fieldType;
    2673          50 :                                 info.name = att_name;
    2674             : 
    2675          50 :                                 if ((s32) f->pos >= 0) {
    2676          12 :                                         att = gf_svg_dump_attribute_indexed(com->node, &info);
    2677             :                                 } else {
    2678          38 :                                         att = gf_svg_dump_attribute(com->node, &info);
    2679             :                                 }
    2680          50 :                                 gf_fprintf(sdump->trace, "value=\"%s\" ", att ? att : "");
    2681          50 :                                 if (att) gf_free(att);
    2682             :                         }
    2683             : 
    2684          52 :                         if (com->fromNodeID) {
    2685             :                                 GF_FieldInfo op_info;
    2686           2 :                                 GF_Node *op = gf_sg_find_node(sdump->sg, com->fromNodeID);
    2687           2 :                                 gf_fprintf(sdump->trace, "operandElementId=\"%s\" ", lsr_format_node_id(op, com->RouteID, szID));
    2688           2 :                                 gf_node_get_field(op, com->fromFieldIndex, &op_info);
    2689           2 :                                 gf_fprintf(sdump->trace, "operandAttributeName=\"%s\" ", op_info.name);
    2690             :                         }
    2691             : 
    2692          52 :                         gf_fprintf(sdump->trace, "/>\n");
    2693          52 :                         return GF_OK;
    2694             :                 }
    2695          10 :                 if (f->new_node && f->new_node->sgprivate->tag==TAG_DOMText) is_text = 1;
    2696             :                 /*if fieldIndex (eg attributeName) is set, this is children replacement*/
    2697          10 :                 if (f->fieldIndex>0)
    2698           0 :                         gf_fprintf(sdump->trace, "attributeName=\"children\" ");
    2699             :         }
    2700             : 
    2701             : 
    2702          10 :         gf_fprintf(sdump->trace, ">");
    2703          10 :         if (!is_text) {
    2704           6 :                 gf_fprintf(sdump->trace, "\n");
    2705           6 :                 sdump->indent++;
    2706             :         }
    2707          10 :         if (f) {
    2708          10 :                 if (f->new_node) {
    2709           8 :                         gf_dump_svg_element(sdump, f->new_node, com->node, 0);
    2710           2 :                 } else if (f->node_list) {
    2711             :                         GF_ChildNodeItem *list = f->node_list;
    2712          80 :                         while (list) {
    2713          78 :                                 gf_dump_svg_element(sdump, list->node, com->node, 0);
    2714          78 :                                 list = list->next;
    2715             :                         }
    2716             :                 }
    2717             :         }
    2718          10 :         if (!is_text) {
    2719           6 :                 sdump->indent--;
    2720           6 :                 DUMP_IND(sdump);
    2721             :         }
    2722          10 :         gf_fprintf(sdump->trace, "</%s%s>\n", lsrns, com_name);
    2723          10 :         return GF_OK;
    2724             : }
    2725             : 
    2726           6 : static GF_Err DumpLSRDelete(GF_SceneDumper *sdump, GF_Command *com)
    2727             : {
    2728             :         char szID[1024];
    2729             :         GF_CommandField *f;
    2730           6 :         char *lsrns = sd_get_lsr_namespace(com->in_scene);
    2731           6 :         DUMP_IND(sdump);
    2732           6 :         gf_fprintf(sdump->trace, "<%sDelete ref=\"%s\" ", lsrns, lsr_format_node_id(com->node, com->RouteID, szID));
    2733           6 :         f = (GF_CommandField *) gf_list_get(com->command_fields, 0);
    2734           6 :         if (f && (f->pos>=0) ) gf_fprintf(sdump->trace, "index=\"%d\" ", f->pos);
    2735           6 :         gf_fprintf(sdump->trace, "/>\n");
    2736           6 :         return GF_OK;
    2737             : }
    2738             : #ifdef GPAC_UNUSED_FUNC
    2739             : static GF_Err DumpLSRInsert(GF_SceneDumper *sdump, GF_Command *com)
    2740             : {
    2741             :         return GF_OK;
    2742             : }
    2743             : 
    2744             : static GF_Err SD_SetSceneGraph(GF_SceneDumper *sdump, GF_SceneGraph *sg)
    2745             : {
    2746             :         if (sdump) sdump->sg = sg;
    2747             :         return GF_OK;
    2748             : }
    2749             : 
    2750             : static GF_Err DumpLSRClean(GF_SceneDumper *sdump, GF_Command *com)
    2751             : {
    2752             :         return GF_OK;
    2753             : }
    2754             : 
    2755             : static GF_Err DumpLSRRestore(GF_SceneDumper *sdump, GF_Command *com)
    2756             : {
    2757             :         return GF_OK;
    2758             : }
    2759             : static GF_Err DumpLSRSave(GF_SceneDumper *sdump, GF_Command *com)
    2760             : {
    2761             :         return GF_OK;
    2762             : }
    2763             : #endif /*GPAC_UNUSED_FUNC*/
    2764             : 
    2765         108 : static GF_Err DumpLSRSendEvent(GF_SceneDumper *sdump, GF_Command *com)
    2766             : {
    2767             :         char szID[1024];
    2768         108 :         char *lsrns = sd_get_lsr_namespace(com->in_scene);
    2769         108 :         DUMP_IND(sdump);
    2770         108 :         gf_fprintf(sdump->trace, "<%sSendEvent ref=\"%s\" event=\"%s\"", lsrns,
    2771             :                 lsr_format_node_id(com->node, com->RouteID, szID),
    2772         108 :                 gf_dom_event_get_name(com->send_event_name)
    2773             :                );
    2774         108 :         if (com->send_event_name <= GF_EVENT_MOUSEWHEEL)
    2775          12 :                 gf_fprintf(sdump->trace, " pointvalue=\"%g %g\"", FIX2FLT(com->send_event_x), FIX2FLT(com->send_event_y) );
    2776             : 
    2777         108 :         switch (com->send_event_name) {
    2778          52 :         case GF_EVENT_KEYDOWN:
    2779             :         case GF_EVENT_LONGKEYPRESS:
    2780             :         case GF_EVENT_REPEAT_KEY:
    2781             :         case GF_EVENT_SHORT_ACCESSKEY:
    2782          52 :                 if (com->send_event_integer) {
    2783          50 :                         gf_fprintf(sdump->trace, " stringvalue=\"%s\"", gf_dom_get_key_name(com->send_event_integer) );
    2784          50 :                         break;
    2785             :                 }
    2786             :         default:
    2787          58 :                 if (com->send_event_integer)
    2788           6 :                         gf_fprintf(sdump->trace, " intvalue=\"%d\"", com->send_event_integer);
    2789          58 :                 if (com->send_event_string)
    2790           0 :                         gf_fprintf(sdump->trace, " stringvalue=\"%s\"", com->send_event_string);
    2791             :                 break;
    2792             :         }
    2793             : 
    2794         108 :         gf_fprintf(sdump->trace, "/>\n");
    2795         108 :         return GF_OK;
    2796             : }
    2797           4 : static GF_Err DumpLSRActivate(GF_SceneDumper *sdump, GF_Command *com)
    2798             : {
    2799             :         char szID[1024];
    2800           4 :         char *lsrns = sd_get_lsr_namespace(com->in_scene);
    2801           4 :         DUMP_IND(sdump);
    2802           4 :         if (com->tag==GF_SG_LSR_ACTIVATE) {
    2803           2 :                 gf_fprintf(sdump->trace, "<%sActivate ref=\"%s\" />\n", lsrns, lsr_format_node_id(com->node, com->RouteID, szID));
    2804             :         } else {
    2805           2 :                 gf_fprintf(sdump->trace, "<%sDeactivate ref=\"%s\" />\n", lsrns, lsr_format_node_id(com->node, com->RouteID, szID));
    2806             :         }
    2807           4 :         return GF_OK;
    2808             : }
    2809             : 
    2810             : #endif
    2811             : 
    2812             : GF_EXPORT
    2813         207 : GF_Err gf_sm_dump_command_list(GF_SceneDumper *sdump, GF_List *comList, u32 indent, Bool skip_first_replace)
    2814             : {
    2815             :         GF_Err e;
    2816             :         u32 i, count;
    2817             :         u32 prev_ind;
    2818             : #ifndef GPAC_DISABLE_VRML
    2819             :         u32 remain = 0, has_scene_replace = 0;
    2820             : #endif
    2821             :         Bool prev_skip;
    2822             : 
    2823         207 :         if (!sdump || !sdump->trace|| !comList || !sdump->sg) return GF_BAD_PARAM;
    2824             : 
    2825         207 :         prev_skip = sdump->skip_scene_replace;
    2826         207 :         sdump->skip_scene_replace = skip_first_replace;
    2827         207 :         prev_ind  = sdump->indent;
    2828         207 :         sdump->indent = indent;
    2829             : 
    2830             :         e = GF_OK;
    2831         207 :         count = gf_list_count(comList);
    2832         854 :         for (i=0; i<count; i++) {
    2833         654 :                 GF_Command *com = (GF_Command *) gf_list_get(comList, i);
    2834        1308 :                 if (i
    2835             : #ifndef GPAC_DISABLE_VRML
    2836         654 :                         && !remain
    2837             : #endif
    2838         391 :                         && (sdump->X3DDump || (sdump->dump_mode==GF_SM_DUMP_VRML))
    2839             :                 ) {
    2840           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[Scene Dump] MPEG-4 Commands found, not supported in %s - skipping\n", sdump->X3DDump ? "X3D" : "VRML"));
    2841             :                         break;
    2842             :                 }
    2843             : #ifndef GPAC_DISABLE_VRML
    2844         654 :                 if (has_scene_replace && (com->tag != GF_SG_ROUTE_INSERT)) {
    2845             :                         has_scene_replace = 0;
    2846           2 :                         if (sdump->XMLDump) {
    2847           2 :                                 sdump->indent--;
    2848           2 :                                 EndElement(sdump, "Scene", 1);
    2849           2 :                                 sdump->indent--;
    2850           2 :                                 EndElement(sdump, "Replace", 1);
    2851             :                         } else {
    2852           0 :                                 DUMP_IND(sdump);
    2853           0 :                                 gf_fprintf(sdump->trace, "\nAT 0 {\n");
    2854           0 :                                 sdump->indent++;
    2855             :                         }
    2856             :                 }
    2857             : #endif
    2858             : 
    2859         654 :                 switch (com->tag) {
    2860             : #ifndef GPAC_DISABLE_VRML
    2861             :                 /*insert commands*/
    2862          45 :                 case GF_SG_NODE_INSERT:
    2863          45 :                         e = DumpNodeInsert(sdump, com);
    2864          45 :                         break;
    2865           4 :                 case GF_SG_INDEXED_INSERT:
    2866           4 :                         e = DumpIndexInsert(sdump, com);
    2867           4 :                         break;
    2868          63 :                 case GF_SG_ROUTE_INSERT:
    2869          63 :                         e = DumpRouteInsert(sdump, com, has_scene_replace);
    2870          63 :                         if (remain) remain--;
    2871             :                         break;
    2872             :                 /*delete commands*/
    2873           9 :                 case GF_SG_NODE_DELETE:
    2874           9 :                         e = DumpNodeDelete(sdump, com);
    2875           9 :                         break;
    2876           9 :                 case GF_SG_INDEXED_DELETE:
    2877           9 :                         e = DumpIndexDelete(sdump, com);
    2878           9 :                         break;
    2879           9 :                 case GF_SG_ROUTE_DELETE:
    2880           9 :                         e = DumpRouteDelete(sdump, com);
    2881           9 :                         break;
    2882             :                 /*replace commands*/
    2883          45 :                 case GF_SG_NODE_REPLACE:
    2884          45 :                         e = DumpNodeReplace(sdump, com);
    2885          45 :                         break;
    2886         133 :                 case GF_SG_FIELD_REPLACE:
    2887         133 :                         e = DumpFieldReplace(sdump, com);
    2888         133 :                         break;
    2889          27 :                 case GF_SG_INDEXED_REPLACE:
    2890          27 :                         e = DumpIndexReplace(sdump, com);
    2891          27 :                         break;
    2892           9 :                 case GF_SG_ROUTE_REPLACE:
    2893           9 :                         e = DumpRouteReplace(sdump, com);
    2894           9 :                         break;
    2895          18 :                 case GF_SG_XREPLACE:
    2896          18 :                         e = DumpXReplace(sdump, com);
    2897          18 :                         break;
    2898          35 :                 case GF_SG_SCENE_REPLACE:
    2899             :                         /*we don't support replace scene in conditional*/
    2900             :                         assert(!sdump->current_com_list);
    2901          35 :                         sdump->current_com_list = comList;
    2902          35 :                         e = DumpSceneReplace(sdump, com);
    2903          35 :                         sdump->current_com_list = NULL;
    2904             :                         has_scene_replace = 1;
    2905          35 :                         remain = count - i - 1;
    2906          35 :                         break;
    2907             :                 /*extended commands*/
    2908           9 :                 case GF_SG_PROTO_INSERT:
    2909           9 :                         e = DumpProtoInsert(sdump, com);
    2910           9 :                         break;
    2911           9 :                 case GF_SG_PROTO_DELETE_ALL:
    2912           9 :                         DUMP_IND(sdump);
    2913           9 :                         if (sdump->XMLDump) {
    2914           5 :                                 gf_fprintf(sdump->trace, "<Delete extended=\"allProtos\"/>\n");
    2915             :                         } else {
    2916           4 :                                 gf_fprintf(sdump->trace, "DELETEPROTO ALL\n");
    2917             :                         }
    2918             :                         e = GF_OK;
    2919             :                         break;
    2920           9 :                 case GF_SG_PROTO_DELETE:
    2921             :                 {
    2922             :                         u32 j;
    2923           9 :                         DUMP_IND(sdump);
    2924           9 :                         if (sdump->XMLDump) {
    2925           5 :                                 gf_fprintf(sdump->trace, "<Delete extended=\"protos\" value=\"");
    2926             :                         } else {
    2927           4 :                                 gf_fprintf(sdump->trace, "DELETEPROTO [");
    2928             :                         }
    2929           9 :                         for (j=0; j<com->del_proto_list_size; j++) {
    2930           9 :                                 if (j) gf_fprintf(sdump->trace, " ");
    2931           9 :                                 gf_fprintf(sdump->trace, "%d", com->del_proto_list[j]);
    2932             :                         }
    2933           9 :                         if (sdump->XMLDump) {
    2934           5 :                                 gf_fprintf(sdump->trace, "\"/>\n");
    2935             :                         } else {
    2936           4 :                                 gf_fprintf(sdump->trace, "]\n");
    2937             :                         }
    2938             :                         e = GF_OK;
    2939             :                 }
    2940             :                 break;
    2941           9 :                 case GF_SG_GLOBAL_QUANTIZER:
    2942           9 :                         e = DumpGlobalQP(sdump, com);
    2943           9 :                         break;
    2944          12 :                 case GF_SG_MULTIPLE_REPLACE:
    2945          12 :                         e = DumpMultipleReplace(sdump, com);
    2946          12 :                         break;
    2947           9 :                 case GF_SG_MULTIPLE_INDEXED_REPLACE:
    2948           9 :                         e = DumpMultipleIndexedReplace(sdump, com);
    2949           9 :                         break;
    2950           9 :                 case GF_SG_NODE_DELETE_EX:
    2951           9 :                         e = DumpNodeDelete(sdump, com);
    2952           9 :                         break;
    2953             : 
    2954             : #endif
    2955             : 
    2956             : 
    2957             : #ifndef GPAC_DISABLE_SVG
    2958             :                 /*laser commands*/
    2959           2 :                 case GF_SG_LSR_NEW_SCENE:
    2960           2 :                         e = DumpLSRNewScene(sdump, com);
    2961           2 :                         break;
    2962           0 :                 case GF_SG_LSR_ADD:
    2963           0 :                         e = DumpLSRAddReplaceInsert(sdump, com);
    2964           0 :                         break;
    2965             :                 case GF_SG_LSR_CLEAN:
    2966             :                         //e = DumpLSRClean(sdump, com);
    2967             :                         break;
    2968          58 :                 case GF_SG_LSR_REPLACE:
    2969          58 :                         e = DumpLSRAddReplaceInsert(sdump, com);
    2970          58 :                         break;
    2971           6 :                 case GF_SG_LSR_DELETE:
    2972           6 :                         e = DumpLSRDelete(sdump, com);
    2973           6 :                         break;
    2974           4 :                 case GF_SG_LSR_INSERT:
    2975           4 :                         e = DumpLSRAddReplaceInsert(sdump, com);
    2976           4 :                         break;
    2977             :                 case GF_SG_LSR_RESTORE:
    2978             :                         //e = DumpLSRRestore(sdump, com);
    2979             :                         break;
    2980             :                 case GF_SG_LSR_SAVE:
    2981             :                         //e = DumpLSRSave(sdump, com);
    2982             :                         break;
    2983         108 :                 case GF_SG_LSR_SEND_EVENT:
    2984         108 :                         e = DumpLSRSendEvent(sdump, com);
    2985         108 :                         break;
    2986           4 :                 case GF_SG_LSR_ACTIVATE:
    2987             :                 case GF_SG_LSR_DEACTIVATE:
    2988           4 :                         e = DumpLSRActivate(sdump, com);
    2989           4 :                         break;
    2990             : #endif
    2991             :                 }
    2992         654 :                 if (e) break;
    2993             : 
    2994             : 
    2995         647 :                 if (sdump->skip_scene_replace
    2996             : #ifndef GPAC_DISABLE_VRML
    2997          44 :                         && !has_scene_replace
    2998             : #endif
    2999             :                 ) {
    3000           2 :                         sdump->skip_scene_replace = 0;
    3001           2 :                         if (!sdump->XMLDump && (i+1<count)) {
    3002           0 :                                 DUMP_IND(sdump);
    3003           0 :                                 gf_fprintf(sdump->trace, "\nAT 0 {\n");
    3004           0 :                                 sdump->indent++;
    3005             :                         }
    3006             :                 }
    3007             :         }
    3008             : 
    3009             : #ifndef GPAC_DISABLE_VRML
    3010         207 :         if (remain && !sdump->XMLDump) {
    3011           0 :                 sdump->indent--;
    3012           0 :                 DUMP_IND(sdump);
    3013           0 :                 gf_fprintf(sdump->trace, "}\n");
    3014             :         }
    3015             : #endif
    3016             : 
    3017         207 :         if (has_scene_replace && sdump->XMLDump) {
    3018          17 :                 sdump->indent--;
    3019          17 :                 if (!sdump->X3DDump) {
    3020          17 :                         EndElement(sdump, "Scene", 1);
    3021          17 :                         sdump->indent--;
    3022          17 :                         EndElement(sdump, "Replace", 1);
    3023             :                 }
    3024             :         }
    3025             : 
    3026         207 :         sdump->indent = prev_ind;
    3027         207 :         sdump->skip_scene_replace = prev_skip;
    3028         207 :         return e;
    3029             : }
    3030             : 
    3031             : #ifndef GPAC_DISABLE_SVG
    3032         382 : void gf_dump_svg_element(GF_SceneDumper *sdump, GF_Node *n, GF_Node *parent, Bool is_root)
    3033             : {
    3034             :         GF_ChildNodeItem *list;
    3035             :         char attName[100], *attValue;
    3036             :         u32 nID;
    3037             :         SVG_Element *svg = (SVG_Element *)n;
    3038             :         GF_FieldInfo info;
    3039             :         SVGAttribute *att;
    3040             :         u32 tag, ns;
    3041         696 :         if (!n) return;
    3042             : 
    3043         382 :         nID = gf_node_get_id(n);
    3044         382 :         tag = n->sgprivate->tag;
    3045             :         /*remove undef listener/handlers*/
    3046         382 :         if (!nID) {
    3047         308 :                 switch (tag) {
    3048             :                 case TAG_SVG_listener:
    3049             :                         if ((0) && gf_node_get_attribute_by_tag(n, TAG_XMLEV_ATT_handler, 0, 0, &info)==GF_OK) {
    3050             :                                 if (((XMLRI*)info.far_ptr)->target && !gf_node_get_id(((XMLRI*)info.far_ptr)->target) )
    3051             :                                         return;
    3052             :                         }
    3053             :                         break;
    3054           0 :                 case TAG_SVG_handler:
    3055             :                         /*this handler was not declared in the graph*/
    3056           0 :                         if (!n->sgprivate->parents || (n->sgprivate->parents->node != parent))
    3057             :                                 return;
    3058             :                         break;
    3059          28 :                 case TAG_DOMText:
    3060             :                 {
    3061             :                         GF_DOMText *txt = (GF_DOMText *)n;
    3062          28 :                         if (txt->textContent) {
    3063          28 :                                 if ((txt->type==GF_DOM_TEXT_CDATA)
    3064          28 :                                         || (parent && (parent->sgprivate->tag == TAG_SVG_script))
    3065          28 :                                         || (parent && (parent->sgprivate->tag == TAG_SVG_handler))
    3066             :                                 ) {
    3067           0 :                                         gf_fprintf(sdump->trace, "<![CDATA[");
    3068           0 :                                         gf_fprintf(sdump->trace, "%s", txt->textContent);
    3069           0 :                                         gf_fprintf(sdump->trace, "]]>");
    3070          28 :                                 } else if (txt->type==GF_DOM_TEXT_REGULAR) {
    3071          28 :                                         scene_dump_utf_string(sdump, 0, txt->textContent);
    3072             :                                 }
    3073             :                         }
    3074             :                 }
    3075             :                 return;
    3076             :                 }
    3077             :         }
    3078             : 
    3079         354 :         if (!sdump->in_text) {
    3080         354 :                 DUMP_IND(sdump);
    3081             :         }
    3082             : 
    3083             :         /*register all namespaces specified on this element */
    3084         354 :         gf_xml_push_namespaces((GF_DOMNode *)n);
    3085             : 
    3086         354 :         gf_fprintf(sdump->trace, "<%s", gf_node_get_class_name(n));
    3087         354 :         ns = gf_xml_get_element_namespace(n);
    3088             : 
    3089         354 :         if (nID) {
    3090             :                 char attID[100];
    3091          74 :                 gf_fprintf(sdump->trace, " id=\"%s\"", lsr_format_node_id(n, 0, attID));
    3092             :         }
    3093         354 :         att = svg->attributes;
    3094        1966 :         while (att) {
    3095        1258 :                 if (att->data_type==SVG_ID_datatype) {
    3096           0 :                         att = att->next;
    3097           0 :                         continue;
    3098             :                 }
    3099             : 
    3100        1258 :                 info.fieldIndex = att->tag;
    3101        1258 :                 info.fieldType = att->data_type;
    3102        1258 :                 if (att->tag==TAG_DOM_ATT_any) {
    3103           0 :                         u32 att_ns = ((GF_DOMFullAttribute*)att)->xmlns;
    3104           0 :                         info.name = ((GF_DOMFullAttribute*)att)->name;
    3105           0 :                         if ((att_ns != ns) && strncmp(info.name, "xmlns", 5)) {
    3106           0 :                                 sprintf(attName, "%s:%s", gf_sg_get_namespace_qname(gf_node_get_graph(n), att_ns), ((GF_DOMFullAttribute*)att)->name);
    3107           0 :                                 info.name = attName;
    3108             :                         }
    3109             :                 } else {
    3110        1258 :                         info.name = gf_svg_get_attribute_name(n, att->tag);
    3111             :                 }
    3112             : 
    3113        1258 :                 if (att->data_type==XMLRI_datatype) {
    3114         116 :                         XMLRI *xlink = (XMLRI *)att->data;
    3115         116 :                         if (xlink->type==XMLRI_ELEMENTID) {
    3116          94 :                                 if (!xlink->target || !gf_node_get_id((GF_Node*)xlink->target) ) {
    3117          28 :                                         att = att->next;
    3118          28 :                                         continue;
    3119             :                                 }
    3120          66 :                                 if (parent && (parent == (GF_Node *) xlink->target)) {
    3121          30 :                                         att = att->next;
    3122          30 :                                         continue;
    3123             :                                 }
    3124             :                         }
    3125          22 :                         else if (xlink->type==XMLRI_STREAMID) {
    3126           2 :                                 gf_fprintf(sdump->trace, " %s=\"#stream%d\"", info.name, xlink->lsr_stream_id);
    3127           2 :                                 att = att->next;
    3128           2 :                                 continue;
    3129             :                         } else {
    3130          20 :                                 gf_fprintf(sdump->trace, " %s=\"%s\"", info.name, xlink->string);
    3131          20 :                                 att = att->next;
    3132          20 :                                 continue;
    3133             :                         }
    3134             :                 }
    3135        1178 :                 info.far_ptr = att->data;
    3136        1178 :                 attValue = gf_svg_dump_attribute((GF_Node*)svg, &info);
    3137        1178 :                 if (attValue) {
    3138        1178 :                         if (/*strcmp(info.name, "xmlns") &&*/ (info.fieldType = (u32) strlen(attValue)))
    3139        1064 :                                 gf_fprintf(sdump->trace, " %s=\"%s\"", info.name, attValue);
    3140        1178 :                         gf_free(attValue);
    3141             :                 }
    3142        1178 :                 att = att->next;
    3143             :         }
    3144             : 
    3145         354 :         gf_dom_event_dump_listeners(n, sdump->trace);
    3146         354 :         if (svg->children) {
    3147          72 :                 gf_fprintf(sdump->trace, ">");
    3148             :         } else {
    3149         282 :                 gf_fprintf(sdump->trace, "/>");
    3150         282 :                 return;
    3151             :         }
    3152             : 
    3153          72 :         if (n->sgprivate->tag==TAG_LSR_conditional) {
    3154           4 :                 GF_DOMUpdates *up = svg->children ? (GF_DOMUpdates *)svg->children->node : NULL;
    3155           4 :                 sdump->indent++;
    3156           4 :                 if (up && (up->sgprivate->tag==TAG_DOMUpdates)) {
    3157           4 :                         if (gf_list_count(up->updates)) {
    3158           2 :                                 gf_fprintf(sdump->trace, "\n");
    3159           2 :                                 gf_sm_dump_command_list(sdump, up->updates, sdump->indent, 0);
    3160           2 :                         } else if (up->data) {
    3161           0 :                                 gf_fprintf(sdump->trace, "<!-- WARNING: LASeR scripts cannot be dumped at run-time -->\n");
    3162             :                         }
    3163             :                 }
    3164           4 :                 sdump->indent--;
    3165           4 :                 DUMP_IND(sdump);
    3166           4 :                 gf_fprintf(sdump->trace, "</%s>\n", gf_node_get_class_name(n));
    3167           4 :                 return;
    3168             :         }
    3169             : 
    3170          68 :         if (tag==TAG_SVG_text || tag==TAG_SVG_textArea) sdump->in_text = 1;
    3171          68 :         sdump->indent++;
    3172          68 :         list = svg->children;
    3173         430 :         while (list) {
    3174         294 :                 if (!sdump->in_text) gf_fprintf(sdump->trace, "\n");
    3175         294 :                 gf_dump_svg_element(sdump, list->node, n, 0);
    3176         294 :                 list = list->next;
    3177             :         }
    3178          68 :         if (!sdump->in_text) gf_fprintf(sdump->trace, "\n");
    3179          68 :         sdump->indent--;
    3180          68 :         if (!sdump->in_text) DUMP_IND(sdump);
    3181          68 :         gf_fprintf(sdump->trace, "</%s>", gf_node_get_class_name(n));
    3182          68 :         if (tag==TAG_SVG_text || tag==TAG_SVG_textArea) sdump->in_text = 0;
    3183             :         /*removes all namespaces specified on this element */
    3184          68 :         gf_xml_pop_namespaces((GF_DOMNode *)n);
    3185             : }
    3186             : #endif
    3187             : 
    3188           6 : static void gf_sm_dump_saf_hdr(GF_SceneDumper *dumper, char *unit_name, u64 au_time, Bool is_rap)
    3189             : {
    3190           6 :         gf_fprintf(dumper->trace, "<saf:%s", unit_name);
    3191           6 :         if (au_time) gf_fprintf(dumper->trace, " time=\""LLD"\"", au_time);
    3192           6 :         if (is_rap) gf_fprintf(dumper->trace, " rap=\"true\"");
    3193           6 :         gf_fprintf(dumper->trace, ">\n");
    3194           6 : }
    3195             : 
    3196           1 : static void dump_od_to_saf(GF_SceneDumper *dumper, GF_AUContext *au, u32 indent)
    3197             : {
    3198             :         u32 i, count;
    3199             : 
    3200           1 :         count = gf_list_count(au->commands);
    3201           1 :         for (i=0; i<count; i++) {
    3202             :                 u32 j, c2;
    3203           1 :                 GF_ODUpdate *com = (GF_ODUpdate *)gf_list_get(au->commands, i);
    3204           1 :                 if (com->tag != GF_ODF_OD_UPDATE_TAG) continue;
    3205             : 
    3206           1 :                 c2 = gf_list_count(com->objectDescriptors);
    3207           1 :                 for (j=0; j<c2; j++) {
    3208           1 :                         GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(com->objectDescriptors, j);
    3209           1 :                         GF_ESD *esd = (GF_ESD *) gf_list_get(od->ESDescriptors, 0);
    3210             :                         GF_MuxInfo *mux;
    3211           1 :                         if (!esd) {
    3212           1 :                                 if (od->URLString) {
    3213           1 :                                         gf_fprintf(dumper->trace, "<saf:RemoteStreamHeader streamID=\"stream%d\" url=\"%s\"", au->owner->ESID, od->URLString);
    3214           1 :                                         if (au->timing) gf_fprintf(dumper->trace, " time=\""LLD"\"", au->timing);
    3215           1 :                                         gf_fprintf(dumper->trace, "/>\n");
    3216             :                                 }
    3217           1 :                                 continue;
    3218             :                         }
    3219           0 :                         mux = (GF_MuxInfo *)gf_list_get(esd->extensionDescriptors, 0);
    3220           0 :                         if (!mux || (mux->tag!=GF_ODF_MUXINFO_TAG)) mux = NULL;
    3221             : 
    3222             : 
    3223           0 :                         gf_fprintf(dumper->trace, "<saf:mediaHeader streamID=\"stream%d\"", esd->ESID);
    3224           0 :                         gf_fprintf(dumper->trace, " streamType=\"%d\" objectTypeIndication=\"%d\" timeStampResolution=\"%d\"", esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication, au->owner->timeScale);
    3225           0 :                         if (au->timing) gf_fprintf(dumper->trace, " time=\""LLD"\"", au->timing);
    3226           0 :                         if (mux && mux->file_name) gf_fprintf(dumper->trace, " source=\"%s\"", mux->file_name);
    3227           0 :                         gf_fprintf(dumper->trace, "/>\n");
    3228             :                 }
    3229             : 
    3230             : 
    3231             :         }
    3232           1 :         gf_fprintf(dumper->trace, "</saf:mediaUnit>\n");
    3233           1 : }
    3234             : 
    3235             : #ifndef GPAC_DISABLE_SVG
    3236           0 : static GF_Err SD_DumpDOMElement(GF_SceneDumper *sdump, GF_DOMFullNode *node)
    3237             : {
    3238             :         const char *ns;
    3239             :         u32 child_type = 0;
    3240             :         GF_DOMFullAttribute *att;
    3241             :         GF_ChildNodeItem *child;
    3242             :         GF_DOMText *txt;
    3243           0 :         ns = gf_sg_get_namespace_qname(node->sgprivate->scenegraph, node->ns);
    3244             : 
    3245           0 :         DUMP_IND(sdump);
    3246           0 :         if (ns) gf_fprintf(sdump->trace, "<%s:%s", ns, node->name);
    3247           0 :         else gf_fprintf(sdump->trace, "<%s", node->name);
    3248           0 :         att = (GF_DOMFullAttribute *)node->attributes;
    3249           0 :         while (att) {
    3250           0 :                 gf_fprintf(sdump->trace, " %s=\"%s\"", att->name, (char *) att->data);
    3251           0 :                 att = (GF_DOMFullAttribute *)att->next;
    3252             :         }
    3253           0 :         if (!node->children) {
    3254           0 :                 gf_fprintf(sdump->trace, "/>\n");
    3255           0 :                 return GF_OK;
    3256             :         }
    3257           0 :         gf_fprintf(sdump->trace, ">");
    3258           0 :         sdump->indent++;
    3259           0 :         child = node->children;
    3260           0 :         while (child) {
    3261           0 :                 switch(child->node->sgprivate->tag) {
    3262           0 :                 case TAG_DOMFullNode:
    3263           0 :                         if (!child_type) gf_fprintf(sdump->trace, "\n");
    3264             :                         child_type = 1;
    3265           0 :                         SD_DumpDOMElement(sdump, (GF_DOMFullNode*)child->node);
    3266           0 :                         break;
    3267           0 :                 case TAG_DOMText:
    3268             :                         child_type = 2;
    3269             :                         txt = (GF_DOMText *)child->node;
    3270           0 :                         if (txt->type==GF_DOM_TEXT_REGULAR) {
    3271           0 :                                 scene_dump_utf_string(sdump, 0, txt->textContent);
    3272           0 :                         } else if (txt->type==GF_DOM_TEXT_CDATA) {
    3273           0 :                                 gf_fprintf(sdump->trace, "<![CDATA[");
    3274           0 :                                 gf_fprintf(sdump->trace, "%s", txt->textContent);
    3275           0 :                                 gf_fprintf(sdump->trace, "]]>");
    3276             :                         }
    3277             :                         break;
    3278             :                 }
    3279           0 :                 child = child->next;
    3280             :         }
    3281             : 
    3282           0 :         sdump->indent--;
    3283           0 :         if (child_type!=2) {
    3284           0 :                 DUMP_IND(sdump);
    3285             :         }
    3286             : 
    3287           0 :         if (ns) gf_fprintf(sdump->trace, "</%s:%s>\n", ns, node->name);
    3288           0 :         else gf_fprintf(sdump->trace, "</%s>\n", node->name);
    3289             : 
    3290             :         return GF_OK;
    3291             : }
    3292             : #endif
    3293             : 
    3294             : GF_EXPORT
    3295           2 : GF_Err gf_sm_dump_graph(GF_SceneDumper *sdump, Bool skip_proto, Bool skip_routes)
    3296             : {
    3297             :         u32 tag;
    3298           2 :         if (!sdump->trace || !sdump->sg || !sdump->sg->RootNode) return GF_BAD_PARAM;
    3299             : 
    3300           2 :         tag = sdump->sg->RootNode->sgprivate->tag;
    3301             : 
    3302           2 :         if (tag<=GF_NODE_RANGE_LAST_X3D) {
    3303           2 :                 gf_dump_setup(sdump, NULL);
    3304             : 
    3305           2 :                 if (sdump->XMLDump) {
    3306           0 :                         StartElement(sdump, "Scene");
    3307           0 :                         EndElementHeader(sdump, 1);
    3308           0 :                         sdump->indent++;
    3309             :                 }
    3310             : 
    3311             : #ifndef GPAC_DISABLE_VRML
    3312             :                 GF_Err e;
    3313           2 :                 if (!skip_proto) {
    3314           2 :                         e = DumpProtos(sdump, sdump->sg->protos);
    3315           2 :                         if (e) return e;
    3316             :                 }
    3317             : 
    3318           2 :                 if (sdump->X3DDump) {
    3319           0 :                         GF_ChildNodeItem *list = ((GF_ParentNode *)sdump->sg->RootNode)->children;
    3320           0 :                         while (list) {
    3321           0 :                                 gf_dump_vrml_node(sdump, list->node, 0, NULL);
    3322           0 :                                 list = list->next;
    3323             :                         }
    3324             :                 } else {
    3325           2 :                         gf_dump_vrml_node(sdump, sdump->sg->RootNode, 0, NULL);
    3326             :                 }
    3327           2 :                 if (!sdump->XMLDump) gf_fprintf(sdump->trace, "\n\n");
    3328           2 :                 if (!skip_routes) {
    3329             :                         GF_Route *r;
    3330           2 :                         u32 i=0;
    3331           4 :                         while ((r = (GF_Route*)gf_list_enum(sdump->sg->Routes, &i))) {
    3332           0 :                                 if (r->IS_route || (r->graph!=sdump->sg)) continue;
    3333           0 :                                 e = gf_dump_vrml_route(sdump, r, 0);
    3334           0 :                                 if (e) return e;
    3335             :                         }
    3336             :                 }
    3337           2 :                 if (sdump->XMLDump) {
    3338           0 :                         sdump->indent--;
    3339           0 :                         EndElement(sdump, "Scene", 1);
    3340             :                 }
    3341             : #endif /*GPAC_DISABLE_VRML*/
    3342             : 
    3343           2 :                 gf_dump_finalize(sdump, NULL);
    3344           2 :                 return GF_OK;
    3345             :         }
    3346             : #ifndef GPAC_DISABLE_SVG
    3347           0 :         else if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) {
    3348           0 :                 sdump->dump_mode = GF_SM_DUMP_SVG;
    3349           0 :                 gf_dump_setup(sdump, NULL);
    3350           0 :                 gf_dump_svg_element(sdump, sdump->sg->RootNode, NULL, 1);
    3351           0 :                 return GF_OK;
    3352             :         }
    3353           0 :         else if (tag==TAG_DOMFullNode) {
    3354           0 :                 sdump->dump_mode = GF_SM_DUMP_XML;
    3355           0 :                 gf_dump_setup(sdump, NULL);
    3356           0 :                 SD_DumpDOMElement(sdump, (GF_DOMFullNode*)sdump->sg->RootNode);
    3357             :         }
    3358             : #endif
    3359             : 
    3360             :         return GF_OK;
    3361             : }
    3362             : 
    3363             : 
    3364             : 
    3365             : 
    3366         194 : static void ReorderAUContext(GF_List *sample_list, GF_AUContext *au, Bool lsr_dump)
    3367             : {
    3368             :         u64 autime, time;
    3369             :         u32 i;
    3370             :         Bool has_base;
    3371             :         GF_AUContext *ptr;
    3372             : 
    3373             :         /*
    3374             :                 this happens when converting from bt to xmt
    3375             :                 NOTE: Comment is wrong? this happens when just loading BT
    3376             :         */
    3377         194 :         if (!au->timing_sec) {
    3378          69 :                 au->timing_sec = (Double) (s64) au->timing;
    3379             :                 /* Hack to avoid timescale=0 which happens when loading a BT with no SLConfig*/
    3380          69 :                 if (!au->owner->timeScale) au->owner->timeScale = 1000;
    3381          69 :                 au->timing_sec /= au->owner->timeScale;
    3382             :         }
    3383             :         /*this happens when converting from xmt to bt*/
    3384         194 :         if (!au->timing) {
    3385             :                 assert(au->owner->timeScale);
    3386          51 :                 au->timing = (u64) (au->timing_sec * au->owner->timeScale);
    3387             :         }
    3388             : 
    3389         194 :         autime = au->timing + au->owner->imp_exp_time;
    3390             :         has_base = 0;
    3391         194 :         i=0;
    3392        1412 :         while ((ptr = (GF_AUContext*)gf_list_enum(sample_list, &i))) {
    3393        1065 :                 time = ptr->timing + ptr->owner->imp_exp_time;
    3394        1065 :                 if (
    3395             :                     /*time ordered*/
    3396             :                     (time > autime)
    3397             :                     /*set bifs first for first AU*/
    3398        1025 :                     || (!has_base && (time == autime) && (ptr->owner->streamType < au->owner->streamType) )
    3399             :                     /*set OD first for laser*/
    3400        1024 :                     || (lsr_dump && (au->owner->streamType==GF_STREAM_OD))
    3401             :                 ) {
    3402          41 :                         gf_list_insert(sample_list, au, i-1);
    3403          41 :                         return;
    3404             :                 }
    3405             : 
    3406             :                 has_base = 0;
    3407        1024 :                 if ( (ptr->owner->streamType == au->owner->streamType) && (time == autime) ) has_base = 1;
    3408             :         }
    3409         153 :         gf_list_add(sample_list, au);
    3410             : }
    3411             : 
    3412             : 
    3413             : GF_EXPORT
    3414          17 : GF_Err gf_sm_dump(GF_SceneManager *ctx, char *rad_name, Bool is_final_name, GF_SceneDumpFormat dump_mode)
    3415             : {
    3416             :         GF_Err e;
    3417             :         GF_List *sample_list;
    3418             :         Bool first_par;
    3419             :         u32 i, j, indent, num_scene, num_od, first_bifs, num_tracks;
    3420             :         Double time;
    3421             :         GF_SceneDumper *dumper;
    3422             :         GF_StreamContext *sc;
    3423             :         GF_AUContext *au;
    3424             :         Bool no_root_found = 1;
    3425             : 
    3426          17 :         sample_list = gf_list_new();
    3427             : 
    3428             :         num_scene = num_od = 0;
    3429             :         num_tracks = 0;
    3430             :         indent = 0;
    3431          17 :         dumper = gf_sm_dumper_new(ctx->scene_graph, rad_name, is_final_name, ' ', dump_mode);
    3432             :         e = GF_OK;
    3433             :         /*configure all systems streams we're dumping*/
    3434          17 :         i=0;
    3435          82 :         while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) {
    3436             : 
    3437          48 :                 switch (sc->streamType) {
    3438          18 :                 case GF_STREAM_SCENE:
    3439          18 :                         num_scene ++;
    3440             :                         num_tracks ++;
    3441          18 :                         break;
    3442          16 :                 case GF_STREAM_OD:
    3443          16 :                         num_od ++;
    3444             :                         num_tracks ++;
    3445          16 :                         break;
    3446          14 :                 default:
    3447          14 :                         continue;
    3448             :                 }
    3449             : 
    3450          34 :                 j=0;
    3451         262 :                 while ((au = (GF_AUContext*)gf_list_enum(sc->AUs, &j))) {
    3452         194 :                         ReorderAUContext(sample_list, au, dumper->LSRDump);
    3453         194 :                         if (dumper->dump_mode==GF_SM_DUMP_SVG) break;
    3454             :                 }
    3455          34 :                 if (dumper->dump_mode==GF_SM_DUMP_SVG) break;
    3456             :         }
    3457          17 :         first_bifs = (num_scene==1) ? 1 : 0;
    3458          17 :         num_scene = (num_scene>1) ? 1 : 0;
    3459          17 :         num_od = (num_od>1) ? 1 : 0;
    3460             : 
    3461          17 :         gf_dump_setup(dumper, (GF_Descriptor *) ctx->root_od);
    3462             : 
    3463             : #ifndef GPAC_DISABLE_SVG
    3464          17 :         if (dumper->dump_mode==GF_SM_DUMP_SVG) {
    3465           0 :                 au = (GF_AUContext*)gf_list_get(sample_list, 0);
    3466             :                 GF_Command *com = NULL;
    3467           0 :                 if (au) com = (GF_Command*)gf_list_get(au->commands, 0);
    3468           0 :                 if (!au) {
    3469           0 :                         gf_dump_svg_element(dumper, dumper->sg->RootNode, NULL, 1);
    3470           0 :                 } else if (!com || (com->tag!=GF_SG_LSR_NEW_SCENE) || !com->node) {
    3471             :                         e = GF_NOT_SUPPORTED;
    3472             :                 } else {
    3473           0 :                         gf_dump_svg_element(dumper, com->node, NULL, 1);
    3474             :                 }
    3475           0 :                 gf_dump_finalize(dumper, (GF_Descriptor *) ctx->root_od);
    3476           0 :                 gf_sm_dumper_del(dumper);
    3477           0 :                 gf_list_del(sample_list);
    3478           0 :                 return e;
    3479             :         }
    3480             : #endif
    3481             : 
    3482          17 :         time = dumper->LSRDump ? -1 : 0;
    3483             :         first_par = 0;
    3484             : 
    3485         211 :         while (gf_list_count(sample_list)) {
    3486         194 :                 au = (GF_AUContext*)gf_list_get(sample_list, 0);
    3487         194 :                 gf_list_rem(sample_list, 0);
    3488             : 
    3489         194 :                 if (!dumper->XMLDump) {
    3490             : 
    3491          86 :                         if (!first_bifs || (au->owner->streamType != GF_STREAM_SCENE) ) {
    3492          83 :                                 if (au->flags & GF_SM_AU_RAP) gf_fprintf(dumper->trace, "RAP ");
    3493          83 :                                 gf_fprintf(dumper->trace, "AT "LLD" ", au->timing);
    3494          83 :                                 if ( (au->owner->streamType==GF_STREAM_OD && num_od) || (au->owner->streamType==GF_STREAM_SCENE && num_scene)) {
    3495           2 :                                         gf_fprintf(dumper->trace, "IN %d ", au->owner->ESID);
    3496             :                                 }
    3497          83 :                                 gf_fprintf(dumper->trace, "{\n");
    3498          83 :                                 indent++;
    3499             :                         }
    3500             : 
    3501          86 :                         switch (au->owner->streamType) {
    3502          21 :                         case GF_STREAM_OD:
    3503          21 :                                 if (dumper->LSRDump) {
    3504           0 :                                         dump_od_to_saf(dumper, au, indent);
    3505             :                                 } else {
    3506             : #ifndef GPAC_DISABLE_OD_DUMP
    3507          21 :                                         e = gf_odf_dump_com_list(au->commands, dumper->trace, indent+1, 0);
    3508             : #endif
    3509             :                                 }
    3510             :                                 break;
    3511          65 :                         case GF_STREAM_SCENE:
    3512          65 :                                 e = gf_sm_dump_command_list(dumper, au->commands, indent, first_bifs);
    3513          65 :                                 break;
    3514             :                         }
    3515          86 :                         if (first_bifs) {
    3516             :                                 first_bifs = 0;
    3517           7 :                                 gf_fprintf(dumper->trace, "\n");
    3518             : 
    3519             :                         } else {
    3520          79 :                                 indent--;
    3521          79 :                                 gf_fprintf(dumper->trace, "}\n\n");
    3522             :                         }
    3523             :                 }
    3524             :                 else {
    3525         108 :                         if (dumper->LSRDump) {
    3526             : /*                              if (time != au->timing_sec) {
    3527             :                                         time = au->timing_sec;
    3528             :                                 }
    3529             : */
    3530         101 :                         } else if (!time && !num_scene && first_bifs) {
    3531          89 :                         } else if (num_scene || num_od) {
    3532           0 :                                 if (!first_par) {
    3533             :                                         first_par = 1;
    3534           0 :                                         indent += 1;
    3535             :                                 } else {
    3536           0 :                                         gf_fprintf(dumper->trace, " </par>\n");
    3537             :                                 }
    3538           0 :                                 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");
    3539          89 :                         } else if (au->timing_sec>time) {
    3540          82 :                                 if (!first_par) {
    3541             :                                         first_par = 1;
    3542           5 :                                         indent += 1;
    3543             :                                 } else {
    3544          77 :                                         gf_fprintf(dumper->trace, " </par>\n");
    3545             :                                 }
    3546          82 :                                 gf_fprintf(dumper->trace, "<par begin=\"%g\">\n", au->timing_sec);
    3547             :                         }
    3548         108 :                         switch (au->owner->streamType) {
    3549          25 :                         case GF_STREAM_OD:
    3550          25 :                                 if (dumper->LSRDump) {
    3551           1 :                                         dump_od_to_saf(dumper, au, indent+1);
    3552             :                                 } else {
    3553             : #ifndef GPAC_DISABLE_OD_DUMP
    3554          24 :                                         e = gf_odf_dump_com_list(au->commands, dumper->trace, indent+1, 1);
    3555             : #endif
    3556             :                                 }
    3557             :                                 break;
    3558          83 :                         case GF_STREAM_SCENE:
    3559          83 :                                 if (gf_list_count(au->commands)) {
    3560          83 :                                         if (dumper->LSRDump)
    3561           6 :                                                 gf_sm_dump_saf_hdr(dumper, "sceneUnit", au->timing, au->flags & GF_SM_AU_RAP);
    3562             : 
    3563          83 :                                         e = gf_sm_dump_command_list(dumper, au->commands, indent+1, first_bifs);
    3564             :                                         first_bifs = 0;
    3565             :                                         no_root_found = 0;
    3566             : 
    3567          83 :                                         if (dumper->LSRDump)
    3568           6 :                                                 gf_fprintf(dumper->trace, "</saf:sceneUnit>\n");
    3569             :                                 }
    3570             :                                 break;
    3571             :                         }
    3572         108 :                         time = au->timing_sec;
    3573             :                 }
    3574         194 :                 if (dumper->X3DDump || (dumper->dump_mode==GF_SM_DUMP_VRML)) break;
    3575             :         }
    3576             : 
    3577             : #ifndef GPAC_DISABLE_VRML
    3578          17 :         if (no_root_found && ctx->scene_graph->RootNode) {
    3579             :                 GF_Route *r;
    3580           0 :                 DumpProtos(dumper, ctx->scene_graph->protos);
    3581           0 :                 gf_dump_vrml_node(dumper, ctx->scene_graph->RootNode, 0, NULL);
    3582           0 :                 i=0;
    3583           0 :                 gf_fprintf(dumper->trace, "\n");
    3584           0 :                 while ((r = (GF_Route*)gf_list_enum(dumper->sg->Routes, &i))) {
    3585           0 :                         if (r->IS_route || (r->graph!=dumper->sg)) continue;
    3586           0 :                         e = gf_dump_vrml_route(dumper, r, 0);
    3587           0 :                         if (e) return e;
    3588             :                 }
    3589             :         }
    3590             : #endif
    3591             : 
    3592             : 
    3593             :         /*close command*/
    3594          17 :         if (!dumper->X3DDump && first_par) gf_fprintf(dumper->trace, " </par>\n");
    3595             : 
    3596          17 :         if (gf_list_count(sample_list) && (dumper->X3DDump || (dumper->dump_mode==GF_SM_DUMP_VRML)) ) {
    3597           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[Scene Dump] MPEG-4 Commands found, not supported in %s - skipping\n", dumper->X3DDump ? "X3D" : "VRML"));
    3598             :         }
    3599             : 
    3600          17 :         gf_dump_finalize(dumper, (GF_Descriptor *) ctx->root_od);
    3601          17 :         gf_sm_dumper_del(dumper);
    3602          17 :         gf_list_del(sample_list);
    3603          17 :         return e;
    3604             : }
    3605             : 
    3606             : #endif /*GPAC_DISABLE_SCENE_DUMP*/

Generated by: LCOV version 1.13