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