+module_t *module_hold (module_t *m)
+{
+ vlc_hold (&m->vlc_gc_data);
+ return m;
+}
+
+void module_release (module_t *m)
+{
+ vlc_release (&m->vlc_gc_data);
+}
+
+/**
+ * Frees the flat list of VLC modules.
+ * @param list list obtained by module_list_get
+ * @param length number of items on the list
+ * @return nothing.
+ */
+void module_list_free (module_t **list)
+{
+ if (list == NULL)
+ return;
+
+ for (size_t i = 0; list[i] != NULL; i++)
+ module_release (list[i]);
+ free (list);
+}
+
+/**
+ * Gets the flat list of VLC modules.
+ * @param n [OUT] pointer to the number of modules or NULL
+ * @return NULL-terminated table of module pointers
+ * (release with module_list_free()), or NULL in case of error.
+ */
+module_t **module_list_get (size_t *n)
+{
+ /* TODO: this whole module lookup is quite inefficient */
+ /* Remove this and improve module_need */
+ module_t **tab = NULL;
+ size_t i = 0;
+
+ for (module_t *mod = p_module_bank->head; mod; mod = mod->next)
+ {
+ module_t **nt;
+ nt = realloc (tab, (i + 2 + mod->submodule_count) * sizeof (*tab));
+ if (nt == NULL)
+ {
+ module_list_free (tab);
+ return NULL;
+ }
+
+ tab = nt;
+ tab[i++] = module_hold (mod);
+ for (module_t *subm = mod->submodule; subm; subm = subm->next)
+ tab[i++] = module_hold (subm);
+ tab[i] = NULL;
+ }
+ if (n != NULL)
+ *n = i;
+ return tab;
+}
+
+typedef struct module_list_t
+{
+ module_t *p_module;
+ uint16_t i_score;
+ bool b_force;
+} module_list_t;
+
+static int modulecmp (const void *a, const void *b)
+{
+ const module_list_t *la = a, *lb = b;
+ /* Note that qsort() uses _ascending_ order,
+ * so the smallest module is the one with the biggest score. */
+ return lb->i_score - la->i_score;
+}
+