Coverage Report

Created: 2023-11-19 06:24

/src/gpac/src/utils/error.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2023
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / common tools 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/tools.h>
27
#include <gpac/thread.h>
28
29
30
//ugly patch, we have a concurrence issue with gf_4cc_to_str, for now fixed by rolling buffers
31
67.5k
#define NB_4CC_BUF  10
32
static char szTYPE_BUF[NB_4CC_BUF][GF_4CC_MSIZE];
33
static u32 buf_4cc_idx = NB_4CC_BUF;
34
35
GF_EXPORT
36
const char *gf_4cc_to_str_safe(u32 type, char szType[GF_4CC_MSIZE])
37
2.76M
{
38
2.76M
  u32 ch, i;
39
2.76M
  if (!type) {
40
0
    strcpy(szType, "00000000");
41
0
    return szType;
42
0
  }
43
2.76M
  char *name = (char *)szType;
44
13.8M
  for (i = 0; i < 4; i++) {
45
11.0M
    ch = type >> (8 * (3-i) ) & 0xff;
46
11.0M
    if ( ch >= 0x20 && ch <= 0x7E ) {
47
10.8M
      *name = ch;
48
10.8M
      name++;
49
10.8M
    } else {
50
207k
      sprintf(name, "%02X", ch);
51
207k
      name += 2;
52
207k
    }
53
11.0M
  }
54
2.76M
  *name = 0;
55
2.76M
  return szType;
56
2.76M
}
57
#include <gpac/thread.h>
58
59
GF_EXPORT
60
const char *gf_4cc_to_str(u32 type)
61
696k
{
62
696k
  if (!type) return "00000000";
63
675k
  if (safe_int_dec(&buf_4cc_idx)==0)
64
67.5k
    buf_4cc_idx=NB_4CC_BUF;
65
66
675k
  return gf_4cc_to_str_safe(type, szTYPE_BUF[buf_4cc_idx-1]);
67
696k
}
68
69
70
71
GF_EXPORT
72
u32 gf_4cc_parse(const char *val)
73
0
{
74
0
  if (val && strlen(val)==4) return GF_4CC(val[0], val[1], val[2], val[3]);
75
0
  GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Value %s is not a properly defined 4CC\n", val));
76
0
  return 0;
77
0
}
78
79
static const char *szProg[] =
80
{
81
  "                    ",
82
  "=                   ",
83
  "==                  ",
84
  "===                 ",
85
  "====                ",
86
  "=====               ",
87
  "======              ",
88
  "=======             ",
89
  "========            ",
90
  "=========           ",
91
  "==========          ",
92
  "===========         ",
93
  "============        ",
94
  "=============       ",
95
  "==============      ",
96
  "===============     ",
97
  "================    ",
98
  "=================   ",
99
  "==================  ",
100
  "=================== ",
101
  "====================",
102
};
103
104
static u64 prev_pos = (u64) -1;
105
static u64 prev_pc = (u64) -1;
106
extern char gf_prog_lf;
107
108
static void gf_on_progress_std(const char *_title, u64 done, u64 total)
109
0
{
110
0
  Double prog;
111
0
  u32 pos, pc;
112
0
  const char *szT = _title ? (char *)_title : (char *) "";
113
114
0
  if (total) {
115
0
    prog = (double) done;
116
0
    prog /= total;
117
0
  } else {
118
0
    prog = 0;
119
0
  }
120
121
0
  pos = MIN((u32) (20 * prog), 20);
122
123
0
  if (done != total && pos>prev_pos) {
124
0
    prev_pos = 0;
125
0
    prev_pc = 0;
126
0
  }
127
0
  pc = (u32) ( 100 * prog);
128
129
0
  if ((done != total || prev_pos ) && ((pos!=prev_pos) || (pc!=prev_pc))) {
130
0
    prev_pos = pos;
131
0
    prev_pc = pc;
132
0
    fprintf(stderr, "%s: |%s| (%02d/100)%c", szT, szProg[pos], pc, gf_prog_lf);
133
0
    fflush(stderr);
134
0
  }
135
0
  if (done==total) {
136
0
    if (prev_pos) {
137
0
      u32 len = (u32) strlen(szT) + 40;
138
0
      while (len) {
139
0
        fprintf(stderr, " ");
140
0
        len--;
141
0
      };
142
0
      fprintf(stderr, "%c", gf_prog_lf);
143
0
    }
144
0
    prev_pos = 0;
145
0
  }
146
0
}
147
148
static gf_on_progress_cbk prog_cbk = NULL;
149
static void *user_cbk = NULL;
150
#if defined(GPAC_CONFIG_IOS) || defined(GPAC_CONFIG_ANDROID) || defined(GPAC_CONFIG_EMSCRIPTEN)
151
static Bool gpac_no_color_logs = GF_TRUE;
152
#else
153
static Bool gpac_no_color_logs = GF_FALSE;
154
#endif
155
156
GF_EXPORT
157
void gf_set_progress(const char *title, u64 done, u64 total)
158
0
{
159
0
  if (done>=total)
160
0
    done=total;
161
0
  if (prog_cbk || user_cbk) {
162
0
    if (prog_cbk)
163
0
      prog_cbk(user_cbk, title, done, total);
164
0
  }
165
0
#ifndef _WIN32_WCE
166
0
  else {
167
0
    gf_on_progress_std(title, done, total);
168
0
  }
169
0
#endif
170
0
}
171
172
GF_EXPORT
173
void gf_set_progress_callback(void *_user_cbk, gf_on_progress_cbk _prog_cbk)
174
0
{
175
0
  prog_cbk = _prog_cbk;
176
0
  user_cbk = _user_cbk;
177
0
}
178
179
#ifndef GPAC_DISABLE_LOG
180
181
/*ENTRIES MUST BE IN THE SAME ORDER AS LOG_TOOL DECLARATION IN <gpac/tools.h>*/
182
static struct log_tool_info {
183
  u32 type;
184
  const char *name;
185
  GF_LOG_Level level;
186
} global_log_tools [] =
187
{
188
  { GF_LOG_CORE, "core", GF_LOG_WARNING },
189
  { GF_LOG_CODING, "coding", GF_LOG_WARNING },
190
  { GF_LOG_CONTAINER, "container", GF_LOG_WARNING },
191
  { GF_LOG_NETWORK, "network", GF_LOG_WARNING },
192
  { GF_LOG_HTTP, "http", GF_LOG_WARNING },
193
  { GF_LOG_RTP, "rtp", GF_LOG_WARNING },
194
  { GF_LOG_CODEC, "codec", GF_LOG_WARNING },
195
  { GF_LOG_PARSER, "parser", GF_LOG_WARNING },
196
  { GF_LOG_MEDIA, "media", GF_LOG_WARNING },
197
  { GF_LOG_SCENE, "scene", GF_LOG_WARNING },
198
  { GF_LOG_SCRIPT, "script", GF_LOG_WARNING },
199
  { GF_LOG_INTERACT, "interact", GF_LOG_WARNING },
200
  { GF_LOG_COMPOSE, "compose", GF_LOG_WARNING },
201
  { GF_LOG_COMPTIME, "ctime", GF_LOG_WARNING },
202
  { GF_LOG_CACHE, "cache", GF_LOG_WARNING },
203
  { GF_LOG_MMIO, "mmio", GF_LOG_WARNING },
204
  { GF_LOG_RTI, "rti", GF_LOG_WARNING },
205
  { GF_LOG_MEMORY, "mem", GF_LOG_WARNING },
206
  { GF_LOG_AUDIO, "audio", GF_LOG_WARNING },
207
  { GF_LOG_MODULE, "module", GF_LOG_WARNING },
208
  { GF_LOG_MUTEX, "mutex", GF_LOG_WARNING },
209
  { GF_LOG_CONDITION, "condition", GF_LOG_WARNING },
210
  { GF_LOG_DASH, "dash", GF_LOG_WARNING },
211
  { GF_LOG_FILTER, "filter", GF_LOG_WARNING },
212
  { GF_LOG_SCHEDULER, "sched", GF_LOG_WARNING },
213
  { GF_LOG_ROUTE, "route", GF_LOG_WARNING },
214
  { GF_LOG_CONSOLE, "console", GF_LOG_INFO },
215
  { GF_LOG_APP, "app", GF_LOG_INFO },
216
};
217
218
0
#define GF_LOG_TOOL_MAX_NAME_SIZE (GF_LOG_TOOL_MAX*10)
219
220
#endif
221
222
GF_EXPORT
223
GF_Err gf_log_modify_tools_levels(const char *val_)
224
0
{
225
0
#ifndef GPAC_DISABLE_LOG
226
0
  char tmp[GF_LOG_TOOL_MAX_NAME_SIZE];
227
0
  const char *val = tmp;
228
0
  if (!val_) val_ = "";
229
0
  assert(strlen(val_) < GF_LOG_TOOL_MAX_NAME_SIZE);
230
0
  strncpy(tmp, val_, GF_LOG_TOOL_MAX_NAME_SIZE - 1);
231
0
  tmp[GF_LOG_TOOL_MAX_NAME_SIZE - 1] = 0;
232
233
0
  while (val && strlen(val)) {
234
0
    void default_log_callback(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist);
235
0
    u32 level;
236
0
    const char *next_val = NULL;
237
0
    const char *tools = NULL;
238
    /*look for log level*/
239
0
    char *sep_level = strchr(val, '@');
240
0
    if (!sep_level) {
241
0
      if (!strcmp(val, "ncl")) {
242
0
        gpac_no_color_logs = GF_TRUE;
243
0
        gf_log_set_callback(NULL, default_log_callback);
244
0
        if (!val[3]) break;
245
0
        val += 4;
246
0
        continue;
247
0
      } else if (!strcmp(val, "cl")) {
248
0
        gpac_no_color_logs = GF_FALSE;
249
0
        gf_log_set_callback(NULL, default_log_callback);
250
0
        if (!val[2]) break;
251
0
        val += 3;
252
0
        continue;
253
0
      } else if (!strcmp(val, "strict")) {
254
0
        gf_log_set_strict_error(GF_TRUE);
255
0
        if (!val[6]) break;
256
0
        val += 7;
257
0
        continue;
258
0
      } else if (!strcmp(val, "quiet")) {
259
0
        u32 i;
260
0
        for (i=0; i<GF_LOG_TOOL_MAX; i++)
261
0
          global_log_tools[i].level = GF_LOG_QUIET;
262
263
0
        if (!val[5]) break;
264
0
        val += 6;
265
0
        continue;
266
0
      } else {
267
0
        GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Unrecognized log format %s - expecting logTool@logLevel\n", val));
268
0
        return GF_BAD_PARAM;
269
0
      }
270
0
    }
271
272
0
    if (!strnicmp(sep_level+1, "error", 5)) {
273
0
      level = GF_LOG_ERROR;
274
0
      next_val = sep_level+1 + 5;
275
0
    }
276
0
    else if (!strnicmp(sep_level+1, "warning", 7)) {
277
0
      level = GF_LOG_WARNING;
278
0
      next_val = sep_level+1 + 7;
279
0
    }
280
0
    else if (!strnicmp(sep_level+1, "info", 4)) {
281
0
      level = GF_LOG_INFO;
282
0
      next_val = sep_level+1 + 4;
283
0
    }
284
0
    else if (!strnicmp(sep_level+1, "debug", 5)) {
285
0
      level = GF_LOG_DEBUG;
286
0
      next_val = sep_level+1 + 5;
287
0
    }
288
0
    else if (!strnicmp(sep_level+1, "quiet", 5)) {
289
0
      level = GF_LOG_QUIET;
290
0
      next_val = sep_level+1 + 5;
291
0
    }
292
0
    else {
293
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Unknown log level specified: %s\n", sep_level+1));
294
0
      return GF_BAD_PARAM;
295
0
    }
296
297
0
    sep_level[0] = 0;
298
0
    tools = val;
299
0
    while (tools) {
300
0
      u32 i;
301
302
0
      char *sep = strchr(tools, ':');
303
0
      if (sep) sep[0] = 0;
304
305
0
      if (!stricmp(tools, "all")) {
306
0
        for (i=0; i<GF_LOG_TOOL_MAX; i++)
307
0
          global_log_tools[i].level = level;
308
0
      }
309
0
      else if (!strcmp(val, "ncl")) {
310
0
        gpac_no_color_logs = GF_TRUE;
311
0
        gf_log_set_callback(NULL, default_log_callback);
312
0
      }
313
0
      else if (!strcmp(val, "cl")) {
314
0
        gpac_no_color_logs = GF_FALSE;
315
0
        gf_log_set_callback(NULL, default_log_callback);
316
0
      }
317
0
      else {
318
0
        Bool found = GF_FALSE;
319
0
        for (i=0; i<GF_LOG_TOOL_MAX; i++) {
320
0
          if (!strcmp(global_log_tools[i].name, tools)) {
321
0
            global_log_tools[i].level = level;
322
0
            found = GF_TRUE;
323
0
            break;
324
0
          }
325
0
        }
326
0
        if (!found) {
327
0
          GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Unknown log tool specified: %s\n", tools));
328
0
          sep_level[0] = '@';
329
0
          if (sep) sep[0] = ':';
330
0
          return GF_BAD_PARAM;
331
0
        }
332
0
      }
333
334
0
      if (!sep) break;
335
0
      sep[0] = ':';
336
0
      tools = sep+1;
337
0
    }
338
339
0
    sep_level[0] = '@';
340
0
    if (!next_val[0]) break;
341
0
    val = next_val+1;
342
0
  }
343
0
#endif
344
0
  return GF_OK;
345
0
}
346
347
GF_EXPORT
348
GF_Err gf_log_set_tools_levels(const char *val, Bool reset_all)
349
0
{
350
0
#ifndef GPAC_DISABLE_LOG
351
0
  u32 i;
352
0
  if (reset_all) {
353
0
    for (i=0; i<GF_LOG_TOOL_MAX; i++)
354
0
      global_log_tools[i].level = GF_LOG_WARNING;
355
0
  }
356
0
  return gf_log_modify_tools_levels(val);
357
#else
358
  return GF_OK;
359
#endif
360
0
}
361
362
GF_EXPORT
363
char *gf_log_get_tools_levels()
364
0
{
365
0
#ifndef GPAC_DISABLE_LOG
366
0
  u32 i, level, len;
367
0
  char szLogs[GF_MAX_PATH];
368
0
  char szLogTools[GF_MAX_PATH];
369
0
  strcpy(szLogTools, "");
370
371
0
  level = GF_LOG_QUIET;
372
0
  while (level <= GF_LOG_DEBUG) {
373
0
    u32 nb_tools = 0;
374
0
    strcpy(szLogs, "");
375
0
    for (i=0; i<GF_LOG_TOOL_MAX; i++) {
376
0
      if (global_log_tools[i].level == level) {
377
0
        strcat(szLogs, global_log_tools[i].name);
378
0
        strcat(szLogs, ":");
379
0
        nb_tools++;
380
0
      }
381
0
    }
382
0
    if (nb_tools) {
383
0
      char *levelstr = "@warning";
384
0
      if (level==GF_LOG_QUIET) levelstr = "@quiet";
385
0
      else if (level==GF_LOG_ERROR) levelstr = "@error";
386
0
      else if (level==GF_LOG_WARNING) levelstr = "@warning";
387
0
      else if (level==GF_LOG_INFO) levelstr = "@info";
388
0
      else if (level==GF_LOG_DEBUG) levelstr = "@debug";
389
390
0
      if (nb_tools>GF_LOG_TOOL_MAX/2) {
391
0
        strcpy(szLogs, szLogTools);
392
0
        strcpy(szLogTools, "all");
393
0
        strcat(szLogTools, levelstr);
394
0
        if (strlen(szLogs)) {
395
0
          strcat(szLogTools, ":");
396
0
          strcat(szLogTools, szLogs);
397
0
        }
398
0
      } else {
399
0
        if (strlen(szLogTools)) {
400
0
          strcat(szLogTools, ":");
401
0
        }
402
        /*remove last ':' from tool*/
403
0
        szLogs[ strlen(szLogs) - 1 ] = 0;
404
0
        strcat(szLogTools, szLogs);
405
0
        strcat(szLogTools, levelstr);
406
0
      }
407
0
    }
408
0
    level++;
409
0
  }
410
0
  len = (u32) strlen(szLogTools);
411
0
  if (len) {
412
    /*remove last ':' from level*/
413
0
    if (szLogTools[ len-1 ] == ':') szLogTools[ len-1 ] = 0;
414
0
    return gf_strdup(szLogTools);
415
0
  }
416
0
#endif
417
0
  return gf_strdup("all@quiet");
418
0
}
419
420
421
#if defined(GPAC_CONFIG_WIN32) || defined(WIN32)
422
#include <windows.h>
423
#include <wincon.h>
424
static HANDLE console = NULL;
425
static WORD console_attr_ori = 0;
426
static CONSOLE_SCREEN_BUFFER_INFO cbck_console;
427
static CONSOLE_CURSOR_INFO cbck_cursor;
428
static PCHAR_INFO cbck_buffer=NULL;
429
static Bool cbck_stored=GF_FALSE;
430
static Bool is_mintty = GF_FALSE;
431
#endif
432
433
434
435
436
GF_EXPORT
437
void gf_sys_set_console_code(FILE *std, GF_ConsoleCodes code)
438
2.18M
{
439
2.18M
  u32 color_code;
440
441
2.18M
  if (gf_sys_is_test_mode() || gpac_no_color_logs)
442
0
    return;
443
2.18M
  color_code = code & 0xFFFF;
444
#if defined(GPAC_CONFIG_WIN32) || defined(WIN32)
445
  WORD attribs=0;
446
  if (!is_mintty && (console == NULL)) {
447
    CONSOLE_SCREEN_BUFFER_INFO console_info;
448
    const char *shellv = getenv("SHELL");
449
    if (shellv) {
450
      is_mintty = GF_TRUE;
451
      GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Console] Detected MSys/MinGW/Cygwin TTY, will use VT for coloring\n"))
452
    } else {
453
      console = GetStdHandle(STD_ERROR_HANDLE);
454
      if (console != INVALID_HANDLE_VALUE) {
455
        GetConsoleScreenBufferInfo(console, &console_info);
456
        console_attr_ori = console_info.wAttributes;
457
        GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Console] Detected Windows shell, will use SetConsoleTextAttribute for coloring\n"))
458
      }
459
    }
