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