registry: Rearrange some things.
[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 /**
24  * SECTION:gst
25  * @short_description: Media library supporting arbitrary formats and filter
26  *                     graphs.
27  * @see_also: Check out both <ulink url="http://www.cse.ogi.edu/sysl/">OGI's
28  *            pipeline</ulink> and Microsoft's DirectShow for some background.
29  *
30  * GStreamer is a framework for constructing graphs of various filters
31  * (termed elements here) that will handle streaming media.  Any discreet
32  * (packetizable) media type is supported, with provisions for automatically
33  * determining source type.  Formatting/framing information is provided with
34  * a powerful negotiation framework.  Plugins are heavily used to provide for
35  * all elements, allowing one to construct plugins outside of the GST
36  * library, even released binary-only if license require (please don't).
37  *
38  * GStreamer borrows heavily from both the <ulink
39  * url="http://www.cse.ogi.edu/sysl/">OGI media pipeline</ulink> and
40  * Microsoft's DirectShow, hopefully taking the best of both and leaving the
41  * cruft behind. Its interface is slowly getting stable.
42  *
43  * The <application>GStreamer</application> library should be initialized with
44  * gst_init() before it can be used. You should pass pointers to the main argc
45  * and argv variables so that GStreamer can process its own command line
46  * options, as shown in the following example.
47  *
48  * <example>
49  * <title>Initializing the gstreamer library</title>
50  * <programlisting language="c">
51  * int
52  * main (int argc, char *argv[])
53  * {
54  *   // initialize the GStreamer library
55  *   gst_init (&amp;argc, &amp;argv);
56  *   ...
57  * }
58  * </programlisting>
59  * </example>
60  *
61  * It's allowed to pass two NULL pointers to gst_init() in case you don't want
62  * to pass the command line args to GStreamer.
63  *
64  * You can also use GOption to initialize your own parameters as shown in
65  * the next code fragment:
66  * <example>
67  * <title>Initializing own parameters when initializing gstreamer</title>
68  * <programlisting>
69  * static gboolean stats = FALSE;
70  * ...
71  * int
72  * main (int argc, char *argv[])
73  * {
74  *  GOptionEntry options[] = {
75  *   {"tags", 't', 0, G_OPTION_ARG_NONE, &amp;tags,
76  *       N_("Output tags (also known as metadata)"), NULL},
77  *   {NULL}
78  *  };
79  *  // must initialise the threading system before using any other GLib funtion
80  *  if (!g_thread_supported ())
81  *    g_thread_init (NULL);
82  *  ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]");
83  *  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
84  *  g_option_context_add_group (ctx, gst_init_get_option_group ());
85  *  if (!g_option_context_parse (ctx, &amp;argc, &amp;argv, &amp;err)) {
86  *    g_print ("Error initializing: &percnt;s\n", GST_STR_NULL (err->message));
87  *    exit (1);
88  *  }
89  *  g_option_context_free (ctx);
90  * ...
91  * }
92  * </programlisting>
93  * </example>
94  *
95  * Use gst_version() to query the library version at runtime or use the
96  * GST_VERSION_* macros to find the version at compile time. Optionally
97  * gst_version_string() returns a printable string.
98  *
99  * The gst_deinit() call is used to clean up all internal resources used
100  * by <application>GStreamer</application>. It is mostly used in unit tests 
101  * to check for leaks.
102  *
103  * Last reviewed on 2006-08-11 (0.10.10)
104  */
105
106 #include "gst_private.h"
107 #include "gstconfig.h"
108 #include <stdlib.h>
109 #include <stdio.h>
110 #include <sys/types.h>
111 #ifdef HAVE_SYS_UTSNAME_H
112 #include <sys/utsname.h>
113 #endif
114 #ifdef HAVE_UNISTD_H
115 #include <unistd.h>
116 #endif
117 #ifdef G_OS_WIN32
118 #define WIN32_LEAN_AND_MEAN     /* prevents from including too many things */
119 #include <windows.h>            /* GetStdHandle, windows console */
120 #endif
121
122 #include "gst-i18n-lib.h"
123 #include <locale.h>             /* for LC_ALL */
124
125 #include "gst.h"
126
127 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
128
129 #define MAX_PATH_SPLIT  16
130 #define GST_PLUGIN_SEPARATOR ","
131
132 static gboolean gst_initialized = FALSE;
133 static gboolean gst_deinitialized = FALSE;
134
135 #ifdef G_OS_WIN32
136 HMODULE _priv_gst_dll_handle = NULL;
137 #endif
138
139 #ifndef GST_DISABLE_REGISTRY
140 GList *_priv_gst_plugin_paths = NULL;   /* for delayed processing in post_init */
141
142 extern gboolean _priv_gst_disable_registry_update;
143 #endif
144
145 #ifndef GST_DISABLE_GST_DEBUG
146 extern const gchar *priv_gst_dump_dot_dir;
147 #endif
148
149 /* defaults */
150
151 /* set to TRUE when segfaults need to be left as is */
152 static gboolean _gst_disable_segtrap = FALSE;
153
154 static gboolean init_pre (GOptionContext * context, GOptionGroup * group,
155     gpointer data, GError ** error);
156 static gboolean init_post (GOptionContext * context, GOptionGroup * group,
157     gpointer data, GError ** error);
158 #ifndef GST_DISABLE_OPTION_PARSING
159 static gboolean parse_goption_arg (const gchar * s_opt,
160     const gchar * arg, gpointer data, GError ** err);
161 #endif
162
163 GSList *_priv_gst_preload_plugins = NULL;
164
165 const gchar g_log_domain_gstreamer[] = "GStreamer";
166
167 static void
168 debug_log_handler (const gchar * log_domain,
169     GLogLevelFlags log_level, const gchar * message, gpointer user_data)
170 {
171   g_log_default_handler (log_domain, log_level, message, user_data);
172   /* FIXME: do we still need this ? fatal errors these days are all
173    * other than core errors */
174   /* g_on_error_query (NULL); */
175 }
176
177 enum
178 {
179   ARG_VERSION = 1,
180   ARG_FATAL_WARNINGS,
181 #ifndef GST_DISABLE_GST_DEBUG
182   ARG_DEBUG_LEVEL,
183   ARG_DEBUG,
184   ARG_DEBUG_DISABLE,
185   ARG_DEBUG_NO_COLOR,
186   ARG_DEBUG_HELP,
187 #endif
188   ARG_PLUGIN_SPEW,
189   ARG_PLUGIN_PATH,
190   ARG_PLUGIN_LOAD,
191   ARG_SEGTRAP_DISABLE,
192   ARG_REGISTRY_UPDATE_DISABLE,
193   ARG_REGISTRY_FORK_DISABLE
194 };
195
196 /* debug-spec ::= category-spec [, category-spec]*
197  * category-spec ::= category:val | val
198  * category ::= [^:]+
199  * val ::= [0-5]
200  */
201
202 #ifndef NUL
203 #define NUL '\0'
204 #endif
205
206 #ifndef GST_DISABLE_GST_DEBUG
207 static gboolean
208 parse_debug_category (gchar * str, const gchar ** category)
209 {
210   if (!str)
211     return FALSE;
212
213   /* works in place */
214   g_strstrip (str);
215
216   if (str[0] != NUL) {
217     *category = str;
218     return TRUE;
219   }
220
221   return FALSE;
222 }
223
224 static gboolean
225 parse_debug_level (gchar * str, gint * level)
226 {
227   if (!str)
228     return FALSE;
229
230   /* works in place */
231   g_strstrip (str);
232
233   if (str[0] != NUL && str[1] == NUL
234       && str[0] >= '0' && str[0] < '0' + GST_LEVEL_COUNT) {
235     *level = str[0] - '0';
236     return TRUE;
237   }
238
239   return FALSE;
240 }
241
242 static void
243 parse_debug_list (const gchar * list)
244 {
245   gchar **split;
246   gchar **walk;
247
248   g_return_if_fail (list != NULL);
249
250   split = g_strsplit (list, ",", 0);
251
252   for (walk = split; *walk; walk++) {
253     if (strchr (*walk, ':')) {
254       gchar **values = g_strsplit (*walk, ":", 2);
255
256       if (values[0] && values[1]) {
257         gint level;
258         const gchar *category;
259
260         if (parse_debug_category (values[0], &category)
261             && parse_debug_level (values[1], &level))
262           gst_debug_set_threshold_for_name (category, level);
263       }
264
265       g_strfreev (values);
266     } else {
267       gint level;
268
269       if (parse_debug_level (*walk, &level))
270         gst_debug_set_default_threshold (level);
271     }
272   }
273
274   g_strfreev (split);
275 }
276 #endif
277
278 #ifdef G_OS_WIN32
279 BOOL WINAPI
280 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
281 {
282   if (fdwReason == DLL_PROCESS_ATTACH)
283     _priv_gst_dll_handle = (HMODULE) hinstDLL;
284   return TRUE;
285 }
286
287 #endif
288
289 /**
290  * gst_init_get_option_group:
291  *
292  * Returns a #GOptionGroup with GStreamer's argument specifications. The
293  * group is set up to use standard GOption callbacks, so when using this
294  * group in combination with GOption parsing methods, all argument parsing
295  * and initialization is automated.
296  *
297  * This function is useful if you want to integrate GStreamer with other
298  * libraries that use GOption (see g_option_context_add_group() ).
299  *
300  * If you use this function, you should make sure you initialise the GLib
301  * threading system as one of the very first things in your program
302  * (see the example at the beginning of this section).
303  *
304  * Returns: a pointer to GStreamer's option group.
305  */
306
307 GOptionGroup *
308 gst_init_get_option_group (void)
309 {
310 #ifndef GST_DISABLE_OPTION_PARSING
311   GOptionGroup *group;
312   static const GOptionEntry gst_args[] = {
313     {"gst-version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
314         (gpointer) parse_goption_arg, N_("Print the GStreamer version"), NULL},
315     {"gst-fatal-warnings", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
316         (gpointer) parse_goption_arg, N_("Make all warnings fatal"), NULL},
317 #ifndef GST_DISABLE_GST_DEBUG
318     {"gst-debug-help", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
319           (gpointer) parse_goption_arg,
320           N_("Print available debug categories and exit"),
321         NULL},
322     {"gst-debug-level", 0, 0, G_OPTION_ARG_CALLBACK,
323           (gpointer) parse_goption_arg,
324           N_("Default debug level from 1 (only error) to 5 (anything) or "
325               "0 for no output"),
326         N_("LEVEL")},
327     {"gst-debug", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) parse_goption_arg,
328           N_("Comma-separated list of category_name:level pairs to set "
329               "specific levels for the individual categories. Example: "
330               "GST_AUTOPLUG:5,GST_ELEMENT_*:3"),
331         N_("LIST")},
332     {"gst-debug-no-color", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
333           (gpointer) parse_goption_arg, N_("Disable colored debugging output"),
334         NULL},
335     {"gst-debug-disable", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
336         (gpointer) parse_goption_arg, N_("Disable debugging"), NULL},
337 #endif
338     {"gst-plugin-spew", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
339           (gpointer) parse_goption_arg,
340           N_("Enable verbose plugin loading diagnostics"),
341         NULL},
342     {"gst-plugin-path", 0, 0, G_OPTION_ARG_CALLBACK,
343           (gpointer) parse_goption_arg,
344         N_("Colon-separated paths containing plugins"), N_("PATHS")},
345     {"gst-plugin-load", 0, 0, G_OPTION_ARG_CALLBACK,
346           (gpointer) parse_goption_arg,
347           N_("Comma-separated list of plugins to preload in addition to the "
348               "list stored in environment variable GST_PLUGIN_PATH"),
349         N_("PLUGINS")},
350     {"gst-disable-segtrap", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
351           (gpointer) parse_goption_arg,
352           N_("Disable trapping of segmentation faults during plugin loading"),
353         NULL},
354     {"gst-disable-registry-update", 0, G_OPTION_FLAG_NO_ARG,
355           G_OPTION_ARG_CALLBACK,
356           (gpointer) parse_goption_arg,
357           N_("Disable updating the registry"),
358         NULL},
359     {"gst-disable-registry-fork", 0, G_OPTION_FLAG_NO_ARG,
360           G_OPTION_ARG_CALLBACK,
361           (gpointer) parse_goption_arg,
362           N_("Disable spawning a helper process while scanning the registry"),
363         NULL},
364     {NULL}
365   };
366
367   /* The GLib threading system must be initialised before calling any other
368    * GLib function according to the documentation; if the application hasn't
369    * called gst_init() yet or initialised the threading system otherwise, we
370    * better issue a warning here (since chances are high that the application
371    * has already called other GLib functions such as g_option_context_new() */
372   if (!g_thread_supported ()) {
373     g_warning ("The GStreamer function gst_init_get_option_group() was\n"
374         "\tcalled, but the GLib threading system has not been initialised\n"
375         "\tyet, something that must happen before any other GLib function\n"
376         "\tis called. The application needs to be fixed so that it calls\n"
377         "\t   if (!g_thread_supported ()) g_thread_init(NULL);\n"
378         "\tas very first thing in its main() function. Please file a bug\n"
379         "\tagainst this application.");
380     g_thread_init (NULL);
381   }
382
383   group = g_option_group_new ("gst", _("GStreamer Options"),
384       _("Show GStreamer Options"), NULL, NULL);
385   g_option_group_set_parse_hooks (group, (GOptionParseFunc) init_pre,
386       (GOptionParseFunc) init_post);
387
388   g_option_group_add_entries (group, gst_args);
389   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
390
391   return group;
392 #else
393   return NULL;
394 #endif
395 }
396
397 /**
398  * gst_init_check:
399  * @argc: pointer to application's argc
400  * @argv: pointer to application's argv
401  * @err: pointer to a #GError to which a message will be posted on error
402  *
403  * Initializes the GStreamer library, setting up internal path lists,
404  * registering built-in elements, and loading standard plugins.
405  *
406  * This function will return %FALSE if GStreamer could not be initialized
407  * for some reason.  If you want your program to fail fatally,
408  * use gst_init() instead.
409  *
410  * This function should be called before calling any other GLib functions. If
411  * this is not an option, your program must initialise the GLib thread system
412  * using g_thread_init() before any other GLib functions are called.
413  *
414  * Returns: %TRUE if GStreamer could be initialized.
415  */
416 gboolean
417 gst_init_check (int *argc, char **argv[], GError ** err)
418 {
419 #ifndef GST_DISABLE_OPTION_PARSING
420   GOptionGroup *group;
421   GOptionContext *ctx;
422 #endif
423   gboolean res;
424
425   if (!g_thread_supported ())
426     g_thread_init (NULL);
427
428   if (gst_initialized) {
429     GST_DEBUG ("already initialized gst");
430     return TRUE;
431   }
432 #ifndef GST_DISABLE_OPTION_PARSING
433   ctx = g_option_context_new ("- GStreamer initialization");
434   g_option_context_set_ignore_unknown_options (ctx, TRUE);
435   group = gst_init_get_option_group ();
436   g_option_context_add_group (ctx, group);
437   res = g_option_context_parse (ctx, argc, argv, err);
438   g_option_context_free (ctx);
439 #else
440   init_pre (NULL, NULL, NULL, NULL);
441   init_post (NULL, NULL, NULL, NULL);
442   res = TRUE;
443 #endif
444
445   gst_initialized = res;
446
447   if (res) {
448     GST_INFO ("initialized GStreamer successfully");
449   } else {
450     GST_INFO ("failed to initialize GStreamer");
451   }
452
453   return res;
454 }
455
456 /**
457  * gst_init:
458  * @argc: (inout): pointer to application's argc
459  * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv
460  *
461  * Initializes the GStreamer library, setting up internal path lists,
462  * registering built-in elements, and loading standard plugins.
463  *
464  * This function should be called before calling any other GLib functions. If
465  * this is not an option, your program must initialise the GLib thread system
466  * using g_thread_init() before any other GLib functions are called.
467  *
468  * <note><para>
469  * This function will terminate your program if it was unable to initialize
470  * GStreamer for some reason.  If you want your program to fall back,
471  * use gst_init_check() instead.
472  * </para></note>
473  *
474  * WARNING: This function does not work in the same way as corresponding
475  * functions in other glib-style libraries, such as gtk_init().  In
476  * particular, unknown command line options cause this function to
477  * abort program execution.
478  */
479 void
480 gst_init (int *argc, char **argv[])
481 {
482   GError *err = NULL;
483
484   if (!gst_init_check (argc, argv, &err)) {
485     g_print ("Could not initialize GStreamer: %s\n",
486         err ? err->message : "unknown error occurred");
487     if (err) {
488       g_error_free (err);
489     }
490     exit (1);
491   }
492 }
493
494 #ifndef GST_DISABLE_REGISTRY
495 static void
496 add_path_func (gpointer data, gpointer user_data)
497 {
498   GST_INFO ("Adding plugin path: \"%s\", will scan later", (gchar *) data);
499   _priv_gst_plugin_paths =
500       g_list_append (_priv_gst_plugin_paths, g_strdup (data));
501 }
502 #endif
503
504 #ifndef GST_DISABLE_OPTION_PARSING
505 static void
506 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
507 {
508   _priv_gst_preload_plugins =
509       g_slist_prepend (_priv_gst_preload_plugins, g_strdup (data));
510 }
511 #endif
512
513 #ifndef GST_DISABLE_OPTION_PARSING
514 static void
515 split_and_iterate (const gchar * stringlist, gchar * separator, GFunc iterator,
516     gpointer user_data)
517 {
518   gchar **strings;
519   gint j = 0;
520   gchar *lastlist = g_strdup (stringlist);
521
522   while (lastlist) {
523     strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
524     g_free (lastlist);
525     lastlist = NULL;
526
527     while (strings[j]) {
528       iterator (strings[j], user_data);
529       if (++j == MAX_PATH_SPLIT) {
530         lastlist = g_strdup (strings[j]);
531         j = 0;
532         break;
533       }
534     }
535     g_strfreev (strings);
536   }
537 }
538 #endif
539
540 /* we have no fail cases yet, but maybe in the future */
541 static gboolean
542 init_pre (GOptionContext * context, GOptionGroup * group, gpointer data,
543     GError ** error)
544 {
545   if (gst_initialized) {
546     GST_DEBUG ("already initialized");
547     return TRUE;
548   }
549
550   /* GStreamer was built against a GLib >= 2.8 and is therefore not doing
551    * the refcount hack. Check that it isn't being run against an older GLib */
552   if (glib_major_version < 2 ||
553       (glib_major_version == 2 && glib_minor_version < 8)) {
554     g_warning ("GStreamer was compiled against GLib %d.%d.%d but is running"
555         " against %d.%d.%d. This will cause reference counting issues",
556         GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
557         glib_major_version, glib_minor_version, glib_micro_version);
558   }
559
560   g_type_init ();
561
562   /* we need threading to be enabled right here */
563   g_assert (g_thread_supported ());
564   _gst_debug_init ();
565
566 #ifdef ENABLE_NLS
567   setlocale (LC_ALL, "");
568   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
569   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
570 #endif /* ENABLE_NLS */
571
572 #ifndef GST_DISABLE_GST_DEBUG
573   {
574     const gchar *debug_list;
575
576     if (g_getenv ("GST_DEBUG_NO_COLOR") != NULL)
577       gst_debug_set_colored (FALSE);
578
579     debug_list = g_getenv ("GST_DEBUG");
580     if (debug_list) {
581       parse_debug_list (debug_list);
582     }
583   }
584
585   priv_gst_dump_dot_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR");
586 #endif
587   /* This is the earliest we can make stuff show up in the logs.
588    * So give some useful info about GStreamer here */
589   GST_INFO ("Initializing GStreamer Core Library version %s", VERSION);
590   GST_INFO ("Using library installed in %s", LIBDIR);
591
592   /* Print some basic system details if possible (OS/architecture) */
593 #ifdef HAVE_SYS_UTSNAME_H
594   {
595     struct utsname sys_details;
596
597     if (uname (&sys_details) == 0) {
598       GST_INFO ("%s %s %s %s %s", sys_details.sysname,
599           sys_details.nodename, sys_details.release, sys_details.version,
600           sys_details.machine);
601     }
602   }
603 #endif
604
605   return TRUE;
606 }
607
608 static gboolean
609 gst_register_core_elements (GstPlugin * plugin)
610 {
611   /* register some standard builtin types */
612   if (!gst_element_register (plugin, "bin", GST_RANK_PRIMARY,
613           GST_TYPE_BIN) ||
614       !gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY,
615           GST_TYPE_PIPELINE)
616       )
617     g_assert_not_reached ();
618
619   return TRUE;
620 }
621
622 /*
623  * this bit handles:
624  * - initalization of threads if we use them
625  * - log handler
626  * - initial output
627  * - initializes gst_format
628  * - registers a bunch of types for gst_objects
629  *
630  * - we don't have cases yet where this fails, but in the future
631  *   we might and then it's nice to be able to return that
632  */
633 static gboolean
634 init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
635     GError ** error)
636 {
637   GLogLevelFlags llf;
638
639 #ifndef GST_DISABLE_TRACE
640   GstTrace *gst_trace;
641 #endif /* GST_DISABLE_TRACE */
642
643   if (gst_initialized) {
644     GST_DEBUG ("already initialized");
645     return TRUE;
646   }
647
648   llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
649   g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
650
651   _priv_gst_quarks_initialize ();
652   _gst_format_initialize ();
653   _gst_query_initialize ();
654   g_type_class_ref (gst_object_get_type ());
655   g_type_class_ref (gst_pad_get_type ());
656   g_type_class_ref (gst_element_factory_get_type ());
657   g_type_class_ref (gst_element_get_type ());
658   g_type_class_ref (gst_type_find_factory_get_type ());
659   g_type_class_ref (gst_bin_get_type ());
660   g_type_class_ref (gst_bus_get_type ());
661   g_type_class_ref (gst_task_get_type ());
662   g_type_class_ref (gst_clock_get_type ());
663
664   g_type_class_ref (gst_index_factory_get_type ());
665   gst_uri_handler_get_type ();
666
667   g_type_class_ref (gst_object_flags_get_type ());
668   g_type_class_ref (gst_bin_flags_get_type ());
669   g_type_class_ref (gst_buffer_flag_get_type ());
670   g_type_class_ref (gst_buffer_copy_flags_get_type ());
671   g_type_class_ref (gst_buffer_list_item_get_type ());
672   g_type_class_ref (gst_bus_flags_get_type ());
673   g_type_class_ref (gst_bus_sync_reply_get_type ());
674   g_type_class_ref (gst_caps_flags_get_type ());
675   g_type_class_ref (gst_clock_return_get_type ());
676   g_type_class_ref (gst_clock_entry_type_get_type ());
677   g_type_class_ref (gst_clock_flags_get_type ());
678   g_type_class_ref (gst_clock_type_get_type ());
679   g_type_class_ref (gst_debug_graph_details_get_type ());
680   g_type_class_ref (gst_state_get_type ());
681   g_type_class_ref (gst_state_change_return_get_type ());
682   g_type_class_ref (gst_state_change_get_type ());
683   g_type_class_ref (gst_element_flags_get_type ());
684   g_type_class_ref (gst_core_error_get_type ());
685   g_type_class_ref (gst_library_error_get_type ());
686   g_type_class_ref (gst_resource_error_get_type ());
687   g_type_class_ref (gst_stream_error_get_type ());
688   g_type_class_ref (gst_event_type_flags_get_type ());
689   g_type_class_ref (gst_event_type_get_type ());
690   g_type_class_ref (gst_seek_type_get_type ());
691   g_type_class_ref (gst_seek_flags_get_type ());
692   g_type_class_ref (gst_format_get_type ());
693   g_type_class_ref (gst_index_certainty_get_type ());
694   g_type_class_ref (gst_index_entry_type_get_type ());
695   g_type_class_ref (gst_index_lookup_method_get_type ());
696   g_type_class_ref (gst_assoc_flags_get_type ());
697   g_type_class_ref (gst_index_resolver_method_get_type ());
698   g_type_class_ref (gst_index_flags_get_type ());
699   g_type_class_ref (gst_debug_level_get_type ());
700   g_type_class_ref (gst_debug_color_flags_get_type ());
701   g_type_class_ref (gst_iterator_result_get_type ());
702   g_type_class_ref (gst_iterator_item_get_type ());
703   g_type_class_ref (gst_message_type_get_type ());
704   g_type_class_ref (gst_mini_object_flags_get_type ());
705   g_type_class_ref (gst_pad_link_return_get_type ());
706   g_type_class_ref (gst_flow_return_get_type ());
707   g_type_class_ref (gst_activate_mode_get_type ());
708   g_type_class_ref (gst_pad_direction_get_type ());
709   g_type_class_ref (gst_pad_flags_get_type ());
710   g_type_class_ref (gst_pad_presence_get_type ());
711   g_type_class_ref (gst_pad_template_flags_get_type ());
712   g_type_class_ref (gst_pipeline_flags_get_type ());
713   g_type_class_ref (gst_plugin_error_get_type ());
714   g_type_class_ref (gst_plugin_flags_get_type ());
715   g_type_class_ref (gst_plugin_dependency_flags_get_type ());
716   g_type_class_ref (gst_rank_get_type ());
717   g_type_class_ref (gst_query_type_get_type ());
718   g_type_class_ref (gst_buffering_mode_get_type ());
719   g_type_class_ref (gst_stream_status_type_get_type ());
720   g_type_class_ref (gst_structure_change_type_get_type ());
721   g_type_class_ref (gst_tag_merge_mode_get_type ());
722   g_type_class_ref (gst_tag_flag_get_type ());
723   g_type_class_ref (gst_task_pool_get_type ());
724   g_type_class_ref (gst_task_state_get_type ());
725   g_type_class_ref (gst_alloc_trace_flags_get_type ());
726   g_type_class_ref (gst_type_find_probability_get_type ());
727   g_type_class_ref (gst_uri_type_get_type ());
728   g_type_class_ref (gst_parse_error_get_type ());
729   g_type_class_ref (gst_parse_flags_get_type ());
730   g_type_class_ref (gst_search_mode_get_type ());
731
732   gst_structure_get_type ();
733   _gst_value_initialize ();
734   g_type_class_ref (gst_param_spec_fraction_get_type ());
735   gst_caps_get_type ();
736   _gst_event_initialize ();
737   _gst_buffer_initialize ();
738   _gst_buffer_list_initialize ();
739   _gst_message_initialize ();
740   _gst_tag_initialize ();
741
742   _gst_plugin_initialize ();
743
744   gst_g_error_get_type ();
745
746   /* register core plugins */
747   gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR,
748       "staticelements", "core elements linked into the GStreamer library",
749       gst_register_core_elements, VERSION, GST_LICENSE, PACKAGE,
750       GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
751
752   /*
753    * Any errors happening below this point are non-fatal, we therefore mark
754    * gstreamer as being initialized, since it is the case from a plugin point of
755    * view.
756    *
757    * If anything fails, it will be put back to FALSE in gst_init_check().
758    * This allows some special plugins that would call gst_init() to not cause a
759    * looping effect (i.e. initializing GStreamer twice).
760    */
761   gst_initialized = TRUE;
762
763   if (!gst_update_registry ())
764     return FALSE;
765
766 #ifndef GST_DISABLE_TRACE
767   _gst_trace_on = 0;
768   if (_gst_trace_on) {
769     gst_trace = gst_trace_new ("gst.trace", 1024);
770     gst_trace_set_default (gst_trace);
771   }
772 #endif /* GST_DISABLE_TRACE */
773
774   return TRUE;
775 }
776
777 #ifndef GST_DISABLE_GST_DEBUG
778 static gboolean
779 select_all (GstPlugin * plugin, gpointer user_data)
780 {
781   return TRUE;
782 }
783
784 static gint
785 sort_by_category_name (gconstpointer a, gconstpointer b)
786 {
787   return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
788       gst_debug_category_get_name ((GstDebugCategory *) b));
789 }
790
791 static void
792 gst_debug_help (void)
793 {
794   GSList *list, *walk;
795   GList *list2, *g;
796
797   /* Need to ensure the registry is loaded to get debug categories */
798   if (!init_post (NULL, NULL, NULL, NULL))
799     exit (1);
800
801   list2 = gst_registry_plugin_filter (gst_registry_get_default (),
802       select_all, FALSE, NULL);
803
804   /* FIXME this is gross.  why don't debug have categories PluginFeatures? */
805   for (g = list2; g; g = g_list_next (g)) {
806     GstPlugin *plugin = GST_PLUGIN_CAST (g->data);
807
808     gst_plugin_load (plugin);
809   }
810   g_list_free (list2);
811
812   list = gst_debug_get_all_categories ();
813   walk = list = g_slist_sort (list, sort_by_category_name);
814
815   g_print ("\n");
816   g_print ("name                  level    description\n");
817   g_print ("---------------------+--------+--------------------------------\n");
818
819   while (walk) {
820     GstDebugCategory *cat = (GstDebugCategory *) walk->data;
821
822     if (gst_debug_is_colored ()) {
823 #ifdef G_OS_WIN32
824       gint color = gst_debug_construct_win_color (cat->color);
825       const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
826
827       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
828       g_print ("%-20s", gst_debug_category_get_name (cat));
829       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
830       g_print (" %1d %s ", gst_debug_category_get_threshold (cat),
831           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)));
832       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
833       g_print ("%s", gst_debug_category_get_description (cat));
834       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
835       g_print ("\n");
836 #else /* G_OS_WIN32 */
837       gchar *color = gst_debug_construct_term_color (cat->color);
838
839       g_print ("%s%-20s\033[00m  %1d %s  %s%s\033[00m\n",
840           color,
841           gst_debug_category_get_name (cat),
842           gst_debug_category_get_threshold (cat),
843           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
844           color, gst_debug_category_get_description (cat));
845       g_free (color);
846 #endif /* G_OS_WIN32 */
847     } else {
848       g_print ("%-20s  %1d %s  %s\n", gst_debug_category_get_name (cat),
849           gst_debug_category_get_threshold (cat),
850           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
851           gst_debug_category_get_description (cat));
852     }
853     walk = g_slist_next (walk);
854   }
855   g_slist_free (list);
856   g_print ("\n");
857 }
858 #endif
859
860 #ifndef GST_DISABLE_OPTION_PARSING
861 static gboolean
862 parse_one_option (gint opt, const gchar * arg, GError ** err)
863 {
864   switch (opt) {
865     case ARG_VERSION:
866       g_print ("GStreamer Core Library version %s\n", PACKAGE_VERSION);
867       exit (0);
868     case ARG_FATAL_WARNINGS:{
869       GLogLevelFlags fatal_mask;
870
871       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
872       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
873       g_log_set_always_fatal (fatal_mask);
874       break;
875     }
876 #ifndef GST_DISABLE_GST_DEBUG
877     case ARG_DEBUG_LEVEL:{
878       gint tmp = 0;
879
880       tmp = strtol (arg, NULL, 0);
881       if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
882         gst_debug_set_default_threshold (tmp);
883       }
884       break;
885     }
886     case ARG_DEBUG:
887       parse_debug_list (arg);
888       break;
889     case ARG_DEBUG_NO_COLOR:
890       gst_debug_set_colored (FALSE);
891       break;
892     case ARG_DEBUG_DISABLE:
893       gst_debug_set_active (FALSE);
894       break;
895     case ARG_DEBUG_HELP:
896       gst_debug_help ();
897       exit (0);
898 #endif
899     case ARG_PLUGIN_SPEW:
900       break;
901     case ARG_PLUGIN_PATH:
902 #ifndef GST_DISABLE_REGISTRY
903       split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, NULL);
904 #endif /* GST_DISABLE_REGISTRY */
905       break;
906     case ARG_PLUGIN_LOAD:
907       split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
908       break;
909     case ARG_SEGTRAP_DISABLE:
910       _gst_disable_segtrap = TRUE;
911       break;
912     case ARG_REGISTRY_UPDATE_DISABLE:
913 #ifndef GST_DISABLE_REGISTRY
914       _priv_gst_disable_registry_update = TRUE;
915 #endif
916       break;
917     case ARG_REGISTRY_FORK_DISABLE:
918       gst_registry_fork_set_enabled (FALSE);
919       break;
920     default:
921       g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
922           _("Unknown option"));
923       return FALSE;
924   }
925
926   return TRUE;
927 }
928
929 static gboolean
930 parse_goption_arg (const gchar * opt,
931     const gchar * arg, gpointer data, GError ** err)
932 {
933   static const struct
934   {
935     gchar *opt;
936     int val;
937   } options[] = {
938     {
939     "--gst-version", ARG_VERSION}, {
940     "--gst-fatal-warnings", ARG_FATAL_WARNINGS},
941 #ifndef GST_DISABLE_GST_DEBUG
942     {
943     "--gst-debug-level", ARG_DEBUG_LEVEL}, {
944     "--gst-debug", ARG_DEBUG}, {
945     "--gst-debug-disable", ARG_DEBUG_DISABLE}, {
946     "--gst-debug-no-color", ARG_DEBUG_NO_COLOR}, {
947     "--gst-debug-help", ARG_DEBUG_HELP},
948 #endif
949     {
950     "--gst-plugin-spew", ARG_PLUGIN_SPEW}, {
951     "--gst-plugin-path", ARG_PLUGIN_PATH}, {
952     "--gst-plugin-load", ARG_PLUGIN_LOAD}, {
953     "--gst-disable-segtrap", ARG_SEGTRAP_DISABLE}, {
954     "--gst-disable-registry-update", ARG_REGISTRY_UPDATE_DISABLE}, {
955     "--gst-disable-registry-fork", ARG_REGISTRY_FORK_DISABLE}, {
956     NULL}
957   };
958   gint val = 0, n;
959
960   for (n = 0; options[n].opt; n++) {
961     if (!strcmp (opt, options[n].opt)) {
962       val = options[n].val;
963       break;
964     }
965   }
966
967   return parse_one_option (val, arg, err);
968 }
969 #endif
970
971 /**
972  * gst_deinit:
973  *
974  * Clean up any resources created by GStreamer in gst_init().
975  *
976  * It is normally not needed to call this function in a normal application
977  * as the resources will automatically be freed when the program terminates.
978  * This function is therefore mostly used by testsuites and other memory
979  * profiling tools.
980  *
981  * After this call GStreamer (including this method) should not be used anymore. 
982  */
983 void
984 gst_deinit (void)
985 {
986   GstClock *clock;
987
988   GST_INFO ("deinitializing GStreamer");
989
990   if (gst_deinitialized) {
991     GST_DEBUG ("already deinitialized");
992     return;
993   }
994
995   g_slist_foreach (_priv_gst_preload_plugins, (GFunc) g_free, NULL);
996   g_slist_free (_priv_gst_preload_plugins);
997   _priv_gst_preload_plugins = NULL;
998
999 #ifndef GST_DISABLE_REGISTRY
1000   g_list_foreach (_priv_gst_plugin_paths, (GFunc) g_free, NULL);
1001   g_list_free (_priv_gst_plugin_paths);
1002   _priv_gst_plugin_paths = NULL;
1003 #endif
1004
1005   clock = gst_system_clock_obtain ();
1006   gst_object_unref (clock);
1007   gst_object_unref (clock);
1008
1009   _priv_gst_registry_cleanup ();
1010
1011   g_type_class_unref (g_type_class_peek (gst_object_get_type ()));
1012   g_type_class_unref (g_type_class_peek (gst_pad_get_type ()));
1013   g_type_class_unref (g_type_class_peek (gst_element_factory_get_type ()));
1014   g_type_class_unref (g_type_class_peek (gst_element_get_type ()));
1015   g_type_class_unref (g_type_class_peek (gst_type_find_factory_get_type ()));
1016   g_type_class_unref (g_type_class_peek (gst_bin_get_type ()));
1017   g_type_class_unref (g_type_class_peek (gst_bus_get_type ()));
1018   g_type_class_unref (g_type_class_peek (gst_task_get_type ()));
1019   g_type_class_unref (g_type_class_peek (gst_index_factory_get_type ()));
1020   g_type_class_unref (g_type_class_peek (gst_object_flags_get_type ()));
1021   g_type_class_unref (g_type_class_peek (gst_bin_flags_get_type ()));
1022   g_type_class_unref (g_type_class_peek (gst_buffer_flag_get_type ()));
1023   g_type_class_unref (g_type_class_peek (gst_buffer_copy_flags_get_type ()));
1024   g_type_class_unref (g_type_class_peek (gst_buffer_list_item_get_type ()));
1025   g_type_class_unref (g_type_class_peek (gst_bus_flags_get_type ()));
1026   g_type_class_unref (g_type_class_peek (gst_bus_sync_reply_get_type ()));
1027   g_type_class_unref (g_type_class_peek (gst_caps_flags_get_type ()));
1028   g_type_class_unref (g_type_class_peek (gst_clock_type_get_type ()));
1029   g_type_class_unref (g_type_class_peek (gst_clock_return_get_type ()));
1030   g_type_class_unref (g_type_class_peek (gst_clock_entry_type_get_type ()));
1031   g_type_class_unref (g_type_class_peek (gst_clock_flags_get_type ()));
1032   g_type_class_unref (g_type_class_peek (gst_debug_graph_details_get_type ()));
1033   g_type_class_unref (g_type_class_peek (gst_state_get_type ()));
1034   g_type_class_unref (g_type_class_peek (gst_state_change_return_get_type ()));
1035   g_type_class_unref (g_type_class_peek (gst_state_change_get_type ()));
1036   g_type_class_unref (g_type_class_peek (gst_element_flags_get_type ()));
1037   g_type_class_unref (g_type_class_peek (gst_core_error_get_type ()));
1038   g_type_class_unref (g_type_class_peek (gst_library_error_get_type ()));
1039   g_type_class_unref (g_type_class_peek (gst_plugin_dependency_flags_get_type
1040           ()));
1041   g_type_class_unref (g_type_class_peek (gst_parse_flags_get_type ()));
1042   g_type_class_unref (g_type_class_peek (gst_resource_error_get_type ()));
1043   g_type_class_unref (g_type_class_peek (gst_search_mode_get_type ()));
1044   g_type_class_unref (g_type_class_peek (gst_stream_error_get_type ()));
1045   g_type_class_unref (g_type_class_peek (gst_stream_status_type_get_type ()));
1046   g_type_class_unref (g_type_class_peek (gst_structure_change_type_get_type
1047           ()));
1048   g_type_class_unref (g_type_class_peek (gst_event_type_flags_get_type ()));
1049   g_type_class_unref (g_type_class_peek (gst_event_type_get_type ()));
1050   g_type_class_unref (g_type_class_peek (gst_seek_type_get_type ()));
1051   g_type_class_unref (g_type_class_peek (gst_seek_flags_get_type ()));
1052   g_type_class_unref (g_type_class_peek (gst_format_get_type ()));
1053   g_type_class_unref (g_type_class_peek (gst_index_certainty_get_type ()));
1054   g_type_class_unref (g_type_class_peek (gst_index_entry_type_get_type ()));
1055   g_type_class_unref (g_type_class_peek (gst_index_lookup_method_get_type ()));
1056   g_type_class_unref (g_type_class_peek (gst_assoc_flags_get_type ()));
1057   g_type_class_unref (g_type_class_peek (gst_index_resolver_method_get_type
1058           ()));
1059   g_type_class_unref (g_type_class_peek (gst_index_flags_get_type ()));
1060   g_type_class_unref (g_type_class_peek (gst_debug_level_get_type ()));
1061   g_type_class_unref (g_type_class_peek (gst_debug_color_flags_get_type ()));
1062   g_type_class_unref (g_type_class_peek (gst_iterator_result_get_type ()));
1063   g_type_class_unref (g_type_class_peek (gst_iterator_item_get_type ()));
1064   g_type_class_unref (g_type_class_peek (gst_message_type_get_type ()));
1065   g_type_class_unref (g_type_class_peek (gst_mini_object_flags_get_type ()));
1066   g_type_class_unref (g_type_class_peek (gst_pad_link_return_get_type ()));
1067   g_type_class_unref (g_type_class_peek (gst_flow_return_get_type ()));
1068   g_type_class_unref (g_type_class_peek (gst_activate_mode_get_type ()));
1069   g_type_class_unref (g_type_class_peek (gst_pad_direction_get_type ()));
1070   g_type_class_unref (g_type_class_peek (gst_pad_flags_get_type ()));
1071   g_type_class_unref (g_type_class_peek (gst_pad_presence_get_type ()));
1072   g_type_class_unref (g_type_class_peek (gst_pad_template_flags_get_type ()));
1073   g_type_class_unref (g_type_class_peek (gst_pipeline_flags_get_type ()));
1074   g_type_class_unref (g_type_class_peek (gst_plugin_error_get_type ()));
1075   g_type_class_unref (g_type_class_peek (gst_plugin_flags_get_type ()));
1076   g_type_class_unref (g_type_class_peek (gst_rank_get_type ()));
1077   g_type_class_unref (g_type_class_peek (gst_query_type_get_type ()));
1078   g_type_class_unref (g_type_class_peek (gst_buffering_mode_get_type ()));
1079   g_type_class_unref (g_type_class_peek (gst_tag_merge_mode_get_type ()));
1080   g_type_class_unref (g_type_class_peek (gst_tag_flag_get_type ()));
1081   g_type_class_unref (g_type_class_peek (gst_task_state_get_type ()));
1082   g_type_class_unref (g_type_class_peek (gst_alloc_trace_flags_get_type ()));
1083   g_type_class_unref (g_type_class_peek (gst_type_find_probability_get_type
1084           ()));
1085   g_type_class_unref (g_type_class_peek (gst_uri_type_get_type ()));
1086   g_type_class_unref (g_type_class_peek (gst_parse_error_get_type ()));
1087   g_type_class_unref (g_type_class_peek (gst_param_spec_fraction_get_type ()));
1088
1089   gst_deinitialized = TRUE;
1090   GST_INFO ("deinitialized GStreamer");
1091 }
1092
1093 /**
1094  * gst_version:
1095  * @major: pointer to a guint to store the major version number
1096  * @minor: pointer to a guint to store the minor version number
1097  * @micro: pointer to a guint to store the micro version number
1098  * @nano:  pointer to a guint to store the nano version number
1099  *
1100  * Gets the version number of the GStreamer library.
1101  */
1102 void
1103 gst_version (guint * major, guint * minor, guint * micro, guint * nano)
1104 {
1105   g_return_if_fail (major);
1106   g_return_if_fail (minor);
1107   g_return_if_fail (micro);
1108   g_return_if_fail (nano);
1109
1110   *major = GST_VERSION_MAJOR;
1111   *minor = GST_VERSION_MINOR;
1112   *micro = GST_VERSION_MICRO;
1113   *nano = GST_VERSION_NANO;
1114 }
1115
1116 /**
1117  * gst_version_string:
1118  *
1119  * This function returns a string that is useful for describing this version
1120  * of GStreamer to the outside world: user agent strings, logging, ...
1121  *
1122  * Returns: a newly allocated string describing this version of GStreamer.
1123  */
1124
1125 gchar *
1126 gst_version_string ()
1127 {
1128   guint major, minor, micro, nano;
1129
1130   gst_version (&major, &minor, &micro, &nano);
1131   if (nano == 0)
1132     return g_strdup_printf ("GStreamer %d.%d.%d", major, minor, micro);
1133   else if (nano == 1)
1134     return g_strdup_printf ("GStreamer %d.%d.%d (GIT)", major, minor, micro);
1135   else
1136     return g_strdup_printf ("GStreamer %d.%d.%d (prerelease)", major, minor,
1137         micro);
1138 }
1139
1140 /**
1141  * gst_segtrap_is_enabled:
1142  *
1143  * Some functions in the GStreamer core might install a custom SIGSEGV handler
1144  * to better catch and report errors to the application. Currently this feature
1145  * is enabled by default when loading plugins.
1146  *
1147  * Applications might want to disable this behaviour with the
1148  * gst_segtrap_set_enabled() function. This is typically done if the application
1149  * wants to install its own handler without GStreamer interfering.
1150  *
1151  * Returns: %TRUE if GStreamer is allowed to install a custom SIGSEGV handler.
1152  *
1153  * Since: 0.10.10
1154  */
1155 gboolean
1156 gst_segtrap_is_enabled (void)
1157 {
1158   /* yeps, it's enabled when it's not disabled */
1159   return !_gst_disable_segtrap;
1160 }
1161
1162 /**
1163  * gst_segtrap_set_enabled:
1164  * @enabled: whether a custom SIGSEGV handler should be installed.
1165  *
1166  * Applications might want to disable/enable the SIGSEGV handling of
1167  * the GStreamer core. See gst_segtrap_is_enabled() for more information.
1168  *
1169  * Since: 0.10.10
1170  */
1171 void
1172 gst_segtrap_set_enabled (gboolean enabled)
1173 {
1174   _gst_disable_segtrap = !enabled;
1175 }