/ext/gpac/src/scene_manager/loader_bt.c
C | 3354 lines | 3266 code | 47 blank | 41 comment | 108 complexity | 28cd8dfc0a20318e11e15877ce58beaa MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception
Large files files are truncated, but you can click here to view the full file
- /*
- * GPAC - Multimedia Framework C SDK
- *
- * Copyright (c) Jean Le Feuvre 2000-2005
- * All rights reserved
- *
- * This file is part of GPAC / Scene Management 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/scene_manager.h>
- #include <gpac/utf.h>
- #include <gpac/constants.h>
- #include <gpac/internal/bifs_dev.h>
- #include <gpac/internal/scenegraph_dev.h>
- #include <gpac/nodes_x3d.h>
- /*for key codes...*/
- #include <gpac/user.h>
- /*since 0.2.2, we use zlib for bt reading to handle wrl.gz files*/
- #include <zlib.h>
- void gf_sm_load_done_BT(GF_SceneLoader *load);
- #define BT_LINE_SIZE 4000
- typedef struct
- {
- char *name;
- char *value;
- } BTDefSymbol;
- typedef struct
- {
- GF_SceneLoader *load;
- gzFile gz_in;
- u32 file_size, file_pos;
- /*create from string only*/
- GF_List *top_nodes;
- GF_Err last_error;
- u32 line;
- Bool done;
- u32 is_wrl;
- /*0: no unicode, 1: UTF-16BE, 2: UTF-16LE*/
- u32 unicode_type;
- GF_List *def_symbols;
- /*routes are not created in the graph when parsing, so we need to track insert and delete/replace*/
- GF_List *unresolved_routes, *inserted_routes, *peeked_nodes;
- GF_List *undef_nodes, *def_nodes;
- char *line_buffer;
- char cur_buffer[500];
- s32 line_size, line_pos, line_start_pos;
- /*set when parsing proto*/
- GF_Proto *parsing_proto;
- Bool is_extern_proto_field;
- /*current stream ID, AU time and RAP flag*/
- u32 stream_id;
- u32 au_time;
- Bool au_is_rap;
- /*current BIFS stream & AU*/
- GF_StreamContext *bifs_es;
- GF_AUContext *bifs_au;
- u32 base_bifs_id;
- GF_Command *cur_com;
- /*current OD stream & AU*/
- GF_StreamContext *od_es;
- GF_AUContext *od_au;
- u32 base_od_id;
- GF_List *scripts;
- } GF_BTParser;
- GF_Err gf_bt_parse_bifs_command(GF_BTParser *parser, char *name, GF_List *cmdList);
- GF_Route *gf_bt_parse_route(GF_BTParser *parser, Bool skip_def, Bool is_insert, GF_Command *com);
- void gf_bt_resolve_routes(GF_BTParser *parser, Bool clean);
- static GF_Err gf_bt_report(GF_BTParser *parser, GF_Err e, char *format, ...)
- {
- #ifndef GPAC_DISABLE_LOG
- if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
- char szMsg[2048];
- va_list args;
- va_start(args, format);
- vsprintf(szMsg, format, args);
- va_end(args);
- GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[BT/WRL Parsing] %s (line %d)\n", szMsg, parser->line));
- }
- #endif
- if (e) parser->last_error = e;
- return e;
- }
- GF_Node *gf_bt_new_node(GF_BTParser *parser, u32 tag)
- {
- GF_Node *n = gf_node_new(parser->load->scene_graph, tag);
- return n;
- }
- void gf_bt_check_line(GF_BTParser *parser)
- {
- while (1) {
- switch (parser->line_buffer[parser->line_pos]) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- parser->line_pos++;
- continue;
- default:
- break;
- }
- break;
- }
- if (parser->line_buffer[parser->line_pos]=='#') {
- parser->line_size = parser->line_pos;
- }
- else if ((parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/') ) parser->line_size = parser->line_pos;
- if (parser->line_size == parser->line_pos) {
- /*string based input - done*/
- if (!parser->gz_in) {
- parser->done = 1;
- return;
- }
- next_line:
- parser->line_start_pos = gztell(parser->gz_in);
- parser->line_buffer[0] = 0;
- if (parser->unicode_type) {
- u8 c1, c2;
- unsigned short wchar;
- unsigned short l[BT_LINE_SIZE];
- unsigned short *dst = l;
- Bool is_ret = 0;
- u32 last_space_pos, last_space_pos_stream;
- u32 go = BT_LINE_SIZE - 1;
- last_space_pos = last_space_pos_stream = 0;
- while (go && !gzeof(parser->gz_in) ) {
- c1 = gzgetc(parser->gz_in);
- c2 = gzgetc(parser->gz_in);
- /*Little-endian order*/
- if (parser->unicode_type==2) {
- if (c2) { wchar = c2; wchar <<=8; wchar |= c1; }
- else wchar = c1;
- } else {
- wchar = c1;
- if (c2) { wchar <<= 8; wchar |= c2;}
- }
- *dst = wchar;
- if (wchar=='\r') is_ret = 1;
- else if (wchar=='\n') {
- dst++;
- break;
- }
- else if (is_ret && wchar!='\n') {
- u32 fpos = gztell(parser->gz_in);
- gzseek(parser->gz_in, fpos-2, SEEK_SET);
- is_ret = 1;
- break;
- }
- if (wchar==' ') {
- last_space_pos_stream = gztell(parser->gz_in);
- last_space_pos = dst - l;
- }
- dst++;
- go--;
- }
- *dst = 0;
- /*long line, rewind stream to last space*/
- if (!go) {
- u32 rew_pos = gztell(parser->gz_in) - 2*(dst - &l[last_space_pos]);
- gzseek(parser->gz_in, rew_pos, SEEK_SET);
- l[last_space_pos+1] = 0;
- }
- /*check eof*/
- if (l[0]==0xFFFF) {
- parser->done = 1;
- return;
- }
- /*convert to mbc string*/
- dst = l;
- gf_utf8_wcstombs(parser->line_buffer, BT_LINE_SIZE, (const unsigned short **) &dst);
- if (!strlen(parser->line_buffer) && gzeof(parser->gz_in)) {
- parser->done = 1;
- return;
- }
- } else {
- if ((gzgets(parser->gz_in, parser->line_buffer, BT_LINE_SIZE) == NULL)
- || (!strlen(parser->line_buffer) && gzeof(parser->gz_in))) {
- parser->done = 1;
- return;
- }
- /*watchout for long lines*/
- if (1 + strlen(parser->line_buffer) == BT_LINE_SIZE) {
- u32 rew, pos, go;
- rew = 0;
- go = 1;
- while (go) {
- switch (parser->line_buffer[strlen(parser->line_buffer)-1]) {
- case ' ':
- case ',':
- case '[':
- case ']':
- go = 0;
- break;
- default:
- parser->line_buffer[strlen(parser->line_buffer)-1] = 0;
- rew++;
- break;
- }
- }
- pos = gztell(parser->gz_in);
- gzseek(parser->gz_in, pos-rew, SEEK_SET);
- }
- }
- while (1) {
- char c;
- u32 len = strlen(parser->line_buffer);
- if (!len) break;
- c = parser->line_buffer[len-1];
- if (!strchr("\n\r\t", c)) break;
- parser->line_buffer[len-1] = 0;
- }
-
- parser->line_size = strlen(parser->line_buffer);
- parser->line_pos = 0;
- parser->line++;
- {
- u32 pos = gztell(parser->gz_in);
- if (pos>=parser->file_pos) {
- parser->file_pos = pos;
- if (parser->line>1) gf_set_progress("BT Parsing", pos, parser->file_size);
- }
- }
- while ((parser->line_buffer[parser->line_pos]==' ') || (parser->line_buffer[parser->line_pos]=='\t'))
- parser->line_pos++;
- if ( (parser->line_buffer[parser->line_pos]=='#')
- || ( (parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/')) ) {
- if (parser->line==1) {
- if (strstr(parser->line_buffer, "VRML")) {
- if (strstr(parser->line_buffer, "VRML V2.0")) parser->is_wrl = 1;
- /*although not std, many files use this*/
- else if (strstr(parser->line_buffer, "VRML2.0")) parser->is_wrl = 1;
- else {
- gf_bt_report(parser, GF_NOT_SUPPORTED, "%s: VRML Version Not Supported", parser->line_buffer);
- return;
- }
- }
- else if (strstr(parser->line_buffer, "X3D")) {
- if (strstr(parser->line_buffer, "X3D V3.0")) parser->is_wrl = 2;
- else {
- gf_bt_report(parser, GF_NOT_SUPPORTED, "%s: X3D Version Not Supported", parser->line_buffer);
- return;
- }
- }
- }
- if (!strnicmp(parser->line_buffer+parser->line_pos, "#define ", 8)) {
- char *buf, *sep;
- parser->line_pos+=8;
- buf = parser->line_buffer+parser->line_pos;
- sep = strchr(buf, ' ');
- if (sep && (sep[1]!='\n') ) {
- BTDefSymbol *def;
- GF_SAFEALLOC(def, BTDefSymbol);
- sep[0] = 0;
- def->name = strdup(buf);
- sep[0] = ' ';
- buf = sep+1;
- while (strchr(" \t", buf[0])) buf++;
- def->value = strdup(buf);
- gf_list_add(parser->def_symbols, def);
- }
- }
- goto next_line;
- }
- /*brute-force replacement of defined symbols (!!FIXME - no mem checking done !!)*/
- if (parser->line_pos < parser->line_size) {
- u32 i, count;
- count = gf_list_count(parser->def_symbols);
- while (1) {
- Bool found = 0;
- for (i=0; i<count; i++) {
- u32 symb_len, val_len, copy_len;
- BTDefSymbol *def = (BTDefSymbol *)gf_list_get(parser->def_symbols, i);
- char *start = strstr(parser->line_buffer, def->name);
- if (!start) continue;
- symb_len = strlen(def->name);
- if (!strchr(" \n\r\t,[]{}\'\"", start[symb_len])) continue;
- val_len = strlen(def->value);
- copy_len = strlen(start + symb_len) + 1;
- memmove(start + val_len, start + symb_len, sizeof(char)*copy_len);
- memcpy(start, def->value, sizeof(char)*val_len);
- parser->line_size = strlen(parser->line_buffer);
- found = 1;
- }
- if (!found) break;
- }
- }
- }
- if (!parser->line_size) {
- if (!gzeof(parser->gz_in)) gf_bt_check_line(parser);
- else parser->done = 1;
- }
- else if (!parser->done && (parser->line_size == parser->line_pos)) gf_bt_check_line(parser);
- }
- void gf_bt_force_line(GF_BTParser *parser)
- {
- parser->line_pos = parser->line_size;
- }
- Bool gf_bt_check_code(GF_BTParser *parser, char code)
- {
- gf_bt_check_line(parser);
- if (parser->line_buffer[parser->line_pos]==code) {
- parser->line_pos++;
- return 1;
- }
- return 0;
- }
- char *gf_bt_get_next(GF_BTParser *parser, Bool point_break)
- {
- u32 has_quote;
- Bool go = 1;
- s32 i;
- gf_bt_check_line(parser);
- i=0;
- has_quote = 0;
- while (go) {
- if (parser->line_buffer[parser->line_pos + i] == '\"') {
- if (!has_quote) has_quote = 1;
- else has_quote = 0;
- parser->line_pos += 1;
- if (parser->line_pos+i==parser->line_size) break;
- continue;
- }
- if (!has_quote) {
- switch (parser->line_buffer[parser->line_pos + i]) {
- case 0:
- case ' ':
- case '\t':
- case '{':
- case '}':
- case ']':
- case '[':
- case ',':
- go = 0;
- break;
- case '.':
- if (point_break) go = 0;
- break;
- }
- if (!go) break;
- }
- parser->cur_buffer[i] = parser->line_buffer[parser->line_pos + i];
- i++;
- if (parser->line_pos+i==parser->line_size) break;
- }
- parser->cur_buffer[i] = 0;
- parser->line_pos += i;
- return parser->cur_buffer;
- }
- char *gf_bt_get_string(GF_BTParser *parser)
- {
- char *res;
- s32 i, size;
- #define BT_STR_CHECK_ALLOC \
- if (i==size) { \
- res = (char*)realloc(res, sizeof(char) * (size+500)); \
- size += 500; \
- } \
- res = (char*)malloc(sizeof(char) * 500);
- size = 500;
- while (parser->line_buffer[parser->line_pos]==' ') parser->line_pos++;
-
- if (parser->line_pos==parser->line_size) {
- if (gzeof(parser->gz_in)) return NULL;
- gf_bt_check_line(parser);
- }
- i=0;
- while (1) {
- if (parser->line_buffer[parser->line_pos] == '\"')
- if (parser->line_buffer[parser->line_pos-1] != '\\') break;
- BT_STR_CHECK_ALLOC
- if ((parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/') && (parser->line_buffer[parser->line_pos-1]!=':') ) {
- /*this looks like a comment*/
- if (!strstr(&parser->line_buffer[parser->line_pos], "\"")) {
- gf_bt_check_line(parser);
- continue;
- }
- }
- if ((parser->line_buffer[parser->line_pos] != '\\') || (parser->line_buffer[parser->line_pos+1] != '"')) {
- /*handle UTF-8 - WARNING: if parser is in unicode string is already utf8 multibyte chars*/
- if (!parser->unicode_type && parser->line_buffer[parser->line_pos] & 0x80) {
- char c = parser->line_buffer[parser->line_pos];
- /*non UTF8 (likely some win-CP)*/
- if ( (parser->line_buffer[parser->line_pos+1] & 0xc0) != 0x80) {
- res[i] = 0xc0 | ( (parser->line_buffer[parser->line_pos] >> 6) & 0x3 );
- i++;
- BT_STR_CHECK_ALLOC
- parser->line_buffer[parser->line_pos] &= 0xbf;
- }
- /*UTF8 2 bytes char*/
- else if ( (c & 0xe0) == 0xc0) {
- res[i] = parser->line_buffer[parser->line_pos]; parser->line_pos++; i++;
- BT_STR_CHECK_ALLOC
- }
- /*UTF8 3 bytes char*/
- else if ( (c & 0xf0) == 0xe0) {
- res[i] = parser->line_buffer[parser->line_pos]; parser->line_pos++; i++;
- BT_STR_CHECK_ALLOC
- res[i] = parser->line_buffer[parser->line_pos]; parser->line_pos++; i++;
- BT_STR_CHECK_ALLOC
- }
- /*UTF8 4 bytes char*/
- else if ( (c & 0xf8) == 0xf0) {
- res[i] = parser->line_buffer[parser->line_pos]; parser->line_pos++; i++;
- BT_STR_CHECK_ALLOC
- res[i] = parser->line_buffer[parser->line_pos]; parser->line_pos++; i++;
- BT_STR_CHECK_ALLOC
- res[i] = parser->line_buffer[parser->line_pos]; parser->line_pos++; i++;
- BT_STR_CHECK_ALLOC
- }
- }
- res[i] = parser->line_buffer[parser->line_pos];
- i++;
- }
- parser->line_pos++;
- if (parser->line_pos==parser->line_size) {
- gf_bt_check_line(parser);
- }
- }
- #undef BT_STR_CHECK_ALLOC
- res[i] = 0;
- parser->line_pos += 1;
- return res;
- }
- Bool gf_bt_check_externproto_field(GF_BTParser *parser, char *str)
- {
- if (!parser->is_extern_proto_field) return 0;
- if (!strcmp(str, "") || !strcmp(str, "field") || !strcmp(str, "eventIn") || !strcmp(str, "eventOut") || !strcmp(str, "exposedField")) {
- parser->last_error = GF_EOS;
- return 1;
- }
- return 0;
- }
- static Bool check_keyword(GF_BTParser *parser, char *str, s32 *val)
- {
- s32 res;
- char *sep;
- sep = strchr(str, '$');
- if (!sep) return 0;
- sep++;
- if (!strcmp(sep, "F1")) res = GF_KEY_F1;
- else if (!strcmp(sep, "F2")) res = GF_KEY_F2;
- else if (!strcmp(sep, "F3")) res = GF_KEY_F3;
- else if (!strcmp(sep, "F4")) res = GF_KEY_F4;
- else if (!strcmp(sep, "F5")) res = GF_KEY_F5;
- else if (!strcmp(sep, "F6")) res = GF_KEY_F6;
- else if (!strcmp(sep, "F7")) res = GF_KEY_F7;
- else if (!strcmp(sep, "F8")) res = GF_KEY_F8;
- else if (!strcmp(sep, "F9")) res = GF_KEY_F9;
- else if (!strcmp(sep, "F10")) res = GF_KEY_F10;
- else if (!strcmp(sep, "F11")) res = GF_KEY_F11;
- else if (!strcmp(sep, "F12")) res = GF_KEY_F12;
- else if (!strcmp(sep, "HOME")) res = GF_KEY_HOME;
- else if (!strcmp(sep, "END")) res = GF_KEY_END;
- else if (!strcmp(sep, "PREV")) res = GF_KEY_PAGEUP;
- else if (!strcmp(sep, "NEXT")) res = GF_KEY_PAGEDOWN;
- else if (!strcmp(sep, "UP")) res = GF_KEY_UP;
- else if (!strcmp(sep, "DOWN")) res = GF_KEY_DOWN;
- else if (!strcmp(sep, "LEFT")) res = GF_KEY_LEFT;
- else if (!strcmp(sep, "RIGHT")) res = GF_KEY_RIGHT;
- else if (!strcmp(sep, "RETURN")) res = GF_KEY_ENTER;
- else if (!strcmp(sep, "BACK")) res = GF_KEY_BACKSPACE;
- else if (!strcmp(sep, "TAB")) res = GF_KEY_TAB;
- else if (strlen(sep)==1) {
- char c;
- sscanf(sep, "%c", &c);
- res = c;
- } else {
- gf_bt_report(parser, GF_OK, "unrecognized keyword %s - skipping", str);
- res = 0;
- }
- if (strchr(str, '-')) *val = -res;
- else *val = res;
- return 1;
- }
- GF_Err gf_bt_parse_float(GF_BTParser *parser, const char *name, Fixed *val)
- {
- s32 var;
- Float f;
- char *str = gf_bt_get_next(parser, 0);
- if (!str) return parser->last_error = GF_IO_ERR;
- if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
-
- if (check_keyword(parser, str, &var)) {
- *val = INT2FIX(var);
- return GF_OK;
- }
- if (sscanf(str, "%g", &f) != 1) {
- return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
- }
- *val = FLT2FIX(f);
- return GF_OK;
- }
- GF_Err gf_bt_parse_double(GF_BTParser *parser, const char *name, SFDouble *val)
- {
- char *str = gf_bt_get_next(parser, 0);
- if (!str) return parser->last_error = GF_IO_ERR;
- if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
- if (sscanf(str, "%lf", val) != 1) {
- return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
- }
- return GF_OK;
- }
- GF_Err gf_bt_parse_int(GF_BTParser *parser, const char *name, SFInt32 *val)
- {
- char *str = gf_bt_get_next(parser, 0);
- if (!str) return parser->last_error = GF_IO_ERR;
- if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
- if (check_keyword(parser, str, val)) return GF_OK;
- /*URL ODID*/
- if (!strnicmp(str, "od:", 3)) str += 3;
- if (sscanf(str, "%d", val) != 1) {
- return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
- }
- return GF_OK;
- }
- GF_Err gf_bt_parse_bool(GF_BTParser *parser, const char *name, SFBool *val)
- {
- char *str = gf_bt_get_next(parser, 0);
- if (!str) return parser->last_error = GF_IO_ERR;
- if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
- if (!stricmp(str, "true") || !strcmp(str, "1") ) {
- *val = 1;
- }
- else if (!stricmp(str, "false") || !strcmp(str, "0") ) {
- *val = 0;
- } else {
- return gf_bt_report(parser, GF_BAD_PARAM, "%s: Boolean expected", name);
- }
- return GF_OK;
- }
- GF_Err gf_bt_parse_color(GF_BTParser *parser, const char *name, SFColor *col)
- {
- Float f;
- char *str = gf_bt_get_next(parser, 0);
- if (!str) return parser->last_error = GF_IO_ERR;
- if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
- /*HTML code*/
- if (str[0]=='$') {
- u32 val;
- sscanf(str+1, "%x", &val);
- col->red = INT2FIX((val>>16) & 0xFF) / 255;
- col->green = INT2FIX((val>>8) & 0xFF) / 255;
- col->blue = INT2FIX(val & 0xFF) / 255;
- return parser->last_error;
- }
- if (sscanf(str, "%f", &f) != 1) {
- return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
- }
- col->red = FLT2FIX(f);
- /*many VRML files use ',' separator*/
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, name, & col->green);
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, name, & col->blue);
- return parser->last_error;
- }
- GF_Err gf_bt_parse_colorRGBA(GF_BTParser *parser, const char *name, SFColorRGBA *col)
- {
- Float f;
- char *str = gf_bt_get_next(parser, 0);
- if (!str) return parser->last_error = GF_IO_ERR;
- if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
- /*HTML code*/
- if (str[0]=='$') {
- u32 val;
- sscanf(str, "%x", &val);
- col->red = INT2FIX((val>>24) & 0xFF) / 255;
- col->green = INT2FIX((val>>16) & 0xFF) / 255;
- col->blue = INT2FIX((val>>8) & 0xFF) / 255;
- col->alpha = INT2FIX(val & 0xFF) / 255;
- return parser->last_error;
- }
- if (sscanf(str, "%f", &f) != 1) {
- return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
- }
- col->red = FLT2FIX(f);
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, name, & col->green);
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, name, & col->blue);
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, name, & col->alpha);
- return parser->last_error;
- }
- static void gf_bt_offset_time(GF_BTParser *parser, Double *time)
- {
- if (!parser->is_wrl) {
- Double res;
- res = parser->au_time;
- res /= parser->bifs_es->timeScale;
- *time += res;
- }
- }
- static void gf_bt_check_time_offset(GF_BTParser *parser, GF_Node *n, GF_FieldInfo *info)
- {
- if (!n || !(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
- if (gf_node_get_tag(n) != TAG_ProtoNode) {
- if (!stricmp(info->name, "startTime") || !stricmp(info->name, "stopTime"))
- gf_bt_offset_time(parser, (Double *)info->far_ptr);
- } else if (gf_sg_proto_field_is_sftime_offset(n, info)) {
- gf_bt_offset_time(parser, (Double *)info->far_ptr);
- }
- }
- static void gf_bt_update_timenode(GF_BTParser *parser, GF_Node *node)
- {
- if (!node || !(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
- switch (gf_node_get_tag(node)) {
- case TAG_MPEG4_AnimationStream:
- gf_bt_offset_time(parser, & ((M_AnimationStream*)node)->startTime);
- gf_bt_offset_time(parser, & ((M_AnimationStream*)node)->stopTime);
- break;
- case TAG_MPEG4_AudioBuffer:
- gf_bt_offset_time(parser, & ((M_AudioBuffer*)node)->startTime);
- gf_bt_offset_time(parser, & ((M_AudioBuffer*)node)->stopTime);
- break;
- case TAG_MPEG4_AudioClip:
- gf_bt_offset_time(parser, & ((M_AudioClip*)node)->startTime);
- gf_bt_offset_time(parser, & ((M_AudioClip*)node)->stopTime);
- break;
- case TAG_MPEG4_AudioSource:
- gf_bt_offset_time(parser, & ((M_AudioSource*)node)->startTime);
- gf_bt_offset_time(parser, & ((M_AudioSource*)node)->stopTime);
- break;
- case TAG_MPEG4_MovieTexture:
- gf_bt_offset_time(parser, & ((M_MovieTexture*)node)->startTime);
- gf_bt_offset_time(parser, & ((M_MovieTexture*)node)->stopTime);
- break;
- case TAG_MPEG4_TimeSensor:
- gf_bt_offset_time(parser, & ((M_TimeSensor*)node)->startTime);
- gf_bt_offset_time(parser, & ((M_TimeSensor*)node)->stopTime);
- break;
- case TAG_ProtoNode:
- {
- u32 i, nbFields;
- GF_FieldInfo inf;
- nbFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL);
- for (i=0; i<nbFields; i++) {
- gf_node_get_field(node, i, &inf);
- if (inf.fieldType != GF_SG_VRML_SFTIME) continue;
- gf_bt_check_time_offset(parser, node, &inf);
- }
- }
- break;
- }
- }
- void gf_bt_sffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
- {
- switch (info->fieldType) {
- case GF_SG_VRML_SFINT32:
- gf_bt_parse_int(parser, info->name, (SFInt32 *)info->far_ptr);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFBOOL:
- gf_bt_parse_bool(parser, info->name, (SFBool *)info->far_ptr);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFFLOAT:
- gf_bt_parse_float(parser, info->name, (SFFloat *)info->far_ptr);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFDOUBLE:
- gf_bt_parse_double(parser, info->name, (SFDouble *)info->far_ptr);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFTIME:
- gf_bt_parse_double(parser, info->name, (SFDouble *)info->far_ptr);
- if (parser->last_error) return;
- gf_bt_check_time_offset(parser, n, info);
- break;
- case GF_SG_VRML_SFCOLOR:
- gf_bt_parse_color(parser, info->name, (SFColor *)info->far_ptr);
- break;
- case GF_SG_VRML_SFCOLORRGBA:
- gf_bt_parse_colorRGBA(parser, info->name, (SFColorRGBA *)info->far_ptr);
- break;
- case GF_SG_VRML_SFVEC2F:
- gf_bt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->x);
- if (parser->last_error) return;
- /*many VRML files use ',' separator*/
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->y);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFVEC2D:
- gf_bt_parse_double(parser, info->name, & ((SFVec2d *)info->far_ptr)->x);
- if (parser->last_error) return;
- /*many VRML files use ',' separator*/
- gf_bt_check_code(parser, ',');
- gf_bt_parse_double(parser, info->name, & ((SFVec2d *)info->far_ptr)->y);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFVEC3F:
- gf_bt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->x);
- if (parser->last_error) return;
- /*many VRML files use ',' separator*/
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->y);
- if (parser->last_error) return;
- /*many VRML files use ',' separator*/
- gf_bt_check_code(parser, ',');
- gf_bt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->z);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFVEC3D:
- gf_bt_parse_double(parser, info->name, & ((SFVec3d *)info->far_ptr)->x);
- if (parser->last_error) return;
- /*many VRML files use ',' separator*/
- gf_bt_check_code(parser, ',');
- gf_bt_parse_double(parser, info->name, & ((SFVec3d *)info->far_ptr)->y);
- if (parser->last_error) return;
- /*many VRML files use ',' separator*/
- gf_bt_check_code(parser, ',');
- gf_bt_parse_double(parser, info->name, & ((SFVec3d *)info->far_ptr)->z);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFROTATION:
- gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->x);
- if (parser->last_error) return;
- gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->y);
- if (parser->last_error) return;
- gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->z);
- if (parser->last_error) return;
- gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->q);
- if (parser->last_error) return;
- break;
- case GF_SG_VRML_SFSTRING:
- if (gf_bt_check_code(parser, '\"') || gf_bt_check_code(parser, '\'')) {
- char *str = gf_bt_get_string(parser);
- if (!str)
- goto err;
- if (((SFString *)info->far_ptr)->buffer) free(((SFString *)info->far_ptr)->buffer);
- ((SFString *)info->far_ptr)->buffer = NULL;
- if (strlen(str))
- ((SFString *)info->far_ptr)->buffer = str;
- else
- free(str);
- } else {
- goto err;
- }
- break;
- case GF_SG_VRML_SFURL:
- if (gf_bt_check_code(parser, '\"') || gf_bt_check_code(parser, '\'')) {
- SFURL *url = (SFURL *)info->far_ptr;
- char *str = gf_bt_get_string(parser);
- if (!str) goto err;
- if (url->url) free(url->url);
- url->url = NULL;
- url->OD_ID = 0;
- if (strchr(str, '#')) {
- url->url = str;
- } else {
- u32 id = 0;
- char *odstr = str;
- if (!strnicmp(str, "od:", 3)) odstr += 3;
- /*be carefull, an url like "11-regression-test.mp4" will return 1 on sscanf :)*/
- if (sscanf(odstr, "%d", &id) == 1) {
- char szURL[20];
- sprintf(szURL, "%d", id);
- if (strcmp(szURL, odstr)) id=0;
- }
- if (id) {
- url->OD_ID = id;
- free(str);
- } else {
- url->url = str;
- }
- }
- } else {
- s32 val;
- gf_bt_parse_int(parser, info->name, & val );
- if (parser->last_error) return;
- ((SFURL *)info->far_ptr)->OD_ID = val;
- }
- break;
- case GF_SG_VRML_SFCOMMANDBUFFER:
- {
- SFCommandBuffer *cb = (SFCommandBuffer *)info->far_ptr;
- if (gf_bt_check_code(parser, '{')) {
- GF_Command *prev_com = parser->cur_com;
- while (!parser->last_error) {
- if (gf_bt_check_code(parser, '}')) break;
- parser->last_error = gf_bt_parse_bifs_command(parser, NULL, cb->commandList);
- }
- parser->cur_com = prev_com;
- }
- }
- break;
- case GF_SG_VRML_SFIMAGE:
- {
- u32 i, size, v;
- char *str;
- SFImage *img = (SFImage *)info->far_ptr;
- gf_bt_parse_int(parser, "width", (SFInt32 *)&img->width);
- if (parser->last_error) return;
- gf_bt_parse_int(parser, "height", (SFInt32 *)&img->height);
- if (parser->last_error) return;
- gf_bt_parse_int(parser, "nbComp", (SFInt32 *)&v);
- if (parser->last_error) return;
- img->numComponents = v;
- size = img->width * img->height * img->numComponents;
- if (img->pixels) free(img->pixels);
- img->pixels = (unsigned char*)malloc(sizeof(char) * size);
- for (i=0; i<size; i++) {
- str = gf_bt_get_next(parser, 0);
- if (strstr(str, "0x")) sscanf(str, "%x", &v);
- else sscanf(str, "%d", &v);
- switch (img->numComponents) {
- case 1:
- img->pixels[i] = (char) v;
- break;
- case 2:
- img->pixels[i] = (char) (v>>8)&0xFF;
- img->pixels[i+1] = (char) (v)&0xFF;
- i++;
- break;
- case 3:
- img->pixels[i] = (char) (v>>16)&0xFF;
- img->pixels[i+1] = (char) (v>>8)&0xFF;
- img->pixels[i+2] = (char) (v)&0xFF;
- i+=2;
- break;
- case 4:
- img->pixels[i] = (char) (v>>24)&0xFF;
- img->pixels[i+1] = (char) (v>>16)&0xFF;
- img->pixels[i+2] = (char) (v>>8)&0xFF;
- img->pixels[i+3] = (char) (v)&0xFF;
- i+=3;
- break;
- }
- }
- }
- break;
- case GF_SG_VRML_SFSCRIPT:
- {
- SFScript *sc = (SFScript *) info->far_ptr;
- if (!gf_bt_check_code(parser, '\"')) {
- gf_bt_report(parser, GF_BAD_PARAM, "\" expected in Script");
- }
- sc->script_text = (unsigned char*)gf_bt_get_string(parser);
- }
- break;
- default:
- parser->last_error = GF_NOT_SUPPORTED;
- break;
- }
- gf_bt_check_code(parser, ',');
- return;
- err:
- gf_bt_report(parser, GF_BAD_PARAM, "%s: Invalid field syntax", info->name);
- }
- void gf_bt_mffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
- {
- GF_FieldInfo sfInfo;
- Bool force_single = 0;
- if (!gf_bt_check_code(parser, '[')) {
- if (parser->is_extern_proto_field) return;
- force_single = 1;
- }
- sfInfo.fieldType = gf_sg_vrml_get_sf_type(info->fieldType);
- sfInfo.name = info->name;
- gf_sg_vrml_mf_reset(info->far_ptr, info->fieldType);
- while (!gf_bt_check_code(parser, ']')) {
- gf_sg_vrml_mf_append(info->far_ptr, info->fieldType, &sfInfo.far_ptr);
- gf_bt_sffield(parser, &sfInfo, n);
- if (parser->last_error) return;
- gf_bt_check_code(parser, ',');
- if (force_single) break;
- }
- }
- Bool gf_bt_check_ndt(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *node, GF_Node *parent)
- {
- if (!node) return 1;
- if (parent->sgprivate->tag == TAG_MPEG4_Script) return 1;
- if (parent->sgprivate->tag == TAG_X3D_Script) return 1;
- if (node->sgprivate->tag == TAG_UndefinedNode) return 1;
- /*this handles undefined nodes*/
- if (gf_node_in_table(node, info->NDTtype)) return 1;
- /*not found*/
- gf_bt_report(parser, GF_BAD_PARAM, "node %s not valid in field %s\n", gf_node_get_class_name(node), info->name);
- gf_node_unregister(node, parent);
- return 0;
- }
- u32 gf_bt_get_next_node_id(GF_BTParser *parser)
- {
- u32 ID;
- GF_SceneGraph *sc = parser->load->scene_graph;
- if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
- ID = gf_sg_get_next_available_node_id(sc);
- if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
- parser->load->ctx->max_node_id = ID;
- return ID;
- }
- u32 gf_bt_get_next_route_id(GF_BTParser *parser)
- {
- u32 ID;
- GF_SceneGraph *sg = parser->load->scene_graph;
- if (parser->parsing_proto) sg = gf_sg_proto_get_graph(parser->parsing_proto);
- ID = gf_sg_get_next_available_route_id(sg);
- if (parser->load->ctx && (ID>parser->load->ctx->max_route_id))
- parser->load->ctx->max_route_id = ID;
- return ID;
- }
- u32 gf_bt_get_next_proto_id(GF_BTParser *parser)
- {
- u32 ID;
- GF_SceneGraph *sc = parser->load->scene_graph;
- if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
- ID = gf_sg_get_next_available_proto_id(sc);
- if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
- parser->load->ctx->max_proto_id = ID;
- return ID;
- }
- u32 gf_bt_get_def_id(GF_BTParser *parser, char *defName)
- {
- GF_Node *n;
- u32 ID;
- if (sscanf(defName, "N%d", &ID) == 1) {
- ID ++;
- n = gf_sg_find_node(parser->load->scene_graph, ID);
- /*if an existing node use*/
- if (n) {
- u32 id;
- u32 nID = gf_bt_get_next_node_id(parser);
- const char *name = gf_node_get_name_and_id(n, &id);
- gf_bt_report(parser, GF_OK, "changing node \"%s\" ID from %d to %d", name, id -1, nID-1);
- gf_node_set_id(n, nID, name);
- }
- if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
- } else {
- ID = gf_bt_get_next_node_id(parser);
- }
- return ID;
- }
- Bool gf_bt_set_field_is(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
- {
- GF_Err e;
- u32 i;
- GF_ProtoFieldInterface *pfield;
- GF_FieldInfo pinfo;
- char *str;
- gf_bt_check_line(parser);
- i=0;
- while ((parser->line_buffer[parser->line_pos + i] == ' ') || (parser->line_buffer[parser->line_pos + i] == '\t')) i++;
- if (strnicmp(&parser->line_buffer[parser->line_pos + i] , "IS", 2)) return 0;
- str = gf_bt_get_next(parser, 0);
- str = gf_bt_get_next(parser, 0);
- /*that's an ISed field*/
- pfield = gf_sg_proto_field_find_by_name(parser->parsing_proto, str);
- if (!pfield) {
- gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown proto field", str);
- return 1;
- }
- gf_sg_proto_field_get_field(pfield, &pinfo);
- e = gf_sg_proto_field_set_ised(parser->parsing_proto, pinfo.fieldIndex, n, info->fieldIndex);
- if (e) gf_bt_report(parser, GF_BAD_PARAM, "IS: Invalid field type for field %s", info->name);
- return 1;
- }
- void gf_bt_check_unresolved_nodes(GF_BTParser *parser)
- {
- u32 i, count;
- count = gf_list_count(parser->undef_nodes);
- if (!count) return;
- for (i=0; i<count; i++) {
- GF_Node *n = (GF_Node *)gf_list_get(parser->undef_nodes, i);
- gf_bt_report(parser, GF_BAD_PARAM, "Cannot find node %s\n", gf_node_get_name(n) );
- }
- parser->last_error = GF_BAD_PARAM;
- }
- Bool gf_bt_has_been_def(GF_BTParser *parser, char *node_name)
- {
- u32 i, count;
- count = gf_list_count(parser->def_nodes);
- for (i=0; i<count; i++) {
- GF_Node *n = (GF_Node *) gf_list_get(parser->def_nodes, i);
- if (!strcmp(gf_node_get_name(n), node_name)) return 1;
- }
- return 0;
- }
- u32 gf_bt_get_node_tag(GF_BTParser *parser, char *node_name)
- {
- u32 tag;
- /*if VRML and allowing non MPEG4 nodes, use X3D*/
- if (parser->is_wrl && !(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) {
- tag = gf_node_x3d_type_by_class_name(node_name);
- if (!tag) tag = gf_node_mpeg4_type_by_class_name(node_name);
- if (tag) return tag;
- if (!strcmp(node_name, "Rectangle")) return TAG_X3D_Rectangle2D;
- if (!strcmp(node_name, "Circle")) return TAG_X3D_Circle2D;
- } else {
- tag = gf_node_mpeg4_type_by_class_name(node_name);
- if (!tag) {
- if (!strcmp(node_name, "Rectangle2D")) return TAG_MPEG4_Rectangle;
- if (!strcmp(node_name, "Circle2D")) return TAG_MPEG4_Circle;
- if (!(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) return gf_node_x3d_type_by_class_name(node_name);
- }
- }
- return tag;
- }
- GF_Node *gf_bt_sf_node(GF_BTParser *parser, char *node_name, GF_Node *parent, char *szDEFName)
- {
- u32 tag, ID;
- Bool is_script, replace_prev, register_def;
- GF_Proto *proto;
- GF_Node *node, *newnode, *undef_node;
- GF_FieldInfo info;
- Bool init_node;
- char *name;
- char * str;
- init_node = 0;
- if (node_name) {
- str = node_name;
- } else {
- str = gf_bt_get_next(parser, 0);
- }
- name = NULL;
- if (!strcmp(str, "NULL")) return NULL;
- ID = 0;
- register_def = 0;
- replace_prev = 0;
- undef_node = NULL;
- if (!strcmp(str, "DEF")) {
- register_def = 1;
- str = gf_bt_get_next(parser, 0);
- name = strdup(str);
- str = gf_bt_get_next(parser, 0);
- } else if (szDEFName) {
- name = strdup(szDEFName);
- register_def = 1;
- }
- if (name) {
- undef_node = gf_sg_find_node_by_name(parser->load->scene_graph, name);
- if (undef_node) {
- gf_list_del_item(parser->peeked_nodes, undef_node);
- ID = gf_node_get_id(undef_node);
- /*if we see twice a DEF N1 then force creation of a new node*/
- if (gf_bt_has_been_def(parser, name)) {
- undef_node = NULL;
- ID = gf_bt_get_def_id(parser, name);
- gf_bt_report(parser, GF_OK, "Node %s has been DEFed several times, IDs may get corrupted", name);
- }
- } else {
- ID = gf_bt_get_def_id(parser, name);
- }
- }
- else if (!strcmp(str, "USE")) {
- str = gf_bt_get_next(parser, 0);
- node = gf_sg_find_node_by_name(parser->load->scene_graph, str);
- if (!node) {
- /*create a temp node (undefined)*/
- node = gf_bt_new_node(parser, TAG_UndefinedNode);
- ID = gf_bt_get_def_id(parser, str);
- gf_node_set_id(node, ID, str);
- gf_list_add(parser->undef_nodes, node);
- }
- gf_node_register(node, parent);
- return node;
- }
- proto = NULL;
- tag = gf_bt_get_node_tag(parser, str);
- if (!tag) {
- GF_SceneGraph *sg = parser->load->scene_graph;
- while (1) {
- proto = gf_sg_find_proto(sg, 0, str);
- if (proto) break;
- sg = sg->parent_scene;
- if (!sg) break;
- }
- if (!proto) {
- /*locate proto*/
- gf_bt_report(parser, GF_BAD_PARAM, "%s: not a valid/supported node", str);
- return NULL;
- }
- tag = TAG_ProtoNode;
- }
- if (undef_node && (undef_node->sgprivate->tag == tag)) {
- node = undef_node;
- } else {
- if (undef_node) replace_prev = 1;
- if (proto) {
- node = gf_sg_proto_create_instance(parser->load->scene_graph, proto);
- } else {
- node = gf_bt_new_node(parser, tag);
- }
- if (!parser->parsing_proto) init_node = 1;
- }
- is_script = 0;
- if ((tag==TAG_MPEG4_Script) || (tag==TAG_X3D_Script))
- is_script = 1;
- if (!node) {
- parser->last_error = GF_SG_UNKNOWN_NODE;
- return NULL;
- }
- if (register_def) gf_list_add(parser->def_nodes, node);
- gf_node_register(node, parent);
- /*VRML: "The transformation hierarchy shall be a directed acyclic graph; results are undefined if a node
- in the transformation hierarchy is its own ancestor"
- that's good, because the scene graph can't handle cyclic graphs (destroy will never be called).
- However we still have to register the node before parsing it, to update node registry and get correct IDs*/
- if (name) {
- if (!undef_node || replace_prev) {
- gf_node_set_id(node, ID, name);
- }
- free(name);
- name = NULL;
- }
- if (!parser->parsing_proto) gf_bt_update_timenode(parser, node);
- if (gf_bt_check_code(parser, '{')) {
- while (1) {
- if (gf_bt_check_code(parser, '}'))
- break;
- str = gf_bt_get_next(parser, 0);
- if (!str) {
- gf_bt_report(parser, GF_BAD_PARAM, "Invalid node syntax");
- goto err;
- }
- /*VRML/X3D specific */
- if (parser->is_wrl) {
- /*we ignore bboxCenter and bboxSize*/
- if (!strcmp(str, "bboxCenter") || !strcmp(str, "bboxSize")) {
- Fixed f;
- gf_bt_parse_float(parser, "x", &f);
- gf_bt_parse_float(parser, "y", &f);
- gf_bt_parse_float(parser, "z", &f);
- continue;
- }
- /*some VRML files declare routes almost anywhere*/
- if (!strcmp(str, "ROUTE")) {
- gf_bt_parse_route(parser, 1, 0, NULL);
- continue;
- }
- }
-
- parser->last_error = gf_node_get_field_by_name(node, str, &info);
- /*check common VRML fields removed in MPEG4*/
- if (parser->last_error) {
- if (!parser->is_wrl) {
- /*we ignore 'solid' for MPEG4 box/cone/etc*/
- if (!strcmp(str, "solid")) {
- Bool b;
- gf_bt_parse_bool(parser, "solid", &b);
- parser->last_error = GF_OK;
- continue;
- }
- /*we ignore 'description' for MPEG4 sensors*/
- else if (!strcmp(str, "description")) {
- char *str = gf_bt_get_string(parser);
- free(str);
- parser->last_error = GF_OK;
- continue;
- }
- /*remaps X3D to old VRML/MPEG4*/
- else if ((tag==TAG_MPEG4_LOD) && !strcmp(str, "children")) {
- str = "level";
- parser->last_error = gf_node_get_field_by_name(node, str, &info);
- }
- else if ((tag==TAG_MPEG4_Switch) && !strcmp(str, "children")) {
- str = "choice";
- parser->last_error = gf_node_get_field_by_name(node, str, &info);
- }
- else if (!strcmp(str, "enabled")) {
- Bool b;
- gf_bt_parse_bool(parser, "collide", &b);
- parser->last_error = GF_OK;
- continue;
- }
- } else {
- /*remaps old VRML/MPEG4 to X3D if possible*/
- if ((tag==TAG_X3D_LOD) && !strcmp(str, "level")) {
- str = "children";
- parser->last_error = gf_node_get_field_by_name(node, str, &info);
- }
- else if ((tag==TAG_X3D_Switch) && !strcmp(str, "choice")) {
- str = "children";
- parser->last_error = gf_node_get_field_by_name(node, str, &info);
- }
- else if (!strcmp(str, "collide")) {
- Bool b;
- gf_bt_parse_bool(parser, "enabled", &b);
- parser->last_error = GF_OK;
- continue;
- }
- }
- }
- if (is_script && parser->last_error) {
- u32 eType, fType;
- GF_ScriptField *sf;
- eType = 0;
- if (!strcmp(str, "eventIn") || !strcmp(str, "inputOnly")) eType = GF_SG_SCRIPT_TYPE_EVENT_IN;
- else if (!strcmp(str, "eventOut") || !strcmp(str, "outputOnly")) eType = GF_SG_SCRIPT_TYPE_EVENT_OUT;
- else if (!strcmp(str, "field") || !strcmp(str, "initializeOnly")) eType = GF_SG_SCRIPT_TYPE_FIELD;
- else {
- gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown script event type", str);
- goto err;
- }
- str = gf_bt_get_next(parser, 0);
- fType = gf_sg_field_type_by_name(str);
- if (fType==GF_SG_VRML_UNKNOWN) {
- gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown script field type", str);
- goto err;
- }
- parser->last_error = GF_OK;
- str = gf_bt_get_next(parser, 0);
- sf = gf_sg_script_field_new(node, eType, fType, str);
- parser->last_error = gf_node_get_field_by_name(node, str, &info);
- if (parser->parsing_proto && gf_bt_set_field_is(parser, &info, node)) continue;
- if ((eType == GF_SG_SCRIPT_TYPE_EVENT_IN) || (eType == GF_SG_SCRIPT_TYPE_EVENT_OUT)) continue;
- }
-
- if (parser->last_error) {
- gf_bt_report(parser, GF_OK, "%s: Unknown field", str);
- goto err;
- }
-
- if (parser->parsing_proto && gf_bt_set_field_is(parser, &info, node)) continue;
- switch (info.fieldType) {
- case GF_SG_VRML_SFNODE:
- /*if redefining node reset it - this happens with CreateVrmlFromString*/
- if (* ((GF_Node **)info.far_ptr) ) {
- gf_node_unregister(* ((GF_Node **)info.far_ptr), node);
- * ((GF_Node **)info.far_ptr) = NULL;
- }
- newnode = gf_bt_sf_node(parser, NULL, node, NULL);
- if (!newnode && parser->last_error) goto err;
- if (newnode) {
- if (!gf_bt_check_ndt(parser, &info, newnode, node)) goto err;
- * ((GF_Node **)info.far_ptr) = newnode;
- }
- break;
- case GF_SG_VRML_MFNODE:
- {
- GF_ChildNodeItem *last = NULL;
- Bool single_child = 0;
- if (!gf_bt_check_code(parser, '[')) {
- if (parser->is_wrl) single_child = 1;
- else break;
- }
- /*if redefining node reset it - this happens with CreateVrmlFromString*/
- if (undef_node==node) {
- gf_node_unregister_children(node, *(GF_ChildNodeItem **)info.far_ptr);
- *(GF_ChildNodeItem **)info.far_ptr = NULL;
- }
- while (single_child || !gf_bt_check_code(parser, ']')) {
- /*VRML seems to allow that*/
- gf_bt_check_code(parser, ',');
- newnode = gf_bt_sf_node(parser, NULL, node, NULL);
- if (!newnode && parser->last_error) goto err;
- if (newnode) {
- if (!gf_bt_check_ndt(parser, &info, newnode, node)) goto err;
- gf_node_list_add_child_last( (GF_ChildNodeItem **)info.far_ptr, newnode, &last);
- }
- if (single_child) break;
- }
- }
- break;
- default:
- if (gf_sg_vrml_is_sf_field(info.fieldType)) {
- gf_bt_sffield(parser, &info, node);
- } else {
- gf_bt_mffield(parser, &info, node);
- }
- if (parser->last_error) goto err;
- break;
- }
- /*VRML seems to allow that*/
- gf_bt_check_code(parser, ',');
- if (proto) gf_sg_proto_mark_field_loaded(node, &info);
- }
- }
- /*VRML seems to allow that*/
- gf_bt_check_code(parser, ',');
- /*we must init the node once ID is set in case we're creating rendering stacks*/
- if (init_node && (gf_node_get_tag(node)!=TAG_ProtoNode) ) gf_node_init(node);
- /*remove temp node*/
- if (replace_prev) {
- gf_node_replace(undef_node, node, 0);
- gf_list_del_item(parser->undef_nodes, undef_node);
- }
- if (!parser->parsing_proto && is_script && (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) ) {
- if (parser->cur_com) {
- if (!parser->cur_com->scripts_to_load) parser->cur_com->scripts_to_load = gf_list_new();
- gf_list_add(parser->cur_com->scripts_to_load, node);
- } else {
- /*postpone script init since it may use routes/nodes not yet defined ...*/
- gf_list_add(parser->scripts, node);
- }
- }
- return node;
- err:
- gf_node_unregister(node, parent);
- if (name) free(name);
- return NULL;
- }
- /*
- locate node, if not defined yet parse ahead in current AU
- optimization: we actually peek ALL DEF NODES till end of AU
- */
- GF_Node *gf_bt_peek_node(GF_BTParser *parser, char *defID)
- {
- GF_Node *n, *the_node;
- u32 tag, ID;
- Bool prev_is_insert = 0;
- char *str, *ret;
- char nName[1000];
- u32 pos, line, line_pos, i, count;
-
- n = gf_sg_find_node_by_name(parser->load->scene_graph, defID);
- if (n) return n;
- count = gf_list_count(parser->peeked_nodes);
- for (i=0; i<count; i++) {
- n = (GF_Node *)gf_list_get(parser->peeked_nodes, i);
- if (!strcmp(gf_node_get_name(n), defID)) return n;
- }
- the_node = NULL;
- pos = parser->line_start_pos;
- line_pos = parser->line_pos;
- line = parser->line;
- strcpy(nName, defID);
- n = NULL;
- while (!parser->done && !the_node) {
- str = gf_bt_get_next(parser, 0);
- gf_bt_check_code(parser, '[');
- gf_bt_check_code(parser, ']');
- gf_bt_check_code(parser, '{');
- gf_bt_check_code(parser, '}');
- gf_bt_check_code(parser, ',');
- gf_bt_check_code(parser, '.');
- if ( (!prev_is_insert && !strcmp(str, "AT")) || !strcmp(str, "PROTO") ) {
- /*only check in current command (but be aware of conditionals..)*/
- if (!the_node && gf_list_find(parser->bifs_au->commands, parser->cur_com)) {
- gf_bt_report(parser, GF_BAD_PARAM, "Cannot find node %s\n", nName);
- break;
- }
- continue;
- }
- if (!strcmp(str, "INSERT")) prev_is_insert = 1;
- else prev_is_insert = 0;
- if (strcmp(str, "DEF")) continue;
- str = gf_bt_get_next(parser, 0);
- ret = strdup(str);
- str = gf_bt_get_next(parser, 0);
- if (!strcmp(str, "ROUTE")) {
- free(ret);
- continue;
- }
- tag = gf_bt_get_node_tag(parser, str);
- if (!tag) {
- GF_Proto *p;
- GF_SceneGraph *sg = parser->load->scene_graph;
- while (1) {
- p = gf_sg_find_proto(sg, 0, str);
- if (p) break;
- sg = sg->parent_scene;
- if (!sg) break;
- }
- if (!p) {
- /*locate proto*/
- gf_bt_report(parser, GF_BAD_PARAM, "%s: not a valid/supported node", str);
- free(ret);
- return NULL;
- }
- n = gf_sg_proto_create_instance(parser->load->scene_graph, p);
- } else {
- n = gf_bt_new_node(parser, tag);
- }
- ID = gf_bt_get_def_id(parser, ret);
- if (n) {
- gf_node_set_id(n, ID, ret);
- gf_list_add(parser->peeked_nodes, n);
- if (!parser->parsing_proto) gf_node_init(n);
- if (!strcmp(ret, nName)) the_node = n;
- }
- free(ret);
- /*NO REGISTER on peek (both scene graph or DEF list) because peek is only used to get node type
- and fields, never to insert in the graph*/
-
- /*go on till end of AU*/
- }
- /*restore context*/
- parser->done = 0;
- gzrewind(parser->gz_in);
- gzseek(parser->gz_in, pos, SEEK_SET);
- parser->line_pos = parser->line_size;
- gf_bt_check_line(parser);
- parser->line = line;
- parser->line_pos = line_pos;
-
- return the_node;
- }
- u32 gf_bt_get_route(GF_BTParser *parser, char *name)
- {
- u32 i;
- GF_Command *com;
- GF_Route *r = gf_sg_route_find_by_name(parser->load->scene_graph, name);
- if (r) return r->ID;
- i=0;
- while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
- if (com->def_name && !strcmp(com->def_name, name)) return com->RouteID;
- }
- return 0;
- }
- Bool gf_bt_route_id_used(GF_BTParser *parser, u32 ID)
- {
- u32 i;
- GF_Command *com;
- GF_Route *r = gf_sg_route_find(parser->load->scene_graph, ID);
- if (r) return 1;
- i=0;
- while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
- if (com->RouteID == ID) return 1;
- }
- return 0;
- }
- static u32 get_evt_type(char *eventName)
- {
- if (!strcmp(eventName, "eventIn") || !strcmp(eventName, "inputOnly")) return GF_SG_EVENT_IN;
- else if (!strcmp(eventName, "eventOut") || !strcmp(eventName, "outputOnly")) return GF_SG_EVENT_OUT;
- else if (!strcmp(eventName, "field") || !strcmp(eventName, "initializeOnly")) return GF_SG_EVENT_FIELD;
- else if (!strcmp(eventName, "exposedField") || !strcmp(eventName, "inputOutput")) return GF_SG_EVENT_EXPOSED_FIELD;
- else return GF_SG_EVENT_UNKNOWN;
- }
- GF_Err gf_bt_parse_proto(GF_BTParser *parser, char *proto_code, GF_List *proto_list)
- {
- GF_FieldInfo info;
- u32 fType, eType, QPType, pID;
- Bool externProto;
- GF_Proto *proto, *prevproto;
- GF_ProtoFieldInterface *pfield;
- GF_SceneGraph *sg;
- char *str, *name;
- char szDefName[1024];
- Bool isDEF;
- if (proto_code)
- str = proto_code;
- else
- str = gf_bt_get_next(parser, 0);
-
- externProto = !strcmp(str, "EXTERNPROTO") ? 1 : 0;
- str = gf_bt_get_next(parser, 0);
- name = strdup(str);
- if (!gf_bt_check_code(parser, '[')) {
- return gf_bt_report(parser, GF_BAD_PARAM, "[ expected in proto declare");
- }
- pID = gf_bt_get_next_proto_id(parser);
- /*if redefinition remove it - WRL only, may be used by loadVRMLFormString*/
- if (!proto_list && parser->is_wrl) {
- proto = gf_sg_find_proto(parser->load->scene_graph, pID, name);
- if (proto) gf_sg_proto_del(proto);
- }
- proto = gf_sg_proto_new(parser->load->scene_graph, pID, name, proto_list ? 1 : 0);
- if (proto_list) gf_list_add(proto_list, proto);
- if (parser->load->ctx && (parser->load->ctx->max_proto_id<pID)) parser->load->ctx->max_proto_id = pID;
- /*hack for VRML, where externProto default field values are not mandatory*/
- parser->is_extern_proto_field = externProto;
- free(name);
- /*get all fields*/
- while (!parser->last_error && !gf_bt_check_code(parser, ']')) {
- str = gf_bt_get_next(parser, 0);
- next_field:
- if (gf_bt_check_code(parser, ']')) break;
- eType = get_evt_type(str);
- if (eType==GF_SG_EVENT_UNKNOWN) {
- gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown event type", str);
- goto err;
- }
- str = gf_bt_get_next(parser, 0);
- fType = gf_sg_field_type_by_name(str);
- if (fType==GF_SG_VRML_UNKNOWN) {
- gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown field type", str);
- goto err;
- }
- str = gf_bt_get_next(parser, 0);
- pfield = gf_sg_proto_field_new(proto, fType, eType, str);
- if ((eType==GF_SG_EVENT_IN) || (eType==GF_SG_EVENT_OUT)) continue;
- gf_sg_proto_field_get_field(pfield, &info);
- if (fType==GF_SG_VRML_SFNODE) {
- str = gf_bt_get_next(parser, 0);
- if (strcmp(str, "NULL")) {
- if ( (!strlen(str) || (get_evt_type(str)!=GF_SG_EVENT_UNKNOWN)) && parser->is_extern_proto_field) goto next_field;
- pfield->def_sfnode_value = gf_bt_sf_node(parser, str, NULL, NULL);
- }
- } else if (fType==GF_SG_VRML_MFNODE) {
- GF_ChildNodeItem *last = NULL;
- if (gf_bt_check_code(parser, '[')) {
- while (1) {
- GF_Node *pf_node;
- if (gf_bt_check_code(parser, ']')) break;
- pf_node = gf_bt_sf_node(parser, NULL, NULL, NULL);
- if (pf_node) gf_node_list_add_child_last( &pfield->def_mfnode_value, pf_node, &last);
- }
- }
- } else if (gf_sg_vrml_is_sf_field(fType)) {
- gf_bt_sffield(parser, &info, NULL);
- if (parser->last_error==GF_EOS) {
- gf_sg_proto_field_set_value_undefined(pfield);
- parser->last_error=GF_OK;
- goto next_field;
- }
- } else {
- gf_bt_mffield(parser, &info, NULL);
- }
- /*check QP info*/
- if (!gf_bt_check_code(parser, '{')) continue;
- if (gf_bt_check_code(parser, '}')) continue;
- str = gf_bt_get_next(parser, 0);
- if (!strcmp(str, "QP")) {
- u32 nbBits, hasMin;
- Fixed ftMin, ftMax;
- gf_bt_parse_int(parser, "QPType", (SFInt32*)&QPType);
- nbBits = 0;
- str = gf_bt_get_next(parser, 0);
- if (!strcmp(str, "nbBits")) {
- gf_bt_parse_int(parser, "nbBits", (SFInt32*)&nbBits);
- str = gf_bt_get_next(parser, 0);
- }
- hasMin = 0;
- eType = 0;
- if (!strcmp(str, "b")) {
- hasMin = 1;
- if (!gf_bt_check_code(parser, '{')) {
- gf_bt_report(parser, GF_BAD_PARAM, "%s: Invalid proto coding parameter declare", str);
- goto err;
- }
- gf_bt_parse_float(parser, "min", &ftMin);
- gf_bt_parse_float(parser, "max", &ftMax);
- if (!gf_bt_check_code(parser, '}')) {
- gf_bt_report(parser, GF_BAD_PARAM, "Invalid proto coding parameter declare");
- goto err;
- }
- if (gf_sg_vrml_get_sf_type(fType) == GF_SG_VRML_SFINT32) {
- eType = GF_SG_VRML_SFINT32;
- } else {
- eType = GF_SG_VRML_SFFLOAT;
- }
- }
- gf_bifs_proto_field_set_aq_info(pfield, QPType, hasMin, eType, &ftMin, &ftMax, nbBits);
- if (!gf_bt_ch…
Large files files are truncated, but you can click here to view the full file