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