gst/gst.c (gst_init_check): Ignore unknown options, as has always been the case.
[platform/upstream/gstreamer.git] / gst / gst.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gst.c: Initialization and non-pipeline operations
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 /**
23  * SECTION:gst
24  * @short_description: Media library supporting arbitrary formats and filter graphs.
25  * @see_also: Check out both <ulink url="http://www.cse.ogi.edu/sysl/">OGI's
26  *   pipeline</ulink> and Microsoft's DirectShow for some background.
27  *
28  * GStreamer is a framework for constructing graphs of various filters
29  * (termed elements here) that will handle streaming media.  Any discreet
30  * (packetizable) media type is supported, with provisions for automatically
31  * determining source type.  Formatting/framing information is provided with
32  * a powerful negotiation framework.  Plugins are heavily used to provide for
33  * all elements, allowing one to construct plugins outside of the GST
34  * library, even released binary-only if license require (please don't).
35  * 
36  * GStreamer borrows heavily from both the <ulink
37  * url="http://www.cse.ogi.edu/sysl/">OGI media pipeline</ulink> and
38  * Microsoft's DirectShow, hopefully taking the best of both and leaving the
39  * cruft behind.  Its interface is still very fluid and thus can be changed 
40  * to increase the sanity/noise ratio.
41  *
42  * The <application>GStreamer</application> library should be initialized with
43  * gst_init() before it can be used. You should pass pointers to the main argc
44  * and argv variables so that GStreamer can process its own command line
45  * options, as shown in the following example.
46  *
47  * <example>
48  * <title>Initializing the gstreamer library</title>
49  * <programlisting language="c">
50  * int 
51  * main (int argc, char *argv[])
52  * {
53  *   // initialize the GStreamer library
54  *   gst_init (&amp;argc, &amp;argv);
55  *   ...
56  * }
57  * </programlisting>
58  * </example>
59  * 
60  * It's allowed to pass two NULL pointers to gst_init() in case you don't want to
61  * pass the command line args to GStreamer.
62  *
63  * You can also use a popt table to initialize your own parameters as shown in
64  * the next code fragment:
65  * <example>
66  * <title>Initializing own parameters when initializing gstreamer</title>
67  * <programlisting>
68  * static gboolean stats = FALSE;
69  * ...
70  *  
71  * int 
72  * main (int argc, char *argv[])
73  * {
74  *   struct poptOption options[] = {
75  *     { "stats",  's',  POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   &amp;stats,   0,
76  *         "Show pad stats", NULL},
77  *       POPT_TABLEEND
78  *     };
79  *   
80  *   // initialize the GStreamer library
81  *   gst_init_with_popt_table (&amp;argc, &amp;argv, options);
82  *   
83  *   ...
84  * }
85  * </programlisting>
86  * </example>
87  *
88  * Use gst_version() to query the library version at runtime or use the GST_VERSION_* macros
89  * to find the version at compile time.
90  *
91  * The functions gst_main() and gst_main_quit() enter and exit the main loop.
92  * GStreamer doesn't currently require you to use a mainloop but can intergrate
93  * with it without problems.
94  */
95
96 #include <stdlib.h>
97 #include <stdio.h>
98
99 #include "gst_private.h"
100 #include "gst-i18n-lib.h"
101 #include <locale.h>             /* for LC_ALL */
102
103 #include "gst.h"
104 #include "gstqueue.h"
105
106 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
107
108 #define MAX_PATH_SPLIT  16
109 #define GST_PLUGIN_SEPARATOR ","
110
111 #ifndef GST_DISABLE_REGISTRY
112 gboolean _gst_registry_auto_load = TRUE;
113 #endif
114
115 static gboolean gst_initialized = FALSE;
116
117 extern gint _gst_trace_on;
118
119 /* set to TRUE when segfaults need to be left as is */
120 gboolean _gst_disable_segtrap = FALSE;
121
122
123 static void load_plugin_func (gpointer data, gpointer user_data);
124 static gboolean init_pre (void);
125 static gboolean init_post (void);
126 static gboolean parse_goption_arg (const gchar * s_opt,
127     const gchar * arg, gpointer data, GError ** err);
128
129 static GSList *preload_plugins = NULL;
130
131 const gchar *g_log_domain_gstreamer = "GStreamer";
132
133 static void
134 debug_log_handler (const gchar * log_domain,
135     GLogLevelFlags log_level, const gchar * message, gpointer user_data)
136 {
137   g_log_default_handler (log_domain, log_level, message, user_data);
138   /* FIXME: do we still need this ? fatal errors these days are all
139    * other than core errors */
140   /* g_on_error_query (NULL); */
141 }
142
143 enum
144 {
145   ARG_VERSION = 1,
146   ARG_FATAL_WARNINGS,
147 #ifndef GST_DISABLE_GST_DEBUG
148   ARG_DEBUG_LEVEL,
149   ARG_DEBUG,
150   ARG_DEBUG_DISABLE,
151   ARG_DEBUG_NO_COLOR,
152   ARG_DEBUG_HELP,
153 #endif
154   ARG_PLUGIN_SPEW,
155   ARG_PLUGIN_PATH,
156   ARG_PLUGIN_LOAD,
157   ARG_SEGTRAP_DISABLE
158 };
159
160 /* debug-spec ::= category-spec [, category-spec]*
161  * category-spec ::= category:val | val
162  * category ::= [^:]+
163  * val ::= [0-5]
164  */
165
166 #ifndef NUL
167 #define NUL '\0'
168 #endif
169
170 static gboolean
171 parse_debug_category (gchar * str, const gchar ** category)
172 {
173   if (!str)
174     return FALSE;
175
176   /* works in place */
177   g_strstrip (str);
178
179   if (str[0] != NUL) {
180     *category = str;
181     return TRUE;
182   }
183
184   return FALSE;
185 }
186
187 static gboolean
188 parse_debug_level (gchar * str, gint * level)
189 {
190   if (!str)
191     return FALSE;
192
193   /* works in place */
194   g_strstrip (str);
195
196   if (str[0] != NUL && str[1] == NUL
197       && str[0] >= '0' && str[0] < '0' + GST_LEVEL_COUNT) {
198     *level = str[0] - '0';
199     return TRUE;
200   }
201
202   return FALSE;
203 }
204
205 static void
206 parse_debug_list (const gchar * list)
207 {
208   gchar **split;
209   gchar **walk;
210
211   g_return_if_fail (list != NULL);
212
213   split = g_strsplit (list, ",", 0);
214
215   for (walk = split; *walk; walk++) {
216     if (strchr (*walk, ':')) {
217       gchar **values = g_strsplit (*walk, ":", 2);
218
219       if (values[0] && values[1]) {
220         gint level;
221         const gchar *category;
222
223         if (parse_debug_category (values[0], &category)
224             && parse_debug_level (values[1], &level))
225           gst_debug_set_threshold_for_name (category, level);
226       }
227
228       g_strfreev (values);
229     } else {
230       gint level;
231
232       if (parse_debug_level (*walk, &level))
233         gst_debug_set_default_threshold (level);
234     }
235   }
236
237   g_strfreev (split);
238 }
239
240 #ifndef GST_HAVE_GLIB_2_8
241 #define G_OPTION_FLAG_NO_ARG 0
242 #endif
243
244 /**
245  * gst_init_get_option_group:
246  *
247  * Returns a #GOptionGroup with GStreamer's argument specifications. The
248  * group is set up to use standard GOption callbacks, so when using this
249  * group in combination with GOption parsing methods, all argument parsing
250  * and initialization is automated.
251  *
252  * This function is useful if you want to integrate GStreamer with other
253  * libraries that use GOption.
254  *
255  * Returns: a pointer to a GStreamer option group. Should be dereferenced
256  * after use.
257  */
258
259 GOptionGroup *
260 gst_init_get_option_group (void)
261 {
262   GOptionGroup *group;
263   static GOptionEntry gst_args[] = {
264     {"gst-version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
265         parse_goption_arg, N_("Print the GStreamer version"), NULL},
266     {"gst-fatal-warnings", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
267         parse_goption_arg, N_("Make all warnings fatal"), NULL},
268 #ifndef GST_DISABLE_GST_DEBUG
269     {"gst-debug-help", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
270           parse_goption_arg, N_("Print available debug categories and exit"),
271         NULL},
272     {"gst-debug-level", 0, 0, G_OPTION_ARG_CALLBACK, parse_goption_arg,
273           N_("Default debug level from 1 (only error) to 5 (anything) or "
274               "0 for no output"),
275         N_("LEVEL")},
276     {"gst-debug", 0, 0, G_OPTION_ARG_CALLBACK, parse_goption_arg,
277           N_("Comma-separated list of category_name:level pairs to set "
278               "specific levels for the individual categories. Example: "
279               "GST_AUTOPLUG:5,GST_ELEMENT_*:3"),
280         N_("LIST")},
281     {"gst-debug-no-color", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
282         parse_goption_arg, N_("Disable colored debugging output"), NULL},
283     {"gst-debug-disable", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
284         parse_goption_arg, N_("Disable debugging"), NULL},
285 #endif
286     {"gst-plugin-spew", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
287           parse_goption_arg, N_("Enable verbose plugin loading diagnostics"),
288         NULL},
289     {"gst-plugin-path", 0, 0, G_OPTION_ARG_CALLBACK, parse_goption_arg,
290         N_("Colon-separated paths containing plugins"), N_("PATHS")},
291     {"gst-plugin-load", 0, 0, G_OPTION_ARG_CALLBACK, parse_goption_arg,
292           N_("Comma-separated list of plugins to preload in addition to the "
293               "list stored in environment variable GST_PLUGIN_PATH"),
294         N_("PLUGINS")},
295     {"gst-disable-segtrap", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
296           parse_goption_arg,
297           N_("Disable trapping of segmentation faults during plugin loading"),
298         NULL},
299     {NULL}
300   };
301
302   group = g_option_group_new ("gst", _("GStreamer Options"),
303       _("Show GStreamer Options"), NULL, NULL);
304   g_option_group_set_parse_hooks (group, (GOptionParseFunc) init_pre,
305       (GOptionParseFunc) init_post);
306
307   g_option_group_add_entries (group, gst_args);
308   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
309
310   return group;
311 }
312
313 /**
314  * gst_init_check:
315  * @argc: pointer to application's argc
316  * @argv: pointer to application's argv
317  * @err: pointer to a #GError to which a message will be posted on error
318  *
319  * Initializes the GStreamer library, setting up internal path lists,
320  * registering built-in elements, and loading standard plugins.
321  *
322  * This function will return %FALSE if GStreamer could not be initialized
323  * for some reason.  If you want your program to fail fatally,
324  * use gst_init() instead.
325  *
326  * Returns: %TRUE if GStreamer could be initialized.
327  */
328 gboolean
329 gst_init_check (int *argc, char **argv[], GError ** err)
330 {
331   GOptionGroup *group;
332   GOptionContext *ctx;
333   gboolean res;
334
335   if (gst_initialized) {
336     GST_DEBUG ("already initialized gst");
337     return TRUE;
338   }
339
340   ctx = g_option_context_new ("- GStreamer initialization");
341   g_option_context_set_ignore_unknown_options (ctx, TRUE);
342   group = gst_init_get_option_group ();
343   g_option_context_add_group (ctx, group);
344   res = g_option_context_parse (ctx, argc, argv, err);
345   g_option_context_free (ctx);
346
347   if (res) {
348     gst_initialized = TRUE;
349   }
350
351   return res;
352 }
353
354 /**
355  * gst_init:
356  * @argc: pointer to application's argc
357  * @argv: pointer to application's argv
358  *
359  * Initializes the GStreamer library, setting up internal path lists,
360  * registering built-in elements, and loading standard plugins.
361  *
362  * This function will terminate your program if it was unable to initialize
363  * GStreamer for some reason.  If you want your program to fall back,
364  * use gst_init_check() instead.
365  *
366  * WARNING: This function does not work in the same way as corresponding
367  * functions in other glib-style libraries, such as gtk_init().  In
368  * particular, unknown command line options cause this function to
369  * abort program execution.
370  */
371 void
372 gst_init (int *argc, char **argv[])
373 {
374   GError *err = NULL;
375
376   if (!gst_init_check (argc, argv, &err)) {
377     g_print ("Could not initialized GStreamer: %s\n",
378         err ? err->message : "unknown error occurred");
379     if (err) {
380       g_error_free (err);
381     }
382     exit (1);
383   }
384 }
385
386 #ifndef GST_DISABLE_REGISTRY
387 static void
388 add_path_func (gpointer data, gpointer user_data)
389 {
390   GST_INFO ("Adding plugin path: \"%s\"", (gchar *) data);
391   gst_registry_scan_path (gst_registry_get_default (), (gchar *) data);
392 }
393 #endif
394
395 static void
396 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
397 {
398   preload_plugins = g_slist_prepend (preload_plugins, data);
399 }
400
401 static void
402 load_plugin_func (gpointer data, gpointer user_data)
403 {
404   GstPlugin *plugin;
405   const gchar *filename;
406   GError *err = NULL;
407
408   filename = (const gchar *) data;
409
410   plugin = gst_plugin_load_file (filename, &err);
411
412   if (plugin) {
413     GST_INFO ("Loaded plugin: \"%s\"", filename);
414
415     gst_default_registry_add_plugin (plugin);
416   } else {
417     if (err) {
418       /* Report error to user, and free error */
419       GST_ERROR ("Failed to load plugin: %s\n", err->message);
420       g_error_free (err);
421     } else {
422       GST_WARNING ("Failed to load plugin: \"%s\"", filename);
423     }
424   }
425
426   g_free (data);
427 }
428
429 static void
430 split_and_iterate (const gchar * stringlist, gchar * separator, GFunc iterator,
431     gpointer user_data)
432 {
433   gchar **strings;
434   gint j = 0;
435   gchar *lastlist = g_strdup (stringlist);
436
437   while (lastlist) {
438     strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
439     g_free (lastlist);
440     lastlist = NULL;
441
442     while (strings[j]) {
443       iterator (strings[j], user_data);
444       if (++j == MAX_PATH_SPLIT) {
445         lastlist = g_strdup (strings[j]);
446         g_strfreev (strings);
447         j = 0;
448         break;
449       }
450     }
451     g_strfreev (strings);
452   }
453 }
454
455 /* we have no fail cases yet, but maybe in the future */
456 static gboolean
457 init_pre (void)
458 {
459   g_type_init ();
460
461   if (g_thread_supported ()) {
462     /* somebody already initialized threading */
463   } else {
464     g_thread_init (NULL);
465   }
466   /* we need threading to be enabled right here */
467   _gst_debug_init ();
468
469 #ifdef ENABLE_NLS
470   setlocale (LC_ALL, "");
471   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
472 #endif /* ENABLE_NLS */
473
474 #ifndef GST_DISABLE_REGISTRY
475   {
476     const gchar *debug_list;
477
478     if (g_getenv ("GST_DEBUG_NO_COLOR") != NULL)
479       gst_debug_set_colored (FALSE);
480
481     debug_list = g_getenv ("GST_DEBUG");
482     if (debug_list) {
483       parse_debug_list (debug_list);
484     }
485   }
486 #endif
487   /* This is the earliest we can make stuff show up in the logs.
488    * So give some useful info about GStreamer here */
489   GST_INFO ("Initializing GStreamer Core Library version %s", VERSION);
490   GST_INFO ("Using library installed in %s", LIBDIR);
491
492   return TRUE;
493 }
494
495 static gboolean
496 gst_register_core_elements (GstPlugin * plugin)
497 {
498   /* register some standard builtin types */
499   if (!gst_element_register (plugin, "bin", GST_RANK_PRIMARY,
500           GST_TYPE_BIN) ||
501       !gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY,
502           GST_TYPE_PIPELINE) ||
503       !gst_element_register (plugin, "queue", GST_RANK_NONE, GST_TYPE_QUEUE)
504       )
505     g_assert_not_reached ();
506
507   return TRUE;
508 }
509
510 static GstPluginDesc plugin_desc = {
511   GST_VERSION_MAJOR,
512   GST_VERSION_MINOR,
513   "gstcoreelements",
514   "core elements of the GStreamer library",
515   gst_register_core_elements,
516   VERSION,
517   GST_LICENSE,
518   PACKAGE,
519   GST_PACKAGE,
520   GST_ORIGIN,
521
522   GST_PADDING_INIT
523 };
524
525 /*
526  * this bit handles:
527  * - initalization of threads if we use them
528  * - log handler
529  * - initial output
530  * - initializes gst_format
531  * - registers a bunch of types for gst_objects
532  *
533  * - we don't have cases yet where this fails, but in the future
534  *   we might and then it's nice to be able to return that
535  */
536 static gboolean
537 init_post (void)
538 {
539   GLogLevelFlags llf;
540
541 #ifndef GST_DISABLE_TRACE
542   GstTrace *gst_trace;
543 #endif /* GST_DISABLE_TRACE */
544
545   llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
546   g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
547
548   _gst_format_initialize ();
549   _gst_query_initialize ();
550   gst_object_get_type ();
551   gst_pad_get_type ();
552   gst_element_factory_get_type ();
553   gst_element_get_type ();
554   gst_type_find_factory_get_type ();
555   gst_bin_get_type ();
556
557 #ifndef GST_DISABLE_INDEX
558   gst_index_factory_get_type ();
559 #endif /* GST_DISABLE_INDEX */
560 #ifndef GST_DISABLE_URI
561   gst_uri_handler_get_type ();
562 #endif /* GST_DISABLE_URI */
563
564   /* register core plugins */
565   _gst_plugin_register_static (&plugin_desc);
566
567   gst_structure_get_type ();
568   _gst_value_initialize ();
569   gst_caps_get_type ();
570   _gst_plugin_initialize ();
571   _gst_event_initialize ();
572   _gst_buffer_initialize ();
573   _gst_message_initialize ();
574   _gst_tag_initialize ();
575
576 #ifndef GST_DISABLE_REGISTRY
577   {
578     char *registry_file;
579     const char *plugin_path;
580     GstRegistry *default_registry;
581
582     default_registry = gst_registry_get_default ();
583     registry_file = g_strdup (g_getenv ("GST_REGISTRY"));
584     if (registry_file == NULL) {
585       registry_file = g_build_filename (g_get_home_dir (),
586           ".gstreamer-0.9", "registry.xml", NULL);
587     }
588     GST_DEBUG ("Reading registry cache");
589     gst_registry_xml_read_cache (default_registry, registry_file);
590
591     /* GST_PLUGIN_PATH specifies a list of directories to scan for
592      * additional plugins.  These take precedence over the system plugins */
593     plugin_path = g_getenv ("GST_PLUGIN_PATH");
594     if (plugin_path) {
595       char **list;
596       int i;
597
598       GST_DEBUG ("GST_PLUGIN_PATH set to %s", plugin_path);
599       list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
600       for (i = 0; list[i]; i++) {
601         gst_registry_scan_path (default_registry, list[i]);
602       }
603       g_strfreev (list);
604     } else {
605       GST_DEBUG ("GST_PLUGIN_PATH not set");
606     }
607
608     /* GST_PLUGIN_SYSTEM_PATH specifies a list of plugins that are always
609      * loaded by default.  If not set, this defaults to the system-installed
610      * path, and the plugins installed in the user's home directory */
611     plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH");
612     if (plugin_path == NULL) {
613       char *home_plugins;
614
615       GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set");
616
617       /* plugins in the user's home directory take precedence over
618        * system-installed ones */
619       home_plugins = g_build_filename (g_get_home_dir (),
620           ".gstreamer-0.9", "plugins", NULL);
621       gst_registry_scan_path (default_registry, home_plugins);
622       g_free (home_plugins);
623
624       /* add the main (installed) library path */
625       gst_registry_scan_path (default_registry, PLUGINS_DIR);
626     } else {
627       char **list;
628       int i;
629
630       GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH set to %s", plugin_path);
631       list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
632       for (i = 0; list[i]; i++) {
633         gst_registry_scan_path (default_registry, list[i]);
634       }
635       g_strfreev (list);
636     }
637
638     gst_registry_xml_write_cache (default_registry, registry_file);
639
640     _gst_registry_remove_cache_plugins (default_registry);
641
642     g_free (registry_file);
643   }
644
645 #endif /* GST_DISABLE_REGISTRY */
646
647   /* if we need to preload plugins */
648   if (preload_plugins) {
649     g_slist_foreach (preload_plugins, load_plugin_func, NULL);
650     g_slist_free (preload_plugins);
651     preload_plugins = NULL;
652   }
653 #ifndef GST_DISABLE_TRACE
654   _gst_trace_on = 0;
655   if (_gst_trace_on) {
656     gst_trace = gst_trace_new ("gst.trace", 1024);
657     gst_trace_set_default (gst_trace);
658   }
659 #endif /* GST_DISABLE_TRACE */
660
661   return TRUE;
662 }
663
664 #ifndef GST_DISABLE_GST_DEBUG
665 static gboolean
666 select_all (GstPlugin * plugin, gpointer user_data)
667 {
668   return TRUE;
669 }
670
671 static gint
672 sort_by_category_name (gconstpointer a, gconstpointer b)
673 {
674   return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
675       gst_debug_category_get_name ((GstDebugCategory *) b));
676 }
677 static void
678 gst_debug_help (void)
679 {
680   GSList *list, *walk;
681   GList *list2, *g;
682
683   if (!init_post ())
684     exit (1);
685
686   list2 = gst_registry_plugin_filter (gst_registry_get_default (),
687       select_all, FALSE, NULL);
688
689   /* FIXME this is gross.  why don't debug have categories PluginFeatures? */
690   for (g = list2; g; g = g_list_next (g)) {
691     GstPlugin *plugin = GST_PLUGIN (g->data);
692
693     gst_plugin_load (plugin);
694   }
695   g_list_free (list2);
696
697   list = gst_debug_get_all_categories ();
698   walk = list = g_slist_sort (list, sort_by_category_name);
699
700   g_print ("\n");
701   g_print ("name                  level    description\n");
702   g_print ("---------------------+--------+--------------------------------\n");
703
704   while (walk) {
705     GstDebugCategory *cat = (GstDebugCategory *) walk->data;
706
707     if (gst_debug_is_colored ()) {
708       gchar *color = gst_debug_construct_term_color (cat->color);
709
710       g_print ("%s%-20s\033[00m  %1d %s  %s%s\033[00m\n",
711           color,
712           gst_debug_category_get_name (cat),
713           gst_debug_category_get_threshold (cat),
714           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
715           color, gst_debug_category_get_description (cat));
716       g_free (color);
717     } else {
718       g_print ("%-20s  %1d %s  %s\n", gst_debug_category_get_name (cat),
719           gst_debug_category_get_threshold (cat),
720           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
721           gst_debug_category_get_description (cat));
722     }
723     walk = g_slist_next (walk);
724   }
725   g_slist_free (list);
726   g_print ("\n");
727 }
728 #endif
729
730 static gboolean
731 parse_one_option (gint opt, const gchar * arg, GError ** err)
732 {
733   switch (opt) {
734     case ARG_VERSION:
735       g_print ("GStreamer Core Library version %s\n", GST_VERSION);
736       exit (0);
737     case ARG_FATAL_WARNINGS:{
738       GLogLevelFlags fatal_mask;
739
740       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
741       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
742       g_log_set_always_fatal (fatal_mask);
743       break;
744     }
745 #ifndef GST_DISABLE_GST_DEBUG
746     case ARG_DEBUG_LEVEL:{
747       gint tmp = 0;
748
749       tmp = strtol (arg, NULL, 0);
750       if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
751         gst_debug_set_default_threshold (tmp);
752       }
753       break;
754     }
755     case ARG_DEBUG:
756       parse_debug_list (arg);
757       break;
758     case ARG_DEBUG_NO_COLOR:
759       gst_debug_set_colored (FALSE);
760       break;
761     case ARG_DEBUG_DISABLE:
762       gst_debug_set_active (FALSE);
763       break;
764     case ARG_DEBUG_HELP:
765       gst_debug_help ();
766       exit (0);
767 #endif
768     case ARG_PLUGIN_SPEW:
769       break;
770     case ARG_PLUGIN_PATH:
771 #ifndef GST_DISABLE_REGISTRY
772       split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, NULL);
773 #endif /* GST_DISABLE_REGISTRY */
774       break;
775     case ARG_PLUGIN_LOAD:
776       split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
777       break;
778     case ARG_SEGTRAP_DISABLE:
779       _gst_disable_segtrap = TRUE;
780       break;
781     default:
782       g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
783           _("Unknown option"));
784       return FALSE;
785   }
786
787   return TRUE;
788 }
789
790 static gboolean
791 parse_goption_arg (const gchar * opt,
792     const gchar * arg, gpointer data, GError ** err)
793 {
794   const struct
795   {
796     gchar *opt;
797     int val;
798   } options[] = {
799     {
800     "--gst-version", ARG_VERSION}, {
801     "--gst-fatal-warnings", ARG_FATAL_WARNINGS},
802 #ifndef GST_DISABLE_GST_DEBUG
803     {
804     "--gst-debug-level", ARG_DEBUG_LEVEL}, {
805     "--gst-debug", ARG_DEBUG}, {
806     "--gst-debug-disable", ARG_DEBUG_DISABLE}, {
807     "--gst-debug-no-color", ARG_DEBUG_NO_COLOR}, {
808     "--gst-debug-help", ARG_DEBUG_HELP},
809 #endif
810     {
811     "--gst-plugin-spew", ARG_PLUGIN_SPEW}, {
812     "--gst-plugin-path", ARG_PLUGIN_PATH}, {
813     "--gst-plugin-load", ARG_PLUGIN_LOAD}, {
814     "--gst-disable-segtrap", ARG_SEGTRAP_DISABLE}, {
815     NULL}
816   };
817   gint val = 0, n;
818
819   for (n = 0; options[n].opt; n++) {
820     if (!strcmp (opt, options[n].opt)) {
821       val = options[n].val;
822       break;
823     }
824   }
825
826   return parse_one_option (val, arg, err);
827 }
828
829 /**
830  * gst_deinit:
831  *
832  * Clean up.
833  * Call only once, before exiting.
834  * After this call GStreamer should not be used anymore.
835  */
836
837 extern GstRegistry *_gst_registry_default;
838 void
839 gst_deinit (void)
840 {
841   GstClock *clock;
842
843   GST_INFO ("deinitializing GStreamer");
844   clock = gst_system_clock_obtain ();
845   gst_object_unref (clock);
846   gst_object_unref (clock);
847
848   _gst_registry_cleanup ();
849
850   gst_initialized = FALSE;
851   GST_INFO ("deinitialized GStreamer");
852 }
853
854 /**
855  * gst_version:
856  * @major: pointer to a guint to store the major version number
857  * @minor: pointer to a guint to store the minor version number
858  * @micro: pointer to a guint to store the micro version number
859  *
860  * Gets the version number of the GStreamer library.
861  */
862 void
863 gst_version (guint * major, guint * minor, guint * micro)
864 {
865   g_return_if_fail (major);
866   g_return_if_fail (minor);
867   g_return_if_fail (micro);
868
869   *major = GST_VERSION_MAJOR;
870   *minor = GST_VERSION_MINOR;
871   *micro = GST_VERSION_MICRO;
872 }