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