LCOV - code coverage report
Current view: top level - scenegraph - vrml_script.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 127 139 91.4 %
Date: 2021-04-29 23:48:07 Functions: 9 9 100.0 %

          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             : #include <gpac/internal/scenegraph_dev.h>
      27             : /*MPEG4 & X3D tags (for node tables & script handling)*/
      28             : #include <gpac/nodes_mpeg4.h>
      29             : #include <gpac/nodes_x3d.h>
      30             : #include "qjs_common.h"
      31             : 
      32             : #ifndef GPAC_DISABLE_VRML
      33             : 
      34             : 
      35             : static u32 script_get_nb_static_field(GF_Node *node)
      36             : {
      37       26102 :         return (node->sgprivate->tag==TAG_MPEG4_Script) ? 3 : 4;
      38             : }
      39             : 
      40        5200 : void Script_PreDestroy(GF_Node *node, void *eff, Bool is_destroy)
      41             : {
      42             :         GF_ScriptPriv *priv;
      43             : 
      44        5200 :         if (!is_destroy) return;
      45             : 
      46         458 :         priv = (GF_ScriptPriv *)node->sgprivate->UserPrivate;
      47             : 
      48         458 :         if (priv->JS_PreDestroy) priv->JS_PreDestroy(node);
      49             : 
      50             :         //destroy extra fields
      51        3365 :         while (gf_list_count(priv->fields)) {
      52        2907 :                 GF_ScriptField *field = (GF_ScriptField *)gf_list_get(priv->fields, 0);
      53        2907 :                 gf_list_rem(priv->fields, 0);
      54        2907 :                 if (field->pField) {
      55             :                         //if Node unregister
      56        2907 :                         switch (field->fieldType) {
      57             :                         //specific case for GF_Node in script
      58         877 :                         case GF_SG_VRML_SFNODE:
      59         877 :                                 gf_node_unregister((GF_Node *) field->pField, node);
      60         877 :                                 break;
      61           3 :                         case GF_SG_VRML_MFNODE:
      62           3 :                                 gf_node_unregister_children(node, (GF_ChildNodeItem*) field->pField);
      63           3 :                                 break;
      64        2027 :                         default:
      65        2027 :                                 gf_sg_vrml_field_pointer_del(field->pField, field->fieldType);
      66        2027 :                                 break;
      67             :                         }
      68           0 :                 }
      69        2907 :                 if (field->name) gf_free(field->name);
      70        2907 :                 gf_free(field);
      71             :         }
      72         458 :         gf_list_del(priv->fields);
      73         458 :         gf_free(priv);
      74             : }
      75             : 
      76        1538 : u32 gf_sg_script_get_num_fields(GF_Node *node, u8 IndexMode)
      77             : {
      78             :         u32 nb_static;
      79        1538 :         GF_ScriptPriv *priv = (GF_ScriptPriv *)node->sgprivate->UserPrivate;
      80        1538 :         switch (IndexMode) {
      81           1 :         case GF_SG_FIELD_CODING_IN:
      82           1 :                 return priv->numIn;
      83           1 :         case GF_SG_FIELD_CODING_OUT:
      84           1 :                 return priv->numOut;
      85          56 :         case GF_SG_FIELD_CODING_DEF:
      86          56 :                 return priv->numDef;
      87             :         case GF_SG_FIELD_CODING_DYN:
      88             :                 return 0;
      89             :         default:
      90             :                 nb_static = script_get_nb_static_field(node);
      91        1479 :                 return priv ? gf_list_count(priv->fields) + nb_static : nb_static;
      92             :         }
      93             : }
      94             : 
      95             : GF_EXPORT
      96        1891 : GF_Err gf_sg_script_get_field_index(GF_Node *node, u32 inField, u8 IndexMode, u32 *allField)
      97             : {
      98             :         u32 i;
      99             :         GF_ScriptField *sf;
     100             :         u32 nb_static = script_get_nb_static_field(node);
     101        1891 :         GF_ScriptPriv *priv = (GF_ScriptPriv *)node->sgprivate->UserPrivate;
     102        1891 :         i=0;
     103        3902 :         while (priv && (sf = (GF_ScriptField *)gf_list_enum(priv->fields, &i))) {
     104         120 :                 *allField = i-1+nb_static;
     105         120 :                 switch (IndexMode) {
     106           0 :                 case GF_SG_FIELD_CODING_IN:
     107           0 :                         if ((u32)sf->IN_index==inField) return GF_OK;
     108             :                         break;
     109         120 :                 case GF_SG_FIELD_CODING_DEF:
     110         120 :                         if ((u32)sf->DEF_index==inField) return GF_OK;
     111             :                         break;
     112           0 :                 case GF_SG_FIELD_CODING_OUT:
     113           0 :                         if ((u32)sf->OUT_index==inField) return GF_OK;
     114             :                         break;
     115             :                 case GF_SG_FIELD_CODING_DYN:
     116             :                         return GF_BAD_PARAM;
     117           0 :                 default:
     118           0 :                         if (inField==i-1+nb_static) return GF_OK;
     119             :                         break;
     120             :                 }
     121             :         }
     122             :         /*try with default*/
     123        1891 :         return gf_sg_mpeg4_node_get_field_index(node, inField, IndexMode, allField);
     124             : }
     125             : 
     126             : 
     127       19367 : GF_Err gf_sg_script_get_field(GF_Node *node, GF_FieldInfo *info)
     128             : {
     129             :         GF_ScriptField *field;
     130             :         GF_ScriptPriv *priv;
     131             :         u32 nb_static;
     132             : 
     133       19367 :         if (!info || !node) return GF_BAD_PARAM;
     134             : 
     135       19367 :         priv = (GF_ScriptPriv *)gf_node_get_private(node);
     136             :         nb_static = script_get_nb_static_field(node);
     137             : 
     138             :         //static fields
     139       19367 :         if (info->fieldIndex < nb_static) {
     140        5557 :                 if (nb_static==3) return gf_sg_mpeg4_node_get_field(node, info);
     141             : #ifndef GPAC_DISABLE_X3D
     142         107 :                 return gf_sg_x3d_node_get_field(node, info);
     143             : #else
     144             :                 return GF_NOT_SUPPORTED;
     145             : #endif
     146             :         }
     147             : 
     148             :         //dyn fields
     149       13810 :         field = (GF_ScriptField *)gf_list_get(priv->fields, info->fieldIndex - nb_static);
     150       13810 :         if (!field) return GF_BAD_PARAM;
     151             : 
     152       13810 :         info->eventType = field->eventType;
     153       13810 :         info->fieldType = field->fieldType;
     154       13810 :         info->name = field->name;
     155             :         //we need the eventIn name to activate the function...
     156       13810 :         info->on_event_in = NULL;
     157             : 
     158             :         //setup pointer (special cases for nodes)
     159       13810 :         switch (field->fieldType) {
     160        3832 :         case GF_SG_VRML_SFNODE:
     161             :         case GF_SG_VRML_MFNODE:
     162        3832 :                 info->far_ptr = &field->pField;
     163        3832 :                 info->NDTtype = NDT_SFWorldNode;
     164        3832 :                 break;
     165        9978 :         default:
     166        9978 :                 info->far_ptr = field->pField;
     167        9978 :                 break;
     168             :         }
     169             :         return GF_OK;
     170             : }
     171             : 
     172         458 : void gf_sg_script_init(GF_Node *node)
     173             : {
     174             :         GF_ScriptPriv *priv;
     175             : 
     176             : 
     177         458 :         GF_SAFEALLOC(priv, GF_ScriptPriv)
     178         458 :         if (!priv) {
     179           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[VRML] Failed to create script node\n"));
     180             :                 return;
     181             :         }
     182         458 :         priv->fields = gf_list_new();
     183             : 
     184         458 :         gf_node_set_private(node, priv);
     185         458 :         node->sgprivate->UserCallback = Script_PreDestroy;
     186             : 
     187             :         //URL is exposedField (in, out Def)
     188         458 :         priv->numDef = priv->numIn = priv->numOut = script_get_nb_static_field(node) - 2;
     189             :         //directOutput and mustEvaluate are fields (def)
     190         458 :         priv->numDef += 2;
     191             : }
     192             : 
     193             : GF_EXPORT
     194        2907 : GF_ScriptField *gf_sg_script_field_new(GF_Node *node, u32 eventType, u32 fieldType, const char *name)
     195             : {
     196             :         GF_ScriptPriv *priv;
     197             :         GF_ScriptField *field;
     198        5814 :         if (!name || ((node->sgprivate->tag != TAG_MPEG4_Script)
     199             : #ifndef GPAC_DISABLE_X3D
     200        2907 :                       && (node->sgprivate->tag != TAG_X3D_Script)
     201             : #endif
     202             :                      ))
     203             :                 return NULL;
     204             : 
     205        2907 :         if (eventType > GF_SG_SCRIPT_TYPE_EVENT_OUT) return NULL;
     206        2907 :         priv = (GF_ScriptPriv *)gf_node_get_private(node);
     207             : 
     208        2907 :         GF_SAFEALLOC(field, GF_ScriptField)
     209        2907 :         if (!field) {
     210           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[VRML] Failed to create script field\n"));
     211             :                 return NULL;
     212             :         }
     213        2907 :         field->fieldType = fieldType;
     214        2907 :         field->name = gf_strdup(name);
     215             : 
     216        2907 :         field->DEF_index = field->IN_index = field->OUT_index = -1;
     217        2907 :         switch (eventType) {
     218        1308 :         case GF_SG_SCRIPT_TYPE_FIELD:
     219        1308 :                 field->DEF_index = priv->numDef;
     220        1308 :                 priv->numDef++;
     221        1308 :                 field->eventType = GF_SG_EVENT_FIELD;
     222        1308 :                 break;
     223        1223 :         case GF_SG_SCRIPT_TYPE_EVENT_IN:
     224        1223 :                 field->IN_index = priv->numIn;
     225        1223 :                 priv->numIn++;
     226        1223 :                 field->eventType = GF_SG_EVENT_IN;
     227        1223 :                 break;
     228         376 :         case GF_SG_SCRIPT_TYPE_EVENT_OUT:
     229         376 :                 field->OUT_index = priv->numOut;
     230         376 :                 field->eventType = GF_SG_EVENT_OUT;
     231         376 :                 priv->numOut++;
     232         376 :                 break;
     233             :         }
     234             :         //+ static fields
     235        2907 :         field->ALL_index = script_get_nb_static_field(node) + gf_list_count(priv->fields);
     236        2907 :         gf_list_add(priv->fields, field);
     237             : 
     238             :         //create field entry
     239        2907 :         if ((fieldType != GF_SG_VRML_SFNODE) && (fieldType != GF_SG_VRML_MFNODE) ) {
     240        2027 :                 field->pField = gf_sg_vrml_field_pointer_new(fieldType);
     241             :         }
     242             : 
     243             :         return field;
     244             : }
     245             : 
     246             : 
     247         365 : GF_Err gf_sg_script_prepare_clone(GF_Node *dest, GF_Node *orig)
     248             : {
     249             :         u32 i, type;
     250             :         GF_ScriptField *sf;
     251             :         GF_ScriptPriv *dest_priv, *orig_priv;
     252         365 :         orig_priv = (GF_ScriptPriv *)orig->sgprivate->UserPrivate;
     253         365 :         dest_priv = (GF_ScriptPriv *)dest->sgprivate->UserPrivate;
     254         365 :         if (!orig_priv || !dest_priv) return GF_BAD_PARAM;
     255             : 
     256         365 :         i=0;
     257        3277 :         while ((sf = (GF_ScriptField *)gf_list_enum(orig_priv->fields, &i))) {
     258        2547 :                 switch (sf->eventType) {
     259             :                 case GF_SG_EVENT_IN:
     260             :                         type = GF_SG_SCRIPT_TYPE_EVENT_IN;
     261             :                         break;
     262         361 :                 case GF_SG_EVENT_OUT:
     263             :                         type = GF_SG_SCRIPT_TYPE_EVENT_OUT;
     264         361 :                         break;
     265        1095 :                 case GF_SG_EVENT_FIELD:
     266             :                         type = GF_SG_SCRIPT_TYPE_FIELD;
     267        1095 :                         break;
     268             :                 default:
     269             :                         return GF_BAD_PARAM;
     270             :                 }
     271        2547 :                 gf_sg_script_field_new(dest, type, sf->fieldType, sf->name);
     272             :         }
     273             :         return GF_OK;
     274             : }
     275             : 
     276             : GF_EXPORT
     277          15 : GF_Err gf_sg_script_field_get_info(GF_ScriptField *field, GF_FieldInfo *info)
     278             : {
     279          15 :         if (!field || !info) return GF_BAD_PARAM;
     280             :         memset(info, 0, sizeof(GF_FieldInfo));
     281             : 
     282          15 :         info->fieldIndex = field->ALL_index;
     283          15 :         info->eventType = field->eventType;
     284          15 :         info->fieldType = field->fieldType;
     285          15 :         info->name = field->name;
     286             : 
     287             :         //setup pointer (special cases for nodes)
     288          15 :         switch (field->fieldType) {
     289          15 :         case GF_SG_VRML_SFNODE:
     290             :         case GF_SG_VRML_MFNODE:
     291          15 :                 info->far_ptr = &field->pField;
     292          15 :                 info->NDTtype = NDT_SFWorldNode;
     293          15 :                 break;
     294           0 :         default:
     295           0 :                 info->far_ptr = field->pField;
     296           0 :                 break;
     297             :         }
     298             :         return GF_OK;
     299             : }
     300             : 
     301             : GF_EXPORT
     302        1763 : void gf_sg_script_event_in(GF_Node *node, GF_FieldInfo *in_field)
     303             : {
     304        1763 :         GF_ScriptPriv *priv = (GF_ScriptPriv *)node->sgprivate->UserPrivate;
     305        1763 :         if (priv->JS_EventIn) priv->JS_EventIn(node, in_field);
     306        1763 : }
     307             : 
     308             : 
     309             : #endif /*GPAC_DISABLE_VRML*/

Generated by: LCOV version 1.13