1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2017
6 * All rights reserved
7 *
8 * This file is part of GPAC / Scene Compositor 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/compositor_dev.h>
27 /*includes X3D nodes for WorldInfo, Inline and Key/String sensors*/
28 #include <gpac/nodes_x3d.h>
29 #include <gpac/nodes_svg.h>
30 #include <gpac/options.h>
31 #ifndef GPAC_DISABLE_VRML
32
33 void InitMediaControl(GF_Scene *scene, GF_Node *node);
34 void MC_Modified(GF_Node *node);
35
36 void InitMediaSensor(GF_Scene *scene, GF_Node *node);
37 void MS_Modified(GF_Node *node);
38
39 void gf_init_inline(GF_Scene *scene, GF_Node *node);
40 void gf_inline_on_modified(GF_Node *node);
41
42 void gf_scene_init_storage(GF_Scene *scene, GF_Node *node);
43
44
TraverseWorldInfo(GF_Node * node,void * rs,Bool is_destroy)45 void TraverseWorldInfo(GF_Node *node, void *rs, Bool is_destroy)
46 {
47 GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
48 scene->world_info = is_destroy ? NULL : (M_WorldInfo *) node;
49 }
50
TraverseKeyNavigator(GF_Node * node,void * rs,Bool is_destroy)51 void TraverseKeyNavigator(GF_Node *node, void *rs, Bool is_destroy)
52 {
53 if (is_destroy) {
54 GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
55 gf_list_del_item(scene->keynavigators, node);
56 gf_sc_key_navigator_del(scene->compositor, node);
57 }
58 }
59
on_kn_set_focus(GF_Node * node,GF_Route * _route)60 void on_kn_set_focus(GF_Node*node, GF_Route *_route)
61 {
62 if (node) {
63 GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
64 gf_sc_change_key_navigator(scene->compositor, node);
65 }
66 }
67
evaluate_scene_cap(GF_Node * node,GF_Route * route)68 void evaluate_scene_cap(GF_Node *node, GF_Route *route)
69 {
70 GF_SystemRTInfo rti;
71 Double fps;
72 u32 height;
73 Bool b_on;
74 u32 b_charge, b_level;
75
76 M_TermCap *tc = (M_TermCap *)node;
77 GF_Scene *scene = gf_node_get_private(node);
78 tc->value = 0;
79 switch (tc->capability) {
80 case 0: /*framerate*/
81 fps = gf_sc_get_fps(scene->compositor, 1);
82 if (fps<=5.0) tc->value = 1;
83 else if (fps<=10.0) tc->value = 2;
84 else if (fps<=20.0) tc->value = 3;
85 else if (fps<=40.0) tc->value = 4;
86 else tc->value = 5;
87 break;
88 case 1: /*colordepth*/
89 return;
90 case 2: /*screensize*/
91 height = scene->compositor->display_height;
92 if (height<200) tc->value = 1;
93 else if (height<400) tc->value = 2;
94 else if (height<800) tc->value = 3;
95 else if (height<1600) tc->value = 4;
96 else tc->value = 4;
97 break;
98 case 3: /*graphics hardware*/
99 return;
100 case 32:/*audio out format*/
101 return;
102 case 33:/*audio out format*/
103 return;
104 case 34:/*spatial audio cap*/
105 return;
106 case 64:/*CPU load*/
107 if (!gf_sys_get_rti(200, &rti, 0) ) return;
108 if (rti.total_cpu_usage<20) tc->value = 1;
109 else if (rti.total_cpu_usage<40) tc->value = 2;
110 else if (rti.total_cpu_usage<60) tc->value = 3;
111 else if (rti.total_cpu_usage<80) tc->value = 4;
112 else tc->value = 5;
113 break;
114 case 65:/*mem load*/
115 if (!gf_sys_get_rti(200, &rti, GF_RTI_SYSTEM_MEMORY_ONLY) ) return;
116 rti.physical_memory_avail /= 1024;
117 if (rti.physical_memory_avail < 100) tc->value = 1;
118 else if (rti.physical_memory_avail < 512) tc->value = 2;
119 else if (rti.physical_memory_avail < 2048) tc->value = 3;
120 else if (rti.physical_memory_avail < 8192) tc->value = 4;
121 else if (rti.physical_memory_avail < 32768) tc->value = 5;
122 else if (rti.physical_memory_avail < 204800) tc->value = 6;
123 else tc->value = 7;
124 break;
125
126 /*GPAC extensions*/
127 case 100: /*display width*/
128 tc->value = scene->compositor->display_width;
129 break;
130 case 101: /*display height*/
131 tc->value = scene->compositor->display_height;
132 break;
133 case 102: /*frame rate*/
134 tc->value = (u32) gf_sc_get_fps(scene->compositor, 1);
135 break;
136 case 103: /*total CPU*/
137 if (!gf_sys_get_rti(200, &rti, 0) ) return;
138 tc->value = rti.total_cpu_usage;
139 break;
140 case 104: /*process CPU*/
141 if (!gf_sys_get_rti(200, &rti, 0) ) return;
142 tc->value = rti.process_cpu_usage;
143 break;
144 case 106: /*total memory in kB*/
145 if (!gf_sys_get_rti(200, &rti, GF_RTI_SYSTEM_MEMORY_ONLY) ) return;
146 tc->value = (u32) (rti.physical_memory/1024);
147 break;
148 case 107: /*total memory available in kB*/
149 if (!gf_sys_get_rti(200, &rti, GF_RTI_SYSTEM_MEMORY_ONLY) ) return;
150 tc->value = (u32) (rti.physical_memory_avail/1024);
151 break;
152 case 108: /*process memory in kB*/
153 if (!gf_sys_get_rti(200, &rti, 0) ) return;
154 tc->value = (u32) (rti.process_memory/1024);
155 break;
156 case 109: /*battery on/off*/
157 gf_sys_get_battery_state(&b_on, &b_charge, &b_level, NULL, NULL);
158 tc->value = b_on;
159 break;
160 case 110: /*battery charging*/
161 gf_sys_get_battery_state(&b_on, &b_charge, &b_level, NULL, NULL);
162 tc->value = b_charge;
163 break;
164 case 111: /*battery level*/
165 gf_sys_get_battery_state(&b_on, &b_charge, &b_level, NULL, NULL);
166 tc->value = b_level;
167 break;
168
169 case 112: /*audio vol*/
170 tc->value = gf_sc_get_option(scene->compositor, GF_OPT_AUDIO_VOLUME);
171 break;
172 case 113: /*audio pan*/
173 tc->value = gf_sc_get_option(scene->compositor, GF_OPT_AUDIO_PAN);
174 break;
175 default:
176 return;
177 }
178 gf_node_event_out(node, 2);
179 }
180
InitTermCap(GF_Scene * scene,GF_Node * node)181 static void InitTermCap(GF_Scene *scene, GF_Node *node)
182 {
183 M_TermCap *tc = (M_TermCap *)node;
184 tc->on_evaluate = evaluate_scene_cap;
185 gf_node_set_private(node, scene);
186 /*evaluate upon init (cf BIFS spec)*/
187 evaluate_scene_cap(node, NULL);
188 }
189
190 #endif /*GPAC_DISABLE_VRML*/
191
192
193 #ifndef GPAC_DISABLE_SVG
svg_traverse_title(GF_Node * node,void * rs,Bool is_destroy)194 static void svg_traverse_title(GF_Node *node, void *rs, Bool is_destroy)
195 {
196 GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
197 scene->world_info = is_destroy ? NULL : node;
198 }
199 #endif
200
201 void gf_sc_on_node_init(GF_Compositor *sc, GF_Node *node);
202
gf_scene_on_node_init(void * _scene,GF_Node * node)203 void gf_scene_on_node_init(void *_scene, GF_Node *node)
204 {
205 GF_Scene *scene = (GF_Scene *)_scene;
206 if (!node || !scene) return;
207
208 switch (gf_node_get_tag(node)) {
209 #ifndef GPAC_DISABLE_VRML
210
211 case TAG_MPEG4_Inline:
212 #ifndef GPAC_DISABLE_X3D
213 case TAG_X3D_Inline:
214 #endif
215 gf_init_inline(scene, node);
216 break;
217 case TAG_MPEG4_MediaBuffer:
218 break;
219 case TAG_MPEG4_MediaControl:
220 InitMediaControl(scene, node);
221 break;
222 case TAG_MPEG4_MediaSensor:
223 InitMediaSensor(scene, node);
224 break;
225 case TAG_MPEG4_InputSensor:
226 InitInputSensor(scene, node);
227 break;
228
229 /*BIFS nodes, get back to codec, but filter externProtos*/
230 case TAG_MPEG4_Conditional:
231 break;
232 case TAG_MPEG4_QuantizationParameter:
233 break;
234 /*world info is stored at the inline scene level*/
235 case TAG_MPEG4_WorldInfo:
236 #ifndef GPAC_DISABLE_X3D
237 case TAG_X3D_WorldInfo:
238 #endif
239 gf_node_set_callback_function(node, TraverseWorldInfo);
240 gf_node_set_private(node, scene);
241 break;
242
243 #ifndef GPAC_DISABLE_X3D
244 case TAG_X3D_KeySensor:
245 InitKeySensor(scene, node);
246 break;
247 case TAG_X3D_StringSensor:
248 InitStringSensor(scene, node);
249 break;
250 #endif
251
252 case TAG_MPEG4_TermCap:
253 InitTermCap(scene, node);
254 break;
255
256 case TAG_MPEG4_Storage:
257 gf_scene_init_storage(scene, node);
258 break;
259
260 case TAG_MPEG4_KeyNavigator:
261 gf_node_set_callback_function(node, TraverseKeyNavigator);
262 gf_node_set_private(node, scene);
263 gf_list_add(scene->keynavigators, node);
264 ((M_KeyNavigator*)node)->on_setFocus = on_kn_set_focus;
265 #ifdef GPAC_ENABLE_COVERAGE
266 if (gf_sys_is_cov_mode()) {
267 on_kn_set_focus(NULL, NULL);
268 }
269 #endif
270 break;
271
272 #endif
273
274
275 #ifndef GPAC_DISABLE_SVG
276 case TAG_SVG_title:
277 gf_node_set_callback_function(node, svg_traverse_title);
278 gf_node_set_private(node, scene);
279 break;
280 #endif
281
282 default:
283 gf_sc_on_node_init(scene->compositor, node);
284 break;
285 }
286 }
287
gf_scene_on_node_modified(void * _is,GF_Node * node)288 void gf_scene_on_node_modified(void *_is, GF_Node *node)
289 {
290 GF_Scene *scene = (GF_Scene *)_is;
291 if (!scene) return;
292 if (!node) {
293 gf_sc_invalidate(scene->compositor, NULL);
294 return;
295 }
296
297 switch (gf_node_get_tag(node)) {
298 #ifndef GPAC_DISABLE_VRML
299 case TAG_MPEG4_Inline:
300 #ifndef GPAC_DISABLE_X3D
301 case TAG_X3D_Inline:
302 #endif
303 gf_inline_on_modified(node);
304 break;
305 case TAG_MPEG4_MediaBuffer:
306 break;
307 case TAG_MPEG4_MediaControl:
308 MC_Modified(node);
309 break;
310 case TAG_MPEG4_MediaSensor:
311 MS_Modified(node);
312 break;
313 case TAG_MPEG4_InputSensor:
314 InputSensorModified(node);
315 break;
316 case TAG_MPEG4_Conditional:
317 break;
318 case TAG_MPEG4_Storage:
319 break;
320 #endif
321 default:
322 gf_sc_invalidate(scene->compositor, node);
323 break;
324 }
325 }
326
gf_scene_on_node_destroyed(void * _is,GF_Node * node)327 static void gf_scene_on_node_destroyed(void *_is, GF_Node *node)
328 {
329 GF_Scene *scene = (GF_Scene *)_is;
330 if (!scene) return;
331 gf_sc_node_destroy(scene->compositor, node, NULL);
332 }
333
334 GF_EXPORT
gf_scene_node_callback(void * _is,GF_SGNodeCbkType type,GF_Node * n,void * param)335 void gf_scene_node_callback(void *_is, GF_SGNodeCbkType type, GF_Node *n, void *param)
336 {
337 switch (type) {
338 case GF_SG_CALLBACK_MODIFIED:
339 gf_scene_on_node_modified(_is, n);
340 break;
341 case GF_SG_CALLBACK_NODE_DESTROY:
342 gf_scene_on_node_destroyed(_is, n);
343 break;
344 case GF_SG_CALLBACK_INIT:
345 gf_scene_on_node_init(_is, n);
346 break;
347 /*get all inline nodes using this subscene and bubble up...*/
348 case GF_SG_CALLBACK_GRAPH_DIRTY:
349 {
350 u32 i=0;
351 GF_Scene *scene = (GF_Scene *)_is;
352 if (scene->root_od->mo) {
353 GF_Node *root;
354 while ((root=(GF_Node*)gf_mo_event_target_enum_node(scene->root_od->mo, &i))) {
355 gf_node_dirty_set(root, GF_SG_CHILD_DIRTY, GF_TRUE);
356 }
357 }
358 }
359 break;
360 }
361 }
362