460
  }
461
462
  if (is_mintty) goto win32_ismtty;
463
464
  switch(color_code) {
465
  case GF_CONSOLE_RED:
466
    attribs = FOREGROUND_INTENSITY | FOREGROUND_RED;
467
    break;
468
  case GF_CONSOLE_BLUE:
469
    attribs = FOREGROUND_INTENSITY | FOREGROUND_BLUE;
470
    break;
471
  case GF_CONSOLE_GREEN:
472
    attribs = FOREGROUND_INTENSITY | FOREGROUND_GREEN;
473
    break;
474
  case GF_CONSOLE_YELLOW:
475
    attribs = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN;
476
    break;
477
  case GF_CONSOLE_MAGENTA:
478
    attribs = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE;
479
    break;
480
  case GF_CONSOLE_CYAN:
481
    attribs = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE;
482
    break;
483
  case GF_CONSOLE_WHITE:
484
    attribs = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
485
    break;
486
487
  case GF_CONSOLE_SAVE:
488
    if (!cbck_stored) {
489
      u32 size, line, line_incr;
490
      COORD pos;
491
      BOOL res;
492
      SMALL_RECT region;
493
494
      res = GetConsoleScreenBufferInfo(console, &cbck_console);
495
      if (res) res = GetConsoleCursorInfo(console, &cbck_cursor);
496
497
      if (!res) {
498
        GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to save win32 console info\n"));
499
        return;
500
      }
501
      size = cbck_console.dwSize.X * cbck_console.dwSize.Y;
502
      cbck_buffer = (PCHAR_INFO) gf_malloc(size * sizeof(CHAR_INFO));
503
      pos.X = 0;
504
      region.Left = 0;
505
      region.Right = cbck_console.dwSize.X - 1;
506
      line_incr = 12000 / cbck_console.dwSize.X;
507
      for (line=0; line < (u32) cbck_console.dwSize.Y; line += line_incr) {
508
        pos.Y = line;
509
        region.Top = line;
510
        region.Bottom = line + line_incr - 1;
511
        if (!ReadConsoleOutput(console, cbck_buffer, cbck_console.dwSize, pos, &region)) {
512
          gf_free(cbck_buffer);
513
          cbck_buffer = NULL;
514
          GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to save win32 console info\n"));
515
          return;
516
        }
517
      }
518
      cbck_stored = GF_TRUE;
519
    }
520
    return;
521
522
  case GF_CONSOLE_RESTORE:
523
    if (cbck_stored) {
524
      COORD pos;
525
      SMALL_RECT region;
526
      BOOL res;
527
      pos.X = pos.Y = 0;
528
      region.Top = region.Left = 0;
529
      region.Bottom = cbck_console.dwSize.Y - 1;
530
      region.Right = cbck_console.dwSize.X - 1;
531
      res = SetConsoleScreenBufferSize(console, cbck_console.dwSize);
532
      if (res) res = SetConsoleWindowInfo(console, TRUE, &cbck_console.srWindow);
533
      if (res) res = SetConsoleCursorPosition(console, cbck_console.dwCursorPosition);
534
      if (res) res = SetConsoleTextAttribute(console, cbck_console.wAttributes);
535
536
      if (!res) {
537
        GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to restore win32 console info\n"));
538
        return;
539
      }
540
      WriteConsoleOutput(console, cbck_buffer, cbck_console.dwSize,
541
        pos, &region);
542
      gf_free(cbck_buffer);
543
      cbck_stored = GF_FALSE;
544
    }
545
    return;
546
547
  case GF_CONSOLE_CLEAR:
548
  {
549
    COORD coords;
550
    DWORD written;
551
    DWORD consolesize;
552
    CONSOLE_SCREEN_BUFFER_INFO console_info;
553
554
    coords.X = coords.Y = 0;
555
    GetConsoleScreenBufferInfo(console, &console_info);
556
    consolesize = console_info.dwSize.X * console_info.dwSize.Y;
557
558
    /* fill space & attribute */
559
    FillConsoleOutputCharacter(console, ' ', consolesize, coords, &written);
560
    FillConsoleOutputAttribute(console, console_info.wAttributes, consolesize, coords, &written);
561
    SetConsoleCursorPosition(console, coords);
562
  }
563
    return;
564
  case GF_CONSOLE_RESET:
565
  default:
566
    attribs = console_attr_ori;
567
  }
568
569
  if ((code & 0xFFFF0000) && !color_code) {
570
    attribs |= COMMON_LVB_UNDERSCORE;
571
  }
572
573
  SetConsoleTextAttribute(console, attribs);
574
  return;
