LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer - nnstreamer_conf.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#58eaa3c6edb7484955a5d8c32f47a60ba9501210 Lines: 75.8 % 256 194
Test Date: 2025-04-18 05:37:26 Functions: 83.3 % 18 15

            Line data    Source code
       1              : /**
       2              :  * NNStreamer Configurations / Environmental Variable Manager.
       3              :  * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@samsung.com>
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Library General Public
       7              :  * License as published by the Free Software Foundation;
       8              :  * version 2.1 of the License.
       9              :  *
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Library General Public License for more details.
      14              :  *
      15              :  */
      16              : /**
      17              :  * @file        nnstreamer_conf.c
      18              :  * @date        26 Nov 2018
      19              :  * @brief       NNStreamer Configuration (conf file, env-var) Management.
      20              :  * @see         https://github.com/nnstreamer/nnstreamer
      21              :  * @author      MyungJoo Ham <myungjoo.ham@samsung.com>
      22              :  * @bug         No known bugs except for NYI items
      23              :  *
      24              :  */
      25              : 
      26              : #include <string.h>
      27              : #include <glib.h>
      28              : 
      29              : #include "nnstreamer_log.h"
      30              : #include "nnstreamer_conf.h"
      31              : #include "nnstreamer_subplugin.h"
      32              : 
      33              : /**
      34              :  * Note that users still can place their custom filters anywhere if they
      35              :  * designate them with the full path.
      36              :  */
      37              : 
      38              : /* Subplugin Naming Rules */
      39              : #define NNSTREAMER_PREFIX_DECODER       "libnnstreamer_decoder_"
      40              : #define NNSTREAMER_PREFIX_FILTER        "libnnstreamer_filter_"
      41              : #define NNSTREAMER_PREFIX_CUSTOMFILTERS ""
      42              : #define NNSTREAMER_PREFIX_CONVERTER     "libnnstreamer_converter_"
      43              : #define NNSTREAMER_PREFIX_TRAINER       "libnnstreamer_trainer_"
      44              : /* Custom filter does not have prefix */
      45              : 
      46              : /* Env-var names */
      47              : static const gchar *NNSTREAMER_ENVVAR[NNSCONF_PATH_END] = {
      48              :   [NNSCONF_PATH_FILTERS] = "NNSTREAMER_FILTERS",
      49              :   [NNSCONF_PATH_DECODERS] = "NNSTREAMER_DECODERS",
      50              :   [NNSCONF_PATH_CUSTOM_FILTERS] = "NNSTREAMER_CUSTOMFILTERS",
      51              :   [NNSCONF_PATH_CONVERTERS] = "NNSTREAMER_CONVERTERS",
      52              :   [NNSCONF_PATH_TRAINERS] = "NNSTREAMER_TRAINERS"
      53              : };
      54              : 
      55              : static const gchar *NNSTREAMER_PATH[NNSCONF_PATH_END] = {
      56              :   [NNSCONF_PATH_FILTERS] = "/usr/lib/nnstreamer/filters/",
      57              :   [NNSCONF_PATH_DECODERS] = "/usr/lib/nnstreamer/decoders/",
      58              :   [NNSCONF_PATH_CUSTOM_FILTERS] = "/usr/lib/nnstreamer/customfilters/",
      59              :   [NNSCONF_PATH_CONVERTERS] = "/usr/lib/nnstreamer/converters/",
      60              :   [NNSCONF_PATH_TRAINERS] = "/usr/lib/nnstreamer/trainers/"
      61              : };
      62              : 
      63              : static const gchar *subplugin_prefixes[] = {
      64              :   [NNSCONF_PATH_FILTERS] = NNSTREAMER_PREFIX_FILTER,
      65              :   [NNSCONF_PATH_DECODERS] = NNSTREAMER_PREFIX_DECODER,
      66              :   [NNSCONF_PATH_CUSTOM_FILTERS] = NNSTREAMER_PREFIX_CUSTOMFILTERS,
      67              :   [NNSCONF_PATH_EASY_CUSTOM_FILTERS] = NNSTREAMER_PREFIX_CUSTOMFILTERS, /**< Same as Custom Filters */
      68              :   [NNSCONF_PATH_CONVERTERS] = NNSTREAMER_PREFIX_CONVERTER,
      69              :   [NNSCONF_PATH_TRAINERS] = NNSTREAMER_PREFIX_TRAINER,
      70              :   [NNSCONF_PATH_END] = NULL
      71              : };
      72              : 
      73              : typedef enum
      74              : {
      75              :   CONF_SOURCE_ENVVAR = 0,
      76              :   CONF_SOURCE_INI = 1,
      77              :   CONF_SOURCE_HARDCODE = 2,
      78              :   CONF_SOURCE_EXTRA_CONF = 3, /**< path from extra config file */
      79              :   CONF_SOURCE_END
      80              : } conf_sources;
      81              : 
      82              : typedef struct
      83              : {
      84              :   /*************************************************
      85              :    * Cached Raw Values                             *
      86              :    * 0: ENVVAR. 1: CONFFILE, 2: Hardcoded          *
      87              :    *************************************************/
      88              :   gchar *path[CONF_SOURCE_END]; /**< directory paths */
      89              : 
      90              :   /*************************************************
      91              :    * Processed Values                              *
      92              :    *************************************************/
      93              :   gchar **files; /**< Null terminated list of full filepaths */
      94              :   gchar **names; /**< Null terminated list of subplugin names */
      95              : } subplugin_conf;
      96              : 
      97              : typedef struct
      98              : {
      99              :   gboolean loaded;            /**< TRUE if loaded at least once */
     100              :   gboolean enable_envvar;     /**< TRUE to parse env variables */
     101              :   gboolean enable_symlink;    /**< TRUE to allow symbolic link file */
     102              : 
     103              :   gchar *conffile;            /**< Location of conf file. */
     104              :   gchar *extra_conffile;      /**< Location of extra configuration file. */
     105              : 
     106              :   subplugin_conf conf[NNSCONF_PATH_END];
     107              : } confdata;
     108              : 
     109              : static confdata conf = { 0 };
     110              : 
     111              : /**
     112              :  * @brief Parse string to get boolean value.
     113              :  */
     114              : static gboolean
     115          910 : _parse_bool_string (const gchar * strval, gboolean def)
     116              : {
     117          910 :   gboolean res = def;
     118              : 
     119          910 :   if (strval) {
     120              :     /* 1/0, true/false, t/f, yes/no, on/off. case incensitive. */
     121          905 :     if (strval[0] == '1' || strval[0] == 't' || strval[0] == 'T' ||
     122          457 :         strval[0] == 'y' || strval[0] == 'Y' ||
     123          455 :         g_ascii_strncasecmp ("on", strval, 2) == 0) {
     124          452 :       res = TRUE;
     125          453 :     } else if (strval[0] == '0' || strval[0] == 'f' || strval[0] == 'F' ||
     126           10 :         strval[0] == 'n' || strval[0] == 'N' ||
     127            8 :         g_ascii_strncasecmp ("of", strval, 2) == 0) {
     128          447 :       res = FALSE;
     129              :     }
     130              :   }
     131              : 
     132          910 :   return res;
     133              : }
     134              : 
     135              : /**
     136              :  * @brief Private function to get strdup-ed env-var if it's valid.
     137              :  *        Otherwise, NULL
     138              :  *
     139              :  * @retval strdup-ed env-var value
     140              :  * @param[in] name Environmental variable name
     141              :  */
     142              : static gchar *
     143         2744 : _strdup_getenv (const gchar * name)
     144              : {
     145              :   /**
     146              :    * @todo Evaluate if we need to use secure_getenv() here
     147              :    *  (and compatible with other OS
     148              :    */
     149         2744 :   const gchar *tmp = g_getenv (name);
     150              : 
     151         2744 :   return g_strdup (tmp);
     152              : }
     153              : 
     154              : /**
     155              :  * @brief Private function to validate .so file can be added to the list.
     156              :  */
     157              : static gboolean
     158        13285 : _validate_file (nnsconf_type_path type, const gchar * fullpath)
     159              : {
     160              :   /* ignore directory */
     161        13285 :   if (!fullpath || !g_file_test (fullpath, G_FILE_TEST_IS_REGULAR))
     162          143 :     return FALSE;
     163              :   /* ignore symbol link file */
     164        13142 :   if (!conf.enable_symlink && g_file_test (fullpath, G_FILE_TEST_IS_SYMLINK))
     165            0 :     return FALSE;
     166        13142 :   if (type < 0 || type >= NNSCONF_PATH_END)
     167            0 :     return FALSE;
     168              :   /** @todo how to validate with nnsconf type. */
     169        13142 :   return TRUE;
     170              : }
     171              : 
     172              : /**
     173              :  * @brief Private function to fill in ".so/.dylib list" with fullpath-filenames in a directory.
     174              :  * @param[in] type conf type to scan.
     175              :  * @param[in] dir Directory to be searched.
     176              :  * @param[in/out] listF The fullpath list to be updated.
     177              :  * @param[in/out] listN The name list to be updated.
     178              :  * @param[in/out] counter increased by the number of appended elements.
     179              :  * @return True if successfully updated.
     180              :  * @todo This assumes .so/.dylib for all sub plugins. Support Windows!
     181              :  */
     182              : static gboolean
     183         3986 : _get_filenames (nnsconf_type_path type, const gchar * dir, GSList ** listF,
     184              :     GSList ** listN, guint * counter)
     185              : {
     186              :   GDir *gdir;
     187              :   const gchar *entry;
     188              :   gchar *fullpath;
     189              :   gchar *basename;
     190              :   gchar *name;
     191              :   gsize prefix, extension, len;
     192              : 
     193         3986 :   if ((gdir = g_dir_open (dir, 0U, NULL)) == NULL)
     194         2657 :     return FALSE;
     195              : 
     196         1329 :   prefix = strlen (subplugin_prefixes[type]);
     197         1329 :   extension = strlen (NNSTREAMER_SO_FILE_EXTENSION);
     198              : 
     199        51648 :   while (NULL != (entry = g_dir_read_name (gdir))) {
     200              :     /* check file prefix for given type, currently handle .so and .dylib. */
     201        48990 :     if (g_str_has_prefix (entry, subplugin_prefixes[type]) &&
     202        44206 :         g_str_has_suffix (entry, NNSTREAMER_SO_FILE_EXTENSION)) {
     203        12824 :       fullpath = g_build_filename (dir, entry, NULL);
     204              : 
     205        12824 :       if (_validate_file (type, fullpath)) {
     206        12824 :         basename = g_path_get_basename (entry);
     207        12824 :         len = strlen (basename) - prefix - extension;
     208        12824 :         name = g_strndup (basename + prefix, len);
     209              : 
     210        12824 :         *listF = g_slist_prepend (*listF, fullpath);
     211        12824 :         *listN = g_slist_prepend (*listN, name);
     212        12824 :         *counter = *counter + 1;
     213              : 
     214        12824 :         g_free (basename);
     215              :       } else {
     216            0 :         g_free (fullpath);
     217              :       }
     218              :     }
     219              :   }
     220              : 
     221         1329 :   g_dir_close (gdir);
     222         1329 :   return TRUE;
     223              : }
     224              : 
     225              : /**
     226              :  * @brief Private function to get sub-plugins list with type.
     227              :  */
     228              : static gboolean
     229         1587 : _get_subplugin_with_type (nnsconf_type_path type, gchar *** name,
     230              :     gchar *** filepath)
     231              : {
     232         1587 :   if (type >= NNSCONF_PATH_END) {
     233              :     /* unknown type */
     234            0 :     ml_loge ("Failed to get sub-plugins, unknown sub-plugin type.");
     235            0 :     return FALSE;
     236              :   }
     237              : 
     238         1587 :   if (!conf.loaded) {
     239            0 :     ml_loge ("Configuration file is not loaded.");
     240            0 :     return FALSE;
     241              :   }
     242              : 
     243              :   /* Easy custom uses the configuration of custom */
     244         1587 :   if (type == NNSCONF_PATH_EASY_CUSTOM_FILTERS)
     245           25 :     type = NNSCONF_PATH_CUSTOM_FILTERS;
     246              : 
     247         1587 :   *name = conf.conf[type].names;
     248         1587 :   *filepath = conf.conf[type].files;
     249         1587 :   return TRUE;
     250              : }
     251              : 
     252              : /**
     253              :  * @brief Data structure for _g_list_foreach_vstr_helper
     254              :  */
     255              : typedef struct
     256              : {
     257              :   gchar **vstr;    /**< The vstr data (string array) */
     258              :   guint cursor;  /**< The first "empty" element in vstr */
     259              :   guint size;    /**< The number of "g_char *" in vstr, excluding the terminator */
     260              : } vstr_helper;
     261              : 
     262              : /**
     263              :  * @brief Private function to help convert linked-list to vstr with foreach
     264              :  * @data The element data of linked-list
     265              :  * @user_data The struct to fill in vstr
     266              :  */
     267              : static void
     268        25648 : _g_list_foreach_vstr_helper (gpointer data, gpointer user_data)
     269              : {
     270        25648 :   vstr_helper *helper = (vstr_helper *) user_data;
     271        25648 :   g_assert (helper->cursor < helper->size); /** library error? internal logic error? */
     272        25648 :   helper->vstr[helper->cursor] = data;
     273        25648 :   helper->cursor++;
     274        25648 : }
     275              : 
     276              : /**
     277              :  * @brief Private function to fill in vstr
     278              :  */
     279              : static void
     280         2215 : _fill_in_vstr (gchar *** fullpath_vstr, gchar *** name_vstr,
     281              :     gchar * searchpath[CONF_SOURCE_END], nnsconf_type_path type)
     282              : {
     283         2215 :   GSList *lstF = NULL, *lstN = NULL;
     284              :   vstr_helper vstrF, vstrN;
     285              :   guint i, j, counter;
     286              : 
     287         2215 :   counter = 0;
     288        11075 :   for (i = 0; i < CONF_SOURCE_END; i++) {
     289         8860 :     if (searchpath[i]) {
     290              :       /* skip duplicated paths */
     291        13275 :       for (j = i + 1; j < CONF_SOURCE_END; j++) {
     292         9289 :         if (searchpath[j] && !g_strcmp0 (searchpath[i], searchpath[j])) {
     293         1764 :           break;
     294              :         }
     295              :       }
     296         5750 :       if (j == CONF_SOURCE_END)
     297         3986 :         _get_filenames (type, searchpath[i], &lstF, &lstN, &counter);
     298              :     }
     299              :   }
     300              : 
     301              :   /* Because _get_* does "prepend", reverse them to have the correct order. */
     302         2215 :   lstF = g_slist_reverse (lstF);
     303         2215 :   lstN = g_slist_reverse (lstN);
     304              : 
     305         2215 :   *fullpath_vstr = g_malloc0_n (counter + 1, sizeof (gchar *));
     306         2215 :   g_assert (*fullpath_vstr != NULL);    /* This won't happen, but doesn't hurt either */
     307         2215 :   *name_vstr = g_malloc0_n (counter + 1, sizeof (gchar *));
     308         2215 :   g_assert (*name_vstr != NULL);        /* This won't happen, but doesn't hurt either */
     309              : 
     310         2215 :   vstrF.vstr = *fullpath_vstr;
     311         2215 :   vstrN.vstr = *name_vstr;
     312         2215 :   vstrF.size = counter;
     313         2215 :   vstrN.size = counter;
     314         2215 :   vstrF.cursor = 0;
     315         2215 :   vstrN.cursor = 0;
     316         2215 :   g_slist_foreach (lstF, _g_list_foreach_vstr_helper, (gpointer) & vstrF);
     317         2215 :   g_slist_foreach (lstN, _g_list_foreach_vstr_helper, (gpointer) & vstrN);
     318              : 
     319              :   /* Do not free elements. They are now at vstr */
     320         2215 :   g_slist_free (lstF);
     321         2215 :   g_slist_free (lstN);
     322         2215 : }
     323              : 
     324              : /** @brief Private function to fill subplugin path */
     325              : static void
     326          443 : _fill_subplugin_path (confdata * cdata, GKeyFile * key_file, conf_sources src)
     327              : {
     328          443 :   cdata->conf[NNSCONF_PATH_FILTERS].path[src] =
     329          443 :       g_key_file_get_string (key_file, "filter", "filters", NULL);
     330          443 :   cdata->conf[NNSCONF_PATH_DECODERS].path[src] =
     331          443 :       g_key_file_get_string (key_file, "decoder", "decoders", NULL);
     332          443 :   cdata->conf[NNSCONF_PATH_CUSTOM_FILTERS].path[src] =
     333          443 :       g_key_file_get_string (key_file, "filter", "customfilters", NULL);
     334          443 :   cdata->conf[NNSCONF_PATH_CONVERTERS].path[src] =
     335          443 :       g_key_file_get_string (key_file, "converter", "converters", NULL);
     336          443 :   cdata->conf[NNSCONF_PATH_TRAINERS].path[src] =
     337          443 :       g_key_file_get_string (key_file, "trainer", "trainer", NULL);
     338          443 : }
     339              : 
     340              : /** @brief Public function defined in the header */
     341              : gboolean
     342         2625 : nnsconf_loadconf (gboolean force_reload)
     343              : {
     344         2625 :   const gchar root_path_prefix[] = NNSTREAMER_SYS_ROOT_PATH_PREFIX;
     345         2625 :   GKeyFile *key_file = NULL;
     346              :   guint i, t;
     347              : 
     348         2625 :   if (!force_reload && conf.loaded)
     349         2625 :     return TRUE;
     350              : 
     351          443 :   if (force_reload && conf.loaded) {
     352              :     /* Do Clean Up */
     353            1 :     g_free (conf.conffile);
     354            1 :     conf.conffile = NULL;
     355            1 :     g_free (conf.extra_conffile);
     356            1 :     conf.extra_conffile = NULL;
     357              : 
     358            7 :     for (t = 0; t < NNSCONF_PATH_END; t++) {
     359              : 
     360           30 :       for (i = 0; i < CONF_SOURCE_END; i++) {
     361           24 :         g_free (conf.conf[t].path[i]);
     362              :       }
     363              : 
     364            6 :       g_strfreev (conf.conf[t].files);
     365            6 :       g_strfreev (conf.conf[t].names);
     366              :     }
     367              : 
     368              :     /* init with 0 */
     369            1 :     memset (&conf, 0, sizeof (confdata));
     370              :   }
     371              : #ifndef __TIZEN__
     372              :   /** if it's not Tizen, configuration from env-var has a higher priority */
     373              :   conf.conffile = _strdup_getenv (NNSTREAMER_ENVVAR_CONF_FILE);
     374              :   if (conf.conffile && !g_file_test (conf.conffile, G_FILE_TEST_IS_REGULAR)) {
     375              :     g_free (conf.conffile);
     376              :     conf.conffile = NULL;
     377              :   }
     378              : #endif
     379          443 :   if (conf.conffile == NULL) {
     380              :     /**
     381              :      * Priority of reading a conf file
     382              :      * 1) read from NNSTREAMER_CONF_FILE
     383              :      * 2) read from NNSTREAMER_DEFAULT_CONF_FILE
     384              :      * 3) read from env-var
     385              :      */
     386          443 :     if (g_path_is_absolute (NNSTREAMER_CONF_FILE)) {
     387          443 :       conf.conffile = g_strdup (NNSTREAMER_CONF_FILE);
     388              :     } else {
     389              :       /** default value of 'sysconfdir' in meson is 'etc' */
     390            0 :       conf.conffile = g_build_path (G_DIR_SEPARATOR_S, root_path_prefix,
     391              :           NNSTREAMER_CONF_FILE, NULL);
     392              :     }
     393              : 
     394          443 :     if (!g_file_test (conf.conffile, G_FILE_TEST_IS_REGULAR)) {
     395              :       /* File not found or not configured */
     396          443 :       g_free (conf.conffile);
     397          443 :       conf.conffile = NULL;
     398              : 
     399          443 :       if (g_file_test (NNSTREAMER_DEFAULT_CONF_FILE, G_FILE_TEST_IS_REGULAR)) {
     400            0 :         conf.conffile = g_strdup (NNSTREAMER_DEFAULT_CONF_FILE);
     401              :       } else {
     402              :         /* Try to read from Environmental Variables */
     403          443 :         conf.conffile = _strdup_getenv (NNSTREAMER_ENVVAR_CONF_FILE);
     404              :       }
     405              :     }
     406              :   }
     407              : 
     408          443 :   if (conf.conffile) {
     409          443 :     key_file = g_key_file_new ();
     410          443 :     g_assert (key_file != NULL); /** Internal lib error? out-of-memory? */
     411              : 
     412              :     /* Read the conf file. It's ok even if we cannot load it. */
     413          443 :     if (g_key_file_load_from_file (key_file, conf.conffile, G_KEY_FILE_NONE,
     414              :             NULL)) {
     415              :       gchar *value;
     416              : 
     417          443 :       value = g_key_file_get_string (key_file, "common", "enable_envvar", NULL);
     418          443 :       conf.enable_envvar = _parse_bool_string (value, FALSE);
     419          443 :       g_free (value);
     420              : 
     421              :       value =
     422          443 :           g_key_file_get_string (key_file, "common", "enable_symlink", NULL);
     423          443 :       conf.enable_symlink = _parse_bool_string (value, FALSE);
     424          443 :       g_free (value);
     425              : 
     426          443 :       conf.extra_conffile =
     427          443 :           g_key_file_get_string (key_file, "common", "extra_config_path", NULL);
     428              : 
     429          443 :       _fill_subplugin_path (&conf, key_file, CONF_SOURCE_INI);
     430              :     }
     431              : 
     432          443 :     g_key_file_free (key_file);
     433              : 
     434              :     /* load from extra config file */
     435          443 :     if (conf.extra_conffile) {
     436            1 :       if (g_file_test (conf.extra_conffile, G_FILE_TEST_IS_REGULAR)) {
     437            0 :         key_file = g_key_file_new ();
     438            0 :         g_assert (key_file != NULL); /** Internal lib error? out-of-memory? */
     439              : 
     440            0 :         if (g_key_file_load_from_file (key_file, conf.extra_conffile,
     441              :                 G_KEY_FILE_NONE, NULL)) {
     442            0 :           _fill_subplugin_path (&conf, key_file, CONF_SOURCE_EXTRA_CONF);
     443              :         }
     444              : 
     445            0 :         g_key_file_free (key_file);
     446              :       } else {
     447            1 :         ml_logw
     448              :             ("Cannot find config file '%s'. You should set a valid path to load extra configuration.",
     449              :             conf.extra_conffile);
     450              :       }
     451              :     }
     452              :   } else {
     453              :     /**
     454              :      * Failed to get the configuration.
     455              :      * Note that Android API does not use the configuration.
     456              :      */
     457            0 :     ml_logw ("Failed to load the configuration, no config file found.");
     458              :   }
     459              : 
     460         3101 :   for (t = 0; t < NNSCONF_PATH_END; t++) {
     461         2658 :     if (t == NNSCONF_PATH_EASY_CUSTOM_FILTERS)
     462          443 :       continue;                 /* It does not have its own configuration */
     463              : 
     464              :     /* Read from env variables. */
     465         2215 :     if (conf.enable_envvar)
     466         2210 :       conf.conf[t].path[CONF_SOURCE_ENVVAR] =
     467         2210 :           _strdup_getenv (NNSTREAMER_ENVVAR[t]);
     468              : 
     469              :     /* Strdup the hardcoded */
     470         2215 :     conf.conf[t].path[CONF_SOURCE_HARDCODE] = g_strdup (NNSTREAMER_PATH[t]);
     471              : 
     472              :     /* Fill in conf.files* */
     473         2215 :     _fill_in_vstr (&conf.conf[t].files, &conf.conf[t].names,
     474         2215 :         conf.conf[t].path, t);
     475              :   }
     476              : 
     477          443 :   conf.loaded = TRUE;
     478          443 :   return TRUE;
     479              : }
     480              : 
     481              : /** @brief Public function defined in the header */
     482              : const gchar *
     483          383 : nnsconf_get_fullpath (const gchar * subpluginname, nnsconf_type_path type)
     484              : {
     485              :   subplugin_info_s info;
     486              :   guint i, total;
     487              : 
     488          383 :   nnsconf_loadconf (FALSE);
     489              : 
     490          383 :   total = nnsconf_get_subplugin_info (type, &info);
     491         3608 :   for (i = 0; i < total; i++) {
     492         3462 :     if (g_strcmp0 (info.names[i], subpluginname) == 0)
     493          383 :       return info.paths[i];
     494              :   }
     495              : 
     496          146 :   return NULL;
     497              : }
     498              : 
     499              : /**
     500              :  * @brief Public function to validate sub-plugin library is available.
     501              :  */
     502              : gboolean
     503          461 : nnsconf_validate_file (nnsconf_type_path type, const gchar * fullpath)
     504              : {
     505          461 :   nnsconf_loadconf (FALSE);
     506              : 
     507          461 :   return _validate_file (type, fullpath);
     508              : }
     509              : 
     510              : /**
     511              :  * @brief Get sub-plugin's name prefix.
     512              :  * @param[in] type The type (FILTERS/DECODERS/CUSTOM_FILTERS)
     513              :  * @return Predefined prefix string for given type.
     514              :  */
     515              : const gchar *
     516            2 : nnsconf_get_subplugin_name_prefix (nnsconf_type_path type)
     517              : {
     518            2 :   g_return_val_if_fail (type >= 0 && type <= NNSCONF_PATH_END, NULL);
     519            1 :   return subplugin_prefixes[type];
     520              : }
     521              : 
     522              : /**
     523              :  * @brief Public function to get the list of sub-plugins name and path
     524              :  * @return total number of sub-plugins for given type
     525              :  * @note DO NOT free sub-plugins info
     526              :  */
     527              : guint
     528         1587 : nnsconf_get_subplugin_info (nnsconf_type_path type, subplugin_info_s * info)
     529              : {
     530              :   gchar **vstr, **vstrFull;
     531              : 
     532         3174 :   g_return_val_if_fail (info != NULL, 0);
     533         1587 :   info->names = info->paths = NULL;
     534              : 
     535         1587 :   nnsconf_loadconf (FALSE);
     536              : 
     537         1587 :   if (!_get_subplugin_with_type (type, &vstr, &vstrFull))
     538            0 :     return 0;
     539              : 
     540         1587 :   info->names = vstr;
     541         1587 :   info->paths = vstrFull;
     542              : 
     543         1587 :   return g_strv_length (vstr);
     544              : }
     545              : 
     546              : /**
     547              :  * @brief Internal cache for the custom key-values
     548              :  */
     549              : static GHashTable *custom_table = NULL;
     550              : 
     551              : /**
     552              :  * @brief Public function defined in the header.
     553              :  * @note This function is included in nnstreamer internal header for native APIs.
     554              :  *       When changing the declaration, you should update the internal header (nnstreamer_internal.h).
     555              :  */
     556              : gchar *
     557          192 : nnsconf_get_custom_value_string (const gchar * group, const gchar * key)
     558              : {
     559          192 :   gchar *hashkey = g_strdup_printf ("[%s]%s", group, key);
     560          192 :   gchar *value = NULL;
     561              : 
     562          192 :   nnsconf_loadconf (FALSE);     /* Load .ini file path */
     563              : 
     564          192 :   if (NULL == custom_table)
     565           43 :     custom_table =
     566           43 :         g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
     567              : 
     568          192 :   value = g_hash_table_lookup (custom_table, hashkey);
     569              : 
     570          192 :   if (NULL == value) {
     571              :     /* 1. Read envvar */
     572           92 :     if (conf.enable_envvar) {
     573           91 :       gchar *envkey = g_strdup_printf ("NNSTREAMER_%s_%s", group, key);
     574              : 
     575           91 :       value = _strdup_getenv (envkey);
     576           91 :       g_free (envkey);
     577              :     }
     578              : 
     579              :     /* 2. Read ini */
     580           92 :     if (NULL == value && conf.conffile) {
     581           92 :       g_autoptr (GKeyFile) key_file = g_key_file_new ();
     582              : 
     583           92 :       g_assert (key_file != NULL); /** Internal lib error? out-of-memory? */
     584              : 
     585           92 :       if (g_key_file_load_from_file (key_file, conf.conffile, G_KEY_FILE_NONE,
     586              :               NULL)) {
     587           92 :         value = g_key_file_get_string (key_file, group, key, NULL);
     588              :       }
     589              :     }
     590              : 
     591           92 :     if (value) {
     592           48 :       g_hash_table_insert (custom_table, hashkey, value);
     593              :     } else {
     594           44 :       g_free (hashkey);
     595              :     }
     596              :   } else {
     597          100 :     g_free (hashkey);
     598              :   }
     599              : 
     600          192 :   return g_strdup (value);
     601              : }
     602              : 
     603              : /**
     604              :  * @brief Public function defined in the header.
     605              :  * @note This function is included in nnstreamer internal header for native APIs.
     606              :  *       When changing the declaration, you should update the internal header (nnstreamer_internal.h).
     607              :  */
     608              : gboolean
     609           24 : nnsconf_get_custom_value_bool (const gchar * group, const gchar * key,
     610              :     gboolean def)
     611              : {
     612              :   gchar *strval;
     613              :   gboolean ret;
     614              : 
     615           24 :   strval = nnsconf_get_custom_value_string (group, key);
     616           24 :   ret = _parse_bool_string (strval, def);
     617              : 
     618           24 :   g_free (strval);
     619           24 :   return ret;
     620              : }
     621              : 
     622              : #define STR_BOOL(x) ((x) ? "TRUE" : "FALSE")
     623              : /**
     624              :  * @brief Print out configurations
     625              :  * @todo Add more configuration values to dump.
     626              :  */
     627              : void
     628            0 : nnsconf_dump (gchar * str, gulong size)
     629              : {
     630            0 :   gchar *cur = str;
     631            0 :   gulong _size = size;
     632              :   gint len;
     633              : 
     634            0 :   if (!conf.loaded)
     635            0 :     nnsconf_loadconf (FALSE);
     636              : 
     637            0 :   len = g_snprintf (cur, _size,
     638              :       "Configuration Loaded: %s\n"
     639              :       "Configuration file path: %s\n"
     640              :       "    Candidates: envvar(NNSTREAMER_CONF): %s\n"
     641              :       "                build-config: %s\n"
     642              :       "                hard-coded: %s\n"
     643              :       "[Common]\n"
     644              :       "  Enable envvar: %s\n"
     645              :       "  Enable sym-linked subplugins: %s\n"
     646              :       "[Filter]\n"
     647              :       "  Filter paths from .ini: %s\n"
     648              :       "             from envvar: %s\n"
     649            0 :       "         from hard-coded: %s\n", STR_BOOL (conf.loaded),
     650              :       /* 1. Configuration file path */
     651            0 :       (conf.conffile ? conf.conffile : "<error> config file not loaded"),
     652              : #ifdef __TIZEN__
     653              :       "Not available (Tizen)",
     654              : #else
     655              :       g_getenv (NNSTREAMER_ENVVAR_CONF_FILE),
     656              : #endif
     657              :       NNSTREAMER_CONF_FILE, NNSTREAMER_DEFAULT_CONF_FILE,
     658              :       /* 2. [Common] */
     659            0 :       STR_BOOL (conf.enable_envvar), STR_BOOL (conf.enable_symlink),
     660              :       /* 3. [Filter] */
     661              :       conf.conf[NNSCONF_PATH_FILTERS].path[CONF_SOURCE_INI],
     662            0 :       (conf.enable_envvar) ?
     663              :       conf.conf[NNSCONF_PATH_FILTERS].path[CONF_SOURCE_ENVVAR] : "<disabled>",
     664              :       conf.conf[NNSCONF_PATH_FILTERS].path[CONF_SOURCE_HARDCODE]);
     665              : 
     666            0 :   if (len <= 0)
     667            0 :     g_printerr ("Config dump is too large. The results show partially.\n");
     668            0 : }
     669              : 
     670              : typedef struct
     671              : {
     672              :   gchar *base;
     673              :   gulong size;
     674              :   gulong pos;
     675              : } dump_buf;
     676              : 
     677              : /**
     678              :  * @brief foreach callback for custom property
     679              :  */
     680              : static void
     681            0 : _foreach_custom_property (GQuark key_id, gpointer data, gpointer user_data)
     682              : {
     683            0 :   dump_buf *buf = (dump_buf *) user_data;
     684              : 
     685            0 :   if (buf->size > buf->pos) {
     686            0 :     buf->pos += g_snprintf (buf->base + buf->pos, buf->size - buf->pos,
     687              :         "    - %s: %s\n", g_quark_to_string (key_id), (gchar *) data);
     688              :   }
     689            0 : }
     690              : 
     691              : /**
     692              :  * @brief Print out the information of registered sub-plugins
     693              :  */
     694              : void
     695            0 : nnsconf_subplugin_dump (gchar * str, gulong size)
     696              : {
     697              :   static const nnsconf_type_path dump_list_type[] = {
     698              :     NNSCONF_PATH_FILTERS, NNSCONF_PATH_DECODERS, NNSCONF_PATH_CONVERTERS,
     699              :     NNSCONF_PATH_TRAINERS
     700              :   };
     701              :   static const char *dump_list_str[] = {
     702              :     "Filter", "Decoder", "Conterver", "Trainer"
     703              :   };
     704              : 
     705              :   dump_buf buf;
     706              :   subplugin_info_s info;
     707              :   guint i, j, ret;
     708              : 
     709            0 :   if (!conf.loaded)
     710            0 :     nnsconf_loadconf (FALSE);
     711              : 
     712            0 :   buf.base = str;
     713            0 :   buf.size = size;
     714            0 :   buf.pos = 0;
     715              : 
     716            0 :   for (i = 0; i < sizeof (dump_list_type) / sizeof (nnsconf_type_path); i++) {
     717            0 :     buf.pos += g_snprintf (buf.base + buf.pos, buf.size - buf.pos,
     718              :         "\n[%s]\n", dump_list_str[i]);
     719            0 :     if (buf.size <= buf.pos)
     720            0 :       goto truncated;
     721              : 
     722            0 :     ret = nnsconf_get_subplugin_info (dump_list_type[i], &info);
     723            0 :     for (j = 0; j < ret; j++) {
     724              :       GData *data;
     725            0 :       subpluginType stype = (subpluginType) dump_list_type[i];
     726            0 :       gchar *sname = info.names[j];
     727              : 
     728            0 :       if (!get_subplugin (stype, sname))
     729            0 :         break;
     730              : 
     731            0 :       buf.pos += g_snprintf (buf.base + buf.pos, buf.size - buf.pos,
     732              :           "  %s\n", sname);
     733            0 :       if (buf.size <= buf.pos)
     734            0 :         goto truncated;
     735              : 
     736            0 :       data = subplugin_get_custom_property_desc (stype, sname);
     737            0 :       if (data) {
     738            0 :         g_datalist_foreach (&data, _foreach_custom_property, &buf);
     739              :       } else {
     740            0 :         buf.pos += g_snprintf (buf.base + buf.pos, buf.size - buf.pos,
     741              :             "    - No custom property found\n");
     742              :       }
     743              : 
     744            0 :       if (buf.size <= buf.pos)
     745            0 :         goto truncated;
     746              :     }
     747              :   }
     748            0 :   return;
     749              : 
     750            0 : truncated:
     751            0 :   g_printerr ("Config dump is too large. The results show partially.\n");
     752              : }
        

Generated by: LCOV version 2.0-1