\section{Architecture de VLC}

VLC est découpé en plusieurs parties. Deux parties ressortent particulièrement
comme étant des bibliothèques charnières pour le fonctionnement du logiciel.
D'un côté, les applications finales utilisent l'interface exposée par la
LibVLC. L'objectif est d'avoir quelque chose de très haut niveau pour
construire un pipeline sans avoir besoin des considérations techniques liées au
multimédia.

De l'autre LibVLC fonctionne à travers la LibVLCCore qui expose les fonctions
bas niveau de chargement de module et contrôle les threads, les modules, les
horloges, la liste de lecture et tout le contrôle bas niveau dans VLC. Les
modules sont alors linkés à la LibVLCCore pour profiter des fonctions bas
niveau.

% Mettre schéma
\begin{figure}[htbp]
    \centering
    \includegraphics[width = 300pt]{schemas/vlc_libvlc}
    \caption{Architecture des applications utilisant libvlc}
\end{figure}

En résumé LibVLC expose l'API tandis que LibVLCCore réalise le lien entre les
différents modules. La sélection des modules à utiliser est donc au cœur du
développement de VLC, ce qui rend le core bien plus maintenable que les modules
eux-mêmes.

Il faut néanmoins noter que les modules sont chargés à partir du moment où un
autre module le demande. C'est ce qui crée la notion de pipeline dynamique:
seuls les modules apportant les fonctionnalités requises par un autre module
sont injectés dans le pipeline. Ces modules sont alors chargés soit de façon
statique, soit depuis une bibliothèque de code dynamique.

Actuellement, le développement de VLC est beaucoup centré sur son approche
multi-thread, par exemple pour que les décodeurs et les sorties fonctionnent de
manière indépendante et correctement synchroniser le temps. Le décodeur et la
sortie vidéo fonctionnent ainsi de manière asynchrone. L'idée centrale est
qu'avoir plusieurs entrées en lecture et plusieurs sorties simultanément ne doit
pas être impossible. Une démonstration de cette fonction a d'ailleurs été mis en
place en tant que \og{}VLM\fg{}, qui permet de contrôler plusieurs flux en entrées et de
choisir comment les utiliser en sortie; que ce soit en les diffusant, en créant
une mosaïque ou en affichant des flux dans de nouvelles sorties.

\section{Variables de configuration}

La gestion de la configuration des modules dans VLC passe principalement par un
système d'objet à travers le type \inltype{vlc_object_t}. Tous les modules de
VLC sont représentés comme un \inltype{vlc_object_t} tout comme certains
éléments du core et la LibVLC elle-même. Ces objets sont liés à un objet
\inltype{libvlc_instance_t} particulier et sont agencés en arbre d'objet.

On peut associer des variables à ces objets en leur faisant suivre certaines
règles. On peut par exemple les créer avec une valeur par défaut, les créer sans
leur donner de valeur ou bien les créer en les initialisant récursivement avec
la valeur du parent.

Ces variables portent ainsi une configuration qui leur est propre, venant de la
configuration imposée ou suggérée par leur parent, qui vient de la configuration
donnée en ligne de commande ou qui vient du fichier de configuration de VLC.\@
Il s'agit donc d'un mélange entre une interface utilisateur et une interface
entre modules.

Dans notre cas, c'est particulièrement important car il y a trois possibilités
dans le modèle multiprocessus.  Où bien les variables sont toutes définies dans
le même processus, où bien l'arbre de variable est découpé dans plusieurs
processus et il faut refaire le lien entre les objets, ou bien chaque processus
ne dispose que d'une projection de l'arbre. Nous verrons dans la suite comment 
gérer les deux premiers cas, mais pour des raisons de simplicité et performance
c'est la troisième option qui est actuellement utilisée.

\section{Modules}

Le principal de l'architecture actuelle de VLC est organisé autour de la notion
de module. D'un côté, le core contrôle le chargement des fonctionnalités et joue
un rôle d'orchestrateur. De l'autre côté chaque fonctionnalité est apportée par
un module qui peut être chargé dynamiquement ou lié statiquement à
l'application.

Les modules sont manipulés à travers les \inltype{vlc_plugin_t} qui eux-même
manipulent les \inltype{module_t} contenant la représentation interne du module.

