La playlist dans totem
Voici une étude du chargement d'une playlist dans totem-xine. J'essayerais d'indiquer ce que j'ai fait et de résumer ce que j'aurais pu faire. Il s'agit d'une étude remplit d'essais et d'erreurs. Le but est de trouver comment totem charge une playlist asf et pourquoi il charge la playlist en UTF-8 même si le charset du serveur envoit du charset=iso-8859-1.
Avoir le source
sous debian $ apt-get source totem-xine $ su -c "apt-get build-dep totem-xine" $ cd totem-2.16.5 # la version peut variée
L'entrée des paramètres
On peut entrer les paramètres suivants à la ligne de commande: $ totem --debug "http://www.site.com/playlist.php?type=asf"
La première rechercher est de savoir à quel endroit il:
- 1. initialise le programme
- 2. charge les options
- 3. gère l'URL
Tout programme en C, et surtout en linux (pour le type de retour int) commence par un int main(int argc, char **argv) ou int main(int argc, char *argv[]). Il y a plusieurs syntaxe pour les paramètres et l'indentation peut variée. On suppose que le type de retour est int. On peut donc faire dans le répertoire de "src" de totem: grep -ERn "main\s*\(int argc" *.c (c'est seulement une expression régulière qui indique qu'il peut y avoir 0 ou plusieurs espace (le \s*) entre le main et la parenthèse de paramètres. On obtient le résultat suivant:
list_v4l.c:30:int main (int argc, char **argv) metadata-test.c:160:int main (int argc, char **argv) test-properties-page.c:63:int main (int argc, char **argv) totem.c:3647:main (int argc, char **argv) totem-mozilla-viewer.c:835:int main (int argc, char **argv) totem-video-thumbnailer.c:330:int main (int argc, char *argv[]) vanity.c:631:main (int argc, char **argv)
On a plusieurs possibilités, on peut les essayer une par une ou encore se douter que le main principal va être dans le fichier "totem.c", ligne 3647. Habituellement, les programmes exécutables ont le même nom que le fichier .c, mais ce n'est pas tout le temps vrai. Donc on fait un vim totem.c +347 et regarder si on a vu juste.
L'important est de regarder le paramètre argc et argv et de le suivre dans la fonction main. On peut voir ces lignes:
3656 if (XInitThreads () == 0) 3657 { 3658 gtk_init (&argc, &argv); 3659 g_set_application_name (_("Totem Movie Player")); 3660 totem_action_error_and_exit (_("Could not initialize the thread-safe libraries."), _("Verify your system installation. Totem will now exit."), NULL); 3661 } ... 3665 #ifdef HAVE_GTK_ONLY 3666 gtk_init (&argc, &argv); 3667 #else 3668 gnome_program_init ("totem", VERSION, 3669 LIBGNOMEUI_MODULE, 3670 argc, argv, 3671 GNOME_PARAM_APP_DATADIR, DATADIR, 3672 GNOME_PARAM_POPT_TABLE, totem_options_get_options (), 3673 GNOME_PARAM_NONE); 3674 #endif /* HAVE_GTK_ONLY */
Ce qui me semble le plus intéressant, sur linux avec gnome est la fonction gnome_program_init. On peut aussi voir GNOME_PARAM_POPT_TABLE et totem_options_get_options(). Puisque j'ai déjà programmé en C, je sais que "popt" est un programme très utilisé pour analyser les paramètres (Parser OPTion). GNOME_PARAM_POPT_TABLE doit être son penchant gnome. (Voir aussi: man popt). Je rejette les deux premiers gtk_init parce que le premier semble mener vers une erreur et le second est utilisé seulement avec un paramètre HAVE_GTK_ONLY (sûrement en environnement sans GNOME). J'utilise donc la fonction find dans vim pour chercher la fonction totem_options_get_options. Puisque je ne trouve rien d'autre, je fais un :!grep -n "totem_options_get_options" *
totem.c: GNOME_PARAM_POPT_TABLE, totem_options_get_options (), totem-options.c:totem_options_get_options (void) totem-options.h:poptOption totem_options_get_options (void);
Le premier résultat est la ligne que nous examinons: rejet, le totem-options.h est la définition: rejet. Nous regardons donc :sp totem-options.c. 55j. La fonction est presque vide, on peut voir un peu plus haut la liste des options, comme debug, mais pas d'appels. Puisque debug est une option, on pourrait rechercher "debug", mais je crois instinctivement qu'il va y avoir trop de résultat. Recherchons une ligne qui peut avoir moins de lignes comme toggle-controls. :!grep -n "toggle-controls" *. On voit que dans le même fichier, l'option est gérée. Regardons le nom de la fonction: totem_options_process_late, regardons la suite des fonctions... totem_options_process_early. On peut voir le code pour la gestion de --debug:
134 if (strcmp (argv[i], "--debug") == 0) 135 { 136 gconf_client_set_bool (gc, GCONF_PREFIX"/debug", 137 TRUE, NULL);
Mais toujours rien pour notre dernier paramètre. Dans totem_options_process_for_server, on peut voir encore plus de traitement des options. Bon, ça se complique un peu, niveau code, mais suffit de lire ligne par ligne.
173 if (strlen (argv[1]) > 3 && g_str_has_prefix (argv[1], "--") == FALSE) 174 { 175 command = TOTEM_REMOTE_COMMAND_REPLACE; 176 i = 1;
Le code signifie: si le 2e argument (le premier, c'est le nom du programme) possède plus de 3 lettres et ne commence pas par "--", la valeur de la variable command est TOTEM_REMOTE_COMMAND_REPLACE. (Note: à lire ce code, on dirait que totem ne gère pas les playlist de 2 caractères). Je suppose que la gestion de --debug dans les fonctions plus haut a enlevé les paramètres précédents. argv[1] doit être l'URL. Puisqu'on a entré dans la condition if(), on lit ce qui suit (après tous les else):
230 for (; argv[i] != NULL; i++) 231 { 232 full_path = totem_create_full_path (argv[i]); 233 line = g_strdup_printf ("%03d %s", command, full_path); 234 bacon_message_connection_send (conn, line); 235 g_free (line); 236 g_free (full_path); 237 command = TOTEM_REMOTE_COMMAND_ENQUEUE; 238 }
Le code indique: pour tous les arguments restants, on exécute totem_create_full_path(argv[i]) et la commande bacon_message_connection_send(conn, TOTEM_REMOTE_COMMAND_ENQUEUE + " " + argv[i]. Remarquer que chaque argument après le premier argument sera traité comme un TOTEM_REMOTE_COMMAND_ENQUEUE.
À ce stade, il ne reste qu'à regarder la fonction totem_create_full_path. :!grep -n totem_create_full_path *". On peut trouver la ligne de déclaration:
totem-uri.c:91:totem_create_full_path (const char *path)
On ouvre le fichier: :sp totem-uri.c 90 j et on voit:
97 if (strstr (path, "://") != NULL) 98 return g_strdup (path);
Rah, il ne s'agissait qu'une ruse!, lorsqu'il y a "://" dans l'url, il ne fait que dupliquer la chaîne et allouer de la mémoire. C'est donc bacon_message_connection_send qui fait tout le travail avec l'option TOTEM_REMOTE_COMMAND_ENQUEUE.
Comprendre le bacon
Qu'est-ce qu'on fait? On recherche TOTEM_REMOTE_COMMAND_ENQUEUE bien attendu! !grep -n TOTEM_REMOTE_COMMAND_ENQUEUE *.c et qui nous retourne la ligne: totem.c:2252: case TOTEM_REMOTE_COMMAND_ENQUEUE:
On revient dans notre fichier totem.c, à la ligne 2252. Voici le code intéressant (les paramètres de la fonction, et le traitement de l'option)
2212 static void 2213 totem_action_remote (Totem *totem, TotemRemoteCommand cmd, const char *url) 2214 { 2215 gboolean handled = TRUE; 2216 2217 switch (cmd) { ... 2252 case TOTEM_REMOTE_COMMAND_ENQUEUE: 2253 g_assert (url != NULL); 2254 if (totem_playlist_add_mrl (totem->playlist, url, NULL) != FALSE) { 2255 totem_action_add_recent (totem, url); 2256 } 2257 break;
C'est donc la fonction totem_playlist_add_mrl qui traite l'URL de notre playlist. On fait une recherche dans les *.c, on trouve: totem-playlist.c:1600:totem_playlist_add_mrl (TotemPlaylist *playlist, const char *mrl,
. Et on observe le traitement de notre URL. Cette fonction appelle: totem_pl_parser_parse (playlist->_priv->parser, mrl, TRUE)
qui est dans le fichier plparse/totem-pl-parser.c, ligne 2452 (un autre grep -Rn) qui appelle totem_pl_parser_parse_internal (parser, url);
2366 static TotemPlParserResult 2367 totem_pl_parser_parse_internal (TotemPlParser *parser, const char *url)