Remove old autoplug code
[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_COPYRIGHT,
471   GST_PACKAGE,
472   GST_ORIGIN,
473
474   GST_STRUCT_PADDING_INIT
475 };                         
476
477 /*
478  * this bit handles:
479  * - initalization of threads if we use them
480  * - log handler
481  * - initial output
482  * - initializes gst_format
483  * - registers a bunch of types for gst_objects
484  *
485  * - we don't have cases yet where this fails, but in the future
486  *   we might and then it's nice to be able to return that
487  */
488 static gboolean
489 init_post (void)
490 {
491   GLogLevelFlags llf;
492   const gchar *plugin_path;
493 #ifndef GST_DISABLE_TRACE
494   GstTrace *gst_trace;
495 #endif /* GST_DISABLE_TRACE */
496
497   llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
498   g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
499   
500   GST_INFO ("Initializing GStreamer Core Library version %s %s",
501             VERSION, _gst_use_threads ? "" : "(no threads)");
502   
503   _gst_format_initialize ();
504   _gst_query_type_initialize ();
505   gst_object_get_type ();
506   gst_pad_get_type ();
507   gst_real_pad_get_type ();
508   gst_ghost_pad_get_type ();
509   gst_element_factory_get_type ();
510   gst_element_get_type ();
511   gst_scheduler_factory_get_type ();
512   gst_type_find_factory_get_type ();
513   gst_bin_get_type ();
514 #ifndef GST_DISABLE_INDEX
515   gst_index_factory_get_type ();
516 #endif /* GST_DISABLE_INDEX */
517 #ifndef GST_DISABLE_URI
518   gst_uri_handler_get_type ();
519 #endif /* GST_DISABLE_URI */
520
521   plugin_path = g_getenv ("GST_PLUGIN_PATH");
522 #ifndef GST_DISABLE_REGISTRY
523   split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func, _user_registry);
524 #endif /* GST_DISABLE_REGISTRY */
525
526   /* register core plugins */
527   _gst_plugin_register_static (&plugin_desc);
528  
529   _gst_cpu_initialize (_gst_enable_cpu_opt);
530   _gst_structure_initialize ();
531   _gst_value_initialize ();
532   _gst_props_initialize ();
533   _gst_caps_initialize ();
534   _gst_plugin_initialize ();
535   _gst_event_initialize ();
536   _gst_buffer_initialize ();
537   _gst_tag_initialize ();
538
539 #ifndef GST_DISABLE_REGISTRY
540   if (!_gst_registry_fixed) {
541     /* don't override command-line options */
542     if (g_getenv ("GST_REGISTRY")) {
543       g_object_set (_user_registry, "location", g_getenv ("GST_REGISTRY"), NULL);
544       _gst_registry_fixed = TRUE;
545     }
546   }
547
548   if (!_gst_registry_fixed) {
549     gst_registry_pool_add (_global_registry, 100);
550     gst_registry_pool_add (_user_registry, 50);
551   } else {
552     gst_registry_pool_add (_user_registry, 50);
553   }
554
555   if (_gst_registry_auto_load) {
556     gst_registry_pool_load_all ();
557   }
558 #endif /* GST_DISABLE_REGISTRY */
559
560   /* if we need to preload plugins */
561   if (preload_plugins) {
562     g_slist_foreach (preload_plugins, load_plugin_func, NULL);
563     g_slist_free (preload_plugins);
564     preload_plugins = NULL;
565   }
566
567 #ifndef GST_DISABLE_TRACE
568   _gst_trace_on = 0;
569   if (_gst_trace_on) {
570     gst_trace = gst_trace_new ("gst.trace", 1024);
571     gst_trace_set_default (gst_trace);
572   }
573 #endif /* GST_DISABLE_TRACE */
574   if (_gst_progname == NULL) {
575     _gst_progname = g_strdup ("gstprog");
576   }
577
578   return TRUE;
579 }
580
581 #ifndef GST_DISABLE_GST_DEBUG
582 static gint
583 sort_by_category_name (gconstpointer a, gconstpointer b)
584 {
585   return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
586                  gst_debug_category_get_name ((GstDebugCategory *) b));
587 }
588 static void
589 gst_debug_help (void) 
590 {
591   GSList *list, *walk;
592   GList *list2, *walk2;
593   
594   if (!init_post ())
595     exit (1);
596   
597   walk2 = list2 = gst_registry_pool_plugin_list ();
598   while (walk2) {
599     GstPlugin *plugin = GST_PLUGIN (walk2->data);
600     walk2 = g_list_next (walk2);
601     
602     if (!gst_plugin_is_loaded (plugin)) {
603 #ifndef GST_DISABLE_REGISTRY 
604       if (GST_IS_REGISTRY (plugin->manager)) {
605         GST_CAT_LOG (GST_CAT_PLUGIN_LOADING, "loading plugin %s", plugin->desc.name);
606         if (gst_registry_load_plugin (GST_REGISTRY (plugin->manager), plugin) != GST_REGISTRY_OK)
607           GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "loading plugin %s failed", plugin->desc.name);
608       }
609 #endif /* GST_DISABLE_REGISTRY */
610     }
611   }
612   g_list_free (list2);
613       
614   list = gst_debug_get_all_categories ();
615   walk = list = g_slist_sort (list, sort_by_category_name);
616   
617   g_print ("\n");
618   g_print ("name                  level    description\n");
619   g_print ("---------------------+--------+--------------------------------\n");
620
621   while (walk) {
622     GstDebugCategory *cat = (GstDebugCategory *) walk->data;
623   
624     if (gst_debug_is_colored ()) {
625       gchar *color = gst_debug_construct_term_color (cat->color);
626       g_print ("%s%-20s\033[00m  %1d %s  %s%s\033[00m\n", 
627                color,
628                gst_debug_category_get_name (cat),
629                gst_debug_category_get_threshold (cat),
630                gst_debug_level_get_name (gst_debug_category_get_threshold (cat)), 
631                color,
632                gst_debug_category_get_description (cat));
633       g_free (color);
634     } else {
635       g_print ("%-20s  %1d %s  %s\n", gst_debug_category_get_name (cat), 
636                gst_debug_category_get_threshold (cat),
637                gst_debug_level_get_name (gst_debug_category_get_threshold (cat)), 
638                gst_debug_category_get_description (cat));
639     }
640     walk = g_slist_next (walk);
641   }   
642   g_slist_free (list);
643   g_print ("\n");
644 }
645 #endif  
646
647 static void
648 init_popt_callback (poptContext context, enum poptCallbackReason reason,
649                     const struct poptOption *option, const char *arg, void *data) 
650 {
651   GLogLevelFlags fatal_mask;
652
653   if (gst_initialized)
654     return;
655   switch (reason) {
656   case POPT_CALLBACK_REASON_PRE:
657     if (!init_pre ()) _gst_initialization_failure = TRUE;
658     break;
659   case POPT_CALLBACK_REASON_OPTION:
660     switch (option->val) {
661     case ARG_VERSION:
662       g_print ("GStreamer Core Library version %s\n", GST_VERSION);
663       exit (0);
664     case ARG_FATAL_WARNINGS:
665       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
666       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
667       g_log_set_always_fatal (fatal_mask);
668       break;
669 #ifndef GST_DISABLE_GST_DEBUG 
670     case ARG_DEBUG_LEVEL: {
671       gint tmp = 0;
672       tmp = strtol (arg, NULL, 0);
673       if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
674         gst_debug_set_default_threshold (tmp);
675       }
676       break;
677     }
678     case ARG_DEBUG:
679       parse_debug_list (arg);
680       break;
681     case ARG_DEBUG_NO_COLOR:
682       gst_debug_set_colored (FALSE);
683       break;
684     case ARG_DEBUG_DISABLE:
685       gst_debug_set_active (FALSE);
686       break;
687     case ARG_DEBUG_HELP:
688       gst_debug_help ();
689       exit (0);
690 #endif
691     case ARG_DISABLE_CPU_OPT:
692       _gst_enable_cpu_opt = FALSE;
693       break;
694     case ARG_PLUGIN_SPEW:
695       break;
696     case ARG_PLUGIN_PATH:
697 #ifndef GST_DISABLE_REGISTRY
698       split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, _user_registry);
699 #endif /* GST_DISABLE_REGISTRY */
700       break;
701     case ARG_PLUGIN_LOAD:
702       split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
703       break;
704     case ARG_SCHEDULER:
705       gst_scheduler_factory_set_default_name (arg);
706       break;
707     case ARG_REGISTRY:
708 #ifndef GST_DISABLE_REGISTRY
709       g_object_set (G_OBJECT (_user_registry), "location", arg, NULL);
710       _gst_registry_fixed = TRUE;
711 #endif /* GST_DISABLE_REGISTRY */
712       break;
713     default:
714       g_warning ("option %d not recognized", option->val);
715       break;
716     }
717     break;
718   case POPT_CALLBACK_REASON_POST:
719     if (!init_post ()) _gst_initialization_failure = TRUE;
720     gst_initialized = TRUE;
721     break;
722   }
723 }
724
725 /**
726  * gst_use_threads:
727  * @use_threads: flag indicating threads should be used
728  *
729  * Instructs the core to turn on/off threading. When threading
730  * is turned off, all thread operations such as mutexes and conditionals
731  * are turned into NOPs. use this if you want absolute minimal overhead
732  * and you don't use any threads in the pipeline.
733  * <note><para>
734  * This function may only be called before threads are initialized. This
735  * usually happens when calling gst_init.
736  * </para></note>
737  */
738 void
739 gst_use_threads (gboolean use_threads)
740 {
741   g_return_if_fail (!gst_initialized);
742   g_return_if_fail (g_thread_supported ());
743
744   _gst_use_threads = use_threads;
745 }
746
747 /**
748  * gst_has_threads:
749  * 
750  * Query if GStreamer has threads enabled.
751  *
752  * Returns: TRUE if threads are enabled.
753  */
754 gboolean
755 gst_has_threads (void)
756 {
757   return _gst_use_threads;
758 }
759
760
761 static GSList *mainloops = NULL;
762
763 /**
764  * gst_main:
765  *
766  * Enter the main GStreamer processing loop 
767  */
768 void 
769 gst_main (void) 
770 {
771   GMainLoop *loop;
772
773   loop = g_main_loop_new (NULL, FALSE);
774   mainloops = g_slist_prepend (mainloops, loop);
775
776   g_main_loop_run (loop);
777 }
778
779 /**
780  * gst_main_quit:
781  *
782  * Exits the main GStreamer processing loop 
783  */
784 void 
785 gst_main_quit (void) 
786 {
787   if (!mainloops)
788     g_error ("Quit more loops than there are");
789   else {
790     GMainLoop *loop = mainloops->data;
791     mainloops = g_slist_delete_link (mainloops, mainloops);
792     g_main_loop_quit (loop);
793     g_main_loop_unref (loop);
794   }
795 }
796
797 /**
798  * gst_version:
799  * @major: pointer to a guint to store the major version number
800  * @minor: pointer to a guint to store the minor version number
801  * @micro: pointer to a guint to store the micro version number
802  *
803  * Gets the version number of the GStreamer library
804  */
805 void 
806 gst_version (guint *major, guint *minor, guint *micro)
807 {
808   g_return_if_fail (major);
809   g_return_if_fail (minor);
810   g_return_if_fail (micro);
811
812   *major = GST_VERSION_MAJOR;
813   *minor = GST_VERSION_MINOR;
814   *micro = GST_VERSION_MICRO;
815 }