Change GST_.*_PADDING to _gst_padding[GST_PADDING];
[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 #include <stdlib.h>
24 #include <stdio.h>
25
26 #include "gst_private.h"
27
28 #include "gst.h"
29 #include "gstqueue.h"
30 #ifndef GST_DISABLE_REGISTRY
31 #include "registries/gstxmlregistry.h"
32 #endif /* GST_DISABLE_REGISTRY */
33 #include "gstregistrypool.h"
34
35 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
36
37 #define MAX_PATH_SPLIT  16
38 #define GST_PLUGIN_SEPARATOR ","
39
40 gchar *_gst_progname;
41
42 #ifndef GST_DISABLE_REGISTRY
43 gboolean _gst_registry_auto_load = TRUE;
44 static GstRegistry *_global_registry;
45 static GstRegistry *_user_registry;
46 static gboolean _gst_registry_fixed = FALSE;
47 #endif
48
49 static gboolean _gst_use_threads = TRUE;
50
51 static gboolean _gst_enable_cpu_opt = TRUE;
52
53 static gboolean gst_initialized = FALSE;
54 /* this will be set in popt callbacks when a problem has been encountered */
55 static gboolean _gst_initialization_failure = FALSE;
56 extern gint _gst_trace_on;
57
58 extern GThreadFunctions gst_thread_dummy_functions;
59
60
61 static void     load_plugin_func        (gpointer data, gpointer user_data);
62 static void     init_popt_callback      (poptContext context,
63                                          enum poptCallbackReason reason,
64                                          const struct poptOption *option,
65                                          const char *arg, void *data);
66 static gboolean init_pre                (void);
67 static gboolean init_post               (void);
68
69 static GSList *preload_plugins = NULL;
70
71 const gchar *g_log_domain_gstreamer = "GStreamer";
72
73 static void
74 debug_log_handler (const gchar *log_domain,
75                    GLogLevelFlags log_level,
76                    const gchar *message,
77                    gpointer user_data)
78 {
79   g_log_default_handler (log_domain, log_level, message, user_data);
80   /* FIXME: do we still need this ? fatal errors these days are all
81    * other than core errors */
82   /* g_on_error_query (NULL); */
83 }
84
85 enum {
86   ARG_VERSION=1,
87   ARG_FATAL_WARNINGS,
88 #ifndef GST_DISABLE_GST_DEBUG 
89   ARG_DEBUG_LEVEL,
90   ARG_DEBUG,
91   ARG_DEBUG_DISABLE,
92   ARG_DEBUG_NO_COLOR,
93   ARG_DEBUG_HELP,
94 #endif
95   ARG_DISABLE_CPU_OPT,
96   ARG_PLUGIN_SPEW,
97   ARG_PLUGIN_PATH,
98   ARG_PLUGIN_LOAD,
99   ARG_SCHEDULER,
100   ARG_REGISTRY
101 };
102
103 #ifndef NUL
104 #define NUL '\0'
105 #endif
106
107 /* default scheduler, can be changed in gstscheduler.h with
108  * the GST_SCHEDULER_DEFAULT_NAME define.
109  */
110 static const struct poptOption gstreamer_options[] = {
111   {NULL, NUL, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, (void *) &init_popt_callback, 0, NULL, NULL},
112   {"gst-version",        NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   NULL, ARG_VERSION,        N_("Print the GStreamer version"), NULL},
113   {"gst-fatal-warnings", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   NULL, ARG_FATAL_WARNINGS, N_("Make all warnings fatal"), NULL},
114 #ifndef GST_DISABLE_GST_DEBUG 
115   {"gst-debug-level",    NUL, POPT_ARG_INT|POPT_ARGFLAG_STRIP,    NULL, ARG_DEBUG_LEVEL,  N_("default debug level from 1 (only error) to 5 (anything) or 0 for no output"), "LEVEL"},
116   {"gst-debug",          NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG,          N_("colon-seperated list of category_name=level pairs to set specific levels for the individual categories.\nExample:GST_AUTOPLUG=5:GST_ELEMENT_*=3"), "CATEGORIES"},
117   {"gst-debug-no-color", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   NULL, ARG_DEBUG_NO_COLOR, N_("disable color debugging output"), NULL},
118   {"gst-disable-debug",  NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   NULL, ARG_DEBUG_DISABLE,  N_("disable debugging")},
119   {"gst-debug-help",     NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   NULL, ARG_DEBUG_HELP,     N_("print available debug categories and exit"), NULL},
120 #endif
121   {"gst-disable-cpu-opt",NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   NULL, ARG_DISABLE_CPU_OPT,N_("Disable accelerated CPU instructions"), NULL},
122   {"gst-plugin-spew",    NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   NULL, ARG_PLUGIN_SPEW,    N_("enable verbose plugin loading diagnostics"), NULL},
123   {"gst-plugin-path",    NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_PATH,    N_("'" G_SEARCHPATH_SEPARATOR_S "'--separated path list for loading plugins"), "PATHS"},
124   {"gst-plugin-load",    NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_LOAD,    N_("comma-separated list of plugins to preload in addition to the list stored in env variable GST_PLUGIN_PATH"), "PLUGINS"},
125   {"gst-scheduler",      NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_SCHEDULER,      N_("scheduler to use ('"GST_SCHEDULER_DEFAULT_NAME"' is the default)"), "SCHEDULER"},
126   {"gst-registry",       NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_REGISTRY,       N_("registry to use") , "REGISTRY"},
127   POPT_TABLEEND
128 };
129
130 /**
131  * gst_init_get_popt_table:
132  *
133  * Returns a popt option table with GStreamer's argument specifications. The
134  * table is set up to use popt's callback method, so whenever the parsing is
135  * actually performed (via a poptGetContext()), the GStreamer libraries will
136  * be initialized.
137  *
138  * Returns: a pointer to the static GStreamer option table.
139  * No free is necessary.
140  */
141 const struct poptOption *
142 gst_init_get_popt_table (void)
143 {
144   return gstreamer_options;
145 }
146
147 /**
148  * gst_init_check:
149  * @argc: pointer to application's argc
150  * @argv: pointer to application's argv
151  *
152  * Initializes the GStreamer library, setting up internal path lists,
153  * registering built-in elements, and loading standard plugins.
154  *
155  * This function will return %FALSE if GStreamer could not be initialized
156  * for some reason.  If you want your program to fail fatally,
157  * use gst_init() instead.
158  *
159  * Returns: TRUE if GStreamer coul be initialized
160  */
161 gboolean
162 gst_init_check (int *argc, char **argv[])
163 {
164   return gst_init_check_with_popt_table (argc, argv, NULL);
165 }
166
167 /**
168  * gst_init:
169  * @argc: pointer to application's argc
170  * @argv: pointer to application's argv
171  *
172  * Initializes the GStreamer library, setting up internal path lists,
173  * registering built-in elements, and loading standard plugins.
174  *
175  * This function will terminate your program if it was unable to initialize
176  * GStreamer for some reason.  If you want your program to fall back,
177  * use gst_init_check() instead.
178  */
179 void
180 gst_init (int *argc, char **argv[])
181 {
182   gst_init_with_popt_table (argc, argv, NULL);
183 }
184
185 /**
186  * gst_init_with_popt_table:
187  * @argc: pointer to application's argc
188  * @argv: pointer to application's argv
189  * @popt_options: pointer to a popt table to append
190  *
191  * Initializes the GStreamer library, parsing the options,
192  * setting up internal path lists,
193  * registering built-in elements, and loading standard plugins.
194  *
195  * This function will terminate your program if it was unable to initialize
196  * GStreamer for some reason.  If you want your program to fall back,
197  * use gst_init_check_with_popt_table() instead.
198  */
199 void
200 gst_init_with_popt_table (int *argc, char **argv[],
201                           const struct poptOption *popt_options)
202 {
203   if (!gst_init_check_with_popt_table (argc, argv, popt_options)) {
204     g_print ("Could not initialize GStreamer !\n");
205     exit (1);
206   }
207 }
208 /**
209  * gst_init_check_with_popt_table:
210  * @argc: pointer to application's argc
211  * @argv: pointer to application's argv
212  * @popt_options: pointer to a popt table to append
213  *
214  * Initializes the GStreamer library, parsing the options,
215  * setting up internal path lists,
216  * registering built-in elements, and loading standard plugins.
217  *
218  * Returns: TRUE if GStreamer coul be initialized
219  */
220 gboolean
221 gst_init_check_with_popt_table (int *argc, char **argv[],
222                                 const struct poptOption *popt_options)
223 {
224   poptContext context;
225   gint nextopt;
226   struct poptOption *options;
227   struct poptOption options_with[] = {
228     {NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions,                                 0, "Help options:", NULL},
229     {NULL, NUL, POPT_ARG_INCLUDE_TABLE, (struct poptOption *) gstreamer_options,         0, "GStreamer options:", NULL},
230     {NULL, NUL, POPT_ARG_INCLUDE_TABLE, (struct poptOption *) popt_options,              0, "Application options:", NULL},
231     POPT_TABLEEND
232   };
233   struct poptOption options_without[] = {
234     {NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions,                                 0, "Help options:", NULL},
235     {NULL, NUL, POPT_ARG_INCLUDE_TABLE, (struct poptOption *) gstreamer_options,         0, "GStreamer options:", NULL},
236     POPT_TABLEEND
237   };
238
239   if (gst_initialized)
240   {
241     GST_DEBUG ("already initialized gst");
242     return TRUE;
243   }
244
245   if (!argc || !argv) {
246     if (argc || argv)
247       g_warning ("gst_init: Only one of argc or argv was NULL");
248
249     if (!init_pre ()) return FALSE;
250     if (!init_post ()) return FALSE;
251     gst_initialized = TRUE;
252     return TRUE;
253   }
254
255   if (popt_options == NULL) {
256     options = options_without;
257   } else {
258     options = options_with;
259   }
260   context = poptGetContext ("GStreamer", *argc, (const char**)*argv,
261                             options, 0);
262
263   while ((nextopt = poptGetNextOpt (context)) > 0)
264   {
265     /* we only check for failures here, actual work is done in callbacks */
266     if (_gst_initialization_failure) return FALSE;
267   }
268
269   if (nextopt != -1) {
270     g_print ("Error on option %s: %s.\nRun '%s --help' "
271              "to see a full list of available command line options.\n",
272              poptBadOption (context, 0),
273              poptStrerror (nextopt),
274              (*argv)[0]);
275
276     poptFreeContext (context);
277     return FALSE;
278   }
279
280   *argc = poptStrippedArgv (context, *argc, *argv);
281   
282   poptFreeContext (context);
283
284   return TRUE;
285 }
286
287 #ifndef GST_DISABLE_REGISTRY
288 static void 
289 add_path_func (gpointer data, gpointer user_data)
290 {
291   GstRegistry *registry = GST_REGISTRY (user_data);
292   
293   GST_INFO ("Adding plugin path: \"%s\"", (gchar *) data);
294   gst_registry_add_path (registry, (gchar *)data);
295 }
296 #endif
297
298 static void 
299 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
300 {
301   preload_plugins = g_slist_prepend (preload_plugins, data);
302 }
303
304 static void
305 parse_debug_list (const gchar *list)
306 {
307   gchar **split;
308   gchar **walk;
309
310   g_return_if_fail (list != NULL);
311
312   walk = split = g_strsplit (list, ":", 0);
313
314   while (walk[0]) {
315     gchar **values = g_strsplit ( walk[0], "=", 2);
316     if (values[0] && values[1]) {
317       gint level = 0;
318       g_strstrip (values[0]);
319       g_strstrip (values[1]);
320       level = strtol (values[1], NULL, 0);
321       if (level >= 0 && level < GST_LEVEL_COUNT) {
322         GST_DEBUG ("setting debugging to level %d for name \"%s\"",
323                        level, values[0]);
324         gst_debug_set_threshold_for_name (values[0], level);
325       }
326     }
327     g_strfreev (values);
328     walk++;
329   }
330   g_strfreev (split);
331 }
332 static void 
333 load_plugin_func (gpointer data, gpointer user_data)
334 {
335   GstPlugin *plugin;
336   const gchar *filename;
337
338   filename = (const gchar *) data;
339
340   plugin = gst_plugin_load_file (filename, NULL);
341
342   if (plugin) {
343     GST_INFO ("Loaded plugin: \"%s\"", filename);
344
345     gst_registry_pool_add_plugin (plugin);
346   } else {
347     GST_WARNING ("Failed to load plugin: \"%s\"", filename);
348   }
349
350   g_free (data);
351 }
352
353 static void
354 split_and_iterate (const gchar *stringlist, gchar *separator, GFunc iterator, gpointer user_data) 
355 {
356   gchar **strings;
357   gint j = 0;
358   gchar *lastlist = g_strdup (stringlist);
359
360   while (lastlist) {
361     strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
362     g_free (lastlist);
363     lastlist = NULL;
364
365     while (strings[j]) {
366       iterator (strings[j], user_data);
367       if (++j == MAX_PATH_SPLIT) {
368         lastlist = g_strdup (strings[j]);
369         g_strfreev (strings); 
370         j=0;
371         break;
372       }
373     }
374   }
375 }
376
377 /* we have no fail cases yet, but maybe in the future */
378 static gboolean
379 init_pre (void)
380 {
381
382   g_type_init ();
383
384   if (g_thread_supported ()) {
385     /* somebody already initialized threading */
386     _gst_use_threads = TRUE;
387   } else {
388     if (_gst_use_threads)
389       g_thread_init (NULL);
390     else
391       g_thread_init (&gst_thread_dummy_functions);
392   }
393   /* we need threading to be enabled right here */
394   _gst_debug_init();
395
396 #ifdef ENABLE_NLS
397   bindtextdomain (GETTEXT_PACKAGE, GST_LOCALEDIR);
398   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
399 #endif /* ENABLE_NLS */
400
401 #ifndef GST_DISABLE_REGISTRY
402   {
403     const gchar *debug_list;
404   
405     debug_list = g_getenv ("GST_DEBUG");
406     if (debug_list) {
407       parse_debug_list (debug_list);
408     }
409   }
410 #endif
411 #ifndef GST_DISABLE_REGISTRY
412   {
413     gchar *user_reg;
414     const gchar *homedir;
415
416     _global_registry = gst_xml_registry_new ("global_registry", GLOBAL_REGISTRY_FILE);
417
418 #ifdef PLUGINS_USE_BUILDDIR
419     /* location libgstelements.so */
420     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/libs/gst");
421     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/elements");
422     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/types");
423     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/autoplug");
424     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/schedulers");
425     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/indexers");
426 #else
427     /* add the main (installed) library path */
428     gst_registry_add_path (_global_registry, PLUGINS_DIR);
429 #endif /* PLUGINS_USE_BUILDDIR */
430
431     if (g_getenv ("GST_REGISTRY"))
432     {
433       user_reg = g_strdup (g_getenv ("GST_REGISTRY"));
434     }
435     else
436     {
437       homedir = g_get_home_dir ();
438       user_reg = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL);
439     }
440     _user_registry = gst_xml_registry_new ("user_registry", user_reg);
441
442     g_free (user_reg);
443   }
444 #endif /* GST_DISABLE_REGISTRY */
445
446   return TRUE;
447 }
448
449 static gboolean
450 gst_register_core_elements (GstPlugin *plugin)
451 {
452   /* register some standard builtin types */
453   g_assert (gst_element_register (plugin, "bin", GST_RANK_PRIMARY, GST_TYPE_BIN));
454   g_assert (gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY, GST_TYPE_PIPELINE));
455   g_assert (gst_element_register (plugin, "thread", GST_RANK_PRIMARY, GST_TYPE_THREAD));
456   g_assert (gst_element_register (plugin, "queue", GST_RANK_PRIMARY, GST_TYPE_QUEUE));
457
458   return TRUE;
459 }
460
461 static GstPluginDesc plugin_desc = {
462   GST_VERSION_MAJOR,           
463   GST_VERSION_MINOR,  
464   "gst_core_elements",
465   "core elements of the GStreamer library",
466   gst_register_core_elements,
467   NULL,
468   VERSION,
469   GST_LICENSE,
470   GST_PACKAGE,
471   GST_ORIGIN,
472
473   GST_PADDING_INIT
474 };                         
475
476 /*
477  * this bit handles:
478  * - initalization of threads if we use them
479  * - log handler
480  * - initial output
481  * - initializes gst_format
482  * - registers a bunch of types for gst_objects
483  *
484  * - we don't have cases yet where this fails, but in the future
485  *   we might and then it's nice to be able to return that
486  */
487 static gboolean
488 init_post (void)
489 {
490   GLogLevelFlags llf;
491   const gchar *plugin_path;
492 #ifndef GST_DISABLE_TRACE
493   GstTrace *gst_trace;
494 #endif /* GST_DISABLE_TRACE */
495
496   llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
497   g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
498   
499   GST_INFO ("Initializing GStreamer Core Library version %s %s",
500             VERSION, _gst_use_threads ? "" : "(no threads)");
501   
502   _gst_format_initialize ();
503   _gst_query_type_initialize ();
504   gst_object_get_type ();
505   gst_pad_get_type ();
506   gst_real_pad_get_type ();
507   gst_ghost_pad_get_type ();
508   gst_element_factory_get_type ();
509   gst_element_get_type ();
510   gst_scheduler_factory_get_type ();
511   gst_type_find_factory_get_type ();
512   gst_bin_get_type ();
513 #ifndef GST_DISABLE_INDEX
514   gst_index_factory_get_type ();
515 #endif /* GST_DISABLE_INDEX */
516 #ifndef GST_DISABLE_URI
517   gst_uri_handler_get_type ();
518 #endif /* GST_DISABLE_URI */
519
520   plugin_path = g_getenv ("GST_PLUGIN_PATH");
521 #ifndef GST_DISABLE_REGISTRY
522   split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func, _user_registry);
523 #endif /* GST_DISABLE_REGISTRY */
524
525   /* register core plugins */
526   _gst_plugin_register_static (&plugin_desc);
527  
528   _gst_cpu_initialize (_gst_enable_cpu_opt);
529   _gst_structure_initialize ();
530   _gst_value_initialize ();
531   _gst_props_initialize ();
532   _gst_caps_initialize ();
533   _gst_plugin_initialize ();
534   _gst_event_initialize ();
535   _gst_buffer_initialize ();
536   _gst_tag_initialize ();
537
538 #ifndef GST_DISABLE_REGISTRY
539   if (!_gst_registry_fixed) {
540     /* don't override command-line options */
541     if (g_getenv ("GST_REGISTRY")) {
542       g_object_set (_user_registry, "location", g_getenv ("GST_REGISTRY"), NULL);
543       _gst_registry_fixed = TRUE;
544     }
545   }
546
547   if (!_gst_registry_fixed) {
548     gst_registry_pool_add (_global_registry, 100);
549     gst_registry_pool_add (_user_registry, 50);
550   } else {
551     gst_registry_pool_add (_user_registry, 50);
552   }
553
554   if (_gst_registry_auto_load) {
555     gst_registry_pool_load_all ();
556   }
557 #endif /* GST_DISABLE_REGISTRY */
558
559   /* if we need to preload plugins */
560   if (preload_plugins) {
561     g_slist_foreach (preload_plugins, load_plugin_func, NULL);
562     g_slist_free (preload_plugins);
563     preload_plugins = NULL;
564   }
565
566 #ifndef GST_DISABLE_TRACE
567   _gst_trace_on = 0;
568   if (_gst_trace_on) {
569     gst_trace = gst_trace_new ("gst.trace", 1024);
570     gst_trace_set_default (gst_trace);
571   }
572 #endif /* GST_DISABLE_TRACE */
573   if (_gst_progname == NULL) {
574     _gst_progname = g_strdup ("gstprog");
575   }
576
577   return TRUE;
578 }
579
580 #ifndef GST_DISABLE_GST_DEBUG
581 static gint
582 sort_by_category_name (gconstpointer a, gconstpointer b)
583 {
584   return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
585                  gst_debug_category_get_name ((GstDebugCategory *) b));
586 }
587 static void
588 gst_debug_help (void) 
589 {
590   GSList *list, *walk;
591   GList *list2, *walk2;
592   
593   if (!init_post ())
594     exit (1);
595   
596   walk2 = list2 = gst_registry_pool_plugin_list ();
597   while (walk2) {
598     GstPlugin *plugin = GST_PLUGIN (walk2->data);
599     walk2 = g_list_next (walk2);
600     
601     if (!gst_plugin_is_loaded (plugin)) {
602 #ifndef GST_DISABLE_REGISTRY 
603       if (GST_IS_REGISTRY (plugin->manager)) {
604         GST_CAT_LOG (GST_CAT_PLUGIN_LOADING, "loading plugin %s", plugin->desc.name);
605         if (gst_registry_load_plugin (GST_REGISTRY (plugin->manager), plugin) != GST_REGISTRY_OK)
606           GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "loading plugin %s failed", plugin->desc.name);
607       }
608 #endif /* GST_DISABLE_REGISTRY */
609     }
610   }
611   g_list_free (list2);
612       
613   list = gst_debug_get_all_categories ();
614   walk = list = g_slist_sort (list, sort_by_category_name);
615   
616   g_print ("\n");
617   g_print ("name                  level    description\n");
618   g_print ("---------------------+--------+--------------------------------\n");
619
620   while (walk) {
621     GstDebugCategory *cat = (GstDebugCategory *) walk->data;
622   
623     if (gst_debug_is_colored ()) {
624       gchar *color = gst_debug_construct_term_color (cat->color);
625       g_print ("%s%-20s\033[00m  %1d %s  %s%s\033[00m\n", 
626                color,
627                gst_debug_category_get_name (cat),
628                gst_debug_category_get_threshold (cat),
629                gst_debug_level_get_name (gst_debug_category_get_threshold (cat)), 
630                color,
631                gst_debug_category_get_description (cat));
632       g_free (color);
633     } else {
634       g_print ("%-20s  %1d %s  %s\n", gst_debug_category_get_name (cat), 
635                gst_debug_category_get_threshold (cat),
636                gst_debug_level_get_name (gst_debug_category_get_threshold (cat)), 
637                gst_debug_category_get_description (cat));
638     }
639     walk = g_slist_next (walk);
640   }   
641   g_slist_free (list);
642   g_print ("\n");
643 }
644 #endif  
645
646 static void
647 init_popt_callback (poptContext context, enum poptCallbackReason reason,
648                     const struct poptOption *option, const char *arg, void *data) 
649 {
650   GLogLevelFlags fatal_mask;
651
652   if (gst_initialized)
653     return;
654   switch (reason) {
655   case POPT_CALLBACK_REASON_PRE:
656     if (!init_pre ()) _gst_initialization_failure = TRUE;
657     break;
658   case POPT_CALLBACK_REASON_OPTION:
659     switch (option->val) {
660     case ARG_VERSION:
661       g_print ("GStreamer Core Library version %s\n", GST_VERSION);
662       exit (0);
663     case ARG_FATAL_WARNINGS:
664       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
665       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
666       g_log_set_always_fatal (fatal_mask);
667       break;
668 #ifndef GST_DISABLE_GST_DEBUG 
669     case ARG_DEBUG_LEVEL: {
670       gint tmp = 0;
671       tmp = strtol (arg, NULL, 0);
672       if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
673         gst_debug_set_default_threshold (tmp);
674       }
675       break;
676     }
677     case ARG_DEBUG:
678       parse_debug_list (arg);
679       break;
680     case ARG_DEBUG_NO_COLOR:
681       gst_debug_set_colored (FALSE);
682       break;
683     case ARG_DEBUG_DISABLE:
684       gst_debug_set_active (FALSE);
685       break;
686     case ARG_DEBUG_HELP:
687       gst_debug_help ();
688       exit (0);
689 #endif
690     case ARG_DISABLE_CPU_OPT:
691       _gst_enable_cpu_opt = FALSE;
692       break;
693     case ARG_PLUGIN_SPEW:
694       break;
695     case ARG_PLUGIN_PATH:
696 #ifndef GST_DISABLE_REGISTRY
697       split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, _user_registry);
698 #endif /* GST_DISABLE_REGISTRY */
699       break;
700     case ARG_PLUGIN_LOAD:
701       split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
702       break;
703     case ARG_SCHEDULER:
704       gst_scheduler_factory_set_default_name (arg);
705       break;
706     case ARG_REGISTRY:
707 #ifndef GST_DISABLE_REGISTRY
708       g_object_set (G_OBJECT (_user_registry), "location", arg, NULL);
709       _gst_registry_fixed = TRUE;
710 #endif /* GST_DISABLE_REGISTRY */
711       break;
712     default:
713       g_warning ("option %d not recognized", option->val);
714       break;
715     }
716     break;
717   case POPT_CALLBACK_REASON_POST:
718     if (!init_post ()) _gst_initialization_failure = TRUE;
719     gst_initialized = TRUE;
720     break;
721   }
722 }
723
724 /**
725  * gst_use_threads:
726  * @use_threads: flag indicating threads should be used
727  *
728  * Instructs the core to turn on/off threading. When threading
729  * is turned off, all thread operations such as mutexes and conditionals
730  * are turned into NOPs. use this if you want absolute minimal overhead
731  * and you don't use any threads in the pipeline.
732  * <note><para>
733  * This function may only be called before threads are initialized. This
734  * usually happens when calling gst_init.
735  * </para></note>
736  */
737 void
738 gst_use_threads (gboolean use_threads)
739 {
740   g_return_if_fail (!gst_initialized);
741   g_return_if_fail (g_thread_supported ());
742
743   _gst_use_threads = use_threads;
744 }
745
746 /**
747  * gst_has_threads:
748  * 
749  * Query if GStreamer has threads enabled.
750  *
751  * Returns: TRUE if threads are enabled.
752  */
753 gboolean
754 gst_has_threads (void)
755 {
756   return _gst_use_threads;
757 }
758
759
760 static GSList *mainloops = NULL;
761
762 /**
763  * gst_main:
764  *
765  * Enter the main GStreamer processing loop 
766  */
767 void 
768 gst_main (void) 
769 {
770   GMainLoop *loop;
771
772   loop = g_main_loop_new (NULL, FALSE);
773   mainloops = g_slist_prepend (mainloops, loop);
774
775   g_main_loop_run (loop);
776 }
777
778 /**
779  * gst_main_quit:
780  *
781  * Exits the main GStreamer processing loop 
782  */
783 void 
784 gst_main_quit (void) 
785 {
786   if (!mainloops)
787     g_error ("Quit more loops than there are");
788   else {
789     GMainLoop *loop = mainloops->data;
790     mainloops = g_slist_delete_link (mainloops, mainloops);
791     g_main_loop_quit (loop);
792     g_main_loop_unref (loop);
793   }
794 }
795
796 /**
797  * gst_version:
798  * @major: pointer to a guint to store the major version number
799  * @minor: pointer to a guint to store the minor version number
800  * @micro: pointer to a guint to store the micro version number
801  *
802  * Gets the version number of the GStreamer library
803  */
804 void 
805 gst_version (guint *major, guint *minor, guint *micro)
806 {
807   g_return_if_fail (major);
808   g_return_if_fail (minor);
809   g_return_if_fail (micro);
810
811   *major = GST_VERSION_MAJOR;
812   *minor = GST_VERSION_MINOR;
813   *micro = GST_VERSION_MICRO;
814 }