575
576
win32_ismtty:
577
#endif
578
579
580
2.18M
#if !defined(_WIN32_WCE)
581
582
2.18M
  switch(color_code) {
583
377k
  case GF_CONSOLE_RED: fprintf(std, "\x1b[31m"); break;
584
0
  case GF_CONSOLE_BLUE:
585
0
    fprintf(std, "\x1b[34m");
586
0
    break;
587
0
  case GF_CONSOLE_GREEN:
588
0
    fprintf(std, "\x1b[32m");
589
0
    break;
590
713k
  case GF_CONSOLE_YELLOW:
591
713k
    fprintf(std, "\x1b[33m");
592
713k
    break;
593
0
  case GF_CONSOLE_MAGENTA:
594
0
    fprintf(std, "\x1b[35m");
595
0
    break;
596
0
  case GF_CONSOLE_CYAN:
597
0
    fprintf(std, "\x1b[36m");
598
0
    break;
599
0
  case GF_CONSOLE_WHITE:
600
0
    fprintf(std, "\x1b[37m");
601
0
    break;
602
603
0
  case GF_CONSOLE_CLEAR:
604
0
    fprintf(std, "\x1b[2J\x1b[0;0H");
605
0
    return;
606
607
0
  case GF_CONSOLE_SAVE:
608
0
    fprintf(std, "\033[?47h");
609
0
    return;
610
0
  case GF_CONSOLE_RESTORE:
611
0
    fprintf(std, "\033[?47l");
612
0
    fprintf(std, "\x1b[J");
613
0
    return;
614
615
1.09M
  case GF_CONSOLE_RESET:
616
1.09M
  default:
617
1.09M
    if (!code)
618
1.09M
      fprintf(std, "\x1b[0m");
619
2.18M
  }
620
2.18M
  if (code) {
621
1.09M
    if (code & GF_CONSOLE_BOLD) fprintf(std, "\x1b[1m");
622
1.09M
    if (code & GF_CONSOLE_ITALIC) fprintf(std, "\x1b[3m");
623
1.09M
    if (code & GF_CONSOLE_UNDERLINED) fprintf(std, "\x1b[4m");
624
1.09M
    if (code & GF_CONSOLE_STRIKE) fprintf(std, "\x1b[9m");
625
1.09M
  }
