Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2019
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Management 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/scene_manager.h>
27 : #include <gpac/utf.h>
28 : #include <gpac/constants.h>
29 : #include <gpac/network.h>
30 : #include <gpac/internal/bifs_dev.h>
31 : #include <gpac/internal/scenegraph_dev.h>
32 :
33 : #include <gpac/nodes_x3d.h>
34 : /*for key codes...*/
35 : #include <gpac/user.h>
36 : #include <gpac/color.h>
37 :
38 :
39 : #if !defined(GPAC_DISABLE_LOADER_BT) && !defined(GPAC_DISABLE_ZLIB)
40 :
41 : #include <gpac/mpeg4_odf.h>
42 :
43 : /*since 0.2.2, we use zlib for bt reading to handle wrl.gz files*/
44 : #include <zlib.h>
45 :
46 : void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName);
47 :
48 : void load_bt_done(GF_SceneLoader *load);
49 :
50 : #define BT_LINE_SIZE 4000
51 :
52 : typedef struct
53 : {
54 : char *name;
55 : char *value;
56 : } BTDefSymbol;
57 :
58 : typedef struct
59 : {
60 : GF_SceneLoader *load;
61 : Bool initialized;
62 : gzFile gz_in;
63 : u32 file_size, file_pos;
64 :
65 : /*create from string only*/
66 : GF_List *top_nodes;
67 :
68 : GF_Err last_error;
69 : u32 line;
70 :
71 : Bool done, in_com;
72 : u32 is_wrl;
73 : /*0: no unicode, 1: UTF-16BE, 2: UTF-16LE*/
74 : u32 unicode_type;
75 :
76 : GF_List *def_symbols;
77 :
78 : /*routes are not created in the graph when parsing, so we need to track insert and delete/replace*/
79 : GF_List *unresolved_routes, *inserted_routes, *peeked_nodes;
80 : GF_List *undef_nodes, *def_nodes;
81 :
82 : char *line_buffer;
83 : char cur_buffer[500];
84 : s32 line_size, line_pos, line_start_pos;
85 :
86 : u32 block_comment;
87 :
88 : /*set when parsing proto*/
89 : GF_Proto *parsing_proto;
90 : Bool is_extern_proto_field;
91 :
92 : /*current stream ID, AU time and RAP flag*/
93 : u32 stream_id;
94 : u32 au_time;
95 : Bool au_is_rap;
96 :
97 : /*current BIFS stream & AU*/
98 : GF_StreamContext *bifs_es;
99 : GF_AUContext *bifs_au;
100 : u32 base_bifs_id;
101 : GF_Command *cur_com;
102 :
103 : /*current OD stream & AU*/
104 : GF_StreamContext *od_es;
105 : GF_AUContext *od_au;
106 : u32 base_od_id;
107 :
108 : GF_List *scripts;
109 :
110 : u32 def_w, def_h;
111 :
112 : } GF_BTParser;
113 :
114 : GF_Err gf_bt_parse_bifs_command(GF_BTParser *parser, char *name, GF_List *cmdList);
115 : GF_Route *gf_bt_parse_route(GF_BTParser *parser, Bool skip_def, Bool is_insert, GF_Command *com);
116 : void gf_bt_resolve_routes(GF_BTParser *parser, Bool clean);
117 :
118 : GF_Node *gf_bt_peek_node(GF_BTParser *parser, char *defID);
119 :
120 433 : static GF_Err gf_bt_report(GF_BTParser *parser, GF_Err e, char *format, ...)
121 : {
122 : #ifndef GPAC_DISABLE_LOG
123 433 : if (format && gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
124 : char szMsg[2048];
125 : va_list args;
126 2 : va_start(args, format);
127 : vsnprintf(szMsg, 2048, format, args);
128 2 : va_end(args);
129 2 : GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[BT/WRL Parsing] %s (line %d)\n", szMsg, parser->line));
130 : }
131 : #endif
132 433 : if (e) parser->last_error = e;
133 433 : return e;
134 : }
135 :
136 :
137 644670 : void gf_bt_check_line(GF_BTParser *parser)
138 : {
139 : while (1) {
140 1001246 : switch (parser->line_buffer[parser->line_pos]) {
141 178288 : case ' ':
142 : case '\t':
143 : case '\n':
144 : case '\r':
145 178288 : parser->line_pos++;
146 178288 : continue;
147 : default:
148 : break;
149 : }
150 : break;
151 : }
152 :
153 644670 : if (parser->line_buffer[parser->line_pos]=='#') {
154 1 : parser->line_size = parser->line_pos;
155 : }
156 644669 : else if ((parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/') ) parser->line_size = parser->line_pos;
157 :
158 644670 : if (parser->line_size == parser->line_pos) {
159 : /*string based input - done*/
160 80904 : if (!parser->gz_in) {
161 14 : parser->done = 1;
162 14 : return;
163 : }
164 :
165 80947 : next_line:
166 81670 : parser->line_start_pos = (s32) gf_gztell(parser->gz_in);
167 81670 : parser->line_buffer[0] = 0;
168 81670 : if (parser->unicode_type) {
169 : u8 c1, c2;
170 : unsigned short wchar;
171 : unsigned short l[BT_LINE_SIZE];
172 4590 : unsigned short *dst = l;
173 : Bool is_ret = 0;
174 : u32 last_space_pos, last_space_pos_stream;
175 : u32 go = BT_LINE_SIZE - 1;
176 : last_space_pos = last_space_pos_stream = 0;
177 93505 : while (go && !gf_gzeof(parser->gz_in) ) {
178 88910 : c1 = gf_gzgetc(parser->gz_in);
179 88910 : c2 = gf_gzgetc(parser->gz_in);
180 : /*Little-endian order*/
181 88910 : if (parser->unicode_type==2) {
182 88910 : if (c2) {
183 5 : wchar = c2;
184 5 : wchar <<=8;
185 5 : wchar |= c1;
186 : }
187 88905 : else wchar = c1;
188 : } else {
189 0 : wchar = c1;
190 0 : if (c2) {
191 0 : wchar <<= 8;
192 0 : wchar |= c2;
193 : }
194 : }
195 88910 : *dst = wchar;
196 88910 : if (wchar=='\r') is_ret = 1;
197 88910 : else if (wchar=='\n') {
198 4585 : dst++;
199 4585 : break;
200 : }
201 84325 : else if (is_ret) {
202 0 : u32 fpos = (u32) gf_gztell(parser->gz_in);
203 0 : gf_gzseek(parser->gz_in, fpos-2, SEEK_SET);
204 0 : break;
205 : }
206 84325 : if (wchar==' ') {
207 : //last_space_pos_stream = (u32) gf_gztell(parser->gz_in);
208 26550 : last_space_pos = (u32) (dst - l);
209 : }
210 84325 : dst++;
211 84325 : go--;
212 :
213 : }
214 4590 : *dst = 0;
215 : /*long line, rewind stream to last space*/
216 4590 : if (!go) {
217 0 : u32 rew_pos = (u32) (gf_gztell(parser->gz_in) - 2*(dst - &l[last_space_pos]) );
218 0 : gf_gzseek(parser->gz_in, rew_pos, SEEK_SET);
219 0 : l[last_space_pos+1] = 0;
220 : }
221 : /*check eof*/
222 4590 : if (l[0]==0xFFFF) {
223 5 : parser->done = 1;
224 10 : return;
225 : }
226 : /*convert to mbc string*/
227 4585 : dst = l;
228 4585 : gf_utf8_wcstombs(parser->line_buffer, BT_LINE_SIZE, (const unsigned short **) &dst);
229 :
230 4585 : if (!strlen(parser->line_buffer) && gf_gzeof(parser->gz_in)) {
231 0 : parser->done = 1;
232 0 : return;
233 : }
234 : } else {
235 77080 : if ((gf_gzgets(parser->gz_in, parser->line_buffer, BT_LINE_SIZE) == NULL)
236 76080 : || (!strlen(parser->line_buffer) && gf_gzeof(parser->gz_in))) {
237 1000 : parser->done = 1;
238 1000 : return;
239 : }
240 : /*watchout for long lines*/
241 76080 : if (1 + strlen(parser->line_buffer) == BT_LINE_SIZE) {
242 : u32 rew, pos, go;
243 : rew = 0;
244 : go = 1;
245 : while (go) {
246 0 : switch (parser->line_buffer[strlen(parser->line_buffer)-1]) {
247 : case ' ':
248 : case ',':
249 : case '[':
250 : case ']':
251 : go = 0;
252 : break;
253 0 : default:
254 0 : parser->line_buffer[strlen(parser->line_buffer)-1] = 0;
255 0 : rew++;
256 0 : break;
257 : }
258 : }
259 0 : pos = (u32) gf_gztell(parser->gz_in);
260 0 : gf_gzseek(parser->gz_in, pos-rew, SEEK_SET);
261 : }
262 : }
263 :
264 :
265 80811 : while (1) {
266 : char c;
267 161476 : u32 len = (u32) strlen(parser->line_buffer);
268 161476 : if (!len) break;
269 158880 : c = parser->line_buffer[len-1];
270 158880 : if (!strchr("\n\r\t", c)) break;
271 80811 : parser->line_buffer[len-1] = 0;
272 : }
273 :
274 :
275 80665 : parser->line_size = (u32) strlen(parser->line_buffer);
276 80665 : parser->line_pos = 0;
277 80665 : parser->line++;
278 :
279 : {
280 80665 : u32 pos = (u32) gf_gztell(parser->gz_in);
281 80665 : if (pos>=parser->file_pos) {
282 80561 : parser->file_pos = pos;
283 80561 : if (parser->line>1) gf_set_progress("BT Parsing", pos, parser->file_size);
284 : }
285 : }
286 :
287 475654 : while ((parser->line_buffer[parser->line_pos]==' ') || (parser->line_buffer[parser->line_pos]=='\t'))
288 394989 : parser->line_pos++;
289 80665 : if ( (parser->line_buffer[parser->line_pos]=='#')
290 80033 : || ( (parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/')) ) {
291 :
292 723 : if (parser->line==1) {
293 60 : if (strstr(parser->line_buffer, "VRML")) {
294 10 : if (strstr(parser->line_buffer, "VRML V2.0")) parser->is_wrl = 1;
295 : /*although not std, many files use this*/
296 0 : else if (strstr(parser->line_buffer, "VRML2.0")) parser->is_wrl = 1;
297 : else {
298 0 : gf_bt_report(parser, GF_NOT_SUPPORTED, "%s: VRML Version Not Supported", parser->line_buffer);
299 0 : return;
300 : }
301 : }
302 50 : else if (strstr(parser->line_buffer, "X3D")) {
303 18 : if (strstr(parser->line_buffer, "X3D V3.0")) parser->is_wrl = 2;
304 : else {
305 0 : gf_bt_report(parser, GF_NOT_SUPPORTED, "%s: X3D Version Not Supported", parser->line_buffer);
306 0 : return;
307 : }
308 : }
309 : }
310 723 : if (!strnicmp(parser->line_buffer+parser->line_pos, "#define ", 8) && !parser->block_comment) {
311 : char *buf, *sep;
312 15 : parser->line_pos+=8;
313 15 : buf = parser->line_buffer+parser->line_pos;
314 15 : sep = strchr(buf, ' ');
315 15 : if (sep && (sep[1]!='\n') ) {
316 : BTDefSymbol *def;
317 15 : GF_SAFEALLOC(def, BTDefSymbol);
318 15 : if (!def) {
319 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("Fail to allocate DEF node\n"));
320 : return;
321 : }
322 15 : sep[0] = 0;
323 15 : def->name = gf_strdup(buf);
324 15 : sep[0] = ' ';
325 15 : buf = sep+1;
326 15 : while (strchr(" \t", buf[0])) buf++;
327 15 : def->value = gf_strdup(buf);
328 15 : gf_list_add(parser->def_symbols, def);
329 : }
330 : }
331 708 : else if (!strnicmp(parser->line_buffer+parser->line_pos, "#if ", 4)) {
332 : u32 len = 0;
333 22 : parser->line_pos+=4;
334 : while (1) {
335 176 : if (parser->line_pos+(s32)len==parser->line_size) break;
336 77 : if (strchr(" \n\t", parser->line_buffer[parser->line_pos+len]))
337 : break;
338 77 : len++;
339 : }
340 22 : if (len) {
341 22 : if (len==1) {
342 17 : if (!strnicmp(parser->line_buffer+parser->line_pos, "0", len)) {
343 14 : parser->block_comment++;
344 : }
345 : } else {
346 : u32 i, count;
347 : char *keyWord = NULL;
348 5 : count = gf_list_count(parser->def_symbols);
349 10 : for (i=0; i<count; i++) {
350 10 : BTDefSymbol *def = (BTDefSymbol *)gf_list_get(parser->def_symbols, i);
351 10 : if (!strnicmp(parser->line_buffer+parser->line_pos, def->name, len)) {
352 5 : keyWord = def->value;
353 5 : break;
354 : }
355 : }
356 5 : if (keyWord && !strcmp(keyWord, "0")) {
357 5 : parser->block_comment++;
358 : }
359 : }
360 : }
361 : }
362 686 : else if (!strnicmp(parser->line_buffer+parser->line_pos, "#endif", 6)) {
363 22 : if (parser->block_comment) parser->block_comment--;
364 : }
365 664 : else if (!strnicmp(parser->line_buffer+parser->line_pos, "#else", 5)) {
366 10 : if (parser->block_comment)
367 10 : parser->block_comment--;
368 : else
369 0 : parser->block_comment++;
370 : }
371 654 : else if (!strnicmp(parser->line_buffer+parser->line_pos, "#size", 5)) {
372 : char *buf;
373 39 : parser->line_pos+=6;
374 39 : buf = parser->line_buffer+parser->line_pos;
375 78 : while (strchr(" \t", buf[0]))
376 0 : buf++;
377 39 : sscanf(buf, "%dx%d", &parser->def_w, &parser->def_h);
378 : }
379 : goto next_line;
380 : }
381 :
382 79942 : if (parser->block_comment)
383 : goto next_line;
384 :
385 : /*brute-force replacement of defined symbols (!!FIXME - no mem checking done !!)*/
386 79885 : if (parser->line_pos < parser->line_size) {
387 : u32 i, count;
388 77215 : count = gf_list_count(parser->def_symbols);
389 : while (1) {
390 : Bool found = 0;
391 90245 : for (i=0; i<count; i++) {
392 : u32 symb_len, val_len, copy_len;
393 13020 : BTDefSymbol *def = (BTDefSymbol *)gf_list_get(parser->def_symbols, i);
394 13020 : char *start = strstr(parser->line_buffer, def->name);
395 13020 : if (!start) continue;
396 10 : symb_len = (u32) strlen(def->name);
397 10 : if (!strchr(" \n\r\t,[]{}\'\"", start[symb_len])) continue;
398 10 : val_len = (u32) strlen(def->value);
399 10 : copy_len = (u32) strlen(start + symb_len) + 1;
400 10 : memmove(start + val_len, start + symb_len, sizeof(char)*copy_len);
401 10 : memcpy(start, def->value, sizeof(char)*val_len);
402 10 : parser->line_size = (u32) strlen(parser->line_buffer);
403 : found = 1;
404 : }
405 77225 : if (!found) break;
406 : }
407 : }
408 : }
409 643651 : if (!parser->line_size) {
410 2596 : if (!gf_gzeof(parser->gz_in)) gf_bt_check_line(parser);
411 0 : else parser->done = 1;
412 : }
413 641055 : else if (!parser->done && (parser->line_size == parser->line_pos)) gf_bt_check_line(parser);
414 : }
415 :
416 0 : void gf_bt_force_line(GF_BTParser *parser)
417 : {
418 5 : parser->line_pos = parser->line_size;
419 0 : }
420 :
421 0 : Bool gf_bt_check_code(GF_BTParser *parser, char code)
422 : {
423 437016 : gf_bt_check_line(parser);
424 437016 : if (parser->line_buffer[parser->line_pos]==code) {
425 124446 : parser->line_pos++;
426 0 : return 1;
427 : }
428 : return 0;
429 : }
430 :
431 201243 : char *gf_bt_get_next(GF_BTParser *parser, Bool point_break)
432 : {
433 : u32 has_quote;
434 : Bool go = 1;
435 : s32 i;
436 201243 : gf_bt_check_line(parser);
437 : i=0;
438 : has_quote = 0;
439 201243 : while (go) {
440 1184980 : if (parser->line_buffer[parser->line_pos + i] == '\"') {
441 515 : if (!has_quote) has_quote = 1;
442 : else has_quote = 0;
443 515 : parser->line_pos += 1;
444 :
445 515 : if (parser->line_pos+i==parser->line_size) break;
446 296 : continue;
447 : }
448 1184465 : if (!has_quote) {
449 1178641 : switch (parser->line_buffer[parser->line_pos + i]) {
450 : case 0:
451 : case ' ':
452 : case '\t':
453 : case '\r':
454 : case '\n':
455 : case '{':
456 : case '}':
457 : case ']':
458 : case '[':
459 : case ',':
460 : go = 0;
461 : break;
462 28930 : case '.':
463 28930 : if (point_break) go = 0;
464 : break;
465 : }
466 : if (!go) break;
467 : }
468 1003441 : parser->cur_buffer[i] = parser->line_buffer[parser->line_pos + i];
469 1003441 : i++;
470 1003441 : if (parser->line_pos+i==parser->line_size) break;
471 : }
472 201243 : parser->cur_buffer[i] = 0;
473 201243 : parser->line_pos += i;
474 201243 : return parser->cur_buffer;
475 : }
476 :
477 5724 : char *gf_bt_get_string(GF_BTParser *parser, u8 string_delim)
478 : {
479 : char *res;
480 : s32 i, size;
481 :
482 : #define BT_STR_CHECK_ALLOC \
483 : if (i==size) { \
484 : res = (char*)gf_realloc(res, sizeof(char) * (size+500+1)); \
485 : size += 500; \
486 : } \
487 :
488 5724 : res = (char*)gf_malloc(sizeof(char) * 500);
489 : size = 500;
490 5724 : while (parser->line_buffer[parser->line_pos]==' ') parser->line_pos++;
491 :
492 5724 : if (parser->line_pos==parser->line_size) {
493 0 : if (gf_gzeof(parser->gz_in)) return NULL;
494 0 : gf_bt_check_line(parser);
495 : }
496 5724 : if (!string_delim) string_delim = '"';
497 :
498 : i=0;
499 : while (1) {
500 184691 : if (parser->line_buffer[parser->line_pos] == string_delim)
501 5732 : if ( !parser->line_pos || (parser->line_buffer[parser->line_pos-1] != '\\') ) break;
502 :
503 178967 : BT_STR_CHECK_ALLOC
504 :
505 178967 : if ((parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/') && (parser->line_buffer[parser->line_pos-1]!=':') ) {
506 : /*this looks like a comment*/
507 11 : if (!strchr(&parser->line_buffer[parser->line_pos], string_delim)) {
508 11 : gf_bt_check_line(parser);
509 11 : continue;
510 : }
511 : }
512 178956 : if ((parser->line_buffer[parser->line_pos] != '\\') || (parser->line_buffer[parser->line_pos+1] != string_delim)) {
513 : /*handle UTF-8 - WARNING: if parser is in unicode string is already utf8 multibyte chars*/
514 178948 : if (!parser->unicode_type && parser->line_buffer[parser->line_pos] & 0x80) {
515 : char c = parser->line_buffer[parser->line_pos];
516 : /*non UTF8 (likely some win-CP)*/
517 23 : if ( (parser->line_buffer[parser->line_pos+1] & 0xc0) != 0x80) {
518 23 : res[i] = 0xc0 | ( (parser->line_buffer[parser->line_pos] >> 6) & 0x3 );
519 23 : i++;
520 23 : BT_STR_CHECK_ALLOC
521 23 : parser->line_buffer[parser->line_pos] &= 0xbf;
522 : }
523 : /*UTF8 2 bytes char*/
524 0 : else if ( (c & 0xe0) == 0xc0) {
525 0 : res[i] = parser->line_buffer[parser->line_pos];
526 0 : parser->line_pos++;
527 0 : i++;
528 0 : BT_STR_CHECK_ALLOC
529 : }
530 : /*UTF8 3 bytes char*/
531 0 : else if ( (c & 0xf0) == 0xe0) {
532 0 : res[i] = parser->line_buffer[parser->line_pos];
533 0 : parser->line_pos++;
534 0 : i++;
535 0 : BT_STR_CHECK_ALLOC
536 0 : res[i] = parser->line_buffer[parser->line_pos];
537 0 : parser->line_pos++;
538 0 : i++;
539 0 : BT_STR_CHECK_ALLOC
540 : }
541 : /*UTF8 4 bytes char*/
542 0 : else if ( (c & 0xf8) == 0xf0) {
543 0 : res[i] = parser->line_buffer[parser->line_pos];
544 0 : parser->line_pos++;
545 0 : i++;
546 0 : BT_STR_CHECK_ALLOC
547 0 : res[i] = parser->line_buffer[parser->line_pos];
548 0 : parser->line_pos++;
549 0 : i++;
550 0 : BT_STR_CHECK_ALLOC
551 0 : res[i] = parser->line_buffer[parser->line_pos];
552 0 : parser->line_pos++;
553 0 : i++;
554 0 : BT_STR_CHECK_ALLOC
555 : }
556 : }
557 :
558 178948 : res[i] = parser->line_buffer[parser->line_pos];
559 178948 : i++;
560 : }
561 178956 : parser->line_pos++;
562 178956 : if (parser->line_pos==parser->line_size) {
563 2124 : gf_bt_check_line(parser);
564 : }
565 :
566 : }
567 :
568 : #undef BT_STR_CHECK_ALLOC
569 :
570 5724 : res[i] = 0;
571 5724 : parser->line_pos += 1;
572 5724 : return res;
573 : }
574 :
575 113386 : Bool gf_bt_check_externproto_field(GF_BTParser *parser, char *str)
576 : {
577 113386 : if (!parser->is_extern_proto_field) return 0;
578 217 : if (!strcmp(str, "") || !strcmp(str, "field") || !strcmp(str, "eventIn") || !strcmp(str, "eventOut") || !strcmp(str, "exposedField")) {
579 0 : parser->last_error = GF_EOS;
580 0 : return 1;
581 : }
582 : return 0;
583 : }
584 :
585 108976 : static Bool check_keyword(GF_BTParser *parser, char *str, s32 *val)
586 : {
587 : s32 res;
588 : char *sep;
589 108976 : sep = strchr(str, '$');
590 108976 : if (!sep) return 0;
591 0 : sep++;
592 0 : if (!strcmp(sep, "F1")) res = GF_KEY_F1;
593 0 : else if (!strcmp(sep, "F2")) res = GF_KEY_F2;
594 0 : else if (!strcmp(sep, "F3")) res = GF_KEY_F3;
595 0 : else if (!strcmp(sep, "F4")) res = GF_KEY_F4;
596 0 : else if (!strcmp(sep, "F5")) res = GF_KEY_F5;
597 0 : else if (!strcmp(sep, "F6")) res = GF_KEY_F6;
598 0 : else if (!strcmp(sep, "F7")) res = GF_KEY_F7;
599 0 : else if (!strcmp(sep, "F8")) res = GF_KEY_F8;
600 0 : else if (!strcmp(sep, "F9")) res = GF_KEY_F9;
601 0 : else if (!strcmp(sep, "F10")) res = GF_KEY_F10;
602 0 : else if (!strcmp(sep, "F11")) res = GF_KEY_F11;
603 0 : else if (!strcmp(sep, "F12")) res = GF_KEY_F12;
604 0 : else if (!strcmp(sep, "HOME")) res = GF_KEY_HOME;
605 0 : else if (!strcmp(sep, "END")) res = GF_KEY_END;
606 0 : else if (!strcmp(sep, "PREV")) res = GF_KEY_PAGEUP;
607 0 : else if (!strcmp(sep, "NEXT")) res = GF_KEY_PAGEDOWN;
608 0 : else if (!strcmp(sep, "UP")) res = GF_KEY_UP;
609 0 : else if (!strcmp(sep, "DOWN")) res = GF_KEY_DOWN;
610 0 : else if (!strcmp(sep, "LEFT")) res = GF_KEY_LEFT;
611 0 : else if (!strcmp(sep, "RIGHT")) res = GF_KEY_RIGHT;
612 0 : else if (!strcmp(sep, "RETURN")) res = GF_KEY_ENTER;
613 0 : else if (!strcmp(sep, "BACK")) res = GF_KEY_BACKSPACE;
614 0 : else if (!strcmp(sep, "TAB")) res = GF_KEY_TAB;
615 0 : else if (strlen(sep)==1) {
616 : char c;
617 0 : sscanf(sep, "%c", &c);
618 0 : res = c;
619 : } else {
620 0 : gf_bt_report(parser, GF_OK, "unrecognized keyword %s - skipping", str);
621 : res = 0;
622 : }
623 0 : if (strchr(str, '-')) *val = -res;
624 0 : else *val = res;
625 : return 1;
626 : }
627 :
628 49563 : GF_Err gf_bt_parse_float(GF_BTParser *parser, const char *name, Fixed *val)
629 : {
630 : s32 var;
631 : Float f;
632 49563 : char *str = gf_bt_get_next(parser, 0);
633 49563 : if (!str) return parser->last_error = GF_IO_ERR;
634 49563 : if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
635 :
636 49563 : if (check_keyword(parser, str, &var)) {
637 0 : *val = INT2FIX(var);
638 0 : return GF_OK;
639 : }
640 49563 : if (sscanf(str, "%g", &f) != 1) {
641 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
642 : }
643 49563 : *val = FLT2FIX(f);
644 49563 : return GF_OK;
645 : }
646 205 : GF_Err gf_bt_parse_double(GF_BTParser *parser, const char *name, SFDouble *val)
647 : {
648 205 : char *str = gf_bt_get_next(parser, 0);
649 205 : if (!str) return parser->last_error = GF_IO_ERR;
650 205 : if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
651 205 : if (sscanf(str, "%lf", val) != 1) {
652 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
653 : }
654 : return GF_OK;
655 : }
656 59413 : GF_Err gf_bt_parse_int(GF_BTParser *parser, const char *name, SFInt32 *val)
657 : {
658 59413 : char *str = gf_bt_get_next(parser, 0);
659 59413 : if (!str) return parser->last_error = GF_IO_ERR;
660 59413 : if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
661 :
662 59413 : if (check_keyword(parser, str, val)) return GF_OK;
663 : /*URL ODID*/
664 59413 : if (!strnicmp(str, "od:", 3)) str += 3;
665 59413 : if (sscanf(str, "%d", val) != 1) {
666 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
667 : }
668 : return GF_OK;
669 : }
670 1964 : GF_Err gf_bt_parse_bool(GF_BTParser *parser, const char *name, SFBool *val)
671 : {
672 1964 : char *str = gf_bt_get_next(parser, 0);
673 1964 : if (!str) return parser->last_error = GF_IO_ERR;
674 1964 : if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
675 :
676 1964 : if (!stricmp(str, "true") || !strcmp(str, "1") ) {
677 1343 : *val = 1;
678 : }
679 621 : else if (!stricmp(str, "false") || !strcmp(str, "0") ) {
680 621 : *val = 0;
681 : } else {
682 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Boolean expected", name);
683 : }
684 : return GF_OK;
685 : }
686 :
687 2233 : GF_Err gf_bt_parse_color(GF_BTParser *parser, const char *name, SFColor *col)
688 : {
689 : Float f;
690 : u32 val;
691 2233 : char *str = gf_bt_get_next(parser, 0);
692 2233 : if (!str) return parser->last_error = GF_IO_ERR;
693 2233 : if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
694 :
695 2233 : if (sscanf(str, "%f", &f) == 1) {
696 2220 : col->red = FLT2FIX(f);
697 : /*many VRML files use ',' separator*/
698 : gf_bt_check_code(parser, ',');
699 2220 : gf_bt_parse_float(parser, name, & col->green);
700 : gf_bt_check_code(parser, ',');
701 2220 : gf_bt_parse_float(parser, name, & col->blue);
702 2220 : return parser->last_error;
703 : }
704 13 : val = gf_color_parse(str);
705 13 : if (!val) {
706 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number or name expected", name);
707 : }
708 13 : col->red = INT2FIX((val>>16) & 0xFF) / 255;
709 13 : col->green = INT2FIX((val>>8) & 0xFF) / 255;
710 13 : col->blue = INT2FIX(val & 0xFF) / 255;
711 13 : return parser->last_error;
712 : }
713 :
714 8 : GF_Err gf_bt_parse_colorRGBA(GF_BTParser *parser, const char *name, SFColorRGBA *col)
715 : {
716 : Float f;
717 8 : char *str = gf_bt_get_next(parser, 0);
718 8 : if (!str) return parser->last_error = GF_IO_ERR;
719 8 : if (gf_bt_check_externproto_field(parser, str)) return GF_OK;
720 :
721 : /*HTML code*/
722 8 : if (str[0]=='$') {
723 : u32 val;
724 0 : sscanf(str, "%x", &val);
725 0 : col->red = INT2FIX((val>>24) & 0xFF) / 255;
726 0 : col->green = INT2FIX((val>>16) & 0xFF) / 255;
727 0 : col->blue = INT2FIX((val>>8) & 0xFF) / 255;
728 0 : col->alpha = INT2FIX(val & 0xFF) / 255;
729 0 : return parser->last_error;
730 : }
731 8 : if (sscanf(str, "%f", &f) != 1) {
732 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Number expected", name);
733 : }
734 8 : col->red = FLT2FIX(f);
735 : gf_bt_check_code(parser, ',');
736 8 : gf_bt_parse_float(parser, name, & col->green);
737 : gf_bt_check_code(parser, ',');
738 8 : gf_bt_parse_float(parser, name, & col->blue);
739 : gf_bt_check_code(parser, ',');
740 8 : gf_bt_parse_float(parser, name, & col->alpha);
741 8 : return parser->last_error;
742 : }
743 :
744 : static void gf_bt_offset_time(GF_BTParser *parser, Double *time)
745 : {
746 418 : if (!parser->is_wrl) {
747 : Double res;
748 418 : res = parser->au_time;
749 418 : res /= parser->bifs_es->timeScale;
750 418 : *time += res;
751 : }
752 : }
753 :
754 223 : static void gf_bt_check_time_offset(GF_BTParser *parser, GF_Node *n, GF_FieldInfo *info)
755 : {
756 223 : if (!n || !(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
757 206 : if (gf_node_get_tag(n) != TAG_ProtoNode) {
758 175 : if (!stricmp(info->name, "startTime") || !stricmp(info->name, "stopTime"))
759 54 : gf_bt_offset_time(parser, (Double *)info->far_ptr);
760 31 : } else if (gf_sg_proto_field_is_sftime_offset(n, info)) {
761 10 : gf_bt_offset_time(parser, (Double *)info->far_ptr);
762 : }
763 : }
764 14112 : static void gf_bt_update_timenode(GF_BTParser *parser, GF_Node *node)
765 : {
766 14112 : if (!node || !(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
767 :
768 12456 : switch (gf_node_get_tag(node)) {
769 7 : case TAG_MPEG4_AnimationStream:
770 : gf_bt_offset_time(parser, & ((M_AnimationStream*)node)->startTime);
771 : gf_bt_offset_time(parser, & ((M_AnimationStream*)node)->stopTime);
772 : break;
773 2 : case TAG_MPEG4_AudioBuffer:
774 : gf_bt_offset_time(parser, & ((M_AudioBuffer*)node)->startTime);
775 : gf_bt_offset_time(parser, & ((M_AudioBuffer*)node)->stopTime);
776 : break;
777 6 : case TAG_MPEG4_AudioClip:
778 : gf_bt_offset_time(parser, & ((M_AudioClip*)node)->startTime);
779 : gf_bt_offset_time(parser, & ((M_AudioClip*)node)->stopTime);
780 : break;
781 7 : case TAG_MPEG4_AudioSource:
782 : gf_bt_offset_time(parser, & ((M_AudioSource*)node)->startTime);
783 : gf_bt_offset_time(parser, & ((M_AudioSource*)node)->stopTime);
784 : break;
785 35 : case TAG_MPEG4_MovieTexture:
786 : gf_bt_offset_time(parser, & ((M_MovieTexture*)node)->startTime);
787 : gf_bt_offset_time(parser, & ((M_MovieTexture*)node)->stopTime);
788 : break;
789 120 : case TAG_MPEG4_TimeSensor:
790 : gf_bt_offset_time(parser, & ((M_TimeSensor*)node)->startTime);
791 : gf_bt_offset_time(parser, & ((M_TimeSensor*)node)->stopTime);
792 : break;
793 74 : case TAG_ProtoNode:
794 : {
795 : u32 i, nbFields;
796 : GF_FieldInfo inf;
797 74 : nbFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL);
798 436 : for (i=0; i<nbFields; i++) {
799 362 : gf_node_get_field(node, i, &inf);
800 362 : if (inf.fieldType != GF_SG_VRML_SFTIME) continue;
801 18 : gf_bt_check_time_offset(parser, node, &inf);
802 : }
803 : }
804 74 : break;
805 : }
806 : }
807 :
808 :
809 90648 : void gf_bt_sffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
810 : {
811 90648 : switch (info->fieldType) {
812 59032 : case GF_SG_VRML_SFINT32:
813 59032 : gf_bt_parse_int(parser, info->name, (SFInt32 *)info->far_ptr);
814 59032 : if (parser->last_error) return;
815 : break;
816 1964 : case GF_SG_VRML_SFBOOL:
817 1964 : gf_bt_parse_bool(parser, info->name, (SFBool *)info->far_ptr);
818 1964 : if (parser->last_error) return;
819 : break;
820 4654 : case GF_SG_VRML_SFFLOAT:
821 4654 : gf_bt_parse_float(parser, info->name, (SFFloat *)info->far_ptr);
822 4654 : if (parser->last_error) return;
823 : break;
824 0 : case GF_SG_VRML_SFDOUBLE:
825 0 : gf_bt_parse_double(parser, info->name, (SFDouble *)info->far_ptr);
826 0 : if (parser->last_error) return;
827 : break;
828 205 : case GF_SG_VRML_SFTIME:
829 205 : gf_bt_parse_double(parser, info->name, (SFDouble *)info->far_ptr);
830 205 : if (parser->last_error) return;
831 205 : gf_bt_check_time_offset(parser, n, info);
832 205 : break;
833 2233 : case GF_SG_VRML_SFCOLOR:
834 2233 : gf_bt_parse_color(parser, info->name, (SFColor *)info->far_ptr);
835 2233 : break;
836 8 : case GF_SG_VRML_SFCOLORRGBA:
837 8 : gf_bt_parse_colorRGBA(parser, info->name, (SFColorRGBA *)info->far_ptr);
838 8 : break;
839 7935 : case GF_SG_VRML_SFVEC2F:
840 7935 : gf_bt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->x);
841 7935 : if (parser->last_error) return;
842 : /*many VRML files use ',' separator*/
843 : gf_bt_check_code(parser, ',');
844 7935 : gf_bt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->y);
845 7935 : if (parser->last_error) return;
846 : break;
847 0 : case GF_SG_VRML_SFVEC2D:
848 0 : gf_bt_parse_double(parser, info->name, & ((SFVec2d *)info->far_ptr)->x);
849 0 : if (parser->last_error) return;
850 : /*many VRML files use ',' separator*/
851 : gf_bt_check_code(parser, ',');
852 0 : gf_bt_parse_double(parser, info->name, & ((SFVec2d *)info->far_ptr)->y);
853 0 : if (parser->last_error) return;
854 : break;
855 8027 : case GF_SG_VRML_SFVEC3F:
856 8027 : gf_bt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->x);
857 8027 : if (parser->last_error) return;
858 : /*many VRML files use ',' separator*/
859 : gf_bt_check_code(parser, ',');
860 8027 : gf_bt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->y);
861 8027 : if (parser->last_error) return;
862 : /*many VRML files use ',' separator*/
863 : gf_bt_check_code(parser, ',');
864 8027 : gf_bt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->z);
865 8027 : if (parser->last_error) return;
866 : break;
867 0 : case GF_SG_VRML_SFVEC3D:
868 0 : gf_bt_parse_double(parser, info->name, & ((SFVec3d *)info->far_ptr)->x);
869 0 : if (parser->last_error) return;
870 : /*many VRML files use ',' separator*/
871 : gf_bt_check_code(parser, ',');
872 0 : gf_bt_parse_double(parser, info->name, & ((SFVec3d *)info->far_ptr)->y);
873 0 : if (parser->last_error) return;
874 : /*many VRML files use ',' separator*/
875 : gf_bt_check_code(parser, ',');
876 0 : gf_bt_parse_double(parser, info->name, & ((SFVec3d *)info->far_ptr)->z);
877 0 : if (parser->last_error) return;
878 : break;
879 6 : case GF_SG_VRML_SFVEC4F:
880 6 : gf_bt_parse_float(parser, info->name, & ((SFVec4f *)info->far_ptr)->x);
881 6 : if (parser->last_error) return;
882 : /*many VRML files use ',' separator*/
883 : gf_bt_check_code(parser, ',');
884 6 : gf_bt_parse_float(parser, info->name, & ((SFVec4f *)info->far_ptr)->y);
885 6 : if (parser->last_error) return;
886 : /*many VRML files use ',' separator*/
887 : gf_bt_check_code(parser, ',');
888 6 : gf_bt_parse_float(parser, info->name, & ((SFVec4f *)info->far_ptr)->z);
889 6 : if (parser->last_error) return;
890 : /*many VRML files use ',' separator*/
891 : gf_bt_check_code(parser, ',');
892 6 : gf_bt_parse_float(parser, info->name, & ((SFVec4f *)info->far_ptr)->q);
893 6 : if (parser->last_error) return;
894 : break;
895 116 : case GF_SG_VRML_SFROTATION:
896 116 : gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->x);
897 116 : if (parser->last_error) return;
898 116 : gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->y);
899 116 : if (parser->last_error) return;
900 116 : gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->z);
901 116 : if (parser->last_error) return;
902 116 : gf_bt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->q);
903 116 : if (parser->last_error) return;
904 : break;
905 5519 : case GF_SG_VRML_SFSTRING:
906 : {
907 : u8 delim = 0;
908 : if (gf_bt_check_code(parser, '\"')) delim = '\"';
909 : else if (gf_bt_check_code(parser, '\'')) delim = '\'';
910 : if (delim) {
911 5519 : char *str = gf_bt_get_string(parser, delim);
912 5519 : if (!str)
913 : goto err;
914 5519 : if (((SFString *)info->far_ptr)->buffer) gf_free(((SFString *)info->far_ptr)->buffer);
915 5519 : ((SFString *)info->far_ptr)->buffer = NULL;
916 5519 : if (strlen(str))
917 5089 : ((SFString *)info->far_ptr)->buffer = str;
918 : else
919 430 : gf_free(str);
920 :
921 5519 : if (n && (n->sgprivate->tag==TAG_MPEG4_BitWrapper)) {
922 15 : gf_sm_update_bitwrapper_buffer(n, parser->load->fileName);
923 : }
924 : } else {
925 : goto err;
926 : }
927 : }
928 : break;
929 334 : case GF_SG_VRML_SFURL:
930 : {
931 : u8 delim = 0;
932 : if (gf_bt_check_code(parser, '\"')) delim = '\"';
933 : else if (gf_bt_check_code(parser, '\'')) delim = '\'';
934 : if (delim) {
935 160 : SFURL *url = (SFURL *)info->far_ptr;
936 160 : char *str = gf_bt_get_string(parser, delim);
937 160 : if (!str) goto err;
938 160 : if (url->url) gf_free(url->url);
939 160 : url->url = NULL;
940 160 : url->OD_ID = 0;
941 160 : if (strchr(str, '#')) {
942 13 : url->url = str;
943 : } else {
944 147 : u32 id = 0;
945 : char *odstr = str;
946 147 : if (!strnicmp(str, "od://", 5)) odstr += 5;
947 147 : else if (!strnicmp(str, "od:", 3)) odstr += 3;
948 : /*be careful, an url like "11-regression-test.mp4" will return 1 on sscanf :)*/
949 147 : if (sscanf(odstr, "%u", &id) == 1) {
950 : char szURL[20];
951 39 : sprintf(szURL, "%u", id);
952 39 : if (strcmp(szURL, odstr)) id=0;
953 : }
954 147 : if (id) {
955 39 : url->OD_ID = id;
956 39 : gf_free(str);
957 : } else {
958 108 : url->url = str;
959 : }
960 : }
961 : } else {
962 : s32 val;
963 174 : gf_bt_parse_int(parser, info->name, & val );
964 174 : if (parser->last_error) return;
965 174 : ((SFURL *)info->far_ptr)->OD_ID = val;
966 : }
967 : }
968 : break;
969 554 : case GF_SG_VRML_SFCOMMANDBUFFER:
970 : {
971 554 : SFCommandBuffer *cb = (SFCommandBuffer *)info->far_ptr;
972 : if (gf_bt_check_code(parser, '{')) {
973 554 : GF_Command *prev_com = parser->cur_com;
974 1844 : while (!parser->last_error) {
975 : if (gf_bt_check_code(parser, '}')) break;
976 736 : parser->last_error = gf_bt_parse_bifs_command(parser, NULL, cb->commandList);
977 : }
978 554 : parser->cur_com = prev_com;
979 : }
980 : }
981 : break;
982 14 : case GF_SG_VRML_SFIMAGE:
983 : {
984 : u32 i, size, v;
985 14 : SFImage *img = (SFImage *)info->far_ptr;
986 14 : gf_bt_parse_int(parser, "width", (SFInt32 *)&img->width);
987 14 : if (parser->last_error) return;
988 14 : gf_bt_parse_int(parser, "height", (SFInt32 *)&img->height);
989 14 : if (parser->last_error) return;
990 14 : gf_bt_parse_int(parser, "nbComp", (SFInt32 *)&v);
991 14 : if (parser->last_error) return;
992 14 : img->numComponents = v;
993 14 : size = img->width * img->height * img->numComponents;
994 14 : if (img->pixels) gf_free(img->pixels);
995 14 : img->pixels = (unsigned char*)gf_malloc(sizeof(char) * size);
996 238 : for (i=0; i<size; i++) {
997 224 : char *str = gf_bt_get_next(parser, 0);
998 224 : if (strstr(str, "0x")) sscanf(str, "%x", &v);
999 0 : else sscanf(str, "%u", &v);
1000 224 : switch (img->numComponents) {
1001 176 : case 1:
1002 176 : img->pixels[i] = (char) v;
1003 176 : break;
1004 16 : case 2:
1005 16 : img->pixels[i] = (char) (v>>8)&0xFF;
1006 16 : img->pixels[i+1] = (char) (v)&0xFF;
1007 : i++;
1008 16 : break;
1009 16 : case 3:
1010 16 : img->pixels[i] = (char) (v>>16)&0xFF;
1011 16 : img->pixels[i+1] = (char) (v>>8)&0xFF;
1012 16 : img->pixels[i+2] = (char) (v)&0xFF;
1013 : i+=2;
1014 16 : break;
1015 16 : case 4:
1016 16 : img->pixels[i] = (char) (v>>24)&0xFF;
1017 16 : img->pixels[i+1] = (char) (v>>16)&0xFF;
1018 16 : img->pixels[i+2] = (char) (v>>8)&0xFF;
1019 16 : img->pixels[i+3] = (char) (v)&0xFF;
1020 : i+=3;
1021 16 : break;
1022 : }
1023 : }
1024 : }
1025 14 : break;
1026 45 : case GF_SG_VRML_SFSCRIPT:
1027 : {
1028 45 : SFScript *sc = (SFScript *) info->far_ptr;
1029 : if (!gf_bt_check_code(parser, '\"')) {
1030 0 : gf_bt_report(parser, GF_BAD_PARAM, "\" expected in Script");
1031 : }
1032 45 : sc->script_text = (char*)gf_bt_get_string(parser, '\"');
1033 : }
1034 45 : break;
1035 2 : case GF_SG_VRML_SFATTRREF:
1036 : {
1037 2 : SFAttrRef *ar = (SFAttrRef*) info->far_ptr;
1038 2 : char *str = gf_bt_get_next(parser, 1);
1039 : if (!gf_bt_check_code(parser, '.')) {
1040 0 : gf_bt_report(parser, GF_BAD_PARAM, "'.' expected in SFAttrRef");
1041 : } else {
1042 : GF_FieldInfo pinfo;
1043 2 : ar->node = gf_bt_peek_node(parser, str);
1044 2 : str = gf_bt_get_next(parser, 0);
1045 2 : if (gf_node_get_field_by_name(ar->node, str, &pinfo) != GF_OK) {
1046 0 : gf_bt_report(parser, GF_BAD_PARAM, "field %s is not a member of node %s", str, gf_node_get_class_name(ar->node) );
1047 : } else {
1048 2 : ar->fieldIndex = pinfo.fieldIndex;
1049 : }
1050 : }
1051 :
1052 : }
1053 : break;
1054 0 : default:
1055 0 : parser->last_error = GF_NOT_SUPPORTED;
1056 0 : break;
1057 :
1058 : }
1059 : gf_bt_check_code(parser, ',');
1060 : return;
1061 0 : err:
1062 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Invalid field syntax", info->name);
1063 : }
1064 :
1065 3733 : void gf_bt_mffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
1066 : {
1067 : GF_FieldInfo sfInfo;
1068 : Bool force_single = 0;
1069 :
1070 : if (!gf_bt_check_code(parser, '[')) {
1071 112 : if (parser->is_extern_proto_field) return;
1072 : force_single = 1;
1073 : }
1074 :
1075 3733 : sfInfo.fieldType = gf_sg_vrml_get_sf_type(info->fieldType);
1076 3733 : sfInfo.name = info->name;
1077 3733 : gf_sg_vrml_mf_reset(info->far_ptr, info->fieldType);
1078 :
1079 3733 : while (!gf_bt_check_code(parser, ']')) {
1080 79647 : gf_sg_vrml_mf_append(info->far_ptr, info->fieldType, &sfInfo.far_ptr);
1081 79647 : gf_bt_sffield(parser, &sfInfo, n);
1082 79647 : if (parser->last_error) return;
1083 :
1084 : gf_bt_check_code(parser, ',');
1085 79647 : if (force_single) break;
1086 : }
1087 : }
1088 :
1089 17454 : Bool gf_bt_check_ndt(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *node, GF_Node *parent)
1090 : {
1091 17454 : if (!node) return 1;
1092 17433 : if (parent->sgprivate->tag == TAG_MPEG4_Script) return 1;
1093 : #ifndef GPAC_DISABLE_X3D
1094 17269 : if (parent->sgprivate->tag == TAG_X3D_Script) return 1;
1095 : #endif
1096 17268 : if (node->sgprivate->tag == TAG_UndefinedNode) return 1;
1097 :
1098 : /*this handles undefined nodes*/
1099 17258 : if (gf_node_in_table(node, info->NDTtype)) return 1;
1100 : /*not found*/
1101 0 : gf_bt_report(parser, GF_BAD_PARAM, "node %s not valid in field %s\n", gf_node_get_class_name(node), info->name);
1102 0 : gf_node_unregister(node, parent);
1103 0 : return 0;
1104 : }
1105 :
1106 3141 : u32 gf_bt_get_next_node_id(GF_BTParser *parser)
1107 : {
1108 : u32 ID;
1109 3141 : GF_SceneGraph *sc = parser->load->scene_graph;
1110 3141 : if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
1111 3141 : ID = gf_sg_get_next_available_node_id(sc);
1112 3141 : if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
1113 3065 : parser->load->ctx->max_node_id = ID;
1114 3141 : return ID;
1115 : }
1116 25 : u32 gf_bt_get_next_route_id(GF_BTParser *parser)
1117 : {
1118 : u32 ID;
1119 25 : GF_SceneGraph *sg = parser->load->scene_graph;
1120 25 : if (parser->parsing_proto) sg = gf_sg_proto_get_graph(parser->parsing_proto);
1121 :
1122 25 : ID = gf_sg_get_next_available_route_id(sg);
1123 25 : if (parser->load->ctx && (ID>parser->load->ctx->max_route_id))
1124 25 : parser->load->ctx->max_route_id = ID;
1125 25 : return ID;
1126 : }
1127 92 : u32 gf_bt_get_next_proto_id(GF_BTParser *parser)
1128 : {
1129 : u32 ID;
1130 92 : GF_SceneGraph *sc = parser->load->scene_graph;
1131 92 : if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
1132 92 : ID = gf_sg_get_next_available_proto_id(sc);
1133 92 : if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
1134 80 : parser->load->ctx->max_proto_id = ID;
1135 92 : return ID;
1136 : }
1137 :
1138 3503 : u32 gf_bt_get_def_id(GF_BTParser *parser, char *defName)
1139 : {
1140 : GF_Node *n=NULL;
1141 3503 : u32 ID=0;
1142 3503 : if (sscanf(defName, "N%u", &ID) == 1) {
1143 : u32 k=1;
1144 1969 : while (defName[k]) {
1145 1279 : if (strchr("0123456789", defName[k])==0) {
1146 0 : ID = 0;
1147 0 : break;
1148 : }
1149 1279 : k++;
1150 : }
1151 690 : if (ID) {
1152 657 : ID ++;
1153 657 : n = gf_sg_find_node(parser->load->scene_graph, ID);
1154 657 : if (!n) {
1155 362 : if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
1156 362 : return ID;
1157 : }
1158 : }
1159 : }
1160 :
1161 3141 : ID = gf_bt_get_next_node_id(parser);
1162 3141 : if (n) {
1163 295 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[BT Parsing] (line %d) Binary ID %d already assigned to %s - keeping internal ID %d", parser->line, gf_node_get_name(n), ID));
1164 : }
1165 3141 : return ID;
1166 : }
1167 :
1168 1148 : Bool gf_bt_set_field_is(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
1169 : {
1170 : GF_Err e;
1171 : u32 i;
1172 : GF_ProtoFieldInterface *pfield;
1173 : GF_FieldInfo pinfo;
1174 : char *str;
1175 1148 : gf_bt_check_line(parser);
1176 : i=0;
1177 1148 : while ((parser->line_buffer[parser->line_pos + i] == ' ') || (parser->line_buffer[parser->line_pos + i] == '\t')) i++;
1178 1148 : if (strnicmp(&parser->line_buffer[parser->line_pos + i] , "IS", 2)) return 0;
1179 :
1180 316 : gf_bt_get_next(parser, 0);
1181 316 : str = gf_bt_get_next(parser, 0);
1182 :
1183 : /*that's an ISed field*/
1184 316 : pfield = gf_sg_proto_field_find_by_name(parser->parsing_proto, str);
1185 316 : if (!pfield) {
1186 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown proto field", str);
1187 0 : return 1;
1188 : }
1189 316 : gf_sg_proto_field_get_field(pfield, &pinfo);
1190 316 : e = gf_sg_proto_field_set_ised(parser->parsing_proto, pinfo.fieldIndex, n, info->fieldIndex);
1191 316 : if (e) gf_bt_report(parser, GF_BAD_PARAM, "IS: Invalid field type for field %s", info->name);
1192 : return 1;
1193 : }
1194 :
1195 1106 : void gf_bt_check_unresolved_nodes(GF_BTParser *parser)
1196 : {
1197 : u32 i, count;
1198 1106 : count = gf_list_count(parser->undef_nodes);
1199 1106 : if (!count) return;
1200 0 : for (i=0; i<count; i++) {
1201 0 : GF_Node *n = (GF_Node *)gf_list_get(parser->undef_nodes, i);
1202 0 : gf_bt_report(parser, GF_BAD_PARAM, "Cannot find node %s\n", gf_node_get_name(n) );
1203 0 : gf_node_unregister(n, NULL);
1204 : }
1205 0 : parser->last_error = GF_BAD_PARAM;
1206 : }
1207 :
1208 22 : Bool gf_bt_has_been_def(GF_BTParser *parser, char *node_name)
1209 : {
1210 : u32 i, count;
1211 22 : count = gf_list_count(parser->def_nodes);
1212 252 : for (i=0; i<count; i++) {
1213 230 : GF_Node *n = (GF_Node *) gf_list_get(parser->def_nodes, i);
1214 230 : if (!strcmp(gf_node_get_name(n), node_name)) return 1;
1215 : }
1216 : return 0;
1217 : }
1218 :
1219 14730 : u32 gf_bt_get_node_tag(GF_BTParser *parser, char *node_name)
1220 : {
1221 : u32 tag;
1222 : /*if VRML and allowing non MPEG4 nodes, use X3D*/
1223 14730 : if (parser->is_wrl && !(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) {
1224 : #ifndef GPAC_DISABLE_X3D
1225 246 : tag = gf_node_x3d_type_by_class_name(node_name);
1226 246 : if (!tag)
1227 : #endif
1228 1 : tag = gf_node_mpeg4_type_by_class_name(node_name);
1229 246 : if (tag) return tag;
1230 : #ifndef GPAC_DISABLE_X3D
1231 0 : if (!strcmp(node_name, "Rectangle")) return TAG_X3D_Rectangle2D;
1232 0 : if (!strcmp(node_name, "Circle")) return TAG_X3D_Circle2D;
1233 : #endif
1234 : } else {
1235 14484 : tag = gf_node_mpeg4_type_by_class_name(node_name);
1236 14484 : if (!tag) {
1237 129 : if (!strcmp(node_name, "Rectangle2D")) return TAG_MPEG4_Rectangle;
1238 129 : if (!strcmp(node_name, "Circle2D")) return TAG_MPEG4_Circle;
1239 : #ifndef GPAC_DISABLE_X3D
1240 129 : if (!(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) return gf_node_x3d_type_by_class_name(node_name);
1241 : #endif
1242 : }
1243 : }
1244 : return tag;
1245 : }
1246 :
1247 18079 : GF_Node *gf_bt_sf_node(GF_BTParser *parser, char *node_name, GF_Node *parent, char *szDEFName)
1248 : {
1249 : u32 tag, ID;
1250 : Bool is_script, replace_prev, register_def;
1251 : GF_Proto *proto;
1252 : GF_Node *node, *newnode, *undef_node;
1253 : GF_FieldInfo info;
1254 : Bool init_node;
1255 : char *name;
1256 : char * str;
1257 :
1258 : init_node = 0;
1259 :
1260 18079 : if (node_name) {
1261 : str = node_name;
1262 : } else {
1263 17515 : str = gf_bt_get_next(parser, 0);
1264 : }
1265 : name = NULL;
1266 18079 : if (!strcmp(str, "NULL")) return NULL;
1267 :
1268 : ID = 0;
1269 : register_def = 0;
1270 : replace_prev = 0;
1271 : undef_node = NULL;
1272 18027 : if (!strcmp(str, "DEF")) {
1273 : register_def = 1;
1274 3431 : str = gf_bt_get_next(parser, 0);
1275 3431 : name = gf_strdup(str);
1276 3431 : str = gf_bt_get_next(parser, 0);
1277 14596 : } else if (szDEFName) {
1278 72 : name = gf_strdup(szDEFName);
1279 : register_def = 1;
1280 : }
1281 18027 : if (name) {
1282 3503 : undef_node = gf_sg_find_node_by_name(parser->load->scene_graph, name);
1283 3503 : if (undef_node) {
1284 22 : gf_list_del_item(parser->peeked_nodes, undef_node);
1285 22 : ID = gf_node_get_id(undef_node);
1286 : /*if we see twice a DEF N1 then force creation of a new node*/
1287 22 : if (gf_bt_has_been_def(parser, name)) {
1288 : undef_node = NULL;
1289 0 : ID = gf_bt_get_def_id(parser, name);
1290 0 : gf_bt_report(parser, GF_OK, "Node %s has been DEFed several times, IDs may get corrupted", name);
1291 : }
1292 : } else {
1293 3481 : ID = gf_bt_get_def_id(parser, name);
1294 : }
1295 : }
1296 14524 : else if (!strcmp(str, "USE")) {
1297 3310 : str = gf_bt_get_next(parser, 0);
1298 3310 : node = gf_sg_find_node_by_name(parser->load->scene_graph, str);
1299 3310 : if (!node) {
1300 : /*create a temp node (undefined)*/
1301 9 : node = gf_node_new(parser->load->scene_graph, TAG_UndefinedNode);
1302 9 : ID = gf_bt_get_def_id(parser, str);
1303 9 : gf_node_set_id(node, ID, str);
1304 9 : gf_node_register(node, NULL);
1305 9 : gf_list_add(parser->undef_nodes, node);
1306 : }
1307 3310 : gf_node_register(node, parent);
1308 3310 : return node;
1309 : }
1310 : proto = NULL;
1311 14717 : tag = gf_bt_get_node_tag(parser, str);
1312 14717 : if (!tag) {
1313 129 : GF_SceneGraph *sg = parser->load->scene_graph;
1314 : while (1) {
1315 151 : proto = gf_sg_find_proto(sg, 0, str);
1316 151 : if (proto) break;
1317 22 : sg = sg->parent_scene;
1318 22 : if (!sg) break;
1319 : }
1320 129 : if (!proto) {
1321 : /*locate proto*/
1322 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: not a valid/supported node", str);
1323 0 : return NULL;
1324 : }
1325 : tag = TAG_ProtoNode;
1326 : }
1327 14717 : if (undef_node && (undef_node->sgprivate->tag == tag)) {
1328 : node = undef_node;
1329 : } else {
1330 14704 : if (undef_node) replace_prev = 1;
1331 14704 : if (proto) {
1332 129 : node = gf_sg_proto_create_instance(parser->load->scene_graph, proto);
1333 : } else {
1334 14575 : node = gf_node_new(parser->load->scene_graph, tag);
1335 : }
1336 14704 : if (!parser->parsing_proto) init_node = 1;
1337 : }
1338 : is_script = 0;
1339 29434 : if ((tag==TAG_MPEG4_Script)
1340 : #ifndef GPAC_DISABLE_X3D
1341 14717 : || (tag==TAG_X3D_Script)
1342 : #endif
1343 : )
1344 : is_script = 1;
1345 :
1346 14717 : if (!node) {
1347 0 : parser->last_error = GF_SG_UNKNOWN_NODE;
1348 0 : return NULL;
1349 : }
1350 14717 : if (register_def) gf_list_add(parser->def_nodes, node);
1351 :
1352 14717 : gf_node_register(node, parent);
1353 :
1354 : /*VRML: "The transformation hierarchy shall be a directed acyclic graph; results are undefined if a node
1355 : in the transformation hierarchy is its own ancestor"
1356 : that's good, because the scene graph can't handle cyclic graphs (destroy will never be called).
1357 : However we still have to register the node before parsing it, to update node registry and get correct IDs*/
1358 14717 : if (name) {
1359 3503 : if (!undef_node || replace_prev) {
1360 3490 : gf_node_set_id(node, ID, name);
1361 : }
1362 3503 : gf_free(name);
1363 : name = NULL;
1364 : }
1365 14717 : if (!parser->parsing_proto) gf_bt_update_timenode(parser, node);
1366 :
1367 : if (gf_bt_check_code(parser, '{')) {
1368 :
1369 : while (1) {
1370 : if (gf_bt_check_code(parser, '}'))
1371 : break;
1372 :
1373 25177 : str = gf_bt_get_next(parser, 0);
1374 25177 : if (!str) {
1375 0 : gf_bt_report(parser, GF_BAD_PARAM, "Invalid node syntax");
1376 0 : goto err;
1377 : }
1378 : /*VRML/X3D specific */
1379 25177 : if (parser->is_wrl) {
1380 : /*we ignore bboxCenter and bboxSize*/
1381 398 : if (!strcmp(str, "bboxCenter") || !strcmp(str, "bboxSize")) {
1382 : Fixed f;
1383 2 : gf_bt_parse_float(parser, "x", &f);
1384 2 : gf_bt_parse_float(parser, "y", &f);
1385 2 : gf_bt_parse_float(parser, "z", &f);
1386 2 : continue;
1387 : }
1388 : /*some VRML files declare routes almost anywhere*/
1389 396 : if (!strcmp(str, "ROUTE")) {
1390 0 : gf_bt_parse_route(parser, 1, 0, NULL);
1391 0 : continue;
1392 : }
1393 : }
1394 :
1395 25175 : parser->last_error = gf_node_get_field_by_name(node, str, &info);
1396 :
1397 : /*check common VRML fields removed in MPEG4*/
1398 25175 : if (parser->last_error) {
1399 320 : if (!parser->is_wrl) {
1400 : /*we ignore 'solid' for MPEG4 box/cone/etc*/
1401 312 : if (!strcmp(str, "solid")) {
1402 : SFBool b;
1403 0 : gf_bt_parse_bool(parser, "solid", &b);
1404 0 : parser->last_error = GF_OK;
1405 0 : continue;
1406 : }
1407 : /*we ignore 'description' for MPEG4 sensors*/
1408 312 : else if (!strcmp(str, "description")) {
1409 0 : char *tmpstr = gf_bt_get_string(parser, 0);
1410 0 : gf_free(tmpstr);
1411 0 : parser->last_error = GF_OK;
1412 0 : continue;
1413 : }
1414 : /*remaps X3D to old VRML/MPEG4*/
1415 312 : else if ((tag==TAG_MPEG4_LOD) && !strcmp(str, "children")) {
1416 : str = "level";
1417 0 : parser->last_error = gf_node_get_field_by_name(node, str, &info);
1418 : }
1419 312 : else if ((tag==TAG_MPEG4_Switch) && !strcmp(str, "children")) {
1420 : str = "choice";
1421 0 : parser->last_error = gf_node_get_field_by_name(node, str, &info);
1422 : }
1423 312 : else if (!strcmp(str, "enabled")) {
1424 : SFBool b;
1425 0 : gf_bt_parse_bool(parser, "collide", &b);
1426 0 : parser->last_error = GF_OK;
1427 0 : continue;
1428 : }
1429 : } else {
1430 : /*remaps old VRML/MPEG4 to X3D if possible*/
1431 : #ifndef GPAC_DISABLE_X3D
1432 8 : if ((tag==TAG_X3D_LOD) && !strcmp(str, "level")) {
1433 : str = "children";
1434 0 : parser->last_error = gf_node_get_field_by_name(node, str, &info);
1435 : }
1436 8 : else if ((tag==TAG_X3D_Switch) && !strcmp(str, "choice")) {
1437 : str = "children";
1438 0 : parser->last_error = gf_node_get_field_by_name(node, str, &info);
1439 : }
1440 : else
1441 : #endif
1442 8 : if (!strcmp(str, "collide")) {
1443 : SFBool b;
1444 0 : gf_bt_parse_bool(parser, "enabled", &b);
1445 0 : parser->last_error = GF_OK;
1446 0 : continue;
1447 : }
1448 : }
1449 : }
1450 :
1451 25175 : if (is_script && parser->last_error) {
1452 : u32 eType, fType;
1453 :
1454 320 : if (!strcmp(str, "eventIn") || !strcmp(str, "inputOnly")) eType = GF_SG_SCRIPT_TYPE_EVENT_IN;
1455 208 : else if (!strcmp(str, "eventOut") || !strcmp(str, "outputOnly")) eType = GF_SG_SCRIPT_TYPE_EVENT_OUT;
1456 193 : else if (!strcmp(str, "field") || !strcmp(str, "initializeOnly")) eType = GF_SG_SCRIPT_TYPE_FIELD;
1457 : else {
1458 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown script event type", str);
1459 0 : goto err;
1460 : }
1461 320 : str = gf_bt_get_next(parser, 0);
1462 320 : fType = gf_sg_field_type_by_name(str);
1463 320 : if (fType==GF_SG_VRML_UNKNOWN) {
1464 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown script field type", str);
1465 0 : goto err;
1466 : }
1467 320 : parser->last_error = GF_OK;
1468 320 : str = gf_bt_get_next(parser, 0);
1469 320 : gf_sg_script_field_new(node, eType, fType, str);
1470 320 : parser->last_error = gf_node_get_field_by_name(node, str, &info);
1471 :
1472 320 : if (parser->parsing_proto && gf_bt_set_field_is(parser, &info, node)) continue;
1473 320 : if ((eType == GF_SG_SCRIPT_TYPE_EVENT_IN) || (eType == GF_SG_SCRIPT_TYPE_EVENT_OUT)) continue;
1474 : }
1475 :
1476 25048 : if (parser->last_error) {
1477 0 : gf_bt_report(parser, parser->last_error, "%s: Unknown field", str);
1478 0 : goto err;
1479 : }
1480 :
1481 25048 : if (proto) gf_sg_proto_mark_field_loaded(node, &info);
1482 25048 : if (parser->parsing_proto && gf_bt_set_field_is(parser, &info, node)) continue;
1483 :
1484 24732 : switch (info.fieldType) {
1485 7918 : case GF_SG_VRML_SFNODE:
1486 : /*if redefining node reset it - this happens with CreateVrmlFromString*/
1487 7918 : if (* ((GF_Node **)info.far_ptr) ) {
1488 0 : gf_node_unregister(* ((GF_Node **)info.far_ptr), node);
1489 0 : * ((GF_Node **)info.far_ptr) = NULL;
1490 : }
1491 :
1492 7918 : newnode = gf_bt_sf_node(parser, NULL, node, NULL);
1493 7918 : if (!newnode && parser->last_error) goto err;
1494 7918 : if (newnode) {
1495 7918 : if (!gf_bt_check_ndt(parser, &info, newnode, node)) goto err;
1496 :
1497 7918 : * ((GF_Node **)info.far_ptr) = newnode;
1498 : }
1499 : break;
1500 3343 : case GF_SG_VRML_MFNODE:
1501 : {
1502 3343 : GF_ChildNodeItem *last = NULL;
1503 : Bool single_child = 0;
1504 : if (!gf_bt_check_code(parser, '[')) {
1505 0 : if (parser->is_wrl) single_child = 1;
1506 : else break;
1507 : }
1508 :
1509 : /*if redefining node reset it - this happens with CreateVrmlFromString*/
1510 3343 : if (undef_node==node) {
1511 0 : gf_node_unregister_children(node, *(GF_ChildNodeItem **)info.far_ptr);
1512 0 : *(GF_ChildNodeItem **)info.far_ptr = NULL;
1513 : }
1514 :
1515 12753 : while (single_child || !gf_bt_check_code(parser, ']')) {
1516 : /*VRML seems to allow that*/
1517 : gf_bt_check_code(parser, ',');
1518 9410 : newnode = gf_bt_sf_node(parser, NULL, node, NULL);
1519 9410 : if (!newnode && parser->last_error) goto err;
1520 9410 : if (newnode) {
1521 9410 : if (!gf_bt_check_ndt(parser, &info, newnode, node)) goto err;
1522 9410 : gf_node_list_add_child_last( (GF_ChildNodeItem **)info.far_ptr, newnode, &last);
1523 : }
1524 9410 : if (single_child) break;
1525 : }
1526 : }
1527 3343 : break;
1528 13471 : default:
1529 13471 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
1530 9816 : gf_bt_sffield(parser, &info, node);
1531 : } else {
1532 3655 : gf_bt_mffield(parser, &info, node);
1533 : }
1534 13471 : if (parser->last_error) goto err;
1535 : break;
1536 : }
1537 : /*VRML seems to allow that*/
1538 : gf_bt_check_code(parser, ',');
1539 : }
1540 : }
1541 : /*VRML seems to allow that*/
1542 : gf_bt_check_code(parser, ',');
1543 :
1544 : /*we must init the node once ID is set in case we're creating rendering stacks*/
1545 14717 : if (init_node && (gf_node_get_tag(node)!=TAG_ProtoNode) ) gf_node_init(node);
1546 :
1547 : /*remove temp node*/
1548 14717 : if (replace_prev) {
1549 9 : gf_node_replace(undef_node, node, 0);
1550 9 : gf_node_unregister(undef_node, NULL);
1551 9 : gf_list_del_item(parser->undef_nodes, undef_node);
1552 : }
1553 :
1554 14717 : if (!parser->parsing_proto && is_script && (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) ) {
1555 35 : if (parser->cur_com) {
1556 34 : if (!parser->cur_com->scripts_to_load) parser->cur_com->scripts_to_load = gf_list_new();
1557 34 : gf_list_add(parser->cur_com->scripts_to_load, node);
1558 : } else {
1559 : /*postpone script init since it may use routes/nodes not yet defined ...*/
1560 1 : gf_list_add(parser->scripts, node);
1561 : }
1562 : }
1563 : /*For Ivica: load proto as soon as found when in playback mode*/
1564 14717 : if ( (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) && proto && !parser->parsing_proto) {
1565 74 : parser->last_error = gf_sg_proto_load_code(node);
1566 : }
1567 : return node;
1568 :
1569 0 : err:
1570 0 : gf_node_unregister(node, parent);
1571 0 : if (name) gf_free(name);
1572 : return NULL;
1573 : }
1574 : /*
1575 : locate node, if not defined yet parse ahead in current AU
1576 : optimization: we actually peek ALL DEF NODES till end of AU
1577 : */
1578 3935 : GF_Node *gf_bt_peek_node(GF_BTParser *parser, char *defID)
1579 : {
1580 : GF_Node *n, *the_node;
1581 : u32 tag, ID;
1582 : Bool prev_is_insert = 0;
1583 : char *ret;
1584 : char nName[1000];
1585 : u32 pos, line, line_pos, i, count;
1586 :
1587 3935 : n = gf_sg_find_node_by_name(parser->load->scene_graph, defID);
1588 3935 : if (n) return n;
1589 :
1590 24 : count = gf_list_count(parser->peeked_nodes);
1591 24 : for (i=0; i<count; i++) {
1592 0 : n = (GF_Node *)gf_list_get(parser->peeked_nodes, i);
1593 0 : if (!strcmp(gf_node_get_name(n), defID)) return n;
1594 : }
1595 :
1596 : the_node = NULL;
1597 24 : pos = parser->line_start_pos;
1598 24 : line_pos = parser->line_pos;
1599 24 : line = parser->line;
1600 : strcpy(nName, defID);
1601 :
1602 : n = NULL;
1603 272 : while (!parser->done && !the_node) {
1604 234 : char *str = gf_bt_get_next(parser, 0);
1605 : gf_bt_check_code(parser, '[');
1606 : gf_bt_check_code(parser, ']');
1607 : gf_bt_check_code(parser, '{');
1608 : gf_bt_check_code(parser, '}');
1609 : gf_bt_check_code(parser, ',');
1610 : gf_bt_check_code(parser, '.');
1611 :
1612 234 : if ( (!prev_is_insert && !strcmp(str, "AT")) || !strcmp(str, "PROTO") ) {
1613 : /*only check in current command (but be aware of conditionals..)*/
1614 10 : if (gf_list_find(parser->bifs_au->commands, parser->cur_com)) {
1615 : break;
1616 : }
1617 0 : continue;
1618 : }
1619 224 : if (!strcmp(str, "INSERT")) prev_is_insert = 1;
1620 : else prev_is_insert = 0;
1621 :
1622 224 : if (strcmp(str, "DEF")) continue;
1623 13 : str = gf_bt_get_next(parser, 0);
1624 13 : ret = gf_strdup(str);
1625 13 : str = gf_bt_get_next(parser, 0);
1626 13 : if (!strcmp(str, "ROUTE")) {
1627 0 : gf_free(ret);
1628 0 : continue;
1629 : }
1630 :
1631 13 : tag = gf_bt_get_node_tag(parser, str);
1632 13 : if (!tag) {
1633 : GF_Proto *p;
1634 0 : GF_SceneGraph *sg = parser->load->scene_graph;
1635 : while (1) {
1636 0 : p = gf_sg_find_proto(sg, 0, str);
1637 0 : if (p) break;
1638 0 : sg = sg->parent_scene;
1639 0 : if (!sg) break;
1640 : }
1641 0 : if (!p) {
1642 : /*locate proto*/
1643 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: not a valid/supported node", str);
1644 0 : gf_free(ret);
1645 0 : return NULL;
1646 : }
1647 0 : n = gf_sg_proto_create_instance(parser->load->scene_graph, p);
1648 : } else {
1649 13 : n = gf_node_new(parser->load->scene_graph, tag);
1650 : }
1651 13 : ID = gf_bt_get_def_id(parser, ret);
1652 13 : if (n) {
1653 13 : gf_node_set_id(n, ID, ret);
1654 13 : gf_list_add(parser->peeked_nodes, n);
1655 13 : if (!parser->parsing_proto) gf_node_init(n);
1656 13 : if (!strcmp(ret, nName)) the_node = n;
1657 : }
1658 13 : gf_free(ret);
1659 :
1660 : /*NO REGISTER on peek (both scene graph or DEF list) because peek is only used to get node type
1661 : and fields, never to insert in the graph*/
1662 :
1663 : /*go on till end of AU*/
1664 : }
1665 : /*restore context*/
1666 24 : parser->done = 0;
1667 24 : gf_gzrewind(parser->gz_in);
1668 24 : gf_gzseek(parser->gz_in, pos, SEEK_SET);
1669 24 : parser->line_pos = parser->line_size;
1670 24 : gf_bt_check_line(parser);
1671 24 : parser->line = line;
1672 24 : parser->line_pos = line_pos;
1673 :
1674 24 : return the_node;
1675 : }
1676 :
1677 104 : u32 gf_bt_get_route(GF_BTParser *parser, char *name)
1678 : {
1679 : u32 i;
1680 : GF_Command *com;
1681 104 : GF_Route *r = gf_sg_route_find_by_name(parser->load->scene_graph, name);
1682 104 : if (r) return r->ID;
1683 101 : i=0;
1684 394 : while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
1685 257 : if (com->def_name && !strcmp(com->def_name, name)) return com->RouteID;
1686 : }
1687 : return 0;
1688 : }
1689 :
1690 8 : Bool gf_bt_route_id_used(GF_BTParser *parser, u32 ID)
1691 : {
1692 : u32 i;
1693 : GF_Command *com;
1694 8 : GF_Route *r = gf_sg_route_find(parser->load->scene_graph, ID);
1695 8 : if (r) return 1;
1696 8 : i=0;
1697 60 : while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
1698 44 : if (com->RouteID == ID) return 1;
1699 : }
1700 : return 0;
1701 : }
1702 :
1703 516 : static u32 get_evt_type(char *eventName)
1704 : {
1705 516 : if (!strcmp(eventName, "eventIn") || !strcmp(eventName, "inputOnly")) return GF_SG_EVENT_IN;
1706 493 : else if (!strcmp(eventName, "eventOut") || !strcmp(eventName, "outputOnly")) return GF_SG_EVENT_OUT;
1707 484 : else if (!strcmp(eventName, "field") || !strcmp(eventName, "initializeOnly")) return GF_SG_EVENT_FIELD;
1708 482 : else if (!strcmp(eventName, "exposedField") || !strcmp(eventName, "inputOutput")) return GF_SG_EVENT_EXPOSED_FIELD;
1709 0 : else return GF_SG_EVENT_UNKNOWN;
1710 : }
1711 :
1712 92 : GF_Err gf_bt_parse_proto(GF_BTParser *parser, char *proto_code, GF_List *proto_list)
1713 : {
1714 : GF_FieldInfo info;
1715 92 : u32 fType, eType, QPType=0, pID;
1716 : Bool externProto;
1717 : GF_Proto *proto, *prevproto;
1718 : GF_ProtoFieldInterface *pfield;
1719 : GF_SceneGraph *sg;
1720 : char *str, *name;
1721 : char szDefName[1024];
1722 : Bool isDEF;
1723 :
1724 92 : if (proto_code)
1725 : str = proto_code;
1726 : else
1727 10 : str = gf_bt_get_next(parser, 0);
1728 :
1729 92 : externProto = !strcmp(str, "EXTERNPROTO") ? 1 : 0;
1730 92 : str = gf_bt_get_next(parser, 0);
1731 92 : name = gf_strdup(str);
1732 : if (!gf_bt_check_code(parser, '[')) {
1733 0 : return gf_bt_report(parser, GF_BAD_PARAM, "[ expected in proto declare");
1734 : }
1735 92 : pID = gf_bt_get_next_proto_id(parser);
1736 : /*if redefinition remove it - WRL only, may be used by loadVRMLFormString*/
1737 92 : if (!proto_list && parser->is_wrl) {
1738 0 : proto = gf_sg_find_proto(parser->load->scene_graph, pID, name);
1739 0 : if (proto) gf_sg_proto_del(proto);
1740 : }
1741 92 : proto = gf_sg_proto_new(parser->load->scene_graph, pID, name, proto_list ? 1 : 0);
1742 92 : if (proto_list) gf_list_add(proto_list, proto);
1743 92 : if (parser->load->ctx && (parser->load->ctx->max_proto_id<pID)) parser->load->ctx->max_proto_id = pID;
1744 :
1745 : /*hack for VRML, where externProto default field values are not mandatory*/
1746 92 : parser->is_extern_proto_field = externProto;
1747 :
1748 92 : gf_free(name);
1749 : /*get all fields*/
1750 700 : while (!parser->last_error && !gf_bt_check_code(parser, ']')) {
1751 516 : str = gf_bt_get_next(parser, 0);
1752 :
1753 0 : next_field:
1754 : if (gf_bt_check_code(parser, ']')) break;
1755 :
1756 516 : eType = get_evt_type(str);
1757 516 : if (eType==GF_SG_EVENT_UNKNOWN) {
1758 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown event type", str);
1759 0 : goto err;
1760 : }
1761 516 : str = gf_bt_get_next(parser, 0);
1762 516 : fType = gf_sg_field_type_by_name(str);
1763 516 : if (fType==GF_SG_VRML_UNKNOWN) {
1764 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown field type", str);
1765 0 : goto err;
1766 : }
1767 516 : str = gf_bt_get_next(parser, 0);
1768 516 : pfield = gf_sg_proto_field_new(proto, fType, eType, str);
1769 516 : if ((eType==GF_SG_EVENT_IN) || (eType==GF_SG_EVENT_OUT)) continue;
1770 :
1771 484 : gf_sg_proto_field_get_field(pfield, &info);
1772 484 : if (fType==GF_SG_VRML_SFNODE) {
1773 54 : str = gf_bt_get_next(parser, 0);
1774 54 : if (strcmp(str, "NULL")) {
1775 0 : if ( (!strlen(str) || (get_evt_type(str)!=GF_SG_EVENT_UNKNOWN)) && parser->is_extern_proto_field) goto next_field;
1776 0 : pfield->def_sfnode_value = gf_bt_sf_node(parser, str, NULL, NULL);
1777 : }
1778 430 : } else if (fType==GF_SG_VRML_MFNODE) {
1779 15 : GF_ChildNodeItem *last = NULL;
1780 : if (gf_bt_check_code(parser, '[')) {
1781 : while (1) {
1782 : GF_Node *pf_node;
1783 : if (gf_bt_check_code(parser, ']')) break;
1784 0 : pf_node = gf_bt_sf_node(parser, NULL, NULL, NULL);
1785 0 : if (pf_node) gf_node_list_add_child_last( &pfield->def_mfnode_value, pf_node, &last);
1786 : }
1787 : }
1788 415 : } else if (gf_sg_vrml_is_sf_field(fType)) {
1789 403 : gf_bt_sffield(parser, &info, NULL);
1790 : /*value not specified for externproto*/
1791 403 : if (parser->last_error==GF_EOS) {
1792 0 : parser->last_error=GF_OK;
1793 0 : goto next_field;
1794 : }
1795 : } else {
1796 12 : gf_bt_mffield(parser, &info, NULL);
1797 : }
1798 : /*check QP info*/
1799 484 : if (!gf_bt_check_code(parser, '{')) continue;
1800 0 : if (gf_bt_check_code(parser, '}')) continue;
1801 0 : str = gf_bt_get_next(parser, 0);
1802 0 : if (!strcmp(str, "QP")) {
1803 : u32 nbBits, hasMin;
1804 : Fixed ftMin, ftMax;
1805 0 : gf_bt_parse_int(parser, "QPType", (SFInt32*)&QPType);
1806 :
1807 0 : nbBits = 0;
1808 0 : str = gf_bt_get_next(parser, 0);
1809 0 : if (!strcmp(str, "nbBits")) {
1810 0 : gf_bt_parse_int(parser, "nbBits", (SFInt32*)&nbBits);
1811 0 : str = gf_bt_get_next(parser, 0);
1812 : }
1813 : hasMin = 0;
1814 : eType = 0;
1815 0 : if (!strcmp(str, "b")) {
1816 : hasMin = 1;
1817 : if (!gf_bt_check_code(parser, '{')) {
1818 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Invalid proto coding parameter declare", str);
1819 0 : goto err;
1820 : }
1821 0 : gf_bt_parse_float(parser, "min", &ftMin);
1822 0 : gf_bt_parse_float(parser, "max", &ftMax);
1823 : if (!gf_bt_check_code(parser, '}')) {
1824 0 : gf_bt_report(parser, GF_BAD_PARAM, "Invalid proto coding parameter declare");
1825 0 : goto err;
1826 : }
1827 0 : if (gf_sg_vrml_get_sf_type(fType) == GF_SG_VRML_SFINT32) {
1828 : eType = GF_SG_VRML_SFINT32;
1829 : } else {
1830 : eType = GF_SG_VRML_SFFLOAT;
1831 : }
1832 : }
1833 0 : gf_bifs_proto_field_set_aq_info(pfield, QPType, hasMin, eType, &ftMin, &ftMax, nbBits);
1834 : if (!gf_bt_check_code(parser, '}')) {
1835 0 : gf_bt_report(parser, GF_BAD_PARAM, "Invalid proto coding parameter declare");
1836 0 : goto err;
1837 : }
1838 : }
1839 : }
1840 92 : parser->is_extern_proto_field = 0;
1841 :
1842 92 : if (externProto) {
1843 : SFURL *url;
1844 : Bool has_urls = 0;
1845 : if (gf_bt_check_code(parser, '[')) has_urls = 1;
1846 :
1847 35 : gf_sg_vrml_mf_reset(&proto->ExternProto, GF_SG_VRML_MFURL);
1848 : do {
1849 35 : str = gf_bt_get_next(parser, 0);
1850 35 : gf_sg_vrml_mf_append(&proto->ExternProto, GF_SG_VRML_MFURL, (void **) &url);
1851 35 : if (!strnicmp(str, "od:", 3)) {
1852 3 : sscanf(str, "od:%u", &url->OD_ID);
1853 : } else {
1854 32 : if (!sscanf(str, "%u", &url->OD_ID)) {
1855 32 : url->url = gf_strdup(str);
1856 : } else {
1857 : char szURL[20];
1858 0 : sprintf(szURL, "%d", url->OD_ID);
1859 0 : if (strcmp(szURL, str)) {
1860 0 : url->OD_ID = 0;
1861 0 : url->url = gf_strdup(str);
1862 : }
1863 : }
1864 : }
1865 35 : if (has_urls) {
1866 : gf_bt_check_code(parser, ',');
1867 : if (gf_bt_check_code(parser, ']')) has_urls = 0;
1868 : }
1869 18 : } while (has_urls);
1870 : return GF_OK;
1871 : }
1872 :
1873 : /*parse proto code */
1874 : if (!gf_bt_check_code(parser, '{')) {
1875 0 : gf_bt_report(parser, GF_OK, "empty proto body");
1876 0 : return GF_OK;
1877 : }
1878 :
1879 57 : prevproto = parser->parsing_proto;
1880 57 : sg = parser->load->scene_graph;
1881 57 : parser->parsing_proto = proto;
1882 57 : parser->load->scene_graph = gf_sg_proto_get_graph(proto);
1883 :
1884 : isDEF = 0;
1885 57 : while (!gf_bt_check_code(parser, '}')) {
1886 192 : str = gf_bt_get_next(parser, 0);
1887 383 : if (!strcmp(str, "PROTO") || !strcmp(str, "EXTERNPROTO")) {
1888 1 : gf_bt_parse_proto(parser, str, NULL);
1889 191 : } else if (!strcmp(str, "DEF")) {
1890 : isDEF = 1;
1891 60 : str = gf_bt_get_next(parser, 0);
1892 : strcpy(szDefName, str);
1893 131 : } else if (!strcmp(str, "ROUTE")) {
1894 31 : GF_Route *r = gf_bt_parse_route(parser, 1, 0, NULL);
1895 31 : if (isDEF) {
1896 2 : u32 rID = gf_bt_get_route(parser, szDefName);
1897 2 : if (!rID) rID = gf_bt_get_next_route_id(parser);
1898 2 : parser->last_error = gf_sg_route_set_id(r, rID);
1899 2 : gf_sg_route_set_name(r, szDefName);
1900 : isDEF = 0;
1901 : }
1902 : } else {
1903 100 : GF_Node *n = gf_bt_sf_node(parser, str, NULL, isDEF ? szDefName : NULL);
1904 : isDEF = 0;
1905 100 : if (!n) goto err;
1906 : if ((0) && isDEF) {
1907 : u32 ID = gf_bt_get_def_id(parser, szDefName);
1908 : isDEF = 0;
1909 : gf_node_set_id(n, ID, szDefName);
1910 : }
1911 100 : gf_sg_proto_add_node_code(proto, n);
1912 : }
1913 : }
1914 57 : gf_bt_resolve_routes(parser, 1);
1915 57 : gf_bt_check_unresolved_nodes(parser);
1916 57 : parser->load->scene_graph = sg;
1917 57 : parser->parsing_proto = prevproto;
1918 57 : return parser->last_error;
1919 :
1920 0 : err:
1921 0 : if (proto_list) gf_list_del_item(proto_list, proto);
1922 0 : gf_sg_proto_del(proto);
1923 0 : return parser->last_error;
1924 : }
1925 :
1926 :
1927 1428 : GF_Route *gf_bt_parse_route(GF_BTParser *parser, Bool skip_def, Bool is_insert, GF_Command *com)
1928 : {
1929 : GF_Route *r;
1930 : char *str, nstr[1000], rName[1000];
1931 : u32 rID;
1932 : GF_Node *orig, *dest;
1933 : GF_FieldInfo orig_field, dest_field;
1934 : GF_Err e;
1935 :
1936 : rID = 0;
1937 1428 : strcpy(nstr, gf_bt_get_next(parser, 1));
1938 1428 : if (!skip_def && !strcmp(nstr, "DEF")) {
1939 23 : str = gf_bt_get_next(parser, 0);
1940 : strcpy(rName, str);
1941 23 : rID = gf_bt_get_route(parser, rName);
1942 23 : if (!rID && (str[0]=='R') ) {
1943 18 : rID = atoi(&str[1]);
1944 9 : if (rID) {
1945 8 : rID++;
1946 8 : if (gf_bt_route_id_used(parser, rID)) rID = 0;
1947 : }
1948 : }
1949 23 : if (!rID) rID = gf_bt_get_next_route_id(parser);
1950 23 : strcpy(nstr, gf_bt_get_next(parser, 1));
1951 : }
1952 1428 : orig = gf_bt_peek_node(parser, nstr);
1953 1428 : if (!orig) {
1954 0 : gf_bt_report(parser, GF_BAD_PARAM, "cannot find node %s", nstr);
1955 0 : return NULL;
1956 : }
1957 : if (!gf_bt_check_code(parser, '.')) {
1958 0 : gf_bt_report(parser, GF_BAD_PARAM, ". expected in route decl");
1959 0 : return NULL;
1960 : }
1961 1428 : str = gf_bt_get_next(parser, 0);
1962 1428 : e = gf_node_get_field_by_name(orig, str, &orig_field);
1963 : /*VRML loosy syntax*/
1964 1428 : if ((e != GF_OK) && parser->is_wrl && !strnicmp(str, "set_", 4))
1965 0 : e = gf_node_get_field_by_name(orig, &str[4], &orig_field);
1966 :
1967 1428 : if ((e != GF_OK) && parser->is_wrl && strstr(str, "_changed")) {
1968 : char *s = strstr(str, "_changed");
1969 0 : s[0] = 0;
1970 0 : e = gf_node_get_field_by_name(orig, str, &orig_field);
1971 : }
1972 :
1973 1428 : if (e != GF_OK) {
1974 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s not a field of node %s (%s)", str, gf_node_get_name(orig), gf_node_get_class_name(orig));
1975 0 : return NULL;
1976 : }
1977 1428 : str = gf_bt_get_next(parser, 0);
1978 1428 : if (strcmp(str, "TO")) {
1979 0 : gf_bt_report(parser, GF_BAD_PARAM, "TO expected in route declaration - got \"%s\"", str);
1980 0 : return NULL;
1981 : }
1982 :
1983 1428 : strcpy(nstr, gf_bt_get_next(parser, 1));
1984 1428 : dest = gf_bt_peek_node(parser, nstr);
1985 1428 : if (!dest) {
1986 0 : gf_bt_report(parser, GF_BAD_PARAM, "cannot find node %s", nstr);
1987 0 : return NULL;
1988 : }
1989 : if (!gf_bt_check_code(parser, '.')) {
1990 0 : gf_bt_report(parser, GF_BAD_PARAM, ". expected in route decl");
1991 0 : return NULL;
1992 : }
1993 1428 : str = gf_bt_get_next(parser, 0);
1994 1428 : e = gf_node_get_field_by_name(dest, str, &dest_field);
1995 : /*VRML loosy syntax*/
1996 1428 : if ((e != GF_OK) && parser->is_wrl && !strnicmp(str, "set_", 4))
1997 0 : e = gf_node_get_field_by_name(dest, &str[4], &dest_field);
1998 :
1999 1428 : if ((e != GF_OK) && parser->is_wrl && strstr(str, "_changed")) {
2000 : char *s = strstr(str, "_changed");
2001 0 : s[0] = 0;
2002 0 : e = gf_node_get_field_by_name(dest, str, &dest_field);
2003 : }
2004 :
2005 1428 : if (e != GF_OK) {
2006 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s not a field of node %s (%s)", str, gf_node_get_name(dest), gf_node_get_class_name(dest));
2007 0 : return NULL;
2008 : }
2009 1428 : if (com) {
2010 1377 : com->fromNodeID = gf_node_get_id(orig);
2011 1377 : com->fromFieldIndex = orig_field.fieldIndex;
2012 1377 : com->toNodeID = gf_node_get_id(dest);
2013 1377 : com->toFieldIndex = dest_field.fieldIndex;
2014 1377 : if (rID) {
2015 23 : com->RouteID = rID;
2016 23 : com->def_name = gf_strdup(rName);
2017 : /*whenever inserting routes, keep track of max defined ID*/
2018 23 : if (is_insert) {
2019 23 : gf_sg_set_max_defined_route_id(parser->load->scene_graph, rID);
2020 23 : if (parser->load->ctx && (rID>parser->load->ctx->max_route_id))
2021 8 : parser->load->ctx->max_route_id = rID;
2022 : }
2023 : }
2024 : return NULL;
2025 : }
2026 51 : r = gf_sg_route_new(parser->load->scene_graph, orig, orig_field.fieldIndex, dest, dest_field.fieldIndex);
2027 51 : if (r && rID) {
2028 0 : gf_sg_route_set_id(r, rID);
2029 0 : gf_sg_route_set_name(r, rName);
2030 : }
2031 : return r;
2032 : }
2033 :
2034 960 : void gf_bt_resolve_routes(GF_BTParser *parser, Bool clean)
2035 : {
2036 : /*resolve all commands*/
2037 1941 : while(gf_list_count(parser->unresolved_routes) ) {
2038 21 : GF_Command *com = (GF_Command *)gf_list_get(parser->unresolved_routes, 0);
2039 21 : gf_list_rem(parser->unresolved_routes, 0);
2040 21 : switch (com->tag) {
2041 21 : case GF_SG_ROUTE_DELETE:
2042 : case GF_SG_ROUTE_REPLACE:
2043 21 : com->RouteID = gf_bt_get_route(parser, com->unres_name);
2044 21 : if (!com->RouteID) gf_bt_report(parser, GF_BAD_PARAM, "Cannot resolve Route %s", com->unres_name);
2045 21 : gf_free(com->unres_name);
2046 21 : com->unres_name = NULL;
2047 21 : com->unresolved = 0;
2048 21 : break;
2049 : }
2050 : }
2051 :
2052 960 : if (!clean) return;
2053 71 : while (gf_list_count(parser->inserted_routes)) gf_list_rem(parser->inserted_routes, 0);
2054 : }
2055 :
2056 :
2057 : static void bd_set_com_node(GF_Command *com, GF_Node *node)
2058 : {
2059 1045 : com->node = node;
2060 1045 : gf_node_register(com->node, NULL);
2061 : }
2062 :
2063 1211 : GF_Err gf_bt_parse_bifs_command(GF_BTParser *parser, char *name, GF_List *cmdList)
2064 : {
2065 : s32 pos;
2066 : GF_Route *r;
2067 : GF_Node *n, *newnode;
2068 : GF_Command *com;
2069 : GF_CommandField *inf;
2070 : GF_FieldInfo info;
2071 : char *str, field[1000];
2072 1211 : if (!name) {
2073 736 : str = gf_bt_get_next(parser, 0);
2074 : } else {
2075 : str = name;
2076 : }
2077 : com = NULL;
2078 1211 : pos = -2;
2079 : /*REPLACE commands*/
2080 1211 : if (!strcmp(str, "REPLACE")) {
2081 919 : str = gf_bt_get_next(parser, 1);
2082 919 : if (!strcmp(str, "ROUTE")) {
2083 20 : str = gf_bt_get_next(parser, 0);
2084 20 : r = gf_sg_route_find_by_name(parser->load->scene_graph, str);
2085 20 : if (!r) strcpy(field, str);
2086 20 : str = gf_bt_get_next(parser, 0);
2087 20 : if (strcmp(str, "BY")) {
2088 0 : return gf_bt_report(parser, GF_BAD_PARAM, "BY expected got %s", str);
2089 : }
2090 20 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_ROUTE_REPLACE);
2091 20 : if (r) {
2092 2 : com->RouteID = r->ID;
2093 : } else {
2094 18 : com->unres_name = gf_strdup(field);
2095 18 : com->unresolved = 1;
2096 18 : gf_list_add(parser->unresolved_routes, com);
2097 : }
2098 20 : gf_bt_parse_route(parser, 1, 0, com);
2099 20 : gf_list_add(cmdList, com);
2100 20 : return parser->last_error;
2101 : }
2102 : /*scene replace*/
2103 899 : if (!strcmp(str, "SCENE")) {
2104 32 : str = gf_bt_get_next(parser, 0);
2105 32 : if (strcmp(str, "BY")) {
2106 0 : return gf_bt_report(parser, GF_BAD_PARAM, "BY expected got %s", str);
2107 : }
2108 32 : gf_bt_resolve_routes(parser, 1);
2109 32 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_SCENE_REPLACE);
2110 32 : while (gf_list_count(parser->def_nodes)) gf_list_rem(parser->def_nodes, 0);
2111 :
2112 : while (1) {
2113 52 : str = gf_bt_get_next(parser, 0);
2114 52 : if (!strcmp(str, "PROTO") || !strcmp(str, "EXTERNPROTO")) {
2115 20 : gf_bt_parse_proto(parser, str, com->new_proto_list);
2116 20 : if (parser->last_error) goto err;
2117 : } else {
2118 : break;
2119 : }
2120 : }
2121 32 : n = gf_bt_sf_node(parser, str, NULL, NULL);
2122 32 : com->node = n;
2123 :
2124 32 : if (parser->last_error) goto err;
2125 32 : gf_list_add(cmdList, com);
2126 32 : parser->cur_com = com;
2127 32 : return GF_OK;
2128 : }
2129 867 : if (!strcmp(str, "LAST")) pos = -1;
2130 867 : else if (!strcmp(str, "BEGIN")) pos = 0;
2131 :
2132 : gf_bt_check_code(parser, '.');
2133 : strcpy(field, str);
2134 867 : n = gf_bt_peek_node(parser, str);
2135 867 : if (!n) return gf_bt_report(parser, GF_BAD_PARAM, "%s: unknown node", field);
2136 :
2137 865 : str = gf_bt_get_next(parser, 0);
2138 : strcpy(field, str);
2139 : if (gf_bt_check_code(parser, '[')) {
2140 53 : if ( (parser->last_error = gf_bt_parse_int(parser, "index", &pos)) ) return parser->last_error;
2141 : if (!gf_bt_check_code(parser, ']'))
2142 0 : return gf_bt_report(parser, GF_BAD_PARAM, "] expected");
2143 : }
2144 : /*node replace*/
2145 865 : if (!strcmp(field, "BY")) {
2146 51 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_NODE_REPLACE);
2147 : bd_set_com_node(com, n);
2148 51 : inf = gf_sg_command_field_new(com);
2149 51 : inf->new_node = gf_bt_sf_node(parser, NULL, NULL, NULL);
2150 51 : inf->fieldType = GF_SG_VRML_SFNODE;
2151 51 : inf->field_ptr = &inf->new_node;
2152 51 : gf_list_add(cmdList, com);
2153 51 : parser->cur_com = com;
2154 51 : return parser->last_error;
2155 : }
2156 814 : str = gf_bt_get_next(parser, 0);
2157 814 : if (strcmp(str, "BY"))
2158 0 : return gf_bt_report(parser, GF_BAD_PARAM, "BY expected got %s", str);
2159 :
2160 814 : parser->last_error = gf_node_get_field_by_name(n, field, &info);
2161 814 : if (parser->last_error)
2162 0 : return gf_bt_report(parser, parser->last_error, "%s: Unknown node field", field);
2163 :
2164 : /*field replace*/
2165 814 : if (pos==-2) {
2166 761 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_FIELD_REPLACE);
2167 : bd_set_com_node(com, n);
2168 :
2169 761 : inf = gf_sg_command_field_new(com);
2170 761 : inf->fieldIndex = info.fieldIndex;
2171 761 : inf->fieldType = info.fieldType;
2172 :
2173 761 : switch (info.fieldType) {
2174 6 : case GF_SG_VRML_SFNODE:
2175 6 : newnode = gf_bt_sf_node(parser, NULL, NULL, NULL);
2176 6 : if (!gf_bt_check_ndt(parser, &info, newnode, n)) goto err;
2177 6 : inf->new_node = newnode;
2178 6 : inf->field_ptr = &inf->new_node;
2179 6 : break;
2180 5 : case GF_SG_VRML_MFNODE:
2181 : {
2182 5 : GF_ChildNodeItem *last = NULL;
2183 : if (!gf_bt_check_code(parser, '[')) break;
2184 5 : inf->field_ptr = &inf->node_list;
2185 5 : while (!gf_bt_check_code(parser, ']')) {
2186 5 : newnode = gf_bt_sf_node(parser, NULL, NULL, NULL);
2187 5 : if (!newnode) goto err;
2188 5 : if (parser->last_error!=GF_OK) goto err;
2189 5 : if (!gf_bt_check_ndt(parser, &info, newnode, n)) goto err;
2190 5 : gf_node_list_add_child_last(& inf->node_list, newnode, &last);
2191 : }
2192 : }
2193 5 : break;
2194 750 : default:
2195 750 : inf->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
2196 750 : info.far_ptr = inf->field_ptr;
2197 750 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2198 684 : gf_bt_sffield(parser, &info, n);
2199 : } else {
2200 66 : gf_bt_mffield(parser, &info, n);
2201 : }
2202 750 : if (parser->last_error) goto err;
2203 : break;
2204 : }
2205 :
2206 761 : gf_list_add(cmdList, com);
2207 761 : parser->cur_com = com;
2208 761 : return parser->last_error;
2209 : }
2210 : /*indexed field replace*/
2211 53 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_INDEXED_REPLACE);
2212 : bd_set_com_node(com, n);
2213 53 : inf = gf_sg_command_field_new(com);
2214 53 : inf->pos = pos;
2215 53 : inf->fieldIndex = info.fieldIndex;
2216 53 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2217 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: MF type field expected", info.name);
2218 0 : goto err;
2219 : }
2220 53 : inf->fieldType = gf_sg_vrml_get_sf_type(info.fieldType);
2221 53 : switch (info.fieldType) {
2222 25 : case GF_SG_VRML_MFNODE:
2223 25 : newnode = gf_bt_sf_node(parser, NULL, NULL, NULL);
2224 25 : if (!gf_bt_check_ndt(parser, &info, newnode, n)) goto err;
2225 25 : inf->new_node = newnode;
2226 25 : inf->field_ptr = &inf->new_node;
2227 25 : break;
2228 28 : default:
2229 28 : info.fieldType = inf->fieldType;
2230 28 : info.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
2231 28 : gf_bt_sffield(parser, &info, n);
2232 28 : break;
2233 : }
2234 53 : if (parser->last_error) goto err;
2235 53 : gf_list_add(cmdList, com);
2236 53 : parser->cur_com = com;
2237 53 : return parser->last_error;
2238 : }
2239 : /*XREPLACE commands*/
2240 292 : if (!strcmp(str, "XREPLACE")) {
2241 : u32 j;
2242 : Bool force_sf=0;
2243 : char csep;
2244 : GF_Node *targetNode, *idxNode, *childNode, *fromNode;
2245 : GF_FieldInfo targetField, idxField, childField, fromField;
2246 :
2247 : idxNode = childNode = fromNode = NULL;
2248 20 : str = gf_bt_get_next(parser, 1);
2249 : /*get source node*/
2250 : strcpy(field, str);
2251 20 : targetNode = gf_bt_peek_node(parser, str);
2252 40 : if (!targetNode) return gf_bt_report(parser, GF_BAD_PARAM, "%s: unknown node", field);
2253 : if (!gf_bt_check_code(parser, '.')) {
2254 0 : return gf_bt_report(parser, GF_BAD_PARAM, "XREPLACE: '.' expected");
2255 : }
2256 : /*get source field*/
2257 20 : str = gf_bt_get_next(parser, 0);
2258 : strcpy(field, str);
2259 20 : parser->last_error = gf_node_get_field_by_name(targetNode, field, &targetField);
2260 20 : if (parser->last_error)
2261 0 : return gf_bt_report(parser, parser->last_error, "%s: Unknown node field", field);
2262 :
2263 : if (gf_bt_check_code(parser, '[')) {
2264 10 : pos = -2;
2265 10 : str = gf_bt_get_next(parser, 1);
2266 : force_sf = 1;
2267 10 : if (sscanf(str, "%d", &pos) != 1) {
2268 10 : pos = -2;
2269 10 : if (!strcmp(str, "LAST")) pos = -1;
2270 10 : else if (!strcmp(str, "first")) pos = 0;
2271 : else {
2272 : strcpy(field, str);
2273 : /*get idx node*/
2274 10 : idxNode = gf_bt_peek_node(parser, str);
2275 10 : if (!idxNode) return gf_bt_report(parser, GF_BAD_PARAM, "%s: unknown node", field);
2276 : if (!gf_bt_check_code(parser, '.'))
2277 0 : return gf_bt_report(parser, GF_BAD_PARAM, "XREPLACE: '.' expected");
2278 :
2279 : /*get idx field*/
2280 10 : str = gf_bt_get_next(parser, 0);
2281 : strcpy(field, str);
2282 10 : parser->last_error = gf_node_get_field_by_name(idxNode, field, &idxField);
2283 10 : if (parser->last_error)
2284 0 : return gf_bt_report(parser, parser->last_error, "%s: Unknown node field", field);
2285 : }
2286 : }
2287 : gf_bt_check_code(parser, ']');
2288 :
2289 : /*check if we have a child node*/
2290 : if (gf_bt_check_code(parser, '.')) {
2291 10 : s32 apos = pos;
2292 : force_sf = 0;
2293 10 : if (idxNode) {
2294 : apos = 0;
2295 10 : switch (idxField.fieldType) {
2296 0 : case GF_SG_VRML_SFBOOL:
2297 0 : if (*(SFBool*)idxField.far_ptr) apos = 1;
2298 : break;
2299 10 : case GF_SG_VRML_SFINT32:
2300 10 : if (*(SFInt32*)idxField.far_ptr >=0) apos = *(SFInt32*)idxField.far_ptr;
2301 : break;
2302 0 : case GF_SG_VRML_SFFLOAT:
2303 0 : if ( (*(SFFloat *)idxField.far_ptr) >=0) apos = (s32) floor( FIX2FLT(*(SFFloat*)idxField.far_ptr) );
2304 : break;
2305 0 : case GF_SG_VRML_SFTIME:
2306 0 : if ( (*(SFTime *)idxField.far_ptr) >=0) apos = (s32) floor( (*(SFTime *)idxField.far_ptr) );
2307 : break;
2308 : }
2309 : }
2310 10 : childNode = gf_node_list_get_child(*(GF_ChildNodeItem **)targetField.far_ptr, apos);
2311 10 : if (!childNode)
2312 0 : return gf_bt_report(parser, GF_BAD_PARAM, "Cannot find child node at specified index");
2313 :
2314 10 : str = gf_bt_get_next(parser, 0);
2315 : strcpy(field, str);
2316 10 : parser->last_error = gf_node_get_field_by_name(childNode, field, &childField);
2317 10 : if (parser->last_error)
2318 0 : return gf_bt_report(parser, parser->last_error, "%s: Unknown node field", field);
2319 : }
2320 : }
2321 :
2322 20 : str = gf_bt_get_next(parser, 0);
2323 20 : if (strcmp(str, "BY"))
2324 0 : return gf_bt_report(parser, GF_BAD_PARAM, "BY expected got %s", str);
2325 :
2326 : /*peek the next word*/
2327 : j = 0;
2328 20 : while (strchr(" \n\t\0", parser->line_buffer[parser->line_pos + j])) j++;
2329 20 : str = parser->line_buffer + parser->line_pos + j;
2330 : j = 0;
2331 20 : while (!strchr(" .\0", str[j])) j++;
2332 : csep = str[j];
2333 20 : str[j]=0;
2334 : strcpy(field, str);
2335 20 : str[j] = csep;
2336 20 : fromNode = gf_bt_peek_node(parser, field);
2337 20 : if (fromNode) {
2338 10 : gf_bt_get_next(parser, 1);
2339 :
2340 : if (!gf_bt_check_code(parser, '.')) {
2341 0 : return gf_bt_report(parser, GF_BAD_PARAM, "XREPLACE: '.' expected");
2342 : }
2343 : /*get source field*/
2344 10 : str = gf_bt_get_next(parser, 0);
2345 : strcpy(field, str);
2346 10 : parser->last_error = gf_node_get_field_by_name(fromNode, field, &fromField);
2347 10 : if (parser->last_error)
2348 0 : return gf_bt_report(parser, parser->last_error, "%s: Unknown node field", field);
2349 :
2350 : } else {
2351 : /*regular parsing*/
2352 : }
2353 :
2354 20 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_XREPLACE);
2355 : bd_set_com_node(com, targetNode);
2356 20 : if (fromNode) {
2357 10 : com->fromNodeID = gf_node_get_id(fromNode);
2358 10 : com->fromFieldIndex = fromField.fieldIndex;
2359 : }
2360 20 : if (idxNode) {
2361 10 : com->toNodeID = gf_node_get_id(idxNode);
2362 10 : com->toFieldIndex = idxField.fieldIndex;
2363 : }
2364 20 : if (childNode) {
2365 10 : com->ChildNodeTag = gf_node_get_tag(childNode);
2366 10 : if (com->ChildNodeTag==1) {
2367 0 : com->ChildNodeTag = ((GF_ProtoInstance*)childNode)->proto_interface->ID;
2368 0 : com->ChildNodeTag = -com->ChildNodeTag ;
2369 : }
2370 10 : com->child_field = childField.fieldIndex;
2371 : }
2372 20 : inf = gf_sg_command_field_new(com);
2373 20 : inf->fieldIndex = targetField.fieldIndex;
2374 20 : inf->pos = pos;
2375 20 : if (force_sf) {
2376 0 : inf->fieldType = gf_sg_vrml_get_sf_type(targetField.fieldType);
2377 20 : } else if (childNode) {
2378 10 : inf->fieldType = childField.fieldType;
2379 : } else {
2380 10 : inf->fieldType = targetField.fieldType;
2381 : }
2382 20 : if (!fromNode) {
2383 10 : switch (inf->fieldType) {
2384 0 : case GF_SG_VRML_SFNODE:
2385 0 : inf->new_node = gf_bt_sf_node(parser, NULL, NULL, NULL);
2386 0 : inf->field_ptr = &inf->new_node;
2387 0 : if (childNode) {
2388 0 : if (!gf_bt_check_ndt(parser, &childField, inf->new_node, childNode)) goto err;
2389 : } else {
2390 0 : if (!gf_bt_check_ndt(parser, &targetField, inf->new_node, targetNode)) goto err;
2391 : }
2392 : break;
2393 0 : case GF_SG_VRML_MFNODE:
2394 : {
2395 0 : GF_ChildNodeItem *last = NULL;
2396 : if (!gf_bt_check_code(parser, '[')) break;
2397 0 : inf->field_ptr = &inf->node_list;
2398 0 : while (!gf_bt_check_code(parser, ']')) {
2399 0 : newnode = gf_bt_sf_node(parser, NULL, NULL, NULL);
2400 0 : if (!newnode) goto err;
2401 0 : if (parser->last_error!=GF_OK) goto err;
2402 :
2403 0 : if (childNode) {
2404 0 : if (!gf_bt_check_ndt(parser, &childField, inf->new_node, childNode)) goto err;
2405 : } else {
2406 0 : if (!gf_bt_check_ndt(parser, &targetField, inf->new_node, targetNode)) goto err;
2407 : }
2408 :
2409 0 : gf_node_list_add_child_last(& inf->node_list, newnode, &last);
2410 : }
2411 : }
2412 0 : break;
2413 10 : default:
2414 10 : inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
2415 10 : info.far_ptr = inf->field_ptr;
2416 10 : info.fieldType = inf->fieldType;
2417 10 : info.name = targetField.name;
2418 :
2419 10 : if (gf_sg_vrml_is_sf_field(inf->fieldType)) {
2420 10 : gf_bt_sffield(parser, &info, childNode ? childNode : targetNode);
2421 : } else {
2422 0 : gf_bt_mffield(parser, &info, childNode ? childNode : targetNode);
2423 : }
2424 10 : if (parser->last_error) goto err;
2425 : break;
2426 : }
2427 10 : }
2428 :
2429 20 : if (parser->last_error) goto err;
2430 20 : gf_list_add(cmdList, com);
2431 20 : parser->cur_com = com;
2432 20 : return parser->last_error;
2433 : }
2434 :
2435 :
2436 : /*INSERT commands*/
2437 272 : if (!strcmp(str, "INSERT") || !strcmp(str, "APPEND")) {
2438 122 : Bool is_append = !strcmp(str, "APPEND") ? 1 : 0;
2439 122 : str = gf_bt_get_next(parser, 0);
2440 122 : if (!strcmp(str, "ROUTE")) {
2441 37 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_ROUTE_INSERT);
2442 37 : gf_bt_parse_route(parser, 0, 1, com);
2443 37 : if (parser->last_error) goto err;
2444 37 : gf_list_add(cmdList, com);
2445 37 : gf_list_add(parser->inserted_routes, com);
2446 37 : parser->cur_com = com;
2447 37 : return GF_OK;
2448 : }
2449 85 : if (strcmp(str, "AT") && strcmp(str, "TO")) {
2450 0 : return gf_bt_report(parser, GF_BAD_PARAM, (char*) (is_append ? "TO expected got %s" : "AT expected got %s"), str);
2451 : }
2452 85 : str = gf_bt_get_next(parser, 1);
2453 : strcpy(field, str);
2454 85 : n = gf_bt_peek_node(parser, str);
2455 85 : if (!n) {
2456 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown node", field);
2457 : }
2458 : if (!gf_bt_check_code(parser, '.')) {
2459 0 : return gf_bt_report(parser, GF_BAD_PARAM, ". expected");
2460 : }
2461 85 : str = gf_bt_get_next(parser, 1);
2462 : strcpy(field, str);
2463 85 : if (!is_append) {
2464 : if (!gf_bt_check_code(parser, '[')) {
2465 0 : return gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
2466 : }
2467 30 : gf_bt_parse_int(parser, "index", &pos);
2468 : if (!gf_bt_check_code(parser, ']')) {
2469 0 : return gf_bt_report(parser, GF_BAD_PARAM, "] expected");
2470 : }
2471 : } else {
2472 : if (gf_bt_check_code(parser, '[')) {
2473 0 : return gf_bt_report(parser, GF_BAD_PARAM, "[ unexpected in Append command");
2474 : }
2475 55 : pos = -1;
2476 : }
2477 85 : gf_node_get_field_by_name(n, field, &info);
2478 85 : if (!strcmp(field, "children")) {
2479 75 : newnode = gf_bt_sf_node(parser, NULL, NULL, NULL);
2480 75 : if (parser->last_error) goto err;
2481 :
2482 75 : if (!gf_bt_check_ndt(parser, &info, newnode, n)) goto err;
2483 75 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_NODE_INSERT);
2484 : bd_set_com_node(com, n);
2485 75 : inf = gf_sg_command_field_new(com);
2486 75 : inf->pos = pos;
2487 75 : inf->new_node = newnode;
2488 75 : inf->fieldType = GF_SG_VRML_SFNODE;
2489 75 : inf->field_ptr = &inf->new_node;
2490 75 : if (parser->last_error) goto err;
2491 75 : parser->cur_com = com;
2492 75 : return gf_list_add(cmdList, com);
2493 : }
2494 10 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2495 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: MF type field expected", info.name);
2496 : goto err;
2497 : }
2498 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_INDEXED_INSERT);
2499 : bd_set_com_node(com, n);
2500 10 : inf = gf_sg_command_field_new(com);
2501 10 : inf->pos = pos;
2502 10 : inf->fieldIndex = info.fieldIndex;
2503 10 : inf->fieldType = gf_sg_vrml_get_sf_type(info.fieldType);
2504 10 : switch (info.fieldType) {
2505 0 : case GF_SG_VRML_MFNODE:
2506 0 : inf->new_node = gf_bt_sf_node(parser, NULL, NULL, NULL);
2507 0 : inf->field_ptr = &inf->new_node;
2508 0 : break;
2509 10 : default:
2510 10 : info.fieldType = inf->fieldType;
2511 10 : inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
2512 10 : info.far_ptr = inf->field_ptr;
2513 10 : gf_bt_sffield(parser, &info, n);
2514 10 : break;
2515 : }
2516 10 : if (parser->last_error) goto err;
2517 10 : gf_list_add(cmdList, com);
2518 10 : parser->cur_com = com;
2519 10 : return parser->last_error;
2520 : }
2521 : /*DELETE commands*/
2522 150 : if (!strcmp(str, "DELETE")) {
2523 75 : str = gf_bt_get_next(parser, 1);
2524 75 : if (!strcmp(str, "ROUTE")) {
2525 35 : str = gf_bt_get_next(parser, 0);
2526 35 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_ROUTE_DELETE);
2527 35 : com->RouteID = gf_bt_get_route(parser, str);
2528 35 : if (!com->RouteID) {
2529 3 : com->unres_name = gf_strdup(str);
2530 3 : com->unresolved = 1;
2531 3 : gf_list_add(parser->unresolved_routes, com);
2532 : }
2533 : /*for bt<->xmt conversions*/
2534 35 : com->def_name = gf_strdup(str);
2535 35 : return gf_list_add(cmdList, com);
2536 : }
2537 : strcpy(field, str);
2538 40 : n = gf_bt_peek_node(parser, str);
2539 40 : if (!n) {
2540 0 : return gf_bt_report(parser, GF_BAD_PARAM, "DELETE %s: Unknown Node", field);
2541 : }
2542 : if (!gf_bt_check_code(parser, '.')) {
2543 25 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_NODE_DELETE);
2544 : bd_set_com_node(com, n);
2545 25 : return gf_list_add(cmdList, com);
2546 : }
2547 15 : str = gf_bt_get_next(parser, 0);
2548 15 : if (gf_node_get_field_by_name(n, str, &info) != GF_OK) {
2549 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s not a field of node %s", str, gf_node_get_class_name(n) );
2550 : }
2551 : if (gf_bt_check_code(parser, '[')) {
2552 10 : gf_bt_parse_int(parser, "index", &pos);
2553 : if (!gf_bt_check_code(parser, ']'))
2554 0 : return gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
2555 : }
2556 15 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2557 5 : if (info.fieldType == GF_SG_VRML_SFNODE) {
2558 5 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_FIELD_REPLACE);
2559 : bd_set_com_node(com, n);
2560 5 : inf = gf_sg_command_field_new(com);
2561 5 : inf->fieldIndex = info.fieldIndex;
2562 5 : inf->fieldType = info.fieldType;
2563 5 : inf->new_node = NULL;
2564 5 : inf->field_ptr = &inf->new_node;
2565 5 : return gf_list_add(cmdList, com);
2566 : }
2567 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s is an SFField - cannot indexed delete", info.name);
2568 : }
2569 :
2570 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_INDEXED_DELETE);
2571 : bd_set_com_node(com, n);
2572 10 : inf = gf_sg_command_field_new(com);
2573 10 : inf->fieldIndex = info.fieldIndex;
2574 10 : inf->fieldType = info.fieldType;
2575 10 : inf->pos = pos;
2576 10 : return gf_list_add(cmdList, com);
2577 : }
2578 : /*Extended BIFS commands*/
2579 :
2580 : /*GlobalQP commands*/
2581 75 : if (!strcmp(str, "GLOBALQP")) {
2582 10 : newnode = gf_bt_sf_node(parser, NULL, NULL, NULL);
2583 10 : if (newnode && (newnode->sgprivate->tag != TAG_MPEG4_QuantizationParameter)) {
2584 0 : gf_bt_report(parser, GF_BAD_PARAM, "Only QuantizationParameter node allowed in GLOBALQP");
2585 0 : gf_node_unregister(newnode, NULL);
2586 0 : return parser->last_error;
2587 : }
2588 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_GLOBAL_QUANTIZER);
2589 10 : com->node = NULL;
2590 10 : inf = gf_sg_command_field_new(com);
2591 10 : inf->new_node = newnode;
2592 10 : inf->field_ptr = &inf->new_node;
2593 10 : inf->fieldType = GF_SG_VRML_SFNODE;
2594 10 : return gf_list_add(cmdList, com);
2595 : }
2596 :
2597 : /*MultipleReplace commands*/
2598 65 : if (!strcmp(str, "MULTIPLEREPLACE")) {
2599 15 : str = gf_bt_get_next(parser, 0);
2600 : strcpy(field, str);
2601 15 : n = gf_bt_peek_node(parser, str);
2602 15 : if (!n) {
2603 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown node", field);
2604 : }
2605 : if (!gf_bt_check_code(parser, '{')) {
2606 0 : return gf_bt_report(parser, GF_BAD_PARAM, "{ expected");
2607 : }
2608 15 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_MULTIPLE_REPLACE);
2609 : bd_set_com_node(com, n);
2610 :
2611 : while (!gf_bt_check_code(parser, '}')) {
2612 35 : str = gf_bt_get_next(parser, 0);
2613 35 : parser->last_error = gf_node_get_field_by_name(n, str, &info);
2614 35 : if (parser->last_error) {
2615 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown node field", str);
2616 0 : goto err;
2617 : }
2618 35 : inf = gf_sg_command_field_new(com);
2619 35 : inf->fieldIndex = info.fieldIndex;
2620 35 : inf->fieldType = info.fieldType;
2621 35 : inf->pos = -1;
2622 :
2623 35 : switch (info.fieldType) {
2624 10 : case GF_SG_VRML_SFNODE:
2625 10 : inf->new_node = gf_bt_sf_node(parser, NULL, NULL, NULL);
2626 10 : if (parser->last_error) goto err;
2627 10 : if (!gf_bt_check_ndt(parser, &info, inf->new_node, n)) goto err;
2628 10 : inf->field_ptr = &inf->new_node;
2629 10 : break;
2630 5 : case GF_SG_VRML_MFNODE:
2631 : {
2632 5 : GF_ChildNodeItem *last = NULL;
2633 : if (!gf_bt_check_code(parser, '[')) {
2634 0 : gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
2635 0 : goto err;
2636 : }
2637 5 : info.far_ptr = inf->field_ptr = &inf->node_list;
2638 5 : while (!gf_bt_check_code(parser, ']')) {
2639 5 : newnode = gf_bt_sf_node(parser, NULL, NULL, NULL);
2640 5 : if (parser->last_error!=GF_OK) goto err;
2641 5 : if (!gf_bt_check_ndt(parser, &info, newnode, n)) goto err;
2642 5 : gf_node_list_add_child_last( & inf->node_list, newnode, &last);
2643 : }
2644 : }
2645 5 : break;
2646 20 : default:
2647 20 : info.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
2648 20 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2649 20 : gf_bt_sffield(parser, &info, n);
2650 : } else {
2651 0 : gf_bt_mffield(parser, &info, n);
2652 : }
2653 20 : if (parser->last_error) goto err;
2654 : break;
2655 : }
2656 : }
2657 15 : parser->cur_com = com;
2658 15 : return gf_list_add(cmdList, com);
2659 : }
2660 :
2661 : /*MultipleIndexReplace commands*/
2662 50 : if (!strcmp(str, "MULTIPLEINDREPLACE")) {
2663 10 : str = gf_bt_get_next(parser, 1);
2664 : strcpy(field, str);
2665 10 : n = gf_bt_peek_node(parser, str);
2666 10 : if (!n) {
2667 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown node", field);
2668 : }
2669 : if (!gf_bt_check_code(parser, '.')) {
2670 0 : return gf_bt_report(parser, GF_BAD_PARAM, ". expected");
2671 : }
2672 10 : str = gf_bt_get_next(parser, 0);
2673 10 : parser->last_error = gf_node_get_field_by_name(n, str, &info);
2674 10 : if (parser->last_error) {
2675 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown field", info.name);
2676 : }
2677 10 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2678 0 : return gf_bt_report(parser, GF_BAD_PARAM, "Only MF field allowed");
2679 : }
2680 : if (!gf_bt_check_code(parser, '[')) {
2681 0 : return gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
2682 : }
2683 :
2684 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_MULTIPLE_INDEXED_REPLACE);
2685 : bd_set_com_node(com, n);
2686 10 : info.fieldType = gf_sg_vrml_get_sf_type(info.fieldType);
2687 :
2688 10 : while (!gf_bt_check_code(parser, ']')) {
2689 30 : pos=0;
2690 30 : if (gf_bt_parse_int(parser, "position", (SFInt32 *)&pos)) goto err;
2691 30 : str = gf_bt_get_next(parser, 0);
2692 30 : if (strcmp(str, "BY")) {
2693 0 : gf_bt_report(parser, GF_BAD_PARAM, "BY expected");
2694 0 : goto err;
2695 : }
2696 30 : inf = gf_sg_command_field_new(com);
2697 30 : inf->fieldIndex = info.fieldIndex;
2698 30 : inf->fieldType = info.fieldType;
2699 30 : inf->pos = pos;
2700 30 : if (inf->fieldType==GF_SG_VRML_SFNODE) {
2701 0 : info.far_ptr = inf->field_ptr = &inf->new_node;
2702 0 : inf->new_node = gf_bt_sf_node(parser, NULL, NULL, NULL);
2703 0 : if (parser->last_error) goto err;
2704 0 : if (!gf_bt_check_ndt(parser, &info, inf->new_node, n)) goto err;
2705 0 : inf->field_ptr = &inf->new_node;
2706 : } else {
2707 30 : info.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
2708 30 : gf_bt_sffield(parser, &info, n);
2709 30 : if (parser->last_error) goto err;
2710 : }
2711 : }
2712 10 : parser->cur_com = com;
2713 10 : return gf_list_add(cmdList, com);
2714 : }
2715 :
2716 40 : if (!strcmp(str, "XDELETE")) {
2717 10 : str = gf_bt_get_next(parser, 1);
2718 : strcpy(field, str);
2719 10 : n = gf_bt_peek_node(parser, str);
2720 10 : if (!n) {
2721 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown Node", field);
2722 : }
2723 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_NODE_DELETE_EX);
2724 : bd_set_com_node(com, n);
2725 10 : return gf_list_add(cmdList, com);
2726 : }
2727 :
2728 30 : if (!strcmp(str, "INSERTPROTO")) {
2729 : if (!gf_bt_check_code(parser, '[')) {
2730 0 : return gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
2731 : }
2732 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_PROTO_INSERT);
2733 10 : while (!gf_bt_check_code(parser, ']')) {
2734 10 : parser->last_error = gf_bt_parse_proto(parser, NULL, com->new_proto_list);
2735 10 : if (parser->last_error) goto err;
2736 : }
2737 10 : gf_list_add(cmdList, com);
2738 10 : return GF_OK;
2739 : }
2740 20 : if (!strcmp(str, "DELETEPROTO")) {
2741 : if (!gf_bt_check_code(parser, '[')) {
2742 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_PROTO_DELETE_ALL);
2743 10 : str = gf_bt_get_next(parser, 0);
2744 10 : if (strcmp(str, "ALL")) {
2745 0 : gf_bt_report(parser, GF_BAD_PARAM, "ALL expected");
2746 0 : goto err;
2747 : }
2748 10 : return gf_list_add(cmdList, com);
2749 : }
2750 10 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_PROTO_DELETE);
2751 10 : while (!gf_bt_check_code(parser, ']')) {
2752 : GF_Proto *proto;
2753 10 : str = gf_bt_get_next(parser, 0);
2754 10 : proto = gf_sg_find_proto(parser->load->scene_graph, 0, str);
2755 10 : if (!proto) {
2756 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown proto", str);
2757 0 : goto err;
2758 : }
2759 10 : com->del_proto_list = (u32*)gf_realloc(com->del_proto_list, sizeof(u32)*(com->del_proto_list_size+1));
2760 10 : com->del_proto_list[com->del_proto_list_size] = proto->ID;
2761 10 : com->del_proto_list_size++;
2762 : }
2763 10 : gf_list_add(cmdList, com);
2764 10 : return GF_OK;
2765 : }
2766 0 : return gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown command syntax, str");
2767 :
2768 0 : err:
2769 0 : if (com) gf_sg_command_del(com);
2770 0 : return parser->last_error;
2771 : }
2772 :
2773 : GF_Descriptor *gf_bt_parse_descriptor(GF_BTParser *parser, char *name);
2774 :
2775 : #ifndef GPAC_MINIMAL_ODF
2776 : GF_IPMPX_Data *gf_bt_parse_ipmpx(GF_BTParser *parser, char *name)
2777 : {
2778 : char *str, field[500];
2779 : GF_IPMPX_Data *desc, *subdesc;
2780 : GF_Descriptor *oddesc;
2781 : GF_Err e;
2782 : u32 type;
2783 : u8 tag;
2784 : if (name) {
2785 : str = name;
2786 : } else {
2787 : str = gf_bt_get_next(parser, 0);
2788 : }
2789 : tag = gf_ipmpx_get_tag(str);
2790 : if (!tag) {
2791 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown IPMPX Data", str);
2792 : return NULL;
2793 : }
2794 : desc = gf_ipmpx_data_new(tag);
2795 :
2796 : if (!desc) return NULL;
2797 : if (!gf_bt_check_code(parser, '{')) return desc;
2798 :
2799 : while (1) {
2800 : /*done*/
2801 : if (gf_bt_check_code(parser, '}')) break;
2802 : str = gf_bt_get_next(parser, 0);
2803 : strcpy(field, str);
2804 : type = gf_ipmpx_get_field_type(desc, str);
2805 : switch (type) {
2806 : /*single descriptor*/
2807 : case GF_ODF_FT_OD:
2808 : assert(desc->tag==GF_IPMPX_CONNECT_TOOL_TAG);
2809 : str = gf_bt_get_next(parser, 0);
2810 : oddesc = gf_bt_parse_descriptor(parser, str);
2811 : if (!oddesc) {
2812 : gf_bt_report(parser, GF_BAD_PARAM, "Unknown desc %s in field %s", str, field);
2813 : gf_ipmpx_data_del(desc);
2814 : return NULL;
2815 : }
2816 : assert(oddesc->tag==GF_ODF_IPMP_TAG);
2817 : ((GF_IPMPX_ConnectTool *)desc)->toolDescriptor = (GF_IPMP_Descriptor *)oddesc;
2818 : break;
2819 : /*descriptor list*/
2820 : case GF_ODF_FT_OD_LIST:
2821 : assert(desc->tag==GF_IPMPX_GET_TOOLS_RESPONSE_TAG);
2822 : if (gf_bt_check_code(parser, '[')) {
2823 : while (!gf_bt_check_code(parser, ']')) {
2824 : GF_Descriptor *ipmp_t = gf_bt_parse_descriptor(parser, NULL);
2825 : if (!ipmp_t) {
2826 : gf_ipmpx_data_del(desc);
2827 : parser->last_error = GF_BAD_PARAM;
2828 : return NULL;
2829 : }
2830 : assert(ipmp_t->tag==GF_ODF_IPMP_TOOL_TAG);
2831 : gf_list_add( ((GF_IPMPX_GetToolsResponse *)desc)->ipmp_tools, ipmp_t);
2832 : }
2833 : }
2834 : break;
2835 :
2836 : /*IPMPX ByteArray list*/
2837 : case GF_ODF_FT_IPMPX_BA_LIST:
2838 : if (gf_bt_check_code(parser, '[')) {
2839 : while (!gf_bt_check_code(parser, ']')) {
2840 : str = gf_bt_get_next(parser, 0);
2841 : if (!str) continue;
2842 : if (gf_ipmpx_set_byte_array(desc, field, str) != GF_OK) {
2843 : gf_bt_report(parser, GF_OK, "Invalid ipmpx %s in field %s - skipping", str, field);
2844 : }
2845 : gf_bt_check_code(parser, ',');
2846 : }
2847 : }
2848 : break;
2849 : /*IPMPX ByteArray: check if declared as sub-data or not*/
2850 : case GF_ODF_FT_IPMPX_BA:
2851 : str = NULL;
2852 : if (gf_bt_check_code(parser, '{')) {
2853 : str = gf_bt_get_next(parser, 0);
2854 : if (stricmp(str, "array")) {
2855 : gf_bt_report(parser, GF_BAD_PARAM, "IPMP ByteArray syntax is %s { array \"...\" } or %s \"....\"\n", field, field);
2856 : gf_ipmpx_data_del(desc);
2857 : return NULL;
2858 : }
2859 : str = gf_bt_get_next(parser, 0);
2860 : gf_bt_check_code(parser, '}');
2861 : } else {
2862 : str = gf_bt_get_next(parser, 0);
2863 : }
2864 : e = gf_ipmpx_set_byte_array(desc, field, str);
2865 : if (e) {
2866 : gf_bt_report(parser, e, "Error assigning IPMP ByteArray %s\n", field);
2867 : gf_ipmpx_data_del(desc);
2868 : return NULL;
2869 : }
2870 : break;
2871 : /*IPMPX Data list*/
2872 : case GF_ODF_FT_IPMPX_LIST:
2873 : if (gf_bt_check_code(parser, '[')) {
2874 : while (!gf_bt_check_code(parser, ']')) {
2875 : subdesc = gf_bt_parse_ipmpx(parser, NULL);
2876 : if (!subdesc) {
2877 : gf_ipmpx_data_del(desc);
2878 : parser->last_error = GF_BAD_PARAM;
2879 : return NULL;
2880 : }
2881 : if (gf_ipmpx_set_sub_data(desc, field, subdesc) != GF_OK) {
2882 : gf_bt_report(parser, GF_BAD_PARAM, "Invalid ipmpx %s in field %s - skipping", str, field);
2883 : gf_ipmpx_data_del(subdesc);
2884 : }
2885 : }
2886 : }
2887 : break;
2888 : /*regular IPMPX Data*/
2889 : case GF_ODF_FT_IPMPX:
2890 : str = gf_bt_get_next(parser, 0);
2891 : subdesc = gf_bt_parse_ipmpx(parser, str);
2892 : if (!subdesc) {
2893 : gf_bt_report(parser, GF_BAD_PARAM, "Unknown ipmpx %s in field %s", str, field);
2894 : gf_ipmpx_data_del(desc);
2895 : return NULL;
2896 : }
2897 : if (gf_ipmpx_set_sub_data(desc, field, subdesc) != GF_OK) {
2898 : gf_bt_report(parser, GF_BAD_PARAM, "Invalid ipmpx in field %s - skipping", field);
2899 : gf_ipmpx_data_del(subdesc);
2900 : }
2901 : break;
2902 : default:
2903 : str = gf_bt_get_next(parser, 0);
2904 : parser->last_error = gf_ipmpx_set_field(desc, field, str);
2905 :
2906 : if (parser->last_error) {
2907 : gf_bt_report(parser, GF_BAD_PARAM, "Invalid value %s in field %s", str, field);
2908 : gf_ipmpx_data_del(desc);
2909 : return NULL;
2910 : }
2911 : break;
2912 : }
2913 : }
2914 : return desc;
2915 : }
2916 : #endif
2917 :
2918 1827 : static void gf_bt_add_desc(GF_BTParser *parser, GF_Descriptor *par, GF_Descriptor *child, char *fieldName)
2919 : {
2920 1827 : GF_Err e = gf_odf_desc_add_desc(par, child);
2921 1827 : if (e) {
2922 0 : gf_bt_report(parser, GF_OK, "Invalid child descriptor in field %s - skipping", fieldName);
2923 0 : gf_odf_desc_del(child);
2924 : }
2925 1827 : }
2926 :
2927 2388 : GF_Descriptor *gf_bt_parse_descriptor(GF_BTParser *parser, char *name)
2928 : {
2929 : char *str, field[500];
2930 : GF_Descriptor *desc, *subdesc;
2931 : u32 type;
2932 : u8 tag;
2933 2388 : if (name) {
2934 : str = name;
2935 : } else {
2936 711 : str = gf_bt_get_next(parser, 0);
2937 : }
2938 2388 : tag = gf_odf_get_tag_by_name(str);
2939 2388 : if (!tag) {
2940 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown descriptor", str);
2941 0 : return NULL;
2942 : }
2943 2388 : desc = gf_odf_desc_new(tag);
2944 :
2945 2388 : if (!desc) return NULL;
2946 : if (!gf_bt_check_code(parser, '{')) return desc;
2947 :
2948 : while (1) {
2949 : Bool is_anim_mask = 0;
2950 : /*done*/
2951 : if (gf_bt_check_code(parser, '}')) break;
2952 7254 : str = gf_bt_get_next(parser, 0);
2953 : strcpy(field, str);
2954 :
2955 7254 : if ((tag==GF_ODF_BIFS_CFG_TAG) && !strcmp(field, "animationMask")) {
2956 0 : gf_bt_get_next(parser, 0);
2957 : if (gf_bt_check_code(parser, '{')) is_anim_mask = 1;
2958 0 : str = gf_bt_get_next(parser, 0);
2959 : strcpy(field, str);
2960 : }
2961 :
2962 7254 : type = gf_odf_get_field_type(desc, str);
2963 7254 : switch (type) {
2964 : #ifndef GPAC_MINIMAL_ODF
2965 : /*IPMPX list*/
2966 : case GF_ODF_FT_IPMPX_LIST:
2967 : if(desc->tag!=GF_ODF_IPMP_TAG) {
2968 : gf_bt_report(parser, GF_BAD_PARAM, "IPMPX_Data list only allowed in GF_IPMP_Descriptor");
2969 : gf_odf_desc_del(desc);
2970 : return NULL;
2971 : }
2972 : if (gf_bt_check_code(parser, '[')) {
2973 : while (!gf_bt_check_code(parser, ']')) {
2974 : GF_IPMPX_Data *ipmpx = gf_bt_parse_ipmpx(parser, NULL);
2975 : if (!ipmpx) {
2976 : gf_odf_desc_del(desc);
2977 : parser->last_error = GF_BAD_PARAM;
2978 : return NULL;
2979 : }
2980 : gf_list_add( ((GF_IPMP_Descriptor *)desc)->ipmpx_data, ipmpx);
2981 : }
2982 : }
2983 : break;
2984 : /*IPMPX*/
2985 : case GF_ODF_FT_IPMPX:
2986 : if(desc->tag!=GF_ODF_IPMP_TOOL_TAG) {
2987 : gf_bt_report(parser, GF_BAD_PARAM, "IPMPX_Data only allowed in GF_IPMP_Tool");
2988 : gf_odf_desc_del(desc);
2989 : return NULL;
2990 : }
2991 : if (gf_bt_check_code(parser, '[')) {
2992 : while (!gf_bt_check_code(parser, ']')) {
2993 : GF_IPMPX_Data *ipmpx = gf_bt_parse_ipmpx(parser, NULL);
2994 : if (!ipmpx) {
2995 : gf_odf_desc_del(desc);
2996 : parser->last_error = GF_BAD_PARAM;
2997 : return NULL;
2998 : }
2999 : if (ipmpx->tag==GF_IPMPX_PARAMETRIC_DESCRIPTION_TAG) {
3000 : GF_IPMP_Tool *it = (GF_IPMP_Tool *)desc;
3001 : if (it->toolParamDesc) gf_ipmpx_data_del((GF_IPMPX_Data *)it->toolParamDesc);
3002 : it->toolParamDesc = (GF_IPMPX_ParametricDescription*)ipmpx;
3003 : } else {
3004 : gf_bt_report(parser, GF_OK, "Only ToolParametricDescription allowed in GF_IPMP_Tool - skipping");
3005 : gf_ipmpx_data_del(ipmpx);
3006 : }
3007 : }
3008 : }
3009 : break;
3010 : #endif
3011 :
3012 : /*descriptor list*/
3013 : case GF_ODF_FT_OD_LIST:
3014 : if (gf_bt_check_code(parser, '[')) {
3015 : while (!gf_bt_check_code(parser, ']')) {
3016 711 : subdesc = gf_bt_parse_descriptor(parser, NULL);
3017 711 : if (!subdesc) {
3018 0 : gf_odf_desc_del(desc);
3019 0 : parser->last_error = GF_BAD_PARAM;
3020 0 : return NULL;
3021 : }
3022 711 : gf_bt_add_desc(parser, desc, subdesc, field);
3023 : }
3024 : }
3025 556 : if (is_anim_mask)
3026 : gf_bt_check_code(parser, '}');
3027 : break;
3028 : /*single descriptor*/
3029 1116 : case GF_ODF_FT_OD:
3030 1116 : str = gf_bt_get_next(parser, 0);
3031 1116 : subdesc = gf_bt_parse_descriptor(parser, str);
3032 1116 : if (!subdesc) {
3033 0 : gf_bt_report(parser, GF_BAD_PARAM, "Unknown desc %s in field %s", str, field);
3034 0 : gf_odf_desc_del(desc);
3035 0 : return NULL;
3036 : }
3037 1116 : gf_bt_add_desc(parser, desc, subdesc, field);
3038 1116 : break;
3039 : /*regular field*/
3040 5582 : default:
3041 5582 : str = gf_bt_get_next(parser, 0);
3042 5582 : parser->last_error = gf_odf_set_field(desc, field, str);
3043 :
3044 5582 : if (parser->last_error) {
3045 0 : gf_bt_report(parser, GF_BAD_PARAM, "Invalid value %s in field %s", str, field);
3046 0 : gf_odf_desc_del(desc);
3047 0 : return NULL;
3048 : }
3049 : break;
3050 : }
3051 : }
3052 2388 : if (desc->tag == GF_ODF_BIFS_CFG_TAG) {
3053 : GF_BIFSConfig *bcfg = (GF_BIFSConfig *)desc;
3054 374 : if (!parser->load->ctx->scene_width) {
3055 372 : parser->load->ctx->scene_width = bcfg->pixelWidth;
3056 372 : parser->load->ctx->scene_height = bcfg->pixelHeight;
3057 372 : parser->load->ctx->is_pixel_metrics = bcfg->pixelMetrics;
3058 : }
3059 :
3060 : /*for bt->xmt*/
3061 374 : if (!bcfg->version) bcfg->version = 1;
3062 : }
3063 2014 : else if (desc->tag==GF_ODF_ESD_TAG) {
3064 : GF_ESD *esd =(GF_ESD*)desc;
3065 692 : if (esd->decoderConfig) {
3066 : GF_StreamContext *sc=NULL;
3067 : GF_MuxInfo *mux;
3068 : /*watchout for default BIFS stream*/
3069 539 : if (parser->bifs_es && !parser->base_bifs_id && (esd->decoderConfig->streamType==GF_STREAM_SCENE)) {
3070 372 : parser->bifs_es->ESID = parser->base_bifs_id = esd->ESID;
3071 372 : parser->bifs_es->timeScale = (esd->slConfig && esd->slConfig->timestampResolution) ? esd->slConfig->timestampResolution : 1000;
3072 372 : sc = parser->bifs_es;
3073 : } else {
3074 167 : sc = gf_sm_stream_new(parser->load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication);
3075 : /*set default timescale for systems tracks (ignored for other)*/
3076 167 : if (sc) sc->timeScale = (esd->slConfig && esd->slConfig->timestampResolution) ? esd->slConfig->timestampResolution : 1000;
3077 : /*assign base OD*/
3078 167 : if (!parser->base_od_id && (esd->decoderConfig->streamType==GF_STREAM_OD)) parser->base_od_id = esd->ESID;
3079 : }
3080 : /*assign broadcast parameter tools*/
3081 539 : mux = gf_sm_get_mux_info(esd);
3082 539 : if (sc && mux) {
3083 5 : sc->aggregate_on_esid = mux->aggregate_on_esid;
3084 5 : if (!mux->carousel_period_plus_one) sc->carousel_period = (u32) -1;
3085 0 : else sc->carousel_period = mux->carousel_period_plus_one - 1;
3086 : }
3087 : }
3088 1322 : } else if (desc->tag==GF_ODF_MUXINFO_TAG) {
3089 : GF_MuxInfo *mi = (GF_MuxInfo *)desc;
3090 158 : if (! mi->src_url) {
3091 158 : mi->src_url = gf_strdup(parser->load->src_url ? parser->load->src_url : parser->load->fileName);
3092 : }
3093 : }
3094 : return desc;
3095 : }
3096 :
3097 168 : void gf_bt_parse_od_command(GF_BTParser *parser, char *name)
3098 : {
3099 168 : u32 val=0;
3100 : char *str;
3101 :
3102 168 : if (!strcmp(name, "UPDATE")) {
3103 146 : str = gf_bt_get_next(parser, 0);
3104 : /*OD update*/
3105 146 : if (!strcmp(str, "OD")) {
3106 : GF_ODUpdate *odU;
3107 : if (!gf_bt_check_code(parser, '[')) {
3108 0 : gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
3109 0 : return;
3110 : }
3111 141 : odU = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
3112 141 : gf_list_add(parser->od_au->commands, odU);
3113 465 : while (!parser->done) {
3114 : GF_Descriptor *desc;
3115 324 : str = gf_bt_get_next(parser, 0);
3116 : if (gf_bt_check_code(parser, ']')) break;
3117 183 : if (strcmp(str, "ObjectDescriptor") && strcmp(str, "InitialObjectDescriptor")) {
3118 0 : gf_bt_report(parser, GF_BAD_PARAM, "Object Descriptor expected got %s", str);
3119 0 : break;
3120 : }
3121 183 : desc = gf_bt_parse_descriptor(parser, str);
3122 183 : if (!desc) break;
3123 183 : gf_list_add(odU->objectDescriptors, desc);
3124 : }
3125 : return;
3126 : }
3127 : /*ESD update*/
3128 5 : if (!strcmp(str, "ESD")) {
3129 : GF_ESDUpdate *esdU;
3130 5 : str = gf_bt_get_next(parser, 0);
3131 5 : if (strcmp(str, "IN")) {
3132 0 : gf_bt_report(parser, GF_BAD_PARAM, "IN expected got %s", str);
3133 0 : return;
3134 : }
3135 5 : esdU = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
3136 5 : parser->last_error = gf_bt_parse_int(parser, "OD_ID", (SFInt32*)&val);
3137 5 : if (parser->last_error) return;
3138 5 : esdU->ODID = val;
3139 5 : gf_list_add(parser->od_au->commands, esdU);
3140 :
3141 : if (!gf_bt_check_code(parser, '[')) {
3142 5 : str = gf_bt_get_next(parser, 0);
3143 5 : if (strcmp(str, "esDescr")) {
3144 0 : gf_bt_report(parser, GF_BAD_PARAM, "esDescr expected got %s", str);
3145 0 : return;
3146 : }
3147 : if (!gf_bt_check_code(parser, '[')) {
3148 0 : gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
3149 0 : return;
3150 : }
3151 : }
3152 :
3153 10 : while (!parser->done) {
3154 : GF_Descriptor *desc;
3155 10 : str = gf_bt_get_next(parser, 0);
3156 : if (gf_bt_check_code(parser, ']')) break;
3157 5 : if (strcmp(str, "ES_Descriptor")) {
3158 0 : gf_bt_report(parser, GF_BAD_PARAM, "ES_Descriptor expected got %s", str);
3159 0 : break;
3160 : }
3161 5 : desc = gf_bt_parse_descriptor(parser, str);
3162 5 : if (!desc) break;
3163 5 : gf_list_add(esdU->ESDescriptors, desc);
3164 : }
3165 : return;
3166 : }
3167 : /*IPMP descriptor update*/
3168 0 : if (!strcmp(str, "IPMPD") || !strcmp(str, "IPMPDX")) {
3169 : GF_IPMPUpdate *ipU;
3170 : if (!gf_bt_check_code(parser, '[')) {
3171 0 : gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
3172 0 : return;
3173 : }
3174 0 : ipU = (GF_IPMPUpdate *) gf_odf_com_new(GF_ODF_IPMP_UPDATE_TAG);
3175 0 : gf_list_add(parser->od_au->commands, ipU);
3176 0 : while (!parser->done) {
3177 : GF_Descriptor *desc;
3178 0 : str = gf_bt_get_next(parser, 0);
3179 : if (gf_bt_check_code(parser, ']')) break;
3180 0 : if (strcmp(str, "IPMP_Descriptor")) {
3181 0 : gf_bt_report(parser, GF_BAD_PARAM, "IPMP_Descriptor expected got %s", str);
3182 0 : break;
3183 : }
3184 0 : desc = gf_bt_parse_descriptor(parser, str);
3185 0 : if (!desc) break;
3186 0 : gf_list_add(ipU->IPMPDescList, desc);
3187 : }
3188 : return;
3189 : }
3190 0 : gf_bt_report(parser, GF_BAD_PARAM, "unknown OD command", str);
3191 0 : return;
3192 : }
3193 22 : if (!strcmp(name, "REMOVE")) {
3194 22 : str = gf_bt_get_next(parser, 0);
3195 : /*OD remove*/
3196 22 : if (!strcmp(str, "OD")) {
3197 : GF_ODRemove *odR;
3198 : if (!gf_bt_check_code(parser, '[')) {
3199 0 : gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
3200 0 : return;
3201 : }
3202 11 : odR = (GF_ODRemove *) gf_odf_com_new(GF_ODF_OD_REMOVE_TAG);
3203 11 : gf_list_add(parser->od_au->commands, odR);
3204 11 : while (!parser->done) {
3205 : u32 id;
3206 : if (gf_bt_check_code(parser, ']')) break;
3207 11 : gf_bt_parse_int(parser, "ODID", (SFInt32*)&id);
3208 11 : if (parser->last_error) return;
3209 11 : odR->OD_ID = (u16*)gf_realloc(odR->OD_ID, sizeof(u16) * (odR->NbODs+1));
3210 11 : odR->OD_ID[odR->NbODs] = id;
3211 11 : odR->NbODs++;
3212 : }
3213 : return;
3214 : }
3215 : /*ESD remove*/
3216 11 : if (!strcmp(str, "ESD")) {
3217 : u32 odid;
3218 : GF_ESDRemove *esdR;
3219 11 : str = gf_bt_get_next(parser, 0);
3220 11 : if (strcmp(str, "FROM")) {
3221 0 : gf_bt_report(parser, GF_BAD_PARAM, "FROM expected got %s", str);
3222 0 : return;
3223 : }
3224 11 : gf_bt_parse_int(parser, "ODID", (SFInt32*)&odid);
3225 11 : if (parser->last_error) return;
3226 :
3227 : if (!gf_bt_check_code(parser, '[')) {
3228 0 : gf_bt_report(parser, GF_BAD_PARAM, "[ expected");
3229 0 : return;
3230 : }
3231 11 : esdR = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
3232 11 : esdR->ODID = odid;
3233 11 : gf_list_add(parser->od_au->commands, esdR);
3234 11 : while (!parser->done) {
3235 : u32 id;
3236 : if (gf_bt_check_code(parser, ']')) break;
3237 11 : gf_bt_parse_int(parser, "ES_ID", (SFInt32*)&id);
3238 11 : if (parser->last_error) return;
3239 11 : esdR->ES_ID = (u16*)gf_realloc(esdR->ES_ID, sizeof(u16) * (esdR->NbESDs+1));
3240 11 : esdR->ES_ID[esdR->NbESDs] = id;
3241 11 : esdR->NbESDs++;
3242 : }
3243 : return;
3244 : }
3245 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown OD command", str);
3246 0 : return;
3247 : }
3248 : }
3249 :
3250 :
3251 :
3252 871 : GF_Err gf_bt_loader_run_intern(GF_BTParser *parser, GF_Command *init_com, Bool initial_run)
3253 : {
3254 : char *str;
3255 : GF_Node *node, *vrml_root_node;
3256 : Bool force_new_com;
3257 : GF_Route *r;
3258 : Bool has_id;
3259 : char szDEFName[1000];
3260 :
3261 : vrml_root_node = NULL;
3262 : has_id = 0;
3263 :
3264 871 : if (init_com)
3265 406 : parser->in_com = 0 ;
3266 :
3267 871 : parser->cur_com = init_com;
3268 :
3269 871 : force_new_com = (parser->load->flags & GF_SM_LOAD_CONTEXT_READY) ? 1 : 0;
3270 :
3271 :
3272 : /*create a default root node for all VRML nodes*/
3273 871 : if (parser->is_wrl && !parser->top_nodes) {
3274 56 : if (initial_run ) {
3275 : #ifndef GPAC_DISABLE_X3D
3276 28 : vrml_root_node = gf_node_new(parser->load->scene_graph, (parser->load->flags & GF_SM_LOAD_MPEG4_STRICT) ? TAG_MPEG4_Group : TAG_X3D_Group);
3277 : #else
3278 : vrml_root_node = gf_node_new(parser->load->scene_graph, TAG_MPEG4_Group);
3279 : #endif
3280 28 : gf_node_register(vrml_root_node, NULL);
3281 28 : gf_node_init(vrml_root_node);
3282 28 : gf_sg_set_root_node(parser->load->scene_graph, vrml_root_node);
3283 : } else {
3284 28 : vrml_root_node = gf_sg_get_root_node(parser->load->scene_graph);
3285 : }
3286 : }
3287 :
3288 871 : if (!parser->in_com)
3289 841 : parser->stream_id = parser->load->force_es_id;
3290 :
3291 : /*parse all top-level items*/
3292 4370 : while (!parser->last_error) {
3293 4368 : str = gf_bt_get_next(parser, 0);
3294 4368 : if (parser->done) break;
3295 :
3296 : /*X3D specific things (ignored for now)*/
3297 3529 : if (!strcmp(str, "PROFILE")) gf_bt_force_line(parser);
3298 3524 : else if (!strcmp(str, "COMPONENT")) gf_bt_force_line(parser);
3299 3524 : else if (!strcmp(str, "META")) gf_bt_force_line(parser);
3300 3524 : else if (!strcmp(str, "IMPORT") || !strcmp(str, "EXPORT")) {
3301 0 : gf_bt_report(parser, GF_NOT_SUPPORTED, "X3D IMPORT/EXPORT not implemented");
3302 0 : break;
3303 : }
3304 :
3305 : /*IOD*/
3306 3524 : else if (!strcmp(str, "InitialObjectDescriptor") || !strcmp(str, "ObjectDescriptor")) {
3307 373 : parser->load->ctx->root_od = (GF_ObjectDescriptor *) gf_bt_parse_descriptor(parser, str);
3308 : }
3309 : /*explicit command*/
3310 3151 : else if (!strcmp(str, "AT") || !strcmp(str, "RAP")) {
3311 318 : parser->au_is_rap = 0;
3312 318 : if (!strcmp(str, "RAP")) {
3313 28 : parser->au_is_rap = 1;
3314 28 : str = gf_bt_get_next(parser, 0);
3315 28 : if (strcmp(str, "AT")) {
3316 0 : gf_bt_report(parser, GF_BAD_PARAM, "AT expected got %s", str);
3317 0 : parser->last_error = GF_BAD_PARAM;
3318 0 : break;
3319 : }
3320 : }
3321 : force_new_com = 0;
3322 318 : str = gf_bt_get_next(parser, 0);
3323 318 : if (str[0] == 'D') {
3324 260 : parser->au_time += atoi(&str[1]);
3325 : } else {
3326 188 : if (sscanf(str, "%u", &parser->au_time) != 1) {
3327 0 : gf_bt_report(parser, GF_BAD_PARAM, "Number expected got %s", str);
3328 0 : break;
3329 : }
3330 : }
3331 318 : if (parser->last_error) break;
3332 : /*reset all contexts*/
3333 318 : if (parser->od_au && (parser->od_au->timing != parser->au_time)) parser->od_au = NULL;
3334 318 : if (parser->bifs_au && (parser->bifs_au->timing != parser->au_time)) {
3335 175 : gf_bt_check_unresolved_nodes(parser);
3336 175 : parser->bifs_au = NULL;
3337 : }
3338 :
3339 318 : parser->stream_id = 0;
3340 : /*fix for mp4tool bt which doesn't support RAP signaling: assume the first AU
3341 : is always RAP*/
3342 318 : if (!parser->au_time) parser->au_is_rap = 1;
3343 :
3344 318 : parser->in_com = 1;
3345 :
3346 : if (!gf_bt_check_code(parser, '{')) {
3347 4 : str = gf_bt_get_next(parser, 0);
3348 4 : if (!strcmp(str, "IN")) {
3349 4 : gf_bt_parse_int(parser, "IN", (SFInt32*)&parser->stream_id);
3350 4 : if (parser->last_error) break;
3351 : }
3352 : if (!gf_bt_check_code(parser, '{')) {
3353 0 : gf_bt_report(parser, GF_BAD_PARAM, "{ expected");
3354 : }
3355 : }
3356 : /*done loading init frame*/
3357 318 : if (init_com && parser->au_time) break;
3358 : }
3359 2833 : else if (!strcmp(str, "PROTO") || !strcmp(str, "EXTERNPROTO")) {
3360 61 : gf_bt_parse_proto(parser, str, init_com ? init_com->new_proto_list : NULL);
3361 : }
3362 : /*compatibility for old bt (mp4tool) in ProtoLibs*/
3363 2772 : else if (!strcmp(str, "NULL")) {
3364 : }
3365 2772 : else if (!strcmp(str, "DEF")) {
3366 37 : str = gf_bt_get_next(parser, 0);
3367 : strcpy(szDEFName, str);
3368 : has_id = 1;
3369 : }
3370 2735 : else if (!strcmp(str, "ROUTE")) {
3371 : GF_Command *com = NULL;
3372 1340 : if (!parser->top_nodes && parser->bifs_au && !parser->is_wrl) {
3373 : /*if doing a scene replace, we need route insert stuff*/
3374 1320 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_ROUTE_INSERT);
3375 1320 : gf_list_add(parser->bifs_au->commands, com);
3376 1320 : gf_list_add(parser->inserted_routes, com);
3377 : }
3378 :
3379 1340 : r = gf_bt_parse_route(parser, 1, 0, com);
3380 1340 : if (has_id) {
3381 23 : u32 rID = gf_bt_get_route(parser, szDEFName);
3382 23 : if (!rID) rID = gf_bt_get_next_route_id(parser);
3383 23 : if (com) {
3384 23 : com->RouteID = rID;
3385 23 : com->def_name = gf_strdup(szDEFName);
3386 23 : gf_sg_set_max_defined_route_id(parser->load->scene_graph, rID);
3387 0 : } else if (r) {
3388 0 : gf_sg_route_set_id(r, rID);
3389 0 : gf_sg_route_set_name(r, szDEFName);
3390 : }
3391 : has_id = 0;
3392 : }
3393 : }
3394 : /*OD commands*/
3395 1395 : else if (!strcmp(str, "UPDATE") || !strcmp(str, "REMOVE")) {
3396 168 : Bool is_base_stream = parser->stream_id ? 0 : 1;
3397 168 : if (!parser->stream_id || parser->stream_id==parser->bifs_es->ESID) parser->stream_id = parser->base_od_id;
3398 :
3399 168 : if (parser->od_es && (parser->od_es->ESID != parser->stream_id)) {
3400 : GF_StreamContext *prev = parser->od_es;
3401 0 : parser->od_es = gf_sm_stream_new(parser->load->ctx, (u16) parser->stream_id, GF_STREAM_OD, GF_CODECID_OD_V1);
3402 : /*force new AU if stream changed*/
3403 0 : if (parser->od_es != prev) {
3404 0 : parser->bifs_au = NULL;
3405 0 : parser->od_au = NULL;
3406 : }
3407 : }
3408 168 : if (!parser->od_es) parser->od_es = gf_sm_stream_new(parser->load->ctx, (u16) parser->stream_id, GF_STREAM_OD, GF_CODECID_OD_V1);
3409 168 : if (!parser->od_au) parser->od_au = gf_sm_stream_au_new(parser->od_es, parser->au_time, 0, parser->au_is_rap);
3410 168 : gf_bt_parse_od_command(parser, str);
3411 168 : if (is_base_stream) parser->stream_id= 0;
3412 : }
3413 : /*BIFS commands*/
3414 1227 : else if (!strcmp(str, "REPLACE") || !strcmp(str, "INSERT") || !strcmp(str, "APPEND") || !strcmp(str, "DELETE")
3415 : /*BIFS extended commands*/
3416 847 : || !strcmp(str, "GLOBALQP") || !strcmp(str, "MULTIPLEREPLACE") || !strcmp(str, "MULTIPLEINDREPLACE") || !strcmp(str, "XDELETE") || !strcmp(str, "DELETEPROTO") || !strcmp(str, "INSERTPROTO")
3417 772 : || !strcmp(str, "XREPLACE")
3418 : ) {
3419 475 : Bool is_base_stream = parser->stream_id ? 0 : 1;
3420 :
3421 475 : if (!parser->stream_id) parser->stream_id = parser->base_bifs_id;
3422 475 : if (!parser->stream_id || (parser->od_es && (parser->stream_id==parser->od_es->ESID)) ) parser->stream_id = parser->base_bifs_id;
3423 :
3424 475 : if (parser->bifs_es->ESID != parser->stream_id) {
3425 : GF_StreamContext *prev = parser->bifs_es;
3426 3 : parser->bifs_es = gf_sm_stream_new(parser->load->ctx, (u16) parser->stream_id, GF_STREAM_SCENE, GF_CODECID_BIFS);
3427 : /*force new AU if stream changed*/
3428 3 : if (parser->bifs_es != prev) {
3429 3 : gf_bt_check_unresolved_nodes(parser);
3430 3 : parser->bifs_au = NULL;
3431 : }
3432 : }
3433 475 : if (force_new_com) {
3434 : force_new_com = 0;
3435 2 : parser->bifs_au = gf_list_last(parser->bifs_es->AUs);
3436 2 : parser->au_time = (u32) (parser->bifs_au ? parser->bifs_au->timing : 0) + 1;
3437 2 : parser->bifs_au = NULL;
3438 : }
3439 :
3440 475 : if (!parser->bifs_au) parser->bifs_au = gf_sm_stream_au_new(parser->bifs_es, parser->au_time, 0, parser->au_is_rap);
3441 475 : gf_bt_parse_bifs_command(parser, str, parser->bifs_au->commands);
3442 475 : if (is_base_stream) parser->stream_id= 0;
3443 : }
3444 : /*implicit BIFS command on SFTopNodes only*/
3445 752 : else if (!strcmp(str, "OrderedGroup")
3446 416 : || !strcmp(str, "Group")
3447 340 : || !strcmp(str, "Layer2D")
3448 340 : || !strcmp(str, "Layer3D")
3449 : /* VRML parsing: all nodes are allowed*/
3450 340 : || parser->is_wrl
3451 : )
3452 : {
3453 :
3454 432 : node = gf_bt_sf_node(parser, str, vrml_root_node, has_id ? szDEFName : NULL);
3455 : has_id = 0;
3456 432 : if (!node) break;
3457 432 : if (parser->top_nodes) {
3458 0 : gf_list_add(parser->top_nodes, node);
3459 432 : } else if (!vrml_root_node) {
3460 394 : if (init_com) init_com->node = node;
3461 0 : else if (parser->load->flags & GF_SM_LOAD_CONTEXT_READY) {
3462 0 : GF_Command *com = gf_sg_command_new(parser->load->scene_graph, GF_SG_SCENE_REPLACE);
3463 : assert(!parser->bifs_au);
3464 : assert(parser->bifs_es);
3465 0 : parser->bifs_au = gf_sm_stream_au_new(parser->bifs_es, 0, 0, 1);
3466 0 : gf_list_add(parser->bifs_au->commands, com);
3467 0 : com->node = node;
3468 : }
3469 : } else {
3470 38 : gf_node_insert_child(vrml_root_node, node, -1);
3471 : }
3472 :
3473 : /*
3474 : if (!gf_sg_get_root_node(parser->load->scene_graph)) {
3475 : gf_node_register(node, NULL);
3476 : gf_sg_set_root_node(parser->load->scene_graph, node);
3477 : }
3478 : */
3479 : }
3480 :
3481 : /*if in command, check command end*/
3482 : else {
3483 : /*check command end*/
3484 320 : if (/*in_com && */gf_bt_check_code(parser, '}')) parser->in_com = 0;
3485 0 : else if (strlen(str)) {
3486 0 : gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown top-level element", str);
3487 : }
3488 320 : parser->au_is_rap = 0;
3489 : }
3490 : }
3491 871 : gf_bt_resolve_routes(parser, 0);
3492 871 : gf_bt_check_unresolved_nodes(parser);
3493 :
3494 : /*load scripts*/
3495 1743 : while (gf_list_count(parser->scripts)) {
3496 1 : GF_Node *n = (GF_Node *)gf_list_get(parser->scripts, 0);
3497 1 : gf_list_rem(parser->scripts, 0);
3498 1 : gf_sg_script_load(n);
3499 : }
3500 871 : return parser->last_error;
3501 : }
3502 :
3503 439 : static GF_Err gf_sm_load_bt_initialize(GF_SceneLoader *load, const char *str, Bool input_only)
3504 : {
3505 : u32 size;
3506 : gzFile gzInput;
3507 : GF_Err e;
3508 : unsigned char BOM[5];
3509 439 : GF_BTParser *parser = load->loader_priv;
3510 :
3511 439 : parser->last_error = GF_OK;
3512 :
3513 439 : if (load->fileName) {
3514 435 : FILE *test = gf_fopen(load->fileName, "rb");
3515 435 : if (!test) return GF_URL_ERROR;
3516 :
3517 435 : size = (u32) gf_fsize(test);
3518 435 : gf_fclose(test);
3519 :
3520 435 : gzInput = gf_gzopen(load->fileName, "rb");
3521 435 : if (!gzInput) return GF_IO_ERR;
3522 :
3523 435 : parser->line_buffer = (char *) gf_malloc(sizeof(char)*BT_LINE_SIZE);
3524 : memset(parser->line_buffer, 0, sizeof(char)*BT_LINE_SIZE);
3525 435 : parser->file_size = size;
3526 :
3527 435 : parser->line_pos = parser->line_size = 0;
3528 435 : gf_gzgets(gzInput, (char*) BOM, 5);
3529 435 : gf_gzseek(gzInput, 0, SEEK_SET);
3530 435 : parser->gz_in = gzInput;
3531 :
3532 : } else {
3533 4 : if (!str || (strlen(str)<5) ) {
3534 : /*wait for first string data to be fed to the parser (for load from string)*/
3535 2 : parser->initialized = 0;
3536 2 : return GF_OK;
3537 : }
3538 : strncpy((char *) BOM, str, 5);
3539 : }
3540 :
3541 : /*0: no unicode, 1: UTF-16BE, 2: UTF-16LE*/
3542 437 : if ((BOM[0]==0xFF) && (BOM[1]==0xFE)) {
3543 5 : if (!BOM[2] && !BOM[3]) {
3544 0 : gf_bt_report(parser, GF_NOT_SUPPORTED, "UTF-32 Text Files not supported");
3545 0 : return GF_NOT_SUPPORTED;
3546 : } else {
3547 5 : parser->unicode_type = 2;
3548 5 : if (parser->gz_in) gf_gzseek(parser->gz_in, 2, SEEK_CUR);
3549 : }
3550 432 : } else if ((BOM[0]==0xFE) && (BOM[1]==0xFF)) {
3551 0 : if (!BOM[2] && !BOM[3]) {
3552 0 : gf_bt_report(parser, GF_NOT_SUPPORTED, "UTF-32 Text Files not supported");
3553 0 : return GF_NOT_SUPPORTED;
3554 : } else {
3555 0 : parser->unicode_type = 1;
3556 0 : if (parser->gz_in) gf_gzseek(parser->gz_in, 2, SEEK_CUR);
3557 : }
3558 432 : } else if ((BOM[0]==0xEF) && (BOM[1]==0xBB) && (BOM[2]==0xBF)) {
3559 : /*we handle UTF8 as asci*/
3560 0 : parser->unicode_type = 0;
3561 0 : if (parser->gz_in) gf_gzseek(parser->gz_in, 3, SEEK_CUR);
3562 : }
3563 437 : parser->initialized = 1;
3564 :
3565 437 : if ( load->fileName )
3566 : {
3567 435 : char *sep = gf_file_ext_start(load->fileName);
3568 435 : if (sep && !strnicmp(sep, ".wrl", 4)) parser->is_wrl = 1;
3569 : }
3570 :
3571 437 : if (input_only) return GF_OK;
3572 :
3573 : /*initalize default streams in the context*/
3574 :
3575 : /*chunk parsing*/
3576 437 : if (load->flags & GF_SM_LOAD_CONTEXT_READY) {
3577 : u32 i;
3578 : GF_StreamContext *sc;
3579 3 : if (!load->ctx) return GF_BAD_PARAM;
3580 :
3581 : /*restore context - note that base layer are ALWAYS declared BEFORE enhancement layers with gpac parsers*/
3582 3 : i=0;
3583 9 : while ((sc = (GF_StreamContext*)gf_list_enum(load->ctx->streams, &i))) {
3584 3 : switch (sc->streamType) {
3585 2 : case GF_STREAM_SCENE:
3586 2 : if (!parser->bifs_es) parser->bifs_es = sc;
3587 : break;
3588 1 : case GF_STREAM_OD:
3589 1 : if (!parser->od_es) parser->od_es = sc;
3590 : break;
3591 : default:
3592 : break;
3593 : }
3594 : }
3595 : /*need at least one scene stream*/
3596 3 : if (!parser->bifs_es) {
3597 2 : parser->bifs_es = gf_sm_stream_new(load->ctx, 0, GF_STREAM_SCENE, GF_CODECID_BIFS);
3598 2 : parser->load->ctx->scene_width = 0;
3599 2 : parser->load->ctx->scene_height = 0;
3600 2 : parser->load->ctx->is_pixel_metrics = 1;
3601 : }
3602 1 : else parser->base_bifs_id = parser->bifs_es->ESID;
3603 3 : if (parser->od_es) parser->base_od_id = parser->od_es->ESID;
3604 :
3605 3 : GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("BT: MPEG-4 (BT) Scene Chunk Parsing"));
3606 : }
3607 : /*context is not initialized - check for VRML*/
3608 : else {
3609 : GF_Command *com;
3610 :
3611 :
3612 434 : parser->load = NULL;
3613 434 : gf_bt_check_line(parser);
3614 434 : parser->load = load;
3615 434 : if (load->ctx && parser->def_w && parser->def_h) {
3616 29 : load->ctx->scene_width = parser->def_w;
3617 29 : load->ctx->scene_height = parser->def_h;
3618 : }
3619 :
3620 : /*create at least one empty BIFS stream*/
3621 434 : if (!parser->is_wrl && load->ctx) {
3622 406 : parser->bifs_es = gf_sm_stream_new(load->ctx, 0, GF_STREAM_SCENE, GF_CODECID_BIFS);
3623 406 : parser->bifs_au = gf_sm_stream_au_new(parser->bifs_es, 0, 0, 1);
3624 406 : parser->load->ctx->is_pixel_metrics = 1;
3625 : }
3626 :
3627 434 : GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ( ((parser->is_wrl==2) ? "BT: X3D (WRL) Scene Parsing\n" : (parser->is_wrl ? "BT: VRML Scene Parsing\n" : "BT: MPEG-4 Scene Parsing\n")) ));
3628 :
3629 : /*default scene replace - we create it no matter what since it is used to store BIFS config when parsing IOD.*/
3630 : com = NULL;
3631 434 : if (!parser->is_wrl) {
3632 406 : com = gf_sg_command_new(parser->load->scene_graph, GF_SG_SCENE_REPLACE);
3633 406 : gf_list_add(parser->bifs_au->commands, com);
3634 : }
3635 :
3636 : /*and perform initial load*/
3637 434 : e = gf_bt_loader_run_intern(parser, com, 1);
3638 434 : if (e) return e;
3639 : }
3640 : return GF_OK;
3641 : }
3642 :
3643 844 : void load_bt_done(GF_SceneLoader *load)
3644 : {
3645 844 : GF_BTParser *parser = (GF_BTParser *)load->loader_priv;
3646 844 : if (!parser) return;
3647 437 : gf_list_del(parser->unresolved_routes);
3648 437 : gf_list_del(parser->inserted_routes);
3649 437 : gf_list_del(parser->undef_nodes);
3650 437 : gf_list_del(parser->def_nodes);
3651 437 : gf_list_del(parser->peeked_nodes);
3652 889 : while (gf_list_count(parser->def_symbols)) {
3653 15 : BTDefSymbol *d = (BTDefSymbol *)gf_list_get(parser->def_symbols, 0);
3654 15 : gf_list_rem(parser->def_symbols, 0);
3655 15 : gf_free(d->name);
3656 15 : gf_free(d->value);
3657 15 : gf_free(d);
3658 : }
3659 437 : gf_list_del(parser->def_symbols);
3660 437 : gf_list_del(parser->scripts);
3661 :
3662 437 : if (parser->gz_in) gf_gzclose(parser->gz_in);
3663 437 : if (parser->line_buffer) gf_free(parser->line_buffer);
3664 437 : gf_free(parser);
3665 437 : load->loader_priv = NULL;
3666 : }
3667 :
3668 435 : GF_Err load_bt_run(GF_SceneLoader *load)
3669 : {
3670 : GF_Err e;
3671 435 : GF_BTParser *parser = (GF_BTParser *)load->loader_priv;
3672 435 : if (!parser) return GF_BAD_PARAM;
3673 :
3674 435 : if (!parser->initialized) {
3675 0 : e = gf_sm_load_bt_initialize(load, NULL, 1);
3676 0 : if (e) return e;
3677 : }
3678 :
3679 435 : e = gf_bt_loader_run_intern(parser, NULL, 0);
3680 :
3681 435 : if ((e<0) || parser->done) {
3682 435 : parser->done = 0;
3683 435 : parser->initialized = 0;
3684 435 : if (parser->gz_in) {
3685 435 : gf_gzclose(parser->gz_in);
3686 435 : parser->gz_in = NULL;
3687 : }
3688 :
3689 435 : if (parser->line_buffer) {
3690 435 : gf_free(parser->line_buffer);
3691 435 : parser->line_buffer = NULL;
3692 : }
3693 435 : parser->file_size = 0;
3694 435 : parser->line_pos = parser->line_size = 0;
3695 435 : load->fileName = NULL;
3696 : }
3697 : return e;
3698 : }
3699 :
3700 :
3701 2 : GF_Err load_bt_parse_string(GF_SceneLoader *load, const char *str)
3702 : {
3703 : GF_Err e;
3704 : char *dup_str;
3705 2 : GF_BTParser *parser = (GF_BTParser *)load->loader_priv;
3706 2 : if (!parser) return GF_BAD_PARAM;
3707 :
3708 2 : if (parser->done) {
3709 0 : parser->done = 0;
3710 0 : parser->initialized = 0;
3711 0 : parser->file_size = 0;
3712 0 : parser->line_pos = 0;
3713 : }
3714 2 : parser->line_buffer = dup_str = gf_strdup(str);
3715 2 : parser->line_size = (s32)strlen(str);
3716 :
3717 2 : if (!parser->initialized) {
3718 2 : e = gf_sm_load_bt_initialize(load, str, 0);
3719 2 : if (e) {
3720 0 : gf_free(dup_str);
3721 0 : return e;
3722 : }
3723 : }
3724 2 : e = gf_bt_loader_run_intern(parser, NULL, 0);
3725 2 : parser->line_buffer = NULL;
3726 2 : parser->line_size = 0;
3727 2 : gf_free(dup_str);
3728 2 : return e;
3729 : }
3730 :
3731 0 : GF_Err load_bt_suspend(GF_SceneLoader *load, Bool suspend)
3732 : {
3733 0 : return GF_OK;
3734 : }
3735 :
3736 437 : GF_Err gf_sm_load_init_bt(GF_SceneLoader *load)
3737 : {
3738 : GF_Err e;
3739 : GF_BTParser *parser;
3740 :
3741 437 : if (!load || (!load->ctx && !load->scene_graph) ) return GF_BAD_PARAM;
3742 437 : if (!load->scene_graph) load->scene_graph = load->ctx->scene_graph;
3743 :
3744 437 : GF_SAFEALLOC(parser, GF_BTParser);
3745 437 : if (!parser) return GF_OUT_OF_MEM;
3746 437 : parser->load = load;
3747 437 : load->loader_priv = parser;
3748 437 : parser->def_symbols = gf_list_new();
3749 437 : parser->unresolved_routes = gf_list_new();
3750 437 : parser->inserted_routes = gf_list_new();
3751 437 : parser->undef_nodes = gf_list_new();
3752 437 : parser->def_nodes = gf_list_new();
3753 437 : parser->peeked_nodes = gf_list_new();
3754 437 : parser->scripts = gf_list_new();
3755 :
3756 437 : load->process = load_bt_run;
3757 437 : load->done = load_bt_done;
3758 437 : load->suspend = load_bt_suspend;
3759 437 : load->parse_string = load_bt_parse_string;
3760 :
3761 : #ifdef GPAC_ENABLE_COVERAGE
3762 437 : if (gf_sys_is_cov_mode()) {
3763 431 : gf_bt_report(parser, GF_OK, NULL);
3764 : }
3765 : #endif
3766 :
3767 437 : e = gf_sm_load_bt_initialize(load, NULL, 0);
3768 437 : if (e) {
3769 0 : load_bt_done(load);
3770 0 : return e;
3771 : }
3772 : return GF_OK;
3773 : }
3774 :
3775 :
3776 : GF_EXPORT
3777 0 : GF_List *gf_sm_load_bt_from_string(GF_SceneGraph *in_scene, char *node_str, Bool force_wrl)
3778 : {
3779 : GF_SceneLoader ctx;
3780 : GF_BTParser parser;
3781 : memset(&ctx, 0, sizeof(GF_SceneLoader));
3782 0 : ctx.scene_graph = in_scene;
3783 : memset(&parser, 0, sizeof(GF_BTParser));
3784 0 : parser.line_buffer = node_str;
3785 0 : parser.line_size = (u32) strlen(node_str);
3786 0 : parser.load = &ctx;
3787 0 : parser.top_nodes = gf_list_new();
3788 0 : parser.undef_nodes = gf_list_new();
3789 0 : parser.def_nodes = gf_list_new();
3790 0 : parser.peeked_nodes = gf_list_new();
3791 0 : parser.is_wrl = force_wrl;
3792 0 : gf_bt_loader_run_intern(&parser, NULL, 1);
3793 0 : gf_list_del(parser.undef_nodes);
3794 0 : gf_list_del(parser.def_nodes);
3795 0 : gf_list_del(parser.peeked_nodes);
3796 0 : while (gf_list_count(parser.def_symbols)) {
3797 0 : BTDefSymbol *d = (BTDefSymbol *)gf_list_get(parser.def_symbols, 0);
3798 0 : gf_list_rem(parser.def_symbols, 0);
3799 0 : gf_free(d->name);
3800 0 : gf_free(d->value);
3801 0 : gf_free(d);
3802 : }
3803 0 : gf_list_del(parser.def_symbols);
3804 0 : gf_list_del(parser.scripts);
3805 :
3806 0 : return parser.top_nodes;
3807 : }
3808 :
3809 : #endif /*GPAC_DISABLE_LOADER_BT*/
|