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"
30 #ifndef GST_DISABLE_TYPEFIND
31 #include "gsttypefind.h"
32 #endif /* GST_DISABLE_TYPEFIND */
33 #ifndef GST_DISABLE_REGISTRY
34 #include "registries/gstxmlregistry.h"
35 #endif /* GST_DISABLE_REGISTRY */
36 #include "gstregistrypool.h"
38 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
40 #define MAX_PATH_SPLIT 16
41 #define GST_PLUGIN_SEPARATOR ","
45 #ifndef GST_DISABLE_REGISTRY
46 gboolean _gst_registry_auto_load = TRUE;
47 static GstRegistry *_global_registry;
48 static GstRegistry *_user_registry;
49 static gboolean _gst_registry_fixed = FALSE;
52 static gboolean _gst_use_threads = TRUE;
54 static gboolean _gst_enable_cpu_opt = TRUE;
56 static gboolean gst_initialized = FALSE;
57 /* this will be set in popt callbacks when a problem has been encountered */
58 static gboolean _gst_initialization_failure = FALSE;
59 extern gint _gst_trace_on;
61 extern GThreadFunctions gst_thread_dummy_functions;
64 static void load_plugin_func (gpointer data, gpointer user_data);
65 static void init_popt_callback (poptContext context,
66 enum poptCallbackReason reason,
67 const struct poptOption *option,
68 const char *arg, void *data);
69 static gboolean init_pre (void);
70 static gboolean init_post (void);
72 static GSList *preload_plugins = NULL;
74 const gchar *g_log_domain_gstreamer = "GStreamer";
77 debug_log_handler (const gchar *log_domain,
78 GLogLevelFlags log_level,
82 g_log_default_handler (log_domain, log_level, message, user_data);
83 /* FIXME: do we still need this ? fatal errors these days are all
84 * other than core errors */
85 /* g_on_error_query (NULL); */
108 /* default scheduler, can be changed in gstscheduler.h with
109 * the GST_SCHEDULER_DEFAULT_NAME define.
111 static const struct poptOption gstreamer_options[] = {
112 {NULL, NUL, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, (void *) &init_popt_callback, 0, NULL, NULL},
113 {"gst-version", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_VERSION, N_("Print the GStreamer version"), NULL},
114 {"gst-fatal-warnings", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_FATAL_WARNINGS, N_("Make all warnings fatal"), NULL},
115 #ifndef GST_DISABLE_GST_DEBUG
116 {"gst-debug-level", NUL, POPT_ARG_INT|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_LEVEL, N_("default debug level from 1 (only error) to 5 (anything) or 0 for no output"), "LEVEL"},
117 {"gst-debug", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG, N_("colon-seperated list of category_name=level pairs to set specific levels for the individual categories.\nExample:GST_AUTOPLUG=5:GST_ELEMENT_*=3"), "CATEGORIES"},
118 {"gst-debug-no-color", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_NO_COLOR, N_("disable color debugging output"), NULL},
119 {"gst-disable-debug", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_DISABLE, N_("disable debugging")},
120 {"gst-debug-help", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_HELP, N_("print available debug categories and exit"), NULL},
122 {"gst-disable-cpu-opt",NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DISABLE_CPU_OPT,N_("Disable accelerated CPU instructions"), NULL},
123 {"gst-plugin-spew", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_SPEW, N_("enable verbose plugin loading diagnostics"), NULL},
124 {"gst-plugin-path", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_PATH, N_("'" G_SEARCHPATH_SEPARATOR_S "'--separated path list for loading plugins"), "PATHS"},
125 {"gst-plugin-load", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_LOAD, N_("comma-separated list of plugins to preload in addition to the list stored in env variable GST_PLUGIN_PATH"), "PLUGINS"},
126 {"gst-scheduler", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_SCHEDULER, N_("scheduler to use ('"GST_SCHEDULER_DEFAULT_NAME"' is the default)"), "SCHEDULER"},
127 {"gst-registry", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_REGISTRY, N_("registry to use") , "REGISTRY"},
132 * gst_init_get_popt_table:
134 * Returns a popt option table with GStreamer's argument specifications. The
135 * table is set up to use popt's callback method, so whenever the parsing is
136 * actually performed (via a poptGetContext()), the GStreamer libraries will
139 * Returns: a pointer to the static GStreamer option table.
140 * No free is necessary.
142 const struct poptOption *
143 gst_init_get_popt_table (void)
145 return gstreamer_options;
150 * @argc: pointer to application's argc
151 * @argv: pointer to application's argv
153 * Initializes the GStreamer library, setting up internal path lists,
154 * registering built-in elements, and loading standard plugins.
156 * This function will return %FALSE if GStreamer could not be initialized
157 * for some reason. If you want your program to fail fatally,
158 * use gst_init() instead.
160 * Returns: TRUE if GStreamer coul be initialized
163 gst_init_check (int *argc, char **argv[])
165 return gst_init_check_with_popt_table (argc, argv, NULL);
170 * @argc: pointer to application's argc
171 * @argv: pointer to application's argv
173 * Initializes the GStreamer library, setting up internal path lists,
174 * registering built-in elements, and loading standard plugins.
176 * This function will terminate your program if it was unable to initialize
177 * GStreamer for some reason. If you want your program to fall back,
178 * use gst_init_check() instead.
181 gst_init (int *argc, char **argv[])
183 gst_init_with_popt_table (argc, argv, NULL);
187 * gst_init_with_popt_table:
188 * @argc: pointer to application's argc
189 * @argv: pointer to application's argv
190 * @popt_options: pointer to a popt table to append
192 * Initializes the GStreamer library, parsing the options,
193 * setting up internal path lists,
194 * registering built-in elements, and loading standard plugins.
196 * This function will terminate your program if it was unable to initialize
197 * GStreamer for some reason. If you want your program to fall back,
198 * use gst_init_check_with_popt_table() instead.
201 gst_init_with_popt_table (int *argc, char **argv[],
202 const struct poptOption *popt_options)
204 if (!gst_init_check_with_popt_table (argc, argv, popt_options)) {
205 g_print ("Could not initialize GStreamer !\n");
210 * gst_init_check_with_popt_table:
211 * @argc: pointer to application's argc
212 * @argv: pointer to application's argv
213 * @popt_options: pointer to a popt table to append
215 * Initializes the GStreamer library, parsing the options,
216 * setting up internal path lists,
217 * registering built-in elements, and loading standard plugins.
219 * Returns: TRUE if GStreamer coul be initialized
222 gst_init_check_with_popt_table (int *argc, char **argv[],
223 const struct poptOption *popt_options)
227 struct poptOption *options;
228 struct poptOption options_with[] = {
229 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:", NULL},
230 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, (struct poptOption *) gstreamer_options, 0, "GStreamer options:", NULL},
231 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, (struct poptOption *) popt_options, 0, "Application options:", NULL},
234 struct poptOption options_without[] = {
235 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:", NULL},
236 {NULL, NUL, POPT_ARG_INCLUDE_TABLE, (struct poptOption *) gstreamer_options, 0, "GStreamer options:", NULL},
242 GST_DEBUG ("already initialized gst");
246 if (!argc || !argv) {
248 g_warning ("gst_init: Only one of argc or argv was NULL");
250 if (!init_pre ()) return FALSE;
251 if (!init_post ()) return FALSE;
252 gst_initialized = TRUE;
256 if (popt_options == NULL) {
257 options = options_without;
259 options = options_with;
261 context = poptGetContext ("GStreamer", *argc, (const char**)*argv,
264 while ((nextopt = poptGetNextOpt (context)) > 0)
266 /* we only check for failures here, actual work is done in callbacks */
267 if (_gst_initialization_failure) return FALSE;
271 g_print ("Error on option %s: %s.\nRun '%s --help' "
272 "to see a full list of available command line options.\n",
273 poptBadOption (context, 0),
274 poptStrerror (nextopt),
277 poptFreeContext (context);
281 *argc = poptStrippedArgv (context, *argc, *argv);
283 poptFreeContext (context);
288 #ifndef GST_DISABLE_REGISTRY
290 add_path_func (gpointer data, gpointer user_data)
292 GstRegistry *registry = GST_REGISTRY (user_data);
294 GST_INFO ("Adding plugin path: \"%s\"", (gchar *) data);
295 gst_registry_add_path (registry, (gchar *)data);
300 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
302 preload_plugins = g_slist_prepend (preload_plugins, data);
306 parse_debug_list (const gchar *list)
311 g_return_if_fail (list != NULL);
313 walk = split = g_strsplit (list, ":", 0);
316 gchar **values = g_strsplit ( walk[0], "=", 2);
317 if (values[0] && values[1]) {
319 g_strstrip (values[0]);
320 g_strstrip (values[1]);
321 level = strtol (values[1], NULL, 0);
322 if (level >= 0 && level < GST_LEVEL_COUNT) {
323 GST_DEBUG ("setting debugging to level %d for name \"%s\"",
325 gst_debug_set_threshold_for_name (values[0], level);
334 load_plugin_func (gpointer data, gpointer user_data)
338 const gchar *filename;
340 filename = (const gchar *) data;
342 plugin = gst_plugin_new (filename);
343 ret = gst_plugin_load_plugin (plugin, NULL);
346 GST_INFO ("Loaded plugin: \"%s\"", filename);
348 gst_registry_pool_add_plugin (plugin);
350 GST_WARNING ("Failed to load plugin: \"%s\"", filename);
357 split_and_iterate (const gchar *stringlist, gchar *separator, GFunc iterator, gpointer user_data)
361 gchar *lastlist = g_strdup (stringlist);
364 strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
369 iterator (strings[j], user_data);
370 if (++j == MAX_PATH_SPLIT) {
371 lastlist = g_strdup (strings[j]);
372 g_strfreev (strings);
380 /* we have no fail cases yet, but maybe in the future */
387 if (g_thread_supported ()) {
388 /* somebody already initialized threading */
389 _gst_use_threads = TRUE;
391 if (_gst_use_threads)
392 g_thread_init (NULL);
394 g_thread_init (&gst_thread_dummy_functions);
396 /* we need threading to be enabled right here */
399 bindtextdomain (GETTEXT_PACKAGE, GST_LOCALEDIR);
400 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
402 #ifndef GST_DISABLE_REGISTRY
404 const gchar *debug_list;
406 debug_list = g_getenv ("GST_DEBUG");
408 parse_debug_list (debug_list);
412 #ifndef GST_DISABLE_REGISTRY
415 const gchar *homedir;
417 _global_registry = gst_xml_registry_new ("global_registry", GLOBAL_REGISTRY_FILE);
419 #ifdef PLUGINS_USE_BUILDDIR
420 /* location libgstelements.so */
421 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/libs/gst");
422 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/elements");
423 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/types");
424 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/autoplug");
425 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/schedulers");
426 gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/indexers");
428 /* add the main (installed) library path */
429 gst_registry_add_path (_global_registry, PLUGINS_DIR);
430 #endif /* PLUGINS_USE_BUILDDIR */
432 if (g_getenv ("GST_REGISTRY"))
434 user_reg = g_strdup (g_getenv ("GST_REGISTRY"));
438 homedir = g_get_home_dir ();
439 user_reg = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL);
441 _user_registry = gst_xml_registry_new ("user_registry", user_reg);
445 #endif /* GST_DISABLE_REGISTRY */
451 gst_register_core_elements (GModule *module, GstPlugin *plugin)
453 GstElementFactory *factory;
455 /* register some standard builtin types */
456 factory = gst_element_factory_new ("bin", gst_bin_get_type (), &gst_bin_details);
457 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
458 factory = gst_element_factory_new ("pipeline", gst_pipeline_get_type (), &gst_pipeline_details);
459 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
460 factory = gst_element_factory_new ("thread", gst_thread_get_type (), &gst_thread_details);
461 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
462 factory = gst_element_factory_new ("queue", gst_queue_get_type (), &gst_queue_details);
463 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
464 #ifndef GST_DISABLE_TYPEFIND
465 factory = gst_element_factory_new ("typefind", gst_type_find_get_type (), &gst_type_find_details);
466 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
467 #endif /* GST_DISABLE_TYPEFIND */
472 static GstPluginDesc plugin_desc = {
476 gst_register_core_elements
481 * - initalization of threads if we use them
484 * - initializes gst_format
485 * - registers a bunch of types for gst_objects
487 * - we don't have cases yet where this fails, but in the future
488 * we might and then it's nice to be able to return that
494 const gchar *plugin_path;
495 #ifndef GST_DISABLE_TRACE
497 #endif /* GST_DISABLE_TRACE */
499 llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
500 g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
502 GST_INFO ("Initializing GStreamer Core Library version %s %s",
503 VERSION, _gst_use_threads ? "" : "(no threads)");
505 _gst_format_initialize ();
506 _gst_query_type_initialize ();
507 gst_object_get_type ();
509 gst_real_pad_get_type ();
510 gst_ghost_pad_get_type ();
511 gst_element_factory_get_type ();
512 gst_element_get_type ();
513 gst_type_factory_get_type ();
514 gst_scheduler_factory_get_type ();
516 #ifndef GST_DISABLE_AUTOPLUG
517 gst_autoplug_factory_get_type ();
518 #endif /* GST_DISABLE_AUTOPLUG */
519 #ifndef GST_DISABLE_INDEX
520 gst_index_factory_get_type ();
521 #endif /* GST_DISABLE_INDEX */
522 #ifndef GST_DISABLE_URI
523 gst_uri_handler_get_type ();
524 #endif /* GST_DISABLE_URI */
526 plugin_path = g_getenv ("GST_PLUGIN_PATH");
527 #ifndef GST_DISABLE_REGISTRY
528 split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func, _user_registry);
529 #endif /* GST_DISABLE_REGISTRY */
531 /* register core plugins */
532 _gst_plugin_register_static (&plugin_desc);
534 _gst_cpu_initialize (_gst_enable_cpu_opt);
535 _gst_props_initialize ();
536 _gst_caps_initialize ();
537 _gst_plugin_initialize ();
538 _gst_event_initialize ();
539 _gst_buffer_initialize ();
541 #ifndef GST_DISABLE_REGISTRY
542 if (!_gst_registry_fixed) {
543 /* don't override command-line options */
544 if (g_getenv ("GST_REGISTRY")) {
545 g_object_set (_user_registry, "location", g_getenv ("GST_REGISTRY"), NULL);
546 _gst_registry_fixed = TRUE;
550 if (!_gst_registry_fixed) {
551 gst_registry_pool_add (_global_registry, 100);
552 gst_registry_pool_add (_user_registry, 50);
554 gst_registry_pool_add (_user_registry, 50);
557 if (_gst_registry_auto_load) {
558 gst_registry_pool_load_all ();
560 #endif /* GST_DISABLE_REGISTRY */
562 /* if we need to preload plugins */
563 if (preload_plugins) {
564 g_slist_foreach (preload_plugins, load_plugin_func, NULL);
565 g_slist_free (preload_plugins);
566 preload_plugins = NULL;
569 #ifndef GST_DISABLE_TRACE
572 gst_trace = gst_trace_new ("gst.trace", 1024);
573 gst_trace_set_default (gst_trace);
575 #endif /* GST_DISABLE_TRACE */
576 if (_gst_progname == NULL) {
577 _gst_progname = g_strdup ("gstprog");
584 gst_debug_help (void)
588 walk = cats = gst_debug_get_all_categories ();
591 g_print ("name level description\n");
592 g_print ("---------------------+--------+--------------------------------\n");
595 /* unused when debugging is disabled */
596 G_GNUC_UNUSED GstDebugCategory *cat = (GstDebugCategory *) walk->data;
598 if (gst_debug_is_colored ()) {
599 gchar *color = gst_debug_construct_term_color (cat->color);
600 g_print ("%s%-20s\033[00m %1d %s %s%s\033[00m\n",
602 gst_debug_category_get_name (cat),
603 gst_debug_category_get_threshold (cat),
604 gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
606 gst_debug_category_get_description (cat));
609 g_print ("%-20s %1d %s %s\n", gst_debug_category_get_name (cat),
610 gst_debug_category_get_threshold (cat),
611 gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
612 gst_debug_category_get_description (cat));
614 walk = g_slist_next (walk);
621 init_popt_callback (poptContext context, enum poptCallbackReason reason,
622 const struct poptOption *option, const char *arg, void *data)
624 GLogLevelFlags fatal_mask;
629 case POPT_CALLBACK_REASON_PRE:
630 if (!init_pre ()) _gst_initialization_failure = TRUE;
632 case POPT_CALLBACK_REASON_OPTION:
633 switch (option->val) {
635 g_print ("GStreamer Core Library version %s\n", GST_VERSION);
637 case ARG_FATAL_WARNINGS:
638 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
639 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
640 g_log_set_always_fatal (fatal_mask);
642 case ARG_DEBUG_LEVEL: {
644 tmp = strtol (arg, NULL, 0);
645 if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
646 gst_debug_set_default_threshold (tmp);
651 parse_debug_list (arg);
653 case ARG_DEBUG_NO_COLOR:
654 gst_debug_set_colored (FALSE);
656 case ARG_DEBUG_DISABLE:
657 gst_debug_set_active (FALSE);
662 case ARG_DISABLE_CPU_OPT:
663 _gst_enable_cpu_opt = FALSE;
665 case ARG_PLUGIN_SPEW:
667 case ARG_PLUGIN_PATH:
668 #ifndef GST_DISABLE_REGISTRY
669 split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, _user_registry);
670 #endif /* GST_DISABLE_REGISTRY */
672 case ARG_PLUGIN_LOAD:
673 split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
676 gst_scheduler_factory_set_default_name (arg);
679 #ifndef GST_DISABLE_REGISTRY
680 g_object_set (G_OBJECT (_user_registry), "location", arg, NULL);
681 _gst_registry_fixed = TRUE;
682 #endif /* GST_DISABLE_REGISTRY */
685 g_warning ("option %d not recognized", option->val);
689 case POPT_CALLBACK_REASON_POST:
690 if (!init_post ()) _gst_initialization_failure = TRUE;
691 gst_initialized = TRUE;
698 * @use_threads: flag indicating threads should be used
700 * Instructs the core to turn on/off threading. When threading
701 * is turned off, all thread operations such as mutexes and conditionals
702 * are turned into NOPs. use this if you want absolute minimal overhead
703 * and you don't use any threads in the pipeline.
705 * This function may only be called before threads are initialized. This
706 * usually happens when calling gst_init.
710 gst_use_threads (gboolean use_threads)
712 g_return_if_fail (!gst_initialized);
713 g_return_if_fail (g_thread_supported ());
715 _gst_use_threads = use_threads;
721 * Query if GStreamer has threads enabled.
723 * Returns: TRUE if threads are enabled.
726 gst_has_threads (void)
728 return _gst_use_threads;
732 static GSList *mainloops = NULL;
737 * Enter the main GStreamer processing loop
744 loop = g_main_loop_new (NULL, FALSE);
745 mainloops = g_slist_prepend (mainloops, loop);
747 g_main_loop_run (loop);
753 * Exits the main GStreamer processing loop
759 g_error ("Quit more loops than there are");
761 GMainLoop *loop = mainloops->data;
762 mainloops = g_slist_delete_link (mainloops, mainloops);
763 g_main_loop_quit (loop);
764 g_main_loop_unref (loop);
770 * @major: pointer to a guint to store the major version number
771 * @minor: pointer to a guint to store the minor version number
772 * @micro: pointer to a guint to store the micro version number
774 * Gets the version number of the GStreamer library
777 gst_version (guint *major, guint *minor, guint *micro)
779 g_return_if_fail (major);
780 g_return_if_fail (minor);
781 g_return_if_fail (micro);
783 *major = GST_VERSION_MAJOR;
784 *minor = GST_VERSION_MINOR;
785 *micro = GST_VERSION_MICRO;