[vlc-devel] [RFC PATCH 01/12] modules: add module_need_next and vlc_module_load_next
Thomas Guillem
thomas at gllm.fr
Tue Jul 19 19:36:23 CEST 2016
These functions save the previous state of a successful vlc_module_load(). A
second call to this function with the saved context allows to load a module
that come after the previous one (i.e. with a lower priority or after the list
given in command line).
TODO: document vlc_modules.h
---
include/vlc_modules.h | 5 ++
src/libvlccore.sym | 2 +
src/modules/modules.c | 162 +++++++++++++++++++++++++++++++++++++-------------
3 files changed, 128 insertions(+), 41 deletions(-)
diff --git a/include/vlc_modules.h b/include/vlc_modules.h
index 7f45217..238690d 100644
--- a/include/vlc_modules.h
+++ b/include/vlc_modules.h
@@ -36,10 +36,15 @@ typedef void (*vlc_deactivate_t)(void *func, va_list args);
VLC_API module_t * vlc_module_load( vlc_object_t *obj, const char *cap, const char *name, bool strict, vlc_activate_t probe, ... ) VLC_USED;
#define vlc_module_load(o,c,n,s,...) \
vlc_module_load(VLC_OBJECT(o),c,n,s,__VA_ARGS__)
+VLC_API module_t * vlc_module_load_next( vlc_object_t *obj, const char *cap, const char *name, bool strict, void **, vlc_activate_t probe, ... ) VLC_USED;
+#define vlc_module_load_next(o,c,n,s,t,...) \
+ vlc_module_load_next(VLC_OBJECT(o),c,n,s,t,__VA_ARGS__)
VLC_API void vlc_module_unload( module_t *, vlc_deactivate_t deinit, ... );
VLC_API module_t * module_need( vlc_object_t *, const char *, const char *, bool ) VLC_USED;
#define module_need(a,b,c,d) module_need(VLC_OBJECT(a),b,c,d)
+VLC_API module_t * module_need_next( vlc_object_t *, const char *, const char *, bool, void ** ) VLC_USED;
+#define module_need_next(a,b,c,d,e) module_need_next(VLC_OBJECT(a),b,c,d,e)
VLC_API void module_unneed( vlc_object_t *, module_t * );
#define module_unneed(a,b) module_unneed(VLC_OBJECT(a),b)
VLC_API bool module_exists(const char *) VLC_USED;
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 1e634dd..a83898d 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -269,9 +269,11 @@ module_gettext
module_list_free
module_list_get
module_need
+module_need_next
module_provides
module_unneed
vlc_module_load
+vlc_module_load_next
vlc_module_unload
vlc_Log
vlc_LogSet
diff --git a/src/modules/modules.c b/src/modules/modules.c
index 7ba6492..b39e3f4 100644
--- a/src/modules/modules.c
+++ b/src/modules/modules.c
@@ -188,41 +188,53 @@ static int module_load (vlc_object_t *obj, module_t *m,
return ret;
}
-#undef vlc_module_load
-/**
- * Finds and instantiates the best module of a certain type.
- * All candidates modules having the specified capability and name will be
- * sorted in decreasing order of priority. Then the probe callback will be
- * invoked for each module, until it succeeds (returns 0), or all candidate
- * module failed to initialize.
- *
- * The probe callback first parameter is the address of the module entry point.
- * Further parameters are passed as an argument list; it corresponds to the
- * variable arguments passed to this function. This scheme is meant to
- * support arbitrary prototypes for the module entry point.
- *
- * \param obj VLC object
- * \param capability capability, i.e. class of module
- * \param name name of the module asked, if any
- * \param strict if true, do not fallback to plugin with a different name
- * but the same capability
- * \param probe module probe callback
- * \return the module or NULL in case of a failure
- */
-module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
- const char *name, bool strict,
- vlc_activate_t probe, ...)
+static module_t *
+vlc_module_load_common(vlc_object_t *obj, const char *capability,
+ const char *name, bool strict, void **saveptr,
+ vlc_activate_t probe, va_list args)
{
- char *var = NULL;
+ struct savectx
+ {
+ const char *name;
+ size_t start_index;
+ char data[];
+ };
- if (name == NULL || name[0] == '\0')
- name = "any";
+ char *var = NULL;
+ struct savectx *savectx;
+ size_t start_index = 0;
- /* Deal with variables */
- if (name[0] == '$')
+ if (saveptr != NULL && *saveptr != NULL)
{
- var = var_InheritString (obj, name + 1);
- name = (var != NULL) ? var : "any";
+ savectx = *saveptr;
+ start_index = savectx->start_index;
+ name = savectx->name;
+ }
+ else
+ {
+ if (name == NULL || name[0] == '\0')
+ name = "any";
+
+ /* Deal with variables */
+ if (name[0] == '$')
+ {
+ var = var_InheritString (obj, name + 1);
+ name = (var != NULL) ? var : "any";
+ }
+ if (saveptr != NULL)
+ {
+ savectx = malloc(sizeof(struct savectx) + strlen(name) + 1);
+ if (savectx == NULL)
+ {
+ free(var);
+ return NULL;
+ }
+ strcpy(savectx->data, name);
+ name = savectx->name = savectx->data;
+ *saveptr = savectx;
+ }
+ else
+ savectx = NULL;
}
/* Find matching modules */
@@ -231,18 +243,16 @@ module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
msg_Dbg (obj, "looking for %s module matching \"%s\": %zd candidates",
capability, name, total);
+
+ module_t *module = NULL;
+ const bool b_force_backup = obj->obj.force; /* FIXME: remove this */
if (total <= 0)
{
- module_list_free (mods);
msg_Dbg (obj, "no %s modules", capability);
- return NULL;
+ goto done;
}
+ assert((size_t)total > start_index);
- module_t *module = NULL;
- const bool b_force_backup = obj->obj.force; /* FIXME: remove this */
- va_list args;
-
- va_start(args, probe);
while (*name)
{
char buf[32];
@@ -265,7 +275,7 @@ module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
goto done;
obj->obj.force = strict && strcasecmp ("any", shortcut);
- for (ssize_t i = 0; i < total; i++)
+ for (ssize_t i = start_index; i < total; i++)
{
module_t *cand = mods[i];
if (cand == NULL)
@@ -278,19 +288,21 @@ module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
switch (ret)
{
case VLC_SUCCESS:
+ start_index = i + 1;
module = cand;
/* fall through */
case VLC_ETIMEOUT:
goto done;
}
}
+ start_index = 0;
}
/* None of the shortcuts matched, fall back to any module */
if (!strict)
{
obj->obj.force = false;
- for (ssize_t i = 0; i < total; i++)
+ for (ssize_t i = start_index; i < total; i++)
{
module_t *cand = mods[i];
if (cand == NULL || module_get_score (cand) <= 0)
@@ -300,30 +312,91 @@ module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
switch (ret)
{
case VLC_SUCCESS:
+ start_index = i + 1;
module = cand;
/* fall through */
case VLC_ETIMEOUT:
goto done;
}
}
+ start_index = 0;
}
done:
- va_end (args);
obj->obj.force = b_force_backup;
module_list_free (mods);
free (var);
if (module != NULL)
{
+ if (savectx != NULL)
+ {
+ assert(name >= savectx->data
+ && name <= savectx->data + strlen(savectx->data));
+ savectx->name = name;
+ savectx->start_index = start_index < (size_t)total ? start_index : 0;
+ }
+
msg_Dbg (obj, "using %s module \"%s\"", capability,
module_get_object (module));
vlc_object_set_name (obj, module_get_object (module));
}
else
+ {
msg_Dbg (obj, "no %s modules matched", capability);
+ free(savectx);
+ if (saveptr != NULL)
+ *saveptr = NULL;
+ }
return module;
}
+#undef vlc_module_load
+/**
+ * Finds and instantiates the best module of a certain type.
+ * All candidates modules having the specified capability and name will be
+ * sorted in decreasing order of priority. Then the probe callback will be
+ * invoked for each module, until it succeeds (returns 0), or all candidate
+ * module failed to initialize.
+ *
+ * The probe callback first parameter is the address of the module entry point.
+ * Further parameters are passed as an argument list; it corresponds to the
+ * variable arguments passed to this function. This scheme is meant to
+ * support arbitrary prototypes for the module entry point.
+ *
+ * \param obj VLC object
+ * \param capability capability, i.e. class of module
+ * \param name name of the module asked, if any
+ * \param strict if true, do not fallback to plugin with a different name
+ * but the same capability
+ * \param probe module probe callback
+ * \return the module or NULL in case of a failure
+ */
+module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
+ const char *name, bool strict,
+ vlc_activate_t probe, ...)
+{
+ va_list args;
+
+ va_start(args, probe);
+ module_t *module = vlc_module_load_common(obj, capability, name, strict,
+ NULL, probe, args);
+ va_end (args);
+ return module;
+}
+
+#undef vlc_module_load_next
+module_t *vlc_module_load_next(vlc_object_t *obj, const char *capability,
+ const char *name, bool strict, void **saveptr,
+ vlc_activate_t probe, ...)
+{
+ va_list args;
+
+ va_start(args, probe);
+ module_t *module = vlc_module_load_common(obj, capability, name, strict,
+ saveptr, probe, args);
+ va_end (args);
+ return module;
+}
/**
* Deinstantiates a module.
@@ -366,6 +439,13 @@ module_t *module_need(vlc_object_t *obj, const char *cap, const char *name,
return vlc_module_load(obj, cap, name, strict, generic_start, obj);
}
+#undef module_need_next
+module_t *module_need_next(vlc_object_t *obj, const char *cap, const char *name,
+ bool strict, void **saveptr)
+{
+ return vlc_module_load_next(obj, cap, name, strict, saveptr, generic_start, obj);
+}
+
#undef module_unneed
void module_unneed(vlc_object_t *obj, module_t *module)
{
--
2.8.1
More information about the vlc-devel
mailing list