LCOV - code coverage report
Current view: top level - jsmods - core.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 860 965 89.1 %
Date: 2021-04-29 23:48:07 Functions: 117 120 97.5 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2007-2020
       6             :  *                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / JavaScript libgpac Core bindings
       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             : /*
      27             :         ANY CHANGE TO THE API MUST BE REFLECTED IN THE DOCUMENTATION IN gpac/share/doc/idl/storage.js
      28             :         (no way to define inline JS doc with doxygen)
      29             : */
      30             : 
      31             : #include <gpac/setup.h>
      32             : 
      33             : #ifdef GPAC_HAS_QJS
      34             : #include <gpac/bitstream.h>
      35             : #include <gpac/network.h>
      36             : #include <gpac/base_coding.h>
      37             : 
      38             : #include "../scenegraph/qjs_common.h"
      39             : 
      40             : #define JS_CGETSET_MAGIC_DEF_ENUM(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE|JS_PROP_ENUMERABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } }
      41             : 
      42             : 
      43             : static JSClassID bitstream_class_id = 0;
      44             : static JSClassID sha1_class_id = 0;
      45             : static JSClassID file_class_id = 0;
      46             : 
      47             : typedef struct
      48             : {
      49             :         GF_BitStream *bs;
      50             :         JSValue buf_ref;
      51             : } JSBitstream;
      52             : 
      53             : #define GET_JSBS \
      54             :         JSBitstream *jbs = JS_GetOpaque(this_val, bitstream_class_id); \
      55             :         GF_BitStream *bs = jbs ? jbs->bs : NULL;
      56             : 
      57             : 
      58           6 : static void js_gpac_free(JSRuntime *rt, void *opaque, void *ptr)
      59             : {
      60           6 :         gf_free(ptr);
      61           6 : }
      62             : 
      63          43 : static void js_bs_finalize(JSRuntime *rt, JSValue this_val)
      64             : {
      65          43 :         GET_JSBS
      66           4 :         if (!bs) return;
      67           4 :         gf_bs_del(bs);
      68             :         JS_FreeValueRT(rt, jbs->buf_ref);
      69           4 :         gf_free(jbs);
      70             : }
      71         188 : static void js_bs_gc_mark(JSRuntime *rt, JSValueConst this_val, JS_MarkFunc *mark_func)
      72             : {
      73         188 :         GET_JSBS
      74           0 :         if (!bs) return;
      75           0 :         JS_MarkValue(rt, jbs->buf_ref, mark_func);
      76             : }
      77             : 
      78             : JSClassDef bitstreamClass = {
      79             :     "Bitstream",
      80             :     .finalizer = js_bs_finalize,
      81             :         .gc_mark = js_bs_gc_mark
      82             : };
      83             : 
      84             : 
      85           1 : static JSValue js_bs_get_u8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
      86             : {
      87           1 :         GET_JSBS
      88           1 :         if (!bs) return JS_EXCEPTION;
      89           1 :         return JS_NewInt32(ctx, gf_bs_read_u8(bs) );
      90             : }
      91           1 : static JSValue js_bs_get_s8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
      92             : {
      93             :         s8 v;
      94           1 :         GET_JSBS
      95           1 :         if (!bs) return JS_EXCEPTION;
      96           1 :         v = (s8) gf_bs_read_u8(bs);
      97           1 :         return JS_NewInt32(ctx, v );
      98             : }
      99           1 : static JSValue js_bs_get_u16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     100             : {
     101           1 :         GET_JSBS
     102           1 :         if (!bs) return JS_EXCEPTION;
     103           1 :         return JS_NewInt32(ctx, gf_bs_read_u16(bs) );
     104             : }
     105           1 : static JSValue js_bs_get_u16_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     106             : {
     107           1 :         GET_JSBS
     108           1 :         if (!bs) return JS_EXCEPTION;
     109           1 :         return JS_NewInt32(ctx, gf_bs_read_u16_le(bs) );
     110             : }
     111           1 : static JSValue js_bs_get_s16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     112             : {
     113             :         s16 v;
     114           1 :         GET_JSBS
     115           1 :         if (!bs) return JS_EXCEPTION;
     116           1 :         v = (s16) gf_bs_read_u16(bs);
     117           1 :         return JS_NewInt32(ctx, v );
     118             : }
     119           1 : static JSValue js_bs_get_u24(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     120             : {
     121           1 :         GET_JSBS
     122           1 :         if (!bs) return JS_EXCEPTION;
     123           1 :         return JS_NewInt32(ctx, gf_bs_read_u24(bs) );
     124             : }
     125           1 : static JSValue js_bs_get_s32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     126             : {
     127             :         s32 v;
     128           1 :         GET_JSBS
     129           1 :         if (!bs) return JS_EXCEPTION;
     130           1 :         v = (s32) gf_bs_read_u32(bs);
     131             :         return JS_NewInt32(ctx, v);
     132             : }
     133           1 : static JSValue js_bs_get_u32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     134             : {
     135           1 :         GET_JSBS
     136           1 :         if (!bs) return JS_EXCEPTION;
     137           1 :         return JS_NewInt32(ctx, gf_bs_read_u32(bs) );
     138             : }
     139           1 : static JSValue js_bs_get_u32_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     140             : {
     141           1 :         GET_JSBS
     142           1 :         if (!bs) return JS_EXCEPTION;
     143           1 :         return JS_NewInt32(ctx, gf_bs_read_u32_le(bs) );
     144             : }
     145           1 : static JSValue js_bs_get_u64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     146             : {
     147           1 :         GET_JSBS
     148           1 :         if (!bs) return JS_EXCEPTION;
     149           1 :         return JS_NewInt64(ctx, gf_bs_read_u64(bs) );
     150             : }
     151           1 : static JSValue js_bs_get_u64_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     152             : {
     153           1 :         GET_JSBS
     154           1 :         if (!bs) return JS_EXCEPTION;
     155           1 :         return JS_NewInt64(ctx, gf_bs_read_u64_le(bs) );
     156             : }
     157           1 : static JSValue js_bs_get_s64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     158             : {
     159             :         s64 v;
     160           1 :         GET_JSBS
     161           1 :         if (!bs) return JS_EXCEPTION;
     162           1 :         v = (s64) gf_bs_read_u64(bs);
     163             :         return JS_NewInt64(ctx, v );
     164             : }
     165           1 : static JSValue js_bs_get_float(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     166             : {
     167           1 :         GET_JSBS
     168           1 :         if (!bs) return JS_EXCEPTION;
     169           1 :         return JS_NewFloat64(ctx, gf_bs_read_float(bs) );
     170             : }
     171           1 : static JSValue js_bs_get_double(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     172             : {
     173           1 :         GET_JSBS
     174           1 :         if (!bs) return JS_EXCEPTION;
     175           1 :         return JS_NewFloat64(ctx, gf_bs_read_double(bs) );
     176             : }
     177           2 : static JSValue js_bs_get_bits(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     178             : {
     179             :         s32 nb_bits;
     180           2 :         GET_JSBS
     181           2 :         if (!bs || !argc) return JS_EXCEPTION;
     182           2 :         if (JS_ToInt32(ctx, &nb_bits, argv[0])) return JS_EXCEPTION;
     183           2 :         if (nb_bits<=32)
     184           1 :                 return JS_NewInt32(ctx, gf_bs_read_int(bs, nb_bits) );
     185           1 :         return JS_NewInt64(ctx, gf_bs_read_long_int(bs, nb_bits) );
     186             : }
     187             : 
     188           3 : static JSValue js_bs_data_io(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 mode)
     189             : {
     190           3 :         s32 nb_bytes=0;
     191           3 :         s64 offset=0;
     192             :         size_t data_size;
     193             :         u8 *data=NULL;
     194           3 :         GET_JSBS
     195           3 :         if (!bs) return JS_EXCEPTION;
     196           3 :         if (argc<1) return JS_EXCEPTION;
     197             : 
     198           6 :         if (JS_IsObject(argv[0])) {
     199           3 :                 data = JS_GetArrayBuffer(ctx, &data_size, argv[0]);
     200           3 :                 if (argc>1) {
     201           0 :                         if (JS_ToInt32(ctx, &nb_bytes, argv[1])) return JS_EXCEPTION;
     202           0 :                         if ((mode==2) && (argc>2)) {
     203           0 :                                 if (JS_ToInt64(ctx, &offset, argv[2])) return JS_EXCEPTION;
     204             : 
     205             :                         }
     206             :                 }
     207             :         }
     208           3 :         if (!data) return JS_EXCEPTION;
     209             : 
     210           3 :         if (nb_bytes> (s32) data_size) nb_bytes = (s32) data_size;
     211           3 :         else if (!nb_bytes) nb_bytes = (s32) data_size;
     212             : 
     213           3 :         if (mode==1) {
     214           1 :                 data_size = gf_bs_write_data(bs, data, nb_bytes);
     215           2 :         } else if (mode==2) {
     216           1 :                 GF_Err e = gf_bs_insert_data(bs, data, nb_bytes, offset);
     217           1 :                 if (e) js_throw_err(ctx, e);
     218           1 :                 return JS_UNDEFINED;
     219             :         } else {
     220           1 :                 data_size = gf_bs_read_data(bs, data, nb_bytes);
     221             :         }
     222           2 :         return JS_NewInt32(ctx, (s32) data_size);
     223             : }
     224             : 
     225           1 : static JSValue js_bs_get_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     226             : {
     227           1 :         return js_bs_data_io(ctx, this_val, argc, argv, 0);
     228             : }
     229           1 : static JSValue js_bs_skip_bytes(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     230             : {
     231             :         s32 nb_bytes;
     232           1 :         GET_JSBS
     233           1 :         if (!bs || !argc) return JS_EXCEPTION;
     234           1 :         if (JS_ToInt32(ctx, &nb_bytes, argv[0])) return JS_EXCEPTION;
     235           1 :         gf_bs_skip_bytes(bs, nb_bytes);
     236           1 :         return JS_UNDEFINED;
     237             : }
     238           1 : static JSValue js_bs_is_align(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     239             : {
     240           1 :         GET_JSBS
     241           1 :         if (!bs) return JS_EXCEPTION;
     242           1 :         if (gf_bs_is_align(bs)) return JS_TRUE;
     243           1 :         return JS_FALSE;
     244             : }
     245           2 : static JSValue js_bs_align(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     246             : {
     247           2 :         GET_JSBS
     248           2 :         if (!bs) return JS_EXCEPTION;
     249           2 :         gf_bs_align(bs);
     250           2 :         return JS_UNDEFINED;
     251             : }
     252           1 : static JSValue js_bs_truncate(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     253             : {
     254           1 :         GET_JSBS
     255           1 :         if (!bs) return JS_EXCEPTION;
     256           1 :         gf_bs_truncate(bs);
     257           1 :         return JS_UNDEFINED;
     258             : }
     259           2 : static JSValue js_bs_flush(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     260             : {
     261           2 :         GET_JSBS
     262           2 :         if (!bs) return JS_EXCEPTION;
     263           2 :         gf_bs_flush(bs);
     264           2 :         return JS_UNDEFINED;
     265             : }
     266           1 : static JSValue js_bs_epb_mode(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     267             : {
     268           1 :         GET_JSBS
     269           1 :         if (!bs || !argc) return JS_EXCEPTION;
     270           1 :         gf_bs_enable_emulation_byte_removal(bs, (JS_ToBool(ctx, argv[0])) ? GF_TRUE : GF_FALSE);
     271           1 :         return JS_UNDEFINED;
     272             : }
     273             : 
     274           1 : static JSValue js_bs_peek(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     275             : {
     276           1 :         u64 byte_offset=0;
     277             :         s32 nb_bits;
     278           1 :         GET_JSBS
     279           1 :         if (!bs || !argc) return JS_EXCEPTION;
     280           1 :         if (JS_ToInt32(ctx, &nb_bits, argv[0])) return JS_EXCEPTION;
     281           1 :         if (argc>1) {
     282           0 :                 if (JS_ToInt64(ctx, &byte_offset, argv[1])) return JS_EXCEPTION;
     283             :         }
     284           1 :         return JS_NewInt32(ctx, gf_bs_peek_bits(bs, nb_bits, byte_offset));
     285             : }
     286             : 
     287          13 : static JSValue js_bs_put_val(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 mode)
     288             : {
     289             :         s64 val;
     290          13 :         GET_JSBS
     291          13 :         if (!bs || !argc) return JS_EXCEPTION;
     292          13 :         if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION;
     293          13 :         switch (mode) {
     294           1 :         case 0: gf_bs_write_u8(bs, (u32) val); break;
     295           1 :         case 1: gf_bs_write_u8(bs, (u32) val); break;
     296           1 :         case 2: gf_bs_write_u16(bs, (u32) val); break;
     297           1 :         case 3: gf_bs_write_u16_le(bs, (u32) val); break;
     298           1 :         case 4: gf_bs_write_u16(bs, (u32) val); break;
     299           1 :         case 5: gf_bs_write_u24(bs, (u32) val); break;
     300           2 :         case 6: gf_bs_write_u32(bs, (u32) val); break;
     301           1 :         case 7: gf_bs_write_u32_le(bs, (u32) val); break;
     302           1 :         case 8: gf_bs_write_u32(bs, (u32) val); break;
     303           1 :         case 9: gf_bs_write_u64(bs, (u64) val); break;
     304           1 :         case 10: gf_bs_write_u64_le(bs, (u64) val); break;
     305           1 :         case 11: gf_bs_write_u64(bs, (u64) val); break;
     306             :         }
     307          13 :         return JS_UNDEFINED;
     308             : }
     309           1 : static JSValue js_bs_put_u8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     310             : {
     311           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 0);
     312             : }
     313           1 : static JSValue js_bs_put_s8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     314             : {
     315           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 1);
     316             : }
     317           1 : static JSValue js_bs_put_u16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     318             : {
     319           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 2);
     320             : }
     321           1 : static JSValue js_bs_put_u16_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     322             : {
     323           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 3);
     324             : }
     325           1 : static JSValue js_bs_put_s16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     326             : {
     327           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 4);
     328             : }
     329           1 : static JSValue js_bs_put_u24(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     330             : {
     331           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 5);
     332             : }
     333           2 : static JSValue js_bs_put_u32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     334             : {
     335           2 :         return js_bs_put_val(ctx, this_val, argc, argv, 6);
     336             : }
     337           1 : static JSValue js_bs_put_u32_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     338             : {
     339           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 7);
     340             : }
     341           1 : static JSValue js_bs_put_s32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     342             : {
     343           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 8);
     344             : }
     345           1 : static JSValue js_bs_put_u64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     346             : {
     347           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 9);
     348             : }
     349           1 : static JSValue js_bs_put_u64_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     350             : {
     351           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 10);
     352             : }
     353           1 : static JSValue js_bs_put_s64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     354             : {
     355           1 :         return js_bs_put_val(ctx, this_val, argc, argv, 11);
     356             : }
     357           2 : static JSValue js_bs_put_bits(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     358             : {
     359             :         s64 val;
     360             :         s32 nb_bits;
     361           2 :         GET_JSBS
     362           2 :         if (!bs || (argc!=2)) return JS_EXCEPTION;
     363           2 :         if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION;
     364           2 :         if (JS_ToInt32(ctx, &nb_bits, argv[1])) return JS_EXCEPTION;
     365           2 :         if (nb_bits<=32)
     366           1 :                 gf_bs_write_int(bs, (u32) val, nb_bits);
     367             :         else
     368           1 :                 gf_bs_write_long_int(bs, val, nb_bits);
     369           2 :         return JS_UNDEFINED;
     370             : }
     371           1 : static JSValue js_bs_put_float(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     372             : {
     373             :         Double val;
     374           1 :         GET_JSBS
     375           1 :         if (!bs || (argc!=1)) return JS_EXCEPTION;
     376           1 :         if (JS_ToFloat64(ctx, &val, argv[0])) return JS_EXCEPTION;
     377           1 :         gf_bs_write_float(bs, (Float) val);
     378           1 :         return JS_UNDEFINED;
     379             : }
     380           1 : static JSValue js_bs_put_double(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     381             : {
     382             :         Double val;
     383           1 :         GET_JSBS
     384           1 :         if (!bs || (argc!=1)) return JS_EXCEPTION;
     385           1 :         if (JS_ToFloat64(ctx, &val, argv[0])) return JS_EXCEPTION;
     386           1 :         gf_bs_write_double(bs, val);
     387           1 :         return JS_UNDEFINED;
     388             : }
     389           1 : static JSValue js_bs_put_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     390             : {
     391           1 :         return js_bs_data_io(ctx, this_val, argc, argv, 1);
     392             : }
     393           1 : static JSValue js_bs_insert_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     394             : {
     395           1 :         return js_bs_data_io(ctx, this_val, argc, argv, 2);
     396             : }
     397             : 
     398           1 : static JSValue js_bs_get_content(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     399             : {
     400             :         u8 *data;
     401             :         u32 size;
     402             :         JSValue res;
     403           1 :         GET_JSBS
     404           1 :         if (!bs) return JS_EXCEPTION;
     405           1 :         gf_bs_get_content(bs, &data, &size);
     406             : 
     407           1 :         if (data) {
     408           1 :                 res = JS_NewArrayBuffer(ctx, data, size, js_gpac_free, NULL, 0);
     409             :         } else {
     410           0 :                 res = JS_NULL;
     411             :         }
     412           1 :         return res;
     413             : }
     414             : 
     415           1 : static JSValue js_bs_transfer(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     416             : {
     417             :         Bool keep_src=GF_FALSE;
     418             :         GF_Err e;
     419             :         JSBitstream *jssrcbs;
     420           1 :         GET_JSBS
     421           1 :         if (!bs || !argc) return JS_EXCEPTION;
     422             : 
     423           1 :         jssrcbs = JS_GetOpaque(argv[0], bitstream_class_id);
     424           1 :         if (!jssrcbs || !jssrcbs->bs) return JS_EXCEPTION;
     425           1 :         if (argc>1) {
     426           0 :                 keep_src = JS_ToBool(ctx, argv[1]);
     427             :         }
     428           1 :         e = gf_bs_transfer(bs, jssrcbs->bs, keep_src);
     429           1 :         if (e) return js_throw_err(ctx, e);
     430           1 :         return JS_UNDEFINED;
     431             : }
     432             : 
     433             : enum
     434             : {
     435             :         JS_BS_POS=0,
     436             :         JS_BS_SIZE,
     437             :         JS_BS_BIT_OFFSET,
     438             :         JS_BS_BIT_POS,
     439             :         JS_BS_AVAILABLE,
     440             :         JS_BS_BITS_AVAILABLE,
     441             :         JS_BS_REFRESH_SIZE,
     442             : };
     443             : 
     444           6 : static JSValue js_bs_prop_get(JSContext *ctx, JSValueConst this_val, int magic)
     445             : {
     446           6 :         GET_JSBS
     447           6 :         if (!bs) return JS_EXCEPTION;
     448           6 :         switch (magic) {
     449           1 :         case JS_BS_POS:
     450           1 :                 return JS_NewInt64(ctx, gf_bs_get_position(bs));
     451           2 :         case JS_BS_SIZE:
     452           2 :                 return JS_NewInt64(ctx, gf_bs_get_size(bs));
     453           1 :         case JS_BS_REFRESH_SIZE:
     454           1 :                 return JS_NewInt64(ctx, gf_bs_get_refreshed_size(bs));
     455           1 :         case JS_BS_BIT_OFFSET:
     456           1 :                 return JS_NewInt64(ctx, gf_bs_get_bit_offset(bs));
     457           0 :         case JS_BS_BIT_POS:
     458           0 :                 return JS_NewInt64(ctx, gf_bs_get_bit_position(bs));
     459           0 :         case JS_BS_AVAILABLE:
     460           0 :                 return JS_NewInt64(ctx, gf_bs_available(bs));
     461           1 :         case JS_BS_BITS_AVAILABLE:
     462           1 :                 return JS_NewInt32(ctx, gf_bs_bits_available(bs));
     463             :         }
     464           0 :         return JS_UNDEFINED;
     465             : 
     466             : }
     467           1 : static JSValue js_bs_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
     468             : {
     469             :         s64 ival;
     470           1 :         GET_JSBS
     471           1 :         if (!bs) return JS_EXCEPTION;
     472             : 
     473           1 :         switch (magic) {
     474           1 :         case JS_BS_POS:
     475           1 :                 if (JS_ToInt64(ctx, &ival, value)) return JS_EXCEPTION;
     476           1 :                 gf_bs_seek(bs, ival);
     477           1 :                 break;
     478             :         }
     479           1 :         return JS_UNDEFINED;
     480             : }
     481             : 
     482             : static const JSCFunctionListEntry bitstream_funcs[] = {
     483             :     JS_CGETSET_MAGIC_DEF_ENUM("pos", js_bs_prop_get, js_bs_prop_set, JS_BS_POS),
     484             :     JS_CGETSET_MAGIC_DEF_ENUM("size", js_bs_prop_get, NULL, JS_BS_SIZE),
     485             :     JS_CGETSET_MAGIC_DEF_ENUM("bit_offset", js_bs_prop_get, NULL, JS_BS_BIT_OFFSET),
     486             :     JS_CGETSET_MAGIC_DEF_ENUM("bit_pos", js_bs_prop_get, NULL, JS_BS_BIT_POS),
     487             :     JS_CGETSET_MAGIC_DEF_ENUM("available", js_bs_prop_get, NULL, JS_BS_AVAILABLE),
     488             :     JS_CGETSET_MAGIC_DEF_ENUM("bits_available", js_bs_prop_get, NULL, JS_BS_BITS_AVAILABLE),
     489             :     JS_CGETSET_MAGIC_DEF_ENUM("refreshed_size", js_bs_prop_get, NULL, JS_BS_REFRESH_SIZE),
     490             : 
     491             :         JS_CFUNC_DEF("skip", 0, js_bs_skip_bytes),
     492             :         JS_CFUNC_DEF("is_align", 0, js_bs_is_align),
     493             :         JS_CFUNC_DEF("align", 0, js_bs_align),
     494             :         JS_CFUNC_DEF("truncate", 0, js_bs_truncate),
     495             :         JS_CFUNC_DEF("peek", 0, js_bs_peek),
     496             :         JS_CFUNC_DEF("flush", 0, js_bs_flush),
     497             :         JS_CFUNC_DEF("epb_mode", 0, js_bs_epb_mode),
     498             : 
     499             :         JS_CFUNC_DEF("get_u8", 0, js_bs_get_u8),
     500             :         JS_CFUNC_DEF("get_s8", 0, js_bs_get_s8),
     501             :         JS_CFUNC_DEF("get_u16", 0, js_bs_get_u16),
     502             :         JS_CFUNC_DEF("get_u16_le", 0, js_bs_get_u16_le),
     503             :         JS_CFUNC_DEF("get_s16", 0, js_bs_get_s16),
     504             :         JS_CFUNC_DEF("get_u24", 0, js_bs_get_u24),
     505             :         JS_CFUNC_DEF("get_u32", 0, js_bs_get_u32),
     506             :         JS_CFUNC_DEF("get_u32_le", 0, js_bs_get_u32_le),
     507             :         JS_CFUNC_DEF("get_s32", 0, js_bs_get_s32),
     508             :         JS_CFUNC_DEF("get_u64", 0, js_bs_get_u64),
     509             :         JS_CFUNC_DEF("get_u64_le", 0, js_bs_get_u64_le),
     510             :         JS_CFUNC_DEF("get_s64", 0, js_bs_get_s64),
     511             :         JS_CFUNC_DEF("get_bits", 0, js_bs_get_bits),
     512             :         JS_CFUNC_DEF("get_float", 0, js_bs_get_float),
     513             :         JS_CFUNC_DEF("get_double", 0, js_bs_get_double),
     514             :         JS_CFUNC_DEF("get_data", 0, js_bs_get_data),
     515             :         JS_CFUNC_DEF("put_u8", 0, js_bs_put_u8),
     516             :         JS_CFUNC_DEF("put_s8", 0, js_bs_put_s8),
     517             :         JS_CFUNC_DEF("put_u16", 0, js_bs_put_u16),
     518             :         JS_CFUNC_DEF("put_u16_le", 0, js_bs_put_u16_le),
     519             :         JS_CFUNC_DEF("put_s16", 0, js_bs_put_s16),
     520             :         JS_CFUNC_DEF("put_u24", 0, js_bs_put_u24),
     521             :         JS_CFUNC_DEF("put_u32", 0, js_bs_put_u32),
     522             :         JS_CFUNC_DEF("put_u32_le", 0, js_bs_put_u32_le),
     523             :         JS_CFUNC_DEF("put_s32", 0, js_bs_put_s32),
     524             :         JS_CFUNC_DEF("put_u64", 0, js_bs_put_u64),
     525             :         JS_CFUNC_DEF("put_u64_le", 0, js_bs_put_u64_le),
     526             :         JS_CFUNC_DEF("put_s64", 0, js_bs_put_s64),
     527             :         JS_CFUNC_DEF("put_bits", 0, js_bs_put_bits),
     528             :         JS_CFUNC_DEF("put_float", 0, js_bs_put_float),
     529             :         JS_CFUNC_DEF("put_double", 0, js_bs_put_double),
     530             :         JS_CFUNC_DEF("put_data", 0, js_bs_put_data),
     531             :         JS_CFUNC_DEF("insert_data", 0, js_bs_insert_data),
     532             :         JS_CFUNC_DEF("get_content", 0, js_bs_get_content),
     533             :         JS_CFUNC_DEF("transfer", 0, js_bs_transfer),
     534             : };
     535             : 
     536           4 : static JSValue bitstream_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
     537             : {
     538             :         JSValue anobj;
     539             :         JSBitstream *jbs;
     540             :         GF_BitStream *bs = NULL;
     541             : 
     542           4 :         if (!argc) {
     543           2 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     544           4 :         } else if (JS_IsObject(argv[0])){
     545           2 :                 FILE *f = JS_GetOpaque(argv[0], file_class_id);
     546           2 :                 if (f) {
     547           1 :                         if ((argc>1) && JS_ToBool(ctx, argv[1])) {
     548           1 :                                 bs = gf_bs_from_file(f, GF_BITSTREAM_WRITE);
     549             :                         } else {
     550           0 :                                 bs = gf_bs_from_file(f, GF_BITSTREAM_READ);
     551             :                         }
     552             :                 } else {
     553             :                         u8 *data;
     554             :                         size_t data_size;
     555             : 
     556           1 :                         data = JS_GetArrayBuffer(ctx, &data_size, argv[0]);
     557           1 :                         if (!data) return JS_EXCEPTION;
     558           1 :                         if ((argc>1) && JS_ToBool(ctx, argv[1])) {
     559           0 :                                 bs = gf_bs_new(data, data_size, GF_BITSTREAM_WRITE);
     560             :                         } else {
     561           1 :                                 bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
     562             :                         }
     563             :                 }
     564             :         } else {
     565           0 :                 return JS_EXCEPTION;
     566             :         }
     567           4 :         GF_SAFEALLOC(jbs, JSBitstream);
     568           4 :         if (!jbs) {
     569           0 :                 gf_bs_del(bs);
     570           0 :                 return js_throw_err(ctx, GF_OUT_OF_MEM);
     571             :         }
     572           4 :         anobj = JS_NewObjectClass(ctx, bitstream_class_id);
     573           4 :         if (JS_IsException(anobj)) {
     574           0 :                 gf_bs_del(bs);
     575           0 :                 gf_free(jbs);
     576           0 :                 return anobj;
     577             :         }
     578           4 :         jbs->bs = bs;
     579           4 :         jbs->buf_ref = JS_UNDEFINED;
     580           4 :         if (argc)
     581           2 :                 jbs->buf_ref = JS_DupValue(ctx, argv[0]);
     582             : 
     583           4 :         JS_SetOpaque(anobj, jbs);
     584           4 :         return anobj;
     585             : }
     586             : 
     587             : enum
     588             : {
     589             :         JS_SYS_NB_CORES = 1,
     590             :         JS_SYS_SAMPLE_DUR,
     591             :         JS_SYS_TOTAL_CPU,
     592             :         JS_SYS_PROCESS_CPU,
     593             :         JS_SYS_TOTAL_CPU_DIFF,
     594             :         JS_SYS_PROCESS_CPU_DIFF,
     595             :         JS_SYS_CPU_IDLE,
     596             :         JS_SYS_TOTAL_CPU_USAGE,
     597             :         JS_SYS_PROCESS_CPU_USAGE,
     598             :         JS_SYS_PID,
     599             :         JS_SYS_THREADS,
     600             :         JS_SYS_PROCESS_MEM,
     601             :         JS_SYS_TOTAL_MEM,
     602             :         JS_SYS_TOTAL_MEM_AVAIL,
     603             :         JS_SYS_GPAC_MEM,
     604             : 
     605             :         JS_SYS_BATTERY_ON,
     606             :         JS_SYS_BATTERY_CHARGE,
     607             :         JS_SYS_BATTERY_PERCENT,
     608             :         JS_SYS_BATTERY_LIFETIME,
     609             :         JS_SYS_BATTERY_LIFETIME_FULL,
     610             :         JS_SYS_HOSTNAME,
     611             :         JS_SYS_LAST_WORK_DIR,
     612             :         JS_SYS_TEST_MODE,
     613             :         JS_SYS_OLD_ARCH,
     614             :         JS_SYS_LOG_COLOR,
     615             :         JS_SYS_QUIET,
     616             :         JS_SYS_USERNAME,
     617             :         JS_SYS_TIMEZONE,
     618             :         JS_SYS_FILES_OPEN,
     619             :         JS_SYS_CACHE_DIR,
     620             :         JS_SYS_SHARED_DIR,
     621             :         JS_SYS_VERSION,
     622             :         JS_SYS_VERSION_FULL,
     623             :         JS_SYS_COPYRIGHT,
     624             :         JS_SYS_V_MAJOR,
     625             :         JS_SYS_V_MINOR,
     626             :         JS_SYS_V_MICRO,
     627             : };
     628             : 
     629             : #define RTI_REFRESH_MS  200
     630          53 : static JSValue js_sys_prop_get(JSContext *ctx, JSValueConst this_val, int magic)
     631             : {
     632             :         u32 uval;
     633             :         Bool bval;
     634             :         const char *res;
     635             :         GF_SystemRTInfo rti;
     636             : 
     637          53 :         if (magic<=JS_SYS_GPAC_MEM) {
     638          25 :                 gf_sys_get_rti(RTI_REFRESH_MS, &rti, 0);
     639          25 :                 switch (magic) {
     640           2 :                 case JS_SYS_NB_CORES:
     641           2 :                         return JS_NewInt32(ctx, rti.nb_cores);
     642           1 :                 case JS_SYS_SAMPLE_DUR:
     643           1 :                         return JS_NewInt32(ctx, rti.sampling_period_duration);
     644           1 :                 case JS_SYS_TOTAL_CPU:
     645           1 :                         return JS_NewInt32(ctx, rti.total_cpu_time);
     646           1 :                 case JS_SYS_PROCESS_CPU:
     647           1 :                         return JS_NewInt32(ctx, rti.process_cpu_time);
     648           1 :                 case JS_SYS_TOTAL_CPU_DIFF:
     649           1 :                         return JS_NewInt32(ctx, rti.total_cpu_time_diff);
     650           1 :                 case JS_SYS_PROCESS_CPU_DIFF:
     651           1 :                         return JS_NewInt32(ctx, rti.process_cpu_time_diff);
     652           1 :                 case JS_SYS_CPU_IDLE:
     653           1 :                         return JS_NewInt32(ctx, rti.cpu_idle_time);
     654           1 :                 case JS_SYS_TOTAL_CPU_USAGE:
     655           1 :                         return JS_NewInt32(ctx, rti.total_cpu_time);
     656           5 :                 case JS_SYS_PROCESS_CPU_USAGE:
     657           5 :                         return JS_NewInt32(ctx, rti.process_cpu_usage);
     658           1 :                 case JS_SYS_PID:
     659           1 :                         return JS_NewInt32(ctx, rti.pid);
     660           1 :                 case JS_SYS_THREADS:
     661           1 :                         return JS_NewInt32(ctx, rti.thread_count);
     662           1 :                 case JS_SYS_PROCESS_MEM:
     663           1 :                         return JS_NewInt64(ctx, rti.process_memory);
     664           2 :                 case JS_SYS_TOTAL_MEM:
     665           2 :                         return JS_NewInt64(ctx, rti.physical_memory);
     666           1 :                 case JS_SYS_TOTAL_MEM_AVAIL:
     667           1 :                         return JS_NewInt64(ctx, rti.physical_memory_avail);
     668           5 :                 case JS_SYS_GPAC_MEM:
     669           5 :                         return JS_NewInt64(ctx, rti.gpac_memory);
     670             :                 }
     671           0 :                 return JS_UNDEFINED;
     672             :         }
     673             : 
     674          28 :         switch (magic) {
     675           1 :         case JS_SYS_BATTERY_ON:
     676           1 :                 bval = GF_FALSE;
     677           1 :                 gf_sys_get_battery_state(&bval, NULL, NULL, NULL, NULL);
     678           1 :                 return JS_NewBool(ctx, bval);
     679             : 
     680           1 :         case JS_SYS_BATTERY_CHARGE:
     681           1 :                 uval = 0;
     682           1 :                 gf_sys_get_battery_state(NULL, &uval, NULL, NULL, NULL);
     683           1 :                 return JS_NewBool(ctx, uval ? 1 : 0);
     684             : 
     685           1 :         case JS_SYS_BATTERY_PERCENT:
     686           1 :                 uval=0;
     687           1 :                 gf_sys_get_battery_state(NULL, NULL, &uval, NULL, NULL);
     688           1 :                 return JS_NewInt32(ctx, uval);
     689             : 
     690           1 :         case JS_SYS_BATTERY_LIFETIME:
     691           1 :                 uval=0;
     692           1 :                 gf_sys_get_battery_state(NULL, NULL, NULL, &uval, NULL);
     693           1 :                 return JS_NewInt32(ctx, uval);
     694             : 
     695           1 :         case JS_SYS_BATTERY_LIFETIME_FULL:
     696           1 :                 uval=0;
     697           1 :                 gf_sys_get_battery_state(NULL, NULL, NULL, NULL, &uval);
     698           1 :                 return JS_NewInt32(ctx, uval);
     699             : 
     700           1 :         case JS_SYS_HOSTNAME:
     701             :                 {
     702             :                         char hostname[100];
     703           1 :                         gf_sk_get_host_name((char*)hostname);
     704           1 :                         return JS_NewString(ctx, hostname);
     705             :                 }
     706             :                 break;
     707           2 :         case JS_SYS_LAST_WORK_DIR:
     708           2 :                 res = gf_opts_get_key("General", "LastWorkingDir");
     709             : #ifdef WIN32
     710             :                 if (!res) res = getenv("HOMEPATH");
     711             :                 if (!res) res = "C:\\";
     712             : #elif defined(GPAC_CONFIG_DARWIN)
     713             :                 if (!res) res = getenv("HOME");
     714             :                 if (!res) res = "/Users";
     715             : #elif defined(GPAC_CONFIG_ANDROID)
     716             :                 if (!res) res = getenv("EXTERNAL_STORAGE");
     717             :                 if (!res) res = "/sdcard";
     718             : #elif defined(GPAC_CONFIG_IOS)
     719             :                 if (!res) res = (char *) gf_opts_get_key("General", "iOSDocumentsDir");
     720             : #else
     721           2 :                 if (!res) res = getenv("HOME");
     722           2 :                 if (!res) res = "/home/";
     723             : #endif
     724           2 :                 return JS_NewString(ctx, res);
     725             : 
     726           1 :         case JS_SYS_TEST_MODE:
     727           1 :                 return JS_NewBool(ctx, gf_sys_is_test_mode() );
     728           1 :         case JS_SYS_OLD_ARCH:
     729           1 :                 return JS_NewBool(ctx, gf_sys_old_arch_compat() );
     730           1 :         case JS_SYS_LOG_COLOR:
     731             : #ifdef GPAC_DISABLE_LOG
     732             :                 return JS_NewBool(ctx, GF_FALSE );
     733             : #else
     734           1 :                 return JS_NewBool(ctx, gf_log_use_color() );
     735             : #endif
     736           1 :         case JS_SYS_QUIET:
     737           1 :                 return JS_NewBool(ctx, gf_sys_is_quiet() );
     738           1 :         case JS_SYS_USERNAME:
     739             :                 {
     740             :                         char username[1024];
     741           1 :                         gf_get_user_name((char*)username);
     742           1 :                         return JS_NewString(ctx, username);
     743             :                 }
     744           1 :         case JS_SYS_TIMEZONE:
     745           1 :                 return JS_NewInt32(ctx, gf_net_get_timezone());
     746             : 
     747           1 :         case JS_SYS_FILES_OPEN:
     748           1 :                 return JS_NewInt32(ctx, gf_file_handles_count());
     749             : 
     750           1 :         case JS_SYS_CACHE_DIR:
     751           1 :                 res = gf_get_default_cache_directory();
     752           1 :                 if (res) return JS_NewString(ctx, res);
     753           0 :                 return JS_NULL;
     754             : 
     755           1 :         case JS_SYS_SHARED_DIR:
     756             :         {
     757             :                 char szDir[GF_MAX_PATH];
     758           1 :                 if (! gf_opts_default_shared_directory(szDir)) return JS_NULL;
     759           1 :                 return JS_NewString(ctx, szDir);
     760             :         }
     761             : 
     762           1 :         case JS_SYS_VERSION:
     763           1 :                 return JS_NewString(ctx, GPAC_VERSION );
     764           6 :         case JS_SYS_VERSION_FULL:
     765           6 :                 return JS_NewString(ctx, gf_gpac_version() );
     766           1 :         case JS_SYS_COPYRIGHT:
     767           1 :                 return JS_NewString(ctx, gf_gpac_copyright() );
     768             : 
     769             :         case JS_SYS_V_MAJOR:
     770             :                 return JS_NewInt32(ctx, GPAC_VERSION_MAJOR );
     771             :         case JS_SYS_V_MINOR:
     772             :                 return JS_NewInt32(ctx, GPAC_VERSION_MINOR );
     773             :         case JS_SYS_V_MICRO:
     774             :                 return JS_NewInt32(ctx, GPAC_VERSION_MICRO );
     775             :         }
     776             : 
     777           0 :         return JS_UNDEFINED;
     778             : }
     779             : 
     780           1 : static JSValue js_sys_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
     781             : {
     782             :         const char *prop_val;
     783           1 :         switch (magic) {
     784           1 :         case JS_SYS_LAST_WORK_DIR:
     785           1 :                 if (!JS_IsString(value)) return JS_EXCEPTION;
     786             :                 prop_val = JS_ToCString(ctx, value);
     787           1 :                 gf_opts_set_key("General", "LastWorkingDir", prop_val);
     788           1 :                 JS_FreeCString(ctx, prop_val);
     789           1 :                 break;
     790             :         }
     791           1 :         return JS_UNDEFINED;
     792             : }
     793             : 
     794          10 : static JSValue js_sys_set_arg_used(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     795             : {
     796             :         u32 idx;
     797             :         Bool used;
     798          10 :         if (argc < 2) return JS_EXCEPTION;
     799             : 
     800          10 :         if (JS_ToInt32(ctx, &idx, argv[0]))
     801           0 :                 return JS_EXCEPTION;
     802          10 :         used = JS_ToBool(ctx, argv[1]);
     803             : 
     804          10 :         gf_sys_mark_arg_used(idx, used);
     805          10 :         return JS_UNDEFINED;
     806             : }
     807             : 
     808             : 
     809             : typedef struct
     810             : {
     811             :         JSContext *c;
     812             :         JSValue array;
     813             :         Bool is_dir;
     814             :         u32 idx;
     815             : } enum_dir_cbk;
     816             : 
     817          54 : static Bool js_enum_dir_fct(void *cbck, char *file_name, char *file_path, GF_FileEnumInfo *file_info)
     818             : {
     819             :         u32 i, len;
     820             :         char *sep;
     821             :         JSValue s;
     822             :         JSValue obj;
     823             :         enum_dir_cbk *cbk = (enum_dir_cbk*)cbck;
     824             : 
     825          54 :         if (file_name && (file_name[0]=='.')) return 0;
     826             : 
     827          54 :         obj = JS_NewObject(cbk->c);
     828          54 :         JS_SetPropertyStr(cbk->c, obj, "name", JS_NewString(cbk->c, file_name) );
     829             : 
     830             :         sep=NULL;
     831          54 :         len = (u32) strlen(file_path);
     832         421 :         for (i=0; i<len; i++) {
     833         421 :                 sep = strchr("/\\", file_path[len-i-1]);
     834         421 :                 if (sep) {
     835          54 :                         sep = file_path+len-i-1;
     836          54 :                         break;
     837             :                 }
     838             :         }
     839          54 :         if (sep) {
     840          54 :                 sep[0] = '/';
     841          54 :                 sep[1] = 0;
     842          54 :                 s = JS_NewString(cbk->c, file_path);
     843             :         } else {
     844           0 :                 s = JS_NewString(cbk->c, file_path);
     845             :         }
     846          54 :         JS_SetPropertyStr(cbk->c, obj, "path", s);
     847             : 
     848         108 :         JS_SetPropertyStr(cbk->c, obj, "directory", JS_NewBool(cbk->c, cbk->is_dir) );
     849         108 :         JS_SetPropertyStr(cbk->c, obj, "drive", JS_NewBool(cbk->c, file_info->drive) );
     850         108 :         JS_SetPropertyStr(cbk->c, obj, "hidden", JS_NewBool(cbk->c, file_info->hidden) );
     851         108 :         JS_SetPropertyStr(cbk->c, obj, "system", JS_NewBool(cbk->c, file_info->system) );
     852         108 :         JS_SetPropertyStr(cbk->c, obj, "size", JS_NewInt64(cbk->c, file_info->size) );
     853         108 :         JS_SetPropertyStr(cbk->c, obj, "last_modified", JS_NewInt64(cbk->c, file_info->last_modified) );
     854             : 
     855          54 :         JS_SetPropertyUint32(cbk->c, cbk->array, cbk->idx, obj);
     856          54 :         cbk->idx++;
     857          54 :         return 0;
     858             : }
     859             : 
     860           5 : static JSValue js_sys_enum_directory(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     861             : {
     862             :         GF_Err err;
     863             :         enum_dir_cbk cbk;
     864             :         char *url = NULL;
     865             :         const char *dir = NULL;
     866             :         const char *filter = NULL;
     867             :         Bool dir_only = 0;
     868             :         Bool browse_root = 0;
     869             : 
     870          10 :         if ((argc >= 1) && JS_IsString(argv[0])) {
     871             :                 dir = JS_ToCString(ctx, argv[0]);
     872           5 :                 if (!strcmp(dir, "/")) browse_root = 1;
     873             :         }
     874           8 :         if ((argc >= 2) && JS_IsString(argv[1])) {
     875             :                 filter = JS_ToCString(ctx, argv[1]);
     876           3 :                 if (!strcmp(filter, "dir")) {
     877             :                         dir_only = 1;
     878             :                         filter = NULL;
     879           3 :                 } else if (!strlen(filter)) {
     880           0 :                         JS_FreeCString(ctx, filter);
     881             :                         filter=NULL;
     882             :                 }
     883             :         }
     884           8 :         if ((argc >= 3) && JS_IsBool(argv[2])) {
     885           0 :                 if (JS_ToBool(ctx, argv[2])) {
     886           0 :                         url = gf_url_concatenate(dir, "..");
     887           0 :                         if (dir && ( !strcmp(url, "..") || (url[0]==0) )) {
     888           0 :                                 if ((dir[1]==':') && ((dir[2]=='/') || (dir[2]=='\\')) ) browse_root = 1;
     889           0 :                                 else if (!strcmp(dir, "/")) browse_root = 1;
     890             :                         }
     891           0 :                         if (!strcmp(url, "/")) browse_root = 1;
     892             :                 }
     893             :         }
     894             : 
     895           5 :         if ( (!dir || !strlen(dir) ) && (!url || !strlen(url))) browse_root = 1;
     896             : 
     897           5 :         if (browse_root) {
     898           1 :                 cbk.c = ctx;
     899           1 :                 cbk.idx = 0;
     900           1 :                 cbk.array = JS_NewArray(ctx);
     901           2 :                 if (JS_IsException(cbk.array)) return cbk.array;
     902           1 :                 cbk.is_dir = 1;
     903           1 :                 gf_enum_directory("/", 1, js_enum_dir_fct, &cbk, NULL);
     904           1 :                 if (url) gf_free(url);
     905           1 :                 JS_FreeCString(ctx, dir);
     906           1 :                 JS_FreeCString(ctx, filter);
     907           1 :                 return cbk.array;
     908             :         }
     909             : 
     910           4 :         cbk.c = ctx;
     911           4 :         cbk.array = JS_NewArray(ctx);
     912           8 :         if (JS_IsException(cbk.array)) return cbk.array;
     913           4 :         cbk.is_dir = 1;
     914           4 :         cbk.idx = 0;
     915             : 
     916             : #if 0
     917             :         compositor = scenejs_get_compositor(ctx, this_val);
     918             : 
     919             :         /*concatenate with service url*/
     920             :         char *an_url = gf_url_concatenate(compositor->root_scene->root_od->scene_ns->url, url ? url : dir);
     921             :         if (an_url) {
     922             :                 gf_free(url);
     923             :                 url = an_url;
     924             :         }
     925             : #endif
     926             : 
     927           4 :         err = gf_enum_directory(url ? url : dir, 1, js_enum_dir_fct, &cbk, NULL);
     928           4 :         if (err) return JS_EXCEPTION;
     929             : 
     930           4 :         if (!dir_only) {
     931           4 :                 cbk.is_dir = 0;
     932           4 :                 err = gf_enum_directory(url ? url : dir, 0, js_enum_dir_fct, &cbk, filter);
     933           4 :                 if (err) return JS_EXCEPTION;
     934             :         }
     935             : 
     936           4 :         if (url) gf_free(url);
     937           4 :         JS_FreeCString(ctx, dir);
     938           4 :         JS_FreeCString(ctx, filter);
     939           4 :         return cbk.array;
     940             : }
     941             : 
     942             : 
     943           1 : static JSValue js_sys_error_string(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     944             : {
     945             :         GF_Err e;
     946           1 :         if (argc < 1) return JS_EXCEPTION;
     947           1 :         if (JS_ToInt32(ctx, (int32_t *) &e, argv[0]))
     948           0 :                 return JS_EXCEPTION;
     949           1 :         return JS_NewString(ctx, gf_error_to_string(e) );
     950             : }
     951             : 
     952           1 : static JSValue js_sys_prompt_input(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     953             : {
     954             :         char in_char[2];
     955             : 
     956           1 :     if (!gf_prompt_has_input())
     957           1 :                 return JS_NULL;
     958           0 :         in_char[0] = gf_prompt_get_char();
     959           0 :         in_char[1] = 0;
     960           0 :         return JS_NewString(ctx, in_char);
     961             : }
     962             : 
     963           1 : static JSValue js_sys_prompt_string(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     964             : {
     965             :         char input[4096], *read;
     966             :         u32 len;
     967             : //#ifdef GPAC_ENABLE_COVERAGE
     968           1 :     if (argc) {
     969           1 :                 return JS_NewString(ctx, "Coverage OK");
     970             :         }
     971             : //#endif // GPAC_ENABLE_COVERAGE
     972             : 
     973           0 :         read = fgets(input, 4095, stdin);
     974           0 :         if (!read) return JS_NULL;
     975           0 :         input[4095]=0;
     976           0 :         len = (u32) strlen(input);
     977           0 :         if (len && (input[len-1] == '\n')) {
     978           0 :         input[len-1] = 0;
     979             :         len--;
     980             :         }
     981           0 :         if (!len) return JS_NULL;
     982           0 :         return JS_NewString(ctx, input);
     983             : }
     984             : 
     985           2 : static JSValue js_sys_prompt_echo_off(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     986             : {
     987             :         Bool echo_off;
     988           2 :         if (!argc) return JS_EXCEPTION;
     989           2 :         echo_off = JS_ToBool(ctx, argv[0]);
     990           2 :         if (argc<2)
     991           0 :                 gf_prompt_set_echo_off(echo_off);
     992           2 :         return JS_UNDEFINED;
     993             : }
     994           2 : static JSValue js_sys_prompt_code(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
     995             : {
     996             :         s32 code;
     997           2 :         if (!argc) return JS_EXCEPTION;
     998           2 :         if (JS_ToInt32(ctx, &code, argv[0])) return JS_EXCEPTION;
     999             : 
    1000           2 :         gf_sys_set_console_code(stderr, code);
    1001           2 :         return JS_UNDEFINED;
    1002             : }
    1003           1 : static JSValue js_sys_prompt_size(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1004             : {
    1005             :         u32 w, h;
    1006             :         JSValue res;
    1007           1 :         GF_Err e = gf_prompt_get_size(&w, &h);
    1008           1 :         if (e) return JS_NULL;
    1009           1 :         res = JS_NewObject(ctx);
    1010           2 :         JS_SetPropertyStr(ctx, res, "w", JS_NewInt32(ctx, w));
    1011           2 :         JS_SetPropertyStr(ctx, res, "h", JS_NewInt32(ctx, h));
    1012           1 :         return res;
    1013             : }
    1014             : 
    1015             : const char *gf_dom_get_friendly_name(u32 key_identifier);
    1016             : 
    1017           0 : static JSValue js_sys_keyname(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1018             : {
    1019             :         u32 code;
    1020           0 :         if (JS_ToInt32(ctx, &code, argv[0])) return JS_EXCEPTION;
    1021           0 :         return JS_NewString(ctx, gf_dom_get_friendly_name(code));
    1022             : }
    1023             : 
    1024             : 
    1025           1 : static JSValue js_sys_gc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1026             : {
    1027           1 :     JS_RunGC(JS_GetRuntime(ctx));
    1028           1 :     return JS_UNDEFINED;
    1029             : }
    1030             : 
    1031           1 : static JSValue js_sys_clock(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1032             : {
    1033           2 :         return JS_NewInt32(ctx, gf_sys_clock() );
    1034             : }
    1035           1 : static JSValue js_sys_clock_high_res(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1036             : {
    1037           2 :         return JS_NewInt64(ctx, gf_sys_clock_high_res() );
    1038             : }
    1039           1 : static JSValue js_sys_4cc_to_str(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1040             : {
    1041             :         u64 val;
    1042           1 :         if (!argc) return JS_EXCEPTION;
    1043           1 :         if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION;
    1044           1 :         return JS_NewString(ctx, gf_4cc_to_str((u32) val) );
    1045             : }
    1046             : 
    1047           1 : static JSValue js_sys_rand_init(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1048             : {
    1049             :         Bool reset=GF_FALSE;
    1050           1 :         if (argc) reset = JS_ToBool(ctx, argv[0]);
    1051           1 :         gf_rand_init(reset);
    1052           1 :         return JS_UNDEFINED;
    1053             : }
    1054           1 : static JSValue js_sys_rand(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1055             : {
    1056           2 :         return JS_NewInt32(ctx, gf_rand());
    1057             : }
    1058           1 : static JSValue js_sys_rand64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1059             : {
    1060           1 :         u64 lrand = (u64) gf_rand();
    1061           1 :         lrand<<=32;
    1062           1 :         lrand |= gf_rand();
    1063           2 :         return JS_NewInt64(ctx, lrand);
    1064             : }
    1065             : 
    1066           1 : static JSValue js_sys_getenv(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1067             : {
    1068             :         const char *str, *val;
    1069           1 :         if (!argc) return JS_EXCEPTION;
    1070             :         str = JS_ToCString(ctx, argv[0]);
    1071           1 :         if (!str) return JS_EXCEPTION;
    1072           1 :         val = getenv(str);
    1073           1 :         JS_FreeCString(ctx, str);
    1074           1 :         return val ? JS_NewString(ctx, val) : JS_NULL;
    1075             : }
    1076             : 
    1077           3 : static JSValue js_sys_get_utc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1078             : {
    1079             :         u32 y, mo, d, h, m, s;
    1080           3 :         if (!argc) return JS_NewInt64(ctx, gf_net_get_utc() );
    1081           2 :         if (argc==1) {
    1082             :                 u64 time;
    1083             :                 const char *date = JS_ToCString(ctx, argv[0]);
    1084           1 :                 if (!date) return JS_EXCEPTION;
    1085           1 :                 time = gf_net_parse_date(date);
    1086           1 :                 JS_FreeCString(ctx, date);
    1087           1 :                 return JS_NewInt64(ctx, time);
    1088             :         }
    1089             : 
    1090           1 :         if (argc != 6) return JS_EXCEPTION;
    1091           1 :         if (JS_ToInt32(ctx, &y, argv[0])) return JS_EXCEPTION;
    1092           1 :         if (JS_ToInt32(ctx, &mo, argv[1])) return JS_EXCEPTION;
    1093           1 :         if (JS_ToInt32(ctx, &d, argv[2])) return JS_EXCEPTION;
    1094           1 :         if (JS_ToInt32(ctx, &h, argv[3])) return JS_EXCEPTION;
    1095           1 :         if (JS_ToInt32(ctx, &m, argv[4])) return JS_EXCEPTION;
    1096           1 :         if (JS_ToInt32(ctx, &s, argv[5])) return JS_EXCEPTION;
    1097             : 
    1098           1 :         return JS_NewInt64(ctx, gf_net_get_utc_ts(y, mo, d, h, m, s) );
    1099             : }
    1100             : 
    1101           0 : static JSValue js_sys_get_ntp(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1102             : {
    1103             :         u32 sec, frac;
    1104           0 :         gf_net_get_ntp(&sec, &frac);
    1105           0 :         JSValue ret = JS_NewObject(ctx);
    1106           0 :         if (JS_IsException(ret)) return ret;
    1107           0 :         JS_SetPropertyStr(ctx, ret, "n", JS_NewInt64(ctx, sec));
    1108           0 :         JS_SetPropertyStr(ctx, ret, "d", JS_NewInt64(ctx, frac));
    1109           0 :         return ret;
    1110             : }
    1111             : 
    1112           0 : static JSValue js_sys_ntp_shift(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1113             : {
    1114             :         JSValue v;
    1115             :         u64 sec, frac, shift;
    1116             :         s64 frac_usec;
    1117           0 :         if ((argc<2) || !JS_IsObject(argv[0]))
    1118           0 :                 return JS_EXCEPTION;
    1119             : 
    1120           0 :         v = JS_GetPropertyStr(ctx, argv[0], "n");
    1121           0 :         if (JS_IsNull(v)) return JS_EXCEPTION;
    1122           0 :         JS_ToInt64(ctx, &sec, v);
    1123             :         JS_FreeValue(ctx, v);
    1124             : 
    1125           0 :         v = JS_GetPropertyStr(ctx, argv[0], "d");
    1126           0 :         if (JS_IsNull(v)) return JS_EXCEPTION;
    1127           0 :         JS_ToInt64(ctx, &frac, v);
    1128             :         JS_FreeValue(ctx, v);
    1129             : 
    1130           0 :         JS_ToInt64(ctx, &shift, argv[1]);
    1131           0 :         frac_usec = (s64) (frac * 1000000) / 0xFFFFFFFFULL;
    1132           0 :         frac_usec += shift;
    1133           0 :         while (frac_usec<0) {
    1134           0 :                 frac_usec += 1000000;
    1135           0 :                 sec -= 1;
    1136             :         }
    1137           0 :         while (frac_usec>1000000) {
    1138           0 :                 frac_usec -= 1000000;
    1139           0 :                 sec += 1;
    1140             :         }
    1141           0 :         frac = (frac_usec * 0xFFFFFFFFULL) / 1000000;
    1142           0 :         v = JS_NewObject(ctx);
    1143           0 :         if (JS_IsException(v)) return v;
    1144           0 :         JS_SetPropertyStr(ctx, v, "n", JS_NewInt64(ctx, sec));
    1145           0 :         JS_SetPropertyStr(ctx, v, "d", JS_NewInt64(ctx, frac));
    1146           0 :         return v;
    1147             : }
    1148             : 
    1149             : 
    1150           1 : static JSValue js_sys_crc32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1151             : {
    1152             :         const u8 *data;
    1153             :         size_t data_size;
    1154             : 
    1155           2 :         if (!argc || !JS_IsObject(argv[0])) return JS_EXCEPTION;
    1156           1 :         data = JS_GetArrayBuffer(ctx, &data_size, argv[0] );
    1157           1 :         if (!data) return JS_EXCEPTION;
    1158           1 :         return JS_NewInt32(ctx, gf_crc_32(data, (u32) data_size) );
    1159             : }
    1160             : 
    1161           2 : static JSValue js_sys_sha1(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1162             : {
    1163             :         u8 csum[GF_SHA1_DIGEST_SIZE];
    1164             :         const u8 *data;
    1165             :         size_t data_size;
    1166             : 
    1167           2 :         if (!argc) return JS_EXCEPTION;
    1168           4 :         if (JS_IsString(argv[0])) {
    1169             :                 const char *filename = JS_ToCString(ctx, argv[0]);
    1170           1 :                 if (!filename) return JS_EXCEPTION;
    1171           1 :                 gf_sha1_file(filename, csum);
    1172           1 :                 JS_FreeCString(ctx, filename);
    1173           1 :                 return JS_NewArrayBufferCopy(ctx, csum, GF_SHA1_DIGEST_SIZE);
    1174           1 :         } else if (JS_IsObject(argv[0])) {
    1175           1 :                 data = JS_GetArrayBuffer(ctx, &data_size, argv[0] );
    1176           1 :                 if (!data) return JS_EXCEPTION;
    1177             : 
    1178           1 :                 gf_sha1_csum((u8 *) data, (u32) data_size, csum);
    1179           1 :                 return JS_NewArrayBufferCopy(ctx, csum, GF_SHA1_DIGEST_SIZE);
    1180             :         }
    1181           0 :         return JS_EXCEPTION;
    1182             : }
    1183             : 
    1184             : 
    1185           1 : static JSValue js_sys_file_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1186             : {
    1187             :         const char *filename;
    1188             :         u8 *data;
    1189             :         u32 data_size;
    1190             :         GF_Err e;
    1191             :         JSValue res;
    1192           2 :         if (!argc || !JS_IsString(argv[0])) return JS_EXCEPTION;
    1193             :         filename = JS_ToCString(ctx, argv[0]);
    1194           1 :         if (!filename) return JS_EXCEPTION;
    1195             : 
    1196           1 :         e = gf_file_load_data(filename, &data, &data_size);
    1197           1 :         if (!data) res = js_throw_err_msg(ctx, e, "Failed to load file %s", filename);
    1198           1 :         else res = JS_NewArrayBuffer(ctx, data, data_size, js_gpac_free, NULL, 0);
    1199           1 :         JS_FreeCString(ctx, filename);
    1200           1 :         return res;
    1201             : }
    1202             : 
    1203           2 : static JSValue js_sys_compress_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool is_decomp)
    1204             : {
    1205             :         const u8 *data;
    1206             :         size_t data_size;
    1207           2 :         u32 out_size=0;
    1208           2 :         u8 *out_ptr = NULL;
    1209             :         JSValue res;
    1210             :         GF_Err e;
    1211           4 :         if (!argc || !JS_IsObject(argv[0])) return JS_EXCEPTION;
    1212           2 :         data = JS_GetArrayBuffer(ctx, &data_size, argv[0] );
    1213           2 :         if (!data) return JS_EXCEPTION;
    1214           2 :         if (is_decomp) {
    1215           1 :                 e = gf_gz_decompress_payload((u8*) data, (u32) data_size, &out_ptr, &out_size);
    1216             :         } else {
    1217           1 :                 e = gf_gz_compress_payload_ex((u8 **)&data, (u32) data_size, &out_size, 0, GF_FALSE, &out_ptr);
    1218             :         }
    1219             : 
    1220           2 :         if (e) return js_throw_err(ctx, e);
    1221           2 :         res = JS_NewArrayBuffer(ctx, out_ptr, out_size, js_gpac_free, NULL, 0);
    1222           2 :         return res;
    1223             : }
    1224           1 : static JSValue js_sys_compress(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1225             : {
    1226           1 :         return js_sys_compress_ex(ctx, this_val, argc, argv, GF_FALSE);
    1227             : }
    1228           1 : static JSValue js_sys_decompress(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1229             : {
    1230           1 :         return js_sys_compress_ex(ctx, this_val, argc, argv, GF_TRUE);
    1231             : }
    1232             : 
    1233             : enum
    1234             : {
    1235             :         OPT_RMDIR,
    1236             :         OPT_MKDIR,
    1237             :         OPT_DIREXISTS,
    1238             :         OPT_DIRCLEAN,
    1239             :         OPT_FILEBASENAME,
    1240             :         OPT_FILEEXT,
    1241             :         OPT_FILEDEL,
    1242             :         OPT_FILEMODTIME,
    1243             :         OPT_FILEEXISTS,
    1244             :         OPT_FILEMOVE,
    1245             : };
    1246             : 
    1247          10 : static JSValue js_sys_file_opt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 file_opt)
    1248             : {
    1249             :         const char *dirname, *newfile;
    1250             :         char *ext;
    1251             :         GF_Err e;
    1252             :         JSValue res;
    1253          20 :         if (!argc || !JS_IsString(argv[0])) return JS_EXCEPTION;
    1254             :         dirname = JS_ToCString(ctx, argv[0]);
    1255          10 :         if (!dirname) return JS_EXCEPTION;
    1256             : 
    1257          10 :         res = JS_UNDEFINED;
    1258          10 :         switch (file_opt) {
    1259           1 :         case OPT_RMDIR:
    1260           1 :                 e = gf_rmdir(dirname);
    1261           1 :                 if (e) res = js_throw_err_msg(ctx, e, "Failed to remove dir %s", dirname);
    1262             :                 break;
    1263           1 :         case OPT_MKDIR:
    1264           1 :                 e = gf_mkdir(dirname);
    1265           1 :                 if (e) res = js_throw_err_msg(ctx, e, "Failed to create dir %s", dirname);
    1266             :                 break;
    1267           1 :         case OPT_DIREXISTS:
    1268           1 :                 res = JS_NewBool(ctx, gf_dir_exists(dirname) );
    1269             :                 break;
    1270           1 :         case OPT_DIRCLEAN:
    1271           1 :                 e = gf_dir_cleanup(dirname);
    1272           1 :                 if (e) res = js_throw_err_msg(ctx, e, "Failed to clean dir %s", dirname);
    1273             :                 break;
    1274           1 :         case OPT_FILEBASENAME:
    1275           1 :                 res = JS_NewString(ctx, gf_file_basename(dirname) );
    1276             :                 break;
    1277           1 :         case OPT_FILEEXT:
    1278           1 :                 ext = gf_file_ext_start(dirname);
    1279           1 :                 res = ext ? JS_NewString(ctx, ext) : JS_NULL;
    1280             :                 break;
    1281           1 :         case OPT_FILEDEL:
    1282           1 :                 e = gf_file_delete(dirname);
    1283           1 :                 if (e) res = js_throw_err_msg(ctx, e, "Failed to delete file %s", dirname);
    1284             :                 break;
    1285           1 :         case OPT_FILEMODTIME:
    1286           1 :                 res = JS_NewInt64(ctx, gf_file_modification_time(dirname) );
    1287             :                 break;
    1288           1 :         case OPT_FILEEXISTS:
    1289           1 :                 res = JS_NewBool(ctx, gf_file_exists(dirname) );
    1290             :                 break;
    1291           1 :         case OPT_FILEMOVE:
    1292           1 :                 newfile = (argc<2) ? NULL : JS_ToCString(ctx, argv[1]);
    1293           1 :                 if (!newfile) res = js_throw_err_msg(ctx, GF_BAD_PARAM, "Missing new file name");
    1294             :                 else {
    1295           1 :                         e = gf_file_move(dirname, newfile);
    1296           1 :                         if (e) res = js_throw_err_msg(ctx, e, "Failed to move file %s to %s", dirname, newfile);
    1297           1 :                         JS_FreeCString(ctx, newfile);
    1298             :                 }
    1299             :                 break;
    1300             :         }
    1301             : 
    1302          10 :         JS_FreeCString(ctx, dirname);
    1303          10 :         return res;
    1304             : }
    1305             : 
    1306           1 : static JSValue js_sys_rmdir(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1307             : {
    1308           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_RMDIR);
    1309             : }
    1310           1 : static JSValue js_sys_mkdir(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1311             : {
    1312           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_MKDIR);
    1313             : }
    1314           1 : static JSValue js_sys_dir_exists(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1315             : {
    1316           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_DIREXISTS);
    1317             : }
    1318           1 : static JSValue js_sys_dir_clean(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1319             : {
    1320           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_DIRCLEAN);
    1321             : }
    1322           1 : static JSValue js_sys_basename(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1323             : {
    1324           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEBASENAME);
    1325             : }
    1326           1 : static JSValue js_sys_file_ext(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1327             : {
    1328           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEEXT);
    1329             : }
    1330           1 : static JSValue js_sys_file_exists(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1331             : {
    1332           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEEXISTS);
    1333             : }
    1334           1 : static JSValue js_sys_file_del(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1335             : {
    1336           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEDEL);
    1337             : }
    1338           1 : static JSValue js_sys_file_modtime(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1339             : {
    1340           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEMODTIME);
    1341             : }
    1342           1 : static JSValue js_sys_file_move(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1343             : {
    1344           1 :         return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEMOVE);
    1345             : }
    1346             : 
    1347             : 
    1348           1 : static JSValue js_sys_get_opt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1349             : {
    1350             :         const char *sec, *key, *val;
    1351             :         JSValue res;
    1352           1 :         if (argc!=2) return JS_EXCEPTION;
    1353             :         sec = JS_ToCString(ctx, argv[0]);
    1354           1 :         if (!sec) return JS_EXCEPTION;
    1355             :         key = JS_ToCString(ctx, argv[1]);
    1356           1 :         if (!key) {
    1357           0 :                 JS_FreeCString(ctx, sec);
    1358           0 :                 return JS_EXCEPTION;
    1359             :         }
    1360           1 :         val = gf_opts_get_key_restricted(sec, key);
    1361           1 :         res = val ? JS_NewString(ctx, val) : JS_NULL;
    1362           1 :         JS_FreeCString(ctx, sec);
    1363           1 :         JS_FreeCString(ctx, key);
    1364           1 :         return res;
    1365             : }
    1366             : 
    1367           1 : static JSValue js_sys_set_opt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1368             : {
    1369             :         const char *sec, *key, *val;
    1370           1 :         if (argc<2) return JS_EXCEPTION;
    1371             :         sec = JS_ToCString(ctx, argv[0]);
    1372           1 :         if (!sec) return JS_EXCEPTION;
    1373             :         key = JS_ToCString(ctx, argv[1]);
    1374           1 :         if (!key) {
    1375           0 :                 JS_FreeCString(ctx, sec);
    1376           0 :                 return JS_EXCEPTION;
    1377             :         }
    1378             :         val = NULL;
    1379           1 :         if (argc>2)
    1380             :                 val = JS_ToCString(ctx, argv[2]);
    1381             : 
    1382           1 :         gf_opts_set_key(sec, key, val);
    1383             : 
    1384           1 :         JS_FreeCString(ctx, sec);
    1385           1 :         JS_FreeCString(ctx, key);
    1386           1 :         if (val)
    1387           1 :                 JS_FreeCString(ctx, val);
    1388           1 :         return JS_UNDEFINED;
    1389             : }
    1390           1 : static JSValue js_sys_discard_opts(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1391             : {
    1392           1 :         gf_opts_discard_changes();
    1393           1 :         return JS_UNDEFINED;
    1394             : }
    1395             : 
    1396           4 : static JSValue js_sys_basecode_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool is_dec, Bool is_16)
    1397             : {
    1398             :         u32 out_size=0;
    1399             :         u8 *out_ptr = NULL;
    1400             :         JSValue res;
    1401             :         GF_Err e;
    1402           4 :         if (!argc) return JS_EXCEPTION;
    1403             : 
    1404           4 :         if (is_dec) {
    1405             :                 u32 len;
    1406             :                 const char *str = JS_ToCString(ctx, argv[0]);
    1407           2 :                 if (!str) return JS_EXCEPTION;
    1408           2 :                 len = (u32) strlen(str);
    1409           2 :                 out_ptr = gf_malloc(sizeof(u8) * len);
    1410           2 :                 if (!out_ptr) {
    1411             :                         e = GF_OUT_OF_MEM;
    1412           2 :                 } else if (is_16) {
    1413           1 :                         out_size = gf_base16_decode((u8*) str, (u32) len, out_ptr, len);
    1414           1 :                         e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM;
    1415             :                 } else {
    1416           1 :                         out_size = gf_base64_decode((u8*) str, (u32) len, out_ptr, len);
    1417           1 :                         e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM;
    1418             :                 }
    1419           2 :                 JS_FreeCString(ctx, str);
    1420             :         } else {
    1421             :                 const u8 *data;
    1422             :                 size_t data_size;
    1423           2 :                 data = JS_GetArrayBuffer(ctx, &data_size, argv[0] );
    1424           2 :                 if (!data) return JS_EXCEPTION;
    1425           2 :                 out_ptr = gf_malloc(sizeof(u8) * (1 + data_size * 2) );
    1426           2 :                 if (!out_ptr) {
    1427             :                         e = GF_OUT_OF_MEM;
    1428           2 :                 } else if (is_16) {
    1429           1 :                         out_size = gf_base16_encode((u8*) data, (u32) data_size, out_ptr, 1 + (u32) data_size * 2);
    1430           1 :                         e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM;
    1431             :                 } else {
    1432           1 :                         out_size = gf_base64_encode((u8*) data, (u32) data_size, out_ptr, 1 + (u32) data_size * 2);
    1433           1 :                         e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM;
    1434             :                 }
    1435             :         }
    1436             : 
    1437           4 :         if (e) return js_throw_err(ctx, e);
    1438           4 :         if (is_dec) {
    1439           2 :                 res = JS_NewArrayBuffer(ctx, out_ptr, out_size, js_gpac_free, NULL, 0);
    1440             :         } else {
    1441           2 :                 out_ptr[out_size] = 0;
    1442           2 :                 res = JS_NewString(ctx, out_ptr);
    1443           2 :                 gf_free(out_ptr);
    1444             :         }
    1445           4 :         return res;
    1446             : }
    1447           1 : static JSValue js_sys_base64enc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1448             : {
    1449           1 :         return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_FALSE, GF_FALSE);
    1450             : }
    1451           1 : static JSValue js_sys_base64dec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1452             : {
    1453           1 :         return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_TRUE, GF_FALSE);
    1454             : }
    1455           1 : static JSValue js_sys_base16enc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1456             : {
    1457           1 :         return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_FALSE, GF_TRUE);
    1458             : }
    1459           1 : static JSValue js_sys_base16dec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1460             : {
    1461           1 :         return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_TRUE, GF_TRUE);
    1462             : }
    1463           1 : static JSValue js_sys_ntohl(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1464             : {
    1465             :         s64 val;
    1466           1 :         if (!argc) return JS_EXCEPTION;
    1467           1 :         if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION;
    1468           1 :         return JS_NewInt32(ctx, gf_ntohl((u32) val));
    1469             : }
    1470           1 : static JSValue js_sys_ntohs(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1471             : {
    1472             :         s64 val;
    1473           1 :         if (!argc) return JS_EXCEPTION;
    1474           1 :         if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION;
    1475           1 :         return JS_NewInt32(ctx, gf_ntohs((u16) val));
    1476             : }
    1477           1 : static JSValue js_sys_htonl(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1478             : {
    1479             :         s64 val;
    1480           1 :         if (!argc) return JS_EXCEPTION;
    1481           1 :         if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION;
    1482           1 :         return JS_NewInt32(ctx, gf_htonl((u32) val));
    1483             : }
    1484           1 : static JSValue js_sys_htons(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1485             : {
    1486             :         s64 val;
    1487           1 :         if (!argc) return JS_EXCEPTION;
    1488           1 :         if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION;
    1489           1 :         return JS_NewInt32(ctx, gf_htons((u16) val));
    1490             : }
    1491             : 
    1492             : static const JSCFunctionListEntry sys_funcs[] = {
    1493             :     JS_CGETSET_MAGIC_DEF_ENUM("nb_cores", js_sys_prop_get, NULL, JS_SYS_NB_CORES),
    1494             :     JS_CGETSET_MAGIC_DEF_ENUM("sampling_period_duration", js_sys_prop_get, NULL, JS_SYS_SAMPLE_DUR),
    1495             :     JS_CGETSET_MAGIC_DEF_ENUM("total_cpu_time", js_sys_prop_get, NULL, JS_SYS_TOTAL_CPU),
    1496             :     JS_CGETSET_MAGIC_DEF_ENUM("process_cpu_time", js_sys_prop_get, NULL, JS_SYS_PROCESS_CPU),
    1497             :     JS_CGETSET_MAGIC_DEF_ENUM("total_cpu_time_diff", js_sys_prop_get, NULL, JS_SYS_TOTAL_CPU_DIFF),
    1498             :     JS_CGETSET_MAGIC_DEF_ENUM("process_cpu_time_diff", js_sys_prop_get, NULL, JS_SYS_PROCESS_CPU_DIFF),
    1499             :     JS_CGETSET_MAGIC_DEF_ENUM("cpu_idle_time", js_sys_prop_get, NULL, JS_SYS_CPU_IDLE),
    1500             :     JS_CGETSET_MAGIC_DEF_ENUM("total_cpu_usage", js_sys_prop_get, NULL, JS_SYS_TOTAL_CPU_USAGE),
    1501             :     JS_CGETSET_MAGIC_DEF_ENUM("process_cpu_usage", js_sys_prop_get, NULL, JS_SYS_PROCESS_CPU_USAGE),
    1502             :     JS_CGETSET_MAGIC_DEF_ENUM("pid", js_sys_prop_get, NULL, JS_SYS_PID),
    1503             :     JS_CGETSET_MAGIC_DEF_ENUM("thread_count", js_sys_prop_get, NULL, JS_SYS_THREADS),
    1504             :     JS_CGETSET_MAGIC_DEF_ENUM("process_memory", js_sys_prop_get, NULL, JS_SYS_PROCESS_MEM),
    1505             :     JS_CGETSET_MAGIC_DEF_ENUM("physical_memory", js_sys_prop_get, NULL, JS_SYS_TOTAL_MEM),
    1506             :     JS_CGETSET_MAGIC_DEF_ENUM("physical_memory_avail", js_sys_prop_get, NULL, JS_SYS_TOTAL_MEM_AVAIL),
    1507             :     JS_CGETSET_MAGIC_DEF_ENUM("gpac_memory", js_sys_prop_get, NULL, JS_SYS_GPAC_MEM),
    1508             : 
    1509             :         JS_CGETSET_MAGIC_DEF_ENUM("last_wdir", js_sys_prop_get, js_sys_prop_set, JS_SYS_LAST_WORK_DIR),
    1510             :         JS_CGETSET_MAGIC_DEF_ENUM("batteryOn", js_sys_prop_get, NULL, JS_SYS_BATTERY_ON),
    1511             :         JS_CGETSET_MAGIC_DEF_ENUM("batteryCharging", js_sys_prop_get, NULL, JS_SYS_BATTERY_CHARGE),
    1512             :         JS_CGETSET_MAGIC_DEF_ENUM("batteryPercent", js_sys_prop_get, NULL, JS_SYS_BATTERY_PERCENT),
    1513             :         JS_CGETSET_MAGIC_DEF_ENUM("batteryLifeTime", js_sys_prop_get, NULL, JS_SYS_BATTERY_LIFETIME),
    1514             :         JS_CGETSET_MAGIC_DEF_ENUM("batteryFullLifeTime", js_sys_prop_get, NULL, JS_SYS_BATTERY_LIFETIME_FULL),
    1515             :         JS_CGETSET_MAGIC_DEF_ENUM("hostname", js_sys_prop_get, NULL, JS_SYS_HOSTNAME),
    1516             :         JS_CGETSET_MAGIC_DEF_ENUM("username", js_sys_prop_get, NULL, JS_SYS_USERNAME),
    1517             : 
    1518             :         JS_CGETSET_MAGIC_DEF_ENUM("test_mode", js_sys_prop_get, NULL, JS_SYS_TEST_MODE),
    1519             :         JS_CGETSET_MAGIC_DEF_ENUM("old_arch", js_sys_prop_get, NULL, JS_SYS_OLD_ARCH),
    1520             :         JS_CGETSET_MAGIC_DEF_ENUM("log_color", js_sys_prop_get, NULL, JS_SYS_LOG_COLOR),
    1521             : 
    1522             :         JS_CGETSET_MAGIC_DEF_ENUM("quiet", js_sys_prop_get, NULL, JS_SYS_QUIET),
    1523             :         JS_CGETSET_MAGIC_DEF_ENUM("timezone", js_sys_prop_get, NULL, JS_SYS_TIMEZONE),
    1524             :         JS_CGETSET_MAGIC_DEF_ENUM("nb_files_open", js_sys_prop_get, NULL, JS_SYS_FILES_OPEN),
    1525             :         JS_CGETSET_MAGIC_DEF_ENUM("cache_dir", js_sys_prop_get, NULL, JS_SYS_CACHE_DIR),
    1526             :         JS_CGETSET_MAGIC_DEF_ENUM("shared_dir", js_sys_prop_get, NULL, JS_SYS_SHARED_DIR),
    1527             :         JS_CGETSET_MAGIC_DEF_ENUM("version", js_sys_prop_get, NULL, JS_SYS_VERSION),
    1528             :         JS_CGETSET_MAGIC_DEF_ENUM("version_full", js_sys_prop_get, NULL, JS_SYS_VERSION_FULL),
    1529             :         JS_CGETSET_MAGIC_DEF_ENUM("copyright", js_sys_prop_get, NULL, JS_SYS_COPYRIGHT),
    1530             :         JS_CGETSET_MAGIC_DEF_ENUM("version_major", js_sys_prop_get, NULL, JS_SYS_V_MAJOR),
    1531             :         JS_CGETSET_MAGIC_DEF_ENUM("version_minor", js_sys_prop_get, NULL, JS_SYS_V_MINOR),
    1532             :         JS_CGETSET_MAGIC_DEF_ENUM("version_micro", js_sys_prop_get, NULL, JS_SYS_V_MICRO),
    1533             : 
    1534             :         JS_CFUNC_DEF("set_arg_used", 0, js_sys_set_arg_used),
    1535             :         JS_CFUNC_DEF("error_string", 0, js_sys_error_string),
    1536             :     JS_CFUNC_DEF("prompt_input", 0, js_sys_prompt_input),
    1537             :     JS_CFUNC_DEF("prompt_string", 0, js_sys_prompt_string),
    1538             :     JS_CFUNC_DEF("prompt_echo_off", 0, js_sys_prompt_echo_off),
    1539             :     JS_CFUNC_DEF("prompt_code", 0, js_sys_prompt_code),
    1540             :     JS_CFUNC_DEF("prompt_size", 0, js_sys_prompt_size),
    1541             : 
    1542             :     JS_CFUNC_DEF("keyname", 0, js_sys_keyname),
    1543             :     JS_CFUNC_DEF("gc", 0, js_sys_gc),
    1544             : 
    1545             :         JS_CFUNC_DEF("enum_directory", 0, js_sys_enum_directory),
    1546             :         JS_CFUNC_DEF("clock_ms", 0, js_sys_clock),
    1547             :         JS_CFUNC_DEF("clock_us", 0, js_sys_clock_high_res),
    1548             :         JS_CFUNC_DEF("fcc_to_str", 0, js_sys_4cc_to_str),
    1549             :         JS_CFUNC_DEF("rand_init", 0, js_sys_rand_init),
    1550             :         JS_CFUNC_DEF("rand", 0, js_sys_rand),
    1551             :         JS_CFUNC_DEF("rand64", 0, js_sys_rand64),
    1552             :         JS_CFUNC_DEF("getenv", 0, js_sys_getenv),
    1553             :         JS_CFUNC_DEF("get_utc", 0, js_sys_get_utc),
    1554             :         JS_CFUNC_DEF("get_ntp", 0, js_sys_get_ntp),
    1555             :         JS_CFUNC_DEF("ntp_shift", 0, js_sys_ntp_shift),
    1556             :         JS_CFUNC_DEF("crc32", 0, js_sys_crc32),
    1557             :         JS_CFUNC_DEF("sha1", 0, js_sys_sha1),
    1558             :         JS_CFUNC_DEF("load_file", 0, js_sys_file_data),
    1559             :         JS_CFUNC_DEF("compress", 0, js_sys_compress),
    1560             :         JS_CFUNC_DEF("decompress", 0, js_sys_decompress),
    1561             :         JS_CFUNC_DEF("rmdir", 0, js_sys_rmdir),
    1562             :         JS_CFUNC_DEF("mkdir", 0, js_sys_mkdir),
    1563             :         JS_CFUNC_DEF("dir_exists", 0, js_sys_dir_exists),
    1564             :         JS_CFUNC_DEF("dir_clean", 0, js_sys_dir_clean),
    1565             :         JS_CFUNC_DEF("basename", 0, js_sys_basename),
    1566             :         JS_CFUNC_DEF("file_ext", 0, js_sys_file_ext),
    1567             :         JS_CFUNC_DEF("file_exists", 0, js_sys_file_exists),
    1568             :         JS_CFUNC_DEF("del", 0, js_sys_file_del),
    1569             :         JS_CFUNC_DEF("mod_time", 0, js_sys_file_modtime),
    1570             :         JS_CFUNC_DEF("move", 0, js_sys_file_move),
    1571             :         JS_CFUNC_DEF("get_opt", 0, js_sys_get_opt),
    1572             :         JS_CFUNC_DEF("set_opt", 0, js_sys_set_opt),
    1573             :         JS_CFUNC_DEF("discard_opts", 0, js_sys_discard_opts),
    1574             : 
    1575             :         JS_CFUNC_DEF("base64enc", 0, js_sys_base64enc),
    1576             :         JS_CFUNC_DEF("base64dec", 0, js_sys_base64dec),
    1577             :         JS_CFUNC_DEF("base16enc", 0, js_sys_base16enc),
    1578             :         JS_CFUNC_DEF("base16dec", 0, js_sys_base16dec),
    1579             : 
    1580             :         JS_CFUNC_DEF("ntohl", 0, js_sys_ntohl),
    1581             :         JS_CFUNC_DEF("ntohs", 0, js_sys_ntohs),
    1582             :         JS_CFUNC_DEF("htonl", 0, js_sys_htonl),
    1583             :         JS_CFUNC_DEF("htons", 0, js_sys_htons),
    1584             : 
    1585             : };
    1586             : 
    1587             : 
    1588          40 : static void js_sha1_finalize(JSRuntime *rt, JSValue obj)
    1589             : {
    1590          40 :         GF_SHA1Context *sha1 = JS_GetOpaque(obj, sha1_class_id);
    1591          40 :         if (!sha1) return;
    1592           0 :         gf_free(sha1);
    1593             : }
    1594             : 
    1595             : JSClassDef sha1Class = {
    1596             :     "SHA1",
    1597             :     .finalizer = js_sha1_finalize,
    1598             : };
    1599             : 
    1600           1 : static JSValue js_sha1_push(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1601             : {
    1602             :         const u8 *data;
    1603             :         size_t data_size;
    1604           1 :         GF_SHA1Context *sha1 = JS_GetOpaque(this_val, sha1_class_id);
    1605           1 :         if (!sha1) {
    1606           0 :                 sha1 = gf_sha1_starts();
    1607           0 :                 if (!sha1) {
    1608           0 :                         return js_throw_err(ctx, GF_OUT_OF_MEM);
    1609             :                 }
    1610           0 :                 JS_SetOpaque(this_val, sha1);
    1611             :         }
    1612           1 :         if (!argc) return JS_EXCEPTION;
    1613           1 :         data = JS_GetArrayBuffer(ctx, &data_size, argv[0]);
    1614           1 :         gf_sha1_update(sha1, (u8 *) data, (u32) data_size);
    1615             : 
    1616           1 :         return JS_UNDEFINED;
    1617             : }
    1618           1 : static JSValue js_sha1_get(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1619             : {
    1620             :         u8 output[GF_SHA1_DIGEST_SIZE];
    1621           1 :         GF_SHA1Context *sha1 = JS_GetOpaque(this_val, sha1_class_id);
    1622           1 :         if (!sha1) return JS_EXCEPTION;
    1623           1 :         gf_sha1_finish(sha1, output);
    1624           1 :         JS_SetOpaque(this_val, NULL);
    1625           1 :         return JS_NewArrayBufferCopy(ctx, output, GF_SHA1_DIGEST_SIZE);
    1626             : }
    1627             : 
    1628             : static const JSCFunctionListEntry sha1_funcs[] = {
    1629             :         JS_CFUNC_DEF("push", 0, js_sha1_push),
    1630             :         JS_CFUNC_DEF("get", 0, js_sha1_get),
    1631             : };
    1632             : 
    1633           1 : static JSValue sha1_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
    1634             : {
    1635             :         JSValue anobj;
    1636             :         GF_SHA1Context *sha1;
    1637             : 
    1638           1 :         sha1 = gf_sha1_starts();
    1639           1 :         if (!sha1) {
    1640           0 :                 return js_throw_err(ctx, GF_OUT_OF_MEM);
    1641             :         }
    1642           1 :         anobj = JS_NewObjectClass(ctx, sha1_class_id);
    1643           1 :         if (JS_IsException(anobj)) {
    1644           0 :                 gf_free(sha1);
    1645           0 :                 return anobj;
    1646             :         }
    1647           1 :         JS_SetOpaque(anobj, sha1);
    1648           1 :         return anobj;
    1649             : }
    1650             : 
    1651             : 
    1652          42 : static void js_file_finalize(JSRuntime *rt, JSValue obj)
    1653             : {
    1654          42 :         FILE *f = JS_GetOpaque(obj, file_class_id);
    1655          42 :         if (!f) return;
    1656           0 :         gf_fclose(f);
    1657             : }
    1658             : 
    1659             : JSClassDef fileClass = {
    1660             :     "FILE",
    1661             :     .finalizer = js_file_finalize,
    1662             : };
    1663             : 
    1664             : enum
    1665             : {
    1666             :         JS_FILE_POS = 0,
    1667             :         JS_FILE_EOF,
    1668             :         JS_FILE_ERROR,
    1669             :         JS_FILE_SIZE,
    1670             :         JS_FILE_IS_GFIO,
    1671             : };
    1672             : 
    1673           5 : static JSValue js_file_prop_get(JSContext *ctx, JSValueConst this_val, int magic)
    1674             : {
    1675           5 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1676           5 :         if (!f) return JS_EXCEPTION;
    1677             : 
    1678           5 :         switch (magic) {
    1679           1 :         case JS_FILE_POS:
    1680           1 :                 return JS_NewInt64(ctx, gf_ftell(f));
    1681           1 :         case JS_FILE_EOF:
    1682           1 :                 return JS_NewBool(ctx, gf_feof(f));
    1683           1 :         case JS_FILE_ERROR:
    1684           1 :                 return JS_NewInt32(ctx, gf_ferror(f) );
    1685           1 :         case JS_FILE_SIZE:
    1686           1 :                 return JS_NewInt64(ctx, gf_fsize(f) );
    1687           1 :         case JS_FILE_IS_GFIO:
    1688           1 :                 return JS_NewBool(ctx, gf_fileio_check(f));
    1689             :         }
    1690           0 :         return JS_UNDEFINED;
    1691             : }
    1692             : 
    1693           1 : static JSValue js_file_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
    1694             : {
    1695             :         s64 lival;
    1696           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1697           1 :         if (!f) return JS_EXCEPTION;
    1698             : 
    1699           1 :         switch (magic) {
    1700           1 :         case JS_FILE_POS:
    1701           1 :                 if (JS_ToInt64(ctx, &lival, value)) return JS_EXCEPTION;
    1702           1 :                 gf_fseek(f, lival, SEEK_SET);
    1703           1 :                 break;
    1704             :         }
    1705           1 :         return JS_UNDEFINED;
    1706             : }
    1707           1 : static JSValue js_file_flush(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1708             : {
    1709           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1710           1 :         if (!f) return JS_EXCEPTION;
    1711           1 :         gf_fflush(f);
    1712           1 :         return JS_UNDEFINED;
    1713             : }
    1714           3 : static JSValue js_file_close(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1715             : {
    1716           3 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1717           3 :         if (!f) return JS_EXCEPTION;
    1718           3 :         gf_fclose(f);
    1719           3 :         JS_SetOpaque(this_val, NULL);
    1720           3 :         return JS_UNDEFINED;
    1721             : }
    1722           1 : static JSValue js_file_read(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1723             : {
    1724             :         const u8 *data;
    1725             :         size_t size;
    1726             :         u32 read;
    1727           1 :         s32 nb_bytes=0;
    1728           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1729           1 :         if (!f) return JS_EXCEPTION;
    1730           1 :         if (!argc) return JS_EXCEPTION;
    1731             : 
    1732           1 :         data = JS_GetArrayBuffer(ctx, &size, argv[0]);
    1733           1 :         if (!data) return JS_EXCEPTION;
    1734           1 :         if (argc>1) {
    1735           0 :                 if (JS_ToInt32(ctx, &nb_bytes, argv[1])) return JS_EXCEPTION;
    1736             :         }
    1737           1 :         if (!nb_bytes) nb_bytes = (s32) size;
    1738           0 :         else if (nb_bytes > (s32) size) nb_bytes = (s32) size;
    1739             : 
    1740           1 :         read = (u32) gf_fread((void *) data, nb_bytes, f);
    1741           1 :         return JS_NewInt64(ctx, read);
    1742             : }
    1743           1 : static JSValue js_file_gets(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1744             : {
    1745           1 :         char *data=NULL;
    1746             :         char temp[1025];
    1747             :         JSValue res;
    1748           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1749           1 :         if (!f) return JS_EXCEPTION;
    1750             : 
    1751           1 :         temp[1024] = 0;
    1752             :         while (1) {
    1753             :                 u32 rlen;
    1754           1 :                 temp[0] = 0;
    1755           1 :                 const char *read = gf_fgets(temp, 1024, f);
    1756           1 :                 if (!read) break;
    1757           1 :                 gf_dynstrcat(&data, temp, NULL);
    1758           1 :                 if (!data) return js_throw_err(ctx, GF_OUT_OF_MEM);
    1759           1 :                 rlen = (u32) strlen(temp);
    1760           1 :                 if (rlen <= 1024)
    1761             :                         break;
    1762           0 :                 if (temp[rlen-1] == '\n')
    1763             :                         break;
    1764             :         }
    1765           1 :         res = JS_NewString(ctx, data);
    1766           1 :         gf_free(data);
    1767           1 :         return res;
    1768             : }
    1769             : 
    1770           1 : static JSValue js_file_getc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1771             : {
    1772             :         char res[2];
    1773           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1774           1 :         if (!f) return JS_EXCEPTION;
    1775             : 
    1776           1 :         res[0] = gf_fgetc(f);
    1777           1 :         res[1] = 0;
    1778           1 :         return JS_NewString(ctx, res);
    1779             : }
    1780             : 
    1781           1 : static JSValue js_file_write(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1782             : {
    1783             :         const u8 *data;
    1784             :         size_t size;
    1785             :         u32 read;
    1786           1 :         s32 nb_bytes=0;
    1787           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1788           1 :         if (!f) return JS_EXCEPTION;
    1789           1 :         if (!argc) return JS_EXCEPTION;
    1790             : 
    1791           1 :         data = JS_GetArrayBuffer(ctx, &size, argv[0]);
    1792           1 :         if (!data) return JS_EXCEPTION;
    1793           1 :         if (argc>1) {
    1794           0 :                 if (JS_ToInt32(ctx, &nb_bytes, argv[1])) return JS_EXCEPTION;
    1795             :         }
    1796           1 :         if (!nb_bytes) nb_bytes = (u32) size;
    1797           0 :         else if (nb_bytes > (s32) size) nb_bytes = (u32) size;
    1798             : 
    1799           1 :         read = (u32) gf_fwrite((void *) data, nb_bytes, f);
    1800           1 :         return JS_NewInt64(ctx, read);
    1801             : }
    1802           1 : static JSValue js_file_puts(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1803             : {
    1804             :         const char *string;
    1805           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1806           1 :         if (!f || !argc) return JS_EXCEPTION;
    1807             : 
    1808             :         string = JS_ToCString(ctx, argv[0]);
    1809           1 :         if (!string) return JS_EXCEPTION;
    1810           1 :         gf_fputs(string, f);
    1811           1 :         JS_FreeCString(ctx, string);
    1812           1 :         return JS_UNDEFINED;
    1813             : }
    1814             : 
    1815           1 : static JSValue js_file_putc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
    1816             : {
    1817           1 :         int val=0;
    1818           1 :         FILE *f = JS_GetOpaque(this_val, file_class_id);
    1819           1 :         if (!f || !argc) return JS_EXCEPTION;
    1820             : 
    1821           2 :         if (JS_IsString(argv[0])) {
    1822             :                 const char *string = JS_ToCString(ctx, argv[0]);
    1823           1 :                 if (!string) return JS_EXCEPTION;
    1824           1 :                 val = string[0];
    1825           1 :                 JS_FreeCString(ctx, string);
    1826             :         } else {
    1827           0 :                 if (JS_ToInt32(ctx, &val, argv[0])) return JS_EXCEPTION;
    1828             :         }
    1829           1 :         gf_fputc(val, f);
    1830           1 :         return JS_UNDEFINED;
    1831             : }
    1832             : 
    1833             : static const JSCFunctionListEntry file_funcs[] = {
    1834             :     JS_CGETSET_MAGIC_DEF_ENUM("pos", js_file_prop_get, js_file_prop_set, JS_FILE_POS),
    1835             :     JS_CGETSET_MAGIC_DEF_ENUM("eof", js_file_prop_get, NULL, JS_FILE_EOF),
    1836             :     JS_CGETSET_MAGIC_DEF_ENUM("error", js_file_prop_get, NULL, JS_FILE_ERROR),
    1837             :     JS_CGETSET_MAGIC_DEF_ENUM("size", js_file_prop_get, NULL, JS_FILE_SIZE),
    1838             :     JS_CGETSET_MAGIC_DEF_ENUM("gfio", js_file_prop_get, NULL, JS_FILE_IS_GFIO),
    1839             : 
    1840             :         JS_CFUNC_DEF("flush", 0, js_file_flush),
    1841             :         JS_CFUNC_DEF("close", 0, js_file_close),
    1842             :         JS_CFUNC_DEF("read", 0, js_file_read),
    1843             :         JS_CFUNC_DEF("gets", 0, js_file_gets),
    1844             :         JS_CFUNC_DEF("getc", 0, js_file_getc),
    1845             :         JS_CFUNC_DEF("write", 0, js_file_write),
    1846             :         JS_CFUNC_DEF("puts", 0, js_file_puts),
    1847             :         JS_CFUNC_DEF("putc", 0, js_file_putc),
    1848             : };
    1849             : 
    1850           3 : static JSValue file_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
    1851             : {
    1852             :         JSValue anobj;
    1853             :         FILE *f=NULL;
    1854             : 
    1855           3 :         if (!argc) {
    1856           1 :                 f = gf_file_temp(NULL);
    1857           1 :                 if (!f) {
    1858           0 :                         return js_throw_err(ctx, GF_OUT_OF_MEM);
    1859             :                 }
    1860             :         } else {
    1861             :                 GF_Err e = GF_OK;
    1862             :                 const char *name=NULL, *mode=NULL, *parent_io=NULL;
    1863             :                 name = JS_ToCString(ctx, argv[0] );
    1864           2 :                 if (argc>1) {
    1865             :                         mode = JS_ToCString(ctx, argv[1] );
    1866           2 :                         if (argc>2) {
    1867             :                                 parent_io = JS_ToCString(ctx, argv[2] );
    1868             :                         }
    1869             :                 }
    1870             : 
    1871           2 :                 if (!name || !mode) {
    1872             :                         e = GF_BAD_PARAM;
    1873             :                 } else {
    1874           2 :                         f = gf_fopen_ex(name, parent_io, mode);
    1875           2 :                         if (!f) e = GF_URL_ERROR;
    1876             :                 }
    1877           2 :                 if (name) JS_FreeCString(ctx, name);
    1878           2 :                 if (mode) JS_FreeCString(ctx, mode);
    1879           2 :                 if (parent_io) JS_FreeCString(ctx, parent_io);
    1880             : 
    1881           2 :                 if (e) {
    1882           0 :                         return js_throw_err(ctx, e);
    1883             :                 }
    1884             :         }
    1885             : 
    1886           3 :         anobj = JS_NewObjectClass(ctx, file_class_id);
    1887           3 :         if (JS_IsException(anobj)) {
    1888           0 :                 gf_fclose(f);
    1889           0 :                 return anobj;
    1890             :         }
    1891           3 :         JS_SetOpaque(anobj, f);
    1892           3 :         return anobj;
    1893             : }
    1894             : 
    1895             : 
    1896          39 : static int js_gpaccore_init(JSContext *ctx, JSModuleDef *m)
    1897             : {
    1898             :         JSValue proto, ctor;
    1899          39 :         if (!bitstream_class_id) {
    1900          39 :                 JS_NewClassID(&bitstream_class_id);
    1901          39 :                 JS_NewClass(JS_GetRuntime(ctx), bitstream_class_id, &bitstreamClass);
    1902             : 
    1903          39 :                 JS_NewClassID(&sha1_class_id);
    1904          39 :                 JS_NewClass(JS_GetRuntime(ctx), sha1_class_id, &sha1Class);
    1905             : 
    1906          39 :                 JS_NewClassID(&file_class_id);
    1907          39 :                 JS_NewClass(JS_GetRuntime(ctx), file_class_id, &fileClass);
    1908             :         }
    1909             : 
    1910          39 :         JSValue core_o = JS_NewObject(ctx);
    1911          39 :         JS_SetPropertyFunctionList(ctx, core_o, sys_funcs, countof(sys_funcs));
    1912          39 :     JS_SetModuleExport(ctx, m, "Sys", core_o);
    1913             : 
    1914          39 :         JSValue args = JS_NewArray(ctx);
    1915          39 :     u32 i, nb_args = gf_sys_get_argc();
    1916         415 :     for (i=0; i<nb_args; i++) {
    1917         376 :         JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, gf_sys_get_arg(i)));
    1918             :     }
    1919          39 :     JS_SetPropertyStr(ctx, core_o, "args", args);
    1920             : 
    1921             : #define DEF_CONST( _val ) \
    1922             :     JS_SetPropertyStr(ctx, core_o, #_val, JS_NewInt32(ctx, _val));
    1923             : 
    1924          39 :         DEF_CONST(GF_CONSOLE_RESET)
    1925          39 :         DEF_CONST(GF_CONSOLE_RED)
    1926          39 :         DEF_CONST(GF_CONSOLE_GREEN)
    1927          39 :         DEF_CONST(GF_CONSOLE_BLUE)
    1928          39 :         DEF_CONST(GF_CONSOLE_YELLOW)
    1929          39 :         DEF_CONST(GF_CONSOLE_CYAN)
    1930          39 :         DEF_CONST(GF_CONSOLE_WHITE)
    1931          39 :         DEF_CONST(GF_CONSOLE_MAGENTA)
    1932          39 :         DEF_CONST(GF_CONSOLE_CLEAR)
    1933          39 :         DEF_CONST(GF_CONSOLE_SAVE)
    1934          39 :         DEF_CONST(GF_CONSOLE_RESTORE)
    1935          39 :         DEF_CONST(GF_CONSOLE_BOLD)
    1936          39 :         DEF_CONST(GF_CONSOLE_ITALIC)
    1937          39 :         DEF_CONST(GF_CONSOLE_UNDERLINED)
    1938          39 :         DEF_CONST(GF_CONSOLE_STRIKE)
    1939             : 
    1940             : #undef DEF_CONST
    1941             : 
    1942             : 
    1943             :         //bitstream constructor
    1944          39 :         proto = JS_NewObjectClass(ctx, bitstream_class_id);
    1945          39 :         JS_SetPropertyFunctionList(ctx, proto, bitstream_funcs, countof(bitstream_funcs));
    1946          39 :         JS_SetClassProto(ctx, bitstream_class_id, proto);
    1947          39 :         ctor = JS_NewCFunction2(ctx, bitstream_constructor, "Bitstream", 1, JS_CFUNC_constructor, 0);
    1948          39 :     JS_SetModuleExport(ctx, m, "Bitstream", ctor);
    1949             : 
    1950             :         //sha1 constructor
    1951          39 :         proto = JS_NewObjectClass(ctx, sha1_class_id);
    1952          39 :         JS_SetPropertyFunctionList(ctx, proto, sha1_funcs, countof(sha1_funcs));
    1953          39 :         JS_SetClassProto(ctx, sha1_class_id, proto);
    1954          39 :         ctor = JS_NewCFunction2(ctx, sha1_constructor, "SHA1", 1, JS_CFUNC_constructor, 0);
    1955          39 :     JS_SetModuleExport(ctx, m, "SHA1", ctor);
    1956             : 
    1957             :         //FILE constructor
    1958          39 :         proto = JS_NewObjectClass(ctx, file_class_id);
    1959          39 :         JS_SetPropertyFunctionList(ctx, proto, file_funcs, countof(file_funcs));
    1960          39 :         JS_SetClassProto(ctx, file_class_id, proto);
    1961          39 :         ctor = JS_NewCFunction2(ctx, file_constructor, "File", 1, JS_CFUNC_constructor, 0);
    1962          39 :     JS_SetModuleExport(ctx, m, "File", ctor);
    1963             : 
    1964          39 :         return 0;
    1965             : }
    1966             : 
    1967             : 
    1968         468 : void qjs_module_init_gpaccore(JSContext *ctx)
    1969             : {
    1970             :         JSModuleDef *m;
    1971         468 :         m = JS_NewCModule(ctx, "gpaccore", js_gpaccore_init);
    1972         468 :         if (!m) return;
    1973             : 
    1974         468 :         JS_AddModuleExport(ctx, m, "Sys");
    1975         468 :         JS_AddModuleExport(ctx, m, "Bitstream");
    1976         468 :         JS_AddModuleExport(ctx, m, "SHA1");
    1977         468 :         JS_AddModuleExport(ctx, m, "File");
    1978         468 :         return;
    1979             : }
    1980             : 
    1981             : 
    1982             : #endif
    1983             : 

Generated by: LCOV version 1.13