gst: Add gobject-introspection support
[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_FORK
112 #include <sys/wait.h>
113 #endif /* HAVE_FORK */
114 #ifdef HAVE_SYS_UTSNAME_H
115 #include <sys/utsname.h>
116 #endif
117 #ifdef HAVE_UNISTD_H
118 #include <unistd.h>
119 #endif
120 #ifdef G_OS_WIN32
121 #define WIN32_LEAN_AND_MEAN     /* prevents from including too many things */
122 #include <windows.h>            /* GetStdHandle, windows console */
123 #endif
124
125 #include "gst-i18n-lib.h"
126 #include <locale.h>             /* for LC_ALL */
127
128 #include "gst.h"
129
130 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
131
132 #define MAX_PATH_SPLIT  16
133 #define GST_PLUGIN_SEPARATOR ","
134
135 static gboolean gst_initialized = FALSE;
136 static gboolean gst_deinitialized = FALSE;
137
138 #ifdef G_OS_WIN32
139 static HMODULE gst_dll_handle = NULL;
140 #endif
141
142 #ifndef GST_DISABLE_REGISTRY
143 static GList *plugin_paths = NULL;      /* for delayed processing in post_init */
144 #endif
145
146 #ifndef GST_DISABLE_GST_DEBUG
147 extern const gchar *priv_gst_dump_dot_dir;
148 #endif
149
150 /* defaults */
151 #if defined(HAVE_FORK) && !defined(GST_HAVE_UNSAFE_FORK)
152 #define DEFAULT_FORK TRUE
153 #else
154 #define DEFAULT_FORK FALSE
155 #endif /* HAVE_FORK */
156
157 /* set to TRUE when segfaults need to be left as is */
158 static gboolean _gst_disable_segtrap = FALSE;
159
160 /* control the behaviour of registry rebuild */
161 static gboolean _gst_enable_registry_fork = DEFAULT_FORK;
162
163 /*set to TRUE when registry needn't to be updated */
164 static gboolean _gst_disable_registry_update = FALSE;
165
166 static void load_plugin_func (gpointer data, gpointer user_data);
167 static gboolean init_pre (GOptionContext * context, GOptionGroup * group,
168     gpointer data, GError ** error);
169 static gboolean init_post (GOptionContext * context, GOptionGroup * group,
170     gpointer data, GError ** error);
171 #ifndef GST_DISABLE_OPTION_PARSING
172 static gboolean parse_goption_arg (const gchar * s_opt,
173     const gchar * arg, gpointer data, GError ** err);
174 #endif
175
176 static GSList *preload_plugins = NULL;
177
178 const gchar g_log_domain_gstreamer[] = "GStreamer";
179
180 static void
181 debug_log_handler (const gchar * log_domain,
182     GLogLevelFlags log_level, const gchar * message, gpointer user_data)
183 {
184   g_log_default_handler (log_domain, log_level, message, user_data);
185   /* FIXME: do we still need this ? fatal errors these days are all
186    * other than core errors */
187   /* g_on_error_query (NULL); */
188 }
189
190 enum
191 {
192   ARG_VERSION = 1,
193   ARG_FATAL_WARNINGS,
194 #ifndef GST_DISABLE_GST_DEBUG
195   ARG_DEBUG_LEVEL,
196   ARG_DEBUG,
197   ARG_DEBUG_DISABLE,
198   ARG_DEBUG_NO_COLOR,
199   ARG_DEBUG_HELP,
200 #endif
201   ARG_PLUGIN_SPEW,
202   ARG_PLUGIN_PATH,
203   ARG_PLUGIN_LOAD,
204   ARG_SEGTRAP_DISABLE,
205   ARG_REGISTRY_UPDATE_DISABLE,
206   ARG_REGISTRY_FORK_DISABLE
207 };
208
209 /* debug-spec ::= category-spec [, category-spec]*
210  * category-spec ::= category:val | val
211  * category ::= [^:]+
212  * val ::= [0-5]
213  */
214
215 #ifndef NUL
216 #define NUL '\0'
217 #endif
218
219 #ifndef GST_DISABLE_GST_DEBUG
220 static gboolean
221 parse_debug_category (gchar * str, const gchar ** category)
222 {
223   if (!str)
224     return FALSE;
225
226   /* works in place */
227   g_strstrip (str);
228
229   if (str[0] != NUL) {
230     *category = str;
231     return TRUE;
232   }
233
234   return FALSE;
235 }
236
237 static gboolean
238 parse_debug_level (gchar * str, gint * level)
239 {
240   if (!str)
241     return FALSE;
242
243   /* works in place */
244   g_strstrip (str);
245
246   if (str[0] != NUL && str[1] == NUL
247       && str[0] >= '0' && str[0] < '0' + GST_LEVEL_COUNT) {
248     *level = str[0] - '0';
249     return TRUE;
250   }
251
252   return FALSE;
253 }
254
255 static void
256 parse_debug_list (const gchar * list)
257 {
258   gchar **split;
259   gchar **walk;
260
261   g_return_if_fail (list != NULL);
262
263   split = g_strsplit (list, ",", 0);
264
265   for (walk = split; *walk; walk++) {
266     if (strchr (*walk, ':')) {
267       gchar **values = g_strsplit (*walk, ":", 2);
268
269       if (values[0] && values[1]) {
270         gint level;
271         const gchar *category;
272
273         if (parse_debug_category (values[0], &category)
274             && parse_debug_level (values[1], &level))
275           gst_debug_set_threshold_for_name (category, level);
276       }
277
278       g_strfreev (values);
279     } else {
280       gint level;
281
282       if (parse_debug_level (*walk, &level))
283         gst_debug_set_default_threshold (level);
284     }
285   }
286
287   g_strfreev (split);
288 }
289 #endif
290
291 #ifdef G_OS_WIN32
292 BOOL WINAPI
293 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
294 {
295   if (fdwReason == DLL_PROCESS_ATTACH)
296     gst_dll_handle = (HMODULE) hinstDLL;
297   return TRUE;
298 }
299
300 #endif
301
302 /**
303  * gst_init_get_option_group:
304  *
305  * Returns a #GOptionGroup with GStreamer's argument specifications. The
306  * group is set up to use standard GOption callbacks, so when using this
307  * group in combination with GOption parsing methods, all argument parsing
308  * and initialization is automated.
309  *
310  * This function is useful if you want to integrate GStreamer with other
311  * libraries that use GOption (see g_option_context_add_group() ).
312  *
313  * If you use this function, you should make sure you initialise the GLib
314  * threading system as one of the very first things in your program
315  * (see the example at the beginning of this section).
316  *
317  * Returns: a pointer to GStreamer's option group.
318  */
319
320 GOptionGroup *
321 gst_init_get_option_group (void)
322 {
323 #ifndef GST_DISABLE_OPTION_PARSING
324   GOptionGroup *group;
325   static const GOptionEntry gst_args[] = {
326     {"gst-version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
327         (gpointer) parse_goption_arg, N_("Print the GStreamer version"), NULL},
328     {"gst-fatal-warnings", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
329         (gpointer) parse_goption_arg, N_("Make all warnings fatal"), NULL},
330 #ifndef GST_DISABLE_GST_DEBUG
331     {"gst-debug-help", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
332           (gpointer) parse_goption_arg,
333           N_("Print available debug categories and exit"),
334         NULL},
335     {"gst-debug-level", 0, 0, G_OPTION_ARG_CALLBACK,
336           (gpointer) parse_goption_arg,
337           N_("Default debug level from 1 (only error) to 5 (anything) or "
338               "0 for no output"),
339         N_("LEVEL")},
340     {"gst-debug", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) parse_goption_arg,
341           N_("Comma-separated list of category_name:level pairs to set "
342               "specific levels for the individual categories. Example: "
343               "GST_AUTOPLUG:5,GST_ELEMENT_*:3"),
344         N_("LIST")},
345     {"gst-debug-no-color", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
346           (gpointer) parse_goption_arg, N_("Disable colored debugging output"),
347         NULL},
348     {"gst-debug-disable", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
349         (gpointer) parse_goption_arg, N_("Disable debugging"), NULL},
350 #endif
351     {"gst-plugin-spew", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
352           (gpointer) parse_goption_arg,
353           N_("Enable verbose plugin loading diagnostics"),
354         NULL},
355     {"gst-plugin-path", 0, 0, G_OPTION_ARG_CALLBACK,
356           (gpointer) parse_goption_arg,
357         N_("Colon-separated paths containing plugins"), N_("PATHS")},
358     {"gst-plugin-load", 0, 0, G_OPTION_ARG_CALLBACK,
359           (gpointer) parse_goption_arg,
360           N_("Comma-separated list of plugins to preload in addition to the "
361               "list stored in environment variable GST_PLUGIN_PATH"),
362         N_("PLUGINS")},
363     {"gst-disable-segtrap", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
364           (gpointer) parse_goption_arg,
365           N_("Disable trapping of segmentation faults during plugin loading"),
366         NULL},
367     {"gst-disable-registry-update", 0, G_OPTION_FLAG_NO_ARG,
368           G_OPTION_ARG_CALLBACK,
369           (gpointer) parse_goption_arg,
370           N_("Disable updating the registry"),
371         NULL},
372     {"gst-disable-registry-fork", 0, G_OPTION_FLAG_NO_ARG,
373           G_OPTION_ARG_CALLBACK,
374           (gpointer) parse_goption_arg,
375           N_("Disable the use of fork() while scanning the registry"),
376         NULL},
377     {NULL}
378   };
379
380   /* The GLib threading system must be initialised before calling any other
381    * GLib function according to the documentation; if the application hasn't
382    * called gst_init() yet or initialised the threading system otherwise, we
383    * better issue a warning here (since chances are high that the application
384    * has already called other GLib functions such as g_option_context_new() */
385   if (!g_thread_supported ()) {
386     g_warning ("The GStreamer function gst_init_get_option_group() was\n"
387         "\tcalled, but the GLib threading system has not been initialised\n"
388         "\tyet, something that must happen before any other GLib function\n"
389         "\tis called. The application needs to be fixed so that it calls\n"
390         "\t   if (!g_thread_supported ()) g_thread_init(NULL);\n"
391         "\tas very first thing in its main() function. Please file a bug\n"
392         "\tagainst this application.");
393     g_thread_init (NULL);
394   }
395
396   group = g_option_group_new ("gst", _("GStreamer Options"),
397       _("Show GStreamer Options"), NULL, NULL);
398   g_option_group_set_parse_hooks (group, (GOptionParseFunc) init_pre,
399       (GOptionParseFunc) init_post);
400
401   g_option_group_add_entries (group, gst_args);
402   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
403
404   return group;
405 #else
406   return NULL;
407 #endif
408 }
409
410 /**
411  * gst_init_check:
412  * @argc: pointer to application's argc
413  * @argv: pointer to application's argv
414  * @err: pointer to a #GError to which a message will be posted on error
415  *
416  * Initializes the GStreamer library, setting up internal path lists,
417  * registering built-in elements, and loading standard plugins.
418  *
419  * This function will return %FALSE if GStreamer could not be initialized
420  * for some reason.  If you want your program to fail fatally,
421  * use gst_init() instead.
422  *
423  * This function should be called before calling any other GLib functions. If
424  * this is not an option, your program must initialise the GLib thread system
425  * using g_thread_init() before any other GLib functions are called.
426  *
427  * Returns: %TRUE if GStreamer could be initialized.
428  */
429 gboolean
430 gst_init_check (int *argc, char **argv[], GError ** err)
431 {
432 #ifndef GST_DISABLE_OPTION_PARSING
433   GOptionGroup *group;
434   GOptionContext *ctx;
435 #endif
436   gboolean res;
437
438   if (!g_thread_supported ())
439     g_thread_init (NULL);
440
441   if (gst_initialized) {
442     GST_DEBUG ("already initialized gst");
443     return TRUE;
444   }
445 #ifndef GST_DISABLE_OPTION_PARSING
446   ctx = g_option_context_new ("- GStreamer initialization");
447   g_option_context_set_ignore_unknown_options (ctx, TRUE);
448   group = gst_init_get_option_group ();
449   g_option_context_add_group (ctx, group);
450   res = g_option_context_parse (ctx, argc, argv, err);
451   g_option_context_free (ctx);
452 #else
453   init_pre (NULL, NULL, NULL, NULL);
454   init_post (NULL, NULL, NULL, NULL);
455   res = TRUE;
456 #endif
457
458   gst_initialized = res;
459
460   if (res) {
461     GST_INFO ("initialized GStreamer successfully");
462   } else {
463     GST_INFO ("failed to initialize GStreamer");
464   }
465
466   return res;
467 }
468
469 /**
470  * gst_init:
471  * @argc: (inout): pointer to application's argc
472  * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv
473  *
474  * Initializes the GStreamer library, setting up internal path lists,
475  * registering built-in elements, and loading standard plugins.
476  *
477  * This function should be called before calling any other GLib functions. If
478  * this is not an option, your program must initialise the GLib thread system
479  * using g_thread_init() before any other GLib functions are called.
480  *
481  * <note><para>
482  * This function will terminate your program if it was unable to initialize
483  * GStreamer for some reason.  If you want your program to fall back,
484  * use gst_init_check() instead.
485  * </para></note>
486  *
487  * WARNING: This function does not work in the same way as corresponding
488  * functions in other glib-style libraries, such as gtk_init().  In
489  * particular, unknown command line options cause this function to
490  * abort program execution.
491  */
492 void
493 gst_init (int *argc, char **argv[])
494 {
495   GError *err = NULL;
496
497   if (!gst_init_check (argc, argv, &err)) {
498     g_print ("Could not initialize GStreamer: %s\n",
499         err ? err->message : "unknown error occurred");
500     if (err) {
501       g_error_free (err);
502     }
503     exit (1);
504   }
505 }
506
507 #ifndef GST_DISABLE_REGISTRY
508 static void
509 add_path_func (gpointer data, gpointer user_data)
510 {
511   GST_INFO ("Adding plugin path: \"%s\", will scan later", (gchar *) data);
512   plugin_paths = g_list_append (plugin_paths, g_strdup (data));
513 }
514 #endif
515
516 #ifndef GST_DISABLE_OPTION_PARSING
517 static void
518 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
519 {
520   preload_plugins = g_slist_prepend (preload_plugins, g_strdup (data));
521 }
522 #endif
523
524 static void
525 load_plugin_func (gpointer data, gpointer user_data)
526 {
527   GstPlugin *plugin;
528   const gchar *filename;
529   GError *err = NULL;
530
531   filename = (const gchar *) data;
532
533   plugin = gst_plugin_load_file (filename, &err);
534
535   if (plugin) {
536     GST_INFO ("Loaded plugin: \"%s\"", filename);
537
538     gst_default_registry_add_plugin (plugin);
539   } else {
540     if (err) {
541       /* Report error to user, and free error */
542       GST_ERROR ("Failed to load plugin: %s", err->message);
543       g_error_free (err);
544     } else {
545       GST_WARNING ("Failed to load plugin: \"%s\"", filename);
546     }
547   }
548 }
549
550 #ifndef GST_DISABLE_OPTION_PARSING
551 static void
552 split_and_iterate (const gchar * stringlist, gchar * separator, GFunc iterator,
553     gpointer user_data)
554 {
555   gchar **strings;
556   gint j = 0;
557   gchar *lastlist = g_strdup (stringlist);
558
559   while (lastlist) {
560     strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
561     g_free (lastlist);
562     lastlist = NULL;
563
564     while (strings[j]) {
565       iterator (strings[j], user_data);
566       if (++j == MAX_PATH_SPLIT) {
567         lastlist = g_strdup (strings[j]);
568         j = 0;
569         break;
570       }
571     }
572     g_strfreev (strings);
573   }
574 }
575 #endif
576
577 /* we have no fail cases yet, but maybe in the future */
578 static gboolean
579 init_pre (GOptionContext * context, GOptionGroup * group, gpointer data,
580     GError ** error)
581 {
582   if (gst_initialized) {
583     GST_DEBUG ("already initialized");
584     return TRUE;
585   }
586
587   /* GStreamer was built against a GLib >= 2.8 and is therefore not doing
588    * the refcount hack. Check that it isn't being run against an older GLib */
589   if (glib_major_version < 2 ||
590       (glib_major_version == 2 && glib_minor_version < 8)) {
591     g_warning ("GStreamer was compiled against GLib %d.%d.%d but is running"
592         " against %d.%d.%d. This will cause reference counting issues",
593         GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
594         glib_major_version, glib_minor_version, glib_micro_version);
595   }
596
597   g_type_init ();
598
599   /* we need threading to be enabled right here */
600   g_assert (g_thread_supported ());
601   _gst_debug_init ();
602
603 #ifdef ENABLE_NLS
604   setlocale (LC_ALL, "");
605   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
606   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
607 #endif /* ENABLE_NLS */
608
609 #ifndef GST_DISABLE_GST_DEBUG
610   {
611     const gchar *debug_list;
612
613     if (g_getenv ("GST_DEBUG_NO_COLOR") != NULL)
614       gst_debug_set_colored (FALSE);
615
616     debug_list = g_getenv ("GST_DEBUG");
617     if (debug_list) {
618       parse_debug_list (debug_list);
619     }
620   }
621
622   priv_gst_dump_dot_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR");
623 #endif
624   /* This is the earliest we can make stuff show up in the logs.
625    * So give some useful info about GStreamer here */
626   GST_INFO ("Initializing GStreamer Core Library version %s", VERSION);
627   GST_INFO ("Using library installed in %s", LIBDIR);
628
629   /* Print some basic system details if possible (OS/architecture) */
630 #ifdef HAVE_SYS_UTSNAME_H
631   {
632     struct utsname sys_details;
633
634     if (uname (&sys_details) == 0) {
635       GST_INFO ("%s %s %s %s %s", sys_details.sysname,
636           sys_details.nodename, sys_details.release, sys_details.version,
637           sys_details.machine);
638     }
639   }
640 #endif
641
642   return TRUE;
643 }
644
645 static gboolean
646 gst_register_core_elements (GstPlugin * plugin)
647 {
648   /* register some standard builtin types */
649   if (!gst_element_register (plugin, "bin", GST_RANK_PRIMARY,
650           GST_TYPE_BIN) ||
651       !gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY,
652           GST_TYPE_PIPELINE)
653       )
654     g_assert_not_reached ();
655
656   return TRUE;
657 }
658
659 #ifndef GST_DISABLE_REGISTRY
660
661 typedef enum
662 {
663   REGISTRY_SCAN_AND_UPDATE_FAILURE = 0,
664   REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED,
665   REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED
666 } GstRegistryScanAndUpdateResult;
667
668 /*
669  * scan_and_update_registry:
670  * @default_registry: the #GstRegistry
671  * @registry_file: registry filename
672  * @write_changes: write registry if it has changed?
673  *
674  * Scans for registry changes and eventually updates the registry cache. 
675  *
676  * Return: %REGISTRY_SCAN_AND_UPDATE_FAILURE if the registry could not scanned
677  *         or updated, %REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED if the
678  *         registry is clean and %REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED if
679  *         it has been updated and the cache needs to be re-read.
680  */
681 static GstRegistryScanAndUpdateResult
682 scan_and_update_registry (GstRegistry * default_registry,
683     const gchar * registry_file, gboolean write_changes, GError ** error)
684 {
685   const gchar *plugin_path;
686   gboolean changed = FALSE;
687   GList *l;
688
689   GST_INFO ("Validating registry cache: %s", registry_file);
690   /* It sounds tempting to just compare the mtime of directories with the mtime
691    * of the registry cache, but it does not work. It would not catch updated
692    * plugins, which might bring more or less features.
693    */
694
695   /* scan paths specified via --gst-plugin-path */
696   GST_DEBUG ("scanning paths added via --gst-plugin-path");
697   for (l = plugin_paths; l != NULL; l = l->next) {
698     GST_INFO ("Scanning plugin path: \"%s\"", (gchar *) l->data);
699     changed |= gst_registry_scan_path (default_registry, (gchar *) l->data);
700   }
701   /* keep plugin_paths around in case a re-scan is forced later on */
702
703   /* GST_PLUGIN_PATH specifies a list of directories to scan for
704    * additional plugins.  These take precedence over the system plugins */
705   plugin_path = g_getenv ("GST_PLUGIN_PATH");
706   if (plugin_path) {
707     char **list;
708     int i;
709
710     GST_DEBUG ("GST_PLUGIN_PATH set to %s", plugin_path);
711     list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
712     for (i = 0; list[i]; i++) {
713       changed |= gst_registry_scan_path (default_registry, list[i]);
714     }
715     g_strfreev (list);
716   } else {
717     GST_DEBUG ("GST_PLUGIN_PATH not set");
718   }
719
720   /* GST_PLUGIN_SYSTEM_PATH specifies a list of plugins that are always
721    * loaded by default.  If not set, this defaults to the system-installed
722    * path, and the plugins installed in the user's home directory */
723   plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH");
724   if (plugin_path == NULL) {
725     char *home_plugins;
726
727     GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set");
728
729     /* plugins in the user's home directory take precedence over
730      * system-installed ones */
731     home_plugins = g_build_filename (g_get_home_dir (),
732         ".gstreamer-" GST_MAJORMINOR, "plugins", NULL);
733     GST_DEBUG ("scanning home plugins %s", home_plugins);
734     changed |= gst_registry_scan_path (default_registry, home_plugins);
735     g_free (home_plugins);
736
737     /* add the main (installed) library path */
738     GST_DEBUG ("scanning main plugins %s", PLUGINDIR);
739     changed |= gst_registry_scan_path (default_registry, PLUGINDIR);
740
741 #ifdef G_OS_WIN32
742     {
743       char *base_dir;
744       char *dir;
745
746       base_dir =
747           g_win32_get_package_installation_directory_of_module (gst_dll_handle);
748
749       dir = g_build_filename (base_dir, "lib", "gstreamer-0.10", NULL);
750       GST_DEBUG ("scanning DLL dir %s", dir);
751
752       changed |= gst_registry_scan_path (default_registry, dir);
753
754       g_free (dir);
755       g_free (base_dir);
756     }
757 #endif
758   } else {
759     gchar **list;
760     gint i;
761
762     GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH set to %s", plugin_path);
763     list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
764     for (i = 0; list[i]; i++) {
765       changed |= gst_registry_scan_path (default_registry, list[i]);
766     }
767     g_strfreev (list);
768   }
769
770   /* Remove cached plugins so stale info is cleared. */
771   changed |= _priv_gst_registry_remove_cache_plugins (default_registry);
772
773   if (!changed) {
774     GST_INFO ("Registry cache has not changed");
775     return REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED;
776   }
777
778   if (!write_changes) {
779     GST_INFO ("Registry cache changed, but writing is disabled. Not writing.");
780     return REGISTRY_SCAN_AND_UPDATE_FAILURE;
781   }
782
783   GST_INFO ("Registry cache changed. Writing new registry cache");
784   if (!gst_registry_binary_write_cache (default_registry, registry_file)) {
785     g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
786         _("Error writing registry cache to %s: %s"),
787         registry_file, g_strerror (errno));
788     return REGISTRY_SCAN_AND_UPDATE_FAILURE;
789   }
790
791   GST_INFO ("Registry cache written successfully");
792   return REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED;
793 }
794
795 static gboolean
796 ensure_current_registry_nonforking (GstRegistry * default_registry,
797     const gchar * registry_file, GError ** error)
798 {
799   /* fork() not available */
800   GST_DEBUG ("Updating registry cache in-process");
801   scan_and_update_registry (default_registry, registry_file, TRUE, error);
802   return TRUE;
803 }
804
805 /* when forking is not available this function always does nothing but return
806  * TRUE immediatly */
807 static gboolean
808 ensure_current_registry_forking (GstRegistry * default_registry,
809     const gchar * registry_file, GError ** error)
810 {
811 #ifdef HAVE_FORK
812   pid_t pid;
813   int pfd[2];
814   int ret;
815
816   /* We fork here, and let the child read and possibly rebuild the registry.
817    * After that, the parent will re-read the freshly generated registry. */
818   GST_DEBUG ("forking to update registry");
819
820   if (pipe (pfd) == -1) {
821     g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
822         _("Error re-scanning registry %s: %s"),
823         ", could not create pipes. Error", g_strerror (errno));
824     return FALSE;
825   }
826
827   pid = fork ();
828   if (pid == -1) {
829     GST_ERROR ("Failed to fork()");
830     g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
831         _("Error re-scanning registry %s: %s"),
832         ", failed to fork. Error", g_strerror (errno));
833     return FALSE;
834   }
835
836   if (pid == 0) {
837     gint result_code;
838
839     /* this is the child. Close the read pipe */
840     (void) close (pfd[0]);
841
842     GST_DEBUG ("child reading registry cache");
843     result_code =
844         scan_and_update_registry (default_registry, registry_file, TRUE, NULL);
845
846     /* need to use _exit, so that any exit handlers registered don't
847      * bring down the main program */
848     GST_DEBUG ("child exiting: %d", result_code);
849
850     /* make valgrind happy (yes, you can call it insane) */
851     g_free ((char *) registry_file);
852
853     /* write a result byte to the pipe */
854     do {
855       ret = write (pfd[1], &result_code, sizeof (result_code));
856     } while (ret == -1 && errno == EINTR);
857     /* if ret == -1 now, we could not write to pipe, probably 
858      * means parent has exited before us */
859     (void) close (pfd[1]);
860
861     _exit (0);
862   } else {
863     gint result_code;
864
865     /* parent. Close write pipe */
866     (void) close (pfd[1]);
867
868     /* Wait for result from the pipe */
869     GST_DEBUG ("Waiting for data from child");
870     do {
871       ret = read (pfd[0], &result_code, sizeof (result_code));
872     } while (ret == -1 && errno == EINTR);
873
874     if (ret == -1) {
875       g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
876           _("Error re-scanning registry %s: %s"),
877           ", read returned error", g_strerror (errno));
878       close (pfd[0]);
879       return FALSE;
880     }
881     (void) close (pfd[0]);
882
883     /* Wait to ensure the child is reaped, but ignore the result */
884     GST_DEBUG ("parent waiting on child");
885     waitpid (pid, NULL, 0);
886     GST_DEBUG ("parent done waiting on child");
887
888     if (ret == 0) {
889       GST_ERROR ("child did not exit normally, terminated by signal");
890       g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
891           _("Error re-scanning registry %s"), ", child terminated by signal");
892       return FALSE;
893     }
894
895     if (result_code == REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED) {
896       GST_DEBUG ("Child succeeded. Parent reading registry cache");
897       _priv_gst_registry_remove_cache_plugins (default_registry);
898       gst_registry_binary_read_cache (default_registry, registry_file);
899     } else if (result_code == REGISTRY_SCAN_AND_UPDATE_FAILURE) {
900       GST_DEBUG ("Child failed. Parent re-scanning registry, ignoring errors.");
901       scan_and_update_registry (default_registry, registry_file, FALSE, NULL);
902     }
903   }
904 #endif /* HAVE_FORK */
905   return TRUE;
906 }
907
908 static gboolean
909 ensure_current_registry (GError ** error)
910 {
911   gchar *registry_file;
912   GstRegistry *default_registry;
913   gboolean ret = TRUE;
914   gboolean do_fork;
915   gboolean do_update;
916   gboolean have_cache;
917
918   default_registry = gst_registry_get_default ();
919   registry_file = g_strdup (g_getenv ("GST_REGISTRY"));
920   if (registry_file == NULL) {
921     registry_file = g_build_filename (g_get_home_dir (),
922         ".gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".bin", NULL);
923   }
924
925   GST_INFO ("reading registry cache: %s", registry_file);
926   have_cache = gst_registry_binary_read_cache (default_registry, registry_file);
927
928   if (have_cache) {
929     do_update = !_gst_disable_registry_update;
930     if (do_update) {
931       const gchar *update_env;
932
933       if ((update_env = g_getenv ("GST_REGISTRY_UPDATE"))) {
934         /* do update for any value different from "no" */
935         do_update = (strcmp (update_env, "no") != 0);
936       }
937     }
938   } else {
939     do_update = TRUE;
940   }
941
942   if (do_update) {
943     /* first see if forking is enabled */
944     do_fork = _gst_enable_registry_fork;
945     if (do_fork) {
946       const gchar *fork_env;
947
948       /* forking enabled, see if it is disabled with an env var */
949       if ((fork_env = g_getenv ("GST_REGISTRY_FORK"))) {
950         /* fork enabled for any value different from "no" */
951         do_fork = strcmp (fork_env, "no") != 0;
952       }
953     }
954
955     /* now check registry with or without forking */
956     if (do_fork) {
957       GST_DEBUG ("forking for registry rebuild");
958       ret = ensure_current_registry_forking (default_registry, registry_file,
959           error);
960     } else {
961       GST_DEBUG ("requested not to fork for registry rebuild");
962       ret = ensure_current_registry_nonforking (default_registry, registry_file,
963           error);
964     }
965   }
966
967   g_free (registry_file);
968   GST_INFO ("registry reading and updating done, result = %d", ret);
969
970   return ret;
971 }
972 #endif /* GST_DISABLE_REGISTRY */
973
974 /*
975  * this bit handles:
976  * - initalization of threads if we use them
977  * - log handler
978  * - initial output
979  * - initializes gst_format
980  * - registers a bunch of types for gst_objects
981  *
982  * - we don't have cases yet where this fails, but in the future
983  *   we might and then it's nice to be able to return that
984  */
985 static gboolean
986 init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
987     GError ** error)
988 {
989   GLogLevelFlags llf;
990
991 #ifndef GST_DISABLE_TRACE
992   GstTrace *gst_trace;
993 #endif /* GST_DISABLE_TRACE */
994
995   if (gst_initialized) {
996     GST_DEBUG ("already initialized");
997     return TRUE;
998   }
999
1000   llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
1001   g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
1002
1003   _priv_gst_quarks_initialize ();
1004   _gst_format_initialize ();
1005   _gst_query_initialize ();
1006   g_type_class_ref (gst_object_get_type ());
1007   g_type_class_ref (gst_pad_get_type ());
1008   g_type_class_ref (gst_element_factory_get_type ());
1009   g_type_class_ref (gst_element_get_type ());
1010   g_type_class_ref (gst_type_find_factory_get_type ());
1011   g_type_class_ref (gst_bin_get_type ());
1012   g_type_class_ref (gst_bus_get_type ());
1013   g_type_class_ref (gst_task_get_type ());
1014   g_type_class_ref (gst_clock_get_type ());
1015
1016   g_type_class_ref (gst_index_factory_get_type ());
1017   gst_uri_handler_get_type ();
1018
1019   g_type_class_ref (gst_object_flags_get_type ());
1020   g_type_class_ref (gst_bin_flags_get_type ());
1021   g_type_class_ref (gst_buffer_flag_get_type ());
1022   g_type_class_ref (gst_buffer_copy_flags_get_type ());
1023   g_type_class_ref (gst_buffer_list_item_get_type ());
1024   g_type_class_ref (gst_bus_flags_get_type ());
1025   g_type_class_ref (gst_bus_sync_reply_get_type ());
1026   g_type_class_ref (gst_caps_flags_get_type ());
1027   g_type_class_ref (gst_clock_return_get_type ());
1028   g_type_class_ref (gst_clock_entry_type_get_type ());
1029   g_type_class_ref (gst_clock_flags_get_type ());
1030   g_type_class_ref (gst_clock_type_get_type ());
1031   g_type_class_ref (gst_debug_graph_details_get_type ());
1032   g_type_class_ref (gst_state_get_type ());
1033   g_type_class_ref (gst_state_change_return_get_type ());
1034   g_type_class_ref (gst_state_change_get_type ());
1035   g_type_class_ref (gst_element_flags_get_type ());
1036   g_type_class_ref (gst_core_error_get_type ());
1037   g_type_class_ref (gst_library_error_get_type ());
1038   g_type_class_ref (gst_resource_error_get_type ());
1039   g_type_class_ref (gst_stream_error_get_type ());
1040   g_type_class_ref (gst_event_type_flags_get_type ());
1041   g_type_class_ref (gst_event_type_get_type ());
1042   g_type_class_ref (gst_seek_type_get_type ());
1043   g_type_class_ref (gst_seek_flags_get_type ());
1044   g_type_class_ref (gst_format_get_type ());
1045   g_type_class_ref (gst_index_certainty_get_type ());
1046   g_type_class_ref (gst_index_entry_type_get_type ());
1047   g_type_class_ref (gst_index_lookup_method_get_type ());
1048   g_type_class_ref (gst_assoc_flags_get_type ());
1049   g_type_class_ref (gst_index_resolver_method_get_type ());
1050   g_type_class_ref (gst_index_flags_get_type ());
1051   g_type_class_ref (gst_debug_level_get_type ());
1052   g_type_class_ref (gst_debug_color_flags_get_type ());
1053   g_type_class_ref (gst_iterator_result_get_type ());
1054   g_type_class_ref (gst_iterator_item_get_type ());
1055   g_type_class_ref (gst_message_type_get_type ());
1056   g_type_class_ref (gst_mini_object_flags_get_type ());
1057   g_type_class_ref (gst_pad_link_return_get_type ());
1058   g_type_class_ref (gst_flow_return_get_type ());
1059   g_type_class_ref (gst_activate_mode_get_type ());
1060   g_type_class_ref (gst_pad_direction_get_type ());
1061   g_type_class_ref (gst_pad_flags_get_type ());
1062   g_type_class_ref (gst_pad_presence_get_type ());
1063   g_type_class_ref (gst_pad_template_flags_get_type ());
1064   g_type_class_ref (gst_pipeline_flags_get_type ());
1065   g_type_class_ref (gst_plugin_error_get_type ());
1066   g_type_class_ref (gst_plugin_flags_get_type ());
1067   g_type_class_ref (gst_plugin_dependency_flags_get_type ());
1068   g_type_class_ref (gst_rank_get_type ());
1069   g_type_class_ref (gst_query_type_get_type ());
1070   g_type_class_ref (gst_buffering_mode_get_type ());
1071   g_type_class_ref (gst_stream_status_type_get_type ());
1072   g_type_class_ref (gst_structure_change_type_get_type ());
1073   g_type_class_ref (gst_tag_merge_mode_get_type ());
1074   g_type_class_ref (gst_tag_flag_get_type ());
1075   g_type_class_ref (gst_task_pool_get_type ());
1076   g_type_class_ref (gst_task_state_get_type ());
1077   g_type_class_ref (gst_alloc_trace_flags_get_type ());
1078   g_type_class_ref (gst_type_find_probability_get_type ());
1079   g_type_class_ref (gst_uri_type_get_type ());
1080   g_type_class_ref (gst_parse_error_get_type ());
1081   g_type_class_ref (gst_parse_flags_get_type ());
1082   g_type_class_ref (gst_search_mode_get_type ());
1083
1084   gst_structure_get_type ();
1085   _gst_value_initialize ();
1086   g_type_class_ref (gst_param_spec_fraction_get_type ());
1087   gst_caps_get_type ();
1088   _gst_event_initialize ();
1089   _gst_buffer_initialize ();
1090   _gst_buffer_list_initialize ();
1091   _gst_message_initialize ();
1092   _gst_tag_initialize ();
1093
1094   _gst_plugin_initialize ();
1095
1096   gst_g_error_get_type ();
1097
1098   /* register core plugins */
1099   gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR,
1100       "staticelements", "core elements linked into the GStreamer library",
1101       gst_register_core_elements, VERSION, GST_LICENSE, PACKAGE,
1102       GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
1103
1104   /*
1105    * Any errors happening below this point are non-fatal, we therefore mark
1106    * gstreamer as being initialized, since it is the case from a plugin point of
1107    * view.
1108    *
1109    * If anything fails, it will be put back to FALSE in gst_init_check().
1110    * This allows some special plugins that would call gst_init() to not cause a
1111    * looping effect (i.e. initializing GStreamer twice).
1112    */
1113   gst_initialized = TRUE;
1114
1115 #ifndef GST_DISABLE_REGISTRY
1116   if (!ensure_current_registry (error))
1117     return FALSE;
1118 #endif /* GST_DISABLE_REGISTRY */
1119
1120   /* if we need to preload plugins, do so now */
1121   g_slist_foreach (preload_plugins, load_plugin_func, NULL);
1122   /* keep preload_plugins around in case a re-scan is forced later on */
1123
1124 #ifndef GST_DISABLE_TRACE
1125   _gst_trace_on = 0;
1126   if (_gst_trace_on) {
1127     gst_trace = gst_trace_new ("gst.trace", 1024);
1128     gst_trace_set_default (gst_trace);
1129   }
1130 #endif /* GST_DISABLE_TRACE */
1131
1132   return TRUE;
1133 }
1134
1135 #ifndef GST_DISABLE_GST_DEBUG
1136 static gboolean
1137 select_all (GstPlugin * plugin, gpointer user_data)
1138 {
1139   return TRUE;
1140 }
1141
1142 static gint
1143 sort_by_category_name (gconstpointer a, gconstpointer b)
1144 {
1145   return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
1146       gst_debug_category_get_name ((GstDebugCategory *) b));
1147 }
1148
1149 static void
1150 gst_debug_help (void)
1151 {
1152   GSList *list, *walk;
1153   GList *list2, *g;
1154
1155   /* Need to ensure the registry is loaded to get debug categories */
1156   if (!init_post (NULL, NULL, NULL, NULL))
1157     exit (1);
1158
1159   list2 = gst_registry_plugin_filter (gst_registry_get_default (),
1160       select_all, FALSE, NULL);
1161
1162   /* FIXME this is gross.  why don't debug have categories PluginFeatures? */
1163   for (g = list2; g; g = g_list_next (g)) {
1164     GstPlugin *plugin = GST_PLUGIN_CAST (g->data);
1165
1166     gst_plugin_load (plugin);
1167   }
1168   g_list_free (list2);
1169
1170   list = gst_debug_get_all_categories ();
1171   walk = list = g_slist_sort (list, sort_by_category_name);
1172
1173   g_print ("\n");
1174   g_print ("name                  level    description\n");
1175   g_print ("---------------------+--------+--------------------------------\n");
1176
1177   while (walk) {
1178     GstDebugCategory *cat = (GstDebugCategory *) walk->data;
1179
1180     if (gst_debug_is_colored ()) {
1181 #ifdef G_OS_WIN32
1182       gint color = gst_debug_construct_win_color (cat->color);
1183       const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
1184
1185       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
1186       g_print ("%-20s", gst_debug_category_get_name (cat));
1187       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
1188       g_print (" %1d %s ", gst_debug_category_get_threshold (cat),
1189           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)));
1190       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
1191       g_print ("%s", gst_debug_category_get_description (cat));
1192       SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
1193       g_print ("\n");
1194 #else /* G_OS_WIN32 */
1195       gchar *color = gst_debug_construct_term_color (cat->color);
1196
1197       g_print ("%s%-20s\033[00m  %1d %s  %s%s\033[00m\n",
1198           color,
1199           gst_debug_category_get_name (cat),
1200           gst_debug_category_get_threshold (cat),
1201           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
1202           color, gst_debug_category_get_description (cat));
1203       g_free (color);
1204 #endif /* G_OS_WIN32 */
1205     } else {
1206       g_print ("%-20s  %1d %s  %s\n", gst_debug_category_get_name (cat),
1207           gst_debug_category_get_threshold (cat),
1208           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
1209           gst_debug_category_get_description (cat));
1210     }
1211     walk = g_slist_next (walk);
1212   }
1213   g_slist_free (list);
1214   g_print ("\n");
1215 }
1216 #endif
1217
1218 #ifndef GST_DISABLE_OPTION_PARSING
1219 static gboolean
1220 parse_one_option (gint opt, const gchar * arg, GError ** err)
1221 {
1222   switch (opt) {
1223     case ARG_VERSION:
1224       g_print ("GStreamer Core Library version %s\n", PACKAGE_VERSION);
1225       exit (0);
1226     case ARG_FATAL_WARNINGS:{
1227       GLogLevelFlags fatal_mask;
1228
1229       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
1230       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
1231       g_log_set_always_fatal (fatal_mask);
1232       break;
1233     }
1234 #ifndef GST_DISABLE_GST_DEBUG
1235     case ARG_DEBUG_LEVEL:{
1236       gint tmp = 0;
1237
1238       tmp = strtol (arg, NULL, 0);
1239       if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
1240         gst_debug_set_default_threshold (tmp);
1241       }
1242       break;
1243     }
1244     case ARG_DEBUG:
1245       parse_debug_list (arg);
1246       break;
1247     case ARG_DEBUG_NO_COLOR:
1248       gst_debug_set_colored (FALSE);
1249       break;
1250     case ARG_DEBUG_DISABLE:
1251       gst_debug_set_active (FALSE);
1252       break;
1253     case ARG_DEBUG_HELP:
1254       gst_debug_help ();
1255       exit (0);
1256 #endif
1257     case ARG_PLUGIN_SPEW:
1258       break;
1259     case ARG_PLUGIN_PATH:
1260 #ifndef GST_DISABLE_REGISTRY
1261       split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, NULL);
1262 #endif /* GST_DISABLE_REGISTRY */
1263       break;
1264     case ARG_PLUGIN_LOAD:
1265       split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
1266       break;
1267     case ARG_SEGTRAP_DISABLE:
1268       _gst_disable_segtrap = TRUE;
1269       break;
1270     case ARG_REGISTRY_UPDATE_DISABLE:
1271       _gst_disable_registry_update = TRUE;
1272       break;
1273     case ARG_REGISTRY_FORK_DISABLE:
1274       _gst_enable_registry_fork = FALSE;
1275       break;
1276     default:
1277       g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
1278           _("Unknown option"));
1279       return FALSE;
1280   }
1281
1282   return TRUE;
1283 }
1284
1285 static gboolean
1286 parse_goption_arg (const gchar * opt,
1287     const gchar * arg, gpointer data, GError ** err)
1288 {
1289   static const struct
1290   {
1291     gchar *opt;
1292     int val;
1293   } options[] = {
1294     {
1295     "--gst-version", ARG_VERSION}, {
1296     "--gst-fatal-warnings", ARG_FATAL_WARNINGS},
1297 #ifndef GST_DISABLE_GST_DEBUG
1298     {
1299     "--gst-debug-level", ARG_DEBUG_LEVEL}, {
1300     "--gst-debug", ARG_DEBUG}, {
1301     "--gst-debug-disable", ARG_DEBUG_DISABLE}, {
1302     "--gst-debug-no-color", ARG_DEBUG_NO_COLOR}, {
1303     "--gst-debug-help", ARG_DEBUG_HELP},
1304 #endif
1305     {
1306     "--gst-plugin-spew", ARG_PLUGIN_SPEW}, {
1307     "--gst-plugin-path", ARG_PLUGIN_PATH}, {
1308     "--gst-plugin-load", ARG_PLUGIN_LOAD}, {
1309     "--gst-disable-segtrap", ARG_SEGTRAP_DISABLE}, {
1310     "--gst-disable-registry-update", ARG_REGISTRY_UPDATE_DISABLE}, {
1311     "--gst-disable-registry-fork", ARG_REGISTRY_FORK_DISABLE}, {
1312     NULL}
1313   };
1314   gint val = 0, n;
1315
1316   for (n = 0; options[n].opt; n++) {
1317     if (!strcmp (opt, options[n].opt)) {
1318       val = options[n].val;
1319       break;
1320     }
1321   }
1322
1323   return parse_one_option (val, arg, err);
1324 }
1325 #endif
1326
1327 extern GstRegistry *_gst_registry_default;
1328
1329 /**
1330  * gst_deinit:
1331  *
1332  * Clean up any resources created by GStreamer in gst_init().
1333  *
1334  * It is normally not needed to call this function in a normal application
1335  * as the resources will automatically be freed when the program terminates.
1336  * This function is therefore mostly used by testsuites and other memory
1337  * profiling tools.
1338  *
1339  * After this call GStreamer (including this method) should not be used anymore. 
1340  */
1341 void
1342 gst_deinit (void)
1343 {
1344   GstClock *clock;
1345
1346   GST_INFO ("deinitializing GStreamer");
1347
1348   if (gst_deinitialized) {
1349     GST_DEBUG ("already deinitialized");
1350     return;
1351   }
1352
1353   g_slist_foreach (preload_plugins, (GFunc) g_free, NULL);
1354   g_slist_free (preload_plugins);
1355   preload_plugins = NULL;
1356
1357 #ifndef GST_DISABLE_REGISTRY
1358   g_list_foreach (plugin_paths, (GFunc) g_free, NULL);
1359   g_list_free (plugin_paths);
1360   plugin_paths = NULL;
1361 #endif
1362
1363   clock = gst_system_clock_obtain ();
1364   gst_object_unref (clock);
1365   gst_object_unref (clock);
1366
1367   _priv_gst_registry_cleanup ();
1368
1369   g_type_class_unref (g_type_class_peek (gst_object_get_type ()));
1370   g_type_class_unref (g_type_class_peek (gst_pad_get_type ()));
1371   g_type_class_unref (g_type_class_peek (gst_element_factory_get_type ()));
1372   g_type_class_unref (g_type_class_peek (gst_element_get_type ()));
1373   g_type_class_unref (g_type_class_peek (gst_type_find_factory_get_type ()));
1374   g_type_class_unref (g_type_class_peek (gst_bin_get_type ()));
1375   g_type_class_unref (g_type_class_peek (gst_bus_get_type ()));
1376   g_type_class_unref (g_type_class_peek (gst_task_get_type ()));
1377   g_type_class_unref (g_type_class_peek (gst_index_factory_get_type ()));
1378   g_type_class_unref (g_type_class_peek (gst_object_flags_get_type ()));
1379   g_type_class_unref (g_type_class_peek (gst_bin_flags_get_type ()));
1380   g_type_class_unref (g_type_class_peek (gst_buffer_flag_get_type ()));
1381   g_type_class_unref (g_type_class_peek (gst_buffer_copy_flags_get_type ()));
1382   g_type_class_unref (g_type_class_peek (gst_buffer_list_item_get_type ()));
1383   g_type_class_unref (g_type_class_peek (gst_bus_flags_get_type ()));
1384   g_type_class_unref (g_type_class_peek (gst_bus_sync_reply_get_type ()));
1385   g_type_class_unref (g_type_class_peek (gst_caps_flags_get_type ()));
1386   g_type_class_unref (g_type_class_peek (gst_clock_type_get_type ()));
1387   g_type_class_unref (g_type_class_peek (gst_clock_return_get_type ()));
1388   g_type_class_unref (g_type_class_peek (gst_clock_entry_type_get_type ()));
1389   g_type_class_unref (g_type_class_peek (gst_clock_flags_get_type ()));
1390   g_type_class_unref (g_type_class_peek (gst_debug_graph_details_get_type ()));
1391   g_type_class_unref (g_type_class_peek (gst_state_get_type ()));
1392   g_type_class_unref (g_type_class_peek (gst_state_change_return_get_type ()));
1393   g_type_class_unref (g_type_class_peek (gst_state_change_get_type ()));
1394   g_type_class_unref (g_type_class_peek (gst_element_flags_get_type ()));
1395   g_type_class_unref (g_type_class_peek (gst_core_error_get_type ()));
1396   g_type_class_unref (g_type_class_peek (gst_library_error_get_type ()));
1397   g_type_class_unref (g_type_class_peek (gst_plugin_dependency_flags_get_type
1398           ()));
1399   g_type_class_unref (g_type_class_peek (gst_parse_flags_get_type ()));
1400   g_type_class_unref (g_type_class_peek (gst_resource_error_get_type ()));
1401   g_type_class_unref (g_type_class_peek (gst_search_mode_get_type ()));
1402   g_type_class_unref (g_type_class_peek (gst_stream_error_get_type ()));
1403   g_type_class_unref (g_type_class_peek (gst_stream_status_type_get_type ()));
1404   g_type_class_unref (g_type_class_peek (gst_structure_change_type_get_type
1405           ()));
1406   g_type_class_unref (g_type_class_peek (gst_event_type_flags_get_type ()));
1407   g_type_class_unref (g_type_class_peek (gst_event_type_get_type ()));
1408   g_type_class_unref (g_type_class_peek (gst_seek_type_get_type ()));
1409   g_type_class_unref (g_type_class_peek (gst_seek_flags_get_type ()));
1410   g_type_class_unref (g_type_class_peek (gst_format_get_type ()));
1411   g_type_class_unref (g_type_class_peek (gst_index_certainty_get_type ()));
1412   g_type_class_unref (g_type_class_peek (gst_index_entry_type_get_type ()));
1413   g_type_class_unref (g_type_class_peek (gst_index_lookup_method_get_type ()));
1414   g_type_class_unref (g_type_class_peek (gst_assoc_flags_get_type ()));
1415   g_type_class_unref (g_type_class_peek (gst_index_resolver_method_get_type
1416           ()));
1417   g_type_class_unref (g_type_class_peek (gst_index_flags_get_type ()));
1418   g_type_class_unref (g_type_class_peek (gst_debug_level_get_type ()));
1419   g_type_class_unref (g_type_class_peek (gst_debug_color_flags_get_type ()));
1420   g_type_class_unref (g_type_class_peek (gst_iterator_result_get_type ()));
1421   g_type_class_unref (g_type_class_peek (gst_iterator_item_get_type ()));
1422   g_type_class_unref (g_type_class_peek (gst_message_type_get_type ()));
1423   g_type_class_unref (g_type_class_peek (gst_mini_object_flags_get_type ()));
1424   g_type_class_unref (g_type_class_peek (gst_pad_link_return_get_type ()));
1425   g_type_class_unref (g_type_class_peek (gst_flow_return_get_type ()));
1426   g_type_class_unref (g_type_class_peek (gst_activate_mode_get_type ()));
1427   g_type_class_unref (g_type_class_peek (gst_pad_direction_get_type ()));
1428   g_type_class_unref (g_type_class_peek (gst_pad_flags_get_type ()));
1429   g_type_class_unref (g_type_class_peek (gst_pad_presence_get_type ()));
1430   g_type_class_unref (g_type_class_peek (gst_pad_template_flags_get_type ()));
1431   g_type_class_unref (g_type_class_peek (gst_pipeline_flags_get_type ()));
1432   g_type_class_unref (g_type_class_peek (gst_plugin_error_get_type ()));
1433   g_type_class_unref (g_type_class_peek (gst_plugin_flags_get_type ()));
1434   g_type_class_unref (g_type_class_peek (gst_rank_get_type ()));
1435   g_type_class_unref (g_type_class_peek (gst_query_type_get_type ()));
1436   g_type_class_unref (g_type_class_peek (gst_buffering_mode_get_type ()));
1437   g_type_class_unref (g_type_class_peek (gst_tag_merge_mode_get_type ()));
1438   g_type_class_unref (g_type_class_peek (gst_tag_flag_get_type ()));
1439   g_type_class_unref (g_type_class_peek (gst_task_state_get_type ()));
1440   g_type_class_unref (g_type_class_peek (gst_alloc_trace_flags_get_type ()));
1441   g_type_class_unref (g_type_class_peek (gst_type_find_probability_get_type
1442           ()));
1443   g_type_class_unref (g_type_class_peek (gst_uri_type_get_type ()));
1444   g_type_class_unref (g_type_class_peek (gst_parse_error_get_type ()));
1445   g_type_class_unref (g_type_class_peek (gst_param_spec_fraction_get_type ()));
1446
1447   gst_deinitialized = TRUE;
1448   GST_INFO ("deinitialized GStreamer");
1449 }
1450
1451 /**
1452  * gst_version:
1453  * @major: pointer to a guint to store the major version number
1454  * @minor: pointer to a guint to store the minor version number
1455  * @micro: pointer to a guint to store the micro version number
1456  * @nano:  pointer to a guint to store the nano version number
1457  *
1458  * Gets the version number of the GStreamer library.
1459  */
1460 void
1461 gst_version (guint * major, guint * minor, guint * micro, guint * nano)
1462 {
1463   g_return_if_fail (major);
1464   g_return_if_fail (minor);
1465   g_return_if_fail (micro);
1466   g_return_if_fail (nano);
1467
1468   *major = GST_VERSION_MAJOR;
1469   *minor = GST_VERSION_MINOR;
1470   *micro = GST_VERSION_MICRO;
1471   *nano = GST_VERSION_NANO;
1472 }
1473
1474 /**
1475  * gst_version_string:
1476  *
1477  * This function returns a string that is useful for describing this version
1478  * of GStreamer to the outside world: user agent strings, logging, ...
1479  *
1480  * Returns: a newly allocated string describing this version of GStreamer.
1481  */
1482
1483 gchar *
1484 gst_version_string ()
1485 {
1486   guint major, minor, micro, nano;
1487
1488   gst_version (&major, &minor, &micro, &nano);
1489   if (nano == 0)
1490     return g_strdup_printf ("GStreamer %d.%d.%d", major, minor, micro);
1491   else if (nano == 1)
1492     return g_strdup_printf ("GStreamer %d.%d.%d (GIT)", major, minor, micro);
1493   else
1494     return g_strdup_printf ("GStreamer %d.%d.%d (prerelease)", major, minor,
1495         micro);
1496 }
1497
1498 /**
1499  * gst_segtrap_is_enabled:
1500  *
1501  * Some functions in the GStreamer core might install a custom SIGSEGV handler
1502  * to better catch and report errors to the application. Currently this feature
1503  * is enabled by default when loading plugins.
1504  *
1505  * Applications might want to disable this behaviour with the
1506  * gst_segtrap_set_enabled() function. This is typically done if the application
1507  * wants to install its own handler without GStreamer interfering.
1508  *
1509  * Returns: %TRUE if GStreamer is allowed to install a custom SIGSEGV handler.
1510  *
1511  * Since: 0.10.10
1512  */
1513 gboolean
1514 gst_segtrap_is_enabled (void)
1515 {
1516   /* yeps, it's enabled when it's not disabled */
1517   return !_gst_disable_segtrap;
1518 }
1519
1520 /**
1521  * gst_segtrap_set_enabled:
1522  * @enabled: whether a custom SIGSEGV handler should be installed.
1523  *
1524  * Applications might want to disable/enable the SIGSEGV handling of
1525  * the GStreamer core. See gst_segtrap_is_enabled() for more information.
1526  *
1527  * Since: 0.10.10
1528  */
1529 void
1530 gst_segtrap_set_enabled (gboolean enabled)
1531 {
1532   _gst_disable_segtrap = !enabled;
1533 }
1534
1535 /**
1536  * gst_registry_fork_is_enabled:
1537  *
1538  * By default GStreamer will perform a fork() when scanning and rebuilding the
1539  * registry file. 
1540  *
1541  * Applications might want to disable this behaviour with the
1542  * gst_registry_fork_set_enabled() function. 
1543  *
1544  * Returns: %TRUE if GStreamer will use fork() when rebuilding the registry. On
1545  * platforms without fork(), this function will always return %FALSE.
1546  *
1547  * Since: 0.10.10
1548  */
1549 gboolean
1550 gst_registry_fork_is_enabled (void)
1551 {
1552   return _gst_enable_registry_fork;
1553 }
1554
1555 /**
1556  * gst_registry_fork_set_enabled:
1557  * @enabled: whether rebuilding the registry may fork
1558  *
1559  * Applications might want to disable/enable the usage of fork() when rebuilding
1560  * the registry. See gst_registry_fork_is_enabled() for more information.
1561  *
1562  * On platforms without fork(), this function will have no effect on the return
1563  * value of gst_registry_fork_is_enabled().
1564  *
1565  * Since: 0.10.10
1566  */
1567 void
1568 gst_registry_fork_set_enabled (gboolean enabled)
1569 {
1570 #ifdef HAVE_FORK
1571   _gst_enable_registry_fork = enabled;
1572 #endif /* HAVE_FORK */
1573 }
1574
1575
1576 /**
1577  * gst_update_registry:
1578  *
1579  * Forces GStreamer to re-scan its plugin paths and update the default
1580  * plugin registry.
1581  *
1582  * Applications will almost never need to call this function, it is only
1583  * useful if the application knows new plugins have been installed (or old
1584  * ones removed) since the start of the application (or, to be precise, the
1585  * first call to gst_init()) and the application wants to make use of any
1586  * newly-installed plugins without restarting the application.
1587  *
1588  * Applications should assume that the registry update is neither atomic nor
1589  * thread-safe and should therefore not have any dynamic pipelines running
1590  * (including the playbin and decodebin elements) and should also not create
1591  * any elements or access the GStreamer registry while the update is in
1592  * progress.
1593  *
1594  * Note that this function may block for a significant amount of time.
1595  *
1596  * Returns: %TRUE if the registry has been updated successfully (does not
1597  *          imply that there were changes), otherwise %FALSE.
1598  *
1599  * Since: 0.10.12
1600  */
1601 gboolean
1602 gst_update_registry (void)
1603 {
1604   gboolean res = FALSE;
1605
1606 #ifndef GST_DISABLE_REGISTRY
1607   GError *err = NULL;
1608
1609   res = ensure_current_registry (&err);
1610   if (err) {
1611     GST_WARNING ("registry update failed: %s", err->message);
1612     g_error_free (err);
1613   } else {
1614     GST_LOG ("registry update succeeded");
1615   }
1616
1617   if (preload_plugins) {
1618     g_slist_foreach (preload_plugins, load_plugin_func, NULL);
1619   }
1620 #else
1621   GST_WARNING ("registry update failed: %s", "registry disabled");
1622 #endif /* GST_DISABLE_REGISTRY */
1623
1624   return res;
1625 }