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*/
|