Coverage Report

Created: 2026-10-26 08:08

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