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