Coverage Report

Created: 2026-10-16 08:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/src/utils/module.c
Line
Count
Source
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2026
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / common tools sub-project
9
 *
10
 *  GPAC is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU Lesser General Public License as published by
12
 *  the Free Software Foundation; either version 2, or (at your option)
13
 *  any later version.
14
 *
15
 *  GPAC is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU Lesser General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU Lesser General Public
21
 *  License along with this library; see the file COPYING.  If not, write to
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
 *
24
 */
25
26
#include "module_wrap.h"
27
#include <gpac/config_file.h>
28
#include <gpac/tools.h>
29
#include <gpac/network.h>
30
31
32
33
#ifndef GPAC_MODULE_CUSTOM_LOAD
34
static void load_all_modules(GF_ModuleManager *mgr)
35
0
{
36
0
#define LOAD_PLUGIN(  __name  ) { \
37
0
  GF_InterfaceRegister *gf_register_module_##__name();  \
38
0
  pr = gf_register_module_##__name();\
39
0
  if (!pr) {\
40
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to statically load module ##__name\n"));\
41
0
  } else {\
42
0
    gf_list_add(mgr->plugin_registry, pr);  \
43
0
  }  \
44
0
  }
45
46
0
#ifdef GPAC_STATIC_MODULES
47
0
  GF_InterfaceRegister *pr;
48
49
#ifdef GPAC_HAS_SDL
50
  LOAD_PLUGIN(sdl_out);
51
#endif
52
53
#if defined(GPAC_HAS_FREETYPE) && !defined(GPAC_DISABLE_EVG)
54
  LOAD_PLUGIN(ftfont);
55
#endif
56
#ifdef GPAC_HAS_ALSA
57
  LOAD_PLUGIN(alsa);
58
#endif
59
60
#ifdef GPAC_HAS_DIRECTFB
61
  LOAD_PLUGIN(directfb_out);
62
#endif
63
64
#ifdef GPAC_HAS_DIRECTX
65
  LOAD_PLUGIN(dx_out);
66
#endif
67
68
#ifdef GPAC_HAS_JACK
69
  LOAD_PLUGIN(jack);
70
#endif
71
72
#ifdef GPAC_HAS_OSS
73
  LOAD_PLUGIN(oss);
74
#endif
75
76
#ifdef GPAC_HAS_PULSEAUDIO
77
  LOAD_PLUGIN(pulseaudio);
78
#endif
79
80
0
#ifndef GPAC_DISABLE_COMPOSITOR
81
0
  LOAD_PLUGIN(validator);
82
0
#endif
83
84
85
#ifdef GPAC_HAS_WAVEOUT
86
  LOAD_PLUGIN(wave_out);
87
#endif
88
89
#ifdef GPAC_HAS_X11
90
  LOAD_PLUGIN(x11_out);
91
#endif
92
93
  //todo fix project for iOS
94
#ifdef GPAC_CONFIG_IOS
95
  //these do not compile with xcode 4.2
96
//    LOAD_PLUGIN(ios_cam);
97
//    LOAD_PLUGIN(ios_mpegv);
98
#endif
99
100
0
#endif //GPAC_STATIC_MODULES
101
102
0
#undef LOAD_PLUGIN
103
104
0
}
105
#endif //GPAC_MODULE_CUSTOM_LOAD
106
107
GF_ModuleManager *gpac_modules_static = NULL;
108
109
GF_EXPORT
110
GF_Err gf_module_load_static(GF_InterfaceRegister *(*register_module)())
111
0
{
112
0
  GF_InterfaceRegister *pr;
113
0
  GF_Err rc;
114
0
  if (register_module == NULL)
115
0
    return GF_OK;
116
117
0
  pr = register_module();
118
0
  if (!pr) {
119
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to statically loaded module\n"));
120
0
    return GF_NOT_SUPPORTED;
121
0
  }
122
123
0
  rc = gf_list_add(gpac_modules_static->plugin_registry, pr);
124
0
  if (rc != GF_OK) {
125
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to statically loaded module\n"));
126
0
    return rc;
127
0
  }
128
0
  return GF_OK;
129
0
}
130
131
u32 gf_modules_refresh(GF_ModuleManager *pm);
132
133
static void gf_modules_check_load()
134
0
{
135
0
  if (gpac_modules_static->needs_load) {
136
0
    gpac_modules_static->needs_load = GF_FALSE;
137
0
#ifndef GPAC_MODULE_CUSTOM_LOAD
138
0
    load_all_modules(gpac_modules_static);
139
0
#endif
140
0
    gf_modules_refresh(gpac_modules_static);
141
0
    GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("Loaded %d modules.\n", gf_modules_count() ));
142
0
  }
143
0
}
144
145
146
void gf_modules_refresh_module_directories()
147
0
{
148
0
  char* directories;
149
0
  char* tmp_dirs;
150
0
  char * pch;
151
0
  u32 i;
152
0
  GF_ModuleManager *pm = gpac_modules_static;
153
0
  if (!pm) return;
154
155
0
  for (i=0; i<pm->num_dirs; i++) {
156
0
    gf_free(pm->dirs[i]);
157
0
  }
158
0
  pm->num_dirs = 0;
159
160
  //default module directory
161
0
  directories = (char*)gf_opts_get_key("core", "module-dir");
162
0
  if (directories) {
163
0
    pm->dirs[0] = gf_strdup(directories);
164
0
    pm->num_dirs = 1;
165
0
  }
166
167
  /* User-defined directories*/
168
0
  directories = (char*)gf_opts_get_key("core", "mod-dirs");
169
0
  if (! directories) {
170
0
    if (!pm->num_dirs) {
171
0
#ifndef GPAC_CONFIG_IOS
172
0
      GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("Modules directories not found - check the \"module-dir\" key is set in the \"core\" section\n"));
173
0
#endif
174
0
    }
175
0
    return;
176
0
  }
177
178
0
  tmp_dirs = directories;
179
0
  pch = strtok (tmp_dirs,";");
180
181
0
  while (pch != NULL) {
182
0
    if (pm->num_dirs == MAX_MODULE_DIRS) {
183
0
      GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("Reach maximum number of module directories %d.\n", MAX_MODULE_DIRS));
184
0
      break;
185
0
    }
186
0
    pm->dirs[pm->num_dirs] = gf_strdup(pch);
187
0
    pm->num_dirs++;
188
0
    pch = strtok (NULL, ";");
189
0
  }
190
0
}
191
192
193
/*!
194
\brief module manager construtcor
195
 *
196
 *Constructs a module manager object.
197
\param config GPAC configuration file handle. If this is NULL, the modules won't be able to share the configuration
198
 *file with the rest of the GPAC framework.
199
*/
200
void gf_modules_new(GF_Config *config)
201
0
{
202
0
  const char *opt;
203
0
  if (!config) return;
204
0
  if (gpac_modules_static) return;
205
206
  /* Try to resolve directory from config file */
207
0
  GF_SAFEALLOC(gpac_modules_static, GF_ModuleManager);
208
0
  if (!gpac_modules_static) return;
209
0
  gpac_modules_static->cfg = config;
210
0
  gpac_modules_static->mutex = gf_mx_new("Module Manager");
211
0
  gf_modules_refresh_module_directories();
212
213
  /* Initialize module list */
214
0
  gpac_modules_static->plug_list = gf_list_new();
215
0
  if (!gpac_modules_static->plug_list) {
216
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("OUT OF MEMORY, cannot create list of modules !!!\n"));
217
0
    gf_free(gpac_modules_static);
218
0
    gpac_modules_static = NULL;
219
0
    return;
220
0
  }
221
0
  gpac_modules_static->plugin_registry = gf_list_new();
222
0
  if (!gpac_modules_static->plugin_registry) {
223
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("OUT OF MEMORY, cannot create list of static module registers !!!\n"));
224
0
    gf_list_del(gpac_modules_static->plug_list);
225
0
    gf_free(gpac_modules_static);
226
0
    gpac_modules_static = NULL;
227
0
    return;
228
0
  }
229
230
0
  gpac_modules_static->no_unload = !gf_opts_get_bool("core", "mod-reload");
231
232
0
  opt = gf_opts_get_key("core", "version");
233
0
  if (!opt || strcmp(opt, gf_gpac_version())) {
234
0
    gf_cfg_del_section(config, "PluginsCache");
235
0
    gf_opts_set_key("core", "version", gf_gpac_version());
236
0
  }
237
238
0
  gpac_modules_static->needs_load = GF_TRUE;
239
0
}
240
241
242
void gf_module_reload_dirs()
243
0
{
244
0
  if (!gpac_modules_static) return;
245
0
  gf_modules_refresh_module_directories();
246
0
  gpac_modules_static->needs_load = GF_TRUE;
247
0
}
248
249
250
/*!
251
\brief module manager destructor
252
 *
253
 *Destroys the module manager
254
 */
255
void gf_modules_del()
256
0
{
257
0
  u32 i;
258
0
  GF_ModuleManager *pm = gpac_modules_static;
259
0
  if (!pm) return;
260
261
0
  gpac_modules_static = NULL;
262
263
  /*unload all modules*/
264
0
  while (gf_list_count(pm->plug_list)) {
265
0
    ModuleInstance *inst = (ModuleInstance *) gf_list_get(pm->plug_list, 0);
266
0
    gf_modules_free_module(inst);
267
0
    gf_list_rem(pm->plug_list, 0);
268
0
  }
269
0
  gf_list_del(pm->plug_list);
270
271
  /* Delete module directories*/
272
0
  for (i = 0; i < pm->num_dirs; i++) {
273
0
    gf_free((void*)pm->dirs[i]);
274
0
  }
275
276
  /*remove all static modules registry*/
277
0
  while (gf_list_count(pm->plugin_registry)) {
278
0
    GF_InterfaceRegister *reg  = (GF_InterfaceRegister *) gf_list_get(pm->plugin_registry, 0);
279
0
    gf_free(reg);
280
0
    gf_list_rem(pm->plugin_registry, 0);
281
0
  }
282
283
0
  if (pm->plugin_registry) gf_list_del(pm->plugin_registry);
284
0
  gf_mx_del(pm->mutex);
285
0
  gf_free(pm);
286
0
}
287
288
Bool gf_module_is_loaded(GF_ModuleManager *pm, char *filename)
289
0
{
290
0
  u32 i = 0;
291
0
  ModuleInstance *inst;
292
0
  while ( (inst = (ModuleInstance *) gf_list_enum(pm->plug_list, &i) ) ) {
293
0
    if (!strcmp(inst->name, filename)) return GF_TRUE;
294
0
  }
295
0
  return GF_FALSE;
296
0
}
297
298
GF_EXPORT
299
u32 gf_modules_count()
300
1.45k
{
301
1.45k
  if (!gpac_modules_static) return 0;
302
0
  gf_modules_check_load();
303
0
  return gf_list_count(gpac_modules_static->plug_list);
304
1.45k
}
305
306
307
GF_EXPORT
308
GF_BaseInterface *gf_modules_load(u32 whichplug, u32 InterfaceFamily)
309
0
{
310
0
  const char *opt;
311
0
  char szKey[32];
312
0
  ModuleInstance *inst;
313
0
  GF_BaseInterface *ifce;
314
0
  GF_ModuleManager *pm = gpac_modules_static;
315
316
0
  if (!pm) {
317
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] gf_modules_load() : No Module Manager set\n"));
318
0
    return NULL;
319
0
  }
320
321
0
  gf_mx_p(pm->mutex);
322
323
0
  gf_modules_check_load();
324
325
0
  inst = (ModuleInstance *) gf_list_get(pm->plug_list, whichplug);
326
0
  if (!inst) {
327
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] gf_modules_load() : no module %d exist.\n", whichplug));
328
0
    gf_mx_v(pm->mutex);
329
0
    return NULL;
330
0
  }
331
0
  GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Load interface...%s\n", inst->name));
332
  /*look in cache*/
333
0
  if (!pm->cfg) {
334
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] No pm->cfg has been set !!!\n"));
335
0
    gf_mx_v(pm->mutex);
336
0
    return NULL;
337
0
  }
338
0
  opt = gf_cfg_get_key(pm->cfg, "PluginsCache", inst->name);
339
0
  if (opt) {
340
0
    const char * ifce_str = gf_4cc_to_str(InterfaceFamily);
341
0
    snprintf(szKey, 32, "%s:yes", ifce_str ? ifce_str : "(null)");
342
0
    if (!strstr(opt, szKey)) {
343
      //cleanup if version changed
344
0
      szKey[3] = 0;
345
0
      char *val = strstr(opt, szKey);
346
0
      if (val && !strncmp(val+4, ":yes", 4)) {
347
0
        gf_cfg_set_key(pm->cfg, "PluginsCache", inst->name, NULL);
348
0
      } else {
349
0
        gf_mx_v(pm->mutex);
350
0
        return NULL;
351
0
      }
352
0
    }
353
0
  }
354
0
  if (!gf_modules_load_library(inst)) {
355
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load library %s\n", inst->name));
356
0
    gf_cfg_set_key(pm->cfg, "PluginsCache", inst->name, "invalid");
357
0
    gf_mx_v(pm->mutex);
358
0
    return NULL;
359
0
  }
360
0
  if (!inst->query_func) {
361
0
    if (!inst->filterreg_func) {
362
0
      GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Library %s missing GPAC export symbols\n", inst->name));
363
0
      gf_cfg_set_key(pm->cfg, "PluginsCache", inst->name, "invalid");
364
0
    }
365
0
    goto err_exit;
366
0
  }
367
368
  /*build cache*/
369
0
  if (!opt) {
370
0
    u32 i;
371
0
    const int maxKeySize = 32;
372
0
    Bool found = GF_FALSE;
373
0
    char *key;
374
0
    const u32 *si = inst->query_func();
375
0
    if (!si) {
376
0
      GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[Core] GPAC module %s has no supported interfaces - disabling\n", inst->name));
377
0
      gf_cfg_set_key(pm->cfg, "PluginsCache", inst->name, "invalid");
378
0
      goto err_exit;
379
0
    }
380
0
    i=0;
381
0
    while (si[i]) i++;
382
383
0
    key = NULL;
384
0
    i=0;
385
0
    while (si[i]) {
386
0
      snprintf(szKey, maxKeySize, "%s:yes ", gf_4cc_to_str(si[i]));
387
0
      gf_dynstrcat(&key, szKey, NULL);
388
0
      if (InterfaceFamily==si[i]) found = GF_TRUE;
389
0
      i++;
390
0
    }
391
0
    gf_dynstrcat(&key, inst->filterreg_func ? "GFR1:yes" : "GFR1:no", NULL);
392
393
0
    gf_cfg_set_key(pm->cfg, "PluginsCache", inst->name, key);
394
0
    gf_free(key);
395
0
    if (!found) goto err_exit;
396
0
  }
397
398
0
  if (!inst->load_func) goto err_exit;
399
0
  ifce = (GF_BaseInterface *) inst->load_func(InterfaceFamily);
400
  /*sanity check*/
401
0
  if (!ifce) goto err_exit;
402
0
  if (!ifce->module_name || (ifce->InterfaceType != InterfaceFamily)) {
403
0
    inst->destroy_func(ifce);
404
0
    goto err_exit;
405
0
  }
406
0
  gf_list_add(inst->interfaces, ifce);
407
  /*keep track of parent*/
408
0
  ifce->HPLUG = inst;
409
0
  GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Load interface %s DONE.\n", inst->name));
410
0
  gf_mx_v(pm->mutex);
411
0
  return ifce;
412
413
0
err_exit:
414
0
  GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Load interface %s exit label, freeing library...\n", inst->name));
415
0
  gf_modules_unload_library(inst);
416
0
  GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Load interface %s EXIT.\n", inst->name));
417
0
  gf_mx_v(pm->mutex);
418
0
  return NULL;
