Line data Source code
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 : #include <gpac/modules/codec.h>
28 : #include <gpac/utf.h>
29 : #include <gpac/nodes_x3d.h>
30 : #include <gpac/constants.h>
31 :
32 : #ifndef GPAC_DISABLE_VRML
33 :
34 : enum
35 : {
36 : IS_KeySensor = 1,
37 : IS_StringSensor,
38 : IS_Mouse,
39 : IS_HTKSensor,
40 : };
41 :
42 : typedef struct
43 : {
44 : /*object for this input stream*/
45 : GF_ObjectManager *odm;
46 :
47 : /*list of attached nodes*/
48 : GF_List *is_nodes;
49 : /*stream ID*/
50 : u16 ES_ID;
51 : /*uncompressed data frame*/
52 : GF_List *ddf;
53 :
54 : GF_InputSensorDevice *io_dev;
55 :
56 : u32 type;
57 :
58 : /*string sensor sep char */
59 : s16 termChar, delChar;
60 : /*current typed text in UTF-8*/
61 : unsigned short enteredText[5000];
62 : u32 text_len;
63 : } GF_InputSensorCtx;
64 :
65 :
66 : void gf_isdec_del(GF_BaseDecoder *plug);
67 :
68 : static GF_Err IS_ProcessData(GF_InputSensorCtx *is_ctx, const char *inBuffer, u32 inBufferLength);
69 :
70 : typedef struct
71 : {
72 : /*stream context*/
73 : u16 ES_ID;
74 : Bool registered;
75 : GF_MediaObject *mo;
76 : M_InputSensor *is;
77 : } ISStack;
78 :
79 :
80 :
81 : typedef struct
82 : {
83 : u16 enteredText[5000];
84 : u32 text_len;
85 : GF_Compositor *compositor;
86 : } StringSensorStack;
87 :
88 :
89 :
90 : /*
91 : input sensor decoder(s) handling
92 : */
93 :
94 :
95 90 : static void add_field(GF_InputSensorCtx *priv, u32 fieldType, const char *fieldName)
96 : {
97 90 : GF_FieldInfo *field = (GF_FieldInfo *) gf_malloc(sizeof(GF_FieldInfo));
98 : memset(field, 0, sizeof(GF_FieldInfo));
99 90 : field->fieldType = fieldType;
100 90 : field->far_ptr = gf_sg_vrml_field_pointer_new(fieldType);
101 90 : field->name = (const char *) fieldName;
102 90 : field->fieldIndex = gf_list_count(priv->ddf);
103 90 : gf_list_add(priv->ddf, field);
104 90 : }
105 :
106 0 : static void isdev_add_field(GF_InputSensorDevice *dev, u32 fieldType, const char *fieldName)
107 : {
108 0 : if (dev) {
109 0 : GF_InputSensorCtx *is = (GF_InputSensorCtx *)dev->input_stream_context;
110 0 : add_field(is, fieldType, fieldName);
111 : }
112 0 : }
113 :
114 15 : static void isdev_dispatch_frame(struct __input_device *dev, const u8 *data, u32 data_len)
115 : {
116 : u32 i;
117 : GF_InputSensorCtx *is_ctx;
118 : GF_InputSensorCtx *priv;
119 30 : if (!dev || !data) return;
120 :
121 0 : priv = (GF_InputSensorCtx *)dev->input_stream_context;
122 :
123 : /*get all decoders and send frame*/
124 0 : i=0;
125 0 : while ((is_ctx = gf_list_enum(priv->odm->parentscene->compositor->input_streams, &i))) {
126 0 : if (is_ctx->type==priv->type) {
127 0 : IS_ProcessData(is_ctx, data, data_len);
128 : }
129 : }
130 : }
131 :
132 61 : static GF_InputSensorCtx *locate_is_ctx_for_odm(GF_Scene *scene, GF_ObjectManager *for_odm)
133 : {
134 : u32 i, count;
135 61 : count = gf_list_count(scene->compositor->input_streams);
136 18 : for (i=0; i<count; i++) {
137 63 : GF_InputSensorCtx *is_ctx = gf_list_get(scene->compositor->input_streams, i);
138 63 : if (is_ctx->odm == for_odm) return is_ctx;
139 : }
140 : return NULL;
141 : }
142 :
143 15 : GF_Err gf_input_sensor_setup_object(GF_ObjectManager *odm, GF_ESD *esd)
144 : {
145 : u32 i;
146 : GF_InputSensorCtx *is_ctx;
147 : GF_BitStream *bs;
148 : u32 len, size;
149 : char devName[255];
150 : u16 termSeq[20];
151 15 : GF_Scene *scene = odm->parentscene;
152 :
153 15 : if (esd->URLString) return GF_NOT_SUPPORTED;
154 :
155 15 : if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->dataLength) return GF_NON_COMPLIANT_BITSTREAM;
156 :
157 15 : if (!scene->compositor->input_streams) {
158 9 : scene->compositor->input_streams = gf_list_new();
159 9 : if (!scene->compositor->input_streams) return GF_OUT_OF_MEM;
160 : }
161 15 : is_ctx = locate_is_ctx_for_odm(scene, odm);
162 15 : if (is_ctx) return GF_OK;
163 :
164 15 : GF_SAFEALLOC(is_ctx, GF_InputSensorCtx);
165 15 : if (!is_ctx) return GF_OUT_OF_MEM;
166 :
167 15 : is_ctx->odm = odm;
168 15 : is_ctx->is_nodes = gf_list_new();
169 15 : is_ctx->ddf = gf_list_new();
170 :
171 15 : is_ctx->ES_ID = esd->ESID;
172 : /*parse config*/
173 15 : bs = gf_bs_new(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_BITSTREAM_READ);
174 15 : len = gf_bs_read_int(bs, 8);
175 133 : for (i=0; i<len; i++) {
176 118 : devName[i] = gf_bs_read_int(bs, 8);
177 : }
178 15 : gf_bs_del(bs);
179 15 : devName[i] = 0;
180 15 : is_ctx->type = gf_crc_32(devName, len);
181 15 : size = len + 1;
182 :
183 15 : if (!stricmp(devName, "KeySensor")) {
184 9 : is_ctx->type = IS_KeySensor;
185 9 : add_field(is_ctx, GF_SG_VRML_SFINT32, "keyPressed");
186 9 : add_field(is_ctx, GF_SG_VRML_SFINT32, "keyReleased");
187 9 : add_field(is_ctx, GF_SG_VRML_SFINT32, "actionKeyPressed");
188 9 : add_field(is_ctx, GF_SG_VRML_SFINT32, "actionKeyReleased");
189 9 : add_field(is_ctx, GF_SG_VRML_SFBOOL, "shiftKeyPressed");
190 9 : add_field(is_ctx, GF_SG_VRML_SFBOOL, "controlKeyPressed");
191 9 : add_field(is_ctx, GF_SG_VRML_SFBOOL, "altKeyPressed");
192 :
193 6 : } else if (!stricmp(devName, "StringSensor")) {
194 1 : is_ctx->type = IS_StringSensor;
195 1 : add_field(is_ctx, GF_SG_VRML_SFSTRING, "enteredText");
196 1 : add_field(is_ctx, GF_SG_VRML_SFSTRING, "finalText");
197 :
198 1 : is_ctx->termChar = '\r';
199 1 : is_ctx->delChar = '\b';
200 :
201 : /*get escape chars if any specified*/
202 1 : if (size<esd->decoderConfig->decoderSpecificInfo->dataLength) {
203 0 : const char *src = esd->decoderConfig->decoderSpecificInfo->data + size;
204 0 : gf_utf8_mbstowcs(termSeq, esd->decoderConfig->decoderSpecificInfo->dataLength - size, &src);
205 0 : is_ctx->termChar = termSeq[0];
206 0 : is_ctx->delChar = termSeq[1];
207 : }
208 5 : } else if (!stricmp(devName, "Mouse")) {
209 5 : is_ctx->type = IS_Mouse;
210 5 : add_field(is_ctx, GF_SG_VRML_SFVEC2F, "position");
211 5 : add_field(is_ctx, GF_SG_VRML_SFBOOL, "leftButtonDown");
212 5 : add_field(is_ctx, GF_SG_VRML_SFBOOL, "middleButtonDown");
213 5 : add_field(is_ctx, GF_SG_VRML_SFBOOL, "rightButtonDown");
214 5 : add_field(is_ctx, GF_SG_VRML_SFFLOAT, "wheel");
215 : }
216 : else {
217 : GF_InputSensorDevice *ifce;
218 : /*not found, check all modules*/
219 0 : u32 plugCount = gf_modules_count();
220 0 : for (i = 0; i < plugCount ; i++) {
221 0 : ifce = (GF_InputSensorDevice *) gf_modules_load(i, GF_INPUT_DEVICE_INTERFACE);
222 0 : if (!ifce) continue;
223 0 : ifce->input_stream_context = is_ctx;
224 0 : if (ifce->RegisterDevice && ifce->RegisterDevice(ifce, devName, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, isdev_add_field) ) {
225 0 : is_ctx->io_dev = ifce;
226 0 : break;
227 : }
228 0 : gf_modules_close_interface((GF_BaseInterface *) ifce);
229 : }
230 0 : if (!is_ctx->io_dev) {
231 0 : gf_free(is_ctx);
232 0 : return GF_NOT_SUPPORTED;
233 : }
234 0 : is_ctx->io_dev->DispatchFrame = isdev_dispatch_frame;
235 : }
236 :
237 : #ifdef GPAC_ENABLE_COVERAGE
238 15 : if (gf_sys_is_cov_mode()) {
239 : isdev_add_field(NULL, 0, NULL);
240 15 : isdev_dispatch_frame(NULL, NULL, 0);
241 : }
242 : #endif
243 :
244 15 : gf_list_add(is_ctx->odm->parentscene->compositor->input_streams, is_ctx);
245 15 : return GF_OK;
246 : }
247 :
248 16 : void gf_input_sensor_delete(GF_ObjectManager *odm)
249 : {
250 : /*get IS dec*/
251 16 : GF_InputSensorCtx *is_ctx = locate_is_ctx_for_odm(odm->parentscene, odm);
252 16 : if (!is_ctx) return;
253 :
254 15 : gf_list_del(is_ctx->is_nodes);
255 :
256 120 : while (gf_list_count(is_ctx->ddf)) {
257 90 : GF_FieldInfo *fi = (GF_FieldInfo *)gf_list_get(is_ctx->ddf, 0);
258 90 : gf_list_rem(is_ctx->ddf, 0);
259 90 : gf_sg_vrml_field_pointer_del(fi->far_ptr, fi->fieldType);
260 90 : gf_free(fi);
261 : }
262 15 : gf_list_del(is_ctx->ddf);
263 15 : gf_list_del_item(odm->parentscene->compositor->input_streams, is_ctx);
264 15 : gf_free(is_ctx);
265 : }
266 :
267 :
268 :
269 59 : static GF_Err IS_ProcessData(GF_InputSensorCtx *is_ctx, const char *inBuffer, u32 inBufferLength)
270 : {
271 : u32 i, j, count;
272 : Double scene_time;
273 : GF_BitStream *bs;
274 : GF_FieldInfo *field;
275 : ISStack *st;
276 : GF_Err e = GF_OK;
277 :
278 : /*decode data frame except if local stringSensor*/
279 59 : bs = gf_bs_new((u8 *)inBuffer, inBufferLength, GF_BITSTREAM_READ);
280 59 : i=0;
281 389 : while ((field = (GF_FieldInfo *)gf_list_enum(is_ctx->ddf, &i))) {
282 : /*store present flag in eventIn for command skip - this is an ugly hack but it works since DDF don't have event types*/
283 271 : field->eventType = gf_bs_read_int(bs, 1);
284 : /*parse val ourselves (we don't want to depend on bifs codec)*/
285 271 : if (field->eventType) {
286 49 : switch (field->fieldType) {
287 7 : case GF_SG_VRML_SFBOOL:
288 7 : * ((SFBool *) field->far_ptr) = (SFBool) gf_bs_read_int(bs, 1);
289 7 : break;
290 0 : case GF_SG_VRML_SFFLOAT:
291 0 : *((SFFloat *)field->far_ptr) = FLT2FIX( gf_bs_read_float(bs) );
292 0 : break;
293 6 : case GF_SG_VRML_SFINT32:
294 6 : *((SFInt32 *)field->far_ptr) = (s32) gf_bs_read_int(bs, 32);
295 6 : break;
296 0 : case GF_SG_VRML_SFTIME:
297 0 : *((SFTime *)field->far_ptr) = gf_bs_read_double(bs);
298 0 : break;
299 36 : case GF_SG_VRML_SFVEC2F:
300 36 : ((SFVec2f *)field->far_ptr)->x = FLT2FIX( gf_bs_read_float(bs) );
301 36 : ((SFVec2f *)field->far_ptr)->y = FLT2FIX( gf_bs_read_float(bs) );
302 36 : break;
303 0 : case GF_SG_VRML_SFVEC3F:
304 0 : ((SFVec3f *)field->far_ptr)->x = FLT2FIX( gf_bs_read_float(bs) );
305 0 : ((SFVec3f *)field->far_ptr)->y = FLT2FIX( gf_bs_read_float(bs) );
306 0 : ((SFVec3f *)field->far_ptr)->z = FLT2FIX( gf_bs_read_float(bs) );
307 0 : break;
308 0 : case GF_SG_VRML_SFCOLOR:
309 0 : ((SFColor *)field->far_ptr)->red = FLT2FIX( gf_bs_read_float(bs) );
310 0 : ((SFColor *)field->far_ptr)->green = FLT2FIX( gf_bs_read_float(bs) );
311 0 : ((SFColor *)field->far_ptr)->blue = FLT2FIX( gf_bs_read_float(bs) );
312 0 : break;
313 0 : case GF_SG_VRML_SFVEC4F:
314 : case GF_SG_VRML_SFROTATION:
315 0 : ((SFRotation *)field->far_ptr)->x = FLT2FIX( gf_bs_read_float(bs) );
316 0 : ((SFRotation *)field->far_ptr)->y = FLT2FIX( gf_bs_read_float(bs) );
317 0 : ((SFRotation *)field->far_ptr)->z = FLT2FIX( gf_bs_read_float(bs) );
318 0 : ((SFRotation *)field->far_ptr)->q = FLT2FIX( gf_bs_read_float(bs) );
319 0 : break;
320 :
321 0 : case GF_SG_VRML_SFSTRING:
322 : {
323 : u32 size, length;
324 0 : size = gf_bs_read_int(bs, 5);
325 0 : length = gf_bs_read_int(bs, size);
326 0 : if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM;
327 :
328 0 : if ( ((SFString *)field->far_ptr)->buffer ) gf_free( ((SFString *)field->far_ptr)->buffer);
329 0 : ((SFString *)field->far_ptr)->buffer = (char*)gf_malloc(sizeof(char)*(length+1));
330 0 : if ( ((SFString *)field->far_ptr)->buffer) {
331 0 : for (j=0; j<length; j++) {
332 0 : ((SFString *)field->far_ptr)->buffer[j] = gf_bs_read_int(bs, 8);
333 : }
334 0 : ((SFString *)field->far_ptr)->buffer[length] = 0;
335 : } else {
336 0 : gf_bs_del(bs);
337 0 : return GF_OUT_OF_MEM;
338 : }
339 : }
340 0 : break;
341 : }
342 : }
343 : }
344 59 : gf_bs_del(bs);
345 :
346 : /*special case for StringSensor in local mode: lookup for special chars*/
347 59 : if (is_ctx->type == IS_StringSensor) {
348 : char tmp_utf8[5000];
349 : const unsigned short *ptr;
350 : u32 len;
351 14 : GF_FieldInfo *field1 = (GF_FieldInfo *)gf_list_get(is_ctx->ddf, 0);
352 14 : GF_FieldInfo *field2 = (GF_FieldInfo *)gf_list_get(is_ctx->ddf, 1);
353 14 : SFString *inText = (SFString *) field1->far_ptr;
354 14 : SFString *outText = (SFString *) field2->far_ptr;
355 :
356 14 : field1->eventType = field2->eventType = 0;
357 14 : is_ctx->enteredText[is_ctx->text_len] = (short) '\0';
358 :
359 14 : len = (u32) gf_utf8_wcslen(is_ctx->enteredText);
360 14 : if (len && (is_ctx->enteredText[len-1] == is_ctx->termChar)) {
361 1 : ptr = is_ctx->enteredText;
362 1 : len = (u32) gf_utf8_wcstombs(tmp_utf8, 5000, &ptr);
363 1 : if (outText->buffer) gf_free(outText->buffer);
364 1 : outText->buffer = (char*)gf_malloc(sizeof(char) * (len));
365 1 : memcpy(outText->buffer, tmp_utf8, sizeof(char) * len-1);
366 1 : outText->buffer[len-1] = 0;
367 1 : if (inText->buffer) gf_free(inText->buffer);
368 1 : inText->buffer = NULL;
369 1 : is_ctx->text_len = 0;
370 :
371 1 : field1->eventType = field2->eventType = 1;
372 : } else {
373 13 : if (is_ctx->delChar) {
374 : /*remove chars*/
375 13 : if ((len>1) && (is_ctx->enteredText[len-1] == is_ctx->delChar)) {
376 4 : is_ctx->enteredText[len-1] = (short) '\0';
377 : len--;
378 4 : is_ctx->enteredText[len-1] = (short) '\0';
379 : len--;
380 : }
381 : }
382 13 : is_ctx->text_len = len;
383 13 : ptr = is_ctx->enteredText;
384 13 : len = (u32) gf_utf8_wcstombs(tmp_utf8, 5000, &ptr);
385 13 : if (inText->buffer) gf_free(inText->buffer);
386 13 : inText->buffer = (char*)gf_malloc(sizeof(char) * (len+1));
387 : memcpy(inText->buffer, tmp_utf8, sizeof(char) * len);
388 13 : inText->buffer[len] = 0;
389 13 : field1->eventType = 1;
390 : }
391 : }
392 :
393 : //we still need this since we have no clue when the device sensor is calling us
394 : //TO CLEANUP (define PIDs and filters for input sensors and put them in the main thread ?)
395 59 : gf_sc_lock(is_ctx->odm->parentscene->compositor, GF_TRUE);
396 :
397 : /*apply it*/
398 59 : i=0;
399 177 : while ((st = (ISStack*)gf_list_enum(is_ctx->is_nodes, &i))) {
400 : assert(st->is);
401 : assert(st->mo);
402 59 : if (!st->is->enabled) continue;
403 :
404 59 : count = gf_list_count(st->is->buffer.commandList);
405 59 : scene_time = gf_scene_get_time(is_ctx->odm->parentscene);
406 330 : for (j=0; j<count; j++) {
407 271 : GF_Command *com = (GF_Command *)gf_list_get(st->is->buffer.commandList, j);
408 271 : GF_CommandField *info = (GF_CommandField *)gf_list_get(com->command_fields, 0);
409 271 : field = (GF_FieldInfo *)gf_list_get(is_ctx->ddf, j);
410 271 : if (info && field && field->eventType) {
411 64 : gf_sg_vrml_field_copy(info->field_ptr, field->far_ptr, field->fieldType);
412 64 : gf_sg_command_apply(is_ctx->odm->parentscene->graph, com, scene_time);
413 : }
414 : }
415 : }
416 59 : gf_sc_lock(is_ctx->odm->parentscene->compositor, GF_FALSE);
417 59 : return e;
418 : }
419 :
420 :
421 : /*
422 : input sensor node handling
423 : */
424 15 : static void InputSensorUnregister(GF_Node *node, ISStack *st)
425 : {
426 : GF_ObjectManager *odm;
427 : GF_InputSensorCtx *is_ctx;
428 :
429 15 : gf_mo_unregister(node, st->mo);
430 :
431 15 : odm = st->mo->odm;
432 15 : if (!odm) return;
433 :
434 : assert(odm->type == GF_STREAM_INTERACT);
435 :
436 : /*get IS dec*/
437 15 : is_ctx = locate_is_ctx_for_odm(odm->parentscene, odm);
438 15 : if (!is_ctx) return;
439 :
440 15 : gf_list_del_item(is_ctx->is_nodes, st);
441 :
442 :
443 : /*stop stream*/
444 15 : if (st->mo->num_open) gf_mo_stop(&st->mo);
445 15 : st->mo = NULL;
446 15 : if (st->registered) {
447 15 : st->registered = 0;
448 15 : if (is_ctx->io_dev && is_ctx->io_dev->Stop) is_ctx->io_dev->Stop(is_ctx->io_dev);
449 : }
450 : }
451 :
452 25 : static void InputSensorRegister(GF_Node *n)
453 : {
454 : GF_ObjectManager *odm;
455 : GF_InputSensorCtx *is_ctx;
456 : u32 i;
457 25 : ISStack *st = (ISStack *)gf_node_get_private(n);
458 25 : odm = st->mo->odm;
459 35 : if (!odm || (odm->type != GF_STREAM_INTERACT)) return;
460 :
461 : assert(odm->type == GF_STREAM_INTERACT);
462 :
463 : /*get IS dec*/
464 15 : is_ctx = locate_is_ctx_for_odm(odm->parentscene, odm);
465 15 : if (!is_ctx) return;
466 :
467 15 : if ( gf_list_find(is_ctx->is_nodes, st) == -1 )
468 15 : gf_list_add(is_ctx->is_nodes, st);
469 :
470 : /*start stream*/
471 15 : gf_mo_play(st->mo, 0, -1, 0);
472 :
473 15 : gf_sc_unqueue_node_traverse(is_ctx->odm->parentscene->compositor, n);
474 :
475 : /*we want at least one sensor enabled*/
476 15 : i=0;
477 30 : while ((st = gf_list_enum(is_ctx->is_nodes, &i))) {
478 15 : if (st->is->enabled) {
479 15 : st->registered = 1;
480 15 : if (is_ctx->io_dev && is_ctx->io_dev->Start) is_ctx->io_dev->Start(is_ctx->io_dev);
481 : break;
482 : }
483 : }
484 : }
485 :
486 447 : static void TraverseInputSensor(GF_Node *node, void *rs, Bool is_destroy)
487 : {
488 447 : ISStack *st = (ISStack*)gf_node_get_private(node);
489 : M_InputSensor *is = (M_InputSensor *)node;
490 :
491 447 : if (is_destroy) {
492 : GF_Scene *scene;
493 15 : if (st->registered) InputSensorUnregister(node, st);
494 15 : scene = (GF_Scene*)gf_sg_get_private(gf_node_get_graph(node));
495 15 : gf_sc_unqueue_node_traverse(scene->compositor, node);
496 15 : gf_free(st);
497 432 : } else if (!st->registered) {
498 : /*get decoder object */
499 25 : if (!st->mo) st->mo = gf_mo_register(node, &is->url, 0, 0);
500 : /*register with decoder*/
501 25 : if (st->mo) InputSensorRegister(node);
502 : }
503 447 : }
504 :
505 :
506 15 : void InitInputSensor(GF_Scene *scene, GF_Node *node)
507 : {
508 : ISStack *stack;
509 15 : GF_SAFEALLOC(stack, ISStack);
510 15 : if (!stack) {
511 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_INTERACT, ("[Terminal] Failed to allocate input sensor stack\n"));
512 : return;
513 : }
514 15 : stack->is = (M_InputSensor *) node;
515 15 : gf_node_set_private(node, stack);
516 15 : gf_node_set_callback_function(node, TraverseInputSensor);
517 :
518 15 : gf_sc_queue_node_traverse(scene->compositor, node);
519 : }
520 :
521 : /*check only URL changes*/
522 3 : void InputSensorModified(GF_Node *node)
523 : {
524 : GF_MediaObject *mo;
525 3 : ISStack *st = (ISStack *)gf_node_get_private(node);
526 :
527 3 : mo = gf_mo_register(node, &st->is->url, 0, 0);
528 3 : if ((mo!=st->mo) || !st->registered) {
529 0 : if (mo!=st->mo) {
530 0 : if (st->mo) InputSensorUnregister(node, st);
531 0 : st->mo = mo;
532 : }
533 0 : if (st->is->enabled)
534 0 : InputSensorRegister(node);
535 : else
536 : return;
537 3 : } else if (!st->is->enabled) {
538 3 : InputSensorUnregister(node, st);
539 3 : return;
540 : }
541 : }
542 :
543 :
544 :
545 : /*
546 : input sensor DDF generations (user interface)
547 : */
548 : GF_EXPORT
549 3889 : void gf_sc_input_sensor_mouse_input(GF_Compositor *compositor, GF_EventMouse *event)
550 : {
551 : s32 X, Y;
552 : u32 left_but_down, middle_but_down, right_but_down;
553 : SFFloat wheel_pos;
554 : u32 i;
555 : GF_BitStream *bs;
556 : u8 *buf;
557 : u32 buf_size;
558 : Fixed bX, bY;
559 : GF_InputSensorCtx *is_ctx;
560 :
561 7716 : if ( !gf_list_count(compositor->input_streams)) return;
562 :
563 62 : X = event->x;
564 62 : Y = event->y;
565 : left_but_down = middle_but_down = right_but_down = 0;
566 : wheel_pos = 0;
567 62 : switch (event->type) {
568 2 : case GF_EVENT_MOUSEDOWN:
569 2 : if (event->button==GF_MOUSE_RIGHT) right_but_down = 2;
570 1 : else if (event->button==GF_MOUSE_MIDDLE) middle_but_down = 2;
571 1 : else if (event->button==GF_MOUSE_LEFT) left_but_down = 2;
572 : break;
573 2 : case GF_EVENT_MOUSEUP:
574 2 : if (event->button==GF_MOUSE_RIGHT) right_but_down = 1;
575 1 : else if (event->button==GF_MOUSE_MIDDLE) middle_but_down = 1;
576 1 : else if (event->button==GF_MOUSE_LEFT) left_but_down = 1;
577 : break;
578 0 : case GF_EVENT_MOUSEWHEEL:
579 0 : wheel_pos = event->wheel_pos;
580 0 : break;
581 : case GF_EVENT_MOUSEMOVE:
582 : break;
583 : default:
584 : return;
585 : }
586 :
587 : /*get BIFS coordinates*/
588 62 : gf_sc_map_point(compositor, X, Y, &bX, &bY);
589 62 : bX = gf_divfix(bX, compositor->scale_x);
590 62 : bY = gf_divfix(bY, compositor->scale_y);
591 :
592 62 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
593 :
594 : /*If wheel is specified disable X and Y (bug from MS wheel handling)*/
595 62 : if (wheel_pos) {
596 0 : gf_bs_write_int(bs, 0, 1);
597 : } else {
598 62 : gf_bs_write_int(bs, 1, 1);
599 62 : gf_bs_write_float(bs, FIX2FLT(bX));
600 62 : gf_bs_write_float(bs, FIX2FLT(bY));
601 : }
602 62 : gf_bs_write_int(bs, left_but_down ? 1 : 0, 1);
603 62 : if (left_but_down) gf_bs_write_int(bs, left_but_down-1, 1);
604 62 : gf_bs_write_int(bs, middle_but_down ? 1 : 0, 1);
605 62 : if (middle_but_down) gf_bs_write_int(bs, middle_but_down-1, 1);
606 62 : gf_bs_write_int(bs, right_but_down ? 1 : 0, 1);
607 62 : if (right_but_down) gf_bs_write_int(bs, right_but_down-1, 1);
608 62 : if (wheel_pos==0) {
609 62 : gf_bs_write_int(bs, 0, 1);
610 : } else {
611 0 : gf_bs_write_int(bs, 1, 1);
612 0 : gf_bs_write_float(bs, FIX2FLT(wheel_pos) );
613 : }
614 :
615 62 : gf_bs_align(bs);
616 62 : gf_bs_get_content(bs, &buf, &buf_size);
617 62 : gf_bs_del(bs);
618 :
619 : /*get all IS Mouse decoders and send frame*/
620 62 : i=0;
621 186 : while ((is_ctx = gf_list_enum(compositor->input_streams, &i))) {
622 62 : if (is_ctx->type==IS_Mouse) {
623 36 : IS_ProcessData(is_ctx, buf, buf_size);
624 : }
625 : }
626 62 : gf_free(buf);
627 : }
628 :
629 : GF_EXPORT
630 146 : Bool gf_sc_input_sensor_keyboard_input(GF_Compositor *compositor, u32 key_code, u32 hw_code, Bool isKeyUp)
631 : {
632 : u32 i;
633 : GF_BitStream *bs;
634 : GF_SLHeader slh;
635 : u8 *buf;
636 : #ifndef GPAC_DISABLE_X3D
637 : X_KeySensor *n;
638 : #endif
639 : GF_InputSensorCtx *is_ctx;
640 : u32 buf_size;
641 : u32 actionKey = 0;
642 : u32 shiftKeyDown, controlKeyDown, altKeyDown;
643 : s32 keyPressed, keyReleased, actionKeyPressed, actionKeyReleased;
644 :
645 146 : if (!gf_list_count(compositor->input_streams) && !gf_list_count(compositor->x3d_sensors)) return 0;
646 :
647 : memset(&slh, 0, sizeof(GF_SLHeader));
648 37 : slh.accessUnitStartFlag = slh.accessUnitEndFlag = 1;
649 37 : slh.compositionTimeStampFlag = 1;
650 : /*cf above*/
651 : slh.compositionTimeStamp = 0;
652 :
653 37 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
654 :
655 : shiftKeyDown = controlKeyDown = altKeyDown = 0;
656 : keyPressed = keyReleased = actionKeyPressed = actionKeyReleased = 0;
657 : /*key-sensor codes*/
658 37 : switch (key_code) {
659 : case GF_KEY_F1:
660 : actionKey = 1;
661 : break;
662 2 : case GF_KEY_F2:
663 : actionKey = 2;
664 2 : break;
665 2 : case GF_KEY_F3:
666 : actionKey = 3;
667 2 : break;
668 0 : case GF_KEY_F4:
669 : actionKey = 4;
670 0 : break;
671 0 : case GF_KEY_F5:
672 : actionKey = 5;
673 0 : break;
674 0 : case GF_KEY_F6:
675 : actionKey = 6;
676 0 : break;
677 0 : case GF_KEY_F7:
678 : actionKey = 7;
679 0 : break;
680 0 : case GF_KEY_F8:
681 : actionKey = 8;
682 0 : break;
683 0 : case GF_KEY_F9:
684 : actionKey = 9;
685 0 : break;
686 0 : case GF_KEY_F10:
687 : actionKey = 10;
688 0 : break;
689 0 : case GF_KEY_F11:
690 : actionKey = 11;
691 0 : break;
692 0 : case GF_KEY_F12:
693 : actionKey = 12;
694 0 : break;
695 0 : case GF_KEY_HOME:
696 : actionKey = 13;
697 0 : break;
698 0 : case GF_KEY_END:
699 : actionKey = 14;
700 0 : break;
701 0 : case GF_KEY_PAGEUP:
702 : actionKey = 15;
703 0 : break;
704 0 : case GF_KEY_PAGEDOWN:
705 : actionKey = 16;
706 0 : break;
707 0 : case GF_KEY_UP:
708 : actionKey = 17;
709 0 : break;
710 0 : case GF_KEY_DOWN:
711 : actionKey = 18;
712 0 : break;
713 0 : case GF_KEY_LEFT:
714 : actionKey = 19;
715 0 : break;
716 0 : case GF_KEY_RIGHT:
717 : actionKey = 20;
718 0 : break;
719 3 : case GF_KEY_SHIFT:
720 : actionKey = 0;
721 3 : shiftKeyDown = isKeyUp ? 1 : 2;
722 : break;
723 0 : case GF_KEY_CONTROL:
724 : actionKey = 0;
725 0 : controlKeyDown = isKeyUp ? 1 : 2;
726 : break;
727 0 : case GF_KEY_ALT:
728 : actionKey = 0;
729 0 : altKeyDown = isKeyUp ? 1 : 2;
730 : break;
731 :
732 28 : default:
733 : actionKey = 0;
734 28 : break;
735 : }
736 37 : if (actionKey) {
737 6 : if (isKeyUp)
738 3 : actionKeyReleased = actionKey;
739 : else
740 3 : actionKeyPressed = actionKey;
741 : } else {
742 : /*handle numeric pad*/
743 31 : if ((key_code>=GF_KEY_0) && (key_code<=GF_KEY_9) ) {
744 0 : key_code = key_code + 0x30 - GF_KEY_0;
745 : }
746 : else
747 : key_code = hw_code;
748 :
749 31 : if (isKeyUp) keyReleased = key_code;
750 16 : else keyPressed = key_code;
751 : }
752 :
753 37 : gf_bs_write_int(bs, keyPressed ? 1 : 0, 1);
754 37 : if (keyPressed) gf_bs_write_int(bs, keyPressed, 32);
755 37 : gf_bs_write_int(bs, keyReleased ? 1 : 0, 1);
756 37 : if (keyReleased) gf_bs_write_int(bs, keyReleased, 32);
757 37 : gf_bs_write_int(bs, actionKeyPressed ? 1 : 0, 1);
758 37 : if (actionKeyPressed) gf_bs_write_int(bs, actionKeyPressed, 32);
759 37 : gf_bs_write_int(bs, actionKeyReleased ? 1 : 0, 1);
760 37 : if (actionKeyReleased) gf_bs_write_int(bs, actionKeyReleased, 32);
761 37 : gf_bs_write_int(bs, shiftKeyDown ? 1 : 0 , 1);
762 37 : if (shiftKeyDown) gf_bs_write_int(bs, shiftKeyDown-1, 1);
763 37 : gf_bs_write_int(bs, controlKeyDown ? 1 : 0 , 1);
764 37 : if (controlKeyDown) gf_bs_write_int(bs, controlKeyDown-1, 1);
765 37 : gf_bs_write_int(bs, altKeyDown ? 1 : 0 , 1);
766 37 : if (altKeyDown) gf_bs_write_int(bs, altKeyDown, 1);
767 :
768 37 : gf_bs_align(bs);
769 37 : gf_bs_get_content(bs, &buf, &buf_size);
770 37 : gf_bs_del(bs);
771 :
772 : /*get all IS keySensor decoders and send frame*/
773 37 : i=0;
774 111 : while ((is_ctx = gf_list_enum(compositor->input_streams, &i))) {
775 37 : if (is_ctx->type==IS_KeySensor) {
776 9 : IS_ProcessData(is_ctx, buf, buf_size);
777 : }
778 : }
779 37 : gf_free(buf);
780 :
781 : #ifndef GPAC_DISABLE_X3D
782 37 : i=0;
783 74 : while ((n = (X_KeySensor*)gf_list_enum(compositor->x3d_sensors, &i))) {
784 : u16 tc[2];
785 : u32 len;
786 : char szStr[10];
787 : const unsigned short *ptr;
788 0 : if (gf_node_get_tag((GF_Node*)n) != TAG_X3D_KeySensor) continue;
789 0 : if (!n->enabled) return 0;
790 :
791 0 : if (keyPressed) {
792 0 : if (n->keyPress.buffer) gf_free(n->keyPress.buffer);
793 0 : tc[0] = keyPressed;
794 0 : tc[1] = 0;
795 0 : ptr = tc;
796 0 : len = (u32) gf_utf8_wcstombs(szStr, 10, &ptr);
797 0 : n->keyPress.buffer = (char*)gf_malloc(sizeof(char) * (len+1));
798 : memcpy(n->keyPress.buffer, szStr, sizeof(char) * len);
799 0 : n->keyPress.buffer[len] = 0;
800 0 : gf_node_event_out_str((GF_Node *)n, "keyPress");
801 : }
802 0 : if (keyReleased) {
803 0 : if (n->keyRelease.buffer) gf_free(n->keyRelease.buffer);
804 0 : tc[0] = keyReleased;
805 0 : tc[1] = 0;
806 0 : ptr = tc;
807 0 : len = (u32) gf_utf8_wcstombs(szStr, 10, &ptr);
808 0 : n->keyRelease.buffer = (char*)gf_malloc(sizeof(char) * (len+1));
809 : memcpy(n->keyRelease.buffer, szStr, sizeof(char) * len);
810 0 : n->keyRelease.buffer[len] = 0;
811 0 : gf_node_event_out_str((GF_Node *)n, "keyRelease");
812 : }
813 0 : if (actionKeyPressed) {
814 0 : n->actionKeyPress = actionKeyPressed;
815 0 : gf_node_event_out_str((GF_Node *)n, "actionKeyPress");
816 : }
817 0 : if (actionKeyReleased) {
818 0 : n->actionKeyRelease = actionKeyReleased;
819 0 : gf_node_event_out_str((GF_Node *)n, "actionKeyRelease");
820 : }
821 0 : if (shiftKeyDown) {
822 0 : n->shiftKey = (shiftKeyDown-1) ? 1 : 0;
823 0 : gf_node_event_out_str((GF_Node *)n, "shiftKey");
824 : }
825 0 : if (controlKeyDown) {
826 0 : n->controlKey = (controlKeyDown-1) ? 1 : 0;
827 0 : gf_node_event_out_str((GF_Node *)n, "controlKey");
828 : }
829 0 : if (altKeyDown) {
830 0 : n->altKey= (altKeyDown-1) ? 1 : 0;
831 0 : gf_node_event_out_str((GF_Node *)n, "altKey");
832 : }
833 0 : if (keyPressed || actionKeyPressed || (shiftKeyDown-1) || (controlKeyDown-1) || (altKeyDown-1)) {
834 0 : if (!n->isActive) {
835 0 : n->isActive = 1;
836 0 : gf_node_event_out_str((GF_Node *)n, "isActive");
837 : }
838 0 : } else if (n->isActive) {
839 0 : n->isActive = 0;
840 0 : gf_node_event_out_str((GF_Node *)n, "isActive");
841 : }
842 : }
843 : #endif
844 : /*with KeySensor, we don't know if the key will be consumed or not, assume it is*/
845 : return 1;
846 : }
847 :
848 : GF_EXPORT
849 14 : void gf_sc_input_sensor_string_input(GF_Compositor *compositor, u32 character)
850 : {
851 : u32 i;
852 : GF_BitStream *bs;
853 : #ifndef GPAC_DISABLE_X3D
854 : X_StringSensor *n;
855 : #endif
856 : GF_InputSensorCtx *is_ctx;
857 : u8 *buf;
858 : u32 buf_size;
859 :
860 14 : if (!character) return;
861 14 : if (!gf_list_count(compositor->input_streams) && !gf_list_count(compositor->x3d_sensors)) return;
862 :
863 : /*get all IS StringSensor decoders and send frame*/
864 14 : i=0;
865 42 : while ((is_ctx = gf_list_enum(compositor->input_streams, &i))) {
866 14 : if (is_ctx->type==IS_StringSensor) {
867 14 : is_ctx->enteredText[is_ctx->text_len] = character;
868 14 : is_ctx->text_len += 1;
869 :
870 : /*write empty DDF*/
871 14 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
872 14 : gf_bs_write_int(bs, 0, 1);
873 14 : gf_bs_write_int(bs, 0, 1);
874 14 : gf_bs_align(bs);
875 14 : gf_bs_get_content(bs, &buf, &buf_size);
876 14 : gf_bs_del(bs);
877 :
878 14 : IS_ProcessData(is_ctx, buf, buf_size);
879 :
880 14 : gf_free(buf);
881 : }
882 : }
883 :
884 :
885 : #ifndef GPAC_DISABLE_X3D
886 : /*get all X3D StringSensors*/
887 14 : i=0;
888 28 : while ((n = (X_StringSensor*)gf_list_enum(compositor->x3d_sensors, &i))) {
889 : StringSensorStack *st;
890 : char szStr[5000];
891 : const unsigned short *ptr;
892 : u32 len;
893 0 : if (gf_node_get_tag((GF_Node*)n) != TAG_X3D_StringSensor) continue;
894 0 : if (!n->enabled) continue;
895 :
896 0 : st = (StringSensorStack *) gf_node_get_private((GF_Node *)n);
897 :
898 0 : if (character=='\b') {
899 0 : if (n->deletionAllowed && st->text_len) {
900 0 : st->text_len -= 1;
901 0 : st->enteredText[st->text_len] = 0;
902 0 : ptr = st->enteredText;
903 0 : len = (u32) gf_utf8_wcstombs(szStr, 10, &ptr);
904 0 : if (n->enteredText.buffer) gf_free(n->enteredText.buffer);
905 0 : szStr[len] = 0;
906 0 : n->enteredText.buffer = gf_strdup(szStr);
907 0 : gf_node_event_out_str((GF_Node *)n, "enteredText");
908 : }
909 0 : } else if (character=='\r') {
910 0 : if (n->finalText.buffer) gf_free(n->finalText.buffer);
911 0 : n->finalText.buffer = n->enteredText.buffer;
912 0 : n->enteredText.buffer = gf_strdup("");
913 0 : st->text_len = 0;
914 0 : gf_node_event_out_str((GF_Node *)n, "enteredText");
915 0 : gf_node_event_out_str((GF_Node *)n, "finalText");
916 : } else {
917 0 : st->enteredText[st->text_len] = character;
918 0 : st->text_len += 1;
919 0 : st->enteredText[st->text_len] = 0;
920 0 : ptr = st->enteredText;
921 0 : len = (u32) gf_utf8_wcstombs(szStr, 10, &ptr);
922 0 : if (n->enteredText.buffer) gf_free(n->enteredText.buffer);
923 0 : szStr[len] = 0;
924 0 : n->enteredText.buffer = gf_strdup(szStr);
925 0 : gf_node_event_out_str((GF_Node *)n, "enteredText");
926 : }
927 : }
928 : #endif
929 : }
930 :
931 : #ifndef GPAC_DISABLE_X3D
932 :
933 6 : void DestroyKeySensor(GF_Node *node, void *rs, Bool is_destroy)
934 : {
935 6 : if (is_destroy) {
936 1 : GF_Compositor *compositor = (GF_Compositor *) gf_node_get_private(node);
937 1 : gf_list_del_item(compositor->x3d_sensors, node);
938 : }
939 6 : }
940 1 : void InitKeySensor(GF_Scene *scene, GF_Node *node)
941 : {
942 1 : gf_node_set_private(node, scene->compositor);
943 1 : gf_node_set_callback_function(node, DestroyKeySensor);
944 1 : if (!scene->compositor->x3d_sensors)
945 1 : scene->compositor->x3d_sensors = gf_list_new();
946 :
947 1 : gf_list_add(scene->compositor->x3d_sensors, node);
948 1 : }
949 :
950 6 : void DestroyStringSensor(GF_Node *node, void *rs, Bool is_destroy)
951 : {
952 6 : if (is_destroy) {
953 1 : StringSensorStack *st = (StringSensorStack *) gf_node_get_private(node);
954 1 : gf_list_del_item(st->compositor->x3d_sensors, node);
955 1 : gf_free(st);
956 : }
957 6 : }
958 1 : void InitStringSensor(GF_Scene *scene, GF_Node *node)
959 : {
960 : StringSensorStack*st;
961 1 : GF_SAFEALLOC(st, StringSensorStack)
962 1 : if (!st) {
963 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_INTERACT, ("[Terminal] Failed to allocate string sensor stack\n"));
964 : return;
965 : }
966 1 : st->compositor = scene->compositor;
967 1 : gf_node_set_private(node, st);
968 1 : gf_node_set_callback_function(node, DestroyStringSensor);
969 :
970 1 : if (!scene->compositor->x3d_sensors)
971 1 : scene->compositor->x3d_sensors = gf_list_new();
972 :
973 1 : gf_list_add(scene->compositor->x3d_sensors, node);
974 : }
975 :
976 : #endif /*GPAC_DISABLE_X3D*/
977 :
978 : #else
979 : GF_EXPORT
980 : void gf_sc_input_sensor_mouse_input(GF_Compositor *compositor, GF_EventMouse *event)
981 : {
982 : }
983 : GF_EXPORT
984 : Bool gf_sc_input_sensor_keyboard_input(GF_Compositor *compositor, u32 key_code, u32 hw_code, Bool isKeyUp)
985 : {
986 : return GF_TRUE;
987 : }
988 : GF_EXPORT
989 : void gf_sc_input_sensor_string_input(GF_Compositor *compositor, u32 character)
990 : {
991 : }
992 :
993 : #endif /*GPAC_DISABLE_VRML*/
|