/*****************************************************************************
* modules.c : Builtin and plugin modules management functions
*****************************************************************************
* Copyright (C) 2001-2011 VLC authors and VideoLAN
*
* Authors: Sam Hocevar <sam@zoy.org>
* Ethan C. Baldridge <BaldridgeE@cadmus.com>
* Hans-Peter Jansen <hpj@urpla.net>
* Gildas Bazin <gbazin@videolan.org>
* Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#ifdef ENABLE_NLS
# include <libintl.h>
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_modules.h>
#include "../libvlc.h"
#include "config/configuration.h"
#include "vlc_arrays.h"
#include "modules/modules.h"
bool module_provides (const module_t *m, const char *cap)
{
return !strcmp (module_get_capability (m), cap);
}
const char *module_get_object( const module_t *m )
{
if (unlikely(m->i_shortcuts == 0))
return "unnamed";
return m->pp_shortcuts[0];
}
const char *module_get_name( const module_t *m, bool long_name )
{
if( long_name && ( m->psz_longname != NULL) )
return m->psz_longname;
if (m->psz_shortname != NULL)
return m->psz_shortname;
return module_get_object (m);
}
const char *module_get_help( const module_t *m )
{
return m->psz_help;
}
const char *module_get_help_html( const module_t *m )
{
return m->psz_help_html;
}
const char *module_get_capability (const module_t *m)
{
return (m->psz_capability != NULL) ? m->psz_capability : "none";
}
int module_get_score( const module_t *m )
{
return m->i_score;
}
const char *module_gettext (const module_t *m, const char *str)
{
if (unlikely(str == NULL || *str == '\0'))
return "";
#ifdef ENABLE_NLS
const char *domain = m->plugin->textdomain;
return dgettext ((domain != NULL) ? domain : PACKAGE_NAME, str);
#else
(void)m;
return str;
#endif
}
static bool module_match_name(const module_t *m, const char *name, size_t len)
{
for (size_t i = 0; i < m->i_shortcuts; i++)
if (strncasecmp(m->pp_shortcuts[i], name, len) == 0
&& m->pp_shortcuts[i][len] == '\0')
return true;
return false;
}
ssize_t vlc_module_match(const char *capability, const char *names,
bool strict, module_t ***restrict modules,
size_t *restrict strict_matches)
{
module_t *const *tab;
size_t total = module_list_cap(&tab, capability);
module_t **unsorted = malloc(total * sizeof (*unsorted));
module_t **sorted = malloc(total * sizeof (*sorted));
size_t matches = 0;
if (total > 0) {
if (unlikely(unsorted == NULL || sorted == NULL)) {
free(unsorted);
free(sorted);
*modules = NULL;
return -1;
}
memcpy(unsorted, tab, total * sizeof (*unsorted));
}
*modules = sorted;
/* Go through the list of module shortcut names. */
if (names != NULL) {
while (names[0] != '\0') {
const char *shortcut = names;
size_t slen = strcspn(names, ",");
names += slen;
names += strspn(names, ",");
/* "none" matches nothing and ends the search */
if (slen == 4 && strncasecmp("none", shortcut, 4) == 0) {
total = 0;
break;
}
/* "any" matches everything with strictly positive score */
if (slen == 3 && strncasecmp("any", shortcut, 3) == 0) {
strict = false;
break;
}
for (size_t i = 0; i < total; i++) {
module_t *cand = unsorted[i];
if (cand != NULL && module_match_name(cand, shortcut, slen)) {
assert(matches < total);
sorted[matches++] = cand;
unsorted[i] = NULL;
}
}
}
}
if (strict_matches != NULL)
*strict_matches = matches;
if (!strict) {
/* List remaining modules with strictly positive score. */
for (size_t i = 0; i < total; i++) {
module_t *cand = unsorted[i];
if (cand != NULL) {
/* Modules are sorted by decreasing score, so there is no point
* carrying on after the first zero score is found.
*/
if (module_get_score(cand) <= 0)
break;
assert(matches < total);
sorted[matches++] = cand;
}
}
}
free(unsorted);
return matches;
}
void *vlc_module_map(vlc_logger_t *log, module_t *module)
{
return vlc_plugin_Map(log, module->plugin) ? NULL : module->pf_activate;
}
module_t *(vlc_module_load)(struct vlc_logger *log, const char *capability,
const char *name, bool strict,
vlc_activate_t probe, ...)
{
if (name == NULL || name[0] == '\0')
name = "any";
/* Find matching modules */
module_t **mods;
size_t strict_total;
ssize_t total = vlc_module_match(capability, name, strict,
&mods, &strict_total);
if (unlikely(total < 0))
return NULL;
vlc_debug(log, "looking for %s module matching \"%s\": %zd candidates",
capability, name, total);
module_t *module = NULL;
va_list args;
va_start(args, probe);
for (size_t i = 0; i < (size_t)total; i++) {
module_t *cand = mods[i];
int ret = VLC_EGENERIC;
void *cb = vlc_module_map(log, cand);
if (cb == NULL)
continue;
va_list ap;
va_copy(ap, args);
ret = probe(cb, i < strict_total, ap);
va_end(ap);
switch (ret) {
case VLC_SUCCESS:
vlc_debug(log, "using %s module \"%s\"", capability,
module_get_object(cand));
module = cand;
/* fall through */
case VLC_ETIMEOUT:
goto done;
}
}
done:
va_end (args);
if (module == NULL)
vlc_debug(log, "no %s modules matched with name %s", capability, name);
free(mods);
return module;
}
static int generic_start(void *func, bool forced, va_list ap)
{
vlc_object_t *obj = va_arg(ap, vlc_object_t *);
int (*activate)(vlc_object_t *) = func;
int ret;
obj->force = forced;
ret = activate(obj);
if (ret != VLC_SUCCESS)
vlc_objres_clear(obj);
return ret;
}
#undef module_need
module_t *module_need(vlc_object_t *obj, const char *cap, const char *name,
bool strict)
{
const bool b_force_backup = obj->force; /* FIXME: remove this */
module_t *module = vlc_module_load(obj->logger, cap, name, strict,
generic_start, obj);
if (module != NULL) {
var_Create(obj, "module-name", VLC_VAR_STRING);
var_SetString(obj, "module-name", module_get_object(module));
}
obj->force = b_force_backup;
return module;
}
#undef module_unneed
void module_unneed(vlc_object_t *obj, module_t *module)
{
msg_Dbg(obj, "removing \"%s\" module \"%s\"", module_get_capability(module),
module_get_object(module));
var_Destroy(obj, "module-name");
if (module->deactivate != NULL)
module->deactivate(obj);
vlc_objres_clear(obj);
}
module_t *module_find (const char *name)
{
size_t count;
module_t **list = module_list_get (&count);
assert (name != NULL);
for (size_t i = 0; i < count; i++)
{
module_t *module = list[i];
if (unlikely(module->i_shortcuts == 0))
continue;
if (!strcmp (module->pp_shortcuts[0], name))
{
module_list_free (list);
return module;
}
}
module_list_free (list);
return NULL;
}
module_config_t *module_config_get( const module_t *module, unsigned *restrict psize )
{
const vlc_plugin_t *plugin = module->plugin;
assert( psize != NULL );
*psize = 0;
if (plugin->module != module)
{ /* For backward compatibility, pretend non-first modules have no
* configuration items. */
return NULL;
}
size_t size = plugin->conf.size;
module_config_t *config = vlc_alloc( size, sizeof( *config ) );
if( !config )
return NULL;
unsigned i, j;
for( i = 0, j = 0; i < size; i++ )
{
const struct vlc_param *param = plugin->conf.params + i;
const module_config_t *item = ¶m->item;
if (param->internal /* internal option */
|| param->obsolete /* removed option */)
continue;
memcpy( config + j, item, sizeof( *config ) );
j++;
}
*psize = j;
return config;
}
void module_config_free( module_config_t *config )
{
free( config );
}
¤ Dauer der Verarbeitung: 0.5 Sekunden
¤
*© Formatika GbR, Deutschland
|
|