419
0
}
420
421
void *gf_modules_load_filter(u32 whichplug, void *fsess)
422
0
{
423
0
  const char *opt;
424
0
  ModuleInstance *inst;
425
0
  void *freg = NULL;
426
0
  GF_ModuleManager *pm = gpac_modules_static;
427
0
  if (!pm) return NULL;
428
0
  gf_modules_check_load();
429
430
0
  inst = (ModuleInstance *) gf_list_get(pm->plug_list, whichplug);
431
0
  if (!inst) {
432
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] gf_modules_load() : no module %d exist.\n", whichplug));
433
0
    return NULL;
434
0
  }
435
0
  if (strncmp(inst->name, "gf_", 3))
436
0
    return NULL;
437
0
  opt = gf_cfg_get_key(pm->cfg, "PluginsCache", inst->name);
438
0
  if (opt) {
439
0
    if (!strcmp(opt, "invalid")) return NULL;
440
0
    if (!strstr(opt, "GFR1:yes")) return NULL;
441
0
  }
442
0
  if (!gf_modules_load_library(inst)) {
443
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load library %s\n", inst->name));
444
0
    gf_cfg_set_key(pm->cfg, "PluginsCache", inst->name, "invalid");
445
0
    return NULL;
446
0
  }
447
0
  freg = NULL;
448
0
  if (inst->filterreg_func) {
449
0
    freg = inst->filterreg_func(fsess);
450
0
  }
451
0
  if (!freg) {
452
0
    gf_modules_unload_library(inst);
453
0
  }
454
0
  return freg;
455
0
}
456
457
GF_EXPORT
458
GF_BaseInterface *gf_modules_load_by_name(const char *plug_name, u32 InterfaceFamily, Bool rebrowse_all)
459
0
{
460
0
  const char *file_name;
461
0
  u32 i, count;
462
0
  GF_BaseInterface *ifce;
463
0
  GF_ModuleManager *pm = gpac_modules_static;
464
0
  if (!pm || !plug_name || !pm->plug_list || !pm->cfg) {
465
0
    GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] gf_modules_load_by_name has bad parameters pm=%p, plug_name=%s.\n", pm, plug_name));
466
0
    return NULL;
467
0
  }
468
469
0
  gf_modules_check_load();
470
471
0
  count = gf_list_count(pm->plug_list);
472
  /*look for cache entry*/
473
0
  file_name = gf_cfg_get_key(pm->cfg, "PluginsCache", plug_name);
474
475
0
  if (file_name) {
476
477
0
    for (i=0; i<count; i++) {
478
0
      ModuleInstance *inst = (ModuleInstance *) gf_list_get(pm->plug_list, i);
479
0
      if (!rebrowse_all && !strcmp(inst->name,  file_name)) {
480
0
        ifce = gf_modules_load(i, InterfaceFamily);
481
0
        if (ifce) return ifce;
482
0
      }
483
0
    }
484
0
  }
485
486
0
  GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Plugin %s of type %d not found in cache, searching for it...\n", plug_name, InterfaceFamily));
487
0
  for (i=0; i<count; i++) {
488
0
    const char *mod_filename;
489
0
    if (!rebrowse_all) {
490
0
      ModuleInstance *inst = (ModuleInstance *) gf_list_get(gpac_modules_static->plug_list, i);
491
0
      if (inst->name && strcmp(inst->name, plug_name)) continue;
492
0
    }
493
0
    ifce = gf_modules_load(i, InterfaceFamily);
494
0
    if (!ifce) continue;
495
0
    if (ifce->module_name && !strcmp(ifce->module_name, plug_name) ) {
496
      /*update cache entry*/
497
0
      gf_cfg_set_key(pm->cfg, "PluginsCache", plug_name, ((ModuleInstance*)ifce->HPLUG)->name);
498
0
      GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Added plugin cache %s for %s\n", plug_name, ((ModuleInstance*)ifce->HPLUG)->name));
499
0
      return ifce;
500
0
    }
501
    /*check direct addressing by dynamic lib name*/
502
0
    mod_filename = gf_module_get_file_name(ifce);
503
0
    if (mod_filename && strstr(mod_filename, plug_name)) {
504
0
      return ifce;
505
0
    }
506
0
    gf_modules_close_interface(ifce);
507
0
  }
508
0
  GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Plugin %s not found in %d modules.\n", plug_name, count));
509
0
  return NULL;
510
0
}
511
512
GF_EXPORT
513
GF_Err gf_modules_close_interface(GF_BaseInterface *ifce)
514
0
{
515
0
  ModuleInstance *par;
516
0
  s32 i;
517
0
  if (!ifce) return GF_BAD_PARAM;
518
0
  par = (ModuleInstance *) ifce->HPLUG;
519
520
0
  if (!par || !ifce->InterfaceType) return GF_BAD_PARAM;
521
522
0
  i = gf_list_find(par->plugman->plug_list, par);
523
0
  if (i<0) return GF_BAD_PARAM;
524
525
0
  i = gf_list_find(par->interfaces, ifce);
526
0
  if (i<0) return GF_BAD_PARAM;
527
0
  gf_list_rem(par->interfaces, (u32) i);
528
0
  par->destroy_func(ifce);
529
0
  gf_modules_unload_library(par);
530
  //GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] interface %s unloaded\n", ifce->module_name));
531
0
  return GF_OK;
532
0
}
533
534
GF_EXPORT
535
const char *gf_modules_get_file_name(u32 i)
536
0
{
537
0
  ModuleInstance *inst = (ModuleInstance *) gf_list_get(gpac_modules_static->plug_list, i);
538
0
  if (!inst) return NULL;
539
0
  return inst->name;
540
0
}
541
542
GF_EXPORT
543
const char *gf_module_get_file_name(GF_BaseInterface *ifce)
544
0
{
545
0
  ModuleInstance *inst = (ModuleInstance *) ifce->HPLUG;
546
0
  if (!inst) return NULL;
547
0
  return inst->name;
548
0
}
549
550
#include <gpac/modules/video_out.h>
551
#include <gpac/modules/audio_out.h>
552
#include <gpac/modules/font.h>
553
static Bool module_check_ifce(GF_BaseInterface *ifce, u32 ifce_type)
554
0
{
555
0
  switch (ifce_type) {
556
0
  case GF_VIDEO_OUTPUT_INTERFACE:
557
0
  {
558
0
    GF_VideoOutput *vout = (GF_VideoOutput *) ifce;
559
0
    if (!vout || !vout->Flush || !vout->Setup) return GF_FALSE;
560
0
    return GF_TRUE;
561
0
  }
562
0
  case GF_AUDIO_OUTPUT_INTERFACE:
563
0
  {
564
0
    GF_AudioOutput *aout = (GF_AudioOutput *) ifce;
565
0
    if (!aout || !aout->Configure || !aout->Setup) return GF_FALSE;
566
    //no more support for raw out, deprecated
567
0
    if (!stricmp(ifce->module_name, "Raw Audio Output")) return GF_FALSE;
568
    /*check that's a valid audio mode*/
569
0
    if ((aout->SelfThreaded && aout->SetPriority) || aout->WriteAudio)
570
0
      return GF_TRUE;
571
0
    return GF_FALSE;
572
0
  }
573
574
0
  default:
575
0
    return GF_TRUE;
576
0
  }
577
0
}
578
579
580
GF_BaseInterface *gf_module_load(u32 ifce_type, const char *name)
581
0
{
582
0
  GF_BaseInterface *ifce = NULL;
583
0
  if (name) {
584
0
    ifce = gf_modules_load_by_name(name, ifce_type, GF_TRUE);
585
0
    if (!module_check_ifce(ifce, ifce_type)) {
586
0
      gf_modules_close_interface(ifce);
587
0
      ifce = NULL;
588
0
    }
589
0
  }
590
  /*get a preferred output*/
591
0
  if (!ifce) {
592
0
    const char *sOpt;
593
0
    switch (ifce_type) {
594
0
    case GF_VIDEO_OUTPUT_INTERFACE:
595
0
      sOpt = gf_opts_get_key("core", "video-output");
596
0
      break;
597
0
    case GF_AUDIO_OUTPUT_INTERFACE:
598
0
      sOpt = gf_opts_get_key("core", "audio-output");
599
0
      break;
600
0
    case GF_FONT_READER_INTERFACE:
601
0
      sOpt = gf_opts_get_key("core", "font-reader");
602
0
      break;
603
0
    default:
604
0
      sOpt = NULL;
605
0
    }
606
0
    if (sOpt) {
607
0
      ifce = gf_modules_load_by_name(sOpt, ifce_type, GF_TRUE);
608
0
      if (!module_check_ifce(ifce, ifce_type)) {
609
0
        gf_modules_close_interface(ifce);
610
0
        ifce = NULL;
611
0
      }
612
0
    }
613
0
  }
614
0
  if (!ifce) {
615
0
    u32 i, count = gf_modules_count();
616
0
    for (i=0; i<count; i++) {
617
0
      ifce = gf_modules_load(i, ifce_type);
618
0
      if (!ifce) continue;
619
620
0
      if (!module_check_ifce(ifce, ifce_type)) {
621
0
        gf_modules_close_interface(ifce);
622
0
        ifce = NULL;
623
0
        continue;
624
0
      }
625
0
      return ifce;
626
0
    }
627
0
  }
628
0
  return ifce;
629
0
}
630
631
Bool module_args_used = GF_FALSE;
632
633
GF_EXPORT
634
const char *gf_module_get_key(GF_BaseInterface *dr, char *key_name)
635
0
{
636
0
  if (!dr || !dr->module_name || !dr->args) return NULL;
637
638
0
  u32 klen = (u32) strlen(key_name);
639
0
  u32 i=0, nb_args = gf_sys_get_argc();
640
0
  Bool found = GF_FALSE;
641
0
  const char *res = NULL;
642
0
  while (dr->args[i].name) {
643
0
    if (!strcmp(dr->args[i].name, key_name)) {
644
0
      res = gf_opts_get_key(dr->module_name, key_name);
645
0
      if (!res)
646
0
        res = dr->args[i].val;
647
0
      found = GF_TRUE;
648
0
    }
649
0
    i++;
650
0
  }
651
0
  if (!found) return NULL;
652
0
  for (i=0; i<nb_args; i++) {
653
0
    const char *a = gf_sys_get_arg(i);
654
0
    if (strncmp(a, "--", 2)) continue;
655
0
    a+=2;
656
0
    char *msep = strchr(a, '@');
657
0
    if (msep) {
658
0
      u32 mlen = (u32) (msep-a);
659
0
      if (strncmp(dr->module_name, a, mlen)) continue;
660
0
      a += mlen+1;
661
0
    }
662
0
    if (strncmp(a, key_name, klen)) continue;
663
0
    if (a[klen] == '=') {
664
0
      gf_sys_mark_arg_used(i, GF_TRUE);
665
0
      module_args_used=GF_TRUE;
666
0
      return a+klen+1;
667
0
    }
668
0
    if (!a[klen]) {
669
0
      module_args_used=GF_TRUE;
670
0
      gf_sys_mark_arg_used(i, GF_TRUE);
671
0
      return "1";
672
0
    }
673
0
  }
674
0
  return res;
675
0
}
676
GF_EXPORT
677
Bool gf_module_get_bool(GF_BaseInterface *dr, char *key_name)
678
0
{
679
0
  const char *res = gf_module_get_key(dr, key_name);
680
0
  if (!res) return GF_FALSE;
681
0
  if (!stricmp(res, "yes") || !stricmp(res, "true") || !strcmp(res, "1")) return GF_TRUE;
682
0
  return GF_FALSE;
683
0
}
684
GF_EXPORT
685
Bool gf_module_get_int(GF_BaseInterface *dr, char *key_name)
686
0
{
687
0
  const char *res = gf_module_get_key(dr, key_name);
688
0
  if (!res) return 0;
689
0
  if (!stricmp(res, "yes") || !stricmp(res, "true") || !strcmp(res, "1")) return atoi(res);
690
0
  return 0;
691
0
}
692