📄 input_sensor.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Media terminal sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/terminal_dev.h>#include <gpac/utf.h>#include <gpac/nodes_x3d.h>#include <gpac/constants.h>/*for screen to BIFS coordinate mapping (MouseSensor) */#include <gpac/renderer.h>#include "input_sensor.h"#if GPAC_HTK_DEMOvoid HTK_Init(const char *htk_path);void HTK_Close(void);void HTK_SetDictionary(char *dicofile);void HTK_DoDetection(void);const char *HTK_GetWord();int HTK_GetWordIndex();float HTK_GetWordScore();void StartHTK(ISPriv *is_dec);static u32 htk_num_users = 0;#endif/* input sensor decoder(s) handling*/GF_Err IS_Configure(GF_BaseDecoder *plug, GF_InlineScene *scene, Bool is_remote){ ISPriv *is = (ISPriv *)plug->privateStack; /*we can only deal with encoded content (for now)*/ if (!scene->scene_codec) return GF_NOT_SUPPORTED; is->scene = scene; is->is_local = !is_remote; return GF_OK;}static void add_field(ISPriv *priv, u32 fieldType, const char *fieldName){ GF_FieldInfo *field = (GF_FieldInfo *) malloc(sizeof(GF_FieldInfo)); memset(field, 0, sizeof(GF_FieldInfo)); field->fieldType = fieldType; field->far_ptr = gf_sg_vrml_field_pointer_new(fieldType); field->name = (const char *) fieldName; field->fieldIndex = gf_list_count(priv->ddf); gf_list_add(priv->ddf, field);}static GF_Err IS_AttachStream(GF_BaseDecoder *plug, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool Upstream){ GF_BitStream *bs; u32 len, size, i; char devName[255]; u16 termSeq[20]; ISPriv *is = (ISPriv *)plug->privateStack; if (Upstream) return GF_NOT_SUPPORTED; if (!decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM; /*no more than one UI stream per object*/ if (is->ES_ID) return GF_NOT_SUPPORTED; is->ES_ID = ES_ID; /*parse config*/ bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ); len = gf_bs_read_int(bs, 8); for (i=0; i<len; i++) { devName[i] = gf_bs_read_int(bs, 8); } devName[i] = 0; size = len + 1; is->type = 0; if (!stricmp(devName, "KeySensor")) { is->type = IS_KeySensor; add_field(is, GF_SG_VRML_SFINT32, "keyPressed"); add_field(is, GF_SG_VRML_SFINT32, "keyReleased"); add_field(is, GF_SG_VRML_SFINT32, "actionKeyPressed"); add_field(is, GF_SG_VRML_SFINT32, "actionKeyReleased"); add_field(is, GF_SG_VRML_SFBOOL, "shiftKeyPressed"); add_field(is, GF_SG_VRML_SFBOOL, "controlKeyPressed"); add_field(is, GF_SG_VRML_SFBOOL, "altKeyPressed"); } else if (!stricmp(devName, "StringSensor")) { is->type = IS_StringSensor; add_field(is, GF_SG_VRML_SFSTRING, "enteredText"); add_field(is, GF_SG_VRML_SFSTRING, "finalText"); is->termChar = '\r'; is->delChar = '\b'; /*get escape chars if any specified*/ if (size<decSpecInfoSize) { const char *src = decSpecInfo + size; gf_utf8_mbstowcs(termSeq, decSpecInfoSize - size, &src); is->termChar = termSeq[0]; is->delChar = termSeq[1]; } } else if (!stricmp(devName, "Mouse")) { is->type = IS_Mouse; add_field(is, GF_SG_VRML_SFVEC2F, "position"); add_field(is, GF_SG_VRML_SFBOOL, "leftButtonDown"); add_field(is, GF_SG_VRML_SFBOOL, "middleButtonDown"); add_field(is, GF_SG_VRML_SFBOOL, "rightButtonDown"); add_field(is, GF_SG_VRML_SFFLOAT, "wheel");#if GPAC_HTK_DEMO } else if (!stricmp(devName, "HTKSensor")) { FILE *f; u32 nb_word, nbPhone, c, j; char szPh[3]; char szName[1024]; char *szPath = gf_cfg_get_key(is->scene->root_od->term->user->config, "HTK", "HTKDirectory"); if (!szPath) szPath = gf_cfg_get_key(is->scene->root_od->term->user->config, "General", "ModulesDirectory"); strcpy(is->szHTKPath, szPath); if (szPath[strlen(szPath)-1] != GF_PATH_SEPARATOR) is->szHTKPath[strlen(szPath)] = GF_PATH_SEPARATOR; add_field(is, GF_SG_VRML_SFSTRING, "word"); add_field(is, GF_SG_VRML_SFINT32, "wordIndex"); add_field(is, GF_SG_VRML_SFFLOAT, "wordScore"); if (!htk_num_users) { HTK_Init(is->szHTKPath); htk_num_users++; } sprintf(szName, "HTKD_%d", (u32) is); strcat(is->szHTKPath, szName); f = fopen(is->szHTKPath, "wt"); szPh[2] = 0; nb_word = gf_bs_read_int(bs, 8); for (i=0; i<nb_word; i++) { nbPhone = gf_bs_read_int(bs, 8); while ((c=gf_bs_read_int(bs, 8))) fprintf(f, "%c", c); fprintf(f, " "); for (j=0; j<nbPhone; j++) { gf_bs_read_data(bs, szPh, 2); if (j) fprintf(f, " "); if (!stricmp(szPh, "vc")) fprintf(f, "vcl"); else fprintf(f, "%s", szPh); } fprintf(f, "\n"); } fprintf(f, "RIEN sp\nSENT-END [] endsil\nSENT-START [] inisil\n"); fclose(f); is->type = IS_HTKSensor; StartHTK(is);#endif } gf_bs_del(bs); return GF_OK;}static GF_Err IS_DetachStream(GF_BaseDecoder *plug, u16 ES_ID){ ISPriv *is = (ISPriv *)plug->privateStack; is->ES_ID = 0;#if GPAC_HTK_DEMO if (htk_num_users) { htk_num_users--; if (!htk_num_users) { while (is->htk_running) gf_sleep(10); HTK_Close(); } }#endif return GF_OK;}static GF_Err IS_GetCapabilities(GF_BaseDecoder *plug, GF_CodecCapability *capability){ capability->cap.valueInt = 0; return GF_OK;}static GF_Err IS_SetCapabilities(GF_BaseDecoder *plug, const GF_CodecCapability capability){ return GF_OK;}static GF_Err IS_ProcessData(GF_SceneDecoder *plug, char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 AU_time, u32 mmlevel){ u32 i, j, count; Double scene_time; GF_BitStream *bs; GF_FieldInfo *field; ISStack *st; ISPriv *priv = (ISPriv *)plug->privateStack; GF_Err e = GF_OK; /*decode data frame except if local stringSensor*/ bs = gf_bs_new(inBuffer, inBufferLength, GF_BITSTREAM_READ); i=0; while ((field = (GF_FieldInfo *)gf_list_enum(priv->ddf, &i))) { /*store present flag in eventIn for command skip - this is an ugly hack but it works since DDF don't have event types*/ field->eventType = gf_bs_read_int(bs, 1); /*parse val ourselves (we don't want to depend on bifs codec)*/ if (field->eventType) { switch (field->fieldType) { case GF_SG_VRML_SFBOOL: * ((SFBool *) field->far_ptr) = (SFBool) gf_bs_read_int(bs, 1); break; case GF_SG_VRML_SFFLOAT: *((SFFloat *)field->far_ptr) = FLT2FIX( gf_bs_read_float(bs) ); break; case GF_SG_VRML_SFINT32: *((SFInt32 *)field->far_ptr) = (s32) gf_bs_read_int(bs, 32); break; case GF_SG_VRML_SFTIME: *((SFTime *)field->far_ptr) = gf_bs_read_double(bs); break; case GF_SG_VRML_SFVEC2F: ((SFVec2f *)field->far_ptr)->x = FLT2FIX( gf_bs_read_float(bs) ); ((SFVec2f *)field->far_ptr)->y = FLT2FIX( gf_bs_read_float(bs) ); break; case GF_SG_VRML_SFVEC3F: ((SFVec3f *)field->far_ptr)->x = FLT2FIX( gf_bs_read_float(bs) ); ((SFVec3f *)field->far_ptr)->y = FLT2FIX( gf_bs_read_float(bs) ); ((SFVec3f *)field->far_ptr)->z = FLT2FIX( gf_bs_read_float(bs) ); break; case GF_SG_VRML_SFCOLOR: ((SFColor *)field->far_ptr)->red = FLT2FIX( gf_bs_read_float(bs) ); ((SFColor *)field->far_ptr)->green = FLT2FIX( gf_bs_read_float(bs) ); ((SFColor *)field->far_ptr)->blue = FLT2FIX( gf_bs_read_float(bs) ); break; case GF_SG_VRML_SFVEC4F: case GF_SG_VRML_SFROTATION: ((SFRotation *)field->far_ptr)->x = FLT2FIX( gf_bs_read_float(bs) ); ((SFRotation *)field->far_ptr)->y = FLT2FIX( gf_bs_read_float(bs) ); ((SFRotation *)field->far_ptr)->z = FLT2FIX( gf_bs_read_float(bs) ); ((SFRotation *)field->far_ptr)->q = FLT2FIX( gf_bs_read_float(bs) ); break; case GF_SG_VRML_SFSTRING: { u32 size, length; size = gf_bs_read_int(bs, 5); length = gf_bs_read_int(bs, size); if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM; if ( ((SFString *)field->far_ptr)->buffer ) free( ((SFString *)field->far_ptr)->buffer); ((SFString *)field->far_ptr)->buffer = (char*)malloc(sizeof(char)*(length+1)); memset(((SFString *)field->far_ptr)->buffer , 0, length+1); for (j=0; j<length; j++) { ((SFString *)field->far_ptr)->buffer[j] = gf_bs_read_int(bs, 8); } } break; } } } gf_bs_del(bs); /*special case for StringSensor in local mode: lookup for special chars*/ if ((priv->type == IS_StringSensor) && priv->is_local) { char tmp_utf8[5000]; const unsigned short *ptr; u32 len; GF_FieldInfo *field1 = (GF_FieldInfo *)gf_list_get(priv->ddf, 0); GF_FieldInfo *field2 = (GF_FieldInfo *)gf_list_get(priv->ddf, 1); SFString *inText = (SFString *) field1->far_ptr; SFString *outText = (SFString *) field2->far_ptr; field1->eventType = field2->eventType = 0; priv->enteredText[priv->text_len] = (short) '\0'; len = gf_utf8_wcslen(priv->enteredText); if (len && (priv->enteredText[len-1] == priv->termChar)) { ptr = priv->enteredText; len = gf_utf8_wcstombs(tmp_utf8, 5000, &ptr); if (outText->buffer) free(outText->buffer); outText->buffer = (char*)malloc(sizeof(char) * (len+1)); memcpy(outText->buffer, tmp_utf8, sizeof(char) * len); outText->buffer[len] = 0; if (inText->buffer) free(inText->buffer); inText->buffer = NULL; priv->text_len = 0; field1->eventType = field2->eventType = 1; } else { if (priv->delChar) { /*remove chars*/ if ((len>1) && (priv->enteredText[len-1] == priv->delChar)) { priv->enteredText[len-1] = (short) '\0'; len--; if (len) { priv->enteredText[len-1] = (short) '\0'; len--; } } } priv->text_len = len; ptr = priv->enteredText; len = gf_utf8_wcstombs(tmp_utf8, 5000, &ptr); if (inText->buffer) free(inText->buffer); inText->buffer = (char*)malloc(sizeof(char) * (len+1)); memcpy(inText->buffer, tmp_utf8, sizeof(char) * len); inText->buffer[len] = 0; field1->eventType = 1; } } /*apply it*/ i=0; while ((st = (ISStack*)gf_list_enum(priv->is_nodes, &i))) { assert(st->is); assert(st->mo); if (!st->is->enabled) continue; count = gf_list_count(st->is->buffer.commandList); scene_time = gf_is_get_time(priv->scene); for (j=0; j<count; j++) { GF_Command *com = (GF_Command *)gf_list_get(st->is->buffer.commandList, j); GF_FieldInfo *field = (GF_FieldInfo *)gf_list_get(priv->ddf, j); GF_CommandField *info = (GF_CommandField *)gf_list_get(com->command_fields, 0); if (info && field && field->eventType) { gf_sg_vrml_field_copy(info->field_ptr, field->far_ptr, field->fieldType); gf_sg_command_apply(priv->scene->graph, com, scene_time); } } } return e;}void ISDec_Delete(GF_BaseDecoder *plug){ ISPriv *priv = (ISPriv *)plug->privateStack; gf_list_del(priv->is_nodes); while (gf_list_count(priv->ddf)) { GF_FieldInfo *fi = (GF_FieldInfo *)gf_list_get(priv->ddf, 0); gf_list_rem(priv->ddf, 0); gf_sg_vrml_field_pointer_del(fi->far_ptr, fi->fieldType); free(fi); } gf_list_del(priv->ddf);#if GPAC_HTK_DEMO gf_th_del(priv->th);#endif free(priv); free(plug);}GF_BaseDecoder *NewISCodec(u32 PL){ ISPriv *priv; GF_SceneDecoder *tmp; tmp = (GF_SceneDecoder*) malloc(sizeof(GF_SceneDecoder)); if (!tmp) return NULL; memset(tmp, 0, sizeof(GF_SceneDecoder)); priv = (ISPriv *) malloc(sizeof(ISPriv)); memset(priv, 0, sizeof(ISPriv)); priv->is_nodes = gf_list_new(); priv->ddf = gf_list_new(); tmp->privateStack = priv; tmp->AttachStream = IS_AttachStream; tmp->DetachStream = IS_DetachStream; tmp->GetCapabilities = IS_GetCapabilities; tmp->SetCapabilities = IS_SetCapabilities; tmp->ProcessData = IS_ProcessData; /*we don't use this...*/ tmp->AttachScene = NULL; GF_REGISTER_MODULE_INTERFACE(tmp, GF_SCENE_DECODER_INTERFACE, "GPAC InputSensor Decoder", "gpac distribution")#if GPAC_HTK_DEMO priv->th = gf_th_new();#endif return (GF_BaseDecoder *) tmp;}/* input sensor node handling*/static void IS_Unregister(ISStack *st){ u32 i; GF_ObjectManager *odm; ISPriv *is_dec; odm = st->mo->odm; if (!odm) return; assert(odm->codec && (odm->codec->type == GF_STREAM_INTERACT)); /*get IS dec*/ is_dec = (ISPriv*)odm->codec->decio->privateStack; for (i=0; i<gf_list_count(is_dec->is_nodes); i++) { ISStack *tmp = (ISStack *)gf_list_get(is_dec->is_nodes, i); if (tmp == st) { gf_list_rem(is_dec->is_nodes, i); i--; } } /*stop stream*/ if (st->mo->num_open) gf_mo_stop(st->mo); st->mo = NULL; st->registered = 0;}static void IS_Register(GF_Node *n){ GF_ObjectManager *odm; ISPriv *is_dec; ISStack *st = (ISStack *)gf_node_get_private(n); odm = st->mo->odm; if (!odm) return; assert(odm->codec && (odm->codec->type == GF_STREAM_INTERACT)); /*get IS dec*/ is_dec = (ISPriv*)odm->codec->decio->privateStack; gf_list_add(is_dec->is_nodes, st); st->registered = 1;#if GPAC_HTK_DEMO StartHTK(is_dec);#endif /*start stream*/ gf_mo_play(st->mo, 0, -1, 0); gf_term_rem_render_node(odm->term, n);}static void RenderInputSensor(GF_Node *node, void *rs, Bool is_destroy){ ISStack *st = (ISStack*)gf_node_get_private(node); M_InputSensor *is = (M_InputSensor *)node; if (is_destroy) { GF_InlineScene *is; if (st->registered) IS_Unregister(st); is = (GF_InlineScene*)gf_sg_get_private(gf_node_get_graph(node)); gf_term_rem_render_node(is->root_od->term, node); free(st); } else { /*get decoder object */ if (!st->mo) st->mo = gf_mo_find(node, &is->url, 0); /*register with decoder*/ if (st->mo && !st->registered) IS_Register(node); }}void InitInputSensor(GF_InlineScene *is, GF_Node *node){ ISStack *stack; GF_SAFEALLOC(stack, ISStack); stack->is = (M_InputSensor *) node; gf_node_set_private(node, stack); gf_node_set_callback_function(node, RenderInputSensor); gf_term_add_render_node(is->root_od->term, node);}/*check only URL changes*/void InputSensorModified(GF_Node *node){#if GPAC_HTK_DEMO GF_ObjectManager *odm; ISPriv *is_dec;#endif GF_MediaObject *mo; ISStack *st = (ISStack *)gf_node_get_private(node); mo = gf_mo_find(node, &st->is->url, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -