LCOV - code coverage report
Current view: top level - scenegraph - commands.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 284 525 54.1 %
Date: 2021-04-29 23:48:07 Functions: 7 8 87.5 %

          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 Graph 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             : 
      27             : #include <gpac/internal/scenegraph_dev.h>
      28             : /*MPEG4 tags (for internal nodes)*/
      29             : #include <gpac/nodes_mpeg4.h>
      30             : 
      31             : #include <gpac/internal/laser_dev.h>
      32             : 
      33             : 
      34             : GF_EXPORT
      35        8369 : GF_Command *gf_sg_command_new(GF_SceneGraph *graph, u32 tag)
      36             : {
      37             :         GF_Command *ptr;
      38        8369 :         GF_SAFEALLOC(ptr, GF_Command);
      39        8369 :         if (!ptr) return NULL;
      40        8369 :         ptr->tag = tag;
      41        8369 :         ptr->in_scene = graph;
      42        8369 :         ptr->command_fields = gf_list_new();
      43        8369 :         if (tag < GF_SG_LAST_BIFS_COMMAND) ptr->new_proto_list = gf_list_new();
      44             :         return ptr;
      45             : }
      46             : 
      47             : GF_EXPORT
      48        8369 : void gf_sg_command_del(GF_Command *com)
      49             : {
      50             : #ifndef GPAC_DISABLE_VRML
      51             :         u32 i;
      52             :         GF_Proto *proto;
      53             : #endif
      54        8369 :         if (!com) return;
      55             : 
      56        8369 :         if (com->tag < GF_SG_LAST_BIFS_COMMAND) {
      57             : #ifndef GPAC_DISABLE_VRML
      58       13864 :                 while (gf_list_count(com->command_fields)) {
      59        5859 :                         GF_CommandField *inf = (GF_CommandField *)gf_list_get(com->command_fields, 0);
      60        5859 :                         gf_list_rem(com->command_fields, 0);
      61             : 
      62        5859 :                         switch (inf->fieldType) {
      63        4323 :                         case GF_SG_VRML_SFNODE:
      64        4323 :                                 if (inf->new_node) gf_node_try_destroy(com->in_scene, inf->new_node, NULL);
      65             :                                 break;
      66          18 :                         case GF_SG_VRML_MFNODE:
      67          18 :                                 if (inf->field_ptr) {
      68             :                                         GF_ChildNodeItem *child;
      69          18 :                                         child = inf->node_list;
      70          54 :                                         while (child) {
      71             :                                                 GF_ChildNodeItem *cur = child;
      72          18 :                                                 gf_node_try_destroy(com->in_scene, child->node, NULL);
      73          18 :                                                 child = child->next;
      74          18 :                                                 gf_free(cur);
      75             :                                         }
      76             :                                 }
      77             :                                 break;
      78        1518 :                         default:
      79        1518 :                                 if (inf->field_ptr) gf_sg_vrml_field_pointer_del(inf->field_ptr, inf->fieldType);
      80             :                                 break;
      81             :                         }
      82        5859 :                         gf_free(inf);
      83             :                 }
      84             : #endif
      85             :         } else {
      86             : #ifndef GPAC_DISABLE_SVG
      87         492 :                 while (gf_list_count(com->command_fields)) {
      88         128 :                         GF_CommandField *inf = (GF_CommandField *)gf_list_get(com->command_fields, 0);
      89         128 :                         gf_list_rem(com->command_fields, 0);
      90             : 
      91         128 :                         if (inf->new_node) gf_node_unregister(inf->new_node, NULL);
      92         114 :                         else if (inf->node_list) {
      93             :                                 GF_ChildNodeItem *child;
      94             :                                 child = inf->node_list;
      95         166 :                                 while (child) {
      96             :                                         GF_ChildNodeItem *cur = child;
      97         160 :                                         gf_node_try_destroy(com->in_scene, child->node, NULL);
      98         160 :                                         child = child->next;
      99         160 :                                         gf_free(cur);
     100             :                                 }
     101         108 :                         } else if (inf->field_ptr) {
     102         100 :                                 gf_svg_delete_attribute_value(inf->fieldType, inf->field_ptr, com->in_scene);
     103             :                         }
     104         128 :                         gf_free(inf);
     105             :                 }
     106             : #endif
     107             :         }
     108        8369 :         gf_list_del(com->command_fields);
     109             : 
     110             : #ifndef GPAC_DISABLE_VRML
     111        8369 :         i=0;
     112       16797 :         while ((proto = (GF_Proto*)gf_list_enum(com->new_proto_list, &i))) {
     113          59 :                 gf_sg_proto_del(proto);
     114             :         }
     115        8369 :         gf_list_del(com->new_proto_list);
     116             : #endif
     117             : 
     118        8369 :         if (com->node) {
     119        6230 :                 gf_node_try_destroy(com->in_scene, com->node, NULL);
     120             :         }
     121             : 
     122        8369 :         if (com->del_proto_list) gf_free(com->del_proto_list);
     123        8369 :         if (com->def_name) gf_free(com->def_name);
     124        8369 :         if (com->scripts_to_load) gf_list_del(com->scripts_to_load);
     125        8369 :         if (com->unres_name) gf_free(com->unres_name);
     126        8369 :         gf_free(com);
     127             : }
     128             : 
     129         649 : static void SG_CheckFieldChange(GF_Node *node, GF_FieldInfo *field)
     130             : {
     131             :         /*and propagate eventIn if any*/
     132         649 :         if (field->on_event_in) {
     133         116 :                 field->on_event_in(node, NULL);
     134             :         }
     135             : #ifndef GPAC_DISABLE_VRML
     136         533 :         else if ((field->eventType==GF_SG_EVENT_IN) && (gf_node_get_tag(node) == TAG_MPEG4_Script)) {
     137           4 :                 gf_sg_script_event_in(node, field);
     138             :         }
     139             :         else {
     140             :                 /*Notify eventOut in all cases to handle protos*/
     141         529 :                 gf_node_event_out(node, field->fieldIndex);
     142             :         }
     143             : #endif
     144             :         /*signal node modif*/
     145         649 :         gf_node_changed(node, field);
     146         649 : }
     147             : 
     148             : #ifndef GPAC_DISABLE_SVG
     149           0 : static void gf_node_unregister_children_deactivate(GF_Node *container, GF_ChildNodeItem *child)
     150             : {
     151           0 :         while (child) {
     152             :                 GF_ChildNodeItem *cur;
     153           0 :                 gf_node_unregister(child->node, container);
     154           0 :                 gf_node_deactivate(child->node);
     155             :                 cur = child;
     156           0 :                 child = child->next;
     157           0 :                 gf_free(cur);
     158             :         }
     159           0 : }
     160             : #endif
     161             : 
     162             : 
     163             : GF_EXPORT
     164        2609 : GF_Err gf_sg_command_apply(GF_SceneGraph *graph, GF_Command *com, Double time_offset)
     165             : {
     166             :         GF_Err e;
     167             : #if !defined(GPAC_DISABLE_VRML) || !defined(GPAC_DISABLE_SVG)
     168             :         GF_CommandField *inf;
     169             :         GF_Node *node;
     170             : #endif
     171             : 
     172             : #ifndef GPAC_DISABLE_VRML
     173             :         GF_FieldInfo field;
     174             :         void *slot_ptr;
     175             :         GF_Node *def;
     176             : #endif
     177             : 
     178        2609 :         if (!com || !graph) return GF_BAD_PARAM;
     179             : 
     180        2609 :         if (com->never_apply) return GF_OK;
     181             : 
     182             :         e = GF_OK;
     183        2609 :         switch (com->tag) {
     184             : #ifndef GPAC_DISABLE_VRML
     185         414 :         case GF_SG_SCENE_REPLACE:
     186             :                 /*unregister root*/
     187         414 :                 gf_node_unregister(graph->RootNode, NULL);
     188             :                 /*remove all protos and routes*/
     189         840 :                 while (gf_list_count(graph->routes_to_activate))
     190          12 :                         gf_list_rem(graph->routes_to_activate, 0);
     191             : 
     192         414 :                 if (!com->aggregated) {
     193             :                         /*destroy all routes*/
     194         449 :                         while (gf_list_count(graph->Routes)) {
     195          36 :                                 GF_Route *r = (GF_Route *)gf_list_get(graph->Routes, 0);
     196             :                                 /*this will unregister the route from the graph, so don't delete the chain entry*/
     197          36 :                                 gf_sg_route_del(r);
     198             :                         }
     199             :                         /*destroy all proto*/
     200         413 :                         while (gf_list_count(graph->protos)) {
     201           0 :                                 GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
     202             :                                 /*this will unregister the proto from the graph, so don't delete the chain entry*/
     203           0 :                                 gf_sg_proto_del(p);
     204             :                         }
     205             :                 }
     206             :                 /*DO NOT TOUCH node registry*/
     207             :                 /*DO NOT TOUCH UNREGISTERED PROTOS*/
     208             : 
     209             :                 /*if no protos (previously aggregated command) create proto list*/
     210         414 :                 if (!graph->protos) graph->protos = gf_list_new();
     211             : 
     212             :                 /*move all protos in graph*/
     213         488 :                 while (gf_list_count(com->new_proto_list)) {
     214          74 :                         GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
     215          74 :                         gf_list_rem(com->new_proto_list, 0);
     216          74 :                         gf_list_del_item(graph->unregistered_protos, p);
     217          74 :                         gf_list_add(graph->protos, p);
     218             :                 }
     219             :                 /*assign new root (no need to register/unregister)*/
     220         414 :                 graph->RootNode = com->node;
     221         414 :                 com->node = NULL;
     222             :                 break;
     223             : 
     224          46 :         case GF_SG_NODE_REPLACE:
     225          46 :                 if (!gf_list_count(com->command_fields)) return GF_OK;
     226          40 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     227          40 :                 e = gf_node_replace(com->node, inf->new_node, 0);
     228             :                 //TOCHECK - this is commented as registering shouldn't happen (already done at command creation) and creates mem leak
     229             : //              if (inf->new_node) gf_node_register(inf->new_node, NULL);
     230          40 :                 break;
     231             : 
     232         493 :         case GF_SG_MULTIPLE_REPLACE:
     233             :         case GF_SG_FIELD_REPLACE:
     234             :         {
     235             :                 u32 j;
     236             :                 GF_ChildNodeItem *list, *cur, *prev;
     237         493 :                 j=0;
     238        1497 :                 while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &j))) {
     239         511 :                         e = gf_node_get_field(com->node, inf->fieldIndex, &field);
     240         511 :                         if (e) return e;
     241             : 
     242         511 :                         switch (field.fieldType) {
     243          16 :                         case GF_SG_VRML_SFNODE:
     244             :                         {
     245          16 :                                 node = *((GF_Node **) field.far_ptr);
     246          16 :                                 e = gf_node_unregister(node, com->node);
     247          16 :                                 *((GF_Node **) field.far_ptr) = inf->new_node;
     248          16 :                                 if (!e) gf_node_register(inf->new_node, com->node);
     249             :                                 break;
     250             :                         }
     251           6 :                         case GF_SG_VRML_MFNODE:
     252           6 :                                 gf_node_unregister_children(com->node, * ((GF_ChildNodeItem **) field.far_ptr));
     253           6 :                                 * ((GF_ChildNodeItem **) field.far_ptr) = NULL;
     254             : 
     255           6 :                                 list = * ((GF_ChildNodeItem **) inf->field_ptr);
     256             :                                 prev=NULL;
     257          18 :                                 while (list) {
     258           6 :                                         cur = gf_malloc(sizeof(GF_ChildNodeItem));
     259           6 :                                         cur->next = NULL;
     260           6 :                                         cur->node = list->node;
     261           6 :                                         if (prev) {
     262           0 :                                                 prev->next = cur;
     263             :                                         } else {
     264           6 :                                                 * ((GF_ChildNodeItem **) field.far_ptr) = cur;
     265             :                                         }
     266           6 :                                         gf_node_register(list->node, com->node);
     267             :                                         prev = cur;
     268           6 :                                         list = list->next;
     269             :                                 }
     270             :                                 break;
     271           0 :                         case GF_SG_VRML_SFCOMMANDBUFFER:
     272             :                         {
     273             :                                 u32 i, count;
     274             :                                 GF_SceneGraph *sg;
     275           0 :                                 SFCommandBuffer *cb_dst = (SFCommandBuffer *)field.far_ptr;
     276           0 :                                 SFCommandBuffer *cb_src = (SFCommandBuffer *)inf->field_ptr;
     277             : 
     278             :                                 /*reset dest*/
     279           0 :                                 if (!cb_dst->commandList) cb_dst->commandList = gf_list_new();
     280             : 
     281           0 :                                 while (gf_list_count(cb_dst->commandList)) {
     282           0 :                                         GF_Command *sub_com = (GF_Command *)gf_list_get(cb_dst->commandList, 0);
     283           0 :                                         gf_sg_command_del(sub_com);
     284           0 :                                         gf_list_rem(cb_dst->commandList, 0);
     285             :                                 }
     286           0 :                                 if (cb_dst->buffer) {
     287           0 :                                         gf_free(cb_dst->buffer);
     288           0 :                                         cb_dst->buffer = NULL;
     289             :                                 }
     290             : 
     291             :                                 /*clone command list*/
     292           0 :                                 sg = gf_node_get_graph(com->node);
     293           0 :                                 count = gf_list_count(cb_src->commandList);
     294           0 :                                 for (i=0; i<count; i++) {
     295           0 :                                         GF_Command *sub_com = (GF_Command *)gf_list_get(cb_src->commandList, i);
     296           0 :                                         GF_Command *new_com = gf_sg_vrml_command_clone(sub_com, sg, 0);
     297           0 :                                         gf_list_add(cb_dst->commandList, new_com);
     298             :                                 }
     299             :                         }
     300             :                         break;
     301             : 
     302         489 :                         default:
     303             :                                 /*this is a regular field, reset it and clone - we cannot switch pointers since the
     304             :                                 original fields are NOT pointers*/
     305         489 :                                 if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
     306          51 :                                         e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
     307             :                                 }
     308         489 :                                 if (e) return e;
     309         489 :                                 gf_sg_vrml_field_copy(field.far_ptr, inf->field_ptr, field.fieldType);
     310             : 
     311         489 :                                 if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
     312          56 :                                         *(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
     313             :                                 break;
     314             :                         }
     315         511 :                         SG_CheckFieldChange(com->node, &field);
     316             :                 }
     317         493 :                 break;
     318             :         }
     319             : 
     320          84 :         case GF_SG_MULTIPLE_INDEXED_REPLACE:
     321             :         case GF_SG_INDEXED_REPLACE:
     322             :         {
     323          84 :                 u32 sftype, i=0;
     324         270 :                 while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &i))) {
     325         102 :                         e = gf_node_get_field(com->node, inf->fieldIndex, &field);
     326         102 :                         if (e) return e;
     327             : 
     328             :                         /*if MFNode remove the child and set new node*/
     329         102 :                         if (field.fieldType == GF_SG_VRML_MFNODE) {
     330             :                                 /*we must remove the node before in case the new node uses the same ID (not forbidden) and this
     331             :                                 command removes the last instance of the node with the same ID*/
     332          23 :                                 gf_node_replace_child(com->node, (GF_ChildNodeItem**) field.far_ptr, inf->pos, inf->new_node);
     333          23 :                                 if (inf->new_node) gf_node_register(inf->new_node, NULL);
     334             :                         }
     335             :                         /*erase the field item*/
     336             :                         else {
     337          79 :                                 if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
     338           9 :                                         inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
     339             :                                         /*may happen with text and default value*/
     340           9 :                                         if (inf->pos < 0) {
     341           0 :                                                 inf->pos = 0;
     342           0 :                                                 gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
     343             :                                         }
     344             :                                 }
     345          79 :                                 e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
     346          79 :                                 if (e) return e;
     347          79 :                                 sftype = gf_sg_vrml_get_sf_type(field.fieldType);
     348          79 :                                 gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
     349             :                                 /*note we don't add time offset, since there's no MFTime*/
     350             :                         }
     351         102 :                         SG_CheckFieldChange(com->node, &field);
     352             :                 }
     353          84 :                 break;
     354             :         }
     355          17 :         case GF_SG_ROUTE_REPLACE:
     356             :         {
     357             :                 GF_Route *r;
     358             :                 char *name;
     359          17 :                 r = gf_sg_route_find(graph, com->RouteID);
     360          17 :                 def = gf_sg_find_node(graph, com->fromNodeID);
     361          17 :                 node = gf_sg_find_node(graph, com->toNodeID);
     362          17 :                 if (!node || !def) return GF_SG_UNKNOWN_NODE;
     363             :                 name = NULL;
     364          17 :                 if (r) {
     365          17 :                         name = r->name;
     366          17 :                         r->name = NULL;
     367          17 :                         gf_sg_route_del(r);
     368             :                 }
     369          17 :                 r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
     370          17 :                 gf_sg_route_set_id(r, com->RouteID);
     371          17 :                 if (name) {
     372          17 :                         gf_sg_route_set_name(r, name);
     373          17 :                         gf_free(name);
     374             :                 }
     375             :                 break;
     376             :         }
     377          33 :         case GF_SG_NODE_DELETE_EX:
     378             :         case GF_SG_NODE_DELETE:
     379             :         {
     380          33 :                 if (com->node) gf_node_replace(com->node, NULL, (com->tag==GF_SG_NODE_DELETE_EX) ? 1 : 0);
     381             :                 break;
     382             :         }
     383          35 :         case GF_SG_ROUTE_DELETE:
     384             :         {
     385          35 :                 return gf_sg_route_del_by_id(graph, com->RouteID);
     386             :         }
     387           9 :         case GF_SG_INDEXED_DELETE:
     388             :         {
     389           9 :                 if (!gf_list_count(com->command_fields)) return GF_OK;
     390           9 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     391             : 
     392           9 :                 e = gf_node_get_field(com->node, inf->fieldIndex, &field);
     393           9 :                 if (e) return e;
     394           9 :                 if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM;
     395             : 
     396             :                 /*then we need special handling in case of a node*/
     397           9 :                 if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFNODE) {
     398           0 :                         e = gf_node_replace_child(com->node, (GF_ChildNodeItem **) field.far_ptr, inf->pos, NULL);
     399             :                 } else {
     400           9 :                         if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
     401           0 :                                 inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
     402             :                         }
     403             :                         /*this is a regular MFField, just remove the item (gf_realloc)*/
     404           9 :                         e = gf_sg_vrml_mf_remove(field.far_ptr, field.fieldType, inf->pos);
     405             :                 }
     406             :                 /*deletion -> node has changed*/
     407           9 :                 if (!e) SG_CheckFieldChange(com->node, &field);
     408             :                 break;
     409             :         }
     410          70 :         case GF_SG_NODE_INSERT:
     411             :         {
     412          70 :                 if (!gf_list_count(com->command_fields)) return GF_OK;
     413          70 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     414             : 
     415          70 :                 e = gf_node_insert_child(com->node, inf->new_node, inf->pos);
     416          70 :                 if (!e) e = gf_node_register(inf->new_node, com->node);
     417          70 :                 if (!e) {
     418          70 :                         gf_node_event_out(com->node, inf->fieldIndex);
     419          70 :                         gf_node_changed(com->node, NULL);
     420             :                 }
     421             :                 break;
     422             :         }
     423        1345 :         case GF_SG_ROUTE_INSERT:
     424             :         {
     425             :                 GF_Route *r;
     426        1345 :                 def = gf_sg_find_node(graph, com->fromNodeID);
     427        1345 :                 node = gf_sg_find_node(graph, com->toNodeID);
     428        1345 :                 if (!node || !def) return GF_SG_UNKNOWN_NODE;
     429        1345 :                 r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
     430        1345 :                 if (com->RouteID) gf_sg_route_set_id(r, com->RouteID);
     431        1345 :                 if (com->def_name) {
     432          44 :                         gf_sg_route_set_name(r, com->def_name);
     433          44 :                         gf_free(com->def_name);
     434          44 :                         com->def_name = NULL;
     435             :                 }
     436             :                 break;
     437             :         }
     438           9 :         case GF_SG_INDEXED_INSERT:
     439             :         {
     440             :                 u32 sftype;
     441           9 :                 if (!gf_list_count(com->command_fields)) return GF_OK;
     442           9 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     443           9 :                 e = gf_node_get_field(com->node, inf->fieldIndex, &field);
     444           9 :                 if (e) return e;
     445             : 
     446             :                 /*rescale the MFField and parse the SFField*/
     447           9 :                 if (field.fieldType != GF_SG_VRML_MFNODE) {
     448           9 :                         if (inf->pos == -1) {
     449           0 :                                 e = gf_sg_vrml_mf_append(field.far_ptr, field.fieldType, & slot_ptr);
     450             :                         } else {
     451           9 :                                 e = gf_sg_vrml_mf_insert(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
     452             :                         }
     453           9 :                         if (e) return e;
     454           9 :                         sftype = gf_sg_vrml_get_sf_type(field.fieldType);
     455           9 :                         gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
     456             :                 } else {
     457           0 :                         if (inf->new_node) {
     458           0 :                                 if (inf->pos == -1) {
     459           0 :                                         gf_node_list_add_child( (GF_ChildNodeItem **) field.far_ptr, inf->new_node);
     460             :                                 } else {
     461           0 :                                         gf_node_list_insert_child((GF_ChildNodeItem **) field.far_ptr, inf->new_node, inf->pos);
     462             :                                 }
     463           0 :                                 gf_node_register(inf->new_node, com->node);
     464             :                         }
     465             :                 }
     466           9 :                 if (!e) SG_CheckFieldChange(com->node, &field);
     467             :                 break;
     468             :         }
     469             :         case GF_SG_PROTO_INSERT:
     470             :                 /*destroy all proto*/
     471          18 :                 while (gf_list_count(com->new_proto_list)) {
     472           9 :                         GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
     473           9 :                         gf_list_rem(com->new_proto_list, 0);
     474           9 :                         gf_list_del_item(graph->unregistered_protos, p);
     475           9 :                         gf_list_add(graph->protos, p);
     476             :                 }
     477             :                 return GF_OK;
     478             :         case GF_SG_PROTO_DELETE:
     479             :         {
     480             :                 u32 i;
     481           9 :                 for (i=0; i<com->del_proto_list_size; i++) {
     482             :                         /*note this will check for unregistered protos, but since IDs are unique we are sure we will
     483             :                         not destroy an unregistered one*/
     484           9 :                         GF_Proto *proto = gf_sg_find_proto(graph, com->del_proto_list[i], NULL);
     485           9 :                         if (proto) gf_sg_proto_del(proto);
     486             :                 }
     487             :         }
     488             :         return GF_OK;
     489             :         case GF_SG_PROTO_DELETE_ALL:
     490             :                 /*destroy all proto*/
     491          27 :                 while (gf_list_count(graph->protos)) {
     492          18 :                         GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
     493          18 :                         gf_list_rem(graph->protos, 0);
     494             :                         /*this will unregister the proto from the graph, so don't delete the chain entry*/
     495          18 :                         gf_sg_proto_del(p);
     496             :                 }
     497             :                 /*DO NOT TOUCH UNREGISTERED PROTOS*/
     498             :                 return GF_OK;
     499          18 :         case GF_SG_XREPLACE:
     500             :         {
     501             :                 s32 pos = -2;
     502             :                 GF_Node *target = NULL;
     503             :                 GF_ChildNodeItem *list, *cur;
     504             :                 GF_FieldInfo value;
     505          18 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     506          18 :                 if (!inf) return GF_SG_UNKNOWN_NODE;
     507             : 
     508          18 :                 e = gf_node_get_field(com->node, inf->fieldIndex, &field);
     509          18 :                 if (e) return e;
     510          18 :                 target = com->node;
     511             : 
     512          18 :                 if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
     513             :                         GF_FieldInfo idxField;
     514           9 :                         if ((inf->pos != -2) || com->toNodeID) {
     515           9 :                                 if (com->toNodeID) {
     516           9 :                                         GF_Node *idxNode = gf_sg_find_node(graph, com->toNodeID);
     517           9 :                                         if (!idxNode) return GF_SG_UNKNOWN_NODE;
     518             : 
     519           9 :                                         if (gf_node_get_field(idxNode, com->toFieldIndex, &idxField) != GF_OK) return GF_OK;
     520             :                                         pos = 0;
     521           9 :                                         switch (idxField.fieldType) {
     522           0 :                                         case GF_SG_VRML_SFBOOL:
     523           0 :                                                 if (*(SFBool*)idxField.far_ptr) pos = 1;
     524             :                                                 break;
     525           9 :                                         case GF_SG_VRML_SFINT32:
     526           9 :                                                 if (*(SFInt32*)idxField.far_ptr >=0) pos = *(SFInt32*)idxField.far_ptr;
     527             :                                                 break;
     528           0 :                                         case GF_SG_VRML_SFFLOAT:
     529           0 :                                                 if ( (*(SFFloat *)idxField.far_ptr) >=0) pos = (s32) floor( FIX2FLT(*(SFFloat*)idxField.far_ptr) );
     530             :                                                 break;
     531           0 :                                         case GF_SG_VRML_SFTIME:
     532           0 :                                                 if ( (*(SFTime *)idxField.far_ptr) >=0) pos = (s32) floor( (*(SFTime *)idxField.far_ptr) );
     533             :                                                 break;
     534             :                                         }
     535             :                                 } else {
     536             :                                         pos = inf->pos;
     537             :                                 }
     538             :                         }
     539             :                 }
     540             :                 /*override target node*/
     541          18 :                 if ((field.fieldType==GF_SG_VRML_MFNODE) && (pos>=-1) && com->ChildNodeTag) {
     542           9 :                         target = gf_node_list_get_child(*(GF_ChildNodeItem **)field.far_ptr, pos);
     543           9 :                         if (!target) return GF_SG_UNKNOWN_NODE;
     544           9 :                         if (gf_node_get_field(target, com->child_field, &field) != GF_OK) return GF_SG_UNKNOWN_NODE;
     545             :                         pos=-2;
     546             :                 }
     547             : 
     548          18 :                 if (com->fromNodeID) {
     549           9 :                         GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
     550           9 :                         if (!fromNode) return GF_SG_UNKNOWN_NODE;
     551           9 :                         e = gf_node_get_field(fromNode, com->fromFieldIndex, &value);
     552           9 :                         if (e) return e;
     553             :                 } else {
     554           9 :                         value.far_ptr = inf->field_ptr;
     555           9 :                         value.fieldType = inf->fieldType;
     556             :                 }
     557             :                 /*indexed replacement*/
     558          18 :                 if (pos>=-1) {
     559             :                         /*if MFNode remove the child and set new node*/
     560           0 :                         if (field.fieldType == GF_SG_VRML_MFNODE) {
     561           0 :                                 GF_Node *nn = *(GF_Node**)value.far_ptr;
     562           0 :                                 gf_node_replace_child(target, (GF_ChildNodeItem**) field.far_ptr, pos, nn);
     563           0 :                                 if (nn) gf_node_register(nn, NULL);
     564             :                         }
     565             :                         /*erase the field item*/
     566             :                         else {
     567             :                                 u32 sftype;
     568           0 :                                 if ((pos < 0) || ((u32) pos >= ((GenMFField *) field.far_ptr)->count) ) {
     569           0 :                                         pos = ((GenMFField *)field.far_ptr)->count - 1;
     570             :                                         /*may happen with text and default value*/
     571           0 :                                         if (pos < 0) {
     572             :                                                 pos = 0;
     573           0 :                                                 gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
     574             :                                         }
     575             :                                 }
     576           0 :                                 e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, pos);
     577           0 :                                 if (e) return e;
     578           0 :                                 sftype = gf_sg_vrml_get_sf_type(field.fieldType);
     579           0 :                                 gf_sg_vrml_field_copy(slot_ptr, value.far_ptr, sftype);
     580             :                                 /*note we don't add time offset, since there's no MFTime*/
     581             :                         }
     582             :                 } else {
     583             :                         GF_ChildNodeItem *prev;
     584          18 :                         switch (field.fieldType) {
     585           0 :                         case GF_SG_VRML_SFNODE:
     586             :                         {
     587           0 :                                 node = *((GF_Node **) field.far_ptr);
     588           0 :                                 e = gf_node_unregister(node, target);
     589           0 :                                 *((GF_Node **) field.far_ptr) = *((GF_Node **) value.far_ptr) ;
     590           0 :                                 if (!e) gf_node_register(*(GF_Node **) value.far_ptr, target);
     591             :                                 break;
     592             :                         }
     593           0 :                         case GF_SG_VRML_MFNODE:
     594           0 :                                 gf_node_unregister_children(target, * ((GF_ChildNodeItem **) field.far_ptr));
     595           0 :                                 * ((GF_ChildNodeItem **) field.far_ptr) = NULL;
     596             : 
     597           0 :                                 list = * ((GF_ChildNodeItem **) value.far_ptr);
     598             :                                 prev=NULL;
     599           0 :                                 while (list) {
     600           0 :                                         cur = gf_malloc(sizeof(GF_ChildNodeItem));
     601           0 :                                         cur->next = NULL;
     602           0 :                                         cur->node = list->node;
     603           0 :                                         if (prev) {
     604           0 :                                                 prev->next = cur;
     605             :                                         } else {
     606           0 :                                                 * ((GF_ChildNodeItem **) field.far_ptr) = cur;
     607             :                                         }
     608           0 :                                         gf_node_register(list->node, target);
     609             :                                         prev = cur;
     610           0 :                                         list = list->next;
     611             :                                 }
     612             :                                 break;
     613             : 
     614          18 :                         default:
     615          18 :                                 if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
     616           0 :                                         e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
     617             :                                 }
     618          18 :                                 if (e) return e;
     619          18 :                                 gf_sg_vrml_field_clone(field.far_ptr, value.far_ptr, field.fieldType, graph);
     620             : 
     621          18 :                                 if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
     622           0 :                                         *(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
     623             :                                 break;
     624             :                         }
     625             :                 }
     626          18 :                 SG_CheckFieldChange(target, &field);
     627             :         }
     628          18 :         return GF_OK;
     629             :         /*only used by BIFS*/
     630             :         case GF_SG_GLOBAL_QUANTIZER:
     631             :                 return GF_OK;
     632             : 
     633             : #endif /*GPAC_DISABLE_VRML*/
     634             : 
     635             : 
     636             : #ifndef GPAC_DISABLE_SVG
     637             :         /*laser commands*/
     638           0 :         case GF_SG_LSR_NEW_SCENE:
     639             :                 /*DO NOT TOUCH node registry*/
     640             : 
     641             :                 /*assign new root (no need to register/unregister)*/
     642           0 :                 graph->RootNode = com->node;
     643           0 :                 com->node = NULL;
     644             :                 break;
     645           0 :         case GF_SG_LSR_DELETE:
     646           0 :                 if (!com->node) return GF_NON_COMPLIANT_BITSTREAM;
     647           0 :                 if (!gf_list_count(com->command_fields)) {
     648           0 :                         gf_node_replace(com->node, NULL, 0);
     649           0 :                         gf_node_deactivate(com->node);
     650           0 :                         return GF_OK;
     651             :                 }
     652           0 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     653           0 :                 node = gf_node_list_get_child(((SVG_Element *)com->node)->children, inf->pos);
     654           0 :                 if (node) {
     655           0 :                         e = gf_node_replace_child(com->node, &((SVG_Element *)com->node)->children, inf->pos, NULL);
     656           0 :                         gf_node_deactivate(node);
     657             :                 }
     658             :                 break;
     659           0 :         case GF_SG_LSR_INSERT:
     660           0 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     661           0 :                 if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
     662           0 :                 if (inf->new_node) {
     663           0 :                         if (inf->pos<0)
     664           0 :                                 gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
     665             :                         else
     666           0 :                                 gf_node_list_insert_child(& ((SVG_Element *)com->node)->children, inf->new_node, inf->pos);
     667             : 
     668           0 :                         gf_node_register(inf->new_node, com->node);
     669           0 :                         gf_node_activate(inf->new_node);
     670           0 :                         gf_node_changed(com->node, NULL);
     671             :                 } else {
     672             :                         /*NOT SUPPORTED*/
     673           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[LASeR] VALUE INSERTION NOT SUPPORTED\n"));
     674             :                 }
     675             :                 break;
     676           0 :         case GF_SG_LSR_ADD:
     677             :         case GF_SG_LSR_REPLACE:
     678           0 :                 inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
     679           0 :                 if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
     680           0 :                 if (inf->new_node) {
     681           0 :                         if (inf->pos<0) {
     682             :                                 /*if fieldIndex (eg attributeName) is set, this is children replacement*/
     683           0 :                                 if (inf->fieldIndex>0) {
     684           0 :                                         gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
     685           0 :                                         ((SVG_Element *)com->node)->children = NULL;
     686           0 :                                         gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
     687           0 :                                         gf_node_register(inf->new_node, com->node);
     688           0 :                                         gf_node_activate(inf->new_node);
     689             :                                 } else {
     690           0 :                                         e = gf_node_replace(com->node, inf->new_node, 0);
     691           0 :                                         gf_node_activate(inf->new_node);
     692             :                                 }
     693             :                         } else {
     694           0 :                                 node = gf_node_list_get_child( ((SVG_Element *)com->node)->children, inf->pos);
     695           0 :                                 gf_node_replace_child(com->node, & ((SVG_Element *)com->node)->children, inf->pos, inf->new_node);
     696           0 :                                 gf_node_register(inf->new_node, com->node);
     697           0 :                                 if (node) gf_node_deactivate(node);
     698           0 :                                 gf_node_activate(inf->new_node);
     699             :                         }
     700             :                         /*signal node modif*/
     701           0 :                         gf_node_changed(com->node, NULL);
     702           0 :                         return e;
     703           0 :                 } else if (inf->node_list) {
     704             :                         GF_ChildNodeItem *child, *cur, *prev;
     705           0 :                         gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
     706           0 :                         ((SVG_Element *)com->node)->children = NULL;
     707             : 
     708             :                         prev = NULL;
     709           0 :                         child = inf->node_list;
     710           0 :                         while (child) {
     711           0 :                                 cur = (GF_ChildNodeItem*)gf_malloc(sizeof(GF_ChildNodeItem));
     712           0 :                                 cur->next = NULL;
     713           0 :                                 cur->node = child->node;
     714           0 :                                 gf_node_register(child->node, com->node);
     715           0 :                                 gf_node_activate(child->node);
     716           0 :                                 if (prev) prev->next = cur;
     717           0 :                                 else ((SVG_Element *)com->node)->children = cur;
     718             :                                 prev = cur;
     719           0 :                                 child = child->next;
     720             :                         }
     721             :                         /*signal node modif*/
     722           0 :                         gf_node_changed(com->node, NULL);
     723           0 :                         return GF_OK;
     724             :                 }
     725             :                 /*attribute modif*/
     726           0 :                 else if (inf->field_ptr) {
     727             :                         GF_FieldInfo a, b;
     728           0 :                         if (inf->fieldIndex==(u32) -2) {
     729             :                                 GF_Point2D scale, translate;
     730             :                                 Fixed rotate;
     731             :                                 GF_Matrix2D *dest;
     732           0 :                                 gf_node_get_field_by_name(com->node, "transform", &a);
     733           0 :                                 dest = (GF_Matrix2D*)a.far_ptr;
     734             : 
     735           0 :                                 if (com->tag==GF_SG_LSR_REPLACE) {
     736           0 :                                         if (gf_mx2d_decompose(dest, &scale, &rotate, &translate)) {
     737           0 :                                                 gf_mx2d_init(*dest);
     738           0 :                                                 if (inf->fieldType==SVG_TRANSFORM_SCALE) scale = *(GF_Point2D *)inf->field_ptr;
     739           0 :                                                 else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) translate = *(GF_Point2D *)inf->field_ptr;
     740           0 :                                                 else if (inf->fieldType==SVG_TRANSFORM_ROTATE) rotate = ((SVG_Point_Angle*)inf->field_ptr)->angle;
     741             : 
     742           0 :                                                 gf_mx2d_add_scale(dest, scale.x, scale.y);
     743           0 :                                                 gf_mx2d_add_rotation(dest, 0, 0, rotate);
     744           0 :                                                 gf_mx2d_add_translation(dest, translate.x, translate.y);
     745             :                                         }
     746             :                                 } else {
     747           0 :                                         GF_Point2D *pt = (GF_Point2D *)inf->field_ptr;
     748           0 :                                         if (inf->fieldType==SVG_TRANSFORM_SCALE) gf_mx2d_add_scale(dest, pt->x, pt->y);
     749           0 :                                         else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) gf_mx2d_add_translation(dest, pt->x, pt->y);
     750           0 :                                         else if (inf->fieldType == SVG_TRANSFORM_ROTATE) gf_mx2d_add_rotation(dest, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
     751             :                                 }
     752             :                                 /*signal node modif*/
     753           0 :                                 gf_node_changed(com->node, &a);
     754             :                         } else {
     755           0 :                                 if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
     756           0 :                                         char *str = *(SVG_String*)inf->field_ptr;
     757             : 
     758           0 :                                         if (com->tag == GF_SG_LSR_REPLACE) {
     759           0 :                                                 GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL;
     760           0 :                                                 if (t && (t->sgprivate->tag==TAG_DOMText)) {
     761           0 :                                                         if (t->textContent) gf_free(t->textContent);
     762           0 :                                                         t->textContent = NULL;
     763           0 :                                                         if (str) t->textContent = gf_strdup(str);
     764             :                                                 }
     765             :                                         } else {
     766           0 :                                                 if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
     767             :                                         }
     768             :                                         /*signal node modif*/
     769           0 :                                         gf_node_changed(com->node, NULL);
     770             :                                 }
     771           0 :                                 else if ((inf->fieldIndex==TAG_LSR_ATT_scale)
     772             :                                          || (inf->fieldIndex==TAG_LSR_ATT_translation)
     773           0 :                                          || (inf->fieldIndex==TAG_LSR_ATT_rotation)
     774             :                                         ) {
     775             :                                         SVG_Transform *mx;
     776           0 :                                         gf_node_get_attribute_by_tag(com->node, TAG_SVG_ATT_transform, 1, 0, &a);
     777           0 :                                         mx = a.far_ptr;
     778           0 :                                         if (com->tag == GF_SG_LSR_REPLACE) {
     779             :                                                 GF_Point2D scale, translate;
     780             :                                                 SVG_Point_Angle rotate;
     781           0 :                                                 if (gf_mx2d_decompose(&mx->mat, &scale, &rotate.angle, &translate)) {
     782           0 :                                                         gf_mx2d_init(mx->mat);
     783           0 :                                                         if (inf->fieldIndex==TAG_LSR_ATT_scale) scale = *(GF_Point2D *)inf->field_ptr;
     784           0 :                                                         else if (inf->fieldIndex==TAG_LSR_ATT_translation) translate = *(GF_Point2D *)inf->field_ptr;
     785           0 :                                                         else if (inf->fieldIndex==TAG_LSR_ATT_rotation) rotate = *(SVG_Point_Angle*)inf->field_ptr;
     786             : 
     787           0 :                                                         gf_mx2d_add_scale(&mx->mat, scale.x, scale.y);
     788           0 :                                                         gf_mx2d_add_rotation(&mx->mat, 0, 0, rotate.angle);
     789           0 :                                                         gf_mx2d_add_translation(&mx->mat, translate.x, translate.y);
     790             :                                                 }
     791             :                                         } else {
     792           0 :                                                 if (inf->fieldIndex==TAG_LSR_ATT_scale) gf_mx2d_add_scale(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y);
     793           0 :                                                 if (inf->fieldIndex==TAG_LSR_ATT_translation) gf_mx2d_add_translation(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y);
     794           0 :                                                 if (inf->fieldIndex==TAG_LSR_ATT_rotation) gf_mx2d_add_rotation(&mx->mat, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
     795             :                                         }
     796             :                                         /*signal node modif*/
     797           0 :                                         gf_node_changed(com->node, &a);
     798             :                                 }
     799           0 :                                 else if (gf_node_get_attribute_by_tag(com->node, inf->fieldIndex, 1, 0, &a) == GF_OK) {
     800           0 :                                         b = a;
     801           0 :                                         b.far_ptr = inf->field_ptr;
     802           0 :                                         if (com->tag == GF_SG_LSR_REPLACE) {
     803           0 :                                                 gf_svg_attributes_copy(&a, &b, 0);
     804             :                                         } else {
     805           0 :                                                 gf_svg_attributes_add(&a, &b, &a, 0);
     806             :                                         }
     807           0 :                                         if (a.fieldType==XMLRI_datatype) {
     808           0 :                                                 gf_node_dirty_set(com->node, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
     809             :                                         }
     810             :                                         /*signal node modif*/
     811           0 :                                         gf_node_changed(com->node, &a);
     812             :                                 }
     813             :                         }
     814           0 :                 } else if (com->fromNodeID) {
     815             :                         GF_FieldInfo a, b;
     816           0 :                         GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
     817           0 :                         if (!fromNode) return GF_NON_COMPLIANT_BITSTREAM;
     818           0 :                         if (gf_node_get_field(fromNode, com->fromFieldIndex, &b) != GF_OK) return GF_NON_COMPLIANT_BITSTREAM;
     819             : 
     820           0 :                         if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
     821           0 :                                 char *str = inf->field_ptr ? *(SVG_String*)inf->field_ptr : NULL;
     822             : 
     823           0 :                                 if (com->tag == GF_SG_LSR_REPLACE) {
     824           0 :                                         GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL;
     825           0 :                                         if (t && (t->sgprivate->tag==TAG_DOMText)) {
     826           0 :                                                 if (t->textContent) gf_free(t->textContent);
     827           0 :                                                 t->textContent = NULL;
     828           0 :                                                 if (str) t->textContent = gf_strdup(str);
     829             :                                         }
     830             :                                 } else {
     831           0 :                                         if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
     832             :                                 }
     833             :                         } else {
     834           0 :                                 gf_node_get_field(com->node, inf->fieldIndex, &a);
     835           0 :                                 if (com->tag == GF_SG_LSR_REPLACE) {
     836           0 :                                         e = gf_svg_attributes_copy(&a, &b, 0);
     837             :                                 } else {
     838           0 :                                         e = gf_svg_attributes_add(&a, &b, &a, 0);
     839             :                                 }
     840             :                         }
     841           0 :                         gf_node_changed(com->node, &a);
     842           0 :                         return e;
     843             :                 } else {
     844             :                         return GF_NON_COMPLIANT_BITSTREAM;
     845             :                 }
     846             :                 break;
     847           0 :         case GF_SG_LSR_ACTIVATE:
     848           0 :                 gf_node_activate(com->node);
     849             :                 break;
     850           0 :         case GF_SG_LSR_DEACTIVATE:
     851           0 :                 gf_node_deactivate(com->node);
     852           0 :                 gf_node_changed(com->node, NULL);
     853             :                 break;
     854             :         case GF_SG_LSR_SEND_EVENT:
     855             :         {
     856             :                 GF_DOM_Event evt;
     857             :                 memset(&evt, 0, sizeof(GF_DOM_Event));
     858           0 :                 evt.type = com->send_event_name;
     859           0 :                 evt.detail = com->send_event_integer;
     860           0 :                 evt.clientX = com->send_event_x;
     861           0 :                 evt.clientY = com->send_event_y;
     862           0 :                 gf_dom_event_fire(com->node, &evt);
     863             :         }
     864             :         break;
     865             : #endif
     866             : 
     867           0 :         default:
     868           0 :                 return GF_NOT_SUPPORTED;
     869             :         }
     870         705 :         if (e) return e;
     871             : 
     872             : #ifndef GPAC_DISABLE_VRML
     873        2514 :         if (com->scripts_to_load) {
     874          70 :                 while (gf_list_count(com->scripts_to_load)) {
     875          35 :                         GF_Node *script = (GF_Node *)gf_list_get(com->scripts_to_load, 0);
     876          35 :                         gf_list_rem(com->scripts_to_load, 0);
     877          35 :                         gf_sg_script_load(script);
     878             :                 }
     879          35 :                 gf_list_del(com->scripts_to_load);
     880          35 :                 com->scripts_to_load = NULL;
     881             :         }
     882             : #endif
     883             : 
     884             :         return GF_OK;
     885             : }
     886             : 
     887             : GF_EXPORT
     888        5987 : GF_CommandField *gf_sg_command_field_new(GF_Command *com)
     889             : {
     890             :         GF_CommandField *ptr;
     891        5987 :         GF_SAFEALLOC(ptr, GF_CommandField);
     892        5987 :         if (ptr)
     893        5987 :                 gf_list_add(com->command_fields, ptr);
     894        5987 :         return ptr;
     895             : }
     896             : 
     897             : 
     898             : GF_EXPORT
     899         365 : GF_Err gf_sg_command_apply_list(GF_SceneGraph *graph, GF_List *comList, Double time_offset)
     900             : {
     901             :         GF_Err e;
     902             :         GF_Command *com;
     903         365 :         u32 i=0;
     904        1365 :         while ((com = (GF_Command *)gf_list_enum(comList, &i))) {
     905         636 :                 e = gf_sg_command_apply(graph, com, time_offset);
     906         636 :                 if (e) return e;
     907             :         }
     908             :         return GF_OK;
     909             : }
     910             : 
     911             : #ifndef GPAC_DISABLE_VRML
     912          58 : GF_Command *gf_sg_vrml_command_clone(GF_Command *com, GF_SceneGraph *inGraph, Bool force_clone)
     913             : {
     914             :         u32 i, count;
     915             :         GF_Command *dest;
     916             : 
     917             :         /*FIXME - to do*/
     918          58 :         if (gf_list_count(com->new_proto_list)) return NULL;
     919          58 :         dest = gf_sg_command_new(inGraph, com->tag);
     920             : 
     921          58 :         if (com->in_scene!=inGraph) force_clone = 1;
     922             : 
     923             :         /*node the command applies to - may be NULL*/
     924           0 :         if (force_clone) {
     925          58 :                 dest->node = gf_node_clone(inGraph, com->node, NULL, "", 0);
     926             :         } else {
     927           0 :                 dest->node = com->node;
     928           0 :                 gf_node_register(dest->node, NULL);
     929             :         }
     930             :         /*route insert, replace and delete*/
     931          58 :         dest->RouteID = com->RouteID;
     932          58 :         if (com->def_name) dest->def_name = gf_strdup(com->def_name);
     933             :         //this is an union
     934             :         //if (com->send_event_string) dest->send_event_string = gf_strdup(com->send_event_string);
     935             : 
     936          58 :         dest->fromNodeID = com->fromNodeID;
     937          58 :         dest->fromFieldIndex = com->fromFieldIndex;
     938          58 :         dest->toNodeID = com->toNodeID;
     939          58 :         dest->toFieldIndex = com->toFieldIndex;
     940          58 :         dest->send_event_integer = com->send_event_integer;
     941          58 :         dest->send_event_x = com->send_event_x;
     942          58 :         dest->send_event_y = com->send_event_y;
     943             : 
     944          58 :         dest->del_proto_list_size = com->del_proto_list_size;
     945          58 :         if (com->del_proto_list_size) {
     946           0 :                 dest->del_proto_list = (u32*)gf_malloc(sizeof(u32) * com->del_proto_list_size);
     947           0 :                 memcpy(dest->del_proto_list, com->del_proto_list, sizeof(u32) * com->del_proto_list_size);
     948             :         }
     949          58 :         count = gf_list_count(com->command_fields);
     950         108 :         for (i=0; i<count; i++) {
     951          50 :                 GF_CommandField *fo = (GF_CommandField *)gf_list_get(com->command_fields, i);
     952          50 :                 GF_CommandField *fd = (GF_CommandField *)gf_sg_command_field_new(dest);
     953             : 
     954          50 :                 fd->fieldIndex = fo->fieldIndex;
     955          50 :                 fd->fieldType = fo->fieldType;
     956          50 :                 fd->pos = fo->pos;
     957             : 
     958             :                 /*FIXME - this can also be LASeR commands, not supported for now*/
     959          50 :                 if (fo->field_ptr) {
     960          50 :                         fd->field_ptr = gf_sg_vrml_field_pointer_new(fd->fieldType);
     961          50 :                         gf_sg_vrml_field_clone(fd->field_ptr, fo->field_ptr, fo->fieldType, dest->in_scene);
     962             :                 }
     963             : 
     964          50 :                 if (fo->new_node) {
     965           0 :                         if (force_clone) {
     966           0 :                                 fd->new_node = gf_node_clone(inGraph, fo->new_node, dest->node, "", 0);
     967             :                         } else {
     968           0 :                                 fd->new_node = fo->new_node;
     969           0 :                                 gf_node_register(fd->new_node, NULL);
     970             :                         }
     971           0 :                         fd->field_ptr = &fd->new_node;
     972             :                 }
     973          50 :                 if (fo->node_list) {
     974             :                         GF_ChildNodeItem *child, *cur, *prev;
     975             :                         prev = NULL;
     976             :                         child = fo->node_list;
     977           0 :                         while (child) {
     978           0 :                                 cur = (GF_ChildNodeItem*) gf_malloc(sizeof(GF_ChildNodeItem));
     979           0 :                                 if (force_clone) {
     980           0 :                                         cur->node = gf_node_clone(inGraph, child->node, dest->node, "", 0);
     981             :                                 } else {
     982           0 :                                         cur->node = child->node;
     983           0 :                                         gf_node_register(cur->node, NULL);
     984             :                                 }
     985           0 :                                 cur->next = NULL;
     986           0 :                                 if (prev) prev->next = cur;
     987           0 :                                 else fd->node_list = cur;
     988             :                                 prev = cur;
     989           0 :                                 child = child->next;
     990             :                         }
     991           0 :                         fd->field_ptr = &fd->node_list;
     992             :                 }
     993             :         }
     994             :         return dest;
     995             : }
     996             : 
     997             : #endif
     998             : 

Generated by: LCOV version 1.13