Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2019-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / QuickJS bindings for GF_Filter
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 : /*
28 : ANY CHANGE TO THE API MUST BE REFLECTED IN THE DOCUMENTATION IN gpac/share/doc/idl/jsf.idl
29 : (no way to define inline JS doc with doxygen)
30 : */
31 :
32 : #include <gpac/filters.h>
33 : #include <gpac/list.h>
34 : #include <gpac/constants.h>
35 : #include <gpac/network.h>
36 :
37 : #ifdef GPAC_HAS_QJS
38 :
39 : #include <gpac/internal/scenegraph_dev.h>
40 : #include "../scenegraph/qjs_common.h"
41 :
42 :
43 : //to load session API
44 : #include "../filter_core/filter_session.h"
45 :
46 : /*
47 : Currently unmapped functions
48 :
49 : //likely not needed
50 : u32 gf_filter_count_source_by_protocol (GF_Filter *filter, const char *protocol_scheme, Bool expand_proto, GF_FilterPid *(*enum_pids)(void *udta, u32 *idx), void *udta)
51 : GF_FilterPacket * gf_filter_pck_new_frame_interface (GF_FilterPid *PID, GF_FilterFrameInterface *frame_ifce, gf_fsess_packet_destructor destruct)
52 : GF_FilterFrameInterface * gf_filter_pck_get_frame_interface (GF_FilterPacket *pck)
53 :
54 : //todo
55 : GF_Err gf_filter_add_event_listener (GF_Filter *filter, GF_FSEventListener *el)
56 : GF_Err gf_filter_remove_event_listener (GF_Filter *filter, GF_FSEventListener *el)
57 : Bool gf_filter_forward_gf_event (GF_Filter *filter, GF_Event *evt, Bool consumed, Bool skip_user)
58 : Bool gf_filter_send_gf_event (GF_Filter *filter, GF_Event *evt)
59 : Bool gf_filter_ui_event (GF_Filter *filter, GF_Event *uievt)
60 : void gf_filter_register_opengl_provider (GF_Filter *filter, Bool do_register)
61 : GF_Err gf_filter_request_opengl (GF_Filter *filter)
62 :
63 : //either not needed or require a dedicated module
64 : GF_DownloadManager *gf_filter_get_download_manager (GF_Filter *filter)
65 :
66 :
67 : */
68 :
69 : enum
70 : {
71 : JSF_EVT_INITIALIZE=0,
72 : JSF_EVT_FINALIZE,
73 : JSF_EVT_CONFIGURE_PID,
74 : JSF_EVT_PROCESS,
75 : JSF_EVT_PROCESS_EVENT,
76 : JSF_EVT_UPDATE_ARG,
77 : JSF_EVT_PROBE_URL,
78 : JSF_EVT_PROBE_DATA,
79 : JSF_EVT_RECONFIGURE_OUTPUT,
80 : JSF_EVT_REMOVE_PID,
81 :
82 : JSF_EVT_LAST_DEFINED,
83 :
84 : JSF_FILTER_MAX_PIDS,
85 : JSF_FILTER_BLOCK_ENABLED,
86 : JSF_FILTER_OUTPUT_BUFFER,
87 : JSF_FILTER_OUTPUT_PLAYOUT,
88 : JSF_FILTER_SEP_ARGS,
89 : JSF_FILTER_SEP_NAME,
90 : JSF_FILTER_SEP_LIST,
91 : JSF_FILTER_DST_ARGS,
92 : JSF_FILTER_DST_NAME,
93 : JSF_FILTER_SINKS_DONE,
94 : JSF_FILTER_REPORTING_ENABLED,
95 :
96 : JSF_FILTER_CAPS_MAX_WIDTH,
97 : JSF_FILTER_CAPS_MAX_HEIGHT,
98 : JSF_FILTER_CAPS_MAX_DISPLAY_DEPTH,
99 : JSF_FILTER_CAPS_MAX_FPS,
100 : JSF_FILTER_CAPS_MAX_VIEWS,
101 : JSF_FILTER_CAPS_MAX_CHANNELS,
102 : JSF_FILTER_CAPS_MAX_SAMPLERATE,
103 : JSF_FILTER_CAPS_MAX_AUDIO_DEPTH,
104 : JSF_FILTER_NB_EVTS_QUEUED,
105 : JSF_FILTER_CLOCK_HINT_TIME,
106 : JSF_FILTER_CLOCK_HINT_MEDIATIME,
107 : JSF_FILTER_CONNECTIONS_PENDING,
108 : JSF_FILTER_INAME
109 : };
110 :
111 : enum
112 : {
113 : JSF_SETUP_ERROR=0,
114 : JSF_NOTIF_ERROR,
115 : JSF_NOTIF_ERROR_AND_DISCONNECT
116 : };
117 :
118 :
119 : typedef struct
120 : {
121 : //options
122 : const char *js;
123 :
124 : GF_Filter *filter;
125 : Bool is_custom;
126 :
127 : JSContext *ctx;
128 :
129 : Bool initialized;
130 : JSValue funcs[JSF_EVT_LAST_DEFINED];
131 : JSValue filter_obj;
132 :
133 : GF_FilterArgs *args;
134 : u32 nb_args;
135 : Bool has_wilcard_arg;
136 :
137 : GF_FilterCapability *caps;
138 : u32 nb_caps;
139 :
140 : GF_List *pids;
141 : char *log_name;
142 :
143 : GF_List *pck_res;
144 :
145 : Bool unload_session_api;
146 : Bool disable_filter;
147 : } GF_JSFilterCtx;
148 :
149 : enum
150 : {
151 : JSF_PID_NAME=0,
152 : JSF_PID_EOS,
153 : JSF_PID_EOS_SEEN,
154 : JSF_PID_EOS_RECEIVED,
155 : JSF_PID_WOULD_BLOCK,
156 : JSF_PID_FILTER_NAME,
157 : JSF_PID_FILTER_SRC,
158 : JSF_PID_FILTER_ARGS,
159 : JSF_PID_FILTER_SRC_ARGS,
160 : JSF_PID_FILTER_UNICITY_ARGS,
161 : JSF_PID_MAX_BUFFER,
162 : JSF_PID_LOOSE_CONNECT,
163 : JSF_PID_FRAMING_MODE,
164 : JSF_PID_BUFFER,
165 : JSF_PID_IS_FULL,
166 : JSF_PID_FIRST_EMPTY,
167 : JSF_PID_FIRST_CTS,
168 : JSF_PID_NB_PACKETS,
169 : JSF_PID_TIMESCALE,
170 : JSF_PID_CLOCK_MODE,
171 : JSF_PID_DISCARD,
172 : JSF_PID_SRC_URL,
173 : JSF_PID_DST_URL,
174 : JSF_PID_REQUIRE_SOURCEID,
175 : JSF_PID_RECOMPUTE_DTS,
176 : JSF_PID_MIN_PCK_DUR,
177 : JSF_PID_IS_PLAYING,
178 : };
179 : typedef struct
180 : {
181 : GF_JSFilterCtx *jsf;
182 : GF_FilterPid *pid;
183 : JSValue jsobj;
184 : struct _js_pck_ctx *pck_head;
185 : GF_List *shared_pck;
186 : } GF_JSPidCtx;
187 :
188 : enum
189 : {
190 : GF_JS_PCK_IS_REF = 1,
191 : GF_JS_PCK_IS_SHARED = 1<<1,
192 : GF_JS_PCK_IS_OUTPUT = 1<<2
193 : };
194 :
195 : typedef struct _js_pck_ctx
196 : {
197 : GF_JSPidCtx *jspid;
198 : GF_FilterPacket *pck;
199 : JSValue jsobj;
200 : //shared packet, this is a string or an array buffer
201 : JSValue ref_val;
202 : //shared packet callback
203 : JSValue cbck_val;
204 : //array buffer
205 : JSValue data_ab;
206 : u32 flags;
207 : } GF_JSPckCtx;
208 :
209 : typedef enum
210 : {
211 : JSF_FINST_SOURCE=0,
212 : JSF_FINST_DEST,
213 : JSF_FINST_FILTER,
214 : } GF_JSFilterMode;
215 : typedef struct
216 : {
217 : GF_JSFilterCtx *jsf;
218 : GF_Filter *filter;
219 : JSValue filter_obj;
220 : GF_JSFilterMode fmode;
221 : JSValue setup_failure_fun;
222 :
223 : } GF_JSFilterInstanceCtx;
224 :
225 :
226 : static JSClassID jsf_filter_class_id;
227 :
228 196 : static void jsf_filter_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
229 : {
230 196 : GF_JSFilterCtx *jsf = JS_GetOpaque(val, jsf_filter_class_id);
231 196 : if (jsf) {
232 : u32 i;
233 680 : for (i=0; i<JSF_EVT_LAST_DEFINED; i++) {
234 680 : JS_MarkValue(rt, jsf->funcs[i], mark_func);
235 : }
236 : }
237 196 : }
238 : static JSClassDef jsf_filter_class = {
239 : "JSFilter",
240 : .gc_mark = jsf_filter_mark
241 : };
242 :
243 : static JSClassID jsf_filter_inst_class_id;
244 :
245 252 : static void jsf_filter_inst_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
246 : {
247 252 : GF_JSFilterInstanceCtx *f_inst = JS_GetOpaque(val, jsf_filter_inst_class_id);
248 252 : if (f_inst) {
249 16 : JS_MarkValue(rt, f_inst->setup_failure_fun, mark_func);
250 : }
251 252 : }
252 47 : static void jsf_filter_inst_finalizer(JSRuntime *rt, JSValue val) {
253 47 : GF_JSFilterInstanceCtx *f_inst = JS_GetOpaque(val, jsf_filter_inst_class_id);
254 47 : if (!f_inst) return;
255 : JS_FreeValueRT(rt, f_inst->setup_failure_fun);
256 5 : gf_free(f_inst);
257 : }
258 : static JSClassDef jsf_filter_inst_class = {
259 : "FilterInstance",
260 : .finalizer = jsf_filter_inst_finalizer,
261 : .gc_mark = jsf_filter_inst_mark
262 : };
263 :
264 : static JSClassID jsf_pid_class_id;
265 : static JSClassDef jsf_pid_class = {
266 : "FilterPid",
267 : };
268 :
269 : static JSClassID jsf_event_class_id;
270 496 : static void jsf_evt_finalizer(JSRuntime *rt, JSValue val)
271 : {
272 496 : GF_FilterEvent *evt = JS_GetOpaque(val, jsf_event_class_id);
273 496 : if (!evt) return;
274 7 : if (evt->base.type==GF_FEVT_USER) {
275 1 : if (evt->user_event.event.type==GF_EVENT_SET_CAPTION) {
276 1 : if (evt->user_event.event.caption.caption)
277 1 : gf_free((char *) evt->user_event.event.caption.caption);
278 : }
279 : }
280 7 : gf_free(evt);
281 : }
282 : static JSClassDef jsf_event_class = {
283 : "FilterEvent",
284 : .finalizer = jsf_evt_finalizer
285 : };
286 :
287 : static JSClassID jsf_pck_class_id;
288 :
289 158 : static void jsf_pck_detach_ab(JSContext *ctx, GF_JSPckCtx *pckctx)
290 : {
291 316 : if (!JS_IsUndefined(pckctx->data_ab)) {
292 0 : JS_DetachArrayBuffer(ctx, pckctx->data_ab);
293 : JS_FreeValue(ctx, pckctx->data_ab);
294 0 : pckctx->data_ab = JS_UNDEFINED;
295 : }
296 158 : }
297 :
298 3104 : static void jsf_pck_finalizer(JSRuntime *rt, JSValue val)
299 : {
300 3104 : GF_JSPckCtx *pckctx = JS_GetOpaque(val, jsf_pck_class_id);
301 3104 : if (!pckctx) return;
302 1409 : pckctx->jspid->pck_head = NULL;
303 :
304 : /*we only keep a ref for input packet(s)*/
305 1409 : if (pckctx->pck && !(pckctx->flags & GF_JS_PCK_IS_OUTPUT))
306 : JS_FreeValueRT(rt, pckctx->jsobj);
307 :
308 2818 : if (!JS_IsUndefined(pckctx->data_ab)) {
309 : JS_FreeValueRT(rt, pckctx->data_ab);
310 348 : pckctx->data_ab = JS_UNDEFINED;
311 : }
312 :
313 2818 : if (JS_IsUndefined(pckctx->ref_val) && pckctx->jspid && pckctx->jspid->jsf) {
314 1409 : gf_list_add(pckctx->jspid->jsf->pck_res, pckctx);
315 : memset(pckctx, 0, sizeof(GF_JSPckCtx));
316 : }
317 : }
318 :
319 274 : static void jsf_filter_pck_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
320 : {
321 274 : GF_JSPckCtx *pckctx = JS_GetOpaque(val, jsf_pck_class_id);
322 274 : if (!pckctx) return;
323 :
324 38 : if (!(pckctx->flags & GF_JS_PCK_IS_OUTPUT))
325 2 : JS_MarkValue(rt, pckctx->jsobj, mark_func);
326 :
327 76 : if (!JS_IsUndefined(pckctx->ref_val)) {
328 0 : JS_MarkValue(rt, pckctx->ref_val, mark_func);
329 : }
330 :
331 76 : if (!JS_IsUndefined(pckctx->data_ab)) {
332 36 : JS_MarkValue(rt, pckctx->data_ab, mark_func);
333 : }
334 : }
335 :
336 : static JSClassDef jsf_pck_class = {
337 : "FilterPacket",
338 : .finalizer = jsf_pck_finalizer,
339 : .gc_mark = jsf_filter_pck_mark
340 : };
341 :
342 4 : GF_DownloadManager *jsf_get_download_manager(JSContext *c)
343 : {
344 : GF_JSFilterCtx *jsf;
345 4 : JSValue global = JS_GetGlobalObject(c);
346 :
347 4 : JSValue filter_obj = JS_GetPropertyStr(c, global, "filter");
348 : JS_FreeValue(c, global);
349 8 : if (JS_IsNull(filter_obj) || JS_IsException(filter_obj)) return NULL;
350 4 : jsf = JS_GetOpaque(filter_obj, jsf_filter_class_id);
351 : JS_FreeValue(c, filter_obj);
352 4 : if (!jsf) return NULL;
353 4 : return gf_filter_get_download_manager(jsf->filter);
354 : }
355 :
356 : GF_FilterSession *jsff_get_session(JSContext *c, JSValue this_val);
357 : struct _gf_ft_mgr *gf_fs_get_font_manager(GF_FilterSession *fsess);
358 :
359 37 : struct _gf_ft_mgr *jsf_get_font_manager(JSContext *c)
360 : {
361 37 : JSValue global = JS_GetGlobalObject(c);
362 : JSValue obj;
363 :
364 37 : obj = JS_GetPropertyStr(c, global, "session");
365 74 : if (!JS_IsNull(obj) && !JS_IsException(obj)) {
366 37 : GF_FilterSession *fs = jsff_get_session(c, obj);
367 : JS_FreeValue(c, obj);
368 37 : if (fs) {
369 : JS_FreeValue(c, global);
370 28 : return gf_fs_get_font_manager(fs);
371 : }
372 : }
373 :
374 9 : obj = JS_GetPropertyStr(c, global, "filter");
375 : JS_FreeValue(c, global);
376 18 : if (!JS_IsNull(obj) && !JS_IsException(obj)) {
377 9 : GF_JSFilterCtx *jsf = JS_GetOpaque(obj, jsf_filter_class_id);
378 : JS_FreeValue(c, obj);
379 9 : if (jsf)
380 9 : return gf_filter_get_font_manager(jsf->filter);
381 : }
382 : return NULL;
383 : }
384 :
385 3 : GF_Err jsf_request_opengl(JSContext *c)
386 : {
387 : GF_JSFilterCtx *jsf;
388 3 : JSValue global = JS_GetGlobalObject(c);
389 :
390 3 : JSValue filter_obj = JS_GetPropertyStr(c, global, "filter");
391 : JS_FreeValue(c, global);
392 6 : if (JS_IsNull(filter_obj) || JS_IsException(filter_obj)) return GF_BAD_PARAM;
393 3 : jsf = JS_GetOpaque(filter_obj, jsf_filter_class_id);
394 : JS_FreeValue(c, filter_obj);
395 :
396 3 : return gf_filter_request_opengl(jsf->filter);
397 : }
398 607 : GF_Err jsf_set_gl_active(JSContext *c)
399 : {
400 : GF_JSFilterCtx *jsf;
401 607 : JSValue global = JS_GetGlobalObject(c);
402 :
403 607 : JSValue filter_obj = JS_GetPropertyStr(c, global, "filter");
404 : JS_FreeValue(c, global);
405 1214 : if (JS_IsNull(filter_obj) || JS_IsException(filter_obj)) return GF_BAD_PARAM;
406 607 : jsf = JS_GetOpaque(filter_obj, jsf_filter_class_id);
407 : JS_FreeValue(c, filter_obj);
408 :
409 607 : return gf_filter_set_active_opengl_context(jsf->filter);
410 : }
411 :
412 708 : Bool jsf_is_packet(JSContext *c, JSValue obj)
413 : {
414 708 : GF_JSPckCtx *pckc = JS_GetOpaque(obj, jsf_pck_class_id);
415 708 : if (pckc) return GF_TRUE;
416 2 : return GF_FALSE;
417 : }
418 504 : const GF_FilterPacket *jsf_get_packet(JSContext *c, JSValue obj)
419 : {
420 504 : GF_JSPckCtx *pckc = JS_GetOpaque(obj, jsf_pck_class_id);
421 504 : if (pckc) return pckc->pck;
422 : return NULL;
423 : }
424 :
425 204 : GF_Err jsf_get_filter_packet_planes(JSContext *c, JSValue obj, u32 *width, u32 *height, u32 *pf, u32 *stride, u32 *stride_uv, const u8 **data, const u8 **p_u, const u8 **p_v, const u8 **p_a)
426 : {
427 : u32 cid;
428 : GF_FilterFrameInterface *frame_ifce;
429 : const GF_PropertyValue *p;
430 204 : GF_JSPckCtx *pckc = JS_GetOpaque(obj, jsf_pck_class_id);
431 204 : if (!pckc) return GF_BAD_PARAM;
432 :
433 : #define GETPROP(_code, _v, opt)\
434 : p = gf_filter_pid_get_property(pckc->jspid->pid, _code);\
435 : if (!opt && !p) return GF_BAD_PARAM;\
436 : _v = p ? p->value.uint : 0;\
437 :
438 204 : GETPROP(GF_PROP_PID_CODECID, cid, 0)
439 204 : if (cid != GF_CODECID_RAW) return GF_BAD_PARAM;
440 204 : GETPROP(GF_PROP_PID_WIDTH, *width, 0)
441 204 : GETPROP(GF_PROP_PID_HEIGHT, *height, 0)
442 204 : GETPROP(GF_PROP_PID_PIXFMT, *pf, 0)
443 204 : GETPROP(GF_PROP_PID_STRIDE, *stride, 1)
444 204 : GETPROP(GF_PROP_PID_STRIDE_UV, *stride_uv, 1)
445 : #undef GETPROP
446 :
447 204 : if (!data || !p_u || !p_v || !p_a) return GF_OK;
448 :
449 202 : frame_ifce = gf_filter_pck_get_frame_interface(pckc->pck);
450 202 : if (!frame_ifce) {
451 202 : u32 size=0;
452 202 : *data = (u8 *) gf_filter_pck_get_data(pckc->pck, &size);
453 : } else {
454 : u32 st_o;
455 0 : frame_ifce->get_plane(frame_ifce, 0, data, stride);
456 0 : frame_ifce->get_plane(frame_ifce, 1, p_u, stride_uv);
457 : //todo we need to cleanup alpha frame fetch, how do we differentiate between NV12+alpha (3 planes) and YUV420 ?
458 0 : frame_ifce->get_plane(frame_ifce, 2, p_v, &st_o);
459 0 : frame_ifce->get_plane(frame_ifce, 3, p_a, &st_o);
460 : }
461 : return GF_OK;
462 : }
463 :
464 11 : const char *jsf_get_script_filename(JSContext *c)
465 : {
466 : GF_JSFilterCtx *jsf;
467 11 : JSValue global = JS_GetGlobalObject(c);
468 11 : JSValue filter_obj = JS_GetPropertyStr(c, global, "filter");
469 : JS_FreeValue(c, global);
470 22 : if (JS_IsNull(filter_obj) || JS_IsException(filter_obj)) return NULL;
471 11 : jsf = JS_GetOpaque(filter_obj, jsf_filter_class_id);
472 : JS_FreeValue(c, filter_obj);
473 11 : if (!jsf) return NULL;
474 11 : return jsf->js;
475 : }
476 :
477 426 : JSValue jsf_NewProp(JSContext *ctx, const GF_PropertyValue *new_val)
478 : {
479 : JSValue res;
480 : u32 i;
481 426 : if (!new_val) return JS_NULL;
482 :
483 426 : switch (new_val->type) {
484 164 : case GF_PROP_BOOL:
485 164 : return JS_NewBool(ctx, new_val->value.boolean);
486 107 : case GF_PROP_UINT:
487 : case GF_PROP_SINT:
488 107 : return JS_NewInt32(ctx, new_val->value.sint);
489 0 : case GF_PROP_4CC:
490 0 : return JS_NewString(ctx, gf_4cc_to_str(new_val->value.uint) );
491 6 : case GF_PROP_LUINT:
492 6 : return JS_NewInt64(ctx, new_val->value.longuint);
493 0 : case GF_PROP_LSINT:
494 0 : return JS_NewInt64(ctx, new_val->value.longsint);
495 0 : case GF_PROP_FLOAT:
496 0 : return JS_NewFloat64(ctx, FIX2FLT(new_val->value.fnumber));
497 36 : case GF_PROP_DOUBLE:
498 36 : return JS_NewFloat64(ctx, new_val->value.number);
499 55 : case GF_PROP_STRING:
500 : case GF_PROP_STRING_NO_COPY:
501 : case GF_PROP_NAME:
502 55 : if (!new_val->value.string) return JS_NULL;
503 45 : return JS_NewString(ctx, new_val->value.string);
504 0 : case GF_PROP_VEC2:
505 0 : res = JS_NewObject(ctx);
506 0 : JS_SetPropertyStr(ctx, res, "x", JS_NewFloat64(ctx, new_val->value.vec2.x));
507 0 : JS_SetPropertyStr(ctx, res, "y", JS_NewFloat64(ctx, new_val->value.vec2.y));
508 0 : return res;
509 0 : case GF_PROP_VEC2I:
510 0 : res = JS_NewObject(ctx);
511 0 : JS_SetPropertyStr(ctx, res, "x", JS_NewInt32(ctx, new_val->value.vec2i.x));
512 0 : JS_SetPropertyStr(ctx, res, "y", JS_NewInt32(ctx, new_val->value.vec2i.y));
513 0 : return res;
514 0 : case GF_PROP_VEC3I:
515 0 : res = JS_NewObject(ctx);
516 0 : JS_SetPropertyStr(ctx, res, "x", JS_NewInt32(ctx, new_val->value.vec3i.x));
517 0 : JS_SetPropertyStr(ctx, res, "y", JS_NewInt32(ctx, new_val->value.vec3i.y));
518 0 : JS_SetPropertyStr(ctx, res, "z", JS_NewInt32(ctx, new_val->value.vec3i.z));
519 0 : return res;
520 0 : case GF_PROP_VEC4I:
521 0 : res = JS_NewObject(ctx);
522 0 : JS_SetPropertyStr(ctx, res, "x", JS_NewInt32(ctx, new_val->value.vec4i.x));
523 0 : JS_SetPropertyStr(ctx, res, "y", JS_NewInt32(ctx, new_val->value.vec4i.y));
524 0 : JS_SetPropertyStr(ctx, res, "z", JS_NewInt32(ctx, new_val->value.vec4i.z));
525 0 : JS_SetPropertyStr(ctx, res, "w", JS_NewInt32(ctx, new_val->value.vec4i.w));
526 0 : return res;
527 16 : case GF_PROP_FRACTION:
528 16 : res = JS_NewObject(ctx);
529 32 : JS_SetPropertyStr(ctx, res, "n", JS_NewInt32(ctx, new_val->value.frac.num));
530 32 : JS_SetPropertyStr(ctx, res, "d", JS_NewInt32(ctx, new_val->value.frac.den));
531 16 : return res;
532 5 : case GF_PROP_FRACTION64:
533 5 : res = JS_NewObject(ctx);
534 5 : JS_SetPropertyStr(ctx, res, "n", JS_NewInt64(ctx, new_val->value.lfrac.num));
535 10 : JS_SetPropertyStr(ctx, res, "d", JS_NewInt64(ctx, new_val->value.lfrac.den));
536 5 : return res;
537 0 : case GF_PROP_UINT_LIST:
538 0 : res = JS_NewArray(ctx);
539 0 : for (i=0; i<new_val->value.uint_list.nb_items; i++) {
540 0 : JS_SetPropertyUint32(ctx, res, i, JS_NewInt64(ctx, new_val->value.uint_list.vals[i]) );
541 : }
542 0 : return res;
543 0 : case GF_PROP_4CC_LIST:
544 0 : res = JS_NewArray(ctx);
545 0 : for (i=0; i<new_val->value.uint_list.nb_items; i++) {
546 0 : JS_SetPropertyUint32(ctx, res, i, JS_NewString(ctx, gf_4cc_to_str(new_val->value.uint_list.vals[i]) ) );
547 : }
548 0 : return res;
549 0 : case GF_PROP_SINT_LIST:
550 0 : res = JS_NewArray(ctx);
551 0 : for (i=0; i<new_val->value.sint_list.nb_items; i++) {
552 0 : JS_SetPropertyUint32(ctx, res, i, JS_NewInt32(ctx, new_val->value.sint_list.vals[i]) );
553 : }
554 0 : return res;
555 5 : case GF_PROP_VEC2I_LIST:
556 5 : res = JS_NewArray(ctx);
557 10 : for (i=0; i<new_val->value.v2i_list.nb_items; i++) {
558 5 : JSValue item = JS_NewObject(ctx);
559 10 : JS_SetPropertyStr(ctx, item, "x", JS_NewInt32(ctx, new_val->value.v2i_list.vals[i].x));
560 10 : JS_SetPropertyStr(ctx, item, "y", JS_NewInt32(ctx, new_val->value.v2i_list.vals[i].y));
561 5 : JS_SetPropertyUint32(ctx, res, i, item);
562 : }
563 5 : return res;
564 0 : case GF_PROP_STRING_LIST:
565 0 : res = JS_NewArray(ctx);
566 0 : for (i=0; i<new_val->value.string_list.nb_items; i++) {
567 0 : JS_SetPropertyUint32(ctx, res, i, JS_NewString(ctx, new_val->value.string_list.vals[i] ) );
568 : }
569 0 : return res;
570 2 : case GF_PROP_DATA:
571 2 : return JS_NewArrayBufferCopy(ctx, new_val->value.data.ptr, new_val->value.data.size);
572 :
573 30 : default:
574 30 : if (gf_props_type_is_enum(new_val->type)) {
575 30 : return JS_NewString(ctx, gf_props_enum_name(new_val->type, new_val->value.uint));
576 : }
577 0 : return JS_NULL;
578 : }
579 : }
580 :
581 56 : JSValue jsf_NewPropTranslate(JSContext *ctx, const GF_PropertyValue *prop, u32 p4cc)
582 : {
583 : const char *cid;
584 : JSValue res;
585 56 : switch (p4cc) {
586 2 : case GF_PROP_PID_CODECID:
587 2 : cid = gf_codecid_file_ext(prop->value.uint);
588 2 : if (!cid) res = JS_EXCEPTION;
589 : else {
590 2 : char *sep = strchr(cid, '|');
591 2 : if (sep)
592 2 : res = JS_NewStringLen(ctx, cid, sep-cid);
593 : else
594 0 : res = JS_NewString(ctx, cid);
595 : }
596 : break;
597 4 : case GF_PROP_PID_STREAM_TYPE:
598 4 : res = JS_NewString(ctx, gf_stream_type_name(prop->value.uint));
599 4 : break;
600 0 : case GF_PROP_PID_CHANNEL_LAYOUT:
601 0 : res = JS_NewString(ctx, gf_audio_fmt_get_layout_name(prop->value.longuint));
602 0 : break;
603 50 : default:
604 50 : res = jsf_NewProp(ctx, prop);
605 50 : break;
606 : }
607 56 : return res;
608 : }
609 :
610 530 : GF_Err jsf_ToProp_ex(GF_Filter *filter, JSContext *ctx, JSValue value, u32 p4cc, GF_PropertyValue *prop, u32 prop_type)
611 : {
612 : u32 type;
613 : memset(prop, 0, sizeof(GF_PropertyValue));
614 :
615 530 : type = prop_type ? prop_type : GF_PROP_STRING;
616 530 : if (p4cc)
617 253 : type = gf_props_4cc_get_type(p4cc);
618 :
619 530 : if (JS_IsString(value)) {
620 : const char *val_str = JS_ToCString(ctx, value);
621 380 : if (p4cc==GF_PROP_PID_STREAM_TYPE) {
622 31 : prop->type = GF_PROP_UINT;
623 31 : prop->value.uint = gf_stream_type_by_name(val_str);
624 349 : } else if (p4cc==GF_PROP_PID_CODECID) {
625 31 : prop->type = GF_PROP_UINT;
626 31 : prop->value.uint = gf_codecid_parse(val_str);
627 318 : } else if (p4cc==GF_PROP_PID_CHANNEL_LAYOUT) {
628 0 : prop->type = GF_PROP_LUINT;
629 0 : prop->value.longuint = gf_audio_fmt_get_layout_from_name(val_str);
630 : } else {
631 318 : *prop = gf_props_parse_value(type, NULL, val_str, NULL, gf_filter_get_sep(filter, GF_FS_SEP_LIST));
632 : }
633 380 : JS_FreeCString(ctx, val_str);
634 380 : if (prop->type==GF_PROP_FORBIDEN) return GF_BAD_PARAM;
635 380 : return GF_OK;
636 : }
637 150 : if (JS_IsBool(value)) {
638 11 : prop->type = GF_PROP_BOOL;
639 11 : prop->value.boolean = JS_ToBool(ctx, value);
640 : }
641 139 : else if (JS_IsInteger(value)) {
642 110 : if (!JS_ToInt32(ctx, &prop->value.sint, value)) {
643 110 : prop->type = GF_PROP_SINT;
644 0 : } else if (!JS_ToInt64(ctx, &prop->value.longsint, value)) {
645 0 : prop->type = GF_PROP_LSINT;
646 : }
647 : }
648 29 : else if (JS_IsNumber(value)) {
649 0 : JS_ToFloat64(ctx, &prop->value.number, value);
650 0 : prop->type = GF_PROP_DOUBLE;
651 : }
652 29 : else if (JS_IsArray(ctx, value)) {
653 0 : u64 len = 0;
654 : u32 i;
655 : u32 atype = 0;
656 0 : JSValue js_length = JS_GetPropertyStr(ctx, value, "length");
657 0 : if (JS_ToIndex(ctx, &len, js_length)) {
658 : JS_FreeValue(ctx, js_length);
659 0 : return GF_BAD_PARAM;
660 : }
661 : JS_FreeValue(ctx, js_length);
662 0 : for (i=0; i<len; i++) {
663 0 : JSValue v = JS_GetPropertyUint32(ctx, value, i);
664 0 : if (JS_IsString(v)) {
665 0 : if (!i) atype = 1;
666 0 : else if (atype!=1) {
667 : JS_FreeValue(ctx, v);
668 0 : return GF_BAD_PARAM;
669 : }
670 0 : } else if (JS_IsInteger(v)) {
671 0 : if (!i) atype = 2;
672 0 : else if (atype!=2) {
673 : JS_FreeValue(ctx, v);
674 : return GF_BAD_PARAM;
675 : }
676 : }
677 : else {
678 : JS_FreeValue(ctx, v);
679 : return GF_BAD_PARAM;
680 : }
681 0 : if (!i) {
682 0 : if (atype==1) {
683 0 : prop->value.uint_list.nb_items = (u32) len;
684 0 : prop->value.uint_list.vals = gf_malloc((u32) (sizeof(char *)*len));
685 : } else {
686 0 : prop->value.uint_list.nb_items = (u32) len;
687 0 : prop->value.uint_list.vals = gf_malloc((u32) (sizeof(s32)*len));
688 : }
689 : }
690 0 : if (atype==1) {
691 : const char *str = JS_ToCString(ctx, v);
692 0 : prop->value.string_list.vals[i] = gf_strdup(str);
693 0 : JS_FreeCString(ctx, str);
694 : } else {
695 0 : JS_ToInt32(ctx, &prop->value.uint_list.vals[i], v);
696 : }
697 : JS_FreeValue(ctx, v);
698 : }
699 : }
700 29 : else if (JS_IsObject(value)) {
701 : Bool is_vec4 = 0;
702 : Bool is_vec3 = 0;
703 : u32 is_vec2 = 0;
704 : u32 is_frac = 0;
705 : Bool is_vec = GF_FALSE;
706 : GF_PropVec2 val_d;
707 : GF_PropVec4i val_i;
708 : GF_Fraction frac;
709 : GF_Fraction64 frac_l;
710 :
711 29 : JSValue res = JS_GetPropertyStr(ctx, value, "w");
712 29 : if (!JS_IsUndefined(res)) {
713 0 : JS_ToInt32(ctx, &val_i.w, res);
714 : is_vec4 = 1;
715 : }
716 : JS_FreeValue(ctx, res);
717 :
718 29 : res = JS_GetPropertyStr(ctx, value, "z");
719 29 : if (!JS_IsUndefined(res)) {
720 0 : JS_ToInt32(ctx, &val_i.z, res);
721 : is_vec3 = 1;
722 : }
723 : JS_FreeValue(ctx, res);
724 :
725 29 : res = JS_GetPropertyStr(ctx, value, "y");
726 29 : if (!JS_IsUndefined(res)) {
727 : is_vec2 = 1;
728 0 : if (JS_ToFloat64(ctx, &val_d.y, res)) {
729 0 : JS_ToInt32(ctx, &val_i.y, res);
730 : is_vec2 = 2;
731 : }
732 : }
733 : JS_FreeValue(ctx, res);
734 :
735 29 : res = JS_GetPropertyStr(ctx, value, "x");
736 29 : if (!JS_IsUndefined(res)) {
737 : is_vec = GF_TRUE;
738 0 : if (JS_ToFloat64(ctx, &val_d.x, res)) {
739 0 : JS_ToInt32(ctx, &val_i.x, res);
740 : }
741 : }
742 : JS_FreeValue(ctx, res);
743 :
744 29 : res = JS_GetPropertyStr(ctx, value, "d");
745 29 : if (!JS_IsUndefined(res)) {
746 : is_frac = 2;
747 26 : if (JS_ToInt32(ctx, &frac.den, res)) {
748 0 : JS_ToInt64(ctx, &frac_l.den, res);
749 : is_frac = 1;
750 : }
751 : }
752 : JS_FreeValue(ctx, res);
753 29 : if (is_frac) {
754 26 : res = JS_GetPropertyStr(ctx, value, "n");
755 26 : if (!JS_IsUndefined(res)) {
756 : is_frac = 2;
757 26 : if (JS_ToInt32(ctx, &frac.num, res)) {
758 0 : JS_ToInt64(ctx, &frac_l.num, res);
759 : is_frac = 1;
760 : }
761 : } else {
762 : is_frac = 0;
763 : }
764 : JS_FreeValue(ctx, res);
765 : }
766 :
767 29 : if (is_vec) {
768 0 : if (is_vec4) {
769 0 : prop->type = GF_PROP_VEC4I;
770 0 : prop->value.vec4i = val_i;
771 0 : } else if (is_vec3) {
772 0 : prop->type = GF_PROP_VEC3I;
773 0 : prop->value.vec3i.x = val_i.x;
774 0 : prop->value.vec3i.y = val_i.y;
775 0 : prop->value.vec3i.z = val_i.z;
776 0 : } else if (is_vec2==2) {
777 0 : prop->type = GF_PROP_VEC2I;
778 0 : prop->value.vec2i.x = val_i.x;
779 0 : prop->value.vec2i.y = val_i.y;
780 0 : } else if (is_vec2==1) {
781 0 : prop->type = GF_PROP_VEC2;
782 0 : prop->value.vec2.x = val_d.x;
783 0 : prop->value.vec2.y = val_d.y;
784 : }
785 29 : } else if (is_frac) {
786 26 : if (is_frac==2) {
787 26 : prop->type = GF_PROP_FRACTION;
788 26 : prop->value.frac = frac;
789 : } else {
790 0 : prop->type = GF_PROP_FRACTION64;
791 0 : prop->value.lfrac = frac_l;
792 : }
793 : }
794 : //try array buffer
795 : else {
796 : size_t ab_size;
797 3 : u8 *data = JS_GetArrayBuffer(ctx, &ab_size, value);
798 3 : if (!data)
799 0 : return GF_BAD_PARAM;
800 :
801 3 : if (prop_type==GF_PROP_CONST_DATA) {
802 0 : prop->value.data.ptr = data;
803 0 : prop->value.data.size = (u32) ab_size;
804 0 : prop->type = GF_PROP_CONST_DATA;
805 : } else {
806 3 : prop->value.data.ptr = gf_malloc(ab_size);
807 3 : memcpy(prop->value.data.ptr, data, ab_size);
808 3 : prop->value.data.size = (u32) ab_size;
809 3 : prop->type = GF_PROP_DATA;
810 : }
811 : }
812 0 : } else if (JS_IsNull(value)) {
813 0 : prop->value.data.ptr = NULL;
814 0 : prop->value.data.size = 0;
815 0 : if (prop_type==GF_PROP_CONST_DATA) {
816 0 : prop->type = GF_PROP_CONST_DATA;
817 : } else {
818 0 : prop->type = GF_PROP_DATA;
819 : }
820 : } else {
821 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Unmapped JS object type, cannot convert back to property\n"));
822 : return GF_NOT_SUPPORTED;
823 : }
824 :
825 150 : if (prop->type==GF_PROP_STRING) {
826 0 : if ((type==GF_PROP_DATA) || (type==GF_PROP_CONST_DATA)) {
827 0 : char *str = prop->value.string;
828 : prop->value.data.ptr = str;
829 0 : prop->value.data.size = (u32) strlen(str);
830 0 : prop->type = GF_PROP_DATA;
831 : }
832 : }
833 : return GF_OK;
834 : }
835 :
836 0 : GF_Err jsf_ToProp(GF_Filter *filter, JSContext *ctx, JSValue value, u32 p4cc, GF_PropertyValue *prop)
837 : {
838 530 : return jsf_ToProp_ex(filter, ctx, value, p4cc, prop, 0);
839 :
840 : }
841 134 : static JSValue jsf_filter_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
842 : {
843 : u32 ival;
844 : GF_FilterSessionCaps caps;
845 134 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
846 134 : if (!jsf)
847 0 : return JS_EXCEPTION;
848 :
849 134 : if (magic < JSF_EVT_LAST_DEFINED) {
850 121 : if (JS_IsFunction(ctx, value) || JS_IsUndefined(value) || JS_IsNull(value)) {
851 : JS_FreeValue(ctx, jsf->funcs[magic]);
852 121 : jsf->funcs[magic] = JS_DupValue(ctx, value);
853 : }
854 121 : return JS_UNDEFINED;
855 : }
856 13 : switch (magic) {
857 5 : case JSF_FILTER_MAX_PIDS:
858 5 : if (JS_ToInt32(ctx, &ival, value))
859 0 : return JS_EXCEPTION;
860 5 : gf_filter_set_max_extra_input_pids(jsf->filter, ival);
861 5 : break;
862 :
863 1 : case JSF_FILTER_CAPS_MAX_WIDTH:
864 1 : gf_filter_get_session_caps(jsf->filter, &caps);
865 1 : if (JS_ToInt32(ctx, &caps.max_screen_width, value)) return JS_EXCEPTION;
866 1 : gf_filter_set_session_caps(jsf->filter, &caps);
867 1 : break;
868 1 : case JSF_FILTER_CAPS_MAX_HEIGHT:
869 1 : gf_filter_get_session_caps(jsf->filter, &caps);
870 1 : if (JS_ToInt32(ctx, &caps.max_screen_height, value)) return JS_EXCEPTION;
871 1 : gf_filter_set_session_caps(jsf->filter, &caps);
872 1 : break;
873 1 : case JSF_FILTER_CAPS_MAX_DISPLAY_DEPTH:
874 1 : gf_filter_get_session_caps(jsf->filter, &caps);
875 1 : if (JS_ToInt32(ctx, &caps.max_screen_bpp, value)) return JS_EXCEPTION;
876 1 : gf_filter_set_session_caps(jsf->filter, &caps);
877 1 : break;
878 1 : case JSF_FILTER_CAPS_MAX_FPS:
879 1 : gf_filter_get_session_caps(jsf->filter, &caps);
880 1 : if (JS_ToInt32(ctx, &caps.max_screen_fps, value)) return JS_EXCEPTION;
881 1 : gf_filter_set_session_caps(jsf->filter, &caps);
882 1 : break;
883 1 : case JSF_FILTER_CAPS_MAX_VIEWS:
884 1 : gf_filter_get_session_caps(jsf->filter, &caps);
885 1 : if (JS_ToInt32(ctx, &caps.max_screen_nb_views, value)) return JS_EXCEPTION;
886 1 : gf_filter_set_session_caps(jsf->filter, &caps);
887 1 : break;
888 1 : case JSF_FILTER_CAPS_MAX_CHANNELS:
889 1 : gf_filter_get_session_caps(jsf->filter, &caps);
890 1 : if (JS_ToInt32(ctx, &caps.max_audio_channels, value)) return JS_EXCEPTION;
891 1 : gf_filter_set_session_caps(jsf->filter, &caps);
892 1 : break;
893 1 : case JSF_FILTER_CAPS_MAX_SAMPLERATE:
894 1 : gf_filter_get_session_caps(jsf->filter, &caps);
895 1 : if (JS_ToInt32(ctx, &caps.max_audio_sample_rate, value)) return JS_EXCEPTION;
896 1 : gf_filter_set_session_caps(jsf->filter, &caps);
897 1 : break;
898 1 : case JSF_FILTER_CAPS_MAX_AUDIO_DEPTH:
899 1 : gf_filter_get_session_caps(jsf->filter, &caps);
900 1 : if (JS_ToInt32(ctx, &caps.max_audio_bit_depth, value)) return JS_EXCEPTION;
901 1 : gf_filter_set_session_caps(jsf->filter, &caps);
902 1 : break;
903 :
904 0 : case JSF_FILTER_INAME:
905 : {
906 : const char *val = JS_ToCString(ctx, value);
907 0 : if (jsf->filter->iname) gf_free(jsf->filter->iname);
908 0 : if (val)
909 0 : jsf->filter->iname = gf_strdup(val);
910 : else
911 0 : jsf->filter->iname = NULL;
912 0 : JS_FreeCString(ctx, val);
913 : }
914 0 : break;
915 : }
916 13 : return JS_UNDEFINED;
917 : }
918 :
919 21 : static JSValue jsf_filter_prop_get(JSContext *ctx, JSValueConst this_val, int magic)
920 : {
921 : u32 ival;
922 : s64 lival;
923 : Double dval;
924 : char *str;
925 : char szSep[2];
926 : GF_FilterSessionCaps caps;
927 : JSValue res;
928 21 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
929 21 : if (!jsf)
930 0 : return JS_EXCEPTION;
931 :
932 21 : if (magic<JSF_EVT_LAST_DEFINED)
933 : return JS_DupValue(jsf->ctx, jsf->funcs[magic]);
934 :
935 21 : switch (magic) {
936 0 : case JSF_FILTER_MAX_PIDS:
937 0 : return JS_NewInt32(ctx, gf_filter_get_max_extra_input_pids(jsf->filter));
938 1 : case JSF_FILTER_BLOCK_ENABLED:
939 1 : return JS_NewBool(jsf->ctx, gf_filter_block_enabled(jsf->filter));
940 1 : case JSF_FILTER_OUTPUT_BUFFER:
941 1 : gf_filter_get_output_buffer_max(jsf->filter, &ival, NULL);
942 1 : return JS_NewInt32(jsf->ctx, ival);
943 1 : case JSF_FILTER_OUTPUT_PLAYOUT:
944 1 : gf_filter_get_output_buffer_max(jsf->filter, NULL, &ival);
945 1 : return JS_NewInt32(jsf->ctx, ival);
946 :
947 1 : case JSF_FILTER_SEP_ARGS:
948 1 : szSep[1]=0;
949 1 : szSep[0] = gf_filter_get_sep(jsf->filter, GF_FS_SEP_ARGS);
950 1 : return JS_NewString(jsf->ctx, szSep);
951 1 : case JSF_FILTER_SEP_NAME:
952 1 : szSep[1]=0;
953 1 : szSep[0] = gf_filter_get_sep(jsf->filter, GF_FS_SEP_NAME);
954 1 : return JS_NewString(jsf->ctx, szSep);
955 1 : case JSF_FILTER_SEP_LIST:
956 1 : szSep[1]=0;
957 1 : szSep[0] = gf_filter_get_sep(jsf->filter, GF_FS_SEP_LIST);
958 1 : return JS_NewString(jsf->ctx, szSep);
959 :
960 1 : case JSF_FILTER_DST_ARGS:
961 1 : str = (char *) gf_filter_get_dst_args(jsf->filter);
962 1 : return str ? JS_NewString(jsf->ctx, str) : JS_NULL;
963 1 : case JSF_FILTER_DST_NAME:
964 1 : str = gf_filter_get_dst_name(jsf->filter);
965 1 : res = str ? JS_NewString(jsf->ctx, str) : JS_NULL;
966 1 : if (str) gf_free(str);
967 1 : return res;
968 1 : case JSF_FILTER_SINKS_DONE:
969 1 : return JS_NewBool(jsf->ctx, gf_filter_all_sinks_done(jsf->filter) );
970 1 : case JSF_FILTER_REPORTING_ENABLED:
971 1 : return JS_NewBool(jsf->ctx, gf_filter_reporting_enabled(jsf->filter) );
972 :
973 1 : case JSF_FILTER_CAPS_MAX_WIDTH:
974 1 : gf_filter_get_session_caps(jsf->filter, &caps);
975 1 : return JS_NewInt32(ctx, caps.max_screen_width);
976 1 : case JSF_FILTER_CAPS_MAX_HEIGHT:
977 1 : gf_filter_get_session_caps(jsf->filter, &caps);
978 1 : return JS_NewInt32(ctx, caps.max_screen_height);
979 1 : case JSF_FILTER_CAPS_MAX_DISPLAY_DEPTH:
980 1 : gf_filter_get_session_caps(jsf->filter, &caps);
981 1 : return JS_NewInt32(ctx, caps.max_screen_bpp);
982 1 : case JSF_FILTER_CAPS_MAX_FPS:
983 1 : gf_filter_get_session_caps(jsf->filter, &caps);
984 1 : return JS_NewInt32(ctx, caps.max_screen_fps);
985 1 : case JSF_FILTER_CAPS_MAX_VIEWS:
986 1 : gf_filter_get_session_caps(jsf->filter, &caps);
987 1 : return JS_NewInt32(ctx, caps.max_screen_nb_views);
988 1 : case JSF_FILTER_CAPS_MAX_CHANNELS:
989 1 : gf_filter_get_session_caps(jsf->filter, &caps);
990 1 : return JS_NewInt32(ctx, caps.max_audio_channels);
991 1 : case JSF_FILTER_CAPS_MAX_SAMPLERATE:
992 1 : gf_filter_get_session_caps(jsf->filter, &caps);
993 1 : return JS_NewInt32(ctx, caps.max_audio_sample_rate);
994 1 : case JSF_FILTER_CAPS_MAX_AUDIO_DEPTH:
995 1 : gf_filter_get_session_caps(jsf->filter, &caps);
996 1 : return JS_NewInt32(ctx, caps.max_audio_bit_depth);
997 :
998 1 : case JSF_FILTER_NB_EVTS_QUEUED:
999 1 : return JS_NewInt32(ctx, gf_filter_get_num_events_queued(jsf->filter) );
1000 1 : case JSF_FILTER_CLOCK_HINT_TIME:
1001 1 : gf_filter_get_clock_hint(jsf->filter, &lival, NULL);
1002 1 : return JS_NewInt64(ctx, lival);
1003 1 : case JSF_FILTER_CLOCK_HINT_MEDIATIME:
1004 : {
1005 : GF_Fraction64 frac;
1006 1 : gf_filter_get_clock_hint(jsf->filter, NULL, &frac);
1007 1 : if (!frac.den) return JS_NULL;
1008 0 : dval = ((Double)frac.num) / frac.den;
1009 : }
1010 : return JS_NewFloat64(ctx, dval);
1011 0 : case JSF_FILTER_CONNECTIONS_PENDING:
1012 0 : return JS_NewBool(ctx, gf_filter_connections_pending(jsf->filter) );
1013 0 : case JSF_FILTER_INAME:
1014 0 : if (jsf->filter->iname) return JS_NewString(ctx, jsf->filter->iname);
1015 0 : return JS_NULL;
1016 : }
1017 :
1018 0 : return JS_UNDEFINED;
1019 : }
1020 :
1021 146 : static JSValue jsf_filter_set_arg(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1022 : {
1023 : JSValue v;
1024 : const char *desc=NULL;
1025 : const char *name=NULL;
1026 : const char *def = NULL;
1027 : const char *min_enum = NULL;
1028 146 : u32 type = 0;
1029 : Bool is_wildcard=GF_FALSE;
1030 146 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1031 146 : if (!jsf || !argc) return JS_EXCEPTION;
1032 :
1033 146 : v = JS_GetPropertyStr(ctx, argv[0], "name");
1034 146 : if (!JS_IsUndefined(v)) name = JS_ToCString(ctx, v);
1035 : JS_FreeValue(ctx, v);
1036 146 : if (!name) return JS_EXCEPTION;
1037 :
1038 146 : if (!strcmp(name, "*")) {
1039 0 : if (jsf->has_wilcard_arg) return JS_UNDEFINED;
1040 : is_wildcard = GF_TRUE;
1041 0 : jsf->has_wilcard_arg = GF_TRUE;
1042 : }
1043 :
1044 146 : v = JS_GetPropertyStr(ctx, argv[0], "desc");
1045 146 : if (!JS_IsUndefined(v)) desc = JS_ToCString(ctx, v);
1046 : JS_FreeValue(ctx, v);
1047 146 : if (!desc) {
1048 0 : JS_FreeCString(ctx, name);
1049 0 : return JS_EXCEPTION;
1050 : }
1051 :
1052 146 : v = JS_GetPropertyStr(ctx, argv[0], "type");
1053 146 : if (!JS_IsUndefined(v))
1054 146 : JS_ToInt32(ctx, &type, v);
1055 : JS_FreeValue(ctx, v);
1056 146 : if (!type) {
1057 0 : if (is_wildcard) {
1058 0 : type = GF_PROP_STRING;
1059 : } else {
1060 0 : JS_FreeCString(ctx, name);
1061 0 : JS_FreeCString(ctx, desc);
1062 0 : return JS_EXCEPTION;
1063 : }
1064 : }
1065 :
1066 146 : v = JS_GetPropertyStr(ctx, argv[0], "def");
1067 146 : if (!JS_IsUndefined(v)) def = JS_ToCString(ctx, v);
1068 : JS_FreeValue(ctx, v);
1069 :
1070 146 : v = JS_GetPropertyStr(ctx, argv[0], "minmax_enum");
1071 146 : if (!JS_IsUndefined(v)) min_enum = JS_ToCString(ctx, v);
1072 : JS_FreeValue(ctx, v);
1073 :
1074 146 : jsf->args = gf_realloc(jsf->args, sizeof(GF_FilterArgs)*(jsf->nb_args+2));
1075 146 : memset(&jsf->args[jsf->nb_args], 0, 2*sizeof(GF_FilterArgs));
1076 146 : jsf->args[jsf->nb_args].arg_name = gf_strdup(name);
1077 146 : jsf->args[jsf->nb_args].arg_desc = desc ? gf_strdup(desc) : NULL;
1078 146 : jsf->args[jsf->nb_args].arg_default_val = def ? gf_strdup(def) : NULL;
1079 146 : jsf->args[jsf->nb_args].min_max_enum = min_enum ? gf_strdup(min_enum) : NULL;
1080 146 : jsf->args[jsf->nb_args].arg_type = type;
1081 146 : jsf->args[jsf->nb_args].offset_in_private = -1;
1082 :
1083 146 : jsf->nb_args ++;
1084 :
1085 146 : gf_filter_define_args(jsf->filter, jsf->args);
1086 :
1087 146 : JS_FreeCString(ctx, name);
1088 146 : JS_FreeCString(ctx, desc);
1089 146 : JS_FreeCString(ctx, def);
1090 146 : JS_FreeCString(ctx, min_enum);
1091 146 : return JS_UNDEFINED;
1092 : }
1093 :
1094 :
1095 74 : static JSValue jsf_filter_set_cap(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1096 : {
1097 : u32 prop_id = 0;
1098 : Bool is_output=GF_FALSE;
1099 : Bool is_inputoutput=GF_FALSE;
1100 : Bool is_excluded=GF_FALSE;
1101 : Bool is_static=GF_FALSE;
1102 : Bool is_loaded_filter_only=GF_FALSE;
1103 : Bool is_optional=GF_FALSE;
1104 : GF_PropertyValue p;
1105 74 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1106 74 : if (!jsf) return JS_EXCEPTION;
1107 74 : jsf->disable_filter = GF_FALSE;
1108 :
1109 : memset(&p, 0, sizeof(GF_PropertyValue));
1110 74 : if (argc) {
1111 : u32 prop_type;
1112 : JSValue v;
1113 : const char *name = NULL;
1114 :
1115 74 : v = JS_GetPropertyStr(ctx, argv[0], "id");
1116 74 : if (!JS_IsUndefined(v)) name = JS_ToCString(ctx, v);
1117 : JS_FreeValue(ctx, v);
1118 74 : if (!name) return JS_EXCEPTION;
1119 74 : prop_id = gf_props_get_id(name);
1120 74 : JS_FreeCString(ctx, name);
1121 74 : if (!prop_id)
1122 0 : return js_throw_err(ctx, GF_BAD_PARAM);
1123 74 : prop_type = gf_props_4cc_get_type(prop_id);
1124 :
1125 : name = NULL;
1126 74 : v = JS_GetPropertyStr(ctx, argv[0], "value");
1127 74 : if (!JS_IsUndefined(v)) name = JS_ToCString(ctx, v);
1128 : JS_FreeValue(ctx, v);
1129 :
1130 74 : if (prop_id==GF_PROP_PID_STREAM_TYPE) {
1131 44 : p.type = GF_PROP_UINT;
1132 44 : p.value.uint = gf_stream_type_by_name(name);
1133 30 : } else if (prop_id==GF_PROP_PID_CODECID) {
1134 30 : p.type = GF_PROP_UINT;
1135 30 : p.value.uint = gf_codecid_parse(name);
1136 : } else {
1137 0 : p = gf_props_parse_value(prop_type, NULL, name, NULL, gf_filter_get_sep(jsf->filter, GF_FS_SEP_LIST) );
1138 : }
1139 74 : JS_FreeCString(ctx, name);
1140 :
1141 : #define GETB(_v, _n)\
1142 : v = JS_GetPropertyStr(ctx, argv[0], _n);\
1143 : if (!JS_IsUndefined(v)) _v = JS_ToBool(ctx, v);\
1144 : JS_FreeValue(ctx, v);\
1145 :
1146 148 : GETB(is_output, "output");
1147 148 : GETB(is_inputoutput, "inout");
1148 148 : GETB(is_excluded, "excluded");
1149 148 : GETB(is_loaded_filter_only, "loaded_filter_only");
1150 148 : GETB(is_static, "static");
1151 148 : GETB(is_optional, "optional");
1152 : #undef GETB
1153 :
1154 : }
1155 :
1156 74 : jsf->caps = gf_realloc(jsf->caps, sizeof(GF_FilterCapability)*(jsf->nb_caps+1));
1157 74 : memset(&jsf->caps[jsf->nb_caps], 0, sizeof(GF_FilterCapability));
1158 74 : if (prop_id) {
1159 74 : GF_FilterCapability *cap = &jsf->caps[jsf->nb_caps];
1160 74 : cap->code = prop_id;
1161 74 : cap->val = p;
1162 74 : cap->flags = GF_CAPFLAG_IN_BUNDLE;
1163 74 : if (is_inputoutput) {
1164 8 : cap->flags |= GF_CAPFLAG_INPUT|GF_CAPFLAG_OUTPUT;
1165 66 : } else if (is_output) {
1166 40 : cap->flags |= GF_CAPFLAG_OUTPUT;
1167 : } else {
1168 26 : cap->flags |= GF_CAPFLAG_INPUT;
1169 : }
1170 74 : if (is_excluded)
1171 8 : cap->flags |= GF_CAPFLAG_EXCLUDED;
1172 74 : if (is_static)
1173 0 : cap->flags |= GF_CAPFLAG_STATIC;
1174 74 : if (is_loaded_filter_only)
1175 0 : cap->flags |= GF_CAPFLAG_LOADED_FILTER;
1176 74 : if (is_optional)
1177 0 : cap->flags |= GF_CAPFLAG_OPTIONAL;
1178 : }
1179 74 : jsf->nb_caps ++;
1180 74 : gf_filter_override_caps(jsf->filter, jsf->caps, jsf->nb_caps);
1181 74 : return JS_UNDEFINED;
1182 : }
1183 :
1184 41 : static JSValue jsf_filter_set_desc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1185 : {
1186 41 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1187 41 : if (!jsf) return JS_EXCEPTION;
1188 : const char *str = JS_ToCString(ctx, argv[0]);
1189 41 : if (!str) return JS_EXCEPTION;
1190 41 : gf_filter_set_description(jsf->filter, str);
1191 41 : JS_FreeCString(ctx, str);
1192 41 : return JS_UNDEFINED;
1193 : }
1194 :
1195 41 : static JSValue jsf_filter_set_version(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1196 : {
1197 41 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1198 41 : if (!jsf) return JS_EXCEPTION;
1199 : const char *str = JS_ToCString(ctx, argv[0]);
1200 41 : if (!str) return JS_EXCEPTION;
1201 41 : gf_filter_set_version(jsf->filter, str);
1202 41 : JS_FreeCString(ctx, str);
1203 41 : return JS_UNDEFINED;
1204 : }
1205 :
1206 41 : static JSValue jsf_filter_set_author(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1207 : {
1208 41 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1209 41 : if (!jsf) return JS_EXCEPTION;
1210 : const char *str = JS_ToCString(ctx, argv[0]);
1211 41 : if (!str) return JS_EXCEPTION;
1212 41 : gf_filter_set_author(jsf->filter, str);
1213 41 : JS_FreeCString(ctx, str);
1214 41 : return JS_UNDEFINED;
1215 : }
1216 :
1217 :
1218 41 : static JSValue jsf_filter_set_help(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1219 : {
1220 41 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1221 41 : if (!jsf) return JS_EXCEPTION;
1222 : const char *str = JS_ToCString(ctx, argv[0]);
1223 41 : if (!str) return JS_EXCEPTION;
1224 41 : gf_filter_set_help(jsf->filter, str);
1225 41 : JS_FreeCString(ctx, str);
1226 41 : return JS_UNDEFINED;
1227 : }
1228 :
1229 41 : static JSValue jsf_filter_set_name(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1230 : {
1231 41 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1232 41 : if (!jsf) return JS_EXCEPTION;
1233 41 : if (jsf->log_name) gf_free(jsf->log_name);
1234 41 : jsf->log_name = NULL;
1235 41 : if (argc) {
1236 : JSValue global;
1237 : const char *str = JS_ToCString(ctx, argv[0]);
1238 41 : if (!str) return JS_EXCEPTION;
1239 41 : jsf->log_name = gf_strdup(str);
1240 41 : JS_FreeCString(ctx, str);
1241 41 : gf_filter_set_name(jsf->filter, jsf->log_name);
1242 :
1243 41 : global = JS_GetGlobalObject(ctx);
1244 41 : JS_SetPropertyStr(ctx, global, "_gpac_log_name", JS_NewString(ctx, jsf->log_name));
1245 : JS_FreeValue(ctx, global);
1246 : }
1247 41 : return JS_UNDEFINED;
1248 : }
1249 :
1250 :
1251 38 : static JSValue jsf_filter_new_pid(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1252 : {
1253 : GF_JSPidCtx *pctx;
1254 38 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1255 38 : if (!jsf) return JS_EXCEPTION;
1256 38 : GF_FilterPid *opid = gf_filter_pid_new(jsf->filter);
1257 38 : if (!opid) return JS_EXCEPTION;
1258 38 : jsf->disable_filter = GF_FALSE;
1259 :
1260 38 : GF_SAFEALLOC(pctx, GF_JSPidCtx);
1261 38 : if (!pctx)
1262 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
1263 38 : gf_list_add(jsf->pids, pctx);
1264 38 : pctx->jsf = jsf;
1265 38 : pctx->pid = opid;
1266 38 : pctx->jsobj = JS_NewObjectClass(ctx, jsf_pid_class_id);
1267 : //keep ref to value we destroy it upon pid removal or filter desctruction
1268 38 : pctx->jsobj = JS_DupValue(ctx, pctx->jsobj);
1269 38 : JS_SetOpaque(pctx->jsobj, pctx);
1270 38 : gf_filter_pid_set_udta(pctx->pid, pctx);
1271 38 : return pctx->jsobj;
1272 : }
1273 :
1274 1 : static JSValue jsf_filter_send_event(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1275 : {
1276 : Bool upstream = GF_FALSE;
1277 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1278 1 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1279 1 : if (!jsf && !jsfi) return JS_EXCEPTION;
1280 1 : GF_FilterEvent *evt = JS_GetOpaque(argv[0], jsf_event_class_id);
1281 1 : if (!evt) return JS_EXCEPTION;
1282 1 : if (argc>1) {
1283 0 : upstream = JS_ToBool(ctx, argv[1]);
1284 : }
1285 :
1286 1 : if (jsf)
1287 1 : gf_filter_send_event(jsf->filter, evt, upstream);
1288 : else
1289 0 : gf_filter_send_event(jsfi->filter, evt, upstream);
1290 1 : return JS_UNDEFINED;
1291 : }
1292 :
1293 1 : static JSValue jsf_filter_get_info(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1294 : {
1295 : JSValue res;
1296 : const char *name=NULL;
1297 : const GF_PropertyValue *prop;
1298 : GF_Filter *filter;
1299 1 : GF_PropertyEntry *pe = NULL;
1300 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1301 1 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1302 1 : if (!jsf && !jsfi) return JS_EXCEPTION;
1303 : name = JS_ToCString(ctx, argv[0]);
1304 1 : if (!name) return JS_EXCEPTION;
1305 1 : filter = jsf ? jsf->filter : jsfi->filter;
1306 :
1307 1 : if ((argc>1) && JS_ToBool(ctx, argv[1])) {
1308 0 : prop = gf_filter_get_info_str(filter, name, &pe);
1309 0 : JS_FreeCString(ctx, name);
1310 0 : if (!prop) return JS_NULL;
1311 0 : res = jsf_NewProp(ctx, prop);
1312 0 : JS_SetPropertyStr(ctx, res, "type", JS_NewInt32(ctx, prop->type));
1313 : } else {
1314 1 : u32 p4cc = gf_props_get_id(name);
1315 1 : JS_FreeCString(ctx, name);
1316 1 : if (!p4cc)
1317 0 : return js_throw_err(ctx, GF_BAD_PARAM);
1318 1 : prop = gf_filter_get_info(filter, p4cc, &pe);
1319 1 : if (!prop) return JS_NULL;
1320 1 : res = jsf_NewPropTranslate(ctx, prop, p4cc);
1321 : }
1322 1 : gf_filter_release_property(pe);
1323 1 : return res;
1324 : }
1325 :
1326 :
1327 :
1328 1 : static JSValue jsf_filter_is_supported_mime(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1329 : {
1330 : const char *mime=NULL;
1331 : JSValue res;
1332 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1333 1 : if (!jsf || !argc) return JS_EXCEPTION;
1334 : mime = JS_ToCString(ctx, argv[0]);
1335 1 : if (!mime) return JS_EXCEPTION;
1336 1 : res = JS_NewBool(ctx, gf_filter_is_supported_mime(jsf->filter, mime));
1337 1 : JS_FreeCString(ctx, mime);
1338 1 : return res;
1339 : }
1340 :
1341 1 : static JSValue jsf_filter_is_supported_source(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1342 : {
1343 : const char *src=NULL;
1344 : const char *parent=NULL;
1345 : JSValue res;
1346 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1347 1 : if (!jsf || !argc) return JS_EXCEPTION;
1348 : src = JS_ToCString(ctx, argv[0]);
1349 1 : if (!src) return JS_EXCEPTION;
1350 1 : if (argc>1) {
1351 : parent = JS_ToCString(ctx, argv[1]);
1352 0 : if (!parent) {
1353 0 : JS_FreeCString(ctx, src);
1354 0 : return JS_EXCEPTION;
1355 : }
1356 : }
1357 1 : res = JS_NewBool(ctx, gf_filter_is_supported_source(jsf->filter, src, parent) );
1358 1 : JS_FreeCString(ctx, src);
1359 1 : JS_FreeCString(ctx, parent);
1360 1 : return res;
1361 : }
1362 :
1363 1 : static JSValue jsf_filter_update_status(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1364 : {
1365 : const char *status;
1366 1 : u32 pc=0;
1367 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1368 1 : if (!jsf || (argc<1)) return JS_EXCEPTION;
1369 :
1370 : status = JS_ToCString(ctx, argv[0]);
1371 1 : if (argc>1)
1372 0 : JS_ToInt32(ctx, &pc, argv[1]);
1373 1 : gf_filter_update_status(jsf->filter, pc, (char*) status);
1374 1 : JS_FreeCString(ctx, status);
1375 1 : return JS_UNDEFINED;
1376 : }
1377 :
1378 348 : static JSValue jsf_filter_reschedule_in(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1379 : {
1380 348 : u32 rt_delay=0;
1381 348 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1382 348 : if (!jsf) return JS_EXCEPTION;
1383 :
1384 348 : if (argc) {
1385 348 : if (JS_ToInt32(ctx, &rt_delay, argv[0]))
1386 0 : return JS_EXCEPTION;
1387 :
1388 348 : gf_filter_ask_rt_reschedule(jsf->filter, rt_delay);
1389 : } else {
1390 0 : gf_filter_post_process_task(jsf->filter);
1391 : }
1392 348 : return JS_UNDEFINED;
1393 : }
1394 :
1395 : typedef struct
1396 : {
1397 : JSValue func;
1398 : JSValue obj;
1399 : GF_JSFilterCtx *jsf;
1400 : } JS_ScriptTask;
1401 :
1402 1 : Bool jsf_task_exec(GF_Filter *filter, void *callback, u32 *reschedule_ms)
1403 : {
1404 1 : s32 fun_result = -1;
1405 : JS_ScriptTask *task = (JS_ScriptTask *) callback;
1406 : JSValue ret;
1407 1 : gf_js_lock(task->jsf->ctx, GF_TRUE);
1408 :
1409 2 : if (JS_IsUndefined(task->obj)) {
1410 1 : ret = JS_Call(task->jsf->ctx, task->func, task->jsf->filter_obj, 0, NULL);
1411 : } else {
1412 0 : ret = JS_Call(task->jsf->ctx, task->func, task->obj, 0, NULL);
1413 : }
1414 :
1415 1 : if (JS_IsException(ret)) {
1416 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error processing JS-defined task\n", task->jsf->log_name));
1417 0 : js_dump_error(task->jsf->ctx);
1418 : }
1419 1 : else if (JS_IsInteger(ret)) {
1420 1 : JS_ToInt32(task->jsf->ctx, &fun_result, ret);
1421 : }
1422 1 : JS_FreeValue(task->jsf->ctx, ret);
1423 :
1424 1 : gf_js_lock(task->jsf->ctx, GF_FALSE);
1425 1 : js_do_loop(task->jsf->ctx);
1426 :
1427 1 : if (fun_result>=0) {
1428 0 : *reschedule_ms = (u32) fun_result;
1429 0 : return GF_TRUE;
1430 : }
1431 2 : if (!JS_IsUndefined(task->obj)) {
1432 0 : JS_FreeValue(task->jsf->ctx, task->obj);
1433 : }
1434 1 : JS_FreeValue(task->jsf->ctx, task->func);
1435 1 : gf_free(task);
1436 1 : return GF_FALSE;
1437 : }
1438 1 : static JSValue jsf_filter_post_task(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1439 : {
1440 : JS_ScriptTask *task;
1441 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1442 1 : if (!jsf || !argc) return JS_EXCEPTION;
1443 1 : jsf->disable_filter = GF_FALSE;
1444 1 : if (!JS_IsFunction(ctx, argv[0]))
1445 0 : return JS_EXCEPTION;
1446 1 : if ((argc>1) && !JS_IsObject(argv[1]))
1447 0 : return JS_EXCEPTION;
1448 :
1449 1 : GF_SAFEALLOC(task, JS_ScriptTask);
1450 1 : if (!task)
1451 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
1452 1 : task->jsf = jsf;
1453 1 : task->func = JS_DupValue(ctx, argv[0]);
1454 1 : task->obj = JS_UNDEFINED;
1455 1 : if (argc>1)
1456 0 : task->obj = JS_DupValue(ctx, argv[1]);
1457 :
1458 1 : gf_filter_post_task(jsf->filter, jsf_task_exec, task, "jsf_task");
1459 1 : return JS_UNDEFINED;
1460 : }
1461 :
1462 1 : static JSValue jsf_filter_notify_failure(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1463 : {
1464 : GF_Err e;
1465 1 : s32 error_type=0;
1466 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1467 1 : if (!jsf || !argc) return JS_EXCEPTION;
1468 1 : if (JS_ToInt32(ctx, (int *) &e, argv[0]))
1469 0 : return JS_EXCEPTION;
1470 :
1471 1 : if (e==GF_OK) return JS_UNDEFINED;
1472 :
1473 0 : if ((argc>1) && JS_ToInt32(ctx, &error_type, argv[1]))
1474 0 : return JS_EXCEPTION;
1475 0 : if (error_type==JSF_NOTIF_ERROR_AND_DISCONNECT)
1476 0 : gf_filter_notification_failure(jsf->filter, e, GF_TRUE);
1477 0 : else if (error_type==JSF_NOTIF_ERROR)
1478 0 : gf_filter_notification_failure(jsf->filter, e, GF_FALSE);
1479 : else
1480 0 : gf_filter_setup_failure(jsf->filter, e);
1481 0 : return JS_UNDEFINED;
1482 : }
1483 :
1484 1 : static JSValue jsf_filter_hint_clock(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1485 : {
1486 1 : s64 time_in_us=0;
1487 : GF_Fraction64 media_timestamp;
1488 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1489 1 : if (!jsf || (argc<2)) return JS_EXCEPTION;
1490 1 : if (JS_ToInt64(ctx, &time_in_us, argv[0]))
1491 0 : return JS_EXCEPTION;
1492 1 : if (argc==2) {
1493 1 : Double t=0;
1494 1 : if (JS_ToFloat64(ctx, &t, argv[0]))
1495 0 : return JS_EXCEPTION;
1496 1 : media_timestamp.den = 1000000;
1497 1 : media_timestamp.num = (s64) (t*media_timestamp.den);
1498 : } else {
1499 0 : if (JS_ToInt64(ctx, &media_timestamp.num, argv[0]))
1500 0 : return JS_EXCEPTION;
1501 0 : if (JS_ToInt64(ctx, &media_timestamp.den, argv[0]))
1502 0 : return JS_EXCEPTION;
1503 : }
1504 1 : gf_filter_hint_single_clock(jsf->filter, time_in_us, media_timestamp);
1505 1 : return JS_UNDEFINED;
1506 : }
1507 :
1508 1 : static JSValue jsf_filter_send_update(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1509 : {
1510 : const char *filter_id=NULL;
1511 : const char *arg_name=NULL;
1512 : const char *arg_val=NULL;
1513 1 : GF_EventPropagateType prop_mask = 0;
1514 1 : JSValue ret = JS_UNDEFINED;
1515 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1516 1 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1517 1 : if ((!jsf && !jsfi) || (argc!=4)) return JS_EXCEPTION;
1518 :
1519 : filter_id = JS_ToCString(ctx, argv[0]);
1520 : arg_name = JS_ToCString(ctx, argv[1]);
1521 : arg_val = JS_ToCString(ctx, argv[2]);
1522 1 : if (!arg_name || !arg_val || JS_ToInt32(ctx, (s32 *) &prop_mask, argv[3])) {
1523 0 : ret = JS_EXCEPTION;
1524 0 : goto exit;
1525 : }
1526 1 : if (jsf)
1527 1 : gf_filter_send_update(jsf->filter, filter_id, arg_name, arg_val, prop_mask);
1528 : else
1529 0 : gf_filter_send_update(jsfi->filter, filter_id, arg_name, arg_val, prop_mask);
1530 :
1531 1 : exit:
1532 1 : JS_FreeCString(ctx, filter_id);
1533 1 : JS_FreeCString(ctx, arg_name);
1534 1 : JS_FreeCString(ctx, arg_val);
1535 1 : return ret;
1536 : }
1537 :
1538 5 : static JSValue jsf_filter_load_filter(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, GF_JSFilterMode mode)
1539 : {
1540 : const char *url=NULL;
1541 : const char *parent=NULL;
1542 5 : GF_Err e=GF_OK;
1543 : Bool inherit_args = GF_FALSE;
1544 : GF_JSFilterInstanceCtx *f_ctx;
1545 5 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1546 5 : if (!jsf || !argc) return JS_EXCEPTION;
1547 : url = JS_ToCString(ctx, argv[0]);
1548 5 : if (!url) return JS_EXCEPTION;
1549 :
1550 5 : if ((mode==JSF_FINST_SOURCE) && (argc>1)) {
1551 : parent = JS_ToCString(ctx, argv[1]);
1552 0 : if (!parent) {
1553 0 : JS_FreeCString(ctx, url);
1554 0 : return JS_EXCEPTION;
1555 : }
1556 0 : if (argc>2) {
1557 0 : inherit_args = JS_ToBool(ctx, argv[2]);
1558 : }
1559 : }
1560 5 : GF_SAFEALLOC(f_ctx, GF_JSFilterInstanceCtx);
1561 5 : if (!f_ctx) {
1562 0 : JS_FreeCString(ctx, url);
1563 0 : JS_FreeCString(ctx, parent);
1564 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
1565 : }
1566 :
1567 5 : f_ctx->fmode = mode;
1568 5 : if (mode==JSF_FINST_SOURCE) {
1569 2 : f_ctx->filter = gf_filter_connect_source(jsf->filter, url, parent, inherit_args, &e);
1570 3 : } else if (mode==JSF_FINST_DEST) {
1571 1 : f_ctx->filter = gf_filter_connect_destination(jsf->filter, url, &e);
1572 : } else {
1573 2 : f_ctx->filter = gf_filter_load_filter(jsf->filter, url, &e);
1574 : }
1575 5 : JS_FreeCString(ctx, url);
1576 5 : JS_FreeCString(ctx, parent);
1577 5 : if (!f_ctx->filter) {
1578 0 : gf_free(f_ctx);
1579 0 : return js_throw_err(ctx, e);
1580 : }
1581 5 : f_ctx->jsf = jsf;
1582 5 : f_ctx->setup_failure_fun = JS_UNDEFINED;
1583 5 : f_ctx->filter_obj = JS_NewObjectClass(ctx, jsf_filter_inst_class_id);
1584 5 : JS_SetOpaque(f_ctx->filter_obj, f_ctx);
1585 5 : return f_ctx->filter_obj;
1586 : }
1587 :
1588 2 : static JSValue jsf_filter_add_source(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1589 : {
1590 2 : return jsf_filter_load_filter(ctx, this_val, argc, argv, JSF_FINST_SOURCE);
1591 :
1592 : }
1593 1 : static JSValue jsf_filter_add_dest(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1594 : {
1595 1 : return jsf_filter_load_filter(ctx, this_val, argc, argv, JSF_FINST_DEST);
1596 : }
1597 2 : static JSValue jsf_filter_add_filter(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1598 : {
1599 2 : return jsf_filter_load_filter(ctx, this_val, argc, argv, JSF_FINST_FILTER);
1600 : }
1601 1 : static JSValue jsf_filter_make_sticky(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1602 : {
1603 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1604 1 : if (!jsf) return JS_EXCEPTION;
1605 1 : gf_filter_make_sticky(jsf->filter);
1606 1 : return JS_UNDEFINED;
1607 : }
1608 1 : static JSValue jsf_filter_prevent_blocking(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1609 : {
1610 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1611 1 : if (!jsf || !argc) return JS_EXCEPTION;
1612 1 : gf_filter_prevent_blocking(jsf->filter, JS_ToBool(ctx, argv[0]) ? GF_TRUE : GF_FALSE);
1613 1 : return JS_UNDEFINED;
1614 : }
1615 1 : static JSValue jsf_filter_block_eos(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1616 : {
1617 1 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1618 1 : if (!jsf || !argc) return JS_EXCEPTION;
1619 1 : gf_filter_block_eos(jsf->filter, JS_ToBool(ctx, argv[0]) ? GF_TRUE : GF_FALSE);
1620 1 : return JS_UNDEFINED;
1621 : }
1622 :
1623 :
1624 0 : static JSValue jsf_filter_abort(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1625 : {
1626 0 : GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id);
1627 0 : if (!jsf) return JS_EXCEPTION;
1628 0 : gf_filter_abort(jsf->filter);
1629 0 : return JS_UNDEFINED;
1630 : }
1631 :
1632 : static const JSCFunctionListEntry jsf_filter_funcs[] = {
1633 : JS_CGETSET_MAGIC_DEF("initialize", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_INITIALIZE),
1634 : JS_CGETSET_MAGIC_DEF("finalize", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_FINALIZE),
1635 : JS_CGETSET_MAGIC_DEF("configure_pid", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_CONFIGURE_PID),
1636 : JS_CGETSET_MAGIC_DEF("process", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_PROCESS),
1637 : JS_CGETSET_MAGIC_DEF("process_event", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_PROCESS_EVENT),
1638 : JS_CGETSET_MAGIC_DEF("update_arg", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_UPDATE_ARG),
1639 : JS_CGETSET_MAGIC_DEF("probe_data", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_PROBE_DATA),
1640 : JS_CGETSET_MAGIC_DEF("probe_url", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_PROBE_URL),
1641 : JS_CGETSET_MAGIC_DEF("reconfigure_output", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_RECONFIGURE_OUTPUT),
1642 : JS_CGETSET_MAGIC_DEF("remove_pid", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_REMOVE_PID),
1643 : JS_CGETSET_MAGIC_DEF("max_pids", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_MAX_PIDS),
1644 : JS_CGETSET_MAGIC_DEF("block_enabled", jsf_filter_prop_get, NULL, JSF_FILTER_BLOCK_ENABLED),
1645 : JS_CGETSET_MAGIC_DEF("output_buffer", jsf_filter_prop_get, NULL, JSF_FILTER_OUTPUT_BUFFER),
1646 : JS_CGETSET_MAGIC_DEF("output_playout", jsf_filter_prop_get, NULL, JSF_FILTER_OUTPUT_PLAYOUT),
1647 : JS_CGETSET_MAGIC_DEF("sep_args", jsf_filter_prop_get, NULL, JSF_FILTER_SEP_ARGS),
1648 : JS_CGETSET_MAGIC_DEF("sep_name", jsf_filter_prop_get, NULL, JSF_FILTER_SEP_NAME),
1649 : JS_CGETSET_MAGIC_DEF("sep_list", jsf_filter_prop_get, NULL, JSF_FILTER_SEP_LIST),
1650 : JS_CGETSET_MAGIC_DEF("dst_args", jsf_filter_prop_get, NULL, JSF_FILTER_DST_ARGS),
1651 : JS_CGETSET_MAGIC_DEF("dst_name", jsf_filter_prop_get, NULL, JSF_FILTER_DST_NAME),
1652 : JS_CGETSET_MAGIC_DEF("sinks_done", jsf_filter_prop_get, NULL, JSF_FILTER_SINKS_DONE),
1653 : JS_CGETSET_MAGIC_DEF("reports_on", jsf_filter_prop_get, NULL, JSF_FILTER_REPORTING_ENABLED),
1654 : JS_CGETSET_MAGIC_DEF("max_screen_width", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_WIDTH),
1655 : JS_CGETSET_MAGIC_DEF("max_screen_height", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_HEIGHT),
1656 : JS_CGETSET_MAGIC_DEF("max_screen_depth", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_DISPLAY_DEPTH),
1657 : JS_CGETSET_MAGIC_DEF("max_screen_fps", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_FPS),
1658 : JS_CGETSET_MAGIC_DEF("max_screen_views", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_VIEWS),
1659 : JS_CGETSET_MAGIC_DEF("max_audio_channels", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_CHANNELS),
1660 : JS_CGETSET_MAGIC_DEF("max_audio_samplerate", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_SAMPLERATE),
1661 : JS_CGETSET_MAGIC_DEF("max_audio_depth", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_CAPS_MAX_AUDIO_DEPTH),
1662 : JS_CGETSET_MAGIC_DEF("events_queued", jsf_filter_prop_get, NULL, JSF_FILTER_NB_EVTS_QUEUED),
1663 : JS_CGETSET_MAGIC_DEF("clock_hint_us", jsf_filter_prop_get, NULL, JSF_FILTER_CLOCK_HINT_TIME),
1664 : JS_CGETSET_MAGIC_DEF("clock_hint_mediatime", jsf_filter_prop_get, NULL, JSF_FILTER_CLOCK_HINT_MEDIATIME),
1665 : JS_CGETSET_MAGIC_DEF("connections_pending", jsf_filter_prop_get, NULL, JSF_FILTER_CONNECTIONS_PENDING),
1666 : JS_CGETSET_MAGIC_DEF("iname", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_INAME),
1667 :
1668 :
1669 : JS_CFUNC_DEF("set_desc", 0, jsf_filter_set_desc),
1670 : JS_CFUNC_DEF("set_version", 0, jsf_filter_set_version),
1671 : JS_CFUNC_DEF("set_author", 0, jsf_filter_set_author),
1672 : JS_CFUNC_DEF("set_help", 0, jsf_filter_set_help),
1673 : JS_CFUNC_DEF("set_arg", 0, jsf_filter_set_arg),
1674 : JS_CFUNC_DEF("set_cap", 0, jsf_filter_set_cap),
1675 : JS_CFUNC_DEF("set_name", 0, jsf_filter_set_name),
1676 : JS_CFUNC_DEF("new_pid", 0, jsf_filter_new_pid),
1677 : JS_CFUNC_DEF("send_event", 0, jsf_filter_send_event),
1678 : JS_CFUNC_DEF("get_info", 0, jsf_filter_get_info),
1679 : JS_CFUNC_DEF("is_supported_mime", 0, jsf_filter_is_supported_mime),
1680 : JS_CFUNC_DEF("update_status", 0, jsf_filter_update_status),
1681 : JS_CFUNC_DEF("reschedule", 0, jsf_filter_reschedule_in),
1682 : JS_CFUNC_DEF("post_task", 0, jsf_filter_post_task),
1683 : JS_CFUNC_DEF("notify_failure", 0, jsf_filter_notify_failure),
1684 : JS_CFUNC_DEF("is_supported_source", 0, jsf_filter_is_supported_source),
1685 : JS_CFUNC_DEF("hint_clock", 0, jsf_filter_hint_clock),
1686 : JS_CFUNC_DEF("send_update", 0, jsf_filter_send_update),
1687 : JS_CFUNC_DEF("add_source", 0, jsf_filter_add_source),
1688 : JS_CFUNC_DEF("add_destination", 0, jsf_filter_add_dest),
1689 : JS_CFUNC_DEF("add_filter", 0, jsf_filter_add_filter),
1690 : JS_CFUNC_DEF("make_sticky", 0, jsf_filter_make_sticky),
1691 : JS_CFUNC_DEF("prevent_blocking", 1, jsf_filter_prevent_blocking),
1692 : JS_CFUNC_DEF("block_eos", 1, jsf_filter_block_eos),
1693 : JS_CFUNC_DEF("abort", 0, jsf_filter_abort),
1694 : };
1695 :
1696 :
1697 :
1698 3 : static JSValue jsf_filter_set_source_internal(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool use_restricted)
1699 : {
1700 : GF_Err e=GF_OK;
1701 : const char *source_id=NULL;
1702 3 : GF_JSFilterInstanceCtx *f_inst = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1703 3 : if (!f_inst || (argc<1)) return JS_EXCEPTION;
1704 :
1705 3 : GF_JSFilterCtx *f_from = JS_GetOpaque(argv[0], jsf_filter_class_id);
1706 3 : GF_JSFilterInstanceCtx *fi_from = JS_GetOpaque(argv[0], jsf_filter_inst_class_id);
1707 3 : if (!f_from && !fi_from) return JS_EXCEPTION;
1708 :
1709 : source_id = NULL;
1710 3 : if (argc>1) {
1711 : source_id = JS_ToCString(ctx, argv[2]);
1712 0 : if (!source_id) return JS_EXCEPTION;
1713 : }
1714 :
1715 3 : if (use_restricted)
1716 0 : e = gf_filter_set_source_restricted(f_inst->filter, fi_from ? fi_from->filter : f_from->filter, source_id);
1717 : else
1718 3 : e = gf_filter_set_source(f_inst->filter, fi_from ? fi_from->filter : f_from->filter, source_id);
1719 :
1720 3 : JS_FreeCString(ctx, source_id);
1721 3 : if (e) return js_throw_err(ctx, e);
1722 3 : return JS_UNDEFINED;
1723 : }
1724 :
1725 3 : static JSValue jsf_filter_set_source(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1726 : {
1727 3 : return jsf_filter_set_source_internal(ctx, this_val, argc, argv, GF_FALSE);
1728 : }
1729 :
1730 0 : static JSValue jsf_filter_set_source_restricted(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1731 : {
1732 0 : return jsf_filter_set_source_internal(ctx, this_val, argc, argv, GF_TRUE);
1733 : }
1734 :
1735 2 : static JSValue jsf_filter_reset_source(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1736 : {
1737 2 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1738 2 : if (!jsfi) return JS_EXCEPTION;
1739 2 : gf_filter_reset_source(jsfi->jsf->filter);
1740 2 : return JS_UNDEFINED;
1741 : }
1742 :
1743 1 : static JSValue jsf_filter_remove(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1744 : {
1745 1 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1746 1 : if (!jsfi) return JS_EXCEPTION;
1747 1 : if (jsfi->fmode==JSF_FINST_SOURCE)
1748 1 : gf_filter_remove_src(jsfi->jsf->filter, jsfi->filter);
1749 1 : return JS_UNDEFINED;
1750 : }
1751 :
1752 :
1753 :
1754 183 : static JSValue jsf_filter_has_pid_connections_pending(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1755 : {
1756 : GF_Filter *stop_at = NULL;
1757 183 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1758 183 : if (!jsfi) return JS_EXCEPTION;
1759 183 : if (argc && (JS_IsNull(argv[0]) || JS_IsObject(argv[0]) ) ) {
1760 0 : GF_JSFilterInstanceCtx *fi_stop = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1761 0 : GF_JSFilterCtx *f_stop = JS_GetOpaque(this_val, jsf_filter_class_id);
1762 0 : if (fi_stop) stop_at = fi_stop->filter;
1763 0 : else if (f_stop) stop_at = f_stop->filter;
1764 183 : } else if (jsfi->fmode==JSF_FINST_SOURCE) {
1765 183 : stop_at = jsfi->jsf->filter;
1766 : }
1767 183 : return JS_NewBool(ctx, gf_filter_has_pid_connection_pending(jsfi->filter, stop_at) );
1768 : }
1769 :
1770 0 : static void jsf_on_setup_error(GF_Filter *f, void *on_setup_error_udta, GF_Err e)
1771 : {
1772 : GF_JSFilterInstanceCtx *f_inst = on_setup_error_udta;
1773 : JSValue ret, argv[1];
1774 0 : gf_js_lock(f_inst->jsf->ctx, GF_TRUE);
1775 :
1776 0 : argv[0] = JS_NewInt32(f_inst->jsf->ctx, e);
1777 :
1778 0 : ret = JS_Call(f_inst->jsf->ctx, f_inst->setup_failure_fun, f_inst->filter_obj, 0, NULL);
1779 :
1780 0 : JS_FreeValue(f_inst->jsf->ctx, argv[0]);
1781 0 : JS_FreeValue(f_inst->jsf->ctx, ret);
1782 0 : gf_js_lock(f_inst->jsf->ctx, GF_FALSE);
1783 0 : js_do_loop(f_inst->jsf->ctx);
1784 0 : }
1785 :
1786 2 : static JSValue jsf_filter_inst_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
1787 : {
1788 2 : GF_JSFilterInstanceCtx *f_inst = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1789 2 : if (!f_inst) return JS_EXCEPTION;
1790 :
1791 2 : if (magic==0) {
1792 2 : if (JS_IsFunction(ctx, value) || JS_IsUndefined(value) || JS_IsNull(value)) {
1793 6 : if (JS_IsUndefined(f_inst->setup_failure_fun) && !JS_IsUndefined(value)) {
1794 :
1795 2 : gf_filter_set_setup_failure_callback(f_inst->jsf->filter, f_inst->filter, jsf_on_setup_error, f_inst);
1796 : }
1797 : JS_FreeValue(ctx, f_inst->setup_failure_fun);
1798 2 : f_inst->setup_failure_fun = JS_DupValue(ctx, value);
1799 : }
1800 2 : return JS_UNDEFINED;
1801 : }
1802 0 : return JS_UNDEFINED;
1803 : }
1804 :
1805 2 : static JSValue jsf_filter_inst_get_arg(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1806 : {
1807 : const char *arg_name=NULL;
1808 : JSValue res;
1809 2 : GF_JSFilterInstanceCtx *f_inst = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1810 2 : if (!f_inst || !argc) return JS_EXCEPTION;
1811 : arg_name = JS_ToCString(ctx, argv[0]);
1812 2 : if (!arg_name) return JS_EXCEPTION;
1813 2 : if ((argc>1) && JS_ToBool(ctx, argv[1])) {
1814 : char dump[GF_PROP_DUMP_ARG_SIZE];
1815 0 : const char *arg_val = gf_filter_get_arg_str(f_inst->filter, arg_name, dump);
1816 0 : res = arg_val ? JS_NewString(ctx, dump) : JS_NULL;
1817 : } else {
1818 : GF_PropertyValue p;
1819 2 : if (gf_filter_get_arg(f_inst->filter, arg_name, &p))
1820 2 : res = jsf_NewProp(ctx, &p);
1821 : else
1822 0 : res = JS_NULL;
1823 : }
1824 2 : JS_FreeCString(ctx, arg_name);
1825 2 : return res;
1826 : }
1827 :
1828 :
1829 2 : static JSValue jsf_filter_inst_disable_probe(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1830 : {
1831 2 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1832 2 : if (!jsfi) return JS_EXCEPTION;
1833 2 : gf_filter_disable_probe(jsfi->filter);
1834 2 : return JS_UNDEFINED;
1835 : }
1836 2 : static JSValue jsf_filter_inst_disable_inputs(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1837 : {
1838 2 : GF_JSFilterInstanceCtx *jsfi = JS_GetOpaque(this_val, jsf_filter_inst_class_id);
1839 2 : if (!jsfi) return JS_EXCEPTION;
1840 2 : gf_filter_disable_inputs(jsfi->filter);
1841 2 : return JS_UNDEFINED;
1842 : }
1843 :
1844 : static const JSCFunctionListEntry jsf_filter_inst_funcs[] = {
1845 : JS_CGETSET_MAGIC_DEF("on_setup_failure", NULL, jsf_filter_inst_prop_set, 0),
1846 : JS_CFUNC_DEF("send_event", 0, jsf_filter_send_event),
1847 : JS_CFUNC_DEF("get_info", 0, jsf_filter_get_info),
1848 : JS_CFUNC_DEF("send_update", 0, jsf_filter_send_update),
1849 : JS_CFUNC_DEF("set_source", 0, jsf_filter_set_source),
1850 : JS_CFUNC_DEF("set_source_restricted", 0, jsf_filter_set_source_restricted),
1851 : JS_CFUNC_DEF("remove", 0, jsf_filter_remove),
1852 : JS_CFUNC_DEF("has_pid_connections_pending", 0, jsf_filter_has_pid_connections_pending),
1853 : JS_CFUNC_DEF("get_arg", 0, jsf_filter_inst_get_arg),
1854 : JS_CFUNC_DEF("disable_probe", 0, jsf_filter_inst_disable_probe),
1855 : JS_CFUNC_DEF("disable_inputs", 0, jsf_filter_inst_disable_inputs),
1856 : JS_CFUNC_DEF("reset_source", 0, jsf_filter_reset_source),
1857 : };
1858 :
1859 :
1860 39 : static JSValue jsf_pid_set_prop(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
1861 : {
1862 : u32 ival;
1863 : GF_Err e = GF_OK;
1864 : const char *str=NULL;
1865 39 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
1866 39 : if (!pctx) return JS_EXCEPTION;
1867 39 : switch (magic) {
1868 11 : case JSF_PID_NAME:
1869 : str = JS_ToCString(ctx, value);
1870 11 : gf_filter_pid_set_name(pctx->pid, str);
1871 : break;
1872 25 : case JSF_PID_EOS:
1873 25 : if (JS_ToBool(ctx, value))
1874 25 : gf_filter_pid_set_eos(pctx->pid);
1875 : break;
1876 1 : case JSF_PID_MAX_BUFFER:
1877 1 : if (JS_ToInt32(ctx, &ival, value))
1878 0 : return JS_EXCEPTION;
1879 1 : gf_filter_pid_set_max_buffer(pctx->pid, ival);
1880 : break;
1881 1 : case JSF_PID_LOOSE_CONNECT:
1882 1 : if (JS_ToBool(ctx, value))
1883 1 : gf_filter_pid_set_loose_connect(pctx->pid);
1884 : break;
1885 0 : case JSF_PID_FRAMING_MODE:
1886 0 : gf_filter_pid_set_framing_mode(pctx->pid, JS_ToBool(ctx, value) );
1887 : break;
1888 0 : case JSF_PID_CLOCK_MODE:
1889 0 : gf_filter_pid_set_clock_mode(pctx->pid, JS_ToBool(ctx, value) );
1890 : break;
1891 1 : case JSF_PID_DISCARD:
1892 1 : gf_filter_pid_set_discard(pctx->pid, JS_ToBool(ctx, value) );
1893 : break;
1894 0 : case JSF_PID_REQUIRE_SOURCEID:
1895 0 : if (JS_ToBool(ctx, value))
1896 0 : gf_filter_pid_require_source_id(pctx->pid);
1897 : break;
1898 0 : case JSF_PID_RECOMPUTE_DTS:
1899 0 : gf_filter_pid_recompute_dts(pctx->pid, JS_ToBool(ctx, value));
1900 : break;
1901 : }
1902 :
1903 11 : if (str)
1904 11 : JS_FreeCString(ctx, str);
1905 : if (e) return js_throw_err(ctx, e);
1906 39 : return JS_UNDEFINED;
1907 : }
1908 :
1909 1063 : static JSValue jsf_pid_get_prop(JSContext *ctx, JSValueConst this_val, int magic)
1910 : {
1911 : u64 dur;
1912 : char *str;
1913 1063 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
1914 1063 : if (!pctx) return JS_EXCEPTION;
1915 1063 : switch (magic) {
1916 524 : case JSF_PID_NAME:
1917 524 : return JS_NewString(ctx, gf_filter_pid_get_name(pctx->pid) );
1918 531 : case JSF_PID_EOS:
1919 531 : return JS_NewBool (ctx, gf_filter_pid_is_eos(pctx->pid) );
1920 0 : case JSF_PID_EOS_SEEN:
1921 0 : return JS_NewBool (ctx, gf_filter_pid_has_seen_eos(pctx->pid) );
1922 0 : case JSF_PID_EOS_RECEIVED:
1923 0 : return JS_NewBool (ctx, gf_filter_pid_eos_received(pctx->pid) );
1924 0 : case JSF_PID_WOULD_BLOCK:
1925 0 : return JS_NewBool(ctx, gf_filter_pid_would_block(pctx->pid) );
1926 2 : case JSF_PID_FILTER_NAME:
1927 2 : return JS_NewString(ctx, gf_filter_pid_get_filter_name(pctx->pid) );
1928 2 : case JSF_PID_FILTER_SRC:
1929 2 : return JS_NewString(ctx, gf_filter_pid_get_source_filter_name(pctx->pid) );
1930 2 : case JSF_PID_FILTER_ARGS:
1931 2 : return JS_NewString(ctx, gf_filter_pid_get_args(pctx->pid) );
1932 2 : case JSF_PID_FILTER_SRC_ARGS:
1933 2 : return JS_NewString(ctx, gf_filter_pid_orig_src_args(pctx->pid, GF_FALSE) );
1934 0 : case JSF_PID_FILTER_UNICITY_ARGS:
1935 0 : return JS_NewString(ctx, gf_filter_pid_orig_src_args(pctx->pid, GF_TRUE) );
1936 0 : case JSF_PID_MAX_BUFFER:
1937 0 : return JS_NewInt32(ctx, gf_filter_pid_get_max_buffer(pctx->pid) );
1938 0 : case JSF_PID_BUFFER:
1939 0 : return JS_NewInt64(ctx, gf_filter_pid_query_buffer_duration(pctx->pid, GF_FALSE) );
1940 0 : case JSF_PID_IS_FULL:
1941 0 : dur = gf_filter_pid_query_buffer_duration(pctx->pid, GF_TRUE);
1942 0 : return JS_NewBool(ctx, !dur ? 0 : 1);
1943 0 : case JSF_PID_FIRST_EMPTY:
1944 0 : return JS_NewBool (ctx, gf_filter_pid_first_packet_is_empty(pctx->pid) );
1945 0 : case JSF_PID_FIRST_CTS:
1946 0 : if (gf_filter_pid_get_first_packet_cts(pctx->pid, &dur))
1947 0 : return JS_NewInt64(ctx, dur);
1948 : else
1949 0 : return JS_NULL;
1950 0 : case JSF_PID_NB_PACKETS:
1951 0 : return JS_NewInt32(ctx, gf_filter_pid_get_packet_count(pctx->pid) );
1952 0 : case JSF_PID_TIMESCALE:
1953 0 : return JS_NewInt32(ctx, gf_filter_pid_get_timescale(pctx->pid) );
1954 0 : case JSF_PID_SRC_URL:
1955 0 : str = gf_filter_pid_get_source(pctx->pid);
1956 0 : if (str) {
1957 0 : JSValue res = JS_NewString(ctx, str);
1958 0 : gf_free(str);
1959 0 : return res;
1960 : }
1961 0 : return JS_NULL;
1962 0 : case JSF_PID_DST_URL:
1963 0 : str = gf_filter_pid_get_destination(pctx->pid);
1964 0 : if (str) {
1965 0 : JSValue res = JS_NewString(ctx, str);
1966 0 : gf_free(str);
1967 0 : return res;
1968 : }
1969 0 : return JS_NULL;
1970 0 : case JSF_PID_MIN_PCK_DUR:
1971 0 : return JS_NewInt32(ctx, gf_filter_pid_get_min_pck_duration(pctx->pid) );
1972 0 : case JSF_PID_IS_PLAYING:
1973 0 : return JS_NewBool(ctx, gf_filter_pid_is_playing(pctx->pid) );
1974 : }
1975 0 : return JS_UNDEFINED;
1976 : }
1977 :
1978 5 : static JSValue jsf_pid_send_event(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1979 : {
1980 5 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
1981 5 : if (!pctx) return JS_EXCEPTION;
1982 5 : GF_FilterEvent *evt = JS_GetOpaque(argv[0], jsf_event_class_id);
1983 5 : if (!evt) return JS_EXCEPTION;
1984 5 : evt->base.on_pid = pctx->pid;
1985 5 : if (evt->base.type == GF_FEVT_PLAY) {
1986 5 : gf_filter_pid_init_play_event(pctx->pid, evt, evt->play.start_range, evt->play.speed, pctx->jsf->log_name);
1987 : }
1988 5 : gf_filter_pid_send_event(pctx->pid, evt);
1989 5 : return JS_UNDEFINED;
1990 : }
1991 :
1992 34 : static JSValue jsf_pid_enum_properties(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
1993 : {
1994 : s32 idx;
1995 : u32 p4cc;
1996 : const char *pname;
1997 : JSValue res;
1998 : const GF_PropertyValue *prop;
1999 34 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2000 34 : if (!pctx) return JS_EXCEPTION;
2001 34 : if (JS_ToInt32(ctx, &idx, argv[0]))
2002 0 : return JS_EXCEPTION;
2003 :
2004 34 : if ((argc>1) && JS_ToBool(ctx, argv[1])) {
2005 0 : prop = gf_filter_pid_enum_info(pctx->pid, &idx, &p4cc, &pname);
2006 : } else {
2007 34 : prop = gf_filter_pid_enum_properties(pctx->pid, &idx, &p4cc, &pname);
2008 : }
2009 34 : if (!prop) return JS_NULL;
2010 32 : if (!pname) pname = gf_props_4cc_get_name(p4cc);
2011 32 : if (!pname) return JS_EXCEPTION;
2012 :
2013 32 : res = JS_NewObject(ctx);
2014 32 : JS_SetPropertyStr(ctx, res, "name", JS_NewString(ctx, pname));
2015 64 : JS_SetPropertyStr(ctx, res, "type", JS_NewInt32(ctx, prop->type));
2016 32 : JS_SetPropertyStr(ctx, res, "value", jsf_NewProp(ctx, prop));
2017 32 : return res;
2018 : }
2019 :
2020 27 : static JSValue jsf_pid_get_property_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool is_info)
2021 : {
2022 : JSValue res;
2023 : const char *name=NULL;
2024 : const GF_PropertyValue *prop;
2025 27 : GF_PropertyEntry *pe = NULL;
2026 27 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2027 27 : if (!pctx) return JS_EXCEPTION;
2028 : name = JS_ToCString(ctx, argv[0]);
2029 27 : if (!name) return JS_EXCEPTION;
2030 27 : if ((argc>1) && JS_ToBool(ctx, argv[1])) {
2031 0 : if (is_info) {
2032 0 : prop = gf_filter_pid_get_info_str(pctx->pid, name, &pe);
2033 : } else {
2034 0 : prop = gf_filter_pid_get_property_str(pctx->pid, name);
2035 : }
2036 0 : JS_FreeCString(ctx, name);
2037 0 : if (!prop) return JS_NULL;
2038 0 : res = jsf_NewProp(ctx, prop);
2039 0 : JS_SetPropertyStr(ctx, res, "type", JS_NewInt32(ctx, prop->type));
2040 : } else {
2041 27 : u32 p4cc = gf_props_get_id(name);
2042 27 : JS_FreeCString(ctx, name);
2043 27 : if (!p4cc) return JS_EXCEPTION;
2044 27 : if (is_info) {
2045 1 : prop = gf_filter_pid_get_info(pctx->pid, p4cc, &pe);
2046 : } else {
2047 26 : prop = gf_filter_pid_get_property(pctx->pid, p4cc);
2048 : }
2049 27 : if (!prop) return JS_NULL;
2050 27 : res = jsf_NewPropTranslate(ctx, prop, p4cc);
2051 : }
2052 27 : gf_filter_release_property(pe);
2053 27 : return res;
2054 : }
2055 26 : static JSValue jsf_pid_get_property(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2056 : {
2057 26 : return jsf_pid_get_property_ex(ctx, this_val, argc, argv, GF_FALSE);
2058 : }
2059 1 : static JSValue jsf_pid_get_info(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2060 : {
2061 1 : return jsf_pid_get_property_ex(ctx, this_val, argc, argv, GF_TRUE);
2062 : }
2063 :
2064 :
2065 2619 : static JSValue jsf_pid_get_packet(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2066 : {
2067 : JSValue res;
2068 : GF_FilterPacket *pck;
2069 : GF_JSPckCtx *pckctx;
2070 2619 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2071 2619 : if (!pctx) return JS_EXCEPTION;
2072 2619 : if (!pctx->jsf->filter->in_process)
2073 0 : return js_throw_err_msg(ctx, GF_BAD_PARAM, "Filter %s attempt to query packet outside process callback not allowed!\n", pctx->jsf->filter->name);
2074 :
2075 2619 : pck = gf_filter_pid_get_packet(pctx->pid);
2076 2619 : if (!pck) return JS_NULL;
2077 :
2078 1407 : if (pctx->pck_head) {
2079 : pckctx = pctx->pck_head;
2080 : assert(pckctx->pck == pck);
2081 : return JS_DupValue(ctx, pckctx->jsobj);
2082 : }
2083 :
2084 1407 : res = JS_NewObjectClass(ctx, jsf_pck_class_id);
2085 1407 : pckctx = gf_list_pop_back(pctx->jsf->pck_res);
2086 1407 : if (!pckctx) {
2087 9 : GF_SAFEALLOC(pckctx, GF_JSPckCtx);
2088 9 : if (!pckctx) return js_throw_err(ctx, GF_OUT_OF_MEM);
2089 : }
2090 : memset(pckctx, 0, sizeof(GF_JSPckCtx));
2091 1407 : pckctx->jspid = pctx;
2092 1407 : pckctx->pck = pck;
2093 1407 : pckctx->jsobj = JS_DupValue(ctx, res);
2094 1407 : pckctx->ref_val = JS_UNDEFINED;
2095 1407 : pckctx->data_ab = JS_UNDEFINED;
2096 1407 : pctx->pck_head = pckctx;
2097 :
2098 1407 : JS_SetOpaque(res, pckctx);
2099 1407 : return res;
2100 : }
2101 1407 : static JSValue jsf_pid_drop_packet(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2102 : {
2103 : GF_JSPckCtx *pckctx;
2104 1407 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2105 1407 : if (!pctx) return JS_EXCEPTION;
2106 1407 : if (!pctx->jsf->filter->in_process)
2107 0 : return js_throw_err_msg(ctx, GF_BAD_PARAM, "Filter %s attempt to drop packet outside process callback not allowed!\n", pctx->jsf->filter->name);
2108 :
2109 1407 : if (!pctx->pck_head) {
2110 0 : if (gf_filter_pid_get_packet_count(pctx->pid)) {
2111 0 : gf_filter_pid_drop_packet(pctx->pid);
2112 : }
2113 0 : return JS_UNDEFINED;
2114 : }
2115 :
2116 : pckctx = pctx->pck_head;
2117 1407 : pckctx->pck = NULL;
2118 1407 : pctx->pck_head = NULL;
2119 : JS_FreeValue(ctx, pckctx->jsobj);
2120 1407 : pckctx->jsobj = JS_UNDEFINED;
2121 1407 : gf_filter_pid_drop_packet(pctx->pid);
2122 1407 : return JS_UNDEFINED;
2123 : }
2124 :
2125 2 : static JSValue jsf_pid_is_filter_in_parents(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2126 : {
2127 2 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2128 2 : if (!pctx || !argc) return JS_EXCEPTION;
2129 2 : GF_JSFilterCtx *f_ctx = JS_GetOpaque(argv[0], jsf_filter_class_id);
2130 2 : GF_JSFilterInstanceCtx *fi_ctx = JS_GetOpaque(argv[0], jsf_filter_inst_class_id);
2131 2 : if (!f_ctx && !fi_ctx) return JS_EXCEPTION;
2132 2 : return JS_NewBool(ctx, gf_filter_pid_is_filter_in_parents(pctx->pid, f_ctx ? f_ctx->filter : fi_ctx->filter));
2133 : }
2134 :
2135 2 : static JSValue jsf_pid_get_buffer_occupancy(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2136 : {
2137 : JSValue res;
2138 : Bool in_final_flush;
2139 : u32 max_units, nb_pck, max_dur, dur;
2140 2 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2141 2 : if (!pctx) return JS_EXCEPTION;
2142 :
2143 2 : in_final_flush = !gf_filter_pid_get_buffer_occupancy(pctx->pid, &max_units, &nb_pck, &max_dur, &dur);
2144 2 : res = JS_NewObject(ctx);
2145 4 : JS_SetPropertyStr(ctx, res, "max_units", JS_NewInt32(ctx, max_units));
2146 4 : JS_SetPropertyStr(ctx, res, "nb_pck", JS_NewInt32(ctx, nb_pck));
2147 4 : JS_SetPropertyStr(ctx, res, "max_dur", JS_NewInt32(ctx, max_dur));
2148 4 : JS_SetPropertyStr(ctx, res, "dur", JS_NewInt32(ctx, dur));
2149 4 : JS_SetPropertyStr(ctx, res, "final_flush", JS_NewBool(ctx, in_final_flush));
2150 2 : return res;
2151 : }
2152 2 : static JSValue jsf_pid_clear_eos(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2153 : {
2154 2 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2155 2 : if (!pctx || !argc) return JS_EXCEPTION;
2156 2 : gf_filter_pid_clear_eos(pctx->pid, JS_ToBool(ctx, argv[0]));
2157 2 : return JS_UNDEFINED;
2158 : }
2159 2 : static JSValue jsf_pid_check_caps(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2160 : {
2161 2 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2162 2 : if (!pctx) return JS_EXCEPTION;
2163 2 : return JS_NewBool(ctx, gf_filter_pid_check_caps(pctx->pid));
2164 : }
2165 2 : static JSValue jsf_pid_discard_block(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2166 : {
2167 2 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2168 2 : if (!pctx) return JS_EXCEPTION;
2169 2 : gf_filter_pid_discard_block(pctx->pid);
2170 2 : return JS_UNDEFINED;
2171 : }
2172 1 : static JSValue jsf_pid_allow_direct_dispatch(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2173 : {
2174 1 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2175 1 : if (!pctx) return JS_EXCEPTION;
2176 1 : gf_filter_pid_allow_direct_dispatch(pctx->pid);
2177 1 : return JS_UNDEFINED;
2178 : }
2179 1 : static JSValue jsf_pid_resolve_file_template(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2180 : {
2181 1 : u32 fileidx=0;
2182 : GF_Err e;
2183 : char szFinal[GF_MAX_PATH];
2184 : const char *templ, *suffix=NULL;
2185 1 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2186 1 : if (!pctx || !argc) return JS_EXCEPTION;
2187 :
2188 : templ = JS_ToCString(ctx, argv[0]);
2189 1 : if (!templ)
2190 0 : return JS_EXCEPTION;
2191 :
2192 1 : if ((argc>=2) && JS_ToInt32(ctx, &fileidx, argv[1])) {
2193 0 : JS_FreeCString(ctx, templ);
2194 0 : return JS_EXCEPTION;
2195 : }
2196 :
2197 1 : if (argc==3)
2198 : suffix = JS_ToCString(ctx, argv[2]);
2199 :
2200 1 : e = gf_filter_pid_resolve_file_template(pctx->pid, (char *)templ, szFinal, fileidx, suffix);
2201 1 : JS_FreeCString(ctx, templ);
2202 :
2203 1 : if (e)
2204 0 : return js_throw_err(ctx, e);
2205 1 : return JS_NewString(ctx, szFinal);
2206 : }
2207 :
2208 2 : static JSValue jsf_pid_query_caps(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2209 : {
2210 : const char *name=NULL;
2211 : const GF_PropertyValue *prop;
2212 2 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2213 2 : if (!pctx || !argc) return JS_EXCEPTION;
2214 :
2215 : name = JS_ToCString(ctx, argv[0]);
2216 2 : if (!name) return JS_EXCEPTION;
2217 :
2218 2 : if ((argc>1) && JS_ToBool(ctx, argv[1])) {
2219 : JSValue res;
2220 1 : prop = gf_filter_pid_caps_query_str(pctx->pid, name);
2221 1 : JS_FreeCString(ctx, name);
2222 1 : if (!prop) return JS_NULL;
2223 0 : res = jsf_NewProp(ctx, prop);
2224 0 : JS_SetPropertyStr(ctx, res, "type", JS_NewInt32(ctx, prop->type));
2225 : } else {
2226 1 : u32 p4cc = gf_props_get_id(name);
2227 1 : JS_FreeCString(ctx, name);
2228 1 : if (!p4cc)
2229 0 : return js_throw_err(ctx, GF_BAD_PARAM);
2230 :
2231 1 : prop = gf_filter_pid_caps_query(pctx->pid, p4cc);
2232 1 : if (!prop) return JS_NULL;
2233 0 : return jsf_NewPropTranslate(ctx, prop, p4cc);
2234 : }
2235 0 : return JS_UNDEFINED;
2236 : }
2237 :
2238 2 : static JSValue jsf_pid_get_statistics(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2239 : {
2240 : JSValue res;
2241 : u32 mode;
2242 : GF_Err e;
2243 : GF_FilterPidStatistics stats;
2244 2 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2245 2 : if (!pctx || !argc) return JS_EXCEPTION;
2246 2 : if (JS_ToInt32(ctx, &mode, argv[0]))
2247 0 : return JS_EXCEPTION;
2248 :
2249 2 : e = gf_filter_pid_get_statistics(pctx->pid, &stats, mode);
2250 2 : if (e)
2251 0 : return js_throw_err(ctx, e);
2252 :
2253 2 : res = JS_NewObject(ctx);
2254 : #define SET_PROP32(_val)\
2255 : JS_SetPropertyStr(ctx, res, #_val, JS_NewInt32(ctx, stats._val));
2256 : #define SET_PROP64(_val)\
2257 : JS_SetPropertyStr(ctx, res, #_val, JS_NewInt64(ctx, stats._val));
2258 : #define SET_PROPB(_val)\
2259 : JS_SetPropertyStr(ctx, res, #_val, JS_NewBool(ctx, stats._val));
2260 :
2261 4 : SET_PROPB(disconnected)
2262 4 : SET_PROP32(average_process_rate)
2263 4 : SET_PROP32(max_process_rate)
2264 4 : SET_PROP32(avgerage_bitrate)
2265 4 : SET_PROP32(max_bitrate)
2266 4 : SET_PROP32(nb_processed)
2267 4 : SET_PROP32(max_process_time)
2268 4 : SET_PROP64(total_process_time)
2269 4 : SET_PROP64(first_process_time)
2270 4 : SET_PROP64(last_process_time)
2271 4 : SET_PROP32(min_frame_dur)
2272 4 : SET_PROP32(nb_saps)
2273 4 : SET_PROP32(max_sap_process_time)
2274 4 : SET_PROP64(total_sap_process_time)
2275 4 : SET_PROP64(max_buffer_time)
2276 4 : SET_PROP64(max_playout_time)
2277 4 : SET_PROP64(min_playout_time)
2278 4 : SET_PROP64(buffer_time)
2279 4 : SET_PROP32(nb_buffer_units)
2280 2 : return res;
2281 : }
2282 :
2283 98 : void jsf_pck_shared_del(GF_Filter *filter, GF_FilterPid *PID, GF_FilterPacket *pck)
2284 : {
2285 : u32 i, count;
2286 98 : GF_JSPidCtx *pctx = gf_filter_pid_get_udta(PID);
2287 98 : count = gf_list_count(pctx->shared_pck);
2288 98 : for (i=0; i<count; i++) {
2289 98 : GF_JSPckCtx *pckc = gf_list_get(pctx->shared_pck, i);
2290 98 : if (pckc->pck == pck) {
2291 196 : if (!JS_IsUndefined(pckc->cbck_val)) {
2292 0 : JSValue res = JS_Call(pctx->jsf->ctx, pckc->cbck_val, pctx->jsobj, 0, NULL);
2293 0 : JS_FreeValue(pctx->jsf->ctx, res);
2294 0 : JS_FreeValue(pctx->jsf->ctx, pckc->cbck_val);
2295 0 : pckc->cbck_val = JS_UNDEFINED;
2296 : }
2297 98 : JS_FreeValue(pctx->jsf->ctx, pckc->ref_val);
2298 98 : pckc->ref_val = JS_UNDEFINED;
2299 98 : jsf_pck_detach_ab(pctx->jsf->ctx, pckc);
2300 : memset(pckc, 0, sizeof(GF_JSPckCtx));
2301 98 : gf_list_add(pctx->jsf->pck_res, pckc);
2302 98 : gf_list_rem(pctx->shared_pck, i);
2303 98 : return;
2304 : }
2305 : }
2306 : }
2307 :
2308 :
2309 : #if !defined(GPAC_DISABLE_3D) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
2310 : JSValue webgl_get_frame_interface(JSContext *ctx, int argc, JSValueConst *argv, gf_fsess_packet_destructor *pck_del, GF_FilterFrameInterface **f_ifce);
2311 : #endif
2312 :
2313 1307 : static JSValue jsf_pid_new_packet(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2314 : {
2315 : size_t ab_size;
2316 : u8 *data, *ab_data;
2317 : JSValue obj;
2318 : Bool use_shared=GF_FALSE;
2319 : GF_JSPckCtx *pckc;
2320 1307 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2321 :
2322 1307 : if (!pctx) return JS_EXCEPTION;
2323 1307 : if (!pctx->jsf->filter->in_process)
2324 0 : return js_throw_err_msg(ctx, GF_BAD_PARAM, "Filter %s attempt to create a new packet outside process callback not allowed!\n", pctx->jsf->filter->name);
2325 :
2326 :
2327 1307 : pckc = gf_list_pop_back(pctx->jsf->pck_res);
2328 1307 : if (!pckc) {
2329 25 : GF_SAFEALLOC(pckc, GF_JSPckCtx);
2330 25 : if (!pckc)
2331 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
2332 : }
2333 1307 : obj = JS_NewObjectClass(ctx, jsf_pck_class_id);
2334 1307 : if (JS_IsException(obj)) {
2335 0 : gf_list_add(pctx->jsf->pck_res, pckc);
2336 0 : return JS_EXCEPTION;
2337 : }
2338 1307 : JS_SetOpaque(obj, pckc);
2339 1307 : pckc->jspid = pctx;
2340 1307 : pckc->jsobj = obj;
2341 1307 : pckc->cbck_val = JS_UNDEFINED;
2342 1307 : pckc->ref_val = JS_UNDEFINED;
2343 1307 : pckc->data_ab = JS_UNDEFINED;
2344 :
2345 1307 : if (argc>1)
2346 980 : use_shared = JS_ToBool(ctx, argv[1]);
2347 :
2348 1307 : if (!argc) {
2349 0 : pckc->pck = gf_filter_pck_new_alloc(pctx->pid, 0, NULL);
2350 0 : goto pck_done;
2351 : }
2352 : /*string or true alloc*/
2353 2614 : if (JS_IsString(argv[0]) || JS_IsInteger(argv[0]) ) {
2354 : u32 len;
2355 : const char *str = NULL;
2356 425 : if (JS_IsInteger(argv[0]) ) {
2357 225 : if (use_shared)
2358 0 : return js_throw_err(ctx, GF_BAD_PARAM);
2359 225 : if (JS_ToInt32(ctx, &len, argv[0])) {
2360 0 : gf_list_add(pctx->jsf->pck_res, pckc);
2361 0 : return JS_EXCEPTION;
2362 : }
2363 : } else {
2364 : str = JS_ToCString(ctx, argv[0]);
2365 200 : len = (u32) strlen(str);
2366 : }
2367 425 : if (use_shared) {
2368 98 : pckc->pck = gf_filter_pck_new_shared(pctx->pid, str, len, jsf_pck_shared_del);
2369 98 : pckc->ref_val = JS_DupValue(ctx, argv[0]);
2370 98 : JS_FreeCString(ctx, str);
2371 98 : if (!pctx->shared_pck) pctx->shared_pck = gf_list_new();
2372 98 : gf_list_add(pctx->shared_pck, pckc);
2373 98 : pckc->flags = GF_JS_PCK_IS_SHARED;
2374 98 : if ((argc>2) && JS_IsFunction(ctx, argv[2]))
2375 0 : pckc->cbck_val = JS_DupValue(ctx, argv[2]);
2376 : } else {
2377 327 : u8 *pdata=NULL;
2378 327 : pckc->pck = gf_filter_pck_new_alloc(pctx->pid, len, &pdata);
2379 327 : if (str) {
2380 102 : memcpy(pdata, str, len);
2381 102 : JS_FreeCString(ctx, str);
2382 : }
2383 : }
2384 425 : goto pck_done;
2385 : }
2386 : //check packet reference
2387 882 : GF_JSPckCtx *pckc_ref = JS_GetOpaque(argv[0], jsf_pck_class_id);
2388 882 : if (pckc_ref) {
2389 277 : if (use_shared) {
2390 75 : pckc->pck = gf_filter_pck_new_ref(pctx->pid, 0, 0, pckc_ref->pck);
2391 75 : if ((argc>2) && JS_IsFunction(ctx, argv[2]))
2392 0 : pckc->cbck_val = JS_DupValue(ctx, argv[2]);
2393 : } else {
2394 : u8 *new_data;
2395 202 : if ((argc>2) && JS_ToBool(ctx, argv[2])) {
2396 0 : pckc->pck = gf_filter_pck_new_copy(pctx->pid, pckc_ref->pck, &new_data);
2397 : } else {
2398 202 : pckc->pck = gf_filter_pck_new_clone(pctx->pid, pckc_ref->pck, &new_data);
2399 : }
2400 : }
2401 : goto pck_done;
2402 : }
2403 : //check array buffer
2404 :
2405 1210 : if (!JS_IsObject(argv[0])) {
2406 : JS_FreeValue(ctx, obj);
2407 0 : return JS_EXCEPTION;
2408 : }
2409 605 : ab_data = JS_GetArrayBuffer(ctx, &ab_size, argv[0]);
2410 : //this is an array buffer
2411 605 : if (ab_data) {
2412 0 : if (use_shared) {
2413 0 : pckc->pck = gf_filter_pck_new_shared(pctx->pid, ab_data, (u32) ab_size, jsf_pck_shared_del);
2414 0 : pckc->ref_val = JS_DupValue(ctx, argv[0]);
2415 0 : if (!pctx->shared_pck) pctx->shared_pck = gf_list_new();
2416 0 : gf_list_add(pctx->shared_pck, pckc);
2417 0 : pckc->flags = GF_JS_PCK_IS_SHARED;
2418 0 : if ((argc>2) && JS_IsFunction(ctx, argv[2]))
2419 0 : pckc->cbck_val = JS_DupValue(ctx, argv[2]);
2420 : } else {
2421 0 : pckc->pck = gf_filter_pck_new_alloc(pctx->pid, (u32) ab_size, &data);
2422 0 : if (!data) {
2423 : JS_FreeValue(ctx, obj);
2424 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
2425 : }
2426 0 : memcpy(data, ab_data, ab_size);
2427 : }
2428 : goto pck_done;
2429 : }
2430 : /*try WebGL canvas*/
2431 : #if !defined(GPAC_DISABLE_3D) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
2432 605 : gf_fsess_packet_destructor pck_del = NULL;
2433 605 : GF_FilterFrameInterface *f_ifce = NULL;
2434 605 : JSValue res = webgl_get_frame_interface(ctx, argc, argv, &pck_del, &f_ifce);
2435 605 : if (!JS_IsNull(res)) {
2436 605 : if (JS_IsException(res)) {
2437 : JS_FreeValue(ctx, obj);
2438 0 : return res;
2439 : }
2440 : assert(f_ifce);
2441 605 : pckc->pck = gf_filter_pck_new_frame_interface(pctx->pid, f_ifce, pck_del);
2442 605 : goto pck_done;
2443 : }
2444 : #endif
2445 :
2446 : JS_FreeValue(ctx, obj);
2447 0 : return JS_EXCEPTION;
2448 :
2449 :
2450 1307 : pck_done:
2451 1307 : if (!pckc->pck) {
2452 : JS_FreeValue(ctx, obj);
2453 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
2454 : }
2455 1307 : pckc->flags |= GF_JS_PCK_IS_OUTPUT;
2456 1307 : return obj;
2457 : }
2458 :
2459 1 : static JSValue jsf_pid_get_clock_info(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2460 : {
2461 : u32 timescale;
2462 : u64 val;
2463 : GF_FilterClockType cktype;
2464 : JSValue res;
2465 1 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2466 1 : if (!pctx) return JS_EXCEPTION;
2467 1 : cktype = gf_filter_pid_get_clock_info(pctx->pid, &val, ×cale);
2468 1 : res = JS_NewObject(ctx);
2469 2 : JS_SetPropertyStr(ctx, res, "type", JS_NewInt32(ctx, cktype));
2470 2 : JS_SetPropertyStr(ctx, res, "timescale", JS_NewInt32(ctx, timescale));
2471 2 : JS_SetPropertyStr(ctx, res, "value", JS_NewInt64(ctx, val));
2472 1 : return res;
2473 : }
2474 :
2475 :
2476 263 : static JSValue jsf_pid_set_property_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 mode)
2477 : {
2478 : GF_Err e;
2479 : GF_PropertyValue prop;
2480 : const GF_PropertyValue *the_prop = NULL;
2481 : const char *name=NULL;
2482 263 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2483 263 : if (!pctx) return JS_EXCEPTION;
2484 : name = JS_ToCString(ctx, argv[0]);
2485 263 : if (!name) return JS_EXCEPTION;
2486 :
2487 263 : if ((argc>2) && JS_ToBool(ctx, argv[2])) {
2488 4 : if (!JS_IsNull(argv[1])) {
2489 2 : e = jsf_ToProp(pctx->jsf->filter, ctx, argv[1], 0, &prop);
2490 2 : JS_FreeCString(ctx, name);
2491 2 : if (e)
2492 0 : return js_throw_err(ctx, e);
2493 : the_prop = ∝
2494 : }
2495 2 : if (mode==1) {
2496 1 : e = gf_filter_pid_set_info_dyn(pctx->pid, (char *) name, &prop);
2497 1 : } else if (mode==2) {
2498 0 : e = gf_filter_pid_negociate_property_dyn(pctx->pid, (char *) name, &prop);
2499 : } else {
2500 1 : e = gf_filter_pid_set_property_dyn(pctx->pid, (char *) name, &prop);
2501 : }
2502 : } else {
2503 261 : u32 p4cc = gf_props_get_id(name);
2504 261 : JS_FreeCString(ctx, name);
2505 261 : if (!p4cc) return JS_EXCEPTION;
2506 522 : if (!JS_IsNull(argv[1])) {
2507 253 : e = jsf_ToProp(pctx->jsf->filter, ctx, argv[1], p4cc, &prop);
2508 253 : if (e)
2509 0 : return js_throw_err(ctx, e);
2510 :
2511 : the_prop = ∝
2512 : }
2513 261 : if (mode==1) {
2514 0 : e = gf_filter_pid_set_info(pctx->pid, p4cc, the_prop);
2515 261 : } else if (mode==2) {
2516 0 : e = gf_filter_pid_negociate_property(pctx->pid, p4cc, the_prop);
2517 : } else {
2518 261 : e = gf_filter_pid_set_property(pctx->pid, p4cc, the_prop);
2519 : }
2520 : }
2521 :
2522 263 : if (the_prop)
2523 255 : gf_props_reset_single(&prop);
2524 263 : if (e) return js_throw_err(ctx, e);
2525 263 : return JS_UNDEFINED;
2526 : }
2527 262 : static JSValue jsf_pid_set_property(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2528 : {
2529 262 : return jsf_pid_set_property_ex(ctx, this_val, argc, argv, 0);
2530 : }
2531 1 : static JSValue jsf_pid_set_info(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2532 : {
2533 1 : return jsf_pid_set_property_ex(ctx, this_val, argc, argv, 1);
2534 : }
2535 0 : static JSValue jsf_pid_negociate_prop(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2536 : {
2537 0 : return jsf_pid_set_property_ex(ctx, this_val, argc, argv, 2);
2538 : }
2539 :
2540 0 : static JSValue jsf_pid_ignore_blocking(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2541 : {
2542 : Bool do_ignore = GF_TRUE;
2543 0 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2544 0 : if (!pctx) return JS_EXCEPTION;
2545 0 : if (argc) do_ignore = JS_ToBool(ctx, argv[0]) ? GF_TRUE : GF_FALSE;
2546 0 : gf_filter_pid_ignore_blocking(pctx->pid, do_ignore);
2547 0 : return JS_UNDEFINED;
2548 :
2549 : }
2550 :
2551 1 : static JSValue jsf_pid_remove(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2552 : {
2553 1 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2554 1 : if (!pctx) return JS_EXCEPTION;
2555 1 : if (pctx->pid) {
2556 1 : gf_filter_pid_remove(pctx->pid);
2557 1 : pctx->pid = NULL;
2558 : }
2559 1 : JS_SetOpaque(this_val, NULL);
2560 1 : return JS_UNDEFINED;
2561 : }
2562 :
2563 1 : static JSValue jsf_pid_reset_props(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2564 : {
2565 : GF_Err e;
2566 1 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2567 1 : if (!pctx) return JS_EXCEPTION;
2568 1 : e = gf_filter_pid_reset_properties(pctx->pid);
2569 1 : if (e) return js_throw_err(ctx, e);
2570 1 : return JS_UNDEFINED;
2571 : }
2572 :
2573 11 : static JSValue jsf_pid_copy_props(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2574 : {
2575 : GF_Err e;
2576 11 : GF_JSPidCtx *pctx_this = JS_GetOpaque(this_val, jsf_pid_class_id);
2577 11 : if (!pctx_this || !argc) return JS_EXCEPTION;
2578 11 : GF_JSPidCtx *pctx_from = JS_GetOpaque(argv[0], jsf_pid_class_id);
2579 11 : if (!pctx_from) return JS_EXCEPTION;
2580 11 : e = gf_filter_pid_copy_properties(pctx_this->pid, pctx_from->pid);
2581 11 : if (e) return js_throw_err(ctx, e);
2582 11 : return JS_UNDEFINED;
2583 : }
2584 :
2585 278 : static JSValue jsf_pid_forward(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
2586 : {
2587 : GF_Err e;
2588 : GF_JSPckCtx *pckc;
2589 278 : GF_JSPidCtx *pctx = JS_GetOpaque(this_val, jsf_pid_class_id);
2590 278 : if (!pctx || !argc) return JS_EXCEPTION;
2591 556 : if (!JS_IsObject(argv[0])) return JS_EXCEPTION;
2592 278 : pckc = JS_GetOpaque(argv[0], jsf_pck_class_id);
2593 278 : if (!pckc || !pckc->pck) return JS_EXCEPTION;
2594 278 : e = gf_filter_pck_forward(pckc->pck, pctx->pid);
2595 278 : if (e) return js_throw_err(ctx, e);
2596 278 : return JS_UNDEFINED;
2597 : }
2598 :
2599 :
2600 : static const JSCFunctionListEntry jsf_pid_funcs[] = {
2601 : JS_CGETSET_MAGIC_DEF("name", jsf_pid_get_prop, jsf_pid_set_prop, JSF_PID_NAME),
2602 : JS_CGETSET_MAGIC_DEF("eos", jsf_pid_get_prop, jsf_pid_set_prop, JSF_PID_EOS),
2603 : JS_CGETSET_MAGIC_DEF("eos_seen", jsf_pid_get_prop, NULL, JSF_PID_EOS_SEEN),
2604 : JS_CGETSET_MAGIC_DEF("eos_received", jsf_pid_get_prop, NULL, JSF_PID_EOS_RECEIVED),
2605 : JS_CGETSET_MAGIC_DEF("would_block", jsf_pid_get_prop, NULL, JSF_PID_WOULD_BLOCK),
2606 : JS_CGETSET_MAGIC_DEF("filter_name", jsf_pid_get_prop, NULL, JSF_PID_FILTER_NAME),
2607 : JS_CGETSET_MAGIC_DEF("src_name", jsf_pid_get_prop, NULL, JSF_PID_FILTER_SRC),
2608 : JS_CGETSET_MAGIC_DEF("args", jsf_pid_get_prop, NULL, JSF_PID_FILTER_ARGS),
2609 : JS_CGETSET_MAGIC_DEF("src_args", jsf_pid_get_prop, NULL, JSF_PID_FILTER_SRC_ARGS),
2610 : JS_CGETSET_MAGIC_DEF("unicity_args", jsf_pid_get_prop, NULL, JSF_PID_FILTER_UNICITY_ARGS),
2611 : JS_CGETSET_MAGIC_DEF("max_buffer", jsf_pid_get_prop, jsf_pid_set_prop, JSF_PID_MAX_BUFFER),
2612 : JS_CGETSET_MAGIC_DEF("loose_connect", NULL, jsf_pid_set_prop, JSF_PID_LOOSE_CONNECT),
2613 : JS_CGETSET_MAGIC_DEF("framing", NULL, jsf_pid_set_prop, JSF_PID_FRAMING_MODE),
2614 : JS_CGETSET_MAGIC_DEF("buffer", jsf_pid_get_prop, NULL, JSF_PID_BUFFER),
2615 : JS_CGETSET_MAGIC_DEF("full", jsf_pid_get_prop, NULL, JSF_PID_IS_FULL),
2616 : JS_CGETSET_MAGIC_DEF("first_empty", jsf_pid_get_prop, NULL, JSF_PID_FIRST_EMPTY),
2617 : JS_CGETSET_MAGIC_DEF("first_cts", jsf_pid_get_prop, NULL, JSF_PID_FIRST_CTS),
2618 : JS_CGETSET_MAGIC_DEF("nb_pck_queued", jsf_pid_get_prop, NULL, JSF_PID_NB_PACKETS),
2619 : JS_CGETSET_MAGIC_DEF("timescale", jsf_pid_get_prop, NULL, JSF_PID_TIMESCALE),
2620 : JS_CGETSET_MAGIC_DEF("clock_mode", NULL, jsf_pid_set_prop, JSF_PID_CLOCK_MODE),
2621 : JS_CGETSET_MAGIC_DEF("discard", NULL, jsf_pid_set_prop, JSF_PID_DISCARD),
2622 : JS_CGETSET_MAGIC_DEF("src_url", jsf_pid_get_prop, NULL, JSF_PID_SRC_URL),
2623 : JS_CGETSET_MAGIC_DEF("dst_url", jsf_pid_get_prop, NULL, JSF_PID_DST_URL),
2624 : JS_CGETSET_MAGIC_DEF("require_source_id", NULL, jsf_pid_set_prop, JSF_PID_REQUIRE_SOURCEID),
2625 : JS_CGETSET_MAGIC_DEF("recompute_dts", NULL, jsf_pid_set_prop, JSF_PID_RECOMPUTE_DTS),
2626 : JS_CGETSET_MAGIC_DEF("min_pck_dur", jsf_pid_get_prop, NULL, JSF_PID_MIN_PCK_DUR),
2627 : JS_CGETSET_MAGIC_DEF("playing", jsf_pid_get_prop, NULL, JSF_PID_IS_PLAYING),
2628 : JS_CFUNC_DEF("send_event", 0, jsf_pid_send_event),
2629 : JS_CFUNC_DEF("enum_properties", 0, jsf_pid_enum_properties),
2630 : JS_CFUNC_DEF("get_prop", 0, jsf_pid_get_property),
2631 : JS_CFUNC_DEF("get_info", 0, jsf_pid_get_info),
2632 : JS_CFUNC_DEF("get_packet", 0, jsf_pid_get_packet),
2633 : JS_CFUNC_DEF("drop_packet", 0, jsf_pid_drop_packet),
2634 : JS_CFUNC_DEF("is_filter_in_parents", 0, jsf_pid_is_filter_in_parents),
2635 : JS_CFUNC_DEF("get_buffer_occupancy", 0, jsf_pid_get_buffer_occupancy),
2636 : JS_CFUNC_DEF("clear_eos", 0, jsf_pid_clear_eos),
2637 : JS_CFUNC_DEF("check_caps", 0, jsf_pid_check_caps),
2638 : JS_CFUNC_DEF("discard_block", 0, jsf_pid_discard_block),
2639 : JS_CFUNC_DEF("allow_direct_dispatch", 0, jsf_pid_allow_direct_dispatch),
2640 : JS_CFUNC_DEF("resolve_file_template", 0, jsf_pid_resolve_file_template),
2641 : JS_CFUNC_DEF("query_caps", 0, jsf_pid_query_caps),
2642 : JS_CFUNC_DEF("get_stats", 0, jsf_pid_get_statistics),
2643 : JS_CFUNC_DEF("get_clock_info", 0, jsf_pid_get_clock_info),
2644 : JS_CFUNC_DEF("set_prop", 0, jsf_pid_set_property),
2645 : JS_CFUNC_DEF("set_info", 0, jsf_pid_set_info),
2646 : JS_CFUNC_DEF("new_packet", 0, jsf_pid_new_packet),
2647 : JS_CFUNC_DEF("remove", 0, jsf_pid_remove),
2648 : JS_CFUNC_DEF("reset_props", 0, jsf_pid_reset_props),
2649 : JS_CFUNC_DEF("copy_props", 0, jsf_pid_copy_props),
2650 : JS_CFUNC_DEF("forward", 0, jsf_pid_forward),
2651 : JS_CFUNC_DEF("negociate_prop", 0, jsf_pid_negociate_prop),
2652 : JS_CFUNC_DEF("ignore_blocking", 0, jsf_pid_ignore_blocking),
2653 : };
2654 :
2655 : enum
2656 : {
2657 : JSF_EVENT_TYPE,
2658 : JSF_EVENT_NAME,
2659 : /*PLAY event*/
2660 : JSF_EVENT_START_RANGE,
2661 : JSF_EVENT_SPEED,
2662 : JSF_EVENT_HW_BUFFER_RESET,
2663 : JSF_EVENT_INITIAL_BROADCAST_PLAY,
2664 : JSF_EVENT_TIMESTAMP_BASED,
2665 : JSF_EVENT_FULL_FILE_ONLY,
2666 : JSF_EVENT_FORCE_DASH_SEG_SWITCH,
2667 : JSF_EVENT_FROM_PCK,
2668 : /*source switch*/
2669 : JSF_EVENT_START_OFFSET,
2670 : JSF_EVENT_END_OFFSET,
2671 : JSF_EVENT_SOURCE_SWITCH,
2672 : JSF_EVENT_SKIP_CACHE_EXPIRATION,
2673 : JSF_EVENT_HINT_BLOCK_SIZE,
2674 : /*segment size*/
2675 : JSF_EVENT_SEG_URL,
2676 : JSF_EVENT_SEG_IS_INIT,
2677 : JSF_EVENT_MEDIA_START_RANGE,
2678 : JSF_EVENT_MEDIA_END_RANGE,
2679 : JSF_EVENT_IDX_START_RANGE,
2680 : JSF_EVENT_IDX_END_RANGE,
2681 : /*quality switch*/
2682 : JSF_EVENT_SWITCH_UP,
2683 : JSF_EVENT_SWITCH_GROUP_IDX,
2684 : JSF_EVENT_SWITCH_QUALITY_IDX,
2685 : JSF_EVENT_SWITCH_TILE_MODE,
2686 : JSF_EVENT_SWITCH_QUALITY_DEGRADATION,
2687 : /*visibility hint*/
2688 : JSF_EVENT_VIS_MIN_X,
2689 : JSF_EVENT_VIS_MIN_Y,
2690 : JSF_EVENT_VIS_MAX_X,
2691 : JSF_EVENT_VIS_MAX_Y,
2692 : JSF_EVENT_VIS_IS_GAZE,
2693 : /*buffer requirements*/
2694 : JSF_EVENT_BUFREQ_MAX_BUFFER_US,
2695 : JSF_EVENT_BUFREQ_MAX_PLAYOUT_US,
2696 : JSF_EVENT_BUFREQ_MIN_PLAYOUT_US,
2697 : JSF_EVENT_BUFREQ_PID_ONLY,
2698 :
2699 : JSF_EVENT_USER_TYPE,
2700 : JSF_EVENT_USER_KEYCODE,
2701 : JSF_EVENT_USER_KEYNAME,
2702 : JSF_EVENT_USER_KEYMODS,
2703 : JSF_EVENT_USER_MOUSE_X,
2704 : JSF_EVENT_USER_MOUSE_Y,
2705 : JSF_EVENT_USER_WHEEL,
2706 : JSF_EVENT_USER_BUTTON,
2707 : JSF_EVENT_USER_HWKEY,
2708 : JSF_EVENT_USER_DROPFILES,
2709 : JSF_EVENT_USER_TEXT,
2710 : JSF_EVENT_USER_MT_ROTATION,
2711 : JSF_EVENT_USER_MT_PINCH,
2712 : JSF_EVENT_USER_MT_FINGERS,
2713 : JSF_EVENT_USER_WIDTH,
2714 : JSF_EVENT_USER_HEIGHT,
2715 : JSF_EVENT_USER_SHOWTYPE,
2716 : JSF_EVENT_USER_MOVE_X,
2717 : JSF_EVENT_USER_MOVE_Y,
2718 : JSF_EVENT_USER_MOVE_RELATIVE,
2719 : JSF_EVENT_USER_MOVE_ALIGN_X,
2720 : JSF_EVENT_USER_MOVE_ALIGN_Y,
2721 : JSF_EVENT_USER_CAPTION,
2722 : };
2723 :
2724 505 : static Bool jsf_check_evt(u32 evt_type, u8 ui_type, int magic)
2725 : {
2726 505 : if (magic==JSF_EVENT_TYPE) return GF_TRUE;
2727 93 : if (magic==JSF_EVENT_NAME) return GF_TRUE;
2728 91 : switch (evt_type) {
2729 6 : case GF_FEVT_PLAY:
2730 6 : switch (magic) {
2731 : case JSF_EVENT_START_RANGE:
2732 : case JSF_EVENT_SPEED:
2733 : case JSF_EVENT_HW_BUFFER_RESET:
2734 : case JSF_EVENT_INITIAL_BROADCAST_PLAY:
2735 : case JSF_EVENT_TIMESTAMP_BASED:
2736 : case JSF_EVENT_FULL_FILE_ONLY:
2737 : case JSF_EVENT_FORCE_DASH_SEG_SWITCH:
2738 : case JSF_EVENT_FROM_PCK:
2739 : return GF_TRUE;
2740 0 : default:
2741 0 : return GF_FALSE;
2742 : }
2743 : break;
2744 0 : case GF_FEVT_SET_SPEED:
2745 0 : return (magic == JSF_EVENT_SPEED) ? GF_TRUE : GF_FALSE;
2746 0 : case GF_FEVT_SOURCE_SWITCH:
2747 0 : switch (magic) {
2748 : case JSF_EVENT_START_OFFSET:
2749 : case JSF_EVENT_END_OFFSET:
2750 : case JSF_EVENT_SOURCE_SWITCH:
2751 : case JSF_EVENT_SKIP_CACHE_EXPIRATION:
2752 : case JSF_EVENT_HINT_BLOCK_SIZE:
2753 : return GF_TRUE;
2754 0 : default:
2755 0 : return GF_FALSE;
2756 : }
2757 : break;
2758 0 : case GF_FEVT_SEGMENT_SIZE:
2759 0 : switch (magic) {
2760 : case JSF_EVENT_SEG_URL:
2761 : case JSF_EVENT_SEG_IS_INIT:
2762 : case JSF_EVENT_MEDIA_START_RANGE:
2763 : case JSF_EVENT_MEDIA_END_RANGE:
2764 : case JSF_EVENT_IDX_START_RANGE:
2765 : case JSF_EVENT_IDX_END_RANGE:
2766 : return GF_TRUE;
2767 0 : default:
2768 0 : return GF_FALSE;
2769 : }
2770 : break;
2771 0 : case GF_FEVT_QUALITY_SWITCH:
2772 0 : switch (magic) {
2773 : case JSF_EVENT_SWITCH_UP:
2774 : case JSF_EVENT_SWITCH_GROUP_IDX:
2775 : case JSF_EVENT_SWITCH_QUALITY_IDX:
2776 : case JSF_EVENT_SWITCH_TILE_MODE:
2777 : case JSF_EVENT_SWITCH_QUALITY_DEGRADATION:
2778 : return GF_TRUE;
2779 0 : default:
2780 0 : return GF_FALSE;
2781 : }
2782 : break;
2783 0 : case GF_FEVT_VISIBILITY_HINT:
2784 0 : switch (magic) {
2785 : case JSF_EVENT_VIS_MIN_X:
2786 : case JSF_EVENT_VIS_MIN_Y:
2787 : case JSF_EVENT_VIS_MAX_X:
2788 : case JSF_EVENT_VIS_MAX_Y:
2789 : case JSF_EVENT_VIS_IS_GAZE:
2790 : return GF_TRUE;
2791 0 : default:
2792 0 : return GF_FALSE;
2793 : }
2794 : break;
2795 0 : case GF_FEVT_BUFFER_REQ:
2796 0 : switch (magic) {
2797 : case JSF_EVENT_BUFREQ_MAX_BUFFER_US:
2798 : case JSF_EVENT_BUFREQ_MAX_PLAYOUT_US:
2799 : case JSF_EVENT_BUFREQ_MIN_PLAYOUT_US:
2800 : case JSF_EVENT_BUFREQ_PID_ONLY:
2801 : return GF_TRUE;
2802 0 : default:
2803 0 : return GF_FALSE;
2804 : }
2805 : break;
2806 85 : case GF_FEVT_USER:
2807 85 : if (magic==JSF_EVENT_USER_TYPE)
2808 : return GF_TRUE;
2809 :
2810 1 : switch (ui_type) {
2811 0 : case GF_EVENT_CLICK:
2812 : case GF_EVENT_MOUSEUP:
2813 : case GF_EVENT_MOUSEDOWN:
2814 : case GF_EVENT_MOUSEOVER:
2815 : case GF_EVENT_MOUSEOUT:
2816 : case GF_EVENT_MOUSEMOVE:
2817 : case GF_EVENT_MOUSEWHEEL:
2818 0 : switch (magic) {
2819 : case JSF_EVENT_USER_MOUSE_X:
2820 : case JSF_EVENT_USER_MOUSE_Y:
2821 : case JSF_EVENT_USER_WHEEL:
2822 : case JSF_EVENT_USER_BUTTON:
2823 : return GF_TRUE;
2824 : default:
2825 : break;
2826 : }
2827 0 : return GF_FALSE;
2828 0 : case GF_EVENT_MULTITOUCH:
2829 : switch (magic) {
2830 : case JSF_EVENT_USER_MOUSE_X:
2831 : case JSF_EVENT_USER_MOUSE_Y:
2832 : case JSF_EVENT_USER_MT_ROTATION:
2833 : case JSF_EVENT_USER_MT_PINCH:
2834 : case JSF_EVENT_USER_MT_FINGERS:
2835 : return GF_TRUE;
2836 : default:
2837 : break;
2838 : }
2839 0 : return GF_FALSE;
2840 :
2841 0 : case GF_EVENT_KEYUP:
2842 : case GF_EVENT_KEYDOWN:
2843 : case GF_EVENT_LONGKEYPRESS:
2844 : case GF_EVENT_TEXTINPUT:
2845 : switch (magic) {
2846 : case JSF_EVENT_USER_KEYCODE:
2847 : case JSF_EVENT_USER_KEYNAME:
2848 : case JSF_EVENT_USER_KEYMODS:
2849 : case JSF_EVENT_USER_HWKEY:
2850 : case JSF_EVENT_USER_DROPFILES:
2851 : return GF_TRUE;
2852 : default:
2853 : break;
2854 : }
2855 0 : return GF_FALSE;
2856 0 : case GF_EVENT_DROPFILE:
2857 0 : switch (magic) {
2858 : case JSF_EVENT_USER_DROPFILES:
2859 : return GF_TRUE;
2860 : default:
2861 : break;
2862 : }
2863 0 : return GF_FALSE;
2864 0 : case GF_EVENT_PASTE_TEXT:
2865 : case GF_EVENT_COPY_TEXT:
2866 0 : switch (magic) {
2867 : case JSF_EVENT_USER_TEXT:
2868 : return GF_TRUE;
2869 : default:
2870 : break;
2871 : }
2872 0 : return GF_FALSE;
2873 0 : case GF_EVENT_SIZE:
2874 0 : switch (magic) {
2875 : case JSF_EVENT_USER_WIDTH:
2876 : case JSF_EVENT_USER_HEIGHT:
2877 : return GF_TRUE;
2878 : default:
2879 : break;
2880 : }
2881 0 : return GF_FALSE;
2882 0 : case GF_EVENT_MOVE:
2883 0 : switch (magic) {
2884 : case JSF_EVENT_USER_MOVE_X:
2885 : case JSF_EVENT_USER_MOVE_Y:
2886 : case JSF_EVENT_USER_MOVE_RELATIVE:
2887 : case JSF_EVENT_USER_MOVE_ALIGN_X:
2888 : case JSF_EVENT_USER_MOVE_ALIGN_Y:
2889 : return GF_TRUE;
2890 : default:
2891 : break;
2892 : }
2893 0 : return GF_FALSE;
2894 1 : case GF_EVENT_SET_CAPTION:
2895 1 : if (magic==JSF_EVENT_USER_CAPTION) return GF_TRUE;
2896 0 : return GF_FALSE;
2897 : }
2898 : }
2899 : return GF_FALSE;
2900 : }
2901 :
2902 :
2903 5 : static JSValue jsf_event_set_prop(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
2904 : {
2905 : GF_Err e = GF_OK;
2906 : u32 ival;
2907 : Double dval;
2908 : const char *str=NULL;
2909 5 : GF_FilterEvent *evt = JS_GetOpaque(this_val, jsf_event_class_id);
2910 5 : if (!evt) return JS_EXCEPTION;
2911 5 : if (!jsf_check_evt(evt->base.type, evt->user_event.event.type, magic))
2912 0 : return JS_EXCEPTION;
2913 :
2914 5 : switch (magic) {
2915 0 : case JSF_EVENT_TYPE:
2916 0 : return JS_EXCEPTION;
2917 : /*PLAY*/
2918 3 : case JSF_EVENT_START_RANGE:
2919 3 : return JS_ToFloat64(ctx, &evt->play.start_range, value) ? JS_EXCEPTION : JS_UNDEFINED;
2920 0 : case JSF_EVENT_SPEED:
2921 0 : return JS_ToFloat64(ctx, &evt->play.speed, value) ? JS_EXCEPTION : JS_UNDEFINED;
2922 0 : case JSF_EVENT_HW_BUFFER_RESET:
2923 0 : evt->play.hw_buffer_reset = JS_ToBool(ctx, value);
2924 0 : return JS_UNDEFINED;
2925 0 : case JSF_EVENT_INITIAL_BROADCAST_PLAY:
2926 0 : evt->play.initial_broadcast_play = JS_ToBool(ctx, value);
2927 0 : return JS_UNDEFINED;
2928 0 : case JSF_EVENT_TIMESTAMP_BASED:
2929 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
2930 0 : evt->play.timestamp_based = (u8) ival;
2931 0 : return JS_UNDEFINED;
2932 0 : case JSF_EVENT_FULL_FILE_ONLY:
2933 0 : evt->play.full_file_only = JS_ToBool(ctx, value);
2934 0 : return JS_UNDEFINED;
2935 0 : case JSF_EVENT_FORCE_DASH_SEG_SWITCH:
2936 0 : evt->play.forced_dash_segment_switch = JS_ToBool(ctx, value);
2937 0 : return JS_UNDEFINED;
2938 0 : case JSF_EVENT_FROM_PCK:
2939 0 : return JS_ToInt32(ctx, &evt->play.from_pck, value) ? JS_EXCEPTION : JS_UNDEFINED;
2940 : /*source switch*/
2941 0 : case JSF_EVENT_START_OFFSET:
2942 0 : return JS_ToInt64(ctx, &evt->seek.start_offset, value) ? JS_EXCEPTION : JS_UNDEFINED;
2943 0 : case JSF_EVENT_END_OFFSET:
2944 0 : return JS_ToInt64(ctx, &evt->seek.end_offset, value) ? JS_EXCEPTION : JS_UNDEFINED;
2945 0 : case JSF_EVENT_SOURCE_SWITCH:
2946 : /*TODO check leak!*/
2947 0 : evt->seek.source_switch = JS_ToCString(ctx, value);
2948 0 : return JS_UNDEFINED;
2949 0 : case JSF_EVENT_SKIP_CACHE_EXPIRATION:
2950 0 : evt->seek.skip_cache_expiration = JS_ToBool(ctx, value);
2951 0 : return JS_UNDEFINED;
2952 0 : case JSF_EVENT_HINT_BLOCK_SIZE:
2953 0 : return JS_ToInt32(ctx, &evt->seek.hint_block_size, value) ? JS_EXCEPTION : JS_UNDEFINED;
2954 : /*segment size*/
2955 0 : case JSF_EVENT_SEG_URL:
2956 : /*TODO check leak!*/
2957 0 : evt->seg_size.seg_url = JS_ToCString(ctx, value);
2958 0 : return JS_UNDEFINED;
2959 0 : case JSF_EVENT_SEG_IS_INIT:
2960 0 : evt->seg_size.is_init = JS_ToBool(ctx, value);
2961 0 : return JS_UNDEFINED;
2962 0 : case JSF_EVENT_MEDIA_START_RANGE:
2963 0 : return JS_ToInt64(ctx, &evt->seg_size.media_range_start, value) ? JS_EXCEPTION : JS_UNDEFINED;
2964 0 : case JSF_EVENT_MEDIA_END_RANGE:
2965 0 : return JS_ToInt64(ctx, &evt->seg_size.media_range_end, value) ? JS_EXCEPTION : JS_UNDEFINED;
2966 0 : case JSF_EVENT_IDX_START_RANGE:
2967 0 : return JS_ToInt64(ctx, &evt->seg_size.idx_range_start, value) ? JS_EXCEPTION : JS_UNDEFINED;
2968 0 : case JSF_EVENT_IDX_END_RANGE:
2969 0 : return JS_ToInt64(ctx, &evt->seg_size.idx_range_end, value) ? JS_EXCEPTION : JS_UNDEFINED;
2970 : /*quality switch*/
2971 0 : case JSF_EVENT_SWITCH_UP:
2972 0 : evt->quality_switch.up = JS_ToBool(ctx, value);
2973 0 : return JS_UNDEFINED;
2974 0 : case JSF_EVENT_SWITCH_GROUP_IDX:
2975 0 : return JS_ToInt32(ctx, &evt->quality_switch.dependent_group_index, value) ? JS_EXCEPTION : JS_UNDEFINED;
2976 0 : case JSF_EVENT_SWITCH_QUALITY_IDX:
2977 0 : return JS_ToInt32(ctx, &evt->quality_switch.q_idx, value) ? JS_EXCEPTION : JS_UNDEFINED;
2978 0 : case JSF_EVENT_SWITCH_TILE_MODE:
2979 0 : return JS_ToInt32(ctx, &evt->quality_switch.set_tile_mode_plus_one, value) ? JS_EXCEPTION : JS_UNDEFINED;
2980 0 : case JSF_EVENT_SWITCH_QUALITY_DEGRADATION:
2981 0 : return JS_ToInt32(ctx, &evt->quality_switch.quality_degradation, value) ? JS_EXCEPTION : JS_UNDEFINED;
2982 : /*visibility hint*/
2983 0 : case JSF_EVENT_VIS_MIN_X: return JS_ToInt32(ctx, &evt->visibility_hint.min_x, value) ? JS_EXCEPTION : JS_UNDEFINED;
2984 0 : case JSF_EVENT_VIS_MIN_Y: return JS_ToInt32(ctx, &evt->visibility_hint.min_y, value) ? JS_EXCEPTION : JS_UNDEFINED;
2985 0 : case JSF_EVENT_VIS_MAX_X: return JS_ToInt32(ctx, &evt->visibility_hint.max_x, value) ? JS_EXCEPTION : JS_UNDEFINED;
2986 0 : case JSF_EVENT_VIS_MAX_Y: return JS_ToInt32(ctx, &evt->visibility_hint.max_y, value) ? JS_EXCEPTION : JS_UNDEFINED;
2987 0 : case JSF_EVENT_VIS_IS_GAZE:
2988 0 : evt->visibility_hint.is_gaze = JS_ToBool(ctx, value);
2989 0 : return JS_UNDEFINED;
2990 : /*buffer reqs*/
2991 0 : case JSF_EVENT_BUFREQ_MAX_BUFFER_US: return JS_ToInt32(ctx, &evt->buffer_req.max_buffer_us, value) ? JS_EXCEPTION : JS_UNDEFINED;
2992 0 : case JSF_EVENT_BUFREQ_MAX_PLAYOUT_US: return JS_ToInt32(ctx, &evt->buffer_req.max_playout_us, value) ? JS_EXCEPTION : JS_UNDEFINED;
2993 0 : case JSF_EVENT_BUFREQ_MIN_PLAYOUT_US: return JS_ToInt32(ctx, &evt->buffer_req.min_playout_us, value) ? JS_EXCEPTION : JS_UNDEFINED;
2994 0 : case JSF_EVENT_BUFREQ_PID_ONLY:
2995 0 : evt->buffer_req.pid_only = JS_ToBool(ctx, value);
2996 0 : return JS_UNDEFINED;
2997 :
2998 1 : case JSF_EVENT_USER_TYPE:
2999 1 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3000 1 : evt->user_event.event.type = (u8) ival;
3001 1 : return JS_UNDEFINED;
3002 :
3003 :
3004 0 : case JSF_EVENT_USER_MOUSE_X:
3005 0 : if (evt->user_event.event.type==GF_EVENT_MULTITOUCH) {
3006 0 : if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION;
3007 0 : evt->user_event.event.mtouch.x = FLT2FIX(dval);
3008 0 : return JS_UNDEFINED;
3009 : }
3010 0 : return JS_ToInt32(ctx, &evt->user_event.event.mouse.x, value) ? JS_EXCEPTION : JS_UNDEFINED;
3011 0 : case JSF_EVENT_USER_MOUSE_Y:
3012 0 : if (evt->user_event.event.type==GF_EVENT_MULTITOUCH) {
3013 0 : if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION;
3014 0 : evt->user_event.event.mtouch.y = FLT2FIX(dval);
3015 0 : return JS_UNDEFINED;
3016 : }
3017 0 : return JS_ToInt32(ctx, &evt->user_event.event.mouse.y, value) ? JS_EXCEPTION : JS_UNDEFINED;
3018 :
3019 0 : case JSF_EVENT_USER_WHEEL:
3020 0 : if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION;
3021 0 : evt->user_event.event.mouse.wheel_pos = FLT2FIX(dval);
3022 0 : return JS_UNDEFINED;
3023 0 : case JSF_EVENT_USER_BUTTON: return JS_ToInt32(ctx, &evt->user_event.event.mouse.button, value) ? JS_EXCEPTION : JS_UNDEFINED;
3024 0 : case JSF_EVENT_USER_HWKEY: return JS_ToInt32(ctx, &evt->user_event.event.key.hw_code, value) ? JS_EXCEPTION : JS_UNDEFINED;
3025 0 : case JSF_EVENT_USER_KEYCODE: return JS_ToInt32(ctx, &evt->user_event.event.key.key_code, value) ? JS_EXCEPTION : JS_UNDEFINED;
3026 0 : case JSF_EVENT_USER_KEYMODS: return JS_ToInt32(ctx, &evt->user_event.event.key.flags, value) ? JS_EXCEPTION : JS_UNDEFINED;
3027 :
3028 0 : case JSF_EVENT_USER_MT_ROTATION:
3029 0 : if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION;
3030 0 : evt->user_event.event.mtouch.rotation = FLT2FIX(dval);
3031 0 : return JS_UNDEFINED;
3032 0 : case JSF_EVENT_USER_MT_PINCH:
3033 0 : if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION;
3034 0 : evt->user_event.event.mtouch.pinch = FLT2FIX(dval);
3035 0 : return JS_UNDEFINED;
3036 0 : case JSF_EVENT_USER_MT_FINGERS:
3037 0 : return JS_ToInt32(ctx, &evt->user_event.event.mtouch.num_fingers, value) ? JS_EXCEPTION : JS_UNDEFINED;
3038 :
3039 0 : case JSF_EVENT_USER_TEXT:
3040 : {
3041 : str = JS_ToCString(ctx, value);
3042 0 : evt->user_event.event.clipboard.text = gf_strdup(str ? str : "");
3043 0 : if (str) JS_FreeCString(ctx, str);
3044 0 : return JS_UNDEFINED;
3045 : }
3046 :
3047 0 : case JSF_EVENT_USER_WIDTH: return JS_ToInt32(ctx, &evt->user_event.event.size.width, value) ? JS_EXCEPTION : JS_UNDEFINED;
3048 0 : case JSF_EVENT_USER_HEIGHT: return JS_ToInt32(ctx, &evt->user_event.event.size.height, value) ? JS_EXCEPTION : JS_UNDEFINED;
3049 0 : case JSF_EVENT_USER_SHOWTYPE: return JS_ToInt32(ctx, &evt->user_event.event.show.show_type, value) ? JS_EXCEPTION : JS_UNDEFINED;
3050 0 : case JSF_EVENT_USER_MOVE_X: return JS_ToInt32(ctx, &evt->user_event.event.move.x, value) ? JS_EXCEPTION : JS_UNDEFINED;
3051 0 : case JSF_EVENT_USER_MOVE_Y: return JS_ToInt32(ctx, &evt->user_event.event.move.y, value) ? JS_EXCEPTION : JS_UNDEFINED;
3052 0 : case JSF_EVENT_USER_MOVE_RELATIVE: return JS_ToInt32(ctx, &evt->user_event.event.move.relative, value) ? JS_EXCEPTION : JS_UNDEFINED;
3053 0 : case JSF_EVENT_USER_MOVE_ALIGN_X:
3054 : case JSF_EVENT_USER_MOVE_ALIGN_Y:
3055 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3056 0 : if (magic==JSF_EVENT_USER_MOVE_ALIGN_X)
3057 0 : evt->user_event.event.move.align_x = ival;
3058 : else
3059 0 : evt->user_event.event.move.align_x = ival;
3060 0 : return JS_UNDEFINED;
3061 :
3062 1 : case JSF_EVENT_USER_CAPTION:
3063 : {
3064 : str = JS_ToCString(ctx, value);
3065 1 : evt->user_event.event.caption.caption = gf_strdup(str ? str : "");
3066 1 : if (str) JS_FreeCString(ctx, str);
3067 1 : return JS_UNDEFINED;
3068 : }
3069 : }
3070 :
3071 : if (str)
3072 : JS_FreeCString(ctx, str);
3073 : if (e) return js_throw_err(ctx, e);
3074 0 : return JS_UNDEFINED;
3075 : }
3076 :
3077 500 : static JSValue jsf_event_get_prop(JSContext *ctx, JSValueConst this_val, int magic)
3078 : {
3079 500 : GF_FilterEvent *evt = JS_GetOpaque(this_val, jsf_event_class_id);
3080 500 : if (!evt) return JS_EXCEPTION;
3081 500 : if (!jsf_check_evt(evt->base.type, evt->user_event.event.type, magic))
3082 0 : return JS_EXCEPTION;
3083 500 : switch (magic) {
3084 412 : case JSF_EVENT_TYPE: return JS_NewInt32(ctx, evt->base.type);
3085 2 : case JSF_EVENT_NAME:
3086 2 : if (evt->base.type==GF_FEVT_USER) {
3087 : const char *ename=NULL;
3088 2 : switch (evt->user_event.event.type) {
3089 : case GF_EVENT_CLICK: ename = "click"; break;
3090 0 : case GF_EVENT_MOUSEUP: ename = "mouseup"; break;
3091 0 : case GF_EVENT_MOUSEDOWN: ename = "mousedown"; break;
3092 0 : case GF_EVENT_MOUSEMOVE: ename = "mousemove"; break;
3093 0 : case GF_EVENT_MOUSEWHEEL: ename = "mousewheel"; break;
3094 0 : case GF_EVENT_DBLCLICK: ename = "dblclick"; break;
3095 0 : case GF_EVENT_MULTITOUCH: ename = "touch"; break;
3096 0 : case GF_EVENT_KEYUP: ename = "keyup"; break;
3097 0 : case GF_EVENT_KEYDOWN: ename = "keydown"; break;
3098 0 : case GF_EVENT_TEXTINPUT: ename = "text"; break;
3099 0 : case GF_EVENT_DROPFILE: ename = "dropfile"; break;
3100 0 : case GF_EVENT_TIMESHIFT_DEPTH: ename = "timeshift_depth"; break;
3101 0 : case GF_EVENT_TIMESHIFT_UPDATE: ename = "timeshift_update"; break;
3102 0 : case GF_EVENT_TIMESHIFT_OVERFLOW: ename = "timeshift_overflow"; break;
3103 0 : case GF_EVENT_TIMESHIFT_UNDERRUN: ename = "timeshift_underrun"; break;
3104 0 : case GF_EVENT_PASTE_TEXT: ename = "paste_text"; break;
3105 0 : case GF_EVENT_COPY_TEXT: ename = "copy_text"; break;
3106 0 : case GF_EVENT_SIZE: ename = "size"; break;
3107 0 : case GF_EVENT_SHOWHIDE: ename = "showhide"; break;
3108 0 : case GF_EVENT_MOVE: ename = "move"; break;
3109 0 : case GF_EVENT_SET_CAPTION: ename = "caption"; break;
3110 0 : case GF_EVENT_REFRESH: ename = "refresh"; break;
3111 0 : case GF_EVENT_QUIT: ename = "quit"; break;
3112 0 : case GF_EVENT_VIDEO_SETUP: ename = "video_setup"; break;
3113 2 : default:
3114 2 : ename = "unknown"; break;
3115 : }
3116 2 : return JS_NewString(ctx, ename);
3117 : }
3118 0 : return JS_NewString(ctx, gf_filter_event_name(evt->base.type));
3119 : /*PLAY*/
3120 3 : case JSF_EVENT_START_RANGE: return JS_NewFloat64(ctx, evt->play.start_range);
3121 0 : case JSF_EVENT_SPEED: return JS_NewFloat64(ctx, evt->play.speed);
3122 0 : case JSF_EVENT_HW_BUFFER_RESET: return JS_NewBool(ctx, evt->play.hw_buffer_reset);
3123 0 : case JSF_EVENT_INITIAL_BROADCAST_PLAY: return JS_NewBool(ctx, evt->play.initial_broadcast_play);
3124 0 : case JSF_EVENT_TIMESTAMP_BASED: return JS_NewInt32(ctx, evt->play.timestamp_based);
3125 0 : case JSF_EVENT_FULL_FILE_ONLY: return JS_NewBool(ctx, evt->play.full_file_only);
3126 0 : case JSF_EVENT_FORCE_DASH_SEG_SWITCH: return JS_NewBool(ctx, evt->play.forced_dash_segment_switch);
3127 0 : case JSF_EVENT_FROM_PCK: return JS_NewInt32(ctx, evt->play.from_pck);
3128 : /*source switch*/
3129 0 : case JSF_EVENT_START_OFFSET: return JS_NewInt64(ctx, evt->seek.start_offset);
3130 0 : case JSF_EVENT_END_OFFSET: return JS_NewInt64(ctx, evt->seek.end_offset);
3131 0 : case JSF_EVENT_SOURCE_SWITCH: return JS_NewString(ctx, evt->seek.source_switch);
3132 0 : case JSF_EVENT_SKIP_CACHE_EXPIRATION: return JS_NewBool(ctx, evt->seek.skip_cache_expiration);
3133 0 : case JSF_EVENT_HINT_BLOCK_SIZE: return JS_NewInt32(ctx, evt->seek.hint_block_size);
3134 : /*segment size*/
3135 0 : case JSF_EVENT_SEG_URL: return JS_NewString(ctx, evt->seg_size.seg_url);
3136 0 : case JSF_EVENT_SEG_IS_INIT: return JS_NewBool(ctx, evt->seg_size.is_init);
3137 0 : case JSF_EVENT_MEDIA_START_RANGE: return JS_NewInt64(ctx, evt->seg_size.media_range_start);
3138 0 : case JSF_EVENT_MEDIA_END_RANGE: return JS_NewInt64(ctx, evt->seg_size.media_range_end);
3139 0 : case JSF_EVENT_IDX_START_RANGE: return JS_NewInt64(ctx, evt->seg_size.media_range_start);
3140 0 : case JSF_EVENT_IDX_END_RANGE: return JS_NewInt64(ctx, evt->seg_size.idx_range_end);
3141 : /*quality switch*/
3142 0 : case JSF_EVENT_SWITCH_UP: return JS_NewBool(ctx, evt->quality_switch.up);
3143 0 : case JSF_EVENT_SWITCH_GROUP_IDX: return JS_NewInt32(ctx, evt->quality_switch.dependent_group_index);
3144 0 : case JSF_EVENT_SWITCH_QUALITY_IDX: return JS_NewInt32(ctx, evt->quality_switch.q_idx);
3145 0 : case JSF_EVENT_SWITCH_TILE_MODE: return JS_NewInt32(ctx, evt->quality_switch.set_tile_mode_plus_one);
3146 0 : case JSF_EVENT_SWITCH_QUALITY_DEGRADATION: return JS_NewInt32(ctx, evt->quality_switch.quality_degradation);
3147 : /*visibility hint*/
3148 0 : case JSF_EVENT_VIS_MIN_X: return JS_NewInt32(ctx, evt->visibility_hint.min_x);
3149 0 : case JSF_EVENT_VIS_MIN_Y: return JS_NewInt32(ctx, evt->visibility_hint.min_y);
3150 0 : case JSF_EVENT_VIS_MAX_X: return JS_NewInt32(ctx, evt->visibility_hint.max_x);
3151 0 : case JSF_EVENT_VIS_MAX_Y: return JS_NewInt32(ctx, evt->visibility_hint.max_y);
3152 0 : case JSF_EVENT_VIS_IS_GAZE: return JS_NewBool(ctx, evt->visibility_hint.is_gaze);
3153 : /*buffer reqs*/
3154 0 : case JSF_EVENT_BUFREQ_MAX_BUFFER_US: return JS_NewInt32(ctx, evt->buffer_req.max_buffer_us);
3155 0 : case JSF_EVENT_BUFREQ_MAX_PLAYOUT_US: return JS_NewInt32(ctx, evt->buffer_req.max_playout_us);
3156 0 : case JSF_EVENT_BUFREQ_MIN_PLAYOUT_US: return JS_NewInt32(ctx, evt->buffer_req.min_playout_us);
3157 0 : case JSF_EVENT_BUFREQ_PID_ONLY: return JS_NewBool(ctx, evt->buffer_req.pid_only);
3158 : /*user event*/
3159 83 : case JSF_EVENT_USER_TYPE: return JS_NewInt32(ctx, evt->user_event.event.type);
3160 0 : case JSF_EVENT_USER_KEYCODE: return JS_NewInt32(ctx, evt->user_event.event.key.key_code);
3161 0 : case JSF_EVENT_USER_KEYMODS:
3162 0 : return JS_NewInt32(ctx, evt->user_event.event.key.flags);
3163 0 : case JSF_EVENT_USER_KEYNAME:
3164 : #ifndef GPAC_DISABLE_SVG
3165 0 : return JS_NewString(ctx, gf_dom_get_key_name(evt->user_event.event.key.key_code) );
3166 : #else
3167 : return JS_NULL;
3168 : #endif
3169 :
3170 0 : case JSF_EVENT_USER_MOUSE_X:
3171 0 : if (evt->user_event.event.type==GF_EVENT_MULTITOUCH)
3172 0 : return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.x) );
3173 0 : return JS_NewInt32(ctx, evt->user_event.event.mouse.x);
3174 0 : case JSF_EVENT_USER_MOUSE_Y:
3175 0 : if (evt->user_event.event.type==GF_EVENT_MULTITOUCH)
3176 0 : return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.y) );
3177 0 : return JS_NewInt32(ctx, evt->user_event.event.mouse.y);
3178 0 : case JSF_EVENT_USER_WHEEL: return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mouse.wheel_pos));
3179 0 : case JSF_EVENT_USER_BUTTON: return JS_NewInt32(ctx, evt->user_event.event.mouse.button);
3180 0 : case JSF_EVENT_USER_HWKEY: return JS_NewInt32(ctx, evt->user_event.event.key.hw_code);
3181 0 : case JSF_EVENT_USER_DROPFILES:
3182 : {
3183 : u32 i, idx;
3184 0 : JSValue files_array = JS_NewArray(ctx);
3185 : idx=0;
3186 0 : for (i=0; i<evt->user_event.event.open_file.nb_files; i++) {
3187 0 : if (evt->user_event.event.open_file.files[i]) {
3188 0 : JS_SetPropertyUint32(ctx, files_array, idx, JS_NewString(ctx, evt->user_event.event.open_file.files[i]) );
3189 0 : idx++;
3190 : }
3191 : }
3192 0 : return files_array;
3193 : }
3194 0 : case JSF_EVENT_USER_TEXT:
3195 0 : return JS_NewString(ctx, evt->user_event.event.clipboard.text ? evt->user_event.event.clipboard.text : "");
3196 :
3197 0 : case JSF_EVENT_USER_MT_ROTATION:
3198 0 : return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.rotation) );
3199 0 : case JSF_EVENT_USER_MT_PINCH:
3200 0 : return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.pinch) );
3201 0 : case JSF_EVENT_USER_MT_FINGERS:
3202 0 : return JS_NewInt32(ctx, evt->user_event.event.mtouch.num_fingers);
3203 0 : case JSF_EVENT_USER_WIDTH: return JS_NewInt32(ctx, evt->user_event.event.size.width);
3204 0 : case JSF_EVENT_USER_HEIGHT: return JS_NewInt32(ctx, evt->user_event.event.size.height);
3205 0 : case JSF_EVENT_USER_SHOWTYPE: return JS_NewInt32(ctx, evt->user_event.event.show.show_type);
3206 :
3207 0 : case JSF_EVENT_USER_MOVE_X: return JS_NewInt32(ctx, evt->user_event.event.move.x);
3208 0 : case JSF_EVENT_USER_MOVE_Y: return JS_NewInt32(ctx, evt->user_event.event.move.y);
3209 0 : case JSF_EVENT_USER_MOVE_RELATIVE: return JS_NewInt32(ctx, evt->user_event.event.move.relative);
3210 0 : case JSF_EVENT_USER_MOVE_ALIGN_X: return JS_NewInt32(ctx, evt->user_event.event.move.align_x);
3211 0 : case JSF_EVENT_USER_MOVE_ALIGN_Y: return JS_NewInt32(ctx, evt->user_event.event.move.align_y);
3212 :
3213 0 : case JSF_EVENT_USER_CAPTION:
3214 0 : return JS_NewString(ctx, evt->user_event.event.caption.caption ? evt->user_event.event.caption.caption : "");
3215 : }
3216 0 : return JS_UNDEFINED;
3217 : }
3218 :
3219 1 : GF_FilterEvent *jsf_get_event(JSContext *ctx, JSValueConst this_val)
3220 : {
3221 1 : GF_FilterEvent *evt = JS_GetOpaque(this_val, jsf_event_class_id);
3222 1 : return evt;
3223 : }
3224 :
3225 : static const JSCFunctionListEntry jsf_event_funcs[] =
3226 : {
3227 : JS_CGETSET_MAGIC_DEF("type", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_TYPE),
3228 : JS_CGETSET_MAGIC_DEF("name", jsf_event_get_prop, NULL, JSF_EVENT_NAME),
3229 : /*PLAY event*/
3230 : JS_CGETSET_MAGIC_DEF("start_range", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_START_RANGE),
3231 : JS_CGETSET_MAGIC_DEF("speed", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SPEED),
3232 : JS_CGETSET_MAGIC_DEF("hw_buffer_reset", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_HW_BUFFER_RESET),
3233 : JS_CGETSET_MAGIC_DEF("initial_broadcast_play", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_INITIAL_BROADCAST_PLAY),
3234 : JS_CGETSET_MAGIC_DEF("timestamp_based", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_TIMESTAMP_BASED),
3235 : JS_CGETSET_MAGIC_DEF("full_file_only", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_FULL_FILE_ONLY),
3236 : JS_CGETSET_MAGIC_DEF("forced_dash_segment_switch", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_FORCE_DASH_SEG_SWITCH),
3237 : JS_CGETSET_MAGIC_DEF("from_pck", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_FROM_PCK),
3238 : /*source switch*/
3239 : JS_CGETSET_MAGIC_DEF("start_offset", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_START_OFFSET),
3240 : JS_CGETSET_MAGIC_DEF("end_offset", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_END_OFFSET),
3241 : JS_CGETSET_MAGIC_DEF("switch_url", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SOURCE_SWITCH),
3242 : JS_CGETSET_MAGIC_DEF("skip_cache_exp", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SKIP_CACHE_EXPIRATION),
3243 : JS_CGETSET_MAGIC_DEF("hint_block_size", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_HINT_BLOCK_SIZE),
3244 : /*segment size*/
3245 : JS_CGETSET_MAGIC_DEF("seg_url", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SEG_URL),
3246 : JS_CGETSET_MAGIC_DEF("is_init", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SEG_IS_INIT),
3247 : JS_CGETSET_MAGIC_DEF("media_start_range", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_MEDIA_START_RANGE),
3248 : JS_CGETSET_MAGIC_DEF("media_end_range", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_MEDIA_END_RANGE),
3249 : JS_CGETSET_MAGIC_DEF("index_start_range", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_IDX_START_RANGE),
3250 : JS_CGETSET_MAGIC_DEF("index_end_range", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_IDX_END_RANGE),
3251 : /*quality switch*/
3252 : JS_CGETSET_MAGIC_DEF("up", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SWITCH_UP),
3253 : JS_CGETSET_MAGIC_DEF("dependent_group_index", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SWITCH_GROUP_IDX),
3254 : JS_CGETSET_MAGIC_DEF("q_idx", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SWITCH_QUALITY_IDX),
3255 : JS_CGETSET_MAGIC_DEF("set_tile_mode_plus_one", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SWITCH_TILE_MODE),
3256 : JS_CGETSET_MAGIC_DEF("quality_degradation", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SWITCH_QUALITY_DEGRADATION),
3257 : /*visibility hint*/
3258 : JS_CGETSET_MAGIC_DEF("min_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_VIS_MIN_X),
3259 : JS_CGETSET_MAGIC_DEF("min_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_VIS_MIN_Y),
3260 : JS_CGETSET_MAGIC_DEF("max_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_VIS_MAX_X),
3261 : JS_CGETSET_MAGIC_DEF("max_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_VIS_MAX_Y),
3262 : JS_CGETSET_MAGIC_DEF("is_gaze", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_VIS_IS_GAZE),
3263 : /*buffer reqs*/
3264 : JS_CGETSET_MAGIC_DEF("max_buffer_us", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_BUFREQ_MAX_BUFFER_US),
3265 : JS_CGETSET_MAGIC_DEF("max_playout_us", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_BUFREQ_MAX_PLAYOUT_US),
3266 : JS_CGETSET_MAGIC_DEF("min_playout_us", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_BUFREQ_MIN_PLAYOUT_US),
3267 : JS_CGETSET_MAGIC_DEF("pid_only", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_BUFREQ_PID_ONLY),
3268 : /*ui events*/
3269 : JS_CGETSET_MAGIC_DEF("ui_type", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_TYPE),
3270 : JS_CGETSET_MAGIC_DEF("keycode", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_KEYCODE),
3271 : JS_CGETSET_MAGIC_DEF("keyname", jsf_event_get_prop, NULL, JSF_EVENT_USER_KEYNAME),
3272 : JS_CGETSET_MAGIC_DEF("keymods", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_KEYMODS),
3273 : JS_CGETSET_MAGIC_DEF("mouse_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_X),
3274 : JS_CGETSET_MAGIC_DEF("mouse_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_Y),
3275 : JS_CGETSET_MAGIC_DEF("wheel", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_WHEEL),
3276 : JS_CGETSET_MAGIC_DEF("button", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_BUTTON),
3277 : JS_CGETSET_MAGIC_DEF("hwkey", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_HWKEY),
3278 : JS_CGETSET_MAGIC_DEF("dropfiles", jsf_event_get_prop, NULL, JSF_EVENT_USER_DROPFILES),
3279 : JS_CGETSET_MAGIC_DEF("clipboard", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_TEXT),
3280 :
3281 : JS_CGETSET_MAGIC_DEF("mt_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_X),
3282 : JS_CGETSET_MAGIC_DEF("mt_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_Y),
3283 : JS_CGETSET_MAGIC_DEF("mt_rotate", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MT_ROTATION),
3284 : JS_CGETSET_MAGIC_DEF("mt_pinch", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MT_PINCH),
3285 : JS_CGETSET_MAGIC_DEF("mt_fingers", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MT_FINGERS),
3286 :
3287 : JS_CGETSET_MAGIC_DEF("width", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_WIDTH),
3288 : JS_CGETSET_MAGIC_DEF("height", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_HEIGHT),
3289 : JS_CGETSET_MAGIC_DEF("showtype", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_SHOWTYPE),
3290 : JS_CGETSET_MAGIC_DEF("move_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_X),
3291 : JS_CGETSET_MAGIC_DEF("move_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_Y),
3292 : JS_CGETSET_MAGIC_DEF("move_relative", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_RELATIVE),
3293 : JS_CGETSET_MAGIC_DEF("move_alignx", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_ALIGN_X),
3294 : JS_CGETSET_MAGIC_DEF("move_aligny", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_ALIGN_Y),
3295 : JS_CGETSET_MAGIC_DEF("caption", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_CAPTION),
3296 : };
3297 :
3298 7 : static JSValue jsf_event_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
3299 : {
3300 : GF_FilterEvent *evt;
3301 : JSValue obj;
3302 : s32 type;
3303 7 : if (argc!=1)
3304 0 : return JS_EXCEPTION;
3305 7 : if (JS_ToInt32(ctx, &type, argv[0]))
3306 0 : return JS_EXCEPTION;
3307 7 : if (!type)
3308 0 : return JS_EXCEPTION;
3309 7 : obj = JS_NewObjectClass(ctx, jsf_event_class_id);
3310 7 : if (JS_IsException(obj)) return obj;
3311 :
3312 7 : GF_SAFEALLOC(evt, GF_FilterEvent);
3313 7 : if (!evt) {
3314 : JS_FreeValue(ctx, obj);
3315 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
3316 : }
3317 7 : evt->base.type = type;
3318 7 : if (type==GF_FEVT_PLAY)
3319 5 : evt->play.speed = 1.0;
3320 7 : JS_SetOpaque(obj, evt);
3321 7 : return obj;
3322 : }
3323 :
3324 : enum
3325 : {
3326 : JSF_PCK_START = 0,
3327 : JSF_PCK_END,
3328 : JSF_PCK_DTS,
3329 : JSF_PCK_CTS,
3330 : JSF_PCK_DUR,
3331 : JSF_PCK_SAP,
3332 : JSF_PCK_TIMESCALE,
3333 : JSF_PCK_INTERLACED,
3334 : JSF_PCK_SEEK,
3335 : JSF_PCK_CORRUPTED,
3336 : JSF_PCK_BYTE_OFFSET,
3337 : JSF_PCK_ROLL,
3338 : JSF_PCK_CRYPT,
3339 : JSF_PCK_CLOCK_TYPE,
3340 : JSF_PCK_CAROUSEL,
3341 : JSF_PCK_SEQNUM,
3342 : JSF_PCK_BLOCKING_REF,
3343 : JSF_PCK_DEPENDS_ON,
3344 : JSF_PCK_DEPENDED_ON,
3345 : JSF_PCK_IS_LEADING,
3346 : JSF_PCK_HAS_REDUNDANT,
3347 : JSF_PCK_SIZE,
3348 : JSF_PCK_DATA,
3349 : JSF_PCK_FRAME_IFCE,
3350 : };
3351 :
3352 1426 : static JSValue jsf_pck_set_prop(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic)
3353 : {
3354 : GF_Err e = GF_OK;
3355 : u32 ival, flags;
3356 : u64 lival;
3357 : Bool a1, a2;
3358 : const char *str=NULL;
3359 : GF_FilterPacket *pck;
3360 1426 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3361 1426 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3362 : pck = pckctx->pck;
3363 :
3364 1426 : switch (magic) {
3365 0 : case JSF_PCK_START:
3366 0 : gf_filter_pck_get_framing(pck, &a1, &a2);
3367 0 : gf_filter_pck_set_framing(pck, JS_ToBool(ctx, value), a2);
3368 0 : break;
3369 0 : case JSF_PCK_END:
3370 0 : gf_filter_pck_get_framing(pck, &a1, &a2);
3371 0 : gf_filter_pck_set_framing(pck, a1, JS_ToBool(ctx, value));
3372 0 : break;
3373 200 : case JSF_PCK_DTS:
3374 200 : if (JS_IsNull(value))
3375 0 : gf_filter_pck_set_dts(pck, GF_FILTER_NO_TS);
3376 : else {
3377 200 : if (JS_ToInt64(ctx, &lival, value)) return JS_EXCEPTION;
3378 200 : gf_filter_pck_set_dts(pck, lival);
3379 : }
3380 : break;
3381 601 : case JSF_PCK_CTS:
3382 601 : if (JS_IsNull(value))
3383 0 : gf_filter_pck_set_cts(pck, GF_FILTER_NO_TS);
3384 : else {
3385 601 : if (JS_ToInt64(ctx, &lival, value)) return JS_EXCEPTION;
3386 601 : gf_filter_pck_set_cts(pck, lival);
3387 : }
3388 : break;
3389 200 : case JSF_PCK_DUR:
3390 200 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3391 200 : gf_filter_pck_set_duration(pck, ival);
3392 200 : break;
3393 425 : case JSF_PCK_SAP:
3394 425 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3395 425 : gf_filter_pck_set_sap(pck, ival);
3396 425 : break;
3397 0 : case JSF_PCK_INTERLACED:
3398 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3399 0 : gf_filter_pck_set_interlaced(pck, ival);
3400 0 : break;
3401 0 : case JSF_PCK_SEEK:
3402 0 : gf_filter_pck_set_seek_flag(pck, JS_ToBool(ctx, value));
3403 0 : break;
3404 0 : case JSF_PCK_CORRUPTED:
3405 0 : gf_filter_pck_set_corrupted(pck, JS_ToBool(ctx, value));
3406 0 : break;
3407 0 : case JSF_PCK_BYTE_OFFSET:
3408 0 : if (JS_IsNull(value))
3409 0 : gf_filter_pck_set_byte_offset(pck, GF_FILTER_NO_BO);
3410 : else {
3411 0 : if (JS_ToInt64(ctx, &lival, value)) return JS_EXCEPTION;
3412 0 : gf_filter_pck_set_byte_offset(pck, lival);
3413 : }
3414 : break;
3415 0 : case JSF_PCK_ROLL:
3416 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3417 0 : gf_filter_pck_set_roll_info(pck, (s16) ival);
3418 0 : break;
3419 0 : case JSF_PCK_CRYPT:
3420 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3421 0 : gf_filter_pck_set_crypt_flags(pck, ival);
3422 0 : break;
3423 0 : case JSF_PCK_CLOCK_TYPE:
3424 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3425 0 : gf_filter_pck_set_clock_type(pck, ival);
3426 0 : break;
3427 0 : case JSF_PCK_CAROUSEL:
3428 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3429 0 : gf_filter_pck_set_carousel_version(pck, ival);
3430 0 : break;
3431 0 : case JSF_PCK_SEQNUM:
3432 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3433 0 : gf_filter_pck_set_seq_num(pck, ival);
3434 0 : break;
3435 0 : case JSF_PCK_IS_LEADING:
3436 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3437 0 : flags = gf_filter_pck_get_dependency_flags(pck);
3438 0 : flags &= 0x3F;
3439 0 : flags |= (ival & 0x3)<<6;
3440 0 : gf_filter_pck_set_seq_num(pck, flags);
3441 0 : break;
3442 0 : case JSF_PCK_DEPENDS_ON:
3443 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3444 0 : flags = gf_filter_pck_get_dependency_flags(pck);
3445 0 : flags &= 0xCF;
3446 0 : flags |= (ival & 0x3)<<4;
3447 0 : gf_filter_pck_set_seq_num(pck, flags);
3448 0 : break;
3449 0 : case JSF_PCK_DEPENDED_ON:
3450 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3451 0 : flags = gf_filter_pck_get_dependency_flags(pck);
3452 0 : flags &= 0xF3;
3453 0 : flags |= (ival & 0x3)<<2;
3454 0 : gf_filter_pck_set_seq_num(pck, flags);
3455 0 : break;
3456 0 : case JSF_PCK_HAS_REDUNDANT:
3457 0 : if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION;
3458 0 : flags = gf_filter_pck_get_dependency_flags(pck);
3459 0 : flags &= 0xFC;
3460 0 : flags |= (ival & 0x3);
3461 0 : gf_filter_pck_set_seq_num(pck, flags);
3462 0 : break;
3463 : }
3464 : if (str)
3465 : JS_FreeCString(ctx, str);
3466 : if (e) return js_throw_err(ctx, e);
3467 1426 : return JS_UNDEFINED;
3468 : }
3469 :
3470 3073 : static JSValue jsf_pck_get_prop(JSContext *ctx, JSValueConst this_val, int magic)
3471 : {
3472 : Bool a1, a2;
3473 : u64 lival;
3474 : u32 ival;
3475 : GF_FilterPacket *pck;
3476 3073 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3477 3073 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3478 : pck = pckctx->pck;
3479 :
3480 3073 : switch (magic) {
3481 0 : case JSF_PCK_START:
3482 0 : gf_filter_pck_get_framing(pck, &a1, &a2);
3483 0 : return JS_NewBool(ctx, a1);
3484 0 : case JSF_PCK_END:
3485 0 : gf_filter_pck_get_framing(pck, &a1, &a2);
3486 0 : return JS_NewBool(ctx, a2);
3487 522 : case JSF_PCK_DTS:
3488 522 : lival = gf_filter_pck_get_dts(pck);
3489 522 : if (lival==GF_FILTER_NO_TS) return JS_NULL;
3490 519 : return JS_NewInt64(ctx, lival);
3491 637 : case JSF_PCK_CTS:
3492 637 : lival = gf_filter_pck_get_cts(pck);
3493 637 : if (lival==GF_FILTER_NO_TS) return JS_NULL;
3494 634 : return JS_NewInt64(ctx, lival);
3495 0 : case JSF_PCK_DUR:
3496 0 : return JS_NewInt32(ctx, gf_filter_pck_get_duration(pck));
3497 522 : case JSF_PCK_SAP:
3498 522 : return JS_NewInt32(ctx, gf_filter_pck_get_sap(pck));
3499 0 : case JSF_PCK_TIMESCALE:
3500 0 : return JS_NewInt32(ctx, gf_filter_pck_get_timescale(pck));
3501 0 : case JSF_PCK_INTERLACED:
3502 0 : return JS_NewInt32(ctx, gf_filter_pck_get_interlaced(pck));
3503 0 : case JSF_PCK_SEEK:
3504 0 : return JS_NewBool(ctx, gf_filter_pck_get_seek_flag(pck));
3505 0 : case JSF_PCK_CORRUPTED:
3506 0 : return JS_NewBool(ctx, gf_filter_pck_get_corrupted(pck));
3507 0 : case JSF_PCK_BYTE_OFFSET:
3508 0 : lival = gf_filter_pck_get_byte_offset(pck);
3509 0 : if (lival==GF_FILTER_NO_TS) return JS_NULL;
3510 0 : return JS_NewInt64(ctx, lival);
3511 0 : case JSF_PCK_ROLL:
3512 0 : return JS_NewInt32(ctx, gf_filter_pck_get_roll_info(pck));
3513 0 : case JSF_PCK_CRYPT:
3514 0 : return JS_NewInt32(ctx, gf_filter_pck_get_crypt_flags(pck));
3515 0 : case JSF_PCK_CLOCK_TYPE:
3516 0 : return JS_NewInt32(ctx, gf_filter_pck_get_clock_type(pck));
3517 0 : case JSF_PCK_CAROUSEL:
3518 0 : return JS_NewInt32(ctx, gf_filter_pck_get_carousel_version(pck));
3519 0 : case JSF_PCK_SEQNUM:
3520 0 : return JS_NewInt32(ctx, gf_filter_pck_get_seq_num(pck));
3521 0 : case JSF_PCK_BLOCKING_REF:
3522 0 : return JS_NewBool(ctx, gf_filter_pck_is_blocking_ref(pck));
3523 0 : case JSF_PCK_IS_LEADING:
3524 0 : ival = gf_filter_pck_get_dependency_flags(pck);
3525 0 : return JS_NewBool(ctx, (ival>>6) & 0x3);
3526 0 : case JSF_PCK_DEPENDS_ON:
3527 0 : ival = gf_filter_pck_get_dependency_flags(pck);
3528 0 : return JS_NewBool(ctx, (ival>>4) & 0x3);
3529 0 : case JSF_PCK_DEPENDED_ON:
3530 0 : ival = gf_filter_pck_get_dependency_flags(pck);
3531 0 : return JS_NewBool(ctx, (ival>>2) & 0x3);
3532 0 : case JSF_PCK_HAS_REDUNDANT:
3533 0 : ival = gf_filter_pck_get_dependency_flags(pck);
3534 0 : return JS_NewBool(ctx, (ival) & 0x3);
3535 542 : case JSF_PCK_SIZE:
3536 542 : gf_filter_pck_get_data(pck, &ival);
3537 542 : return JS_NewInt32(ctx, ival);
3538 850 : case JSF_PCK_DATA:
3539 1700 : if (JS_IsUndefined(pckctx->data_ab)) {
3540 775 : const u8 *data = gf_filter_pck_get_data(pck, &ival);
3541 775 : if (!data) return JS_NULL;
3542 775 : pckctx->data_ab = JS_NewArrayBuffer(ctx, (u8 *) data, ival, NULL, NULL, GF_TRUE);
3543 : }
3544 : return JS_DupValue(ctx, pckctx->data_ab);
3545 0 : case JSF_PCK_FRAME_IFCE:
3546 0 : if (gf_filter_pck_get_frame_interface(pck) != NULL) return JS_NewBool(ctx, 1);
3547 : else return JS_NewBool(ctx, 0);
3548 : }
3549 0 : return JS_UNDEFINED;
3550 : }
3551 :
3552 75 : static JSValue jsf_pck_set_readonly(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3553 : {
3554 : GF_FilterPacket *pck;
3555 75 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3556 75 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3557 : pck = pckctx->pck;
3558 :
3559 75 : gf_filter_pck_set_readonly(pck);
3560 75 : return JS_UNDEFINED;
3561 : }
3562 348 : static JSValue jsf_pck_enum_properties(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3563 : {
3564 : s32 idx;
3565 : u32 p4cc;
3566 : const char *pname;
3567 : JSValue res;
3568 : const GF_PropertyValue *prop;
3569 : GF_FilterPacket *pck;
3570 348 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3571 348 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3572 : pck = pckctx->pck;
3573 :
3574 348 : if (JS_ToInt32(ctx, &idx, argv[0]))
3575 0 : return JS_EXCEPTION;
3576 :
3577 348 : prop = gf_filter_pck_enum_properties(pck, &idx, &p4cc, &pname);
3578 348 : if (!prop) return JS_NULL;
3579 0 : if (!pname) pname = gf_props_4cc_get_name(p4cc);
3580 0 : if (!pname) return JS_EXCEPTION;
3581 :
3582 0 : res = JS_NewObject(ctx);
3583 0 : JS_SetPropertyStr(ctx, res, "name", JS_NewString(ctx, pname));
3584 0 : JS_SetPropertyStr(ctx, res, "type", JS_NewInt32(ctx, prop->type));
3585 0 : JS_SetPropertyStr(ctx, res, "value", jsf_NewProp(ctx, prop));
3586 0 : return res;
3587 : }
3588 :
3589 75 : static JSValue jsf_pck_get_property(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3590 : {
3591 : JSValue res;
3592 : const char *name=NULL;
3593 : const GF_PropertyValue *prop;
3594 : GF_FilterPacket *pck;
3595 75 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3596 75 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3597 : pck = pckctx->pck;
3598 :
3599 : name = JS_ToCString(ctx, argv[0]);
3600 75 : if (!name) return JS_EXCEPTION;
3601 75 : if ((argc>1) && JS_ToBool(ctx, argv[1])) {
3602 75 : prop = gf_filter_pck_get_property_str(pck, name);
3603 75 : JS_FreeCString(ctx, name);
3604 75 : if (!prop) return JS_NULL;
3605 0 : res = jsf_NewProp(ctx, prop);
3606 0 : JS_SetPropertyStr(ctx, res, "type", JS_NewInt32(ctx, prop->type));
3607 : } else {
3608 0 : u32 p4cc = gf_props_get_id(name);
3609 0 : JS_FreeCString(ctx, name);
3610 0 : if (!p4cc)
3611 0 : return js_throw_err(ctx, GF_BAD_PARAM);
3612 :
3613 0 : prop = gf_filter_pck_get_property(pck, p4cc);
3614 0 : if (!prop) return JS_NULL;
3615 0 : res = jsf_NewPropTranslate(ctx, prop, p4cc);
3616 : }
3617 0 : return res;
3618 : }
3619 :
3620 348 : static JSValue jsf_pck_ref(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3621 : {
3622 : Bool is_ref_props = GF_FALSE;
3623 : GF_JSPckCtx *ref_pckctx;
3624 348 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3625 348 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3626 :
3627 348 : if (argc && JS_ToBool(ctx, argv[0])) is_ref_props = GF_TRUE;
3628 :
3629 348 : ref_pckctx = gf_list_pop_back(pckctx->jspid->jsf->pck_res);
3630 348 : if (!ref_pckctx) {
3631 2 : GF_SAFEALLOC(ref_pckctx, GF_JSPckCtx);
3632 2 : if (!ref_pckctx)
3633 0 : return js_throw_err(ctx, GF_OUT_OF_MEM);
3634 : }
3635 : memcpy(ref_pckctx, pckctx, sizeof(GF_JSPckCtx));
3636 348 : if (is_ref_props)
3637 0 : gf_filter_pck_ref_props(&ref_pckctx->pck);
3638 : else {
3639 348 : gf_filter_pck_ref(&ref_pckctx->pck);
3640 : }
3641 348 : ref_pckctx->flags = GF_JS_PCK_IS_REF;
3642 348 : ref_pckctx->jsobj = JS_NewObjectClass(ctx, jsf_pck_class_id);
3643 348 : ref_pckctx->data_ab = JS_UNDEFINED;
3644 348 : ref_pckctx->ref_val = JS_UNDEFINED;
3645 348 : JS_SetOpaque(ref_pckctx->jsobj, ref_pckctx);
3646 : return JS_DupValue(ctx, ref_pckctx->jsobj);
3647 : }
3648 :
3649 348 : static JSValue jsf_pck_unref(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3650 : {
3651 348 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3652 348 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3653 348 : if (!(pckctx->flags & GF_JS_PCK_IS_REF))
3654 0 : return js_throw_err_msg(ctx, GF_BAD_PARAM, "Attempt to unref a non-reference packet");
3655 :
3656 348 : gf_filter_pck_unref(pckctx->pck);
3657 348 : pckctx->pck = NULL;
3658 : JS_FreeValue(ctx, pckctx->jsobj);
3659 348 : JS_SetOpaque(this_val, NULL);
3660 348 : gf_list_add(pckctx->jspid->jsf->pck_res, pckctx);
3661 : memset(pckctx, 0, sizeof(GF_JSPckCtx));
3662 348 : return JS_UNDEFINED;
3663 : }
3664 :
3665 1305 : static JSValue jsf_pck_send(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3666 : {
3667 : GF_FilterPacket *pck;
3668 1305 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3669 1305 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3670 1305 : if (! pckctx->jspid->jsf->filter->in_process)
3671 0 : return js_throw_err_msg(ctx, GF_BAD_PARAM, "Filter %s attempt to send packet outside process callback not allowed!\n", pckctx->jspid->jsf->filter->name);
3672 :
3673 : pck = pckctx->pck;
3674 2610 : if (!JS_IsUndefined(pckctx->data_ab)) {
3675 : JS_FreeValue(ctx, pckctx->data_ab);
3676 427 : pckctx->data_ab = JS_UNDEFINED;
3677 : }
3678 1305 : gf_filter_pck_send(pck);
3679 1305 : JS_SetOpaque(this_val, NULL);
3680 1305 : if (!(pckctx->flags & GF_JS_PCK_IS_SHARED)) {
3681 1207 : if (pckctx->jspid) {
3682 1207 : gf_list_add(pckctx->jspid->jsf->pck_res, pckctx);
3683 : memset(pckctx, 0, sizeof(GF_JSPckCtx));
3684 : }
3685 : }
3686 1305 : return JS_UNDEFINED;
3687 : }
3688 2 : static JSValue jsf_pck_discard(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3689 : {
3690 : GF_FilterPacket *pck;
3691 2 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3692 2 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3693 : pck = pckctx->pck;
3694 2 : pckctx->pck = NULL;
3695 2 : gf_filter_pck_discard(pck);
3696 2 : return JS_UNDEFINED;
3697 : }
3698 :
3699 275 : static JSValue jsf_pck_set_property(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3700 : {
3701 : GF_Err e;
3702 : GF_PropertyValue prop;
3703 : const char *name=NULL;
3704 : GF_FilterPacket *pck;
3705 275 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3706 275 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3707 : pck = pckctx->pck;
3708 :
3709 : name = JS_ToCString(ctx, argv[0]);
3710 275 : if (!name) return JS_EXCEPTION;
3711 :
3712 275 : if ((argc>2) && JS_ToBool(ctx, argv[2])) {
3713 550 : if (!JS_IsNull(argv[2])) {
3714 275 : e = jsf_ToProp(pckctx->jspid->jsf->filter, ctx, argv[1], 0, &prop);
3715 275 : JS_FreeCString(ctx, name);
3716 275 : if (e) return js_throw_err(ctx, e);
3717 275 : e = gf_filter_pck_set_property_dyn(pck, (char *) name, &prop);
3718 275 : gf_props_reset_single(&prop);
3719 : } else {
3720 0 : e = gf_filter_pck_set_property_dyn(pck, (char *) name, NULL);
3721 : }
3722 : } else {
3723 0 : u32 p4cc = gf_props_get_id(name);
3724 0 : if (!p4cc) {
3725 : JSValue ret;
3726 0 : JS_FreeCString(ctx, name);
3727 0 : ret = js_throw_err_msg(ctx, GF_BAD_PARAM, "Urecognized builtin property name %s\n", name);
3728 0 : return ret;
3729 : }
3730 0 : JS_FreeCString(ctx, name);
3731 0 : if ( ((p4cc==GF_PROP_PCK_SENDER_NTP) || (p4cc==GF_PROP_PCK_RECEIVER_NTP))
3732 0 : && JS_IsBool(argv[1]) && JS_ToBool(ctx, argv[1])
3733 : ) {
3734 0 : e = gf_filter_pck_set_property(pck, p4cc, &PROP_LONGUINT(gf_net_get_ntp_ts()) );
3735 : }
3736 0 : else if (JS_IsNull(argv[1])) {
3737 0 : e = gf_filter_pck_set_property(pck, p4cc, NULL);
3738 : }
3739 : else {
3740 0 : e = jsf_ToProp(pckctx->jspid->jsf->filter, ctx, argv[1], p4cc, &prop);
3741 0 : if (e) return js_throw_err(ctx, e);
3742 0 : if ( ((p4cc==GF_PROP_PCK_SENDER_NTP) || (p4cc==GF_PROP_PCK_RECEIVER_NTP)) && (prop.type==GF_PROP_FRACTION)) {
3743 0 : u64 ntp = (u32) prop.value.frac.num;
3744 0 : ntp <<= 32;
3745 0 : ntp |= prop.value.frac.den;
3746 0 : prop.type = GF_PROP_LUINT;
3747 0 : prop.value.longuint = ntp;
3748 : }
3749 :
3750 0 : e = gf_filter_pck_set_property(pck, p4cc, &prop);
3751 0 : gf_props_reset_single(&prop);
3752 : }
3753 : }
3754 275 : if (e) return js_throw_err(ctx, e);
3755 275 : return JS_UNDEFINED;
3756 : }
3757 :
3758 40 : static JSValue jsf_pck_append_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3759 : {
3760 40 : u8 *data_start=NULL;
3761 40 : u32 data_size=0;
3762 : u8 *new_start;
3763 : GF_Err e;
3764 : GF_FilterPacket *pck;
3765 40 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3766 40 : if (!pckctx || !pckctx->pck || !argc) return JS_EXCEPTION;
3767 : pck = pckctx->pck;
3768 :
3769 80 : if (JS_IsString(argv[0]) || JS_IsInteger(argv[0])) {
3770 : u32 len;
3771 : const char *str = NULL;
3772 :
3773 40 : if (JS_IsInteger(argv[0])) {
3774 0 : JS_ToInt32(ctx, &len, argv[0]);
3775 : } else {
3776 : str = JS_ToCString(ctx, argv[0]);
3777 40 : if (!str) return JS_EXCEPTION;
3778 40 : len = (u32) strlen(str);
3779 : }
3780 :
3781 40 : e = gf_filter_pck_expand(pck, len, &data_start, &new_start, &data_size);
3782 40 : if (!new_start || e) {
3783 0 : if (str) JS_FreeCString(ctx, str);
3784 0 : return js_throw_err(ctx, e);
3785 : }
3786 40 : if (str) {
3787 40 : memcpy(new_start, str, len);
3788 40 : JS_FreeCString(ctx, str);
3789 : }
3790 :
3791 40 : jsf_pck_detach_ab(ctx, pckctx);
3792 40 : return JS_NewArrayBuffer(ctx, (u8 *) new_start, len, NULL, NULL, GF_TRUE);
3793 : }
3794 :
3795 0 : if (!JS_IsObject(argv[0])) return JS_EXCEPTION;
3796 :
3797 : size_t ab_size;
3798 0 : u8 *data = JS_GetArrayBuffer(ctx, &ab_size, argv[0]);
3799 0 : if (!data)
3800 0 : return JS_EXCEPTION;
3801 :
3802 0 : e = gf_filter_pck_expand(pck, (u32) ab_size, &data_start, &new_start, &data_size);
3803 0 : if (!new_start || e) {
3804 0 : return js_throw_err(ctx, e);
3805 : }
3806 0 : memcpy(new_start, data, ab_size);
3807 :
3808 0 : jsf_pck_detach_ab(ctx, pckctx);
3809 :
3810 0 : return JS_NewArrayBuffer(ctx, (u8 *) new_start, ab_size, NULL, NULL, GF_TRUE);
3811 : }
3812 :
3813 20 : static JSValue jsf_pck_truncate(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3814 : {
3815 20 : u32 len=0;
3816 : GF_Err e;
3817 : GF_FilterPacket *pck;
3818 20 : GF_JSPckCtx *pckctx = JS_GetOpaque(this_val, jsf_pck_class_id);
3819 20 : if (!pckctx || !pckctx->pck) return JS_EXCEPTION;
3820 : pck = pckctx->pck;
3821 20 : if (argc) {
3822 20 : JS_ToInt32(ctx, &len, argv[0]);
3823 : }
3824 20 : e = gf_filter_pck_truncate(pck, len);
3825 20 : if (e) return js_throw_err(ctx, e);
3826 :
3827 20 : jsf_pck_detach_ab(ctx, pckctx);
3828 20 : return JS_UNDEFINED;
3829 : }
3830 579 : static JSValue jsf_pck_copy_props(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
3831 : {
3832 : GF_Err e;
3833 579 : GF_JSPckCtx *pck_dst = JS_GetOpaque(this_val, jsf_pck_class_id);
3834 579 : if (!pck_dst || !pck_dst->pck || !argc)
3835 0 : return JS_EXCEPTION;
3836 579 : GF_JSPckCtx *pck_from = JS_GetOpaque(argv[0], jsf_pck_class_id);
3837 579 : if (!pck_from || !pck_from->pck)
3838 0 : return JS_EXCEPTION;
3839 579 : e = gf_filter_pck_merge_properties(pck_from->pck, pck_dst->pck);
3840 579 : if (e) return js_throw_err(ctx, e);
3841 579 : return JS_UNDEFINED;
3842 : }
3843 :
3844 : static const JSCFunctionListEntry jsf_pck_funcs[] =
3845 : {
3846 : JS_CGETSET_MAGIC_DEF("start", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_START),
3847 : JS_CGETSET_MAGIC_DEF("end", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_END),
3848 : JS_CGETSET_MAGIC_DEF("dts", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_DTS),
3849 : JS_CGETSET_MAGIC_DEF("cts", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_CTS),
3850 : JS_CGETSET_MAGIC_DEF("dur", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_DUR),
3851 : JS_CGETSET_MAGIC_DEF("sap", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_SAP),
3852 : JS_CGETSET_MAGIC_DEF("timescale", jsf_pck_get_prop, NULL, JSF_PCK_TIMESCALE),
3853 : JS_CGETSET_MAGIC_DEF("interlaced", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_INTERLACED),
3854 : JS_CGETSET_MAGIC_DEF("corrupted", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_CORRUPTED),
3855 : JS_CGETSET_MAGIC_DEF("seek", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_SEEK),
3856 : JS_CGETSET_MAGIC_DEF("byte_offset", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_BYTE_OFFSET),
3857 : JS_CGETSET_MAGIC_DEF("roll", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_ROLL),
3858 : JS_CGETSET_MAGIC_DEF("crypt", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_CRYPT),
3859 : JS_CGETSET_MAGIC_DEF("clock_type", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_CLOCK_TYPE),
3860 : JS_CGETSET_MAGIC_DEF("carousel", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_CAROUSEL),
3861 : JS_CGETSET_MAGIC_DEF("seqnum", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_SEQNUM),
3862 : JS_CGETSET_MAGIC_DEF("blocking_ref", jsf_pck_get_prop, NULL, JSF_PCK_BLOCKING_REF),
3863 : JS_CGETSET_MAGIC_DEF("is_leading", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_IS_LEADING),
3864 : JS_CGETSET_MAGIC_DEF("depends_on", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_DEPENDS_ON),
3865 : JS_CGETSET_MAGIC_DEF("depended_on", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_DEPENDED_ON),
3866 : JS_CGETSET_MAGIC_DEF("redundant", jsf_pck_get_prop, jsf_pck_set_prop, JSF_PCK_HAS_REDUNDANT),
3867 : JS_CGETSET_MAGIC_DEF("size", jsf_pck_get_prop, NULL, JSF_PCK_SIZE),
3868 : JS_CGETSET_MAGIC_DEF("data", jsf_pck_get_prop, NULL, JSF_PCK_DATA),
3869 : JS_CGETSET_MAGIC_DEF("frame_ifce", jsf_pck_get_prop, NULL, JSF_PCK_DATA),
3870 :
3871 : JS_CFUNC_DEF("set_readonly", 0, jsf_pck_set_readonly),
3872 : JS_CFUNC_DEF("enum_properties", 0, jsf_pck_enum_properties),
3873 : JS_CFUNC_DEF("get_prop", 0, jsf_pck_get_property),
3874 : JS_CFUNC_DEF("ref", 0, jsf_pck_ref),
3875 : JS_CFUNC_DEF("unref", 0, jsf_pck_unref),
3876 : JS_CFUNC_DEF("send", 0, jsf_pck_send),
3877 : JS_CFUNC_DEF("discard", 0, jsf_pck_discard),
3878 : JS_CFUNC_DEF("set_prop", 0, jsf_pck_set_property),
3879 : JS_CFUNC_DEF("append", 0, jsf_pck_append_data),
3880 : JS_CFUNC_DEF("truncate", 0, jsf_pck_truncate),
3881 : JS_CFUNC_DEF("copy_props", 0, jsf_pck_copy_props),
3882 : };
3883 :
3884 :
3885 2449 : static GF_Err jsfilter_process(GF_Filter *filter)
3886 : {
3887 : JSValue ret;
3888 2449 : GF_Err e = GF_OK;
3889 2449 : GF_JSFilterCtx *jsf = gf_filter_get_udta(filter);
3890 2449 : if (!jsf) return GF_BAD_PARAM;
3891 :
3892 2449 : gf_js_lock(jsf->ctx, GF_TRUE);
3893 2449 : ret = JS_Call(jsf->ctx, jsf->funcs[JSF_EVT_PROCESS], jsf->filter_obj, 0, NULL);
3894 2449 : if (JS_IsException(ret)) {
3895 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error processing\n", jsf->log_name));
3896 0 : js_dump_error(jsf->ctx);
3897 0 : e = GF_BAD_PARAM;
3898 : }
3899 2449 : else if (JS_IsInteger(ret))
3900 1532 : JS_ToInt32(jsf->ctx, (int*)&e, ret);
3901 :
3902 2449 : JS_FreeValue(jsf->ctx, ret);
3903 2449 : gf_js_lock(jsf->ctx, GF_FALSE);
3904 :
3905 2449 : js_do_loop(jsf->ctx);
3906 2449 : return e;
3907 : }
3908 :
3909 :
3910 :
3911 14 : static GF_Err jsfilter_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
3912 : {
3913 : JSValue ret;
3914 14 : GF_Err e = GF_OK;
3915 14 : GF_JSFilterCtx *jsf = gf_filter_get_udta(filter);
3916 : GF_JSPidCtx *pctx;
3917 :
3918 14 : if (!jsf) return GF_BAD_PARAM;
3919 :
3920 14 : pctx = gf_filter_pid_get_udta(pid);
3921 :
3922 14 : if (is_remove) {
3923 : assert(pctx);
3924 1 : gf_js_lock(jsf->ctx, GF_TRUE);
3925 1 : ret = JS_Call(jsf->ctx, jsf->funcs[JSF_EVT_REMOVE_PID], jsf->filter_obj, 1, &pctx->jsobj);
3926 1 : if (JS_IsException(ret)) {
3927 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error removing pid\n", jsf->log_name));
3928 0 : js_dump_error(jsf->ctx);
3929 0 : e = GF_BAD_PARAM;
3930 : }
3931 1 : else if (JS_IsInteger(ret))
3932 0 : JS_ToInt32(jsf->ctx, (int*)&e, ret);
3933 1 : JS_FreeValue(jsf->ctx, ret);
3934 1 : JS_FreeValue(jsf->ctx, pctx->jsobj);
3935 1 : gf_list_del_item(jsf->pids, pctx);
3936 1 : gf_filter_pid_set_udta(pid, NULL);
3937 1 : gf_free(pctx);
3938 1 : gf_js_lock(jsf->ctx, GF_FALSE);
3939 1 : js_do_loop(jsf->ctx);
3940 1 : return e;
3941 : }
3942 :
3943 13 : gf_js_lock(jsf->ctx, GF_TRUE);
3944 :
3945 13 : if (!pctx) {
3946 9 : GF_SAFEALLOC(pctx, GF_JSPidCtx);
3947 9 : if (!pctx) return GF_OUT_OF_MEM;
3948 :
3949 9 : pctx->jsf = jsf;
3950 9 : pctx->pid = pid;
3951 9 : pctx->jsobj = JS_NewObjectClass(jsf->ctx, jsf_pid_class_id);
3952 9 : gf_filter_pid_set_udta(pid, pctx);
3953 9 : gf_list_add(jsf->pids, pctx);
3954 9 : JS_SetOpaque(pctx->jsobj, pctx);
3955 : }
3956 :
3957 13 : ret = JS_Call(jsf->ctx, jsf->funcs[JSF_EVT_CONFIGURE_PID], jsf->filter_obj, 1, &pctx->jsobj);
3958 13 : if (JS_IsException(ret)) {
3959 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error configure pid\n", jsf->log_name));
3960 0 : js_dump_error(jsf->ctx);
3961 0 : e = GF_BAD_PARAM;
3962 : }
3963 13 : else if (JS_IsInteger(ret))
3964 0 : JS_ToInt32(jsf->ctx, (int*)&e, ret);
3965 13 : JS_FreeValue(jsf->ctx, ret);
3966 :
3967 13 : gf_js_lock(jsf->ctx, GF_FALSE);
3968 13 : js_do_loop(jsf->ctx);
3969 13 : return e;
3970 : }
3971 :
3972 77 : void js_load_constants(JSContext *ctx, JSValue global_obj)
3973 : {
3974 : JSValue val;
3975 :
3976 77 : val = JS_NewObject(ctx);
3977 77 : JS_SetPropertyStr(ctx, val, "log", JS_NewCFunction(ctx, js_print, "log", 1));
3978 77 : JS_SetPropertyStr(ctx, global_obj, "console", val);
3979 :
3980 : #define DEF_CONST( _val ) \
3981 : JS_SetPropertyStr(ctx, global_obj, #_val, JS_NewInt32(ctx, _val));
3982 :
3983 77 : DEF_CONST(GF_LOG_ERROR)
3984 77 : DEF_CONST(GF_LOG_WARNING)
3985 77 : DEF_CONST(GF_LOG_INFO)
3986 77 : DEF_CONST(GF_LOG_DEBUG)
3987 :
3988 77 : DEF_CONST(GF_PROP_BOOL)
3989 77 : DEF_CONST(GF_PROP_UINT)
3990 77 : DEF_CONST(GF_PROP_SINT)
3991 77 : DEF_CONST(GF_PROP_LUINT)
3992 77 : DEF_CONST(GF_PROP_LSINT)
3993 77 : DEF_CONST(GF_PROP_FRACTION)
3994 77 : DEF_CONST(GF_PROP_FRACTION64)
3995 77 : DEF_CONST(GF_PROP_FLOAT)
3996 77 : DEF_CONST(GF_PROP_DOUBLE)
3997 77 : DEF_CONST(GF_PROP_VEC2I)
3998 77 : DEF_CONST(GF_PROP_VEC2)
3999 77 : DEF_CONST(GF_PROP_VEC3I)
4000 77 : DEF_CONST(GF_PROP_VEC4I)
4001 77 : DEF_CONST(GF_PROP_STRING)
4002 77 : DEF_CONST(GF_PROP_STRING)
4003 77 : DEF_CONST(GF_PROP_STRING_NO_COPY)
4004 77 : DEF_CONST(GF_PROP_DATA)
4005 77 : DEF_CONST(GF_PROP_NAME)
4006 77 : DEF_CONST(GF_PROP_DATA_NO_COPY)
4007 77 : DEF_CONST(GF_PROP_CONST_DATA)
4008 77 : DEF_CONST(GF_PROP_POINTER)
4009 77 : DEF_CONST(GF_PROP_STRING_LIST)
4010 77 : DEF_CONST(GF_PROP_UINT_LIST)
4011 77 : DEF_CONST(GF_PROP_SINT_LIST)
4012 77 : DEF_CONST(GF_PROP_VEC2I_LIST)
4013 77 : DEF_CONST(GF_PROP_4CC)
4014 77 : DEF_CONST(GF_PROP_4CC_LIST)
4015 :
4016 77 : DEF_CONST(GF_PROP_PIXFMT)
4017 77 : DEF_CONST(GF_PROP_PCMFMT)
4018 77 : DEF_CONST(GF_PROP_CICP_COL_PRIM)
4019 77 : DEF_CONST(GF_PROP_CICP_COL_TFC)
4020 77 : DEF_CONST(GF_PROP_CICP_COL_MX)
4021 :
4022 :
4023 77 : DEF_CONST(GF_FEVT_PLAY)
4024 77 : DEF_CONST(GF_FEVT_SET_SPEED)
4025 77 : DEF_CONST(GF_FEVT_STOP)
4026 77 : DEF_CONST(GF_FEVT_PAUSE)
4027 77 : DEF_CONST(GF_FEVT_RESUME)
4028 77 : DEF_CONST(GF_FEVT_SOURCE_SEEK)
4029 77 : DEF_CONST(GF_FEVT_SOURCE_SWITCH)
4030 77 : DEF_CONST(GF_FEVT_SEGMENT_SIZE)
4031 77 : DEF_CONST(GF_FEVT_QUALITY_SWITCH)
4032 77 : DEF_CONST(GF_FEVT_VISIBILITY_HINT)
4033 77 : DEF_CONST(GF_FEVT_INFO_UPDATE)
4034 77 : DEF_CONST(GF_FEVT_BUFFER_REQ)
4035 77 : DEF_CONST(GF_FEVT_CAPS_CHANGE)
4036 77 : DEF_CONST(GF_FEVT_CONNECT_FAIL)
4037 77 : DEF_CONST(GF_FEVT_USER)
4038 :
4039 77 : DEF_CONST(GF_STATS_LOCAL)
4040 77 : DEF_CONST(GF_STATS_LOCAL_INPUTS)
4041 77 : DEF_CONST(GF_STATS_DECODER_SINK)
4042 77 : DEF_CONST(GF_STATS_DECODER_SOURCE)
4043 77 : DEF_CONST(GF_STATS_ENCODER_SINK)
4044 77 : DEF_CONST(GF_STATS_ENCODER_SOURCE)
4045 :
4046 77 : DEF_CONST(GF_FILTER_CLOCK_NONE)
4047 77 : DEF_CONST(GF_FILTER_CLOCK_PCR)
4048 77 : DEF_CONST(GF_FILTER_CLOCK_PCR_DISC)
4049 :
4050 77 : DEF_CONST(GF_FILTER_SAP_NONE)
4051 77 : DEF_CONST(GF_FILTER_SAP_1)
4052 77 : DEF_CONST(GF_FILTER_SAP_2)
4053 77 : DEF_CONST(GF_FILTER_SAP_3)
4054 77 : DEF_CONST(GF_FILTER_SAP_4)
4055 77 : DEF_CONST(GF_FILTER_SAP_4_PROL)
4056 :
4057 77 : DEF_CONST(GF_EOS);
4058 77 : DEF_CONST(GF_OK)
4059 77 : DEF_CONST(GF_BAD_PARAM)
4060 77 : DEF_CONST(GF_OUT_OF_MEM)
4061 77 : DEF_CONST(GF_IO_ERR)
4062 77 : DEF_CONST(GF_NOT_SUPPORTED)
4063 77 : DEF_CONST(GF_CORRUPTED_DATA)
4064 77 : DEF_CONST(GF_SG_UNKNOWN_NODE)
4065 77 : DEF_CONST(GF_SG_INVALID_PROTO)
4066 77 : DEF_CONST(GF_SCRIPT_ERROR)
4067 77 : DEF_CONST(GF_BUFFER_TOO_SMALL)
4068 77 : DEF_CONST(GF_NON_COMPLIANT_BITSTREAM)
4069 77 : DEF_CONST(GF_FILTER_NOT_FOUND)
4070 77 : DEF_CONST(GF_URL_ERROR)
4071 77 : DEF_CONST(GF_SERVICE_ERROR)
4072 77 : DEF_CONST(GF_REMOTE_SERVICE_ERROR)
4073 77 : DEF_CONST(GF_STREAM_NOT_FOUND)
4074 77 : DEF_CONST(GF_ISOM_INVALID_FILE)
4075 77 : DEF_CONST(GF_ISOM_INCOMPLETE_FILE)
4076 77 : DEF_CONST(GF_ISOM_INVALID_MEDIA)
4077 77 : DEF_CONST(GF_ISOM_INVALID_MODE)
4078 77 : DEF_CONST(GF_ISOM_UNKNOWN_DATA_REF)
4079 77 : DEF_CONST(GF_ODF_INVALID_DESCRIPTOR)
4080 77 : DEF_CONST(GF_ODF_FORBIDDEN_DESCRIPTOR)
4081 77 : DEF_CONST(GF_ODF_INVALID_COMMAND)
4082 77 : DEF_CONST(GF_BIFS_UNKNOWN_VERSION)
4083 77 : DEF_CONST(GF_IP_ADDRESS_NOT_FOUND)
4084 77 : DEF_CONST(GF_IP_CONNECTION_FAILURE)
4085 77 : DEF_CONST(GF_IP_NETWORK_FAILURE)
4086 77 : DEF_CONST(GF_IP_CONNECTION_CLOSED)
4087 77 : DEF_CONST(GF_IP_NETWORK_EMPTY)
4088 77 : DEF_CONST(GF_IP_SOCK_WOULD_BLOCK)
4089 77 : DEF_CONST(GF_IP_UDP_TIMEOUT)
4090 77 : DEF_CONST(GF_AUTHENTICATION_FAILURE)
4091 77 : DEF_CONST(GF_SCRIPT_NOT_READY)
4092 77 : DEF_CONST(GF_INVALID_CONFIGURATION)
4093 77 : DEF_CONST(GF_NOT_FOUND)
4094 77 : DEF_CONST(GF_PROFILE_NOT_SUPPORTED)
4095 77 : DEF_CONST(GF_REQUIRES_NEW_INSTANCE)
4096 77 : DEF_CONST(GF_FILTER_NOT_SUPPORTED)
4097 :
4098 77 : DEF_CONST(JSF_SETUP_ERROR)
4099 77 : DEF_CONST(JSF_NOTIF_ERROR)
4100 77 : DEF_CONST(JSF_NOTIF_ERROR_AND_DISCONNECT)
4101 :
4102 77 : DEF_CONST(GF_FILTER_UPDATE_DOWNSTREAM)
4103 77 : DEF_CONST(GF_FILTER_UPDATE_UPSTREAM)
4104 :
4105 77 : DEF_CONST(GF_EVENT_CLICK)
4106 77 : DEF_CONST(GF_EVENT_MOUSEUP)
4107 77 : DEF_CONST(GF_EVENT_MOUSEDOWN)
4108 77 : DEF_CONST(GF_EVENT_MOUSEMOVE)
4109 77 : DEF_CONST(GF_EVENT_MOUSEWHEEL)
4110 77 : DEF_CONST(GF_EVENT_DBLCLICK)
4111 77 : DEF_CONST(GF_EVENT_MULTITOUCH)
4112 77 : DEF_CONST(GF_EVENT_KEYUP)
4113 77 : DEF_CONST(GF_EVENT_KEYDOWN)
4114 77 : DEF_CONST(GF_EVENT_TEXTINPUT)
4115 77 : DEF_CONST(GF_EVENT_DROPFILE)
4116 77 : DEF_CONST(GF_EVENT_TIMESHIFT_DEPTH)
4117 77 : DEF_CONST(GF_EVENT_TIMESHIFT_UPDATE)
4118 77 : DEF_CONST(GF_EVENT_TIMESHIFT_OVERFLOW)
4119 77 : DEF_CONST(GF_EVENT_TIMESHIFT_UNDERRUN)
4120 77 : DEF_CONST(GF_EVENT_PASTE_TEXT)
4121 77 : DEF_CONST(GF_EVENT_COPY_TEXT)
4122 77 : DEF_CONST(GF_EVENT_SIZE)
4123 77 : DEF_CONST(GF_EVENT_SHOWHIDE)
4124 77 : DEF_CONST(GF_EVENT_MOVE)
4125 77 : DEF_CONST(GF_EVENT_SET_CAPTION)
4126 77 : DEF_CONST(GF_EVENT_REFRESH)
4127 77 : DEF_CONST(GF_EVENT_QUIT)
4128 :
4129 77 : DEF_CONST(GF_KEY_UNIDENTIFIED)
4130 77 : DEF_CONST(GF_KEY_ACCEPT)
4131 77 : DEF_CONST(GF_KEY_AGAIN)
4132 77 : DEF_CONST(GF_KEY_ALLCANDIDATES)
4133 77 : DEF_CONST(GF_KEY_ALPHANUM)
4134 77 : DEF_CONST(GF_KEY_ALT)
4135 77 : DEF_CONST(GF_KEY_ALTGRAPH)
4136 77 : DEF_CONST(GF_KEY_APPS)
4137 77 : DEF_CONST(GF_KEY_ATTN)
4138 77 : DEF_CONST(GF_KEY_BROWSERBACK)
4139 77 : DEF_CONST(GF_KEY_BROWSERFAVORITES)
4140 77 : DEF_CONST(GF_KEY_BROWSERFORWARD)
4141 77 : DEF_CONST(GF_KEY_BROWSERHOME)
4142 77 : DEF_CONST(GF_KEY_BROWSERREFRESH)
4143 77 : DEF_CONST(GF_KEY_BROWSERSEARCH)
4144 77 : DEF_CONST(GF_KEY_BROWSERSTOP)
4145 77 : DEF_CONST(GF_KEY_CAPSLOCK)
4146 77 : DEF_CONST(GF_KEY_CLEAR)
4147 77 : DEF_CONST(GF_KEY_CODEINPUT)
4148 77 : DEF_CONST(GF_KEY_COMPOSE)
4149 77 : DEF_CONST(GF_KEY_CONTROL)
4150 77 : DEF_CONST(GF_KEY_CRSEL)
4151 77 : DEF_CONST(GF_KEY_CONVERT)
4152 77 : DEF_CONST(GF_KEY_COPY)
4153 77 : DEF_CONST(GF_KEY_CUT)
4154 77 : DEF_CONST(GF_KEY_DOWN)
4155 77 : DEF_CONST(GF_KEY_END)
4156 77 : DEF_CONST(GF_KEY_ENTER)
4157 77 : DEF_CONST(GF_KEY_ERASEEOF)
4158 77 : DEF_CONST(GF_KEY_EXECUTE)
4159 77 : DEF_CONST(GF_KEY_EXSEL)
4160 77 : DEF_CONST(GF_KEY_F1)
4161 77 : DEF_CONST(GF_KEY_F2)
4162 77 : DEF_CONST(GF_KEY_F3)
4163 77 : DEF_CONST(GF_KEY_F4)
4164 77 : DEF_CONST(GF_KEY_F5)
4165 77 : DEF_CONST(GF_KEY_F6)
4166 77 : DEF_CONST(GF_KEY_F7)
4167 77 : DEF_CONST(GF_KEY_F8)
4168 77 : DEF_CONST(GF_KEY_F9)
4169 77 : DEF_CONST(GF_KEY_F10)
4170 77 : DEF_CONST(GF_KEY_F11)
4171 77 : DEF_CONST(GF_KEY_F12)
4172 77 : DEF_CONST(GF_KEY_F13)
4173 77 : DEF_CONST(GF_KEY_F14)
4174 77 : DEF_CONST(GF_KEY_F15)
4175 77 : DEF_CONST(GF_KEY_F16)
4176 77 : DEF_CONST(GF_KEY_F17)
4177 77 : DEF_CONST(GF_KEY_F18)
4178 77 : DEF_CONST(GF_KEY_F19)
4179 77 : DEF_CONST(GF_KEY_F20)
4180 77 : DEF_CONST(GF_KEY_F21)
4181 77 : DEF_CONST(GF_KEY_F22)
4182 77 : DEF_CONST(GF_KEY_F23)
4183 77 : DEF_CONST(GF_KEY_F24)
4184 77 : DEF_CONST(GF_KEY_FINALMODE)
4185 77 : DEF_CONST(GF_KEY_FIND)
4186 77 : DEF_CONST(GF_KEY_FULLWIDTH)
4187 77 : DEF_CONST(GF_KEY_HALFWIDTH)
4188 77 : DEF_CONST(GF_KEY_HANGULMODE)
4189 77 : DEF_CONST(GF_KEY_HANJAMODE)
4190 77 : DEF_CONST(GF_KEY_HELP)
4191 77 : DEF_CONST(GF_KEY_HIRAGANA)
4192 77 : DEF_CONST(GF_KEY_HOME)
4193 77 : DEF_CONST(GF_KEY_INSERT)
4194 77 : DEF_CONST(GF_KEY_JAPANESEHIRAGANA)
4195 77 : DEF_CONST(GF_KEY_JAPANESEKATAKANA)
4196 77 : DEF_CONST(GF_KEY_JAPANESEROMAJI)
4197 77 : DEF_CONST(GF_KEY_JUNJAMODE)
4198 77 : DEF_CONST(GF_KEY_KANAMODE)
4199 77 : DEF_CONST(GF_KEY_KANJIMODE)
4200 77 : DEF_CONST(GF_KEY_KATAKANA)
4201 77 : DEF_CONST(GF_KEY_LAUNCHAPPLICATION1)
4202 77 : DEF_CONST(GF_KEY_LAUNCHAPPLICATION2)
4203 77 : DEF_CONST(GF_KEY_LAUNCHMAIL)
4204 77 : DEF_CONST(GF_KEY_LEFT)
4205 77 : DEF_CONST(GF_KEY_META)
4206 77 : DEF_CONST(GF_KEY_MEDIANEXTTRACK)
4207 77 : DEF_CONST(GF_KEY_MEDIAPLAYPAUSE)
4208 77 : DEF_CONST(GF_KEY_MEDIAPREVIOUSTRACK)
4209 77 : DEF_CONST(GF_KEY_MEDIASTOP)
4210 77 : DEF_CONST(GF_KEY_MODECHANGE)
4211 77 : DEF_CONST(GF_KEY_NONCONVERT)
4212 77 : DEF_CONST(GF_KEY_NUMLOCK)
4213 77 : DEF_CONST(GF_KEY_PAGEDOWN)
4214 77 : DEF_CONST(GF_KEY_PAGEUP)
4215 77 : DEF_CONST(GF_KEY_PASTE)
4216 77 : DEF_CONST(GF_KEY_PAUSE)
4217 77 : DEF_CONST(GF_KEY_PLAY)
4218 77 : DEF_CONST(GF_KEY_PREVIOUSCANDIDATE)
4219 77 : DEF_CONST(GF_KEY_PRINTSCREEN)
4220 77 : DEF_CONST(GF_KEY_PROCESS)
4221 77 : DEF_CONST(GF_KEY_PROPS)
4222 77 : DEF_CONST(GF_KEY_RIGHT)
4223 77 : DEF_CONST(GF_KEY_ROMANCHARACTERS)
4224 77 : DEF_CONST(GF_KEY_SCROLL)
4225 77 : DEF_CONST(GF_KEY_SELECT)
4226 77 : DEF_CONST(GF_KEY_SELECTMEDIA)
4227 77 : DEF_CONST(GF_KEY_SHIFT)
4228 77 : DEF_CONST(GF_KEY_STOP)
4229 77 : DEF_CONST(GF_KEY_UP)
4230 77 : DEF_CONST(GF_KEY_UNDO)
4231 77 : DEF_CONST(GF_KEY_VOLUMEDOWN)
4232 77 : DEF_CONST(GF_KEY_VOLUMEMUTE)
4233 77 : DEF_CONST(GF_KEY_VOLUMEUP)
4234 77 : DEF_CONST(GF_KEY_WIN)
4235 77 : DEF_CONST(GF_KEY_ZOOM)
4236 77 : DEF_CONST(GF_KEY_BACKSPACE)
4237 77 : DEF_CONST(GF_KEY_TAB)
4238 77 : DEF_CONST(GF_KEY_CANCEL)
4239 77 : DEF_CONST(GF_KEY_ESCAPE)
4240 77 : DEF_CONST(GF_KEY_SPACE)
4241 77 : DEF_CONST(GF_KEY_EXCLAMATION)
4242 77 : DEF_CONST(GF_KEY_QUOTATION)
4243 77 : DEF_CONST(GF_KEY_NUMBER)
4244 77 : DEF_CONST(GF_KEY_DOLLAR)
4245 77 : DEF_CONST(GF_KEY_AMPERSAND)
4246 77 : DEF_CONST(GF_KEY_APOSTROPHE)
4247 77 : DEF_CONST(GF_KEY_LEFTPARENTHESIS)
4248 77 : DEF_CONST(GF_KEY_RIGHTPARENTHESIS)
4249 77 : DEF_CONST(GF_KEY_STAR)
4250 77 : DEF_CONST(GF_KEY_PLUS)
4251 77 : DEF_CONST(GF_KEY_COMMA)
4252 77 : DEF_CONST(GF_KEY_HYPHEN)
4253 77 : DEF_CONST(GF_KEY_FULLSTOP)
4254 77 : DEF_CONST(GF_KEY_SLASH)
4255 77 : DEF_CONST(GF_KEY_0)
4256 77 : DEF_CONST(GF_KEY_1)
4257 77 : DEF_CONST(GF_KEY_2)
4258 77 : DEF_CONST(GF_KEY_3)
4259 77 : DEF_CONST(GF_KEY_4)
4260 77 : DEF_CONST(GF_KEY_5)
4261 77 : DEF_CONST(GF_KEY_6)
4262 77 : DEF_CONST(GF_KEY_7)
4263 77 : DEF_CONST(GF_KEY_8)
4264 77 : DEF_CONST(GF_KEY_9)
4265 77 : DEF_CONST(GF_KEY_COLON)
4266 77 : DEF_CONST(GF_KEY_SEMICOLON)
4267 77 : DEF_CONST(GF_KEY_LESSTHAN)
4268 77 : DEF_CONST(GF_KEY_EQUALS)
4269 77 : DEF_CONST(GF_KEY_GREATERTHAN)
4270 77 : DEF_CONST(GF_KEY_QUESTION)
4271 77 : DEF_CONST(GF_KEY_AT)
4272 77 : DEF_CONST(GF_KEY_A)
4273 77 : DEF_CONST(GF_KEY_B)
4274 77 : DEF_CONST(GF_KEY_C)
4275 77 : DEF_CONST(GF_KEY_D)
4276 77 : DEF_CONST(GF_KEY_E)
4277 77 : DEF_CONST(GF_KEY_F)
4278 77 : DEF_CONST(GF_KEY_G)
4279 77 : DEF_CONST(GF_KEY_H)
4280 77 : DEF_CONST(GF_KEY_I)
4281 77 : DEF_CONST(GF_KEY_J)
4282 77 : DEF_CONST(GF_KEY_K)
4283 77 : DEF_CONST(GF_KEY_L)
4284 77 : DEF_CONST(GF_KEY_M)
4285 77 : DEF_CONST(GF_KEY_N)
4286 77 : DEF_CONST(GF_KEY_O)
4287 77 : DEF_CONST(GF_KEY_P)
4288 77 : DEF_CONST(GF_KEY_Q)
4289 77 : DEF_CONST(GF_KEY_R)
4290 77 : DEF_CONST(GF_KEY_S)
4291 77 : DEF_CONST(GF_KEY_T)
4292 77 : DEF_CONST(GF_KEY_U)
4293 77 : DEF_CONST(GF_KEY_V)
4294 77 : DEF_CONST(GF_KEY_W)
4295 77 : DEF_CONST(GF_KEY_X)
4296 77 : DEF_CONST(GF_KEY_Y)
4297 77 : DEF_CONST(GF_KEY_Z)
4298 77 : DEF_CONST(GF_KEY_LEFTSQUAREBRACKET)
4299 77 : DEF_CONST(GF_KEY_BACKSLASH)
4300 77 : DEF_CONST(GF_KEY_RIGHTSQUAREBRACKET)
4301 77 : DEF_CONST(GF_KEY_CIRCUM)
4302 77 : DEF_CONST(GF_KEY_UNDERSCORE)
4303 77 : DEF_CONST(GF_KEY_GRAVEACCENT)
4304 77 : DEF_CONST(GF_KEY_LEFTCURLYBRACKET)
4305 77 : DEF_CONST(GF_KEY_PIPE)
4306 77 : DEF_CONST(GF_KEY_RIGHTCURLYBRACKET)
4307 77 : DEF_CONST(GF_KEY_DEL)
4308 77 : DEF_CONST(GF_KEY_INVERTEXCLAMATION)
4309 77 : DEF_CONST(GF_KEY_DEADGRAVE)
4310 77 : DEF_CONST(GF_KEY_DEADEACUTE)
4311 77 : DEF_CONST(GF_KEY_DEADCIRCUM)
4312 77 : DEF_CONST(GF_KEY_DEADTILDE)
4313 77 : DEF_CONST(GF_KEY_DEADMACRON)
4314 77 : DEF_CONST(GF_KEY_DEADBREVE)
4315 77 : DEF_CONST(GF_KEY_DEADABOVEDOT)
4316 77 : DEF_CONST(GF_KEY_DEADDIARESIS)
4317 77 : DEF_CONST(GF_KEY_DEADRINGABOVE)
4318 77 : DEF_CONST(GF_KEY_DEADDOUBLEACUTE)
4319 77 : DEF_CONST(GF_KEY_DEADCARON)
4320 77 : DEF_CONST(GF_KEY_DEADCEDILLA)
4321 77 : DEF_CONST(GF_KEY_DEADOGONEK)
4322 77 : DEF_CONST(GF_KEY_DEADIOTA)
4323 77 : DEF_CONST(GF_KEY_EURO)
4324 77 : DEF_CONST(GF_KEY_DEADVOICESOUND)
4325 77 : DEF_CONST(GF_KEY_DEADSEMIVOICESOUND)
4326 77 : DEF_CONST(GF_KEY_CHANNELUP)
4327 77 : DEF_CONST(GF_KEY_CHANNELDOWN)
4328 77 : DEF_CONST(GF_KEY_TEXT)
4329 77 : DEF_CONST(GF_KEY_INFO)
4330 77 : DEF_CONST(GF_KEY_EPG)
4331 77 : DEF_CONST(GF_KEY_RECORD)
4332 77 : DEF_CONST(GF_KEY_BEGINPAGE)
4333 77 : DEF_CONST(GF_KEY_CELL_SOFT1)
4334 77 : DEF_CONST(GF_KEY_CELL_SOFT2)
4335 77 : DEF_CONST(GF_KEY_JOYSTICK)
4336 :
4337 77 : DEF_CONST(GF_KEY_MOD_SHIFT)
4338 77 : DEF_CONST(GF_KEY_MOD_CTRL)
4339 77 : DEF_CONST(GF_KEY_MOD_ALT)
4340 77 : DEF_CONST(GF_KEY_EXT_NUMPAD)
4341 77 : DEF_CONST(GF_KEY_EXT_LEFT)
4342 77 : DEF_CONST(GF_KEY_EXT_RIGHT)
4343 :
4344 :
4345 77 : JS_SetPropertyStr(ctx, global_obj, "print", JS_NewCFunction(ctx, js_print, "print", 1));
4346 77 : JS_SetPropertyStr(ctx, global_obj, "alert", JS_NewCFunction(ctx, js_print, "alert", 1));
4347 :
4348 :
4349 : //initialize filter event class
4350 77 : JS_NewClassID(&jsf_event_class_id);
4351 77 : JS_NewClass(JS_GetRuntime(ctx), jsf_event_class_id, &jsf_event_class);
4352 77 : JSValue evt_proto = JS_NewObjectClass(ctx, jsf_event_class_id);
4353 77 : JS_SetPropertyFunctionList(ctx, evt_proto, jsf_event_funcs, countof(jsf_event_funcs));
4354 77 : JS_SetClassProto(ctx, jsf_event_class_id, evt_proto);
4355 :
4356 77 : JSValue evt_ctor = JS_NewCFunction2(ctx, jsf_event_constructor, "FilterEvent", 1, JS_CFUNC_constructor, 0);
4357 77 : JS_SetPropertyStr(ctx, global_obj, "FilterEvent", evt_ctor);
4358 :
4359 77 : }
4360 :
4361 42 : static GF_Err jsfilter_initialize_ex(GF_Filter *filter, JSContext *custom_ctx)
4362 : {
4363 : u8 *buf;
4364 : u32 buf_len;
4365 : u32 flags = JS_EVAL_TYPE_GLOBAL;
4366 : JSValue ret;
4367 : JSValue global_obj;
4368 : u32 i;
4369 : JSRuntime *rt;
4370 42 : GF_JSFilterCtx *jsf = gf_filter_get_udta(filter);
4371 :
4372 42 : if (custom_ctx) {
4373 1 : GF_SAFEALLOC(jsf, GF_JSFilterCtx);
4374 1 : filter->filter_udta = jsf;
4375 : }
4376 :
4377 42 : jsf->filter = filter;
4378 42 : jsf->pids = gf_list_new();
4379 42 : jsf->pck_res = gf_list_new();
4380 42 : jsf->log_name = gf_strdup(custom_ctx ? filter->name : "JSF");
4381 :
4382 42 : if (custom_ctx) {
4383 1 : jsf->ctx = custom_ctx;
4384 1 : jsf->is_custom = GF_TRUE;
4385 1 : global_obj = JS_GetGlobalObject(jsf->ctx);
4386 : } else {
4387 41 : if (!jsf->js) {
4388 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Missing script file\n"));
4389 : return GF_BAD_PARAM;
4390 : }
4391 41 : if (!gf_file_exists(jsf->js)) {
4392 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Script file %s does not exist\n", jsf->js));
4393 : return GF_BAD_PARAM;
4394 : }
4395 41 : jsf->filter_obj = JS_UNDEFINED;
4396 :
4397 41 : jsf->ctx = gf_js_create_context();
4398 41 : if (!jsf->ctx) {
4399 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Failed to load QuickJS context\n"));
4400 : return GF_IO_ERR;
4401 : }
4402 41 : JS_SetContextOpaque(jsf->ctx, jsf);
4403 41 : global_obj = JS_GetGlobalObject(jsf->ctx);
4404 41 : js_load_constants(jsf->ctx, global_obj);
4405 : }
4406 42 : rt = JS_GetRuntime(jsf->ctx);
4407 :
4408 :
4409 :
4410 : //initialize filter class and create a single filter object in global scope
4411 42 : JS_NewClassID(&jsf_filter_class_id);
4412 42 : JS_NewClass(rt, jsf_filter_class_id, &jsf_filter_class);
4413 :
4414 42 : jsf->filter_obj = JS_NewObjectClass(jsf->ctx, jsf_filter_class_id);
4415 42 : JS_SetPropertyFunctionList(jsf->ctx, jsf->filter_obj, jsf_filter_funcs, countof(jsf_filter_funcs));
4416 42 : JS_SetOpaque(jsf->filter_obj, jsf);
4417 42 : if (!custom_ctx)
4418 41 : JS_SetPropertyStr(jsf->ctx, global_obj, "filter", jsf->filter_obj);
4419 :
4420 : //initialize filter instance class
4421 42 : JS_NewClassID(&jsf_filter_inst_class_id);
4422 42 : JS_NewClass(rt, jsf_filter_inst_class_id, &jsf_filter_inst_class);
4423 42 : JSValue finst_proto = JS_NewObjectClass(jsf->ctx, jsf_filter_inst_class_id);
4424 42 : JS_SetPropertyFunctionList(jsf->ctx, finst_proto, jsf_filter_inst_funcs, countof(jsf_filter_inst_funcs));
4425 42 : JS_SetClassProto(jsf->ctx, jsf_filter_inst_class_id, finst_proto);
4426 :
4427 : //initialize filter pid class
4428 42 : JS_NewClassID(&jsf_pid_class_id);
4429 42 : JS_NewClass(rt, jsf_pid_class_id, &jsf_pid_class);
4430 42 : JSValue pid_proto = JS_NewObjectClass(jsf->ctx, jsf_pid_class_id);
4431 42 : JS_SetPropertyFunctionList(jsf->ctx, pid_proto, jsf_pid_funcs, countof(jsf_pid_funcs));
4432 42 : JS_SetClassProto(jsf->ctx, jsf_pid_class_id, pid_proto);
4433 :
4434 :
4435 : //initialize filter packet class
4436 42 : JS_NewClassID(&jsf_pck_class_id);
4437 42 : JS_NewClass(rt, jsf_pck_class_id, &jsf_pck_class);
4438 42 : JSValue pck_proto = JS_NewObjectClass(jsf->ctx, jsf_pck_class_id);
4439 42 : JS_SetPropertyFunctionList(jsf->ctx, pck_proto, jsf_pck_funcs, countof(jsf_pck_funcs));
4440 42 : JS_SetClassProto(jsf->ctx, jsf_pck_class_id, pck_proto);
4441 :
4442 42 : if (!custom_ctx)
4443 41 : JS_SetPropertyStr(jsf->ctx, global_obj, "_gpac_log_name", JS_NewString(jsf->ctx, gf_file_basename(jsf->js) ) );
4444 :
4445 42 : JS_FreeValue(jsf->ctx, global_obj);
4446 :
4447 42 : if (custom_ctx) return GF_OK;
4448 :
4449 :
4450 : //load script
4451 41 : GF_Err e = gf_file_load_data(jsf->js, &buf, &buf_len);
4452 41 : if (e) {
4453 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Error loading script file %s: %s\n", jsf->js, gf_error_to_string(e) ));
4454 : return e;
4455 : }
4456 :
4457 41 : if (strstr(buf, "session.")) {
4458 : GF_Err gf_fs_load_js_api(JSContext *c, GF_FilterSession *fs);
4459 : // GF_FilterSession *fs = sjs->compositor->filter->session;
4460 :
4461 0 : e = gf_fs_load_js_api(jsf->ctx, filter->session);
4462 0 : if (e) {
4463 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Error loading session API: %s\n", gf_error_to_string(e) ));
4464 : return e;
4465 : }
4466 0 : jsf->unload_session_api = GF_TRUE;
4467 : }
4468 :
4469 410 : for (i=0; i<JSF_EVT_LAST_DEFINED; i++) {
4470 410 : jsf->funcs[i] = JS_UNDEFINED;
4471 : }
4472 :
4473 :
4474 41 : if (!gf_opts_get_bool("core", "no-js-mods") && JS_DetectModule((char *)buf, buf_len)) {
4475 : //init modules
4476 33 : qjs_module_init_gpaccore(jsf->ctx);
4477 33 : qjs_module_init_xhr(jsf->ctx);
4478 33 : qjs_module_init_evg(jsf->ctx);
4479 33 : qjs_module_init_storage(jsf->ctx);
4480 33 : qjs_module_init_webgl(jsf->ctx);
4481 : flags = JS_EVAL_TYPE_MODULE;
4482 : }
4483 41 : jsf->disable_filter = GF_TRUE;
4484 41 : ret = JS_Eval(jsf->ctx, (char *)buf, buf_len, jsf->js, flags);
4485 41 : gf_free(buf);
4486 :
4487 41 : if (JS_IsException(ret)) {
4488 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Error loading script %s\n", jsf->js));
4489 0 : js_dump_error(jsf->ctx);
4490 0 : JS_FreeValue(jsf->ctx, ret);
4491 : return GF_BAD_PARAM;
4492 : }
4493 41 : JS_FreeValue(jsf->ctx, ret);
4494 : return GF_OK;
4495 : }
4496 :
4497 :
4498 41 : static GF_Err jsfilter_initialize(GF_Filter *filter)
4499 : {
4500 41 : return jsfilter_initialize_ex(filter, NULL);
4501 : }
4502 :
4503 42 : static void jsfilter_finalize(GF_Filter *filter)
4504 : {
4505 : u32 i, count;
4506 42 : GF_JSFilterCtx *jsf = gf_filter_get_udta(filter);
4507 42 : if (!jsf->ctx) return;
4508 :
4509 : //reset references but do not destroy PIDs yet
4510 42 : count = gf_list_count(jsf->pids);
4511 88 : for (i=0; i<count; i++) {
4512 46 : GF_JSPidCtx *pctx = gf_list_get(jsf->pids, i);
4513 46 : JS_FreeValue(jsf->ctx, pctx->jsobj);
4514 46 : if (pctx->shared_pck) {
4515 2 : while (gf_list_count(pctx->shared_pck)) {
4516 0 : GF_JSPckCtx *pckc = gf_list_pop_back(pctx->shared_pck);
4517 0 : JS_FreeValue(jsf->ctx, pckc->ref_val);
4518 0 : pckc->ref_val = JS_UNDEFINED;
4519 0 : jsf_pck_detach_ab(jsf->ctx, pckc);
4520 :
4521 : //do not free here since pck->jsobj may already have been GCed/destroyed
4522 : }
4523 : }
4524 : }
4525 :
4526 420 : for (i=0; i<JSF_EVT_LAST_DEFINED; i++) {
4527 420 : JS_FreeValue(jsf->ctx, jsf->funcs[i]);
4528 : }
4529 :
4530 42 : JS_SetOpaque(jsf->filter_obj, NULL);
4531 :
4532 42 : if (jsf->unload_session_api)
4533 0 : gf_fs_unload_script(filter->session, jsf->ctx);
4534 :
4535 42 : if (!jsf->is_custom)
4536 41 : gf_js_delete_context(jsf->ctx);
4537 :
4538 88 : while (gf_list_count(jsf->pids)) {
4539 46 : GF_JSPidCtx *pctx = gf_list_pop_back(jsf->pids);
4540 46 : if (pctx->shared_pck)
4541 2 : gf_list_del(pctx->shared_pck);
4542 46 : gf_free(pctx);
4543 : }
4544 42 : gf_list_del(jsf->pids);
4545 :
4546 42 : if (jsf->log_name) gf_free(jsf->log_name);
4547 :
4548 78 : while (gf_list_count(jsf->pck_res)) {
4549 36 : GF_JSPckCtx *pck = gf_list_pop_back(jsf->pck_res);
4550 36 : gf_free(pck);
4551 : }
4552 42 : gf_list_del(jsf->pck_res);
4553 :
4554 42 : if (jsf->args) {
4555 146 : for (i=0; i<jsf->nb_args; i++) {
4556 146 : if (jsf->args[i].arg_default_val)
4557 132 : gf_free((char *) jsf->args[i].arg_default_val);
4558 146 : if (jsf->args[i].arg_desc)
4559 146 : gf_free((char *) jsf->args[i].arg_desc);
4560 146 : if (jsf->args[i].arg_name)
4561 146 : gf_free((char *) jsf->args[i].arg_name);
4562 146 : if (jsf->args[i].min_max_enum)
4563 10 : gf_free((char *) jsf->args[i].min_max_enum);
4564 : }
4565 36 : gf_free(jsf->args);
4566 : }
4567 :
4568 42 : if (jsf->caps) gf_free(jsf->caps);
4569 : }
4570 :
4571 :
4572 :
4573 200 : static GF_Err jsfilter_update_arg(GF_Filter *filter, const char *arg_name, const GF_PropertyValue *new_val)
4574 : {
4575 200 : GF_JSFilterCtx *jsf = gf_filter_get_udta(filter);
4576 : JSValue ret, val;
4577 : const GF_FilterArgs *the_arg = NULL;
4578 : u32 i;
4579 200 : GF_Err e = GF_OK;
4580 200 : if (!jsf->ctx)
4581 : return GF_OK;
4582 :
4583 200 : if (!arg_name && !new_val) {
4584 41 : gf_js_lock(jsf->ctx, GF_TRUE);
4585 41 : if (JS_IsFunction(jsf->ctx, jsf->funcs[JSF_EVT_INITIALIZE]) ) {
4586 41 : ret = JS_Call(jsf->ctx, jsf->funcs[JSF_EVT_INITIALIZE], jsf->filter_obj, 0, NULL);
4587 41 : if (JS_IsException(ret)) {
4588 1 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error initializing filter\n", jsf->log_name));
4589 1 : js_dump_error(jsf->ctx);
4590 1 : JS_FreeValue(jsf->ctx, ret);
4591 1 : gf_js_lock(jsf->ctx, GF_FALSE);
4592 1 : return GF_BAD_PARAM;
4593 : }
4594 40 : if (JS_IsInteger(ret))
4595 1 : JS_ToInt32(jsf->ctx, (int*)&e, ret);
4596 :
4597 40 : JS_FreeValue(jsf->ctx, ret);
4598 : }
4599 40 : jsf->initialized = GF_TRUE;
4600 : //we still call initialize even in help-only mode to properly print links and cap bundles
4601 40 : if (gf_opts_get_bool("temp", "helponly"))
4602 6 : jsf->disable_filter = GF_TRUE;
4603 :
4604 : //filter object not used (no new_pid, post_task or set_cap), disable it
4605 40 : if (jsf->disable_filter) {
4606 : JSAtom prop;
4607 10 : JSValue global_obj = JS_GetGlobalObject(jsf->ctx);
4608 10 : prop = JS_NewAtom(jsf->ctx, "filter");
4609 10 : JS_DeleteProperty(jsf->ctx, global_obj, prop, 0);
4610 10 : JS_FreeValue(jsf->ctx, global_obj);
4611 10 : JS_FreeAtom(jsf->ctx, prop);
4612 10 : filter->disabled = GF_TRUE;
4613 10 : jsf->filter_obj = JS_UNDEFINED;
4614 : }
4615 40 : gf_js_lock(jsf->ctx, GF_FALSE);
4616 40 : return e;
4617 : }
4618 159 : if (!arg_name || (jsf->initialized && jsf->disable_filter))
4619 : return GF_OK;
4620 :
4621 875 : for (i=0; i<jsf->nb_args; i++) {
4622 1034 : if (jsf->args[i].arg_name && !strcmp(jsf->args[i].arg_name, arg_name)) {
4623 : the_arg = &jsf->args[i];
4624 : break;
4625 : }
4626 : }
4627 159 : if (!the_arg && !jsf->has_wilcard_arg) return GF_OK;
4628 :
4629 159 : gf_js_lock(jsf->ctx, GF_TRUE);
4630 :
4631 159 : val = jsf_NewProp(jsf->ctx, new_val);
4632 159 : if (!jsf->initialized) {
4633 159 : JS_SetPropertyStr(jsf->ctx, jsf->filter_obj, arg_name, val);
4634 159 : gf_js_lock(jsf->ctx, GF_FALSE);
4635 159 : return GF_OK;
4636 : }
4637 :
4638 : JSValue args[2];
4639 0 : args[0] = JS_NewString(jsf->ctx, arg_name);
4640 0 : args[1] = val;
4641 0 : ret = JS_Call(jsf->ctx, jsf->funcs[JSF_EVT_UPDATE_ARG], jsf->filter_obj, 2, args);
4642 0 : if (JS_IsException(ret)) {
4643 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error updating arg\n", jsf->log_name));
4644 0 : js_dump_error(jsf->ctx);
4645 0 : e = GF_BAD_PARAM;
4646 : }
4647 0 : if (JS_IsInteger(ret))
4648 0 : JS_ToInt32(jsf->ctx, (int*)&e, ret);
4649 0 : JS_FreeValue(jsf->ctx, ret);
4650 0 : JS_FreeValue(jsf->ctx, args[0]);
4651 0 : JS_FreeValue(jsf->ctx, args[1]);
4652 0 : gf_js_lock(jsf->ctx, GF_FALSE);
4653 0 : return e;
4654 : }
4655 :
4656 412 : JSValue js_init_evt_obj(JSContext *ctx, const GF_FilterEvent *evt)
4657 : {
4658 412 : JSValue v = JS_NewObjectClass(ctx, jsf_event_class_id);
4659 412 : JS_SetOpaque(v, (void *) evt);
4660 412 : return v;
4661 : }
4662 :
4663 996 : static Bool jsfilter_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
4664 : {
4665 : JSValue argv[2];
4666 : JSValue ret;
4667 : Bool canceled=GF_TRUE;
4668 996 : GF_JSFilterCtx *jsf = gf_filter_get_udta(filter);
4669 996 : if (!jsf) return GF_TRUE;
4670 :
4671 996 : if (!JS_IsFunction(jsf->ctx, jsf->funcs[JSF_EVT_PROCESS_EVENT]))
4672 : return GF_FALSE;
4673 :
4674 327 : gf_js_lock(jsf->ctx, GF_TRUE);
4675 327 : if (evt->base.on_pid) {
4676 326 : GF_JSPidCtx *pctx = gf_filter_pid_get_udta(evt->base.on_pid);
4677 652 : argv[0] = pctx ? JS_DupValue(jsf->ctx, pctx->jsobj) : JS_NULL;
4678 : } else {
4679 1 : argv[0] = JS_NULL;
4680 : }
4681 327 : argv[1] = js_init_evt_obj(jsf->ctx, evt);
4682 :
4683 327 : ret = JS_Call(jsf->ctx, jsf->funcs[JSF_EVT_PROCESS_EVENT], jsf->filter_obj, 2, argv);
4684 327 : if (JS_IsException(ret)) {
4685 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error processing event\n", jsf->log_name));
4686 0 : js_dump_error(jsf->ctx);
4687 : }
4688 : else {
4689 327 : canceled = JS_ToBool(jsf->ctx, ret);
4690 : }
4691 327 : JS_FreeValue(jsf->ctx, ret);
4692 327 : JS_FreeValue(jsf->ctx, argv[0]);
4693 327 : JS_SetOpaque(argv[1], NULL);
4694 327 : JS_FreeValue(jsf->ctx, argv[1]);
4695 327 : gf_js_lock(jsf->ctx, GF_FALSE);
4696 :
4697 327 : js_do_loop(jsf->ctx);
4698 327 : return canceled;
4699 : }
4700 :
4701 : /*static GF_Err jsfilter_reconfigure_output(GF_Filter *filter, GF_FilterPid *PID)
4702 : {
4703 : return GF_NOT_SUPPORTED;
4704 : }
4705 :
4706 : static GF_FilterProbeScore jsfilter_probe_url(const char *url, const char *mime)
4707 : {
4708 : return GF_FPROBE_NOT_SUPPORTED;
4709 : }
4710 :
4711 : static const char * jsfilter_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
4712 : {
4713 : return NULL;
4714 : }
4715 : */
4716 :
4717 : #define OFFS(_n) #_n, offsetof(GF_JSFilterCtx, _n)
4718 : static GF_FilterArgs JSFilterArgs[] =
4719 : {
4720 : { OFFS(js), "location of script source", GF_PROP_NAME, NULL, NULL, 0},
4721 : { "*", -1, "any possible options defined for the script. See `gpac -hx jsf:js=$YOURSCRIPT`", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_META},
4722 : {0}
4723 : };
4724 :
4725 : static const GF_FilterCapability JSFilterCaps[] =
4726 : {
4727 : CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_UNKNOWN),
4728 : CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_UNKNOWN),
4729 : };
4730 :
4731 : GF_FilterRegister JSFilterRegister = {
4732 : .name = "jsf",
4733 : GF_FS_SET_DESCRIPTION("JavaScript filter")
4734 : GF_FS_SET_HELP("This filter runs a javascript file specified in [-js]() defining a new JavaScript filter.\n"
4735 : " \n"
4736 : "For more information on how to use JS filters, please check https://wiki.gpac.io/jsfilter\n")
4737 : .private_size = sizeof(GF_JSFilterCtx),
4738 : .flags = GF_FS_REG_SCRIPT,
4739 : .args = JSFilterArgs,
4740 : SETCAPS(JSFilterCaps),
4741 : .initialize = jsfilter_initialize,
4742 : .finalize = jsfilter_finalize,
4743 : .configure_pid = jsfilter_configure_pid,
4744 : .process = jsfilter_process,
4745 : .update_arg = jsfilter_update_arg,
4746 : .process_event = jsfilter_process_event,
4747 : // .probe_url = jsfilter_probe_url,
4748 : // .probe_data = jsfilter_probe_data
4749 : // .reconfigure_output = jsfilter_reconfigure_output
4750 : };
4751 :
4752 :
4753 2877 : const GF_FilterRegister *jsfilter_register(GF_FilterSession *session)
4754 : {
4755 2877 : return &JSFilterRegister;
4756 : }
4757 :
4758 :
4759 1 : JSValue jsfilter_initialize_custom(GF_Filter *filter, JSContext *ctx)
4760 : {
4761 : GF_JSFilterCtx *jsf;
4762 1 : GF_Err e = jsfilter_initialize_ex(filter, ctx);
4763 1 : if (e) return js_throw_err(ctx, e);
4764 1 : jsf = gf_filter_get_udta(filter);
4765 1 : ((GF_FilterRegister *) filter->freg)->finalize = jsfilter_finalize;
4766 1 : ((GF_FilterRegister *) filter->freg)->process = jsfilter_process;
4767 1 : ((GF_FilterRegister *) filter->freg)->configure_pid = jsfilter_configure_pid;
4768 1 : ((GF_FilterRegister *) filter->freg)->process_event = jsfilter_process_event;
4769 : // ((GF_FilterRegister *) filter->freg)->reconfigure_output = jsfilter_reconfigure_output;
4770 : // ((GF_FilterRegister *) filter->freg)->probe_data = jsfilter_probe_data;
4771 : //signal reg is script, so we don't free the filter reg caps as with custom filters
4772 1 : ((GF_FilterRegister *) filter->freg)->flags |= GF_FS_REG_SCRIPT;
4773 1 : return jsf->filter_obj;
4774 : }
4775 :
4776 : #else
4777 :
4778 : const GF_FilterRegister *jsfilter_register(GF_FilterSession *session)
4779 : {
4780 : return NULL;
4781 : }
4782 :
4783 : #endif
4784 :
|