gst/autoplug/gstspider.c: add a template for spider's sink
[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 envronment 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
341   if (!argc || !argv) {
342     if (argc || argv)
343       g_warning ("gst_init: Only one of argc or argv was NULL");
344
345     if (!init_pre ())
346       return FALSE;
347     if (!init_post ())
348       return FALSE;
349     gst_initialized = TRUE;
350     return TRUE;
351   }
352
353   if (popt_options == NULL) {
354     options = options_without;
355   } else {
356     options = options_with;
357   }
358   context = poptGetContext ("GStreamer", *argc, (const char **) *argv,
359       options, 0);
360
361   /* check for GST_DEBUG environment variable */
362   gst_debug_env = g_getenv ("GST_DEBUG");
363   if (gst_debug_env)
364     parse_debug_list (gst_debug_env);
365
366   /* Scan until we reach the end (-1), ignoring errors */
367   while ((nextopt = poptGetNextOpt (context)) != -1) {
368
369     /* If an error occurred and it's not an missing options, throw an error
370      * We don't want to show the "unknown option" message, since it'll
371      * might interfere with the applications own command line parsing
372      */
373     if (nextopt < 0 && nextopt != POPT_ERROR_BADOPT) {
374       g_print ("Error on option %s: %s.\nRun '%s --help' "
375           "to see a full list of available command line options.\n",
376           poptBadOption (context, 0), poptStrerror (nextopt), (*argv)[0]);
377
378       poptFreeContext (context);
379       return FALSE;
380     }
381   }
382
383   *argc = poptStrippedArgv (context, *argc, *argv);
384
385   poptFreeContext (context);
386
387   return TRUE;
388 }
389
390 #ifndef GST_DISABLE_REGISTRY
391 static void
392 add_path_func (gpointer data, gpointer user_data)
393 {
394   GstRegistry *registry = GST_REGISTRY (user_data);
395
396   GST_INFO ("Adding plugin path: \"%s\"", (gchar *) data);
397   gst_registry_add_path (registry, (gchar *) data);
398 }
399 #endif
400
401 static void
402 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
403 {
404   preload_plugins = g_slist_prepend (preload_plugins, data);
405 }
406
407 static void
408 load_plugin_func (gpointer data, gpointer user_data)
409 {
410   GstPlugin *plugin;
411   const gchar *filename;
412
413   filename = (const gchar *) data;
414
415   plugin = gst_plugin_load_file (filename, NULL);
416
417   if (plugin) {
418     GST_INFO ("Loaded plugin: \"%s\"", filename);
419
420     gst_registry_pool_add_plugin (plugin);
421   } else {
422     GST_WARNING ("Failed to load plugin: \"%s\"", filename);
423   }
424
425   g_free (data);
426 }
427
428 static void
429 split_and_iterate (const gchar * stringlist, gchar * separator, GFunc iterator,
430     gpointer user_data)
431 {
432   gchar **strings;
433   gint j = 0;
434   gchar *lastlist = g_strdup (stringlist);
435
436   while (lastlist) {
437     strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
438     g_free (lastlist);
439     lastlist = NULL;
440
441     while (strings[j]) {
442       iterator (strings[j], user_data);
443       if (++j == MAX_PATH_SPLIT) {
444         lastlist = g_strdup (strings[j]);
445         g_strfreev (strings);
446         j = 0;
447         break;
448       }
449     }
450   }
451 }
452
453 /* we have no fail cases yet, but maybe in the future */
454 static gboolean
455 init_pre (void)
456 {
457   g_type_init ();
458
459   if (g_thread_supported ()) {
460     /* somebody already initialized threading */
461   } else {
462     g_thread_init (NULL);
463   }
464   /* we need threading to be enabled right here */
465   _gst_debug_init ();
466
467 #ifdef ENABLE_NLS
468   setlocale (LC_ALL, "");
469   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
470 #endif /* ENABLE_NLS */
471
472 #ifndef GST_DISABLE_REGISTRY
473   {
474     const gchar *debug_list;
475
476     debug_list = g_getenv ("GST_DEBUG");
477     if (debug_list) {
478       parse_debug_list (debug_list);
479     }
480   }
481 #endif
482 #ifndef GST_DISABLE_REGISTRY
483   {
484     gchar *user_reg;
485     const gchar *homedir;
486
487     _global_registry =
488         gst_xml_registry_new ("global_registry", GLOBAL_REGISTRY_FILE);
489
490 #ifdef PLUGINS_USE_BUILDDIR
491     /* location libgstelements.so */
492     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/libs/gst");
493     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/elements");
494     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/types");
495     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/autoplug");
496     gst_registry_add_path (_global_registry,
497         PLUGINS_BUILDDIR "/gst/schedulers");
498     gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/indexers");
499 #else
500     /* add the main (installed) library path */
501     gst_registry_add_path (_global_registry, PLUGINS_DIR);
502 #endif /* PLUGINS_USE_BUILDDIR */
503
504     if (g_getenv ("GST_REGISTRY")) {
505       user_reg = g_strdup (g_getenv ("GST_REGISTRY"));
506     } else {
507       homedir = g_get_home_dir ();
508       user_reg = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL);
509     }
510     _user_registry = gst_xml_registry_new ("user_registry", user_reg);
511
512     g_free (user_reg);
513   }
514 #endif /* GST_DISABLE_REGISTRY */
515
516   return TRUE;
517 }
518
519 static gboolean
520 gst_register_core_elements (GstPlugin * plugin)
521 {
522   /* register some standard builtin types */
523   if (!gst_element_register (plugin, "bin", GST_RANK_PRIMARY,
524           GST_TYPE_BIN) ||
525       !gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY,
526           GST_TYPE_PIPELINE) ||
527       !gst_element_register (plugin, "thread", GST_RANK_PRIMARY,
528           GST_TYPE_THREAD) ||
529       !gst_element_register (plugin, "queue", GST_RANK_NONE, GST_TYPE_QUEUE))
530     g_assert_not_reached ();
531
532   return TRUE;
533 }
534
535 static GstPluginDesc plugin_desc = {
536   GST_VERSION_MAJOR,
537   GST_VERSION_MINOR,
538   "gstcoreelements",
539   "core elements of the GStreamer library",
540   gst_register_core_elements,
541   NULL,
542   VERSION,
543   GST_LICENSE,
544   GST_PACKAGE,
545   GST_ORIGIN,
546
547   GST_PADDING_INIT
548 };
549
550 /*
551  * this bit handles:
552  * - initalization of threads if we use them
553  * - log handler
554  * - initial output
555  * - initializes gst_format
556  * - registers a bunch of types for gst_objects
557  *
558  * - we don't have cases yet where this fails, but in the future
559  *   we might and then it's nice to be able to return that
560  */
561 static gboolean
562 init_post (void)
563 {
564   GLogLevelFlags llf;
565   const gchar *plugin_path;
566
567 #ifndef GST_DISABLE_TRACE
568   GstTrace *gst_trace;
569 #endif /* GST_DISABLE_TRACE */
570
571   llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
572   g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
573
574   GST_INFO ("Initializing GStreamer Core Library version %s", VERSION);
575
576   _gst_format_initialize ();
577   _gst_query_type_initialize ();
578   gst_object_get_type ();
579   gst_pad_get_type ();
580   gst_real_pad_get_type ();
581   gst_ghost_pad_get_type ();
582   gst_element_factory_get_type ();
583   gst_element_get_type ();
584   gst_scheduler_factory_get_type ();
585   gst_type_find_factory_get_type ();
586   gst_bin_get_type ();
587 #ifndef GST_DISABLE_INDEX
588   gst_index_factory_get_type ();
589 #endif /* GST_DISABLE_INDEX */
590 #ifndef GST_DISABLE_URI
591   gst_uri_handler_get_type ();
592 #endif /* GST_DISABLE_URI */
593
594   plugin_path = g_getenv ("GST_PLUGIN_PATH");
595 #ifndef GST_DISABLE_REGISTRY
596   split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func,
597       _global_registry);
598 #endif /* GST_DISABLE_REGISTRY */
599
600   /* register core plugins */
601   _gst_plugin_register_static (&plugin_desc);
602
603   _gst_cpu_initialize (_gst_enable_cpu_opt);
604   gst_structure_get_type ();
605   _gst_value_initialize ();
606   gst_caps_get_type ();
607   _gst_plugin_initialize ();
608   _gst_event_initialize ();
609   _gst_buffer_initialize ();
610   _gst_tag_initialize ();
611
612 #ifndef GST_DISABLE_REGISTRY
613   if (!_gst_registry_fixed) {
614     /* don't override command-line options */
615     if (g_getenv ("GST_REGISTRY")) {
616       g_object_set (_global_registry, "location", g_getenv ("GST_REGISTRY"),
617           NULL);
618       _gst_registry_fixed = TRUE;
619     }
620   }
621
622   if (!_gst_registry_fixed) {
623     gst_registry_pool_add (_global_registry, 100);
624     gst_registry_pool_add (_user_registry, 50);
625   } else {
626
627     gst_registry_pool_add (_global_registry, 100);
628   }
629
630   if (_gst_registry_auto_load) {
631     gst_registry_pool_load_all ();
632   }
633 #endif /* GST_DISABLE_REGISTRY */
634
635   /* if we need to preload plugins */
636   if (preload_plugins) {
637     g_slist_foreach (preload_plugins, load_plugin_func, NULL);
638     g_slist_free (preload_plugins);
639     preload_plugins = NULL;
640   }
641 #ifndef GST_DISABLE_TRACE
642   _gst_trace_on = 0;
643   if (_gst_trace_on) {
644     gst_trace = gst_trace_new ("gst.trace", 1024);
645     gst_trace_set_default (gst_trace);
646   }
647 #endif /* GST_DISABLE_TRACE */
648
649   return TRUE;
650 }
651
652 #ifndef GST_DISABLE_GST_DEBUG
653 static gint
654 sort_by_category_name (gconstpointer a, gconstpointer b)
655 {
656   return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
657       gst_debug_category_get_name ((GstDebugCategory *) b));
658 }
659 static void
660 gst_debug_help (void)
661 {
662   GSList *list, *walk;
663   GList *list2, *walk2;
664
665   if (!init_post ())
666     exit (1);
667
668   walk2 = list2 = gst_registry_pool_plugin_list ();
669   while (walk2) {
670     GstPlugin *plugin = GST_PLUGIN (walk2->data);
671
672     walk2 = g_list_next (walk2);
673
674     if (!gst_plugin_is_loaded (plugin)) {
675 #ifndef GST_DISABLE_REGISTRY
676       if (GST_IS_REGISTRY (plugin->manager)) {
677         GST_CAT_LOG (GST_CAT_PLUGIN_LOADING, "loading plugin %s",
678             plugin->desc.name);
679         if (gst_registry_load_plugin (GST_REGISTRY (plugin->manager),
680                 plugin) != GST_REGISTRY_OK)
681           GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "loading plugin %s failed",
682               plugin->desc.name);
683       }
684 #endif /* GST_DISABLE_REGISTRY */
685     }
686   }
687   g_list_free (list2);
688
689   list = gst_debug_get_all_categories ();
690   walk = list = g_slist_sort (list, sort_by_category_name);
691
692   g_print ("\n");
693   g_print ("name                  level    description\n");
694   g_print ("---------------------+--------+--------------------------------\n");
695
696   while (walk) {
697     GstDebugCategory *cat = (GstDebugCategory *) walk->data;
698
699     if (gst_debug_is_colored ()) {
700       gchar *color = gst_debug_construct_term_color (cat->color);
701
702       g_print ("%s%-20s\033[00m  %1d %s  %s%s\033[00m\n",
703           color,
704           gst_debug_category_get_name (cat),
705           gst_debug_category_get_threshold (cat),
706           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
707           color, gst_debug_category_get_description (cat));
708       g_free (color);
709     } else {
710       g_print ("%-20s  %1d %s  %s\n", gst_debug_category_get_name (cat),
711           gst_debug_category_get_threshold (cat),
712           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
713           gst_debug_category_get_description (cat));
714     }
715     walk = g_slist_next (walk);
716   }
717   g_slist_free (list);
718   g_print ("\n");
719 }
720 #endif
721
722 static void
723 init_popt_callback (poptContext context, enum poptCallbackReason reason,
724     const GstPoptOption * option, const char *arg, void *data)
725 {
726   GLogLevelFlags fatal_mask;
727
728   if (gst_initialized)
729     return;
730   switch (reason) {
731     case POPT_CALLBACK_REASON_PRE:
732       if (!init_pre ())
733         _gst_initialization_failure = TRUE;
734       break;
735     case POPT_CALLBACK_REASON_OPTION:
736       switch (option->val) {
737         case ARG_VERSION:
738           g_print ("GStreamer Core Library version %s\n", GST_VERSION);
739           exit (0);
740         case ARG_FATAL_WARNINGS:
741           fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
742           fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
743           g_log_set_always_fatal (fatal_mask);
744           break;
745 #ifndef GST_DISABLE_GST_DEBUG
746         case ARG_DEBUG_LEVEL:{
747           gint tmp = 0;
748
749           tmp = strtol (arg, NULL, 0);
750           if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
751             gst_debug_set_default_threshold (tmp);
752           }
753           break;
754         }
755         case ARG_DEBUG:
756           parse_debug_list (arg);
757           break;
758         case ARG_DEBUG_NO_COLOR:
759           gst_debug_set_colored (FALSE);
760           break;
761         case ARG_DEBUG_DISABLE:
762           gst_debug_set_active (FALSE);
763           break;
764         case ARG_DEBUG_HELP:
765           gst_debug_help ();
766           exit (0);
767 #endif
768         case ARG_DISABLE_CPU_OPT:
769           _gst_enable_cpu_opt = FALSE;
770           break;
771         case ARG_PLUGIN_SPEW:
772           break;
773         case ARG_PLUGIN_PATH:
774 #ifndef GST_DISABLE_REGISTRY
775           split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func,
776               _user_registry);
777 #endif /* GST_DISABLE_REGISTRY */
778           break;
779         case ARG_PLUGIN_LOAD:
780           split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
781           break;
782         case ARG_SEGTRAP_DISABLE:
783           _gst_disable_segtrap = TRUE;
784           break;
785         case ARG_SCHEDULER:
786           gst_scheduler_factory_set_default_name (arg);
787           break;
788         case ARG_REGISTRY:
789 #ifndef GST_DISABLE_REGISTRY
790           g_object_set (G_OBJECT (_user_registry), "location", arg, NULL);
791           _gst_registry_fixed = TRUE;
792 #endif /* GST_DISABLE_REGISTRY */
793           break;
794         default:
795           g_warning ("option %d not recognized", option->val);
796           break;
797       }
798       break;
799     case POPT_CALLBACK_REASON_POST:
800       if (!init_post ())
801         _gst_initialization_failure = TRUE;
802       gst_initialized = TRUE;
803       break;
804   }
805 }
806
807 /**
808  * gst_use_threads:
809  * @use_threads: a #gboolean indicating whether threads should be used
810  *
811  * This function is deprecated and should not be used in new code.
812  * GStreamer requires threads to be enabled at all times.
813  */
814 void
815 gst_use_threads (gboolean use_threads)
816 {
817 }
818
819 /**
820  * gst_has_threads:
821  *
822  * This function is deprecated and should not be used in new code.
823  *
824  * Queries if GStreamer has threads enabled.
825  *
826  * Returns: %TRUE if threads are enabled.
827  */
828 gboolean
829 gst_has_threads (void)
830 {
831   return TRUE;
832 }
833
834
835 static GSList *mainloops = NULL;
836
837 /**
838  * gst_main:
839  *
840  * Enters the main GStreamer processing loop.
841  *
842  * This function duplicates functionality in glib, and will be removed
843  * during the 0.9 development series.
844  */
845 void
846 gst_main (void)
847 {
848   GMainLoop *loop;
849
850   loop = g_main_loop_new (NULL, FALSE);
851   mainloops = g_slist_prepend (mainloops, loop);
852
853   g_main_loop_run (loop);
854 }
855
856 /**
857  * gst_main_quit:
858  *
859  * Exits the main GStreamer processing loop.
860  *
861  * This function duplicates functionality in glib, and will be removed
862  * during the 0.9 development series.
863  */
864 void
865 gst_main_quit (void)
866 {
867   if (!mainloops)
868     g_error ("Quit more loops than there are");
869   else {
870     GMainLoop *loop = mainloops->data;
871
872     mainloops = g_slist_delete_link (mainloops, mainloops);
873     g_main_loop_quit (loop);
874     g_main_loop_unref (loop);
875   }
876 }
877
878 /**
879  * gst_version:
880  * @major: pointer to a guint to store the major version number
881  * @minor: pointer to a guint to store the minor version number
882  * @micro: pointer to a guint to store the micro version number
883  *
884  * Gets the version number of the GStreamer library.
885  */
886 void
887 gst_version (guint * major, guint * minor, guint * micro)
888 {
889   g_return_if_fail (major);
890   g_return_if_fail (minor);
891   g_return_if_fail (micro);
892
893   *major = GST_VERSION_MAJOR;
894   *minor = GST_VERSION_MINOR;
895   *micro = GST_VERSION_MICRO;
896 }