626
2.18M
#endif
627
2.18M
}
628
629
#ifndef GPAC_DISABLE_LOG
630
u32 call_lev = 0;
631
u32 call_tool = 0;
632
633
GF_EXPORT
634
Bool gf_log_tool_level_on(GF_LOG_Tool log_tool, GF_LOG_Level log_level)
635
3.76M
{
636
3.76M
  if (log_tool==GF_LOG_TOOL_MAX) return GF_TRUE;
637
3.76M
  if (log_tool>GF_LOG_TOOL_MAX) return GF_FALSE;
638
3.76M
  if (global_log_tools[log_tool].level >= log_level) return GF_TRUE;
639
2.67M
  return GF_FALSE;
640
3.76M
}
641
642
GF_EXPORT
643
const char *gf_log_tool_name(GF_LOG_Tool log_tool)
644
0
{
645
0
  if (log_tool>=GF_LOG_TOOL_MAX) return "unknown";
646
0
  return global_log_tools[log_tool].name;
647
0
}
648
const char *gf_log_level_name(GF_LOG_Level log_level)
649
0
{
650
0
  switch (log_level) {
651
0
  case GF_LOG_DEBUG: return "debug";
652
0
  case GF_LOG_INFO: return "info";
653
0
  case GF_LOG_WARNING: return "warning";
654
0
  case GF_LOG_ERROR: return "error";
655
0
  default: return "unknown";
656
0
  }
657
0
}
658
659
GF_EXPORT
660
u32 gf_log_get_tool_level(GF_LOG_Tool log_tool)
661
0
{
662
0
  if (log_tool>=GF_LOG_TOOL_MAX) return GF_LOG_ERROR;
663
0
  return global_log_tools[log_tool].level;
664
0
}
665
666
FILE *gpac_log_file = NULL;
667
Bool gpac_log_time_start = GF_FALSE;
668
Bool gpac_log_utc_time = GF_FALSE;
669
Bool gpac_log_dual = GF_FALSE;
670
Bool last_log_is_lf = GF_TRUE;
671
static u64 gpac_last_log_time=0;
672
673
static void do_log_time(FILE *logs, const char *fmt)
674
1.09M
{
675
1.09M
  if (!gpac_log_time_start && !gpac_log_utc_time) return;
676
677
0
  if (last_log_is_lf) {
678
0
    if (gpac_log_time_start) {
679
0
      u64 now = gf_sys_clock_high_res();
680
0
      gf_fprintf(logs, "At "LLD" (diff %d) - ", now, (u32) (now - gpac_last_log_time) );
681
0
      gpac_last_log_time = now;
682
0
    }
683
0
    if (gpac_log_utc_time) {
684
0
      u64 utc_clock = gf_net_get_utc() ;
685
0
      time_t secs = utc_clock/1000;
686
0
      struct tm t;
687
0
      t = *gf_gmtime(&secs);
688
0
      gf_fprintf(logs, "UTC %d-%02d-%02dT%02d:%02d:%02dZ (TS "LLU") - ", 1900+t.tm_year, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, utc_clock);
689
0
    }
690
0
  }
691
0
  u32 flen = (u32) strlen(fmt);
692
0
  if (flen && fmt[flen-1] == '\n') last_log_is_lf = GF_TRUE;
693
0
  else last_log_is_lf = GF_FALSE;
694
0
}
695
696
int gf_fileio_printf(GF_FileIO *gfio, const char *format, va_list args);
697
698
void default_log_callback(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist)
699
0
{
700
0
  FILE *logs = gpac_log_file ? gpac_log_file : stderr;
701
0
  if (tool != GF_LOG_APP)
702
0
    do_log_time(logs, fmt);
703
704
0
  if (gf_fileio_check(logs)) {
705
0
    gf_fileio_printf((GF_FileIO *)logs, fmt, vlist);
706
0
  } else {
707
0
    if (gpac_log_dual && gpac_no_color_logs) {
708
0
      va_list vlist_c;
709
0
      va_copy(vlist_c, vlist);
710
0
      vfprintf(stderr, fmt, vlist_c);
711
0
      va_end(vlist_c);
712
0
    }
713
0
    vfprintf(logs, fmt, vlist);
714
0
  }
715
0
  gf_fflush(logs);
716
0
}
717
718
void default_log_callback_color(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist)
719
1.09M
{
720
1.09M
  if (gpac_log_file) {
721
0
    if (!gpac_log_dual) {
722
0
      default_log_callback(cbck, level, tool, fmt, vlist);
723
0
      return;
724
0
    }
725
0
    va_list vlist_c;
726
0
    va_copy(vlist_c, vlist);
727
0
    default_log_callback(cbck, level, tool, fmt, vlist_c);
728
0
    va_end(vlist_c);
729
0
  }
730
1.09M
  switch(level) {
731
377k
  case GF_LOG_ERROR:
732
377k
    gf_sys_set_console_code(stderr, GF_CONSOLE_RED);
733
377k
    break;
734
713k
  case GF_LOG_WARNING:
735
713k
    gf_sys_set_console_code(stderr, GF_CONSOLE_YELLOW);
736
713k
    break;
737
0
  case GF_LOG_INFO:
738
0
    gf_sys_set_console_code(stderr, (tool==GF_LOG_APP) ? GF_CONSOLE_WHITE : GF_CONSOLE_GREEN);
739
0
    break;
740
0
  case GF_LOG_DEBUG:
741
0
    gf_sys_set_console_code(stderr, GF_CONSOLE_CYAN);
742
0
    break;
743
0
  default:
744
0
    gf_sys_set_console_code(stderr, GF_CONSOLE_WHITE);
745
0
    break;
746
1.09M
  }
747
1.09M
  if (tool != GF_LOG_APP)
748
1.09M
    do_log_time(stderr, fmt);
749
750
1.09M
  vfprintf(stderr, fmt, vlist);
751
1.09M
  gf_sys_set_console_code(stderr, GF_CONSOLE_RESET);
752
1.09M
  gf_fflush(stderr);
753
1.09M
}
754
755
756
757
static void *user_log_cbk = NULL;
758
gf_log_cbk log_cbk = default_log_callback_color;
759
static Bool log_exit_on_error = GF_FALSE;
760
extern GF_Mutex *logs_mx;
761
762
GF_EXPORT
763
Bool gf_log_use_color()
764
0
{
765
0
  return (log_cbk == default_log_callback_color) ? GF_TRUE : GF_FALSE;
766
0
}
767
768
GF_EXPORT
769
void gf_log(const char *fmt, ...)
770
1.09M
{
771
1.09M
  va_list vl;
772
1.09M
  va_start(vl, fmt);
773
1.09M
  gf_mx_p(logs_mx);
774
1.09M
  log_cbk(user_log_cbk, call_lev, call_tool, fmt, vl);
775
1.09M
  gf_mx_v(logs_mx);
776
1.09M
  va_end(vl);
777
1.09M
  if (log_exit_on_error && (call_lev==GF_LOG_ERROR) && (call_tool != GF_LOG_MEMORY)) {
778
0
    exit(1);
779
0
  }
780
1.09M
}
781
782
GF_EXPORT
783
void gf_log_va_list(GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vl)
784
0
{
785
0
  log_cbk(user_log_cbk, call_lev, call_tool, fmt, vl);
786
0
  if (log_exit_on_error && (call_lev==GF_LOG_ERROR) && (call_tool != GF_LOG_MEMORY)) {
787
0
    exit(1);
788
0
  }
789
0
}
790
791
GF_EXPORT
792
Bool gf_log_set_strict_error(Bool strict)
793
0
{
794
0
  Bool old = log_exit_on_error;
795
0
  log_exit_on_error = strict;
796
0
  return old;
797
0
}
798
799
GF_EXPORT
800
void gf_log_set_tool_level(GF_LOG_Tool tool, GF_LOG_Level level)
801
0
{
802
0
  assert(tool<=GF_LOG_TOOL_MAX);
803
0
  if (tool==GF_LOG_ALL) {
804
0
    u32 i;
805
0
    for (i=0; i<GF_LOG_TOOL_MAX; i++) {
806
0
      global_log_tools[i].level = level;
807
0
    }
808
0
  } else {
809
0
    global_log_tools[tool].level = level;
810
0
  }
811
0
}
812
813
GF_EXPORT
814
void gf_log_lt(GF_LOG_Level ll, GF_LOG_Tool lt)
815
1.09M
{
816
1.09M
  call_lev = ll;
817
1.09M
  call_tool = lt;
818
1.09M
}
819
820
GF_EXPORT
821
gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
822
0
{
823
0
  gf_log_cbk prev_cbk = log_cbk;
824
0
  log_cbk = cbk;
825
0
  if (!log_cbk) log_cbk = default_log_callback;
826
0
  if (usr_cbk) user_log_cbk = usr_cbk;
827
0
  return prev_cbk;
828
0
}
829
830
#else
831
GF_EXPORT
832
void gf_log(const char *fmt, ...)
833
{
834
}
835
GF_EXPORT
836
void gf_log_lt(GF_LOG_Level ll, GF_LOG_Tool lt)
837
{
838
}
839
840
Bool log_exit_on_error=GF_FALSE;
841
GF_EXPORT
842
Bool gf_log_set_strict_error(Bool strict)
843
{
844
  Bool old = log_exit_on_error;
845
  log_exit_on_error = strict;
846
  return old;
847
}
848
849
GF_EXPORT
850
void gf_log_check_error(GF_LOG_Level loglev, GF_LOG_Tool logtool)
851
{
852
  if (log_exit_on_error && (loglev==GF_LOG_ERROR) && (logtool != GF_LOG_MEMORY)) {
853
    exit(1);
854
  }
855
}
856
857
GF_EXPORT
858
gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
859
{
860
  return NULL;
861
}
862
863
GF_EXPORT
864
void gf_log_set_tool_level(GF_LOG_Tool tool, GF_LOG_Level level)
865
{
866
}
867
868
GF_EXPORT
869
u32 gf_log_get_tool_level(GF_LOG_Tool log_tool)
870
{
871
  return 0;
872
}
873
874
GF_EXPORT
875
Bool gf_log_tool_level_on(GF_LOG_Tool log_tool, GF_LOG_Level log_level)
876
{
877
  return GF_FALSE;
878
}
879
880
#endif
881
882
static char szErrMsg[50];
883
884
GF_EXPORT
885
const char *gf_error_to_string(GF_Err e)
886
123k
{
887
123k
  switch (e) {
888
0
  case GF_EOS:
889
0
    return "End Of Stream / File";
890
0
  case GF_OK:
891
0
    return "No Error";
892
893
  /*General errors */
894
5.49k
  case GF_BAD_PARAM:
895
5.49k
    return "Bad Parameter";
896
0
  case GF_OUT_OF_MEM:
897
0
    return "Out Of Memory";
898
0
  case GF_IO_ERR:
899
0
    return "I/O Error";
900
94
  case GF_NOT_SUPPORTED:
901
94
    return "Feature Not Supported";
902
0
  case GF_CORRUPTED_DATA:
903
0
    return "Corrupted Data in file/stream";
904
905
  /*File Format Errors */
906
36.0k
  case GF_ISOM_INVALID_FILE:
907
36.0k
    return "Invalid IsoMedia File";
908
0
  case GF_ISOM_INCOMPLETE_FILE:
909
0
    return "IsoMedia File is truncated";
910
52.6k
  case GF_ISOM_INVALID_MEDIA:
911
52.6k
    return "Invalid IsoMedia Media";
912
0
  case GF_ISOM_INVALID_MODE:
913
0
    return "Invalid Mode while accessing the file";
914
0
  case GF_ISOM_UNKNOWN_DATA_REF:
915
0
    return "Media Data Reference not found";
916
917
  /*Object Descriptor Errors */
918
26.5k
  case GF_ODF_INVALID_DESCRIPTOR:
919
26.5k
    return "Invalid MPEG-4 Descriptor";
920
2.00k
  case GF_ODF_FORBIDDEN_DESCRIPTOR:
921
2.00k
    return "MPEG-4 Descriptor Not Allowed";
922
0
  case GF_ODF_INVALID_COMMAND:
923
0
    return "Read OD Command Failed";
924
925
  /*BIFS Errors */
926
0
  case GF_SG_UNKNOWN_NODE:
927
0
    return "Unknown BIFS Node";
928
0
  case GF_SG_INVALID_PROTO:
929
0
    return "Invalid Proto Interface";
930
0
  case GF_BIFS_UNKNOWN_VERSION:
931
0
    return "Invalid BIFS version";
932
0
  case GF_SCRIPT_ERROR:
933
0
    return "Invalid Script";
934
935
0
  case GF_BUFFER_TOO_SMALL:
936
0
    return "Bad Buffer size (too small)";
937
1.03k
  case GF_NON_COMPLIANT_BITSTREAM:
938
1.03k
    return "BitStream Not Compliant";
939
0
  case GF_FILTER_NOT_FOUND:
940
0
    return "Filter not found for the desired type";
941
942
0
  case GF_URL_ERROR:
943
0
    return "Requested URL is not valid or cannot be found";
944
0
  case GF_URL_REMOVED:
945
0
    return "Requested URL is no longer available";
946
947
0
  case GF_SERVICE_ERROR:
948
0
    return "Internal Service Error";
949
0
  case GF_REMOTE_SERVICE_ERROR:
950
0
    return "Dialog Failure with remote peer";
951
952
0
  case GF_STREAM_NOT_FOUND:
953
0
    return "Media Channel couldn't be found";
954
955
0
  case GF_IP_ADDRESS_NOT_FOUND:
956
0
    return "IP Address Not Found";
957
0
  case GF_IP_CONNECTION_FAILURE:
958
0
    return "IP Connection Failed";
959
0
  case GF_IP_NETWORK_FAILURE:
960
0
    return "Network Unreachable";
961
962
0
  case GF_IP_NETWORK_EMPTY:
963
0
    return "Network Empty";
964
0
  case GF_IP_CONNECTION_CLOSED:
965
0
    return "Connection to server closed";
966
0
  case GF_IP_UDP_TIMEOUT:
967
0
    return "UDP traffic timeout";
968
0
  case GF_AUTHENTICATION_FAILURE:
969
0
    return "Authentication failure";
970
0
  case GF_NOT_READY:
971
0
    return "Not ready, retry later";
972
0
  case GF_INVALID_CONFIGURATION:
973
0
    return "Bad configuration for the current context";
974
0
  case GF_NOT_FOUND:
975
0
    return "At least one required element has not been found";
976
0
  case GF_PROFILE_NOT_SUPPORTED:
977
0
    return "Unsupported codec profile";
978
0
  case GF_REQUIRES_NEW_INSTANCE:
979
0
    return "Requires a new instance of the filter to be supported";
980
0
  case GF_FILTER_NOT_SUPPORTED:
981
0
    return "Not supported by any filter chain";
982
0
  default:
983
0
    sprintf(szErrMsg, "Unknown Error (%d)", e);
984
0
    return szErrMsg;
985
123k
  }
986
123k
}
987
988
static const u32 gf_crc_table[256] = {
989
  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
990
  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
991
  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
992
  0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
993
  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
994
  0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
995
  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
996
  0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
997
  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
998
  0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
999
  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
1000
  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1001
  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
1002
  0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1003
  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
1004
  0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1005
  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
1006
  0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1007
  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
1008
  0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1009
  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
1010
  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1011
  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
1012
  0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1013
  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
1014
  0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1015
  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
1016
  0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1017
  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
1018
  0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1019
  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
1020
  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1021
  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
1022
  0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1023
  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
1024
  0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1025
  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
1026
  0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1027
  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
1028
  0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1029
  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
1030
  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1031
  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1032
};
1033
1034
GF_EXPORT
1035
u32 gf_crc_32(const u8 *data, u32 len)
1036
0
{
1037
0
  register u32 i;
1038
0
  u32 crc = 0xffffffff;
1039
0
  if (!data) return 0;
1040
0
  for (i=0; i<len; i++)
1041
0
    crc = (crc << 8) ^ gf_crc_table[((crc >> 24) ^ *data++) & 0xff];
1042
1043
0
  return crc;
1044
0
}
1045
1046
1047
#define CHECK_MAC(_a) "#_a :" ? (_a) ? "yes":"no"
1048
1049
static const char *gf_enabled_features()
1050
0
{
1051
0
  const char *features = ""
1052
#ifdef GPAC_CONFIG_WIN32
1053
                         "GPAC_CONFIG_WIN32 "
1054
#endif
1055
#ifdef GPAC_CONFIG_DARWIN
1056
                         "GPAC_CONFIG_DARWIN "
1057
#endif
1058
0
#ifdef GPAC_CONFIG_LINUX
1059
0
                         "GPAC_CONFIG_LINUX "
1060
0
#endif
1061
#ifdef GPAC_CONFIG_ANDROID
1062
                         "GPAC_CONFIG_ANDROID "
1063
#endif
1064
#ifdef GPAC_CONFIG_IOS
1065
                         "GPAC_CONFIG_IOS "
1066
#endif
1067
#ifdef GPAC_CONFIG_EMSCRIPTEN
1068
                         "GPAC_CONFIG_EMSCRIPTEN "
1069
#endif
1070
0
#ifdef GPAC_64_BITS
1071
0
                         "GPAC_64_BITS "
1072
0
#endif
1073
#ifdef GPAC_FIXED_POINT
1074
                         "GPAC_FIXED_POINT "
1075
#endif
1076
#ifdef GPAC_MEMORY_TRACKING
1077
                         "GPAC_MEMORY_TRACKING "
1078
#endif
1079
#ifdef GPAC_BIG_ENDIAN
1080
                         "GPAC_BIG_ENDIAN "
1081
#endif
1082
0
#ifdef GPAC_HAS_IPV6
1083
0
                         "GPAC_HAS_IPV6 "
1084
0
#endif
1085
0
#ifdef GPAC_HAS_SSL
1086
0
                         "GPAC_HAS_SSL "
1087
0
#endif
1088
0
#ifdef GPAC_HAS_SOCK_UN
1089
0
                         "GPAC_HAS_SOCK_UN "
1090
0
#endif
1091
#ifdef GPAC_ENABLE_COVERAGE
1092
                         "GPAC_ENABLE_COVERAGE "
1093
#endif
1094
0
#ifdef GPAC_MINIMAL_ODF
1095
0
                         "GPAC_MINIMAL_ODF "
1096
0
#endif
1097
0
#ifdef GPAC_HAS_QJS
1098
0
                         "GPAC_HAS_QJS "
1099
0
#endif
1100
#ifdef GPAC_HAS_FREETYPE
1101
                         "GPAC_HAS_FREETYPE "
1102
#endif
1103
#ifdef GPAC_HAS_FAAD
1104
                         "GPAC_HAS_FAAD "
1105
#endif
1106
#ifdef GPAC_HAS_MAD
1107
                         "GPAC_HAS_MAD "
1108
#endif
1109
#ifdef GPAC_HAS_LIBA52
1110
                         "GPAC_HAS_LIBA52 "
1111
#endif
1112
#ifdef GPAC_HAS_JPEG
1113
                         "GPAC_HAS_JPEG "
1114
#endif
1115
#ifdef GPAC_HAS_PNG
1116
                         "GPAC_HAS_PNG "
1117
#endif
1118
#ifdef GPAC_HAS_FFMPEG
1119
                         "GPAC_HAS_FFMPEG "
1120
#endif
1121
#ifdef GPAC_HAS_OPENSVC
1122
                         "GPAC_HAS_OPENSVC "
1123
#endif
1124
#ifdef GPAC_HAS_JP2
1125
                         "GPAC_HAS_JP2 "
1126
#endif
1127
#ifdef GPAC_HAS_OPENHEVC
1128
                         "GPAC_HAS_OPENHEVC "
1129
#endif
1130
#ifdef GPAC_HAS_THEORA
1131
                         "GPAC_HAS_THEORA "
1132
#endif
1133
#ifdef GPAC_HAS_VORBIS
1134
                         "GPAC_HAS_VORBIS "
1135
#endif
1136
#ifdef GPAC_HAS_XVID
1137
                         "GPAC_HAS_XVID "
1138
#endif
1139
0
#ifdef GPAC_HAS_LINUX_DVB
1140
0
                         "GPAC_HAS_LINUX_DVB "
1141
0
#endif
1142
#ifdef GPAC_HAS_GLU
1143
                         "GPAC_HAS_GLU "
1144
#endif
1145
#ifdef GPAC_USE_TINYGL
1146
                         "GPAC_USE_TINYGL "
1147
#endif
1148
#ifdef GPAC_USE_GLES1X
1149
                         "GPAC_USE_GLES1X "
1150
#endif
1151
#ifdef GPAC_USE_GLES2
1152
                         "GPAC_USE_GLES2 "
1153
#endif
1154
#ifdef GPAC_HAS_HTTP2
1155
                         "GPAC_HAS_HTTP2 "
1156
#endif
1157
1158
#if defined(_WIN32_WCE)
1159
#ifdef GPAC_USE_IGPP
1160
                         "GPAC_USE_IGPP "
1161
#endif
1162
#ifdef GPAC_USE_IGPP_HP
1163
                         "GPAC_USE_IGPP_HP "
1164
#endif
1165
#endif
1166
0
                         ;
1167
0
  return features;
1168
0
}
1169
1170
static const char *gf_disabled_features()
1171
0
{
1172
0
  const char *features = ""
1173
0
#ifdef GPAC_DISABLE_3D
1174
0
                         "GPAC_DISABLE_3D "
1175
0
#endif
1176
#ifdef GPAC_DISABLE_DOC
1177
                         "GPAC_DISABLE_DOC "
1178
#endif
1179
#ifdef GPAC_DISABLE_ZLIB
1180
                         "GPAC_DISABLE_ZLIB "
1181
#endif
1182
#ifdef GPAC_DISABLE_THREADS
1183
                         "GPAC_DISABLE_THREADS "
1184
#endif
1185
#ifdef GPAC_DISABLE_NETWORK
1186
                         "GPAC_DISABLE_NETWORK "
1187
#endif
1188
#ifdef GPAC_DISABLE_STREAMING
1189
                         "GPAC_DISABLE_STREAMING "
1190
#endif
1191
#ifdef GPAC_DISABLE_ROUTE
1192
                         "GPAC_DISABLE_ROUTE "
1193
#endif
1194
#ifdef GPAC_DISABLE_EVG
1195
                         "GPAC_DISABLE_EVG "
1196
#endif
1197
#ifdef GPAC_DISABLE_AVILIB
1198
                         "GPAC_DISABLE_AVILIB "
1199
#endif
1200
#ifdef GPAC_DISABLE_OGG
1201
                         "GPAC_DISABLE_OGG "
1202
#endif
1203
#ifdef GPAC_DISABLE_AV_PARSERS
1204
                         "GPAC_DISABLE_AV_PARSERS "
1205
#endif
1206
#ifdef GPAC_DISABLE_MPEG2PS
1207
                         "GPAC_DISABLE_MPEG2PS "
1208
#endif
1209
#ifdef GPAC_DISABLE_MPEG2PS
1210
                         "GPAC_DISABLE_MPEG2TS "
1211
#endif
1212
#ifdef GPAC_DISABLE_MEDIA_IMPORT
1213
                         "GPAC_DISABLE_MEDIA_IMPORT "
1214
#endif
1215
#ifdef GPAC_DISABLE_MEDIA_EXPORT
1216
                         "GPAC_DISABLE_MEDIA_EXPORT "
1217
#endif
1218
#ifdef GPAC_DISABLE_VRML
1219
                         "GPAC_DISABLE_VRML "
1220
#endif
1221
#ifdef GPAC_DISABLE_SVG
1222
                         "GPAC_DISABLE_SVG "
1223
#endif
1224
#ifdef GPAC_DISABLE_QTVR
1225
                         "GPAC_DISABLE_QTVR "
1226
#endif
1227
#ifdef GPAC_DISABLE_SWF_IMPORT
1228
                         "GPAC_DISABLE_SWF_IMPORT "
1229
#endif
1230
#ifdef GPAC_DISABLE_SCENE_STATS
1231
                         "GPAC_DISABLE_SCENE_STATS "
1232
#endif
1233
#ifdef GPAC_DISABLE_SCENE_DUMP
1234
                         "GPAC_DISABLE_SCENE_DUMP "
1235
#endif
1236
#ifdef GPAC_DISABLE_BIFS
1237
                         "GPAC_DISABLE_BIFS "
1238
#endif
1239
#ifdef GPAC_DISABLE_LASER
1240
                         "GPAC_DISABLE_LASER "
1241
#endif
1242
#ifdef GPAC_DISABLE_SENG
1243
                         "GPAC_DISABLE_SENG "
1244
#endif
1245
#ifdef GPAC_DISABLE_SCENE_ENCODER
1246
                         "GPAC_DISABLE_SCENE_ENCODER "
1247
#endif
1248
#ifdef GPAC_DISABLE_LOADER_ISOM
1249
                         "GPAC_DISABLE_LOADER_ISOM "
1250
#endif
1251
#ifdef GPAC_DISABLE_OD_DUMP
1252
                         "GPAC_DISABLE_OD_DUMP "
1253
#endif
1254
#ifdef GPAC_DISABLE_CRYPTO
1255
                         "GPAC_DISABLE_CRYPTO "
1256
#endif
1257
#ifdef GPAC_DISABLE_ISOM
1258
                         "GPAC_DISABLE_CRYPTO "
1259
#endif
1260
#ifdef GPAC_DISABLE_ISOM_HINTING
1261
                         "GPAC_DISABLE_ISOM_HINTING "
1262
#endif
1263
#ifdef GPAC_DISABLE_ISOM_WRITE
1264
                         "GPAC_DISABLE_ISOM_WRITE "
1265
#endif
1266
#ifdef GPAC_DISABLE_ISOM_FRAGMENTS
1267
                         "GPAC_DISABLE_ISOM_FRAGMENTS "
1268
#endif
1269
#ifdef GPAC_DISABLE_ISOM_DUMP
1270
                         "GPAC_DISABLE_ISOM_DUMP "
1271
#endif
1272
#ifdef GPAC_DISABLE_NETCAP
1273
                         "GPAC_DISABLE_NETCAP "
1274
#endif
1275
1276
#ifdef GPAC_DISABLE_COMPOSITOR
1277
                         "GPAC_DISABLE_COMPOSITOR "
1278
#endif
1279
#ifdef GPAC_DISABLE_FONTS
1280
                         "GPAC_DISABLE_FONTS "
1281
#endif
1282
#ifdef GPAC_DISABLE_VOUT
1283
                         "GPAC_DISABLE_VOUT "
1284
#endif
1285
#ifdef GPAC_DISABLE_AOUT
1286
                         "GPAC_DISABLE_AOUT "
1287
#endif
1288
#ifdef GPAC_DISABLE_BSAGG
1289
                         "GPAC_DISABLE_BSAGG "
1290
#endif
1291
#ifdef GPAC_DISABLE_BSSPLIT
1292
                         "GPAC_DISABLE_BSSPLIT "
1293
#endif
1294
#ifdef GPAC_DISABLE_BSRW
1295
                         "GPAC_DISABLE_BSRW "
1296
#endif
1297
#ifdef GPAC_DISABLE_DASHER
1298
                         "GPAC_DISABLE_DASHER "
1299
#endif
1300
#ifdef GPAC_DISABLE_DASHIN
1301
                         "GPAC_DISABLE_DASHIN "
1302
#endif
1303
#ifdef GPAC_DISABLE_IMGDEC
1304
                         "GPAC_DISABLE_IMGDEC "
1305
#endif
1306
#ifdef GPAC_DISABLE_UNCVDEC
1307
                         "GPAC_DISABLE_UNCVDEC "
1308
#endif
1309
#ifdef GPAC_DISABLE_CDCRYPT
1310
                         "GPAC_DISABLE_CDCRYPT "
1311
#endif
1312
#ifdef GPAC_DISABLE_GHIDMX
1313
                         "GPAC_DISABLE_GHIDMX "
1314
#endif
1315
#ifdef GPAC_DISABLE_GSFDMX
1316
                         "GPAC_DISABLE_GSFDMX "
1317
#endif
1318
#ifdef GPAC_DISABLE_NHMLR
1319
                         "GPAC_DISABLE_NHMLR "
1320
#endif
1321
#ifdef GPAC_DISABLE_NHNTR
1322
                         "GPAC_DISABLE_NHNTR "
1323
#endif
1324
#ifdef GPAC_DISABLE_CECRYPT
1325
                         "GPAC_DISABLE_CECRYPT "
1326
#endif
1327
#ifdef GPAC_DISABLE_FLIST
1328
                         "GPAC_DISABLE_FLIST "
1329
#endif
1330
#ifdef GPAC_DISABLE_HEVCMERGE
1331
                         "GPAC_DISABLE_HEVCMERGE "
1332
#endif
1333
#ifdef GPAC_DISABLE_HEVCSPLIT
1334
                         "GPAC_DISABLE_HEVCSPLIT "
1335
#endif
1336
#ifdef GPAC_DISABLE_FIN
1337
                         "GPAC_DISABLE_FIN "
1338
#endif
1339
#ifdef GPAC_DISABLE_PIN
1340
                         "GPAC_DISABLE_PIN "
1341
#endif
1342
#ifdef GPAC_DISABLE_INSPECT
1343
                         "GPAC_DISABLE_INSPECT "
1344
#endif
1345
#ifdef GPAC_DISABLE_CRYPTFILE
1346
                         "GPAC_DISABLE_CRYPTFILE "
1347
#endif
1348
#ifdef GPAC_DISABLE_MP4DMX
1349
                         "GPAC_DISABLE_MP4DMX "
1350
#endif
1351
#ifdef GPAC_DISABLE_TXTIN
1352
                         "GPAC_DISABLE_TXTIN "
1353
#endif
1354
#ifdef GPAC_DISABLE_GSFMX
1355
                         "GPAC_DISABLE_GSFMX "
1356
#endif
1357
#ifdef GPAC_DISABLE_MP4MX
1358
                         "GPAC_DISABLE_MP4MX "
1359
#endif
1360
#ifdef GPAC_DISABLE_FOUT
1361
                         "GPAC_DISABLE_FOUT "
1362
#endif
1363
#ifdef GPAC_DISABLE_POUT
1364
                         "GPAC_DISABLE_POUT "
1365
#endif
1366
#ifdef GPAC_DISABLE_RFAC3
1367
                         "GPAC_DISABLE_RFAC3 "
1368
#endif
1369
#ifdef GPAC_DISABLE_RFADTS
1370
                         "GPAC_DISABLE_RFADTS "
1371
#endif
1372
#ifdef GPAC_DISABLE_RFAMR
1373
                         "GPAC_DISABLE_RFAMR "
1374
#endif
1375
#ifdef GPAC_DISABLE_RFAV1
1376
                         "GPAC_DISABLE_RFAV1 "
1377
#endif
1378
#ifdef GPAC_DISABLE_RFFLAC
1379
                         "GPAC_DISABLE_RFFLAC "
1380
#endif
1381
#ifdef GPAC_DISABLE_RFH263
1382
                         "GPAC_DISABLE_RFH263 "
1383
#endif
1384
#ifdef GPAC_DISABLE_RFIMG
1385
                         "GPAC_DISABLE_RFIMG "
1386
#endif
1387
#ifdef GPAC_DISABLE_RFLATM
1388
                         "GPAC_DISABLE_RFLATM "
1389
#endif
1390
#ifdef GPAC_DISABLE_RFMHAS
1391
                         "GPAC_DISABLE_RFMHAS "
1392
#endif
1393
#ifdef GPAC_DISABLE_RFMP3
1394
                         "GPAC_DISABLE_RFMP3 "
1395
#endif
1396
#ifdef GPAC_DISABLE_RFMPGVID
1397
                         "GPAC_DISABLE_RFMPGVID "
1398
#endif
1399
#ifdef GPAC_DISABLE_RFNALU
1400
                         "GPAC_DISABLE_RFNALU "
1401
#endif
1402
#ifdef GPAC_DISABLE_RFPRORES
1403
                         "GPAC_DISABLE_RFPRORES "
1404
#endif
1405
#ifdef GPAC_DISABLE_RFQCP
1406
                         "GPAC_DISABLE_RFQCP "
1407
#endif
1408
#ifdef GPAC_DISABLE_RFPCM
1409
                         "GPAC_DISABLE_RFPCM "
1410
#endif
1411
#ifdef GPAC_DISABLE_RFRAWVID
1412
                         "GPAC_DISABLE_RFRAWVID "
1413
#endif
1414
#ifdef GPAC_DISABLE_RFTRUEHD
1415
                         "GPAC_DISABLE_RFTRUEHD "
1416
#endif
1417
#ifdef GPAC_DISABLE_REFRAMER
1418
                         "GPAC_DISABLE_REFRAMER "
1419
#endif
1420
#ifdef GPAC_DISABLE_RESAMPLE
1421
                         "GPAC_DISABLE_RESAMPLE "
1422
#endif
1423
#ifdef GPAC_DISABLE_RESTAMP
1424
                         "GPAC_DISABLE_RESTAMP "
1425
#endif
1426
#ifdef GPAC_DISABLE_REWIND
1427
                         "GPAC_DISABLE_REWIND "
1428
#endif
1429
#ifdef GPAC_DISABLE_UFAAC
1430
                         "GPAC_DISABLE_UFAAC "
1431
#endif
1432
#ifdef GPAC_DISABLE_UFMHAS
1433
                         "GPAC_DISABLE_UFMHAS "
1434
#endif
1435
#ifdef GPAC_DISABLE_UFM4V
1436
                         "GPAC_DISABLE_UFM4V "
1437
#endif
1438
#ifdef GPAC_DISABLE_UFNALU
1439
                         "GPAC_DISABLE_UFNALU "
1440
#endif
1441
#ifdef GPAC_DISABLE_UFOBU
1442
                         "GPAC_DISABLE_UFOBU "
1443
#endif
1444
#ifdef GPAC_DISABLE_TILEAGG
1445
                         "GPAC_DISABLE_TILEAGG "
1446
#endif
1447
#ifdef GPAC_DISABLE_TILESPLIT
1448
                         "GPAC_DISABLE_TILESPLIT "
1449
#endif
1450
#ifdef GPAC_DISABLE_TTMLCONV
1451
                         "GPAC_DISABLE_TTMLCONV "
1452
#endif
1453
#ifdef GPAC_DISABLE_UNFRAMER
1454
                         "GPAC_DISABLE_UNFRAMER "
1455
#endif
1456
#ifdef GPAC_DISABLE_VCROP
1457
                         "GPAC_DISABLE_VCROP "
1458
#endif
1459
#ifdef GPAC_DISABLE_VFLIP
1460
                         "GPAC_DISABLE_VFLIP "
1461
#endif
1462
#ifdef GPAC_DISABLE_WRITEGEN
1463
                         "GPAC_DISABLE_WRITEGEN "
1464
#endif
1465
#ifdef GPAC_DISABLE_NHMLW
1466
                         "GPAC_DISABLE_NHMLW "
1467
#endif
1468
#ifdef GPAC_DISABLE_NHNTW
1469
                         "GPAC_DISABLE_NHNTW "
1470
#endif
1471
#ifdef GPAC_DISABLE_WRITEQCP
1472
                         "GPAC_DISABLE_WRITEQCP "
1473
#endif
1474
#ifdef GPAC_DISABLE_UNITS
1475
                         "GPAC_DISABLE_UNITS "
1476
#endif
1477
#ifdef GPAC_DISABLE_NVDEC
1478
                         "GPAC_DISABLE_NVDEC "
1479
#endif
1480
#ifdef GPAC_DISABLE_VTBDEC
1481
                         "GPAC_DISABLE_VTBDEC "
1482
#endif
1483
0
                         ;
1484
0
  return features;
1485
0
}
1486
1487
GF_EXPORT
1488
const char *gf_sys_features(Bool disabled)
1489
0
{
1490
0
  if (disabled)
1491
0
    return gf_disabled_features();
1492
0
  else
1493
0
    return gf_enabled_features();
1494
0
}
1495
1496
static const struct lang_def {
1497
  const char *name;
1498
  const char *three_char_code;
1499
  const char *two_char_code;
1500
} defined_languages [] =
1501
{
1502
  { "Abkhazian","abk","ab"} ,
1503
  { "Achinese","ace",""} ,
1504
  { "Acoli","ach",""} ,
1505
  { "Adangme","ada",""} ,
1506
  { "Adyghe; Adygei","ady",""} ,
1507
  { "Afar","aar","aa"} ,
1508
  { "Afrihili","afh",""} ,
1509
  { "Afrikaans","afr","af"} ,
1510
  { "Afro-Asiatic languages","afa",""} ,
1511
  { "Ainu","ain",""} ,
1512
  { "Akan","aka","ak"} ,
1513
  { "Akkadian","akk",""} ,
1514
  { "Albanian","sqi","sq"} ,
1515
  { "Aleut","ale",""} ,
1516
  { "Algonquian languages","alg",""} ,
1517
  { "Altaic languages","tut",""} ,
1518
  { "Amharic","amh","am"} ,
1519
  { "Angika","anp",""} ,
1520
  { "Apache languages","apa",""} ,
1521
  { "Arabic","ara","ar"} ,
1522
  { "Aragonese","arg","an"} ,
1523
  { "Arapaho","arp",""} ,
1524
  { "Arawak","arw",""} ,
1525
  { "Armenian","hye","hy"} ,
1526
  { "Aromanian; Arumanian; Macedo-Romanian","rup",""} ,
1527
  { "Artificial languages","art",""} ,
1528
  { "Assamese","asm","as"} ,
1529
  { "Asturian; Bable; Leonese; Asturleonese","ast",""} ,
1530
  { "Athapascan languages","ath",""} ,
1531
  { "Australian languages","aus",""} ,
1532
  { "Austronesian languages","map",""} ,
1533
  { "Avaric","ava","av"} ,
1534
  { "Avestan","ave","ae"} ,
1535
  { "Awadhi","awa",""} ,
1536
  { "Aymara","aym","ay"} ,
1537
  { "Azerbaijani","aze","az"} ,
1538
  { "Balinese","ban",""} ,
1539
  { "Baltic languages","bat",""} ,
1540
  { "Baluchi","bal",""} ,
1541
  { "Bambara","bam","bm"} ,
1542
  { "Bamileke languages","bai",""} ,
1543
  { "Banda languages","bad",""} ,
1544
  { "Bantu languages","bnt",""} ,
1545
  { "Basa","bas",""} ,
1546
  { "Bashkir","bak","ba"} ,
1547
  { "Basque","eus","eu"} ,
1548
  { "Batak languages","btk",""} ,
1549
  { "Beja; Bedawiyet","bej",""} ,
1550
  { "Belarusian","bel","be"} ,
1551
  { "Bemba","bem",""} ,
1552
  { "Bengali","ben","bn"} ,
1553
  { "Berber languages","ber",""} ,
1554
  { "Bhojpuri","bho",""} ,
1555
  { "Bihari languages","bih","bh"} ,
1556
  { "Bikol","bik",""} ,
1557
  { "Bini; Edo","bin",""} ,
1558
  { "Bislama","bis","bi"} ,
1559
  { "Blin; Bilin","byn",""} ,
1560
  { "Blissymbols; Blissymbolics; Bliss","zbl",""} ,
1561
  { "Bokmal, Norwegian; Norwegian Bokmal","nob","nb"} ,
1562
  { "Bosnian","bos","bs"} ,
1563
  { "Braj","bra",""} ,
1564
  { "Breton","bre","br"} ,
1565
  { "Buginese","bug",""} ,
1566
  { "Bulgarian","bul","bg"} ,
1567
  { "Buriat","bua",""} ,
1568
  { "Burmese","mya","my"} ,
1569
  { "Caddo","cad",""} ,
1570
  { "Catalan; Valencian","cat","ca"} ,
1571
  { "Caucasian languages","cau",""} ,
1572
  { "Cebuano","ceb",""} ,
1573
  { "Celtic languages","cel",""} ,
1574
  { "Central American Indian languages","cai",""} ,
1575
  { "Central Khmer","khm","km"} ,
1576
  { "Chagatai","chg",""} ,
1577
  { "Chamic languages","cmc",""} ,
1578
  { "Chamorro","cha","ch"} ,
1579
  { "Chechen","che","ce"} ,
1580
  { "Cherokee","chr",""} ,
1581
  { "Cheyenne","chy",""} ,
1582
  { "Chibcha","chb",""} ,
1583
  { "Chichewa; Chewa; Nyanja","nya","ny"} ,
1584
  { "Chinese","zho","zh"} ,
1585
  { "Chinook jargon","chn",""} ,
1586
  { "Chipewyan; Dene Suline","chp",""} ,
1587
  { "Choctaw","cho",""} ,
1588
  { "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church}  S{ lavonic","chu","cu"} ,
1589
  { "Chuukese","chk",""} ,
1590
  { "Chuvash","chv","cv"} ,
1591
  { "Classical Newari; Old Newari; Classical Nepal Bhasa","nwc",""} ,
1592
  { "Classical Syriac","syc",""} ,
1593
  { "Coptic","cop",""} ,
1594
  { "Cornish","cor","kw"} ,
1595
  { "Corsican","cos","co"} ,
1596
  { "Cree","cre","cr"} ,
1597
  { "Creek","mus",""} ,
1598
  { "Creoles and pidgins","crp",""} ,
1599
  { "Creoles and pidgins, English based","cpe",""} ,
1600
  { "Creoles and pidgins, French-based","cpf",""} ,
1601
  { "Creoles and pidgins, Portuguese-based","cpp",""} ,
1602
  { "Crimean Tatar; Crimean Turkish","crh",""} ,
1603
  { "Croatian","hrv","hr"} ,
1604
  { "Cushitic languages","cus",""} ,
1605
  { "Czech","ces","cs"} ,
1606
  { "Dakota","dak",""} ,
1607
  { "Danish","dan","da"} ,
1608
  { "Dargwa","dar",""} ,
1609
  { "Delaware","del",""} ,
1610
  { "Dinka","din",""} ,
1611
  { "Divehi; Dhivehi; Maldivian","div","dv"} ,
1612
  { "Dogri","doi",""} ,
1613
  { "Dogrib","dgr",""} ,
1614
  { "Dravidian languages","dra",""} ,
1615
  { "Duala","dua",""} ,
1616
  { "Dutch, Middle (ca.1050-1350)","dum",""} ,
1617
  { "Dutch; Flemish","nld","nl"} ,
1618
  { "Dyula","dyu",""} ,
1619
  { "Dzongkha","dzo","dz"} ,
1620
  { "Eastern Frisian","frs",""} ,
1621
  { "Efik","efi",""} ,
1622
  { "Egyptian (Ancient)","egy",""} ,
1623
  { "Ekajuk","eka",""} ,
1624
  { "Elamite","elx",""} ,
1625
  { "English","eng","en"} ,
1626
  { "English, Middle (1100-1500)","enm",""} ,
1627
  { "English, Old (ca.450-1100)","ang",""} ,
1628
  { "Erzya","myv",""} ,
1629
  { "Esperanto","epo","eo"} ,
1630
  { "Estonian","est","et"} ,
1631
  { "Ewe","ewe","ee"} ,
1632
  { "Ewondo","ewo",""} ,
1633
  { "Fang","fan",""} ,
1634
  { "Fanti","fat",""} ,
1635
  { "Faroese","fao","fo"} ,
1636
  { "Fijian","fij","fj"} ,
1637
  { "Filipino; Pilipino","fil",""} ,
1638
  { "Finnish","fin","fi"} ,
1639
  { "Finno-Ugrian languages","fiu",""} ,
1640
  { "Fon","fon",""} ,
1641
  { "French","fra","fr"} ,
1642
  { "French, Middle (ca.1400-1600)","frm",""} ,
1643
  { "French, Old (842-ca.1400)","fro",""} ,
1644
  { "Friulian","fur",""} ,
1645
  { "Fulah","ful","ff"} ,
1646
  { "Ga","gaa",""} ,
1647
  { "Gaelic; Scottish Gaelic","gla","gd"} ,
1648
  { "Galibi Carib","car",""} ,
1649
  { "Galician","glg","gl"} ,
1650
  { "Ganda","lug","lg"} ,
1651
  { "Gayo","gay",""} ,
1652
  { "Gbaya","gba",""} ,
1653
  { "Geez","gez",""} ,
1654
  { "Georgian","kat","ka"} ,
1655
  { "German","deu","de"} ,
1656
  { "German, Middle High (ca.1050-1500)","gmh",""} ,
1657
  { "German, Old High (ca.750-1050)","goh",""} ,
1658
  { "Germanic languages","gem",""} ,
1659
  { "Gilbertese","gil",""} ,
1660
  { "Gondi","gon",""} ,
1661
  { "Gorontalo","gor",""} ,
1662
  { "Gothic","got",""} ,
1663
  { "Grebo","grb",""} ,
1664
  { "Greek, Ancient (to 1453)","grc",""} ,
1665
  { "Greek, Modern (1453-)","ell","el"} ,
1666
  { "Guarani","grn","gn"} ,
1667
  { "Gujarati","guj","gu"} ,
1668
  { "Gwich'in","gwi",""} ,
1669
  { "Haida","hai",""} ,
1670
  { "Haitian; Haitian Creole","hat","ht"} ,
1671
  { "Hausa","hau","ha"} ,
1672
  { "Hawaiian","haw",""} ,
1673
  { "Hebrew","heb","he"} ,
1674
  { "Herero","her","hz"} ,
1675
  { "Hiligaynon","hil",""} ,
1676
  { "Himachali languages; Western Pahari languages","him",""} ,
1677
  { "Hindi","hin","hi"} ,
1678
  { "Hiri Motu","hmo","ho"} ,
1679
  { "Hittite","hit",""} ,
1680
  { "Hmong; Mong","hmn",""} ,
1681
  { "Hungarian","hun","hu"} ,
1682
  { "Hupa","hup",""} ,
1683
  { "Iban","iba",""} ,
1684
  { "Icelandic","isl","is"} ,
1685
  { "Ido","ido","io"} ,
1686
  { "Igbo","ibo","ig"} ,
1687
  { "Ijo languages","ijo",""} ,
1688
  { "Iloko","ilo",""} ,
1689
  { "Inari Sami","smn",""} ,
1690
  { "Indic languages","inc",""} ,
1691
  { "Indo-European languages","ine",""} ,
1692
  { "Indonesian","ind","id"} ,
1693
  { "Ingush","inh",""} ,
1694
  { "Interlingua (International Auxiliary Language Association)","ina","ia"} ,
1695
  { "Interlingue; Occidental","ile","ie"} ,
1696
  { "Inuktitut","iku","iu"} ,
1697
  { "Inupiaq","ipk","ik"} ,
1698
  { "Iranian languages","ira",""} ,
1699
  { "Irish","gle","ga"} ,
1700
  { "Irish, Middle (900-1200)","mga",""} ,
1701
  { "Irish, Old (to 900)","sga",""} ,
1702
  { "Iroquoian languages","iro",""} ,
1703
  { "Italian","ita","it"} ,
1704
  { "Japanese","jpn","ja"} ,
1705
  { "Javanese","jav","jv"} ,
1706
  { "Judeo-Arabic","jrb",""} ,
1707
  { "Judeo-Persian","jpr",""} ,
1708
  { "Kabardian","kbd",""} ,
1709
  { "Kabyle","kab",""} ,
1710
  { "Kachin; Jingpho","kac",""} ,
1711
  { "Kalaallisut; Greenlandic","kal","kl"} ,
1712
  { "Kalmyk; Oirat","xal",""} ,
1713
  { "Kamba","kam",""} ,
1714
  { "Kannada","kan","kn"} ,
1715
  { "Kanuri","kau","kr"} ,
1716
  { "Kara-Kalpak","kaa",""} ,
1717
  { "Karachay-Balkar","krc",""} ,
1718
  { "Karelian","krl",""} ,
1719
  { "Karen languages","kar",""} ,
1720
  { "Kashmiri","kas","ks"} ,
1721
  { "Kashubian","csb",""} ,
1722
  { "Kawi","kaw",""} ,
1723
  { "Kazakh","kaz","kk"} ,
1724
  { "Khasi","kha",""} ,
1725
  { "Khoisan languages","khi",""} ,
1726
  { "Khotanese; Sakan","kho",""} ,
1727
  { "Kikuyu; Gikuyu","kik","ki"} ,
1728
  { "Kimbundu","kmb",""} ,
1729
  { "Kinyarwanda","kin","rw"} ,
1730
  { "Kirghiz; Kyrgyz","kir","ky"} ,
1731
  { "Klingon; tlhIngan-Hol","tlh",""} ,
1732
  { "Komi","kom","kv"} ,
1733
  { "Kongo","kon","kg"} ,
1734
  { "Konkani","kok",""} ,
1735
  { "Korean","kor","ko"} ,
1736
  { "Kosraean","kos",""} ,
1737
  { "Kpelle","kpe",""} ,
1738
  { "Kru languages","kro",""} ,
1739
  { "Kuanyama; Kwanyama","kua","kj"} ,
1740
  { "Kumyk","kum",""} ,
1741
  { "Kurdish","kur","ku"} ,
1742
  { "Kurukh","kru",""} ,
1743
  { "Kutenai","kut",""} ,
1744
  { "Ladino","lad",""} ,
1745
  { "Lahnda","lah",""} ,
1746
  { "Lamba","lam",""} ,
1747
  { "Land Dayak languages","day",""} ,
1748
  { "Lao","lao","lo"} ,
1749
  { "Latin","lat","la"} ,
1750
  { "Latvian","lav","lv"} ,
1751
  { "Lezghian","lez",""} ,
1752
  { "Limburgan; Limburger; Limburgish","lim","li"} ,
1753
  { "Lingala","lin","ln"} ,
1754
  { "Lithuanian","lit","lt"} ,
1755
  { "Lojban","jbo",""} ,
1756
  { "Low German; Low Saxon; German, Low; Saxon, Low","nds",""} ,
1757
  { "Lower Sorbian","dsb",""} ,
1758
  { "Lozi","loz",""} ,
1759
  { "Luba-Katanga","lub","lu"} ,
1760
  { "Luba-Lulua","lua",""} ,
1761
  { "Luiseno","lui",""} ,
1762
  { "Lule Sami","smj",""} ,
1763
  { "Lunda","lun",""} ,
1764
  { "Luo (Kenya and Tanzania)","luo",""} ,
1765
  { "Lushai","lus",""} ,
1766
  { "Luxembourgish; Letzeburgesch","ltz","lb"} ,
1767
  { "Macedonian","mkd","mk"} ,
1768
  { "Madurese","mad",""} ,
1769
  { "Magahi","mag",""} ,
1770
  { "Maithili","mai",""} ,
1771
  { "Makasar","mak",""} ,
1772
  { "Malagasy","mlg","mg"} ,
1773
  { "Malay","msa","ms"} ,
1774
  { "Malayalam","mal","ml"} ,
1775
  { "Maltese","mlt","mt"} ,
1776
  { "Manchu","mnc",""} ,
1777
  { "Mandar","mdr",""} ,
1778
  { "Mandingo","man",""} ,
1779
  { "Manipuri","mni",""} ,
1780
  { "Manobo languages","mno",""} ,
1781
  { "Manx","glv","gv"} ,
1782
  { "Maori","mri","mi"} ,
1783
  { "Mapudungun; Mapuche","arn",""} ,
1784
  { "Marathi","mar","mr"} ,
1785
  { "Mari","chm",""} ,
1786
  { "Marshallese","mah","mh"} ,
1787
  { "Marwari","mwr",""} ,
1788
  { "Masai","mas",""} ,
1789
  { "Mayan languages","myn",""} ,
1790
  { "Mende","men",""} ,
1791
  { "Mi'kmaq; Micmac","mic",""} ,
1792
  { "Minangkabau","min",""} ,
1793
  { "Mirandese","mwl",""} ,
1794
  { "Mohawk","moh",""} ,
1795
  { "Moksha","mdf",""} ,
1796
  { "Mon-Khmer languages","mkh",""} ,
1797
  { "Mongo","lol",""} ,
1798
  { "Mongolian","mon","mn"} ,
1799
  { "Mossi","mos",""} ,
1800
  { "Multiple languages","mul",""} ,
1801
  { "Munda languages","mun",""} ,
1802
  { "N'Ko","nqo",""} ,
1803
  { "Nahuatl languages","nah",""} ,
1804
  { "Nauru","nau","na"} ,
1805
  { "Navajo; Navaho","nav","nv"} ,
1806
  { "Ndebele, North; North Ndebele","nde","nd"} ,
1807
  { "Ndebele, South; South Ndebele","nbl","nr"} ,
1808
  { "Ndonga","ndo","ng"} ,
1809
  { "Neapolitan","nap",""} ,
1810
  { "Nepal Bhasa; Newari","new",""} ,
1811
  { "Nepali","nep","ne"} ,
1812
  { "Nias","nia",""} ,
1813
  { "Niger-Kordofanian languages","nic",""} ,
1814
  { "Nilo-Saharan languages","ssa",""} ,
1815
  { "Niuean","niu",""} ,
1816
  { "No linguistic content; Not applicable","zxx",""} ,
1817
  { "Nogai","nog",""} ,
1818
  { "Norse, Old","non",""} ,
1819
  { "North American Indian languages","nai",""} ,
1820
  { "Northern Frisian","frr",""} ,
1821
  { "Northern Sami","sme","se"} ,
1822
  { "Norwegian","nor","no"} ,
1823
  { "Norwegian Nynorsk; Nynorsk, Norwegian","nno","nn"} ,
1824
  { "Nubian languages","nub",""} ,
1825
  { "Nyamwezi","nym",""} ,
1826
  { "Nyankole","nyn",""} ,
1827
  { "Nyoro","nyo",""} ,
1828
  { "Nzima","nzi",""} ,
1829
  { "Occitan (post 1500)","oci","oc"} ,
1830
  { "Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)","arc",""} ,
1831
  { "Ojibwa","oji","oj"} ,
1832
  { "Oriya","ori","or"} ,
1833
  { "Oromo","orm","om"} ,
1834
  { "Osage","osa",""} ,
1835
  { "Ossetian; Ossetic","oss","os"} ,
1836
  { "Otomian languages","oto",""} ,
1837
  { "Pahlavi","pal",""} ,
1838
  { "Palauan","pau",""} ,
1839
  { "Pali","pli","pi"} ,
1840
  { "Pampanga; Kapampangan","pam",""} ,
1841
  { "Pangasinan","pag",""} ,
1842
  { "Panjabi; Punjabi","pan","pa"} ,
1843
  { "Papiamento","pap",""} ,
1844
  { "Papuan languages","paa",""} ,
1845
  { "Pedi; Sepedi; Northern Sotho","nso",""} ,
1846
  { "Persian","fas","fa"} ,
1847
  { "Persian, Old (ca.600-400 B.C.)","peo",""} ,
1848
  { "Philippine languages","phi",""} ,
1849
  { "Phoenician","phn",""} ,
1850
  { "Pohnpeian","pon",""} ,
1851
  { "Polish","pol","pl"} ,
1852
  { "Portuguese","por","pt"} ,
1853
  { "Prakrit languages","pra",""} ,
1854
  { "Provencal, Old (to 1500);Occitan, Old (to 1500)","pro",""} ,
1855
  { "Pushto; Pashto","pus","ps"} ,
1856
  { "Quechua","que","qu"} ,
1857
  { "Rajasthani","raj",""} ,
1858
  { "Rapanui","rap",""} ,
1859
  { "Rarotongan; Cook Islands Maori","rar",""} ,
1860
  { "Reserved for local use","qaa-qtz",""} ,
1861
  { "Romance languages","roa",""} ,
1862
  { "Romanian; Moldavian; Moldovan","ron","ro"} ,
1863
  { "Romansh","roh","rm"} ,
1864
  { "Romany","rom",""} ,
1865
  { "Rundi","run","rn"} ,
1866
  { "Russian","rus","ru"} ,
1867
  { "Salishan languages","sal",""} ,
1868
  { "Samaritan Aramaic","sam",""} ,
1869
  { "Sami languages","smi",""} ,
1870
  { "Samoan","smo","sm"} ,
1871
  { "Sandawe","sad",""} ,
1872
  { "Sango","sag","sg"} ,
1873
  { "Sanskrit","san","sa"} ,
1874
  { "Santali","sat",""} ,
1875
  { "Sardinian","srd","sc"} ,
1876
  { "Sasak","sas",""} ,
1877
  { "Scots","sco",""} ,
1878
  { "Selkup","sel",""} ,
1879
  { "Semitic languages","sem",""} ,
1880
  { "Serbian","srp","sr"} ,
1881
  { "Serer","srr",""} ,
1882
  { "Shan","shn",""} ,
1883
  { "Shona","sna","sn"} ,
1884
  { "Sichuan Yi; Nuosu","iii","ii"} ,
1885
  { "Sicilian","scn",""} ,
1886
  { "Sidamo","sid",""} ,
1887
  { "Sign Languages","sgn",""} ,
1888
  { "Siksika","bla",""} ,
1889
  { "Sindhi","snd","sd"} ,
1890
  { "Sinhala; Sinhalese","sin","si"} ,
1891
  { "Sino-Tibetan languages","sit",""} ,
1892
  { "Siouan languages","sio",""} ,
1893
  { "Skolt Sami","sms",""} ,
1894
  { "Slave (Athapascan)","den",""} ,
1895
  { "Slavic languages","sla",""} ,
1896
  { "Slovak","slk","sk"} ,
1897
  { "Slovenian","slv","sl"} ,
1898
  { "Sogdian","sog",""} ,
1899
  { "Somali","som","so"} ,
1900
  { "Songhai languages","son",""} ,
1901
  { "Soninke","snk",""} ,
1902
  { "Sorbian languages","wen",""} ,
1903
  { "Sotho, Southern","sot","st"} ,
1904
  { "South American Indian languages","sai",""} ,
1905
  { "Southern Altai","alt",""} ,
1906
  { "Southern Sami","sma",""} ,
1907
  { "Spanish; Castilian","spa","es"} ,
1908
  { "Sranan Tongo","srn",""} ,
1909
  { "Sukuma","suk",""} ,
1910
  { "Sumerian","sux",""} ,
1911
  { "Sundanese","sun","su"} ,
1912
  { "Susu","sus",""} ,
1913
  { "Swahili","swa","sw"} ,
1914
  { "Swati","ssw","ss"} ,
1915
  { "Swedish","swe","sv"} ,
1916
  { "Swiss German; Alemannic; Alsatian","gsw",""} ,
1917
  { "Syriac","syr",""} ,
1918
  { "Tagalog","tgl","tl"} ,
1919
  { "Tahitian","tah","ty"} ,
1920
  { "Tai languages","tai",""} ,
1921
  { "Tajik","tgk","tg"} ,
1922
  { "Tamashek","tmh",""} ,
1923
  { "Tamil","tam","ta"} ,
1924
  { "Tatar","tat","tt"} ,
1925
  { "Telugu","tel","te"} ,
1926
  { "Tereno","ter",""} ,
1927
  { "Tetum","tet",""} ,
1928
  { "Thai","tha","th"} ,
1929
  { "Tibetan","bod","bo"} ,
1930
  { "Tigre","tig",""} ,
1931
  { "Tigrinya","tir","ti"} ,
1932
  { "Timne","tem",""} ,
1933
  { "Tiv","tiv",""} ,
1934
  { "Tlingit","tli",""} ,
1935
  { "Tok Pisin","tpi",""} ,
1936
  { "Tokelau","tkl",""} ,
1937
  { "Tonga (Nyasa)","tog",""} ,
1938
  { "Tonga (Tonga Islands)","ton","to"} ,
1939
  { "Tsimshian","tsi",""} ,
1940
  { "Tsonga","tso","ts"} ,
1941
  { "Tswana","tsn","tn"} ,
1942
  { "Tumbuka","tum",""} ,
1943
  { "Tupi languages","tup",""} ,
1944
  { "Turkish","tur","tr"} ,
1945
  { "Turkish, Ottoman (1500-1928)","ota",""} ,
1946
  { "Turkmen","tuk","tk"} ,
1947
  { "Tuvalu","tvl",""} ,
1948
  { "Tuvinian","tyv",""} ,
1949
  { "Twi","twi","tw"} ,
1950
  { "Udmurt","udm",""} ,
1951
  { "Ugaritic","uga",""} ,
1952
  { "Uighur; Uyghur","uig","ug"} ,
1953
  { "Ukrainian","ukr","uk"} ,
1954
  { "Umbundu","umb",""} ,
1955
  { "Uncoded languages","mis",""} ,
1956
  { "Undetermined","und",""} ,
1957
  { "Upper Sorbian","hsb",""} ,
1958
  { "Urdu","urd","ur"} ,
1959
  { "Uzbek","uzb","uz"} ,
1960
  { "Vai","vai",""} ,
1961
  { "Venda","ven","ve"} ,
1962
  { "Vietnamese","vie","vi"} ,
1963
  { "Volapuk","vol","vo"} ,
1964
  { "Votic","vot",""} ,
1965
  { "Wakashan languages","wak",""} ,
1966
  { "Walloon","wln","wa"} ,
1967
  { "Waray","war",""} ,
1968
  { "Washo","was",""} ,
1969
  { "Welsh","cym","cy"} ,
1970
  { "Western Frisian","fry","fy"} ,
1971
  { "Wolaitta; Wolaytta","wal",""} ,
1972
  { "Wolof","wol","wo"} ,
1973
  { "Xhosa","xho","xh"} ,
1974
  { "Yakut","sah",""} ,
1975
  { "Yao","yao",""} ,
1976
  { "Yapese","yap",""} ,
1977
  { "Yiddish","yid","yi"} ,
1978
  { "Yoruba","yor","yo"} ,
1979
  { "Yupik languages","ypk",""} ,
1980
  { "Zande languages","znd",""} ,
1981
  { "Zapotec","zap",""} ,
1982
  { "Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki","zza",""} ,
1983
  { "Zenaga","zen",""} ,
1984
  { "Zhuang; Chuang","zha","za"} ,
1985
  { "Zulu","zul","zu"} ,
1986
  { "Zuni","zun",""} ,
1987
};
1988
1989
1990
GF_EXPORT
1991
u32 gf_lang_get_count()
1992
0
{
1993
0
  return sizeof(defined_languages) / sizeof(struct lang_def);
1994
0
}
1995
1996
GF_EXPORT
1997
s32 gf_lang_find(const char *lang_or_rfc_5646_code)
1998
0
{
1999
  //find the language ISO639 entry for the given code
2000
0
  u32 i=0;
2001
0
  u32 len=0;
2002
0
  char *sep;
2003
0
  u32 count = sizeof(defined_languages) / sizeof(struct lang_def);
2004
2005
0
  if (!lang_or_rfc_5646_code) return -1;
2006
2007
0
  len = (u32)strlen(lang_or_rfc_5646_code);
2008
0
  sep = (char *) strchr(lang_or_rfc_5646_code, '-');
2009
0
  if (sep) {
2010
0
    sep[0] = 0;
2011
0
    len = (u32) strlen(lang_or_rfc_5646_code);
2012
0
    sep[0] = '-';
2013
0
  }
2014
2015
0
  for (i=0; i<count; i++) {
2016
0
    if (!strcmp(defined_languages[i].name, lang_or_rfc_5646_code)) {
2017
0
      return i;
2018
0
    }
2019
0
    if ((len==3) && !strnicmp(defined_languages[i].three_char_code, lang_or_rfc_5646_code, 3)) {
2020
0
      return i;
2021
0
    }
2022
0
    if ((len==2) && !strnicmp(defined_languages[i].two_char_code, lang_or_rfc_5646_code, 2)) {
2023
0
      return i;
2024
0
    }
2025
0
  }
2026
0
  return -1;
2027
0
}
2028
2029
GF_EXPORT
2030
const char *gf_lang_get_name(u32 idx)
2031
0
{
2032
0
  if (idx>=sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
2033
0
  return defined_languages[idx].name;
2034
0
}
2035
2036
GF_EXPORT
2037
const char *gf_lang_get_2cc(u32 idx)
2038
0
{
2039
0
  if (idx>=sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
2040
0
  return defined_languages[idx].two_char_code;
2041
0
}
2042
2043
GF_EXPORT
2044
const char *gf_lang_get_3cc(u32 idx)
2045
0
{
2046
0
  if (idx>=sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
2047
0
  return defined_languages[idx].three_char_code;
2048
0
}
2049
2050
2051
GF_EXPORT
2052
GF_Err gf_dynstrcat(char **str, const char *to_append, const char *sep)
2053
0
{
2054
0
  u32 l1, l2, lsep;
2055
0
  if (!to_append) return GF_OK;
2056
2057
0
  lsep = sep ? (u32) strlen(sep) : 0;
2058
0
  l1 = *str ? (u32) strlen(*str) : 0;
2059
0
  l2 = (u32) strlen(to_append);
2060
0
  if (l1) (*str) = gf_realloc((*str), sizeof(char)*(l1+l2+lsep+1));
2061
0
  else (*str) = gf_realloc((*str), sizeof(char)*(l2+lsep+1));
2062
2063
0
  if (! (*str) )
2064
0
    return GF_OUT_OF_MEM;
2065
2066
0
  (*str)[l1]=0;
2067
0
  if (l1 && sep) strcat((*str), sep);
2068
0
  strcat((*str), to_append);
2069
0
  return GF_OK;
2070
0
}
2071
2072
GF_EXPORT
2073
Bool gf_parse_lfrac(const char *value, GF_Fraction64 *frac)
2074
0
{
2075
0
  Float v;
2076
0
  u32 len, i;
2077
0
  Bool all_num=GF_TRUE;
2078
0
  char *sep;
2079
0
  if (!frac) return GF_FALSE;
2080
0
  frac->num = 0;
2081
0
  frac->den = 0;
2082
0
  if (!value) return GF_FALSE;
2083
2084
0
  if (sscanf(value, LLD"/"LLU, &frac->num, &frac->den) == 2) {
2085
0
    return GF_TRUE;
2086
0
  }
2087
0
  if (sscanf(value, LLD"-"LLU, &frac->num, &frac->den) == 2) {
2088
0
    return GF_TRUE;
2089
0
  }
2090
0
  if (sscanf(value, "%g", &v) != 1) {
2091
0
    frac->num = 0;
2092
0
    frac->den = 0;
2093
0
    return GF_FALSE;
2094
0
  }
2095
0
  sep = strchr(value, '.');
2096
0
  if (!sep) sep = strchr(value, ',');
2097
0
  if (!sep) {
2098
0
    len = (u32) strlen(value);
2099
0
    for (i=0; i<len; i++) {
2100
0
      if (((value[i]<'0') || (value[i]>'9')) && (value[i]!='-') && (value[i]!='+'))
2101
0
        return GF_FALSE;
2102
0
    }
2103
0
    frac->num = atol(value);
2104
0
    frac->den = 1;
2105
0
    return GF_TRUE;
2106
0
  }
2107
2108
0
  len = (u32) strlen(sep+1);
2109
0
  for (i=1; i<=len; i++) {
2110
0
    if ((sep[i]<'0') || (sep[i]>'9')) {
2111
0
      all_num = GF_FALSE;
2112
0
      break;
2113
0
    }
2114
0
  }
2115
0
  if (all_num) {
2116
0
    u32 div_trail_zero = 1;
2117
0
    sscanf(value, LLD"."LLU, &frac->num, &frac->den);
2118
2119
0
    i=0;
2120
0
    frac->den = 1;
2121
0
    while (i<len) {
2122
0
      i++;
2123
0
      frac->den *= 10;
2124
0
    }
2125
    //trash trailing zero
2126
0
    i=len;
2127
0
    while (i>0) {
2128
0
      if (sep[i] != '0') {
2129
0
        break;
2130
0
      }
2131
0
      div_trail_zero *= 10;
2132
0
      i--;
2133
0
    }
2134
2135
2136
0
    frac->num *= frac->den / div_trail_zero;
2137
0
    frac->num += atoi(sep+1) / div_trail_zero;
2138
0
    frac->den /= div_trail_zero;
2139
2140
0
    return GF_TRUE;
2141
0
  }
2142
2143
0
  if (len <= 3) frac->den = 1000;
2144
0
  else if (len <= 6) frac->den = 1000000;
2145
0
  else frac->den = 1000000000;
2146
2147
0
  frac->num = (u64)( (atof(value) * frac->den) + 0.5 );
2148
0
  return GF_TRUE;
2149
0
}
2150
2151
GF_EXPORT
2152
Bool gf_parse_frac(const char *value, GF_Fraction *frac)
2153
0
{
2154
0
  GF_Fraction64 r;
2155
0
  Bool res;
2156
0
  if (!frac) return GF_FALSE;
2157
0
  res = gf_parse_lfrac(value, &r);
2158
0
  while ((r.num >= 0x80000000) && (r.den > 1000)) {
2159
0
    r.num /= 1000;
2160
0
    r.den /= 1000;
2161
0
  }
2162
0
  frac->num = (s32) r.num;
2163
0
  frac->den = (u32) r.den;
2164
0
  return res;
2165
0
}