% TODO: décrire plus exactement ce qu'il faut highlight, en particulier
% chargement des modules dans la sandbox, stockage des options, etc
\begin{code}{c}{Structure d'un plugin}
typedef struct vlc_plugin_t
{
    struct vlc_plugin_t *next;
    module_t *module;
    unsigned modules_count;

    const char *textdomain; /**< gettext domain (or NULL) */

    /* Variables set by the module to store its config options */
    struct
    {
        module_config_t *items; /**< Table of configuration parameters */
        size_t size; /**< Size of items table */
        size_t count; /**< Number of configuration items */
        size_t booleans; /**< Number of booleal config items */
    } conf;

#ifdef HAVE_DYNAMIC_PLUGINS
    bool unloadable; /**< Whether the plug-in can be unloaded safely */
    atomic_uintptr_t handle; /**< Run-time linker handle (or nul) */
    char *abspath; /**< Absolute path */

    char *path; /**< Relative path (within plug-in directory) */
    int64_t mtime; /**< Last modification time */
    uint64_t size; /**< File size */
#endif
} vlc_plugin_t;
\end{code}

\inltype{vlc_plugin_t} contient ainsi les informations pour charger et décharger
les modules.

\clearpage
\begin{code}{c}{Structure d'un module}
struct module_t
{
    vlc_plugin_t *plugin; /**< Plug-in/library containing the module */
    module_t   *next;

    /** Shortcuts to the module */
    unsigned    i_shortcuts;
    const char **pp_shortcuts;

    /*
     * Variables set by the module to identify itself
     */
    const char *psz_shortname;                              /**< Module name */
    const char *psz_longname;                   /**< Module descriptive name */
    const char *psz_help;        /**< Long help string for "special" modules */

    const char *psz_capability;                              /**< Capability */
    int      i_score;                          /**< Score for the capability */

    /* Callbacks */
    const char *activate_name;
    const char *deactivate_name;
    void *pf_activate;
    void *pf_deactivate;
};
\end{code}

De l'autre côté, \inltype{module_t} contient la description d'un module, qu'il
soit chargé dynamiquement ou non.

Chaque module dispose d'une priorité, qui correspond au score \inltype{i_score}
dans \inltype{module_t}.

Ces modules sont chargés dans l'application depuis deux fonctions du core:
\begin{itemize}
    \item \inltype{module_need} permet de charger un module correspondant au nom ou à la
fonction \inltype{i_capability} du module, en utilisant le premier module de plus forte
priorité qui est capable de se charger sans erreur.
    \item \inltype{module_need_var} qui dans les faits appelle \inltype{module_need} en lui donnant le
contenu d'une variable au lieu d'une recherche hardcodée.
\end{itemize}

Les détails de ces fonctions sont décrits ici car il s'agit de l'interface
exposée par VLC pour charger un nouveau module. C'est donc un point d'entrée
potentiel pour l'injection des abstractions de la sandbox.

\begin{code}{c}{API de requête de module}
module_t *vlc_module_load(vlc_object_t *obj, const char *capability,
                          const char *name, bool strict,
                          vlc_activate_t probe, ...);

module_t *module_need(vlc_object_t *obj, const char *cap, const char *name,
                      bool strict)
\end{code}

Ces fonctions sont généralement appelées après avoir créé un objet correspondant
au type du module en question. Si dessous, on peut voir un exemple au sein de
l'API de gestion des documents XML.\@

\begin{code}{c}{Création d'objet VLC puis chargement de modules}
    /* from src/misc/xml.c */
    p_xml = vlc_custom_create( p_this, sizeof( *p_xml ), "xml" );
    p_xml->p_module = module_need( p_xml, "xml", NULL, false );

    reader = vlc_custom_create(obj, sizeof(*reader), "xml reader");
    reader->p_module = module_need(reader, "xml reader", NULL, false);
\end{code}

Par exemple, nous avons ici la création d'un objet représentant un module
d'analyse syntaxique XML. Le module est ensuite chargé dans l'objet. Puis un
autre couple d'objet et module est chargé, cette fois-ci pour une \inltype{i_capability}
de type \inltype{xml_reader}. 

Cela montre en particulier que l'application ne va pas manipuler directement le
module, mais un objet lié à ce module. Ce pattern va nous permettre de concevoir
une façon simple de sandboxer ces modules en patchant la fonction
\inltype{module_need},
qui sera rapidement décrite dans la suite.
