2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gst.c: Initialization and non-pipeline operations
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.
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.
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.
26 #include "gst_private.h"
27 #include "gst-i18n-lib.h"
28 #include <locale.h> /* for LC_ALL */
32 #ifndef GST_DISABLE_REGISTRY
33 #include "registries/gstxmlregistry.h"
34 #endif /* GST_DISABLE_REGISTRY */
35 #include "gstregistrypool.h"
37 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
39 #define MAX_PATH_SPLIT 16
40 #define GST_PLUGIN_SEPARATOR ","
42 #ifndef GST_DISABLE_REGISTRY
43 gboolean _gst_registry_auto_load = TRUE;
44 static GstRegistry *_global_registry;
45 static GstRegistry *_user_registry;
46 static gboolean _gst_registry_fixed = FALSE;
49 static gboolean _gst_enable_cpu_opt = TRUE;
51 static gboolean gst_initialized = FALSE;
53 /* this will be set in popt callbacks when a problem has been encountered */
54 static gboolean _gst_initialization_failure = FALSE;
55 extern gint _gst_trace_on;
57 /* set to TRUE when segfaults need to be left as is */
58 gboolean _gst_disable_segtrap = FALSE;
61 static void load_plugin_func (gpointer data, gpointer user_data);
62 static void init_popt_callback (poptContext context,
63 enum poptCallbackReason reason,
64 const GstPoptOption * option, const char *arg, void *data);
65 static gboolean init_pre (void);
66 static gboolean init_post (void);
68 static GSList *preload_plugins = NULL;
70 const gchar *g_log_domain_gstreamer = "GStreamer";
73 debug_log_handler (const gchar * log_domain,
74 GLogLevelFlags log_level, const gchar * message, gpointer user_data)
76 g_log_default_handler (log_domain, log_level, message, user_data);
77 /* FIXME: do we still need this ? fatal errors these days are all
78 * other than core errors */
79 /* g_on_error_query (NULL); */
86 #ifndef GST_DISABLE_GST_DEBUG
103 parse_debug_list (const gchar * list)
108 g_return_if_fail (list != NULL);
110 walk = split = g_strsplit (list, ",", 0);
113 gchar **values = g_strsplit (walk[0], ":", 2);
115 if (values[0] && values[1]) {
118 g_strstrip (values[0]);
119 g_strstrip (values[1]);
120 level = strtol (values[1], NULL, 0);
121 if (level >= 0 && level < GST_LEVEL_COUNT) {
122 GST_DEBUG ("setting debugging to level %d for name \"%s\"",
124 gst_debug_set_threshold_for_name (values[0], level);
138 * gst_init_get_popt_table:
140 * Returns a popt option table with GStreamer's argument specifications. The
141 * table is set up to use popt's callback method, so whenever the parsing is
142 * actually performed (via poptGetContext), the GStreamer libraries will
145 * This function is useful if you want to integrate GStreamer with other
146 * libraries that use popt.
148 * Returns: a pointer to the static GStreamer option table.
149 * No free is necessary.
151 const GstPoptOption *
152 gst_init_get_popt_table (void)
154 static GstPoptOption gstreamer_options[] = {
155 {NULL, NUL, POPT_ARG_CALLBACK | POPT_CBFLAG_PRE | POPT_CBFLAG_POST,
156 (void *) &init_popt_callback, 0, NULL, NULL},
157 /* make sure we use our GETTEXT_PACKAGE as the domain for popt translations */
158 {NULL, NUL, POPT_ARG_INTL_DOMAIN, GETTEXT_PACKAGE, 0, NULL, NULL},
159 {"gst-version", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL, ARG_VERSION,
160 N_("Print the GStreamer version"), NULL},
161 {"gst-fatal-warnings", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
162 ARG_FATAL_WARNINGS, N_("Make all warnings fatal"), NULL},
164 #ifndef GST_DISABLE_GST_DEBUG
165 {"gst-debug-help", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
166 ARG_DEBUG_HELP, N_("Print available debug categories and exit"), NULL},
167 {"gst-debug-level", NUL, POPT_ARG_INT | POPT_ARGFLAG_STRIP, NULL,
169 N_("Default debug level from 1 (only error) to 5 (anything) or "
172 {"gst-debug", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG,
173 N_("Comma-separated list of category_name:level pairs to set "
174 "specific levels for the individual categories. Example: "
175 "GST_AUTOPLUG:5,GST_ELEMENT_*:3"),
177 {"gst-debug-no-color", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
178 ARG_DEBUG_NO_COLOR, N_("Disable colored debugging output"), NULL},
179 {"gst-debug-disable", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
180 ARG_DEBUG_DISABLE, N_("Disable debugging")},
183 {"gst-disable-cpu-opt", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
184 ARG_DISABLE_CPU_OPT, N_("Disable accelerated CPU instructions"), NULL},
185 {"gst-plugin-spew", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
186 ARG_PLUGIN_SPEW, N_("Enable verbose plugin loading diagnostics"), NULL},
187 {"gst-plugin-path", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
188 ARG_PLUGIN_PATH, NULL, N_("PATHS")},
189 {"gst-plugin-load", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
191 N_("Comma-separated list of plugins to preload in addition to the "
192 "list stored in envronment variable GST_PLUGIN_PATH"),
194 {"gst-disable-segtrap", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
196 N_("Disable trapping of segmentation faults during plugin loading"),
198 {"gst-scheduler", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
199 ARG_SCHEDULER, NULL, N_("SCHEDULER")},
200 {"gst-registry", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
201 ARG_REGISTRY, N_("Registry to use"), N_("REGISTRY")},
204 static gboolean inited = FALSE;
209 for (i = 0; i < G_N_ELEMENTS (gstreamer_options); i++) {
210 if (gstreamer_options[i].longName == NULL) {
211 } else if (strcmp (gstreamer_options[i].longName, "gst-plugin-path") == 0) {
212 gstreamer_options[i].descrip =
214 ("path list for loading plugins (separated by '%s')"),
215 G_SEARCHPATH_SEPARATOR_S);
216 } else if (strcmp (gstreamer_options[i].longName, "gst-scheduler") == 0) {
217 gstreamer_options[i].descrip =
218 g_strdup_printf (_("Scheduler to use (default is '%s')"),
219 GST_SCHEDULER_DEFAULT_NAME);
226 return gstreamer_options;
231 * @argc: pointer to application's argc
232 * @argv: pointer to application's argv
234 * Initializes the GStreamer library, setting up internal path lists,
235 * registering built-in elements, and loading standard plugins.
237 * This function will return %FALSE if GStreamer could not be initialized
238 * for some reason. If you want your program to fail fatally,
239 * use gst_init() instead.
241 * Returns: %TRUE if GStreamer could be initialized.
244 gst_init_check (int *argc, char **argv[])
246 return gst_init_check_with_popt_table (argc, argv, NULL);
251 * @argc: pointer to application's argc
252 * @argv: pointer to application's argv
254 * Initializes the GStreamer library, setting up internal path lists,
255 * registering built-in elements, and loading standard plugins.
257 * This function will terminate your program if it was unable to initialize
258 * GStreamer for some reason. If you want your program to fall back,
259 * use gst_init_check() instead.
261 * WARNING: This function does not work in the same way as corresponding
262 * functions in other glib-style libraries, such as gtk_init(). In
263 * particular, unknown command line options cause this function to
264 * abort program execution.
267 gst_init (int *argc, char **argv[])
269 gst_init_with_popt_table (argc, argv, NULL);
273 * gst_init_with_popt_table:
274 * @argc: pointer to application's argc
275 * @argv: pointer to application's argv
276 * @popt_options: pointer to a popt table to append
278 * Initializes the GStreamer library, parsing the options,
279 * setting up internal path lists,
280 * registering built-in elements, and loading standard plugins.
282 * This function will terminate your program if it was unable to initialize
283 * GStreamer for some reason. If you want your program to fall back,
284 * use gst_init_check_with_popt_table() instead.
287 gst_init_with_popt_table (int *argc, char **argv[],
288 const GstPoptOption * popt_options)
290 if (!gst_init_check_with_popt_table (argc, argv, popt_options)) {
291 g_print ("Could not initialize GStreamer !\n");
297 * gst_init_check_with_popt_table:
298 * @argc: pointer to application's argc
299 * @argv: pointer to application's argv
300 * @popt_options: pointer to a popt table to append
302 * Initializes the GStreamer library, parsing the options,
303 * setting up internal path lists,
304 * registering built-in elements, and loading standard plugins.
306 * Returns: %TRUE if GStreamer could be initialized.
309 gst_init_check_with_popt_table (int *argc, char **argv[],
310 const GstPoptOption * popt_options)
314 GstPoptOption *options;
315 const gchar *gst_debug_env = NULL;
317 GstPoptOption options_with[] = {
318 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:",
320 {NULL, NUL, POPT_ARG_INCLUDE_TABLE,
321 (GstPoptOption *) gst_init_get_popt_table (), 0,
322 "GStreamer options:", NULL},
323 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, (GstPoptOption *) popt_options, 0,
324 "Application options:", NULL},
327 GstPoptOption options_without[] = {
328 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:",
330 {NULL, NUL, POPT_ARG_INCLUDE_TABLE,
331 (GstPoptOption *) gst_init_get_popt_table (), 0,
332 "GStreamer options:", NULL},
336 if (gst_initialized) {
337 GST_DEBUG ("already initialized gst");
341 if (!argc || !argv) {
343 g_warning ("gst_init: Only one of argc or argv was NULL");
349 gst_initialized = TRUE;
353 if (popt_options == NULL) {
354 options = options_without;
356 options = options_with;
358 context = poptGetContext ("GStreamer", *argc, (const char **) *argv,
361 /* check for GST_DEBUG environment variable */
362 gst_debug_env = g_getenv ("GST_DEBUG");
364 parse_debug_list (gst_debug_env);
366 /* Scan until we reach the end (-1), ignoring errors */
367 while ((nextopt = poptGetNextOpt (context)) != -1) {
369 /* If an error occurred and it's not an missing options, throw an error
370 * We don't want to show the "unknown option" message, since it'll
371 * might interfere with the applications own command line parsing
373 if (nextopt < 0 && nextopt != POPT_ERROR_BADOPT) {
374 g_print ("Error on option %s: %s.\nRun '%s --help' "
375 "to see a full list of available command line options.\n",
376 poptBadOption (context, 0), poptStrerror (nextopt), (*argv)[0]);
378 poptFreeContext (context);
383 *argc = poptStrippedArgv (context, *argc, *argv);
385 poptFreeContext (context);
390 #ifndef GST_DISABLE_REGISTRY
392 add_path_func (gpointer data, gpointer user_data)
394 GstRegistry *registry = GST_REGISTRY (user_data);
396 GST_INFO ("Adding plugin path: \"%s\"", (gchar *) data);
397 gst_registry_add_path (registry, (gchar *) data);
402 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
404 preload_plugins = g_slist_prepend (preload_plugins, data);
408 load_plugin_func (gpointer data, gpointer user_data)
411 const gchar *filename;
413 filename = (const gchar *) data;
415 plugin = gst_plugin_load_file (filename, NULL);
418 GST_INFO ("Loaded plugin: \"%s\"", filename);
420 gst_registry_pool_add_plugin (plugin);
422 GST_WARNING ("Failed to load plugin: \"%s\"", filename);
429 split_and_iterate (const gchar * stringlist, gchar * separator, GFunc iterator,
434 gchar *lastlist = g_strdup (stringlist);
437 strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
442 iterator (strings[j], user_data);
443 if (++j == MAX_PATH_SPLIT) {
444 lastlist = g_strdup (strings[j]);
445 g_strfreev (strings);
453 /* we have no fail cases yet, but maybe in the future */
459 if (g_thread_supported ()) {
460 /* somebody already initialized threading */
462 g_thread_init (NULL);
464 /* we need threading to be enabled right here */
468 setlocale (LC_ALL, "");
469 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
470 #endif /* ENABLE_NLS */
472 #ifndef GST_DISABLE_REGISTRY
474 const gchar *debug_list;
476 debug_list = g_getenv ("GST_DEBUG");
478 parse_debug_list (debug_list);
482 #ifndef GST_DISABLE_REGISTRY
485 const gchar *homedir;
488 gst_xml_registry_new ("global_registry", GLOBAL_REGISTRY_FILE);
490 #ifdef PLUGINS_USE_BUILDDIR
491 /* location libgstelements.so */
492 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/libs/gst");
493 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/elements");
494 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/types");
495 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/autoplug");
496 gst_registry_add_path (_global_registry,
497 PLUGINS_BUILDDIR "/gst/schedulers");
498 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/indexers");
500 /* add the main (installed) library path */
501 gst_registry_add_path (_global_registry, PLUGINS_DIR);
502 #endif /* PLUGINS_USE_BUILDDIR */
504 if (g_getenv ("GST_REGISTRY")) {
505 user_reg = g_strdup (g_getenv ("GST_REGISTRY"));
507 homedir = g_get_home_dir ();
508 user_reg = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL);
510 _user_registry = gst_xml_registry_new ("user_registry", user_reg);
514 #endif /* GST_DISABLE_REGISTRY */
520 gst_register_core_elements (GstPlugin * plugin)
522 /* register some standard builtin types */
523 if (!gst_element_register (plugin, "bin", GST_RANK_PRIMARY,
525 !gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY,
526 GST_TYPE_PIPELINE) ||
527 !gst_element_register (plugin, "thread", GST_RANK_PRIMARY,
529 !gst_element_register (plugin, "queue", GST_RANK_NONE, GST_TYPE_QUEUE))
530 g_assert_not_reached ();
535 static GstPluginDesc plugin_desc = {
539 "core elements of the GStreamer library",
540 gst_register_core_elements,
552 * - initalization of threads if we use them
555 * - initializes gst_format
556 * - registers a bunch of types for gst_objects
558 * - we don't have cases yet where this fails, but in the future
559 * we might and then it's nice to be able to return that
565 const gchar *plugin_path;
567 #ifndef GST_DISABLE_TRACE
569 #endif /* GST_DISABLE_TRACE */
571 llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
572 g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
574 GST_INFO ("Initializing GStreamer Core Library version %s", VERSION);
576 _gst_format_initialize ();
577 _gst_query_type_initialize ();
578 gst_object_get_type ();
580 gst_real_pad_get_type ();
581 gst_ghost_pad_get_type ();
582 gst_element_factory_get_type ();
583 gst_element_get_type ();
584 gst_scheduler_factory_get_type ();
585 gst_type_find_factory_get_type ();
587 #ifndef GST_DISABLE_INDEX
588 gst_index_factory_get_type ();
589 #endif /* GST_DISABLE_INDEX */
590 #ifndef GST_DISABLE_URI
591 gst_uri_handler_get_type ();
592 #endif /* GST_DISABLE_URI */
594 plugin_path = g_getenv ("GST_PLUGIN_PATH");
595 #ifndef GST_DISABLE_REGISTRY
596 split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func,
598 #endif /* GST_DISABLE_REGISTRY */
600 /* register core plugins */
601 _gst_plugin_register_static (&plugin_desc);
603 _gst_cpu_initialize (_gst_enable_cpu_opt);
604 gst_structure_get_type ();
605 _gst_value_initialize ();
606 gst_caps_get_type ();
607 _gst_plugin_initialize ();
608 _gst_event_initialize ();
609 _gst_buffer_initialize ();
610 _gst_tag_initialize ();
612 #ifndef GST_DISABLE_REGISTRY
613 if (!_gst_registry_fixed) {
614 /* don't override command-line options */
615 if (g_getenv ("GST_REGISTRY")) {
616 g_object_set (_global_registry, "location", g_getenv ("GST_REGISTRY"),
618 _gst_registry_fixed = TRUE;
622 if (!_gst_registry_fixed) {
623 gst_registry_pool_add (_global_registry, 100);
624 gst_registry_pool_add (_user_registry, 50);
627 gst_registry_pool_add (_global_registry, 100);
630 if (_gst_registry_auto_load) {
631 gst_registry_pool_load_all ();
633 #endif /* GST_DISABLE_REGISTRY */
635 /* if we need to preload plugins */
636 if (preload_plugins) {
637 g_slist_foreach (preload_plugins, load_plugin_func, NULL);
638 g_slist_free (preload_plugins);
639 preload_plugins = NULL;
641 #ifndef GST_DISABLE_TRACE
644 gst_trace = gst_trace_new ("gst.trace", 1024);
645 gst_trace_set_default (gst_trace);
647 #endif /* GST_DISABLE_TRACE */
652 #ifndef GST_DISABLE_GST_DEBUG
654 sort_by_category_name (gconstpointer a, gconstpointer b)
656 return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
657 gst_debug_category_get_name ((GstDebugCategory *) b));
660 gst_debug_help (void)
663 GList *list2, *walk2;
668 walk2 = list2 = gst_registry_pool_plugin_list ();
670 GstPlugin *plugin = GST_PLUGIN (walk2->data);
672 walk2 = g_list_next (walk2);
674 if (!gst_plugin_is_loaded (plugin)) {
675 #ifndef GST_DISABLE_REGISTRY
676 if (GST_IS_REGISTRY (plugin->manager)) {
677 GST_CAT_LOG (GST_CAT_PLUGIN_LOADING, "loading plugin %s",
679 if (gst_registry_load_plugin (GST_REGISTRY (plugin->manager),
680 plugin) != GST_REGISTRY_OK)
681 GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "loading plugin %s failed",
684 #endif /* GST_DISABLE_REGISTRY */
689 list = gst_debug_get_all_categories ();
690 walk = list = g_slist_sort (list, sort_by_category_name);
693 g_print ("name level description\n");
694 g_print ("---------------------+--------+--------------------------------\n");
697 GstDebugCategory *cat = (GstDebugCategory *) walk->data;
699 if (gst_debug_is_colored ()) {
700 gchar *color = gst_debug_construct_term_color (cat->color);
702 g_print ("%s%-20s\033[00m %1d %s %s%s\033[00m\n",
704 gst_debug_category_get_name (cat),
705 gst_debug_category_get_threshold (cat),
706 gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
707 color, gst_debug_category_get_description (cat));
710 g_print ("%-20s %1d %s %s\n", gst_debug_category_get_name (cat),
711 gst_debug_category_get_threshold (cat),
712 gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
713 gst_debug_category_get_description (cat));
715 walk = g_slist_next (walk);
723 init_popt_callback (poptContext context, enum poptCallbackReason reason,
724 const GstPoptOption * option, const char *arg, void *data)
726 GLogLevelFlags fatal_mask;
731 case POPT_CALLBACK_REASON_PRE:
733 _gst_initialization_failure = TRUE;
735 case POPT_CALLBACK_REASON_OPTION:
736 switch (option->val) {
738 g_print ("GStreamer Core Library version %s\n", GST_VERSION);
740 case ARG_FATAL_WARNINGS:
741 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
742 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
743 g_log_set_always_fatal (fatal_mask);
745 #ifndef GST_DISABLE_GST_DEBUG
746 case ARG_DEBUG_LEVEL:{
749 tmp = strtol (arg, NULL, 0);
750 if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
751 gst_debug_set_default_threshold (tmp);
756 parse_debug_list (arg);
758 case ARG_DEBUG_NO_COLOR:
759 gst_debug_set_colored (FALSE);
761 case ARG_DEBUG_DISABLE:
762 gst_debug_set_active (FALSE);
768 case ARG_DISABLE_CPU_OPT:
769 _gst_enable_cpu_opt = FALSE;
771 case ARG_PLUGIN_SPEW:
773 case ARG_PLUGIN_PATH:
774 #ifndef GST_DISABLE_REGISTRY
775 split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func,
777 #endif /* GST_DISABLE_REGISTRY */
779 case ARG_PLUGIN_LOAD:
780 split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
782 case ARG_SEGTRAP_DISABLE:
783 _gst_disable_segtrap = TRUE;
786 gst_scheduler_factory_set_default_name (arg);
789 #ifndef GST_DISABLE_REGISTRY
790 g_object_set (G_OBJECT (_user_registry), "location", arg, NULL);
791 _gst_registry_fixed = TRUE;
792 #endif /* GST_DISABLE_REGISTRY */
795 g_warning ("option %d not recognized", option->val);
799 case POPT_CALLBACK_REASON_POST:
801 _gst_initialization_failure = TRUE;
802 gst_initialized = TRUE;
809 * @use_threads: a #gboolean indicating whether threads should be used
811 * This function is deprecated and should not be used in new code.
812 * GStreamer requires threads to be enabled at all times.
815 gst_use_threads (gboolean use_threads)
822 * This function is deprecated and should not be used in new code.
824 * Queries if GStreamer has threads enabled.
826 * Returns: %TRUE if threads are enabled.
829 gst_has_threads (void)
835 static GSList *mainloops = NULL;
840 * Enters the main GStreamer processing loop.
842 * This function duplicates functionality in glib, and will be removed
843 * during the 0.9 development series.
850 loop = g_main_loop_new (NULL, FALSE);
851 mainloops = g_slist_prepend (mainloops, loop);
853 g_main_loop_run (loop);
859 * Exits the main GStreamer processing loop.
861 * This function duplicates functionality in glib, and will be removed
862 * during the 0.9 development series.
868 g_error ("Quit more loops than there are");
870 GMainLoop *loop = mainloops->data;
872 mainloops = g_slist_delete_link (mainloops, mainloops);
873 g_main_loop_quit (loop);
874 g_main_loop_unref (loop);
880 * @major: pointer to a guint to store the major version number
881 * @minor: pointer to a guint to store the minor version number
882 * @micro: pointer to a guint to store the micro version number
884 * Gets the version number of the GStreamer library.
887 gst_version (guint * major, guint * minor, guint * micro)
889 g_return_if_fail (major);
890 g_return_if_fail (minor);
891 g_return_if_fail (micro);
893 *major = GST_VERSION_MAJOR;
894 *minor = GST_VERSION_MINOR;
895 *micro = GST_VERSION_MICRO;