1 /* GStreamer 2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> 3 * 2000 Wim Taymans <wtay@chello.be> 4 * 2005 David A. Schleef <ds@schleef.org> 5 * 6 * gstregistry.c: handle registry 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public 19 * License along with this library; if not, write to the 20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24 /** 25 * SECTION:gstregistry 26 * @short_description: Abstract base class for management of #GstPlugin objects 27 * @see_also: #GstPlugin, #GstPluginFeature 28 * 29 * One registry holds the metadata of a set of plugins. 30 * 31 * <emphasis role="bold">Design:</emphasis> 32 * 33 * The #GstRegistry object is a list of plugins and some functions for dealing 34 * with them. Each #GstPlugin is matched 1-1 with a file on disk, and may or may 35 * not be loaded at a given time. 36 * 37 * The primary source, at all times, of plugin information is each plugin file 38 * itself. Thus, if an application wants information about a particular plugin, 39 * or wants to search for a feature that satisfies given criteria, the primary 40 * means of doing so is to load every plugin and look at the resulting 41 * information that is gathered in the default registry. Clearly, this is a time 42 * consuming process, so we cache information in the registry file. The format 43 * and location of the cache file is internal to gstreamer. 44 * 45 * On startup, plugins are searched for in the plugin search path. The following 46 * locations are checked in this order: 47 * <itemizedlist> 48 * <listitem> 49 * <para>location from --gst-plugin-path commandline option.</para> 50 * </listitem> 51 * <listitem> 52 * <para>the GST_PLUGIN_PATH environment variable.</para> 53 * </listitem> 54 * <listitem> 55 * <para>the GST_PLUGIN_SYSTEM_PATH environment variable.</para> 56 * </listitem> 57 * <listitem> 58 * <para>default locations (if GST_PLUGIN_SYSTEM_PATH is not set). Those 59 * default locations are: 60 * <filename>$XDG_DATA_HOME/gstreamer-$GST_API_VERSION/plugins/</filename> 61 * and <filename>$prefix/libs/gstreamer-$GST_API_VERSION/</filename>. 62 * <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html"> 63 * <filename>$XDG_DATA_HOME</filename></ulink> defaults to 64 * <filename>$HOME/.local/share</filename>. 65 * </para> 66 * </listitem> 67 * </itemizedlist> 68 * The registry cache file is loaded from 69 * <filename>$XDG_CACHE_HOME/gstreamer-$GST_API_VERSION/registry-$ARCH.bin</filename> 70 * (where 71 * <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html"> 72 * <filename>$XDG_CACHE_HOME</filename></ulink> defaults to 73 * <filename>$HOME/.cache</filename>) or the file listed in the GST_REGISTRY 74 * env var. One reason to change the registry location is for testing. 75 * 76 * For each plugin that is found in the plugin search path, there could be 3 77 * possibilities for cached information: 78 * <itemizedlist> 79 * <listitem> 80 * <para>the cache may not contain information about a given file.</para> 81 * </listitem> 82 * <listitem> 83 * <para>the cache may have stale information.</para> 84 * </listitem> 85 * <listitem> 86 * <para>the cache may have current information.</para> 87 * </listitem> 88 * </itemizedlist> 89 * 90 * In the first two cases, the plugin is loaded and the cache updated. In 91 * addition to these cases, the cache may have entries for plugins that are not 92 * relevant to the current process. These are marked as not available to the 93 * current process. If the cache is updated for whatever reason, it is marked 94 * dirty. 95 * 96 * A dirty cache is written out at the end of initialization. Each entry is 97 * checked to make sure the information is minimally valid. If not, the entry is 98 * simply dropped. 99 * 100 * <emphasis role="bold">Implementation notes:</emphasis> 101 * 102 * The "cache" and "registry" are different concepts and can represent 103 * different sets of plugins. For various reasons, at init time, the cache is 104 * stored in the default registry, and plugins not relevant to the current 105 * process are marked with the %GST_PLUGIN_FLAG_CACHED bit. These plugins are 106 * removed at the end of initialization. 107 */ 108 109 #ifdef HAVE_CONFIG_H 110 #include "config.h" 111 #endif 112 #include "gstconfig.h" 113 #include "gst_private.h" 114 #include <glib.h> 115 #include <sys/types.h> 116 #include <sys/stat.h> 117 #ifdef HAVE_UNISTD_H 118 #include <unistd.h> 119 #endif 120 #include <errno.h> 121 #include <stdio.h> 122 #include <string.h> 123 124 /* For g_stat () */ 125 #include <glib/gstdio.h> 126 127 #include "gstinfo.h" 128 #include "gsterror.h" 129 #include "gstregistry.h" 130 #ifndef GSTREAMER_LITE 131 #include "gstdeviceproviderfactory.h" 132 #endif // GSTREAMER_LITE 133 134 #include "gstpluginloader.h" 135 136 #include "gst-i18n-lib.h" 137 138 #include "gst.h" 139 #include "glib-compat-private.h" 140 141 #ifdef GSTREAMER_LITE 142 #define LIBGSTREAMER_LIB_NAME "gstreamer-lite" 143 #endif // GSTREAMER_LITE 144 145 146 #ifdef G_OS_WIN32 147 #include <windows.h> 148 extern HMODULE _priv_gst_dll_handle; 149 #endif 150 151 #if defined(GSTREAMER_LITE) && defined(HAVE_OSX) 152 #include <mach-o/dyld.h> 153 #include <mach-o/ldsyms.h> //defines _mh_dylib_header see man page for ld 154 #endif // GSTREAMER_LITE 155 156 #if defined (GSTREAMER_LITE) && defined(LINUX) 157 #include <link.h> 158 #include <dlfcn.h> 159 160 // For libav (libavcodec.so) 161 static const int AVCODEC_LIBAV_EXPLICIT_VERSIONS[] = { 53, 54, 55, 56 }; 162 // For ffmpeg (libavcodec-ffmpeg.so) 163 static const int AVCODEC_FFMPEG_EXPLICIT_VERSIONS[] = { 56 }; 164 // For libav or ffmpeg (libavcodec.so) 165 static const int AVCODEC_EXPLICIT_VERSIONS[] = { 57 }; 166 167 /* 168 * Callback passed to dl_iterate_phdr(): finds the path of 169 * LIBGSTREAMER_LIB_NAME and returns it in data which is actually 170 * a char**. 171 */ 172 static int dl_callback (struct dl_phdr_info *info, size_t size, void *data) 173 { 174 int result = 0; 175 176 if (NULL != info) 177 { 178 if (NULL != strstr (info->dlpi_name, LIBGSTREAMER_LIB_NAME)) 179 { 180 if (NULL != data) 181 { 182 char** name = (char**)data; 183 *name = (char*)info->dlpi_name; 184 } 185 186 result = 1; 187 } 188 } 189 190 return result; 191 } 192 #endif // GSTREAMER_LITE && LINUX 193 194 #define GST_CAT_DEFAULT GST_CAT_REGISTRY 195 196 struct _GstRegistryPrivate 197 { 198 GList *plugins; 199 GList *features; 200 201 #if 0 202 GList *paths; 203 #endif 204 205 int cache_file; 206 207 /* hash to speedup _lookup_feature_locked() */ 208 GHashTable *feature_hash; 209 /* hash to speedup _lookup */ 210 GHashTable *basename_hash; 211 212 /* updated whenever the feature list changes */ 213 guint32 cookie; 214 /* speedup for searching features */ 215 GList *element_factory_list; 216 guint32 efl_cookie; 217 GList *typefind_factory_list; 218 guint32 tfl_cookie; 219 GList *device_provider_factory_list; 220 guint32 dmfl_cookie; 221 }; 222 223 /* the one instance of the default registry and the mutex protecting the 224 * variable. */ 225 static GMutex _gst_registry_mutex; 226 static GstRegistry *_gst_registry_default = NULL; 227 228 /* defaults */ 229 #ifndef GSTREAMER_LITE 230 #define DEFAULT_FORK TRUE 231 #else // GSTREAMER_LITE 232 // For GSTREAMER_LITE do not use fork for registry since it may break things, because 233 // we do not use file to store registry and registry is kept in memory. 234 #define DEFAULT_FORK FALSE 235 #define LIBGSTREAMER_LIB_NAME "gstreamer-lite" 236 #endif // GSTREAMER_LITE 237 238 /* control the behaviour of registry rebuild */ 239 static gboolean _gst_enable_registry_fork = DEFAULT_FORK; 240 /* List of plugins that need preloading/reloading after scanning registry */ 241 extern GSList *_priv_gst_preload_plugins; 242 243 #ifndef GST_DISABLE_REGISTRY 244 /*set to TRUE when registry needn't to be updated */ 245 gboolean _priv_gst_disable_registry_update = FALSE; 246 extern GList *_priv_gst_plugin_paths; 247 248 /* Set to TRUE when the registry cache should be disabled */ 249 gboolean _gst_disable_registry_cache = FALSE; 250 251 static gboolean __registry_reuse_plugin_scanner = TRUE; 252 #endif 253 254 /* Element signals and args */ 255 enum 256 { 257 PLUGIN_ADDED, 258 FEATURE_ADDED, 259 LAST_SIGNAL 260 }; 261 262 #ifdef GSTREAMER_LITE 263 gchar *gstlite_plugins_list[] = 264 { 265 #ifdef LINUX 266 267 "libfxplugins", 268 "libavplugin", 269 #elif defined (G_OS_WIN32) 270 "fxplugins", 271 #elif defined (HAVE_OSX) 272 "libfxplugins", 273 #endif 274 NULL 275 }; 276 #endif // GSTREAMER_LITE 277 278 static void gst_registry_finalize (GObject * object); 279 280 static guint gst_registry_signals[LAST_SIGNAL] = { 0 }; 281 282 static GstPluginFeature *gst_registry_lookup_feature_locked (GstRegistry * 283 registry, const char *name); 284 static GstPlugin *gst_registry_lookup_bn_locked (GstRegistry * registry, 285 const char *basename); 286 287 #define gst_registry_parent_class parent_class 288 G_DEFINE_TYPE (GstRegistry, gst_registry, GST_TYPE_OBJECT); 289 290 static void 291 gst_registry_class_init (GstRegistryClass * klass) 292 { 293 GObjectClass *gobject_class; 294 295 gobject_class = (GObjectClass *) klass; 296 297 g_type_class_add_private (klass, sizeof (GstRegistryPrivate)); 298 299 /** 300 * GstRegistry::plugin-added: 301 * @registry: the registry that emitted the signal 302 * @plugin: the plugin that has been added 303 * 304 * Signals that a plugin has been added to the registry (possibly 305 * replacing a previously-added one by the same name) 306 */ 307 gst_registry_signals[PLUGIN_ADDED] = 308 g_signal_new ("plugin-added", G_TYPE_FROM_CLASS (klass), 309 G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, 310 G_TYPE_NONE, 1, GST_TYPE_PLUGIN); 311 312 /** 313 * GstRegistry::feature-added: 314 * @registry: the registry that emitted the signal 315 * @feature: the feature that has been added 316 * 317 * Signals that a feature has been added to the registry (possibly 318 * replacing a previously-added one by the same name) 319 */ 320 gst_registry_signals[FEATURE_ADDED] = 321 g_signal_new ("feature-added", G_TYPE_FROM_CLASS (klass), 322 G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, 323 G_TYPE_NONE, 1, GST_TYPE_PLUGIN_FEATURE); 324 325 gobject_class->finalize = gst_registry_finalize; 326 } 327 328 static void 329 gst_registry_init (GstRegistry * registry) 330 { 331 registry->priv = 332 G_TYPE_INSTANCE_GET_PRIVATE (registry, GST_TYPE_REGISTRY, 333 GstRegistryPrivate); 334 registry->priv->feature_hash = g_hash_table_new (g_str_hash, g_str_equal); 335 registry->priv->basename_hash = g_hash_table_new (g_str_hash, g_str_equal); 336 } 337 338 static void 339 gst_registry_finalize (GObject * object) 340 { 341 GstRegistry *registry = GST_REGISTRY (object); 342 GList *plugins, *p; 343 GList *features, *f; 344 345 plugins = registry->priv->plugins; 346 registry->priv->plugins = NULL; 347 348 GST_DEBUG_OBJECT (registry, "registry finalize"); 349 p = plugins; 350 while (p) { 351 GstPlugin *plugin = p->data; 352 353 if (plugin) { 354 GST_LOG_OBJECT (registry, "removing plugin %s", 355 gst_plugin_get_name (plugin)); 356 gst_object_unref (plugin); 357 } 358 p = g_list_next (p); 359 } 360 g_list_free (plugins); 361 362 features = registry->priv->features; 363 registry->priv->features = NULL; 364 365 f = features; 366 while (f) { 367 GstPluginFeature *feature = f->data; 368 369 if (feature) { 370 GST_LOG_OBJECT (registry, "removing feature %p (%s)", feature, 371 GST_OBJECT_NAME (feature)); 372 gst_object_unparent (GST_OBJECT_CAST (feature)); 373 } 374 f = g_list_next (f); 375 } 376 g_list_free (features); 377 378 g_hash_table_destroy (registry->priv->feature_hash); 379 registry->priv->feature_hash = NULL; 380 g_hash_table_destroy (registry->priv->basename_hash); 381 registry->priv->basename_hash = NULL; 382 383 if (registry->priv->element_factory_list) { 384 GST_DEBUG_OBJECT (registry, "Cleaning up cached element factory list"); 385 gst_plugin_feature_list_free (registry->priv->element_factory_list); 386 } 387 388 if (registry->priv->typefind_factory_list) { 389 GST_DEBUG_OBJECT (registry, "Cleaning up cached typefind factory list"); 390 gst_plugin_feature_list_free (registry->priv->typefind_factory_list); 391 } 392 393 if (registry->priv->device_provider_factory_list) { 394 GST_DEBUG_OBJECT (registry, 395 "Cleaning up cached device provider factory list"); 396 gst_plugin_feature_list_free (registry->priv->device_provider_factory_list); 397 } 398 399 G_OBJECT_CLASS (parent_class)->finalize (object); 400 } 401 402 /** 403 * gst_registry_get: 404 * 405 * Retrieves the singleton plugin registry. The caller does not own a 406 * reference on the registry, as it is alive as long as GStreamer is 407 * initialized. 408 * 409 * Returns: (transfer none): the #GstRegistry. 410 */ 411 GstRegistry * 412 gst_registry_get (void) 413 { 414 GstRegistry *registry; 415 416 g_mutex_lock (&_gst_registry_mutex); 417 if (G_UNLIKELY (!_gst_registry_default)) { 418 _gst_registry_default = g_object_newv (GST_TYPE_REGISTRY, 0, NULL); 419 gst_object_ref_sink (GST_OBJECT_CAST (_gst_registry_default)); 420 } 421 registry = _gst_registry_default; 422 g_mutex_unlock (&_gst_registry_mutex); 423 424 return registry; 425 } 426 427 #if 0 428 /** 429 * gst_registry_add_path: 430 * @registry: the registry to add the path to 431 * @path: the path to add to the registry 432 * 433 * Add the given path to the registry. The syntax of the 434 * path is specific to the registry. If the path has already been 435 * added, do nothing. 436 */ 437 void 438 gst_registry_add_path (GstRegistry * registry, const gchar * path) 439 { 440 g_return_if_fail (GST_IS_REGISTRY (registry)); 441 g_return_if_fail (path != NULL); 442 443 if (strlen (path) == 0) 444 goto empty_path; 445 446 GST_OBJECT_LOCK (registry); 447 if (g_list_find_custom (registry->priv->paths, path, (GCompareFunc) strcmp)) 448 goto was_added; 449 450 GST_INFO ("Adding plugin path: \"%s\"", path); 451 registry->priv->paths = 452 g_list_append (registry->priv->paths, g_strdup (path)); 453 GST_OBJECT_UNLOCK (registry); 454 455 return; 456 457 empty_path: 458 { 459 GST_INFO ("Ignoring empty plugin path"); 460 return; 461 } 462 was_added: 463 { 464 g_warning ("path %s already added to registry", path); 465 GST_OBJECT_UNLOCK (registry); 466 return; 467 } 468 } 469 470 /** 471 * gst_registry_get_path_list: 472 * @registry: the registry to get the pathlist of 473 * 474 * Get the list of paths for the given registry. 475 * 476 * Returns: (transfer container) (element-type char*): A #GList of paths as 477 * strings. g_list_free after use. 478 * 479 * MT safe. 480 */ 481 GList * 482 gst_registry_get_path_list (GstRegistry * registry) 483 { 484 GList *list; 485 486 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 487 488 GST_OBJECT_LOCK (registry); 489 /* We don't need to copy the strings, because they won't be deleted 490 * as long as the GstRegistry is around */ 491 list = g_list_copy (registry->priv->paths); 492 GST_OBJECT_UNLOCK (registry); 493 494 return list; 495 } 496 #endif 497 498 /** 499 * gst_registry_add_plugin: 500 * @registry: the registry to add the plugin to 501 * @plugin: (transfer full): the plugin to add 502 * 503 * Add the plugin to the registry. The plugin-added signal will be emitted. 504 * This function will sink @plugin. 505 * 506 * Returns: %TRUE on success. 507 * 508 * MT safe. 509 */ 510 gboolean 511 gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin) 512 { 513 GstPlugin *existing_plugin; 514 515 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); 516 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE); 517 518 GST_OBJECT_LOCK (registry); 519 if (G_LIKELY (plugin->basename)) { 520 /* we have a basename, see if we find the plugin */ 521 existing_plugin = 522 gst_registry_lookup_bn_locked (registry, plugin->basename); 523 if (existing_plugin) { 524 GST_DEBUG_OBJECT (registry, 525 "Replacing existing plugin \"%s\" %p with new plugin %p for filename \"%s\"", 526 GST_STR_NULL (existing_plugin->filename), existing_plugin, plugin, 527 GST_STR_NULL (plugin->filename)); 528 /* If the new plugin is blacklisted and the existing one isn't cached, do not 529 * accept if it's from a different location than the existing one */ 530 if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED) && 531 strcmp (plugin->filename, existing_plugin->filename)) { 532 GST_WARNING_OBJECT (registry, 533 "Not replacing plugin because new one (%s) is blacklisted but for a different location than existing one (%s)", 534 plugin->filename, existing_plugin->filename); 535 gst_object_unref (plugin); 536 GST_OBJECT_UNLOCK (registry); 537 return FALSE; 538 } 539 registry->priv->plugins = 540 g_list_remove (registry->priv->plugins, existing_plugin); 541 if (G_LIKELY (existing_plugin->basename)) 542 g_hash_table_remove (registry->priv->basename_hash, 543 existing_plugin->basename); 544 gst_object_unref (existing_plugin); 545 } 546 } 547 548 GST_DEBUG_OBJECT (registry, "adding plugin %p for filename \"%s\"", 549 plugin, GST_STR_NULL (plugin->filename)); 550 551 registry->priv->plugins = g_list_prepend (registry->priv->plugins, plugin); 552 if (G_LIKELY (plugin->basename)) 553 g_hash_table_replace (registry->priv->basename_hash, plugin->basename, 554 plugin); 555 556 gst_object_ref_sink (plugin); 557 GST_OBJECT_UNLOCK (registry); 558 559 GST_LOG_OBJECT (registry, "emitting plugin-added for filename \"%s\"", 560 GST_STR_NULL (plugin->filename)); 561 g_signal_emit (registry, gst_registry_signals[PLUGIN_ADDED], 0, plugin); 562 563 return TRUE; 564 } 565 566 static void 567 gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry, 568 GstPlugin * plugin) 569 { 570 GList *f; 571 572 g_return_if_fail (GST_IS_REGISTRY (registry)); 573 g_return_if_fail (GST_IS_PLUGIN (plugin)); 574 575 /* Remove all features for this plugin */ 576 f = registry->priv->features; 577 while (f != NULL) { 578 GList *next = g_list_next (f); 579 GstPluginFeature *feature = f->data; 580 581 if (G_UNLIKELY (feature && feature->plugin == plugin)) { 582 GST_DEBUG_OBJECT (registry, "removing feature %p (%s) for plugin %p (%s)", 583 feature, gst_plugin_feature_get_name (feature), plugin, 584 plugin->desc.name); 585 586 registry->priv->features = 587 g_list_delete_link (registry->priv->features, f); 588 g_hash_table_remove (registry->priv->feature_hash, 589 GST_OBJECT_NAME (feature)); 590 gst_object_unparent (GST_OBJECT_CAST (feature)); 591 } 592 f = next; 593 } 594 registry->priv->cookie++; 595 } 596 597 /** 598 * gst_registry_remove_plugin: 599 * @registry: the registry to remove the plugin from 600 * @plugin: (transfer none): the plugin to remove 601 * 602 * Remove the plugin from the registry. 603 * 604 * MT safe. 605 */ 606 void 607 gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin) 608 { 609 g_return_if_fail (GST_IS_REGISTRY (registry)); 610 g_return_if_fail (GST_IS_PLUGIN (plugin)); 611 612 GST_DEBUG_OBJECT (registry, "removing plugin %p (%s)", 613 plugin, gst_plugin_get_name (plugin)); 614 615 GST_OBJECT_LOCK (registry); 616 registry->priv->plugins = g_list_remove (registry->priv->plugins, plugin); 617 if (G_LIKELY (plugin->basename)) 618 g_hash_table_remove (registry->priv->basename_hash, plugin->basename); 619 gst_registry_remove_features_for_plugin_unlocked (registry, plugin); 620 GST_OBJECT_UNLOCK (registry); 621 gst_object_unref (plugin); 622 } 623 624 /** 625 * gst_registry_add_feature: 626 * @registry: the registry to add the plugin to 627 * @feature: (transfer full): the feature to add 628 * 629 * Add the feature to the registry. The feature-added signal will be emitted. 630 * This function sinks @feature. 631 * 632 * Returns: %TRUE on success. 633 * 634 * MT safe. 635 */ 636 gboolean 637 gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature) 638 { 639 GstPluginFeature *existing_feature; 640 641 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); 642 g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE); 643 g_return_val_if_fail (GST_OBJECT_NAME (feature) != NULL, FALSE); 644 g_return_val_if_fail (feature->plugin_name != NULL, FALSE); 645 646 GST_OBJECT_LOCK (registry); 647 existing_feature = gst_registry_lookup_feature_locked (registry, 648 GST_OBJECT_NAME (feature)); 649 if (G_UNLIKELY (existing_feature)) { 650 GST_DEBUG_OBJECT (registry, "replacing existing feature %p (%s)", 651 existing_feature, GST_OBJECT_NAME (feature)); 652 /* Remove the existing feature from the list now, before we insert the new 653 * one, but don't unref yet because the hash is still storing a reference to 654 * it. */ 655 registry->priv->features = 656 g_list_remove (registry->priv->features, existing_feature); 657 } 658 659 GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, 660 GST_OBJECT_NAME (feature)); 661 662 registry->priv->features = g_list_prepend (registry->priv->features, feature); 663 g_hash_table_replace (registry->priv->feature_hash, GST_OBJECT_NAME (feature), 664 feature); 665 666 if (G_UNLIKELY (existing_feature)) { 667 /* We unref now. No need to remove the feature name from the hash table, it 668 * got replaced by the new feature */ 669 gst_object_unparent (GST_OBJECT_CAST (existing_feature)); 670 } 671 672 gst_object_set_parent (GST_OBJECT_CAST (feature), GST_OBJECT_CAST (registry)); 673 674 registry->priv->cookie++; 675 GST_OBJECT_UNLOCK (registry); 676 677 GST_LOG_OBJECT (registry, "emitting feature-added for %s", 678 GST_OBJECT_NAME (feature)); 679 g_signal_emit (registry, gst_registry_signals[FEATURE_ADDED], 0, feature); 680 681 return TRUE; 682 } 683 684 /** 685 * gst_registry_remove_feature: 686 * @registry: the registry to remove the feature from 687 * @feature: (transfer none): the feature to remove 688 * 689 * Remove the feature from the registry. 690 * 691 * MT safe. 692 */ 693 void 694 gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature) 695 { 696 g_return_if_fail (GST_IS_REGISTRY (registry)); 697 g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature)); 698 699 GST_DEBUG_OBJECT (registry, "removing feature %p (%s)", 700 feature, gst_plugin_feature_get_name (feature)); 701 702 GST_OBJECT_LOCK (registry); 703 registry->priv->features = g_list_remove (registry->priv->features, feature); 704 g_hash_table_remove (registry->priv->feature_hash, GST_OBJECT_NAME (feature)); 705 registry->priv->cookie++; 706 GST_OBJECT_UNLOCK (registry); 707 708 gst_object_unparent ((GstObject *) feature); 709 } 710 711 /** 712 * gst_registry_plugin_filter: 713 * @registry: registry to query 714 * @filter: (scope call): the filter to use 715 * @first: only return first match 716 * @user_data: (closure): user data passed to the filter function 717 * 718 * Runs a filter against all plugins in the registry and returns a #GList with 719 * the results. If the first flag is set, only the first match is 720 * returned (as a list with a single object). 721 * Every plugin is reffed; use gst_plugin_list_free() after use, which 722 * will unref again. 723 * 724 * Returns: (transfer full) (element-type Gst.Plugin): a #GList of #GstPlugin. 725 * Use gst_plugin_list_free() after usage. 726 * 727 * MT safe. 728 */ 729 GList * 730 gst_registry_plugin_filter (GstRegistry * registry, 731 GstPluginFilter filter, gboolean first, gpointer user_data) 732 { 733 GList *list = NULL; 734 735 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 736 737 GST_OBJECT_LOCK (registry); 738 { 739 const GList *walk; 740 741 for (walk = registry->priv->plugins; walk != NULL; walk = walk->next) { 742 GstPlugin *plugin = walk->data; 743 744 if (filter == NULL || filter (plugin, user_data)) { 745 list = g_list_prepend (list, gst_object_ref (plugin)); 746 747 if (first) 748 break; 749 } 750 } 751 } 752 GST_OBJECT_UNLOCK (registry); 753 754 return list; 755 } 756 757 typedef struct 758 { 759 const gchar *name; 760 GType type; 761 } GstTypeNameData; 762 763 static gboolean 764 gst_plugin_feature_type_name_filter (GstPluginFeature * feature, 765 GstTypeNameData * data) 766 { 767 g_assert (GST_IS_PLUGIN_FEATURE (feature)); 768 769 return ((data->type == 0 || data->type == G_OBJECT_TYPE (feature)) && 770 (data->name == NULL || !strcmp (data->name, GST_OBJECT_NAME (feature)))); 771 } 772 773 /* returns TRUE if the list was changed 774 * 775 * Must be called with the object lock taken */ 776 static gboolean 777 gst_registry_get_feature_list_or_create (GstRegistry * registry, 778 GList ** previous, guint32 * cookie, GType type) 779 { 780 gboolean res = FALSE; 781 GstRegistryPrivate *priv = registry->priv; 782 783 if (G_UNLIKELY (!*previous || priv->cookie != *cookie)) { 784 GstTypeNameData data; 785 const GList *walk; 786 787 if (*previous) { 788 gst_plugin_feature_list_free (*previous); 789 *previous = NULL; 790 } 791 792 data.type = type; 793 data.name = NULL; 794 795 for (walk = registry->priv->features; walk != NULL; walk = walk->next) { 796 GstPluginFeature *feature = walk->data; 797 798 if (gst_plugin_feature_type_name_filter (feature, &data)) { 799 *previous = g_list_prepend (*previous, gst_object_ref (feature)); 800 } 801 } 802 803 *cookie = priv->cookie; 804 res = TRUE; 805 } 806 807 return res; 808 } 809 810 static gint 811 type_find_factory_rank_cmp (const GstPluginFeature * fac1, 812 const GstPluginFeature * fac2) 813 { 814 if (G_LIKELY (fac1->rank != fac2->rank)) 815 return fac2->rank - fac1->rank; 816 817 /* to make the order in which things happen more deterministic, 818 * sort by name when the ranks are the same. */ 819 return strcmp (GST_OBJECT_NAME (fac1), GST_OBJECT_NAME (fac2)); 820 } 821 822 static GList * 823 gst_registry_get_element_factory_list (GstRegistry * registry) 824 { 825 GList *list; 826 827 GST_OBJECT_LOCK (registry); 828 829 gst_registry_get_feature_list_or_create (registry, 830 ®istry->priv->element_factory_list, ®istry->priv->efl_cookie, 831 GST_TYPE_ELEMENT_FACTORY); 832 833 /* Return reffed copy */ 834 list = gst_plugin_feature_list_copy (registry->priv->element_factory_list); 835 836 GST_OBJECT_UNLOCK (registry); 837 838 return list; 839 } 840 841 static GList * 842 gst_registry_get_typefind_factory_list (GstRegistry * registry) 843 { 844 GList *list; 845 846 GST_OBJECT_LOCK (registry); 847 848 if (G_UNLIKELY (gst_registry_get_feature_list_or_create (registry, 849 ®istry->priv->typefind_factory_list, 850 ®istry->priv->tfl_cookie, GST_TYPE_TYPE_FIND_FACTORY))) 851 registry->priv->typefind_factory_list = 852 g_list_sort (registry->priv->typefind_factory_list, 853 (GCompareFunc) type_find_factory_rank_cmp); 854 855 /* Return reffed copy */ 856 list = gst_plugin_feature_list_copy (registry->priv->typefind_factory_list); 857 858 GST_OBJECT_UNLOCK (registry); 859 860 return list; 861 } 862 863 #ifndef GSTREAMER_LITE 864 static GList * 865 gst_registry_get_device_provider_factory_list (GstRegistry * registry) 866 { 867 GList *list; 868 869 GST_OBJECT_LOCK (registry); 870 871 gst_registry_get_feature_list_or_create (registry, 872 ®istry->priv->device_provider_factory_list, 873 ®istry->priv->dmfl_cookie, GST_TYPE_DEVICE_PROVIDER_FACTORY); 874 875 /* Return reffed copy */ 876 list = 877 gst_plugin_feature_list_copy (registry-> 878 priv->device_provider_factory_list); 879 880 GST_OBJECT_UNLOCK (registry); 881 882 return list; 883 } 884 #endif // GSTREAMER_LITE 885 886 /** 887 * gst_registry_feature_filter: 888 * @registry: registry to query 889 * @filter: (scope call): the filter to use 890 * @first: only return first match 891 * @user_data: (closure): user data passed to the filter function 892 * 893 * Runs a filter against all features of the plugins in the registry 894 * and returns a GList with the results. 895 * If the first flag is set, only the first match is 896 * returned (as a list with a single object). 897 * 898 * Returns: (transfer full) (element-type Gst.PluginFeature): a #GList of 899 * #GstPluginFeature. Use gst_plugin_feature_list_free() after usage. 900 * 901 * MT safe. 902 */ 903 GList * 904 gst_registry_feature_filter (GstRegistry * registry, 905 GstPluginFeatureFilter filter, gboolean first, gpointer user_data) 906 { 907 GList *list = NULL; 908 909 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 910 911 GST_OBJECT_LOCK (registry); 912 { 913 const GList *walk; 914 915 for (walk = registry->priv->features; walk != NULL; walk = walk->next) { 916 GstPluginFeature *feature = walk->data; 917 918 if (filter == NULL || filter (feature, user_data)) { 919 list = g_list_prepend (list, gst_object_ref (feature)); 920 921 if (first) 922 break; 923 } 924 } 925 } 926 GST_OBJECT_UNLOCK (registry); 927 928 return list; 929 } 930 931 static gboolean 932 gst_registry_plugin_name_filter (GstPlugin * plugin, const gchar * name) 933 { 934 return (plugin->desc.name && !strcmp (plugin->desc.name, name)); 935 } 936 937 /** 938 * gst_registry_find_plugin: 939 * @registry: the registry to search 940 * @name: the plugin name to find 941 * 942 * Find the plugin with the given name in the registry. 943 * The plugin will be reffed; caller is responsible for unreffing. 944 * 945 * Returns: (transfer full) (nullable): the plugin with the given name 946 * or %NULL if the plugin was not found. gst_object_unref() after 947 * usage. 948 * 949 * MT safe. 950 */ 951 GstPlugin * 952 gst_registry_find_plugin (GstRegistry * registry, const gchar * name) 953 { 954 GList *walk; 955 GstPlugin *result = NULL; 956 957 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 958 g_return_val_if_fail (name != NULL, NULL); 959 960 walk = gst_registry_plugin_filter (registry, 961 (GstPluginFilter) gst_registry_plugin_name_filter, TRUE, (gpointer) name); 962 if (walk) { 963 result = GST_PLUGIN_CAST (walk->data); 964 965 gst_object_ref (result); 966 gst_plugin_list_free (walk); 967 } 968 969 return result; 970 } 971 972 /** 973 * gst_registry_find_feature: 974 * @registry: the registry to search 975 * @name: the pluginfeature name to find 976 * @type: the pluginfeature type to find 977 * 978 * Find the pluginfeature with the given name and type in the registry. 979 * 980 * Returns: (transfer full) (nullable): the pluginfeature with the 981 * given name and type or %NULL if the plugin was not 982 * found. gst_object_unref() after usage. 983 * 984 * MT safe. 985 */ 986 GstPluginFeature * 987 gst_registry_find_feature (GstRegistry * registry, const gchar * name, 988 GType type) 989 { 990 GstPluginFeature *feature = NULL; 991 992 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 993 g_return_val_if_fail (name != NULL, NULL); 994 g_return_val_if_fail (g_type_is_a (type, GST_TYPE_PLUGIN_FEATURE), NULL); 995 996 feature = gst_registry_lookup_feature (registry, name); 997 if (feature && !g_type_is_a (G_TYPE_FROM_INSTANCE (feature), type)) { 998 gst_object_unref (feature); 999 feature = NULL; 1000 } 1001 1002 return feature; 1003 } 1004 1005 /** 1006 * gst_registry_get_feature_list: 1007 * @registry: a #GstRegistry 1008 * @type: a #GType. 1009 * 1010 * Retrieves a #GList of #GstPluginFeature of @type. 1011 * 1012 * Returns: (transfer full) (element-type Gst.PluginFeature): a #GList of 1013 * #GstPluginFeature of @type. Use gst_plugin_feature_list_free() after use 1014 * 1015 * MT safe. 1016 */ 1017 GList * 1018 gst_registry_get_feature_list (GstRegistry * registry, GType type) 1019 { 1020 GstTypeNameData data; 1021 1022 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 1023 g_return_val_if_fail (g_type_is_a (type, GST_TYPE_PLUGIN_FEATURE), NULL); 1024 1025 /* Speed up */ 1026 if (type == GST_TYPE_ELEMENT_FACTORY) 1027 return gst_registry_get_element_factory_list (registry); 1028 else if (type == GST_TYPE_TYPE_FIND_FACTORY) 1029 return gst_registry_get_typefind_factory_list (registry); 1030 #ifndef GSTREAMER_LITE 1031 else if (type == GST_TYPE_DEVICE_PROVIDER_FACTORY) 1032 return gst_registry_get_device_provider_factory_list (registry); 1033 #endif // GSTREAMER_LITE 1034 1035 data.type = type; 1036 data.name = NULL; 1037 1038 return gst_registry_feature_filter (registry, 1039 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter, 1040 FALSE, &data); 1041 } 1042 1043 /** 1044 * gst_registry_get_plugin_list: 1045 * @registry: the registry to search 1046 * 1047 * Get a copy of all plugins registered in the given registry. The refcount 1048 * of each element in the list in incremented. 1049 * 1050 * Returns: (transfer full) (element-type Gst.Plugin): a #GList of #GstPlugin. 1051 * Use gst_plugin_list_free() after usage. 1052 * 1053 * MT safe. 1054 */ 1055 GList * 1056 gst_registry_get_plugin_list (GstRegistry * registry) 1057 { 1058 GList *list; 1059 GList *g; 1060 1061 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 1062 1063 GST_OBJECT_LOCK (registry); 1064 list = g_list_copy (registry->priv->plugins); 1065 for (g = list; g; g = g->next) { 1066 gst_object_ref (GST_PLUGIN_CAST (g->data)); 1067 } 1068 GST_OBJECT_UNLOCK (registry); 1069 1070 return list; 1071 } 1072 1073 static GstPluginFeature * 1074 gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name) 1075 { 1076 return g_hash_table_lookup (registry->priv->feature_hash, name); 1077 } 1078 1079 /** 1080 * gst_registry_lookup_feature: 1081 * @registry: a #GstRegistry 1082 * @name: a #GstPluginFeature name 1083 * 1084 * Find a #GstPluginFeature with @name in @registry. 1085 * 1086 * Returns: (transfer full): a #GstPluginFeature with its refcount incremented, 1087 * use gst_object_unref() after usage. 1088 * 1089 * MT safe. 1090 */ 1091 GstPluginFeature * 1092 gst_registry_lookup_feature (GstRegistry * registry, const char *name) 1093 { 1094 GstPluginFeature *feature; 1095 1096 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 1097 g_return_val_if_fail (name != NULL, NULL); 1098 1099 GST_OBJECT_LOCK (registry); 1100 feature = gst_registry_lookup_feature_locked (registry, name); 1101 if (feature) 1102 gst_object_ref (feature); 1103 GST_OBJECT_UNLOCK (registry); 1104 1105 return feature; 1106 } 1107 1108 static GstPlugin * 1109 gst_registry_lookup_bn_locked (GstRegistry * registry, const char *basename) 1110 { 1111 return g_hash_table_lookup (registry->priv->basename_hash, basename); 1112 } 1113 1114 static GstPlugin * 1115 gst_registry_lookup_bn (GstRegistry * registry, const char *basename) 1116 { 1117 GstPlugin *plugin; 1118 1119 GST_OBJECT_LOCK (registry); 1120 plugin = gst_registry_lookup_bn_locked (registry, basename); 1121 if (plugin) 1122 gst_object_ref (plugin); 1123 GST_OBJECT_UNLOCK (registry); 1124 1125 return plugin; 1126 } 1127 1128 /** 1129 * gst_registry_lookup: 1130 * @registry: the registry to look up in 1131 * @filename: the name of the file to look up 1132 * 1133 * Look up a plugin in the given registry with the given filename. 1134 * If found, plugin is reffed. 1135 * 1136 * Returns: (transfer full) (nullable): the #GstPlugin if found, or 1137 * %NULL if not. gst_object_unref() after usage. 1138 */ 1139 GstPlugin * 1140 gst_registry_lookup (GstRegistry * registry, const char *filename) 1141 { 1142 GstPlugin *plugin; 1143 gchar *basename; 1144 1145 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 1146 g_return_val_if_fail (filename != NULL, NULL); 1147 1148 basename = g_path_get_basename (filename); 1149 if (G_UNLIKELY (basename == NULL)) 1150 return NULL; 1151 1152 plugin = gst_registry_lookup_bn (registry, basename); 1153 1154 g_free (basename); 1155 1156 return plugin; 1157 } 1158 1159 typedef enum 1160 { 1161 REGISTRY_SCAN_HELPER_NOT_STARTED = 0, 1162 REGISTRY_SCAN_HELPER_DISABLED, 1163 REGISTRY_SCAN_HELPER_RUNNING 1164 } GstRegistryScanHelperState; 1165 1166 typedef struct 1167 { 1168 GstRegistry *registry; 1169 GstRegistryScanHelperState helper_state; 1170 GstPluginLoader *helper; 1171 gboolean changed; 1172 } GstRegistryScanContext; 1173 1174 static void 1175 init_scan_context (GstRegistryScanContext * context, GstRegistry * registry) 1176 { 1177 gboolean do_fork; 1178 1179 context->registry = registry; 1180 1181 /* see if forking is enabled and set up the scan helper state accordingly */ 1182 do_fork = _gst_enable_registry_fork; 1183 if (do_fork) { 1184 const gchar *fork_env; 1185 1186 /* forking enabled, see if it is disabled with an env var */ 1187 if ((fork_env = g_getenv ("GST_REGISTRY_FORK"))) { 1188 /* fork enabled for any value different from "no" */ 1189 do_fork = strcmp (fork_env, "no") != 0; 1190 } 1191 } 1192 1193 if (do_fork) 1194 context->helper_state = REGISTRY_SCAN_HELPER_NOT_STARTED; 1195 else 1196 context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; 1197 1198 context->helper = NULL; 1199 context->changed = FALSE; 1200 } 1201 1202 static void 1203 clear_scan_context (GstRegistryScanContext * context) 1204 { 1205 if (context->helper) { 1206 context->changed |= _priv_gst_plugin_loader_funcs.destroy (context->helper); 1207 context->helper = NULL; 1208 } 1209 } 1210 1211 static gboolean 1212 gst_registry_scan_plugin_file (GstRegistryScanContext * context, 1213 const gchar * filename, off_t file_size, time_t file_mtime) 1214 { 1215 gboolean changed = FALSE; 1216 GstPlugin *newplugin = NULL; 1217 1218 #ifdef G_OS_WIN32 1219 /* Disable external plugin loader on Windows until it is ported properly. */ 1220 context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; 1221 #endif 1222 1223 1224 /* Have a plugin to load - see if the scan-helper needs starting */ 1225 if (context->helper_state == REGISTRY_SCAN_HELPER_NOT_STARTED) { 1226 GST_DEBUG ("Starting plugin scanner for file %s", filename); 1227 context->helper = _priv_gst_plugin_loader_funcs.create (context->registry); 1228 if (context->helper != NULL) 1229 context->helper_state = REGISTRY_SCAN_HELPER_RUNNING; 1230 else { 1231 GST_WARNING ("Failed starting plugin scanner. Scanning in-process"); 1232 context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; 1233 } 1234 } 1235 1236 if (context->helper_state == REGISTRY_SCAN_HELPER_RUNNING) { 1237 GST_DEBUG ("Using scan-helper to load plugin %s", filename); 1238 if (!_priv_gst_plugin_loader_funcs.load (context->helper, 1239 filename, file_size, file_mtime)) { 1240 g_warning ("External plugin loader failed. This most likely means that " 1241 "the plugin loader helper binary was not found or could not be run. " 1242 "You might need to set the GST_PLUGIN_SCANNER environment variable " 1243 "if your setup is unusual. This should normally not be required " 1244 "though."); 1245 context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; 1246 } 1247 } 1248 1249 /* Check if the helper is disabled (or just got disabled above) */ 1250 if (context->helper_state == REGISTRY_SCAN_HELPER_DISABLED) { 1251 /* Load plugin the old fashioned way... */ 1252 1253 /* We don't use a GError here because a failure to load some shared 1254 * objects as plugins is normal (particularly in the uninstalled case) 1255 */ 1256 newplugin = gst_plugin_load_file (filename, NULL); 1257 } 1258 1259 if (newplugin) { 1260 GST_DEBUG_OBJECT (context->registry, "marking new plugin %p as registered", 1261 newplugin); 1262 newplugin->registered = TRUE; 1263 gst_object_unref (newplugin); 1264 changed = TRUE; 1265 } 1266 #ifndef GST_DISABLE_REGISTRY 1267 if (!__registry_reuse_plugin_scanner) { 1268 clear_scan_context (context); 1269 context->helper_state = REGISTRY_SCAN_HELPER_NOT_STARTED; 1270 } 1271 #endif 1272 1273 return changed; 1274 } 1275 1276 #ifndef GSTREAMER_LITE 1277 static gboolean 1278 is_blacklisted_hidden_directory (const gchar * dirent) 1279 { 1280 if (G_LIKELY (dirent[0] != '.')) 1281 return FALSE; 1282 1283 /* skip the .debug directory, these contain elf files that are not 1284 * useful or worse, can crash dlopen () */ 1285 if (strcmp (dirent, ".debug") == 0) 1286 return TRUE; 1287 1288 /* can also skip .git and .deps dirs, those won't contain useful files. 1289 * This speeds up scanning a bit in uninstalled setups. */ 1290 if (strcmp (dirent, ".git") == 0 || strcmp (dirent, ".deps") == 0) 1291 return TRUE; 1292 1293 return FALSE; 1294 } 1295 #endif 1296 1297 static gboolean 1298 gst_registry_scan_path_level (GstRegistryScanContext * context, 1299 const gchar * path, int level) 1300 { 1301 #ifndef GSTREAMER_LITE 1302 GDir *dir; 1303 const gchar *dirent; 1304 #endif // GSTREAMER_LITE 1305 gchar *filename; 1306 GstPlugin *plugin; 1307 gboolean changed = FALSE; 1308 #ifdef GSTREAMER_LITE 1309 gint gstlite_plugins_list_index = 0; 1310 struct stat file_status; 1311 gchar *filename_partial; 1312 #ifdef LINUX 1313 void *avcHandle = NULL; 1314 gboolean isAVCFFMPEG = FALSE; 1315 #endif // LINUX 1316 #endif // GSTREAMER_LITE 1317 1318 #ifndef GSTREAMER_LITE 1319 dir = g_dir_open (path, 0, NULL); 1320 if (!dir) 1321 return FALSE; 1322 1323 while ((dirent = g_dir_read_name (dir))) { 1324 GStatBuf file_status; 1325 1326 filename = g_build_filename (path, dirent, NULL); 1327 if (g_stat (filename, &file_status) < 0) { 1328 /* Plugin will be removed from cache after the scan completes if it 1329 * is still marked 'cached' */ 1330 g_free (filename); 1331 continue; 1332 } 1333 1334 if (file_status.st_mode & S_IFDIR) { 1335 if (G_UNLIKELY (is_blacklisted_hidden_directory (dirent))) { 1336 GST_TRACE_OBJECT (context->registry, "ignoring %s directory", dirent); 1337 g_free (filename); 1338 continue; 1339 } 1340 /* FIXME 0.11: Don't recurse into directories, this behaviour 1341 * is inconsistent with other PATH environment variables 1342 */ 1343 if (level > 0) { 1344 GST_LOG_OBJECT (context->registry, "recursing into directory %s", 1345 filename); 1346 changed |= gst_registry_scan_path_level (context, filename, level - 1); 1347 } else { 1348 GST_LOG_OBJECT (context->registry, "not recursing into directory %s, " 1349 "recursion level too deep", filename); 1350 } 1351 g_free (filename); 1352 continue; 1353 } 1354 if (!(file_status.st_mode & S_IFREG)) { 1355 GST_TRACE_OBJECT (context->registry, "%s is not a regular file, ignoring", 1356 filename); 1357 g_free (filename); 1358 continue; 1359 } 1360 if (!g_str_has_suffix (dirent, G_MODULE_SUFFIX) 1361 #ifdef GST_EXTRA_MODULE_SUFFIX 1362 && !g_str_has_suffix (dirent, GST_EXTRA_MODULE_SUFFIX) 1363 #endif 1364 ) { 1365 GST_TRACE_OBJECT (context->registry, 1366 "extension is not recognized as module file, ignoring file %s", 1367 filename); 1368 g_free (filename); 1369 continue; 1370 } 1371 #else // GSTREAMER_LITE 1372 1373 for (gstlite_plugins_list_index = 0; gstlite_plugins_list[gstlite_plugins_list_index] != NULL; gstlite_plugins_list_index++) { 1374 filename_partial = g_build_filename (path, gstlite_plugins_list[gstlite_plugins_list_index], NULL); 1375 #ifdef LINUX 1376 if (g_str_has_suffix(filename_partial, "libavplugin")) { // Check libav version and load correspondent module. 1377 int plugin_version = 0; 1378 // Look for libavcodec and check its version to figure out if it is 1379 // libav or ffmpeg. Starting from 57 and up 1380 int vi = (sizeof(AVCODEC_EXPLICIT_VERSIONS)/sizeof(AVCODEC_EXPLICIT_VERSIONS[0])); 1381 while(!avcHandle && --vi >= 0) { 1382 int version = AVCODEC_EXPLICIT_VERSIONS[vi]; 1383 gchar* libname = g_strdup_printf("libavcodec.so.%d", version); 1384 avcHandle = dlopen(libname, RTLD_NOW); 1385 g_free(libname); 1386 } 1387 1388 // Check if it is libav or ffmpeg 1389 if (avcHandle) { 1390 unsigned int (*av_version)(void); 1391 av_version = dlsym(avcHandle, "avcodec_version"); 1392 if (av_version != NULL) { 1393 unsigned int version = (*av_version)(); 1394 unsigned int micro = version & 0xFF; 1395 if (micro >= 100) 1396 isAVCFFMPEG = TRUE; 1397 plugin_version = AVCODEC_EXPLICIT_VERSIONS[vi]; 1398 } else { // Something wrong 1399 dlclose(avcHandle); 1400 avcHandle = NULL; 1401 } 1402 } 1403 1404 // Look for libavcodec-ffmpeg. For 56 only 1405 if (avcHandle == NULL) { 1406 vi = (sizeof(AVCODEC_FFMPEG_EXPLICIT_VERSIONS)/sizeof(AVCODEC_FFMPEG_EXPLICIT_VERSIONS[0])); 1407 while(!avcHandle && --vi >= 0) { 1408 int version = AVCODEC_FFMPEG_EXPLICIT_VERSIONS[vi]; 1409 gchar* libname = g_strdup_printf("libavcodec-ffmpeg.so.%d", version); 1410 avcHandle = dlopen(libname, RTLD_NOW); 1411 g_free(libname); 1412 } 1413 1414 if (avcHandle) { 1415 plugin_version = AVCODEC_FFMPEG_EXPLICIT_VERSIONS[vi]; 1416 isAVCFFMPEG = TRUE; 1417 } 1418 } 1419 1420 // Looks for libav 56 and below 1421 if (avcHandle == NULL) { 1422 vi = (sizeof(AVCODEC_LIBAV_EXPLICIT_VERSIONS)/sizeof(AVCODEC_LIBAV_EXPLICIT_VERSIONS[0])); 1423 while(!avcHandle && --vi >= 0) { 1424 int version = AVCODEC_LIBAV_EXPLICIT_VERSIONS[vi]; 1425 gchar* libname = g_strdup_printf("libavcodec.so.%d", version); 1426 avcHandle = dlopen(libname, RTLD_NOW); 1427 g_free(libname); 1428 } 1429 1430 if (avcHandle) { 1431 plugin_version = AVCODEC_LIBAV_EXPLICIT_VERSIONS[vi]; 1432 } 1433 } 1434 1435 if (avcHandle) { 1436 dlclose(avcHandle); 1437 avcHandle = NULL; 1438 1439 // Try simple name first. OpenJDK build may contain the latest bits. 1440 filename = g_strdup_printf("%s%s", filename_partial, GST_EXTRA_MODULE_SUFFIX); 1441 if (g_stat (filename, &file_status) < 0) { // Not available, create a versioned filename 1442 g_free(filename); 1443 if (isAVCFFMPEG) 1444 filename = g_strdup_printf("%s-ffmpeg-%d%s", filename_partial, plugin_version, GST_EXTRA_MODULE_SUFFIX); 1445 else 1446 filename = g_strdup_printf("%s-%d%s", filename_partial, plugin_version, GST_EXTRA_MODULE_SUFFIX); 1447 } 1448 } else { 1449 g_free(filename_partial); 1450 continue; // No libavcodec.so installed. 1451 } 1452 } else { 1453 filename = g_strconcat(filename_partial, GST_EXTRA_MODULE_SUFFIX, NULL); 1454 } 1455 #else 1456 filename = g_strconcat(filename_partial, GST_EXTRA_MODULE_SUFFIX, NULL); 1457 #endif 1458 g_free(filename_partial); 1459 1460 if (g_stat (filename, &file_status) < 0) { 1461 /* Plugin will be removed from cache after the scan completes if it 1462 * is still marked 'cached' */ 1463 g_free (filename); 1464 continue; 1465 } 1466 #endif // GSTREAMER_LITE 1467 1468 GST_LOG_OBJECT (context->registry, "file %s looks like a possible module", 1469 filename); 1470 1471 #ifndef GSTREAMER_LITE 1472 /* try to avoid unnecessary plugin-move pain */ 1473 if (g_str_has_prefix (dirent, "libgstvalve") || 1474 g_str_has_prefix (dirent, "libgstselector")) { 1475 GST_WARNING_OBJECT (context->registry, "ignoring old plugin %s which " 1476 "has been merged into the corelements plugin", filename); 1477 /* Plugin will be removed from cache after the scan completes if it 1478 * is still marked 'cached' */ 1479 g_free (filename); 1480 continue; 1481 } 1482 1483 /* plug-ins are considered unique by basename; if the given name 1484 * was already seen by the registry, we ignore it */ 1485 plugin = gst_registry_lookup_bn (context->registry, dirent); 1486 #else 1487 plugin = gst_registry_lookup (context->registry, filename); 1488 #endif 1489 if (plugin) { 1490 gboolean env_vars_changed, deps_changed = FALSE; 1491 1492 if (plugin->registered) { 1493 GST_DEBUG_OBJECT (context->registry, 1494 "plugin already registered from path \"%s\"", 1495 GST_STR_NULL (plugin->filename)); 1496 g_free (filename); 1497 gst_object_unref (plugin); 1498 continue; 1499 } 1500 1501 env_vars_changed = _priv_plugin_deps_env_vars_changed (plugin); 1502 1503 /* If a file with a certain basename is seen on a different path, 1504 * update the plugin to ensure the registry cache will reflect up 1505 * to date information */ 1506 1507 if (plugin->file_mtime == file_status.st_mtime && 1508 plugin->file_size == file_status.st_size && !env_vars_changed && 1509 !(deps_changed = _priv_plugin_deps_files_changed (plugin)) && 1510 !strcmp (plugin->filename, filename)) { 1511 GST_LOG_OBJECT (context->registry, "file %s cached", filename); 1512 GST_OBJECT_FLAG_UNSET (plugin, GST_PLUGIN_FLAG_CACHED); 1513 GST_LOG_OBJECT (context->registry, 1514 "marking plugin %p as registered as %s", plugin, filename); 1515 plugin->registered = TRUE; 1516 } else { 1517 GST_INFO_OBJECT (context->registry, "cached info for %s is stale", 1518 filename); 1519 GST_DEBUG_OBJECT (context->registry, "mtime %" G_GINT64_FORMAT " != %" 1520 G_GINT64_FORMAT " or size %" G_GINT64_FORMAT " != %" 1521 G_GINT64_FORMAT " or external dependency env_vars changed: %d or" 1522 " external dependencies changed: %d or old path %s != new path %s", 1523 (gint64) plugin->file_mtime, (gint64) file_status.st_mtime, 1524 (gint64) plugin->file_size, (gint64) file_status.st_size, 1525 env_vars_changed, deps_changed, plugin->filename, filename); 1526 gst_registry_remove_plugin (context->registry, plugin); 1527 changed |= gst_registry_scan_plugin_file (context, filename, 1528 file_status.st_size, file_status.st_mtime); 1529 } 1530 gst_object_unref (plugin); 1531 1532 } else { 1533 GST_DEBUG_OBJECT (context->registry, "file %s not yet in registry", 1534 filename); 1535 changed |= gst_registry_scan_plugin_file (context, filename, 1536 file_status.st_size, file_status.st_mtime); 1537 } 1538 1539 g_free (filename); 1540 } 1541 1542 #ifndef GSTREAMER_LITE 1543 g_dir_close (dir); 1544 #endif // GSTREAMER_LITE 1545 1546 return changed; 1547 } 1548 1549 static gboolean 1550 gst_registry_scan_path_internal (GstRegistryScanContext * context, 1551 const gchar * path) 1552 { 1553 gboolean changed; 1554 1555 GST_DEBUG_OBJECT (context->registry, "scanning path %s", path); 1556 #ifndef GSTREAMER_LITE 1557 changed = gst_registry_scan_path_level (context, path, 10); 1558 #else // GSTREAMER_LITE 1559 changed = gst_registry_scan_path_level (context, path, 0); 1560 #endif // GSTREAMER_LITE 1561 1562 GST_DEBUG_OBJECT (context->registry, "registry changed in path %s: %d", path, 1563 changed); 1564 return changed; 1565 } 1566 1567 /** 1568 * gst_registry_scan_path: 1569 * @registry: the registry to add found plugins to 1570 * @path: the path to scan 1571 * 1572 * Scan the given path for plugins to add to the registry. The syntax of the 1573 * path is specific to the registry. 1574 * 1575 * Returns: %TRUE if registry changed 1576 */ 1577 gboolean 1578 gst_registry_scan_path (GstRegistry * registry, const gchar * path) 1579 { 1580 GstRegistryScanContext context; 1581 gboolean result; 1582 1583 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); 1584 g_return_val_if_fail (path != NULL, FALSE); 1585 1586 init_scan_context (&context, registry); 1587 1588 result = gst_registry_scan_path_internal (&context, path); 1589 1590 clear_scan_context (&context); 1591 result |= context.changed; 1592 1593 return result; 1594 } 1595 1596 static gboolean 1597 _gst_plugin_feature_filter_plugin_name (GstPluginFeature * feature, 1598 gpointer user_data) 1599 { 1600 return (strcmp (feature->plugin_name, (gchar *) user_data) == 0); 1601 } 1602 1603 /** 1604 * gst_registry_get_feature_list_by_plugin: 1605 * @registry: a #GstRegistry. 1606 * @name: a plugin name. 1607 * 1608 * Retrieves a #GList of features of the plugin with name @name. 1609 * 1610 * Returns: (transfer full) (element-type Gst.PluginFeature): a #GList of 1611 * #GstPluginFeature. Use gst_plugin_feature_list_free() after usage. 1612 */ 1613 GList * 1614 gst_registry_get_feature_list_by_plugin (GstRegistry * registry, 1615 const gchar * name) 1616 { 1617 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); 1618 g_return_val_if_fail (name != NULL, NULL); 1619 1620 return gst_registry_feature_filter (registry, 1621 _gst_plugin_feature_filter_plugin_name, FALSE, (gpointer) name); 1622 } 1623 1624 /* Unref and delete the default registry */ 1625 void 1626 _priv_gst_registry_cleanup (void) 1627 { 1628 GstRegistry *registry; 1629 1630 g_mutex_lock (&_gst_registry_mutex); 1631 if ((registry = _gst_registry_default) != NULL) { 1632 _gst_registry_default = NULL; 1633 } 1634 g_mutex_unlock (&_gst_registry_mutex); 1635 1636 /* unref outside of the lock because we can. */ 1637 if (registry) 1638 gst_object_unref (registry); 1639 } 1640 1641 /** 1642 * gst_registry_check_feature_version: 1643 * @registry: a #GstRegistry 1644 * @feature_name: the name of the feature (e.g. "oggdemux") 1645 * @min_major: the minimum major version number 1646 * @min_minor: the minimum minor version number 1647 * @min_micro: the minimum micro version number 1648 * 1649 * Checks whether a plugin feature by the given name exists in 1650 * @registry and whether its version is at least the 1651 * version required. 1652 * 1653 * Returns: %TRUE if the feature could be found and the version is 1654 * the same as the required version or newer, and %FALSE otherwise. 1655 */ 1656 gboolean 1657 gst_registry_check_feature_version (GstRegistry * registry, 1658 const gchar * feature_name, guint min_major, guint min_minor, 1659 guint min_micro) 1660 { 1661 GstPluginFeature *feature; 1662 gboolean ret = FALSE; 1663 1664 g_return_val_if_fail (feature_name != NULL, FALSE); 1665 1666 GST_DEBUG ("Looking up plugin feature '%s'", feature_name); 1667 1668 feature = gst_registry_lookup_feature (registry, feature_name); 1669 if (feature) { 1670 ret = gst_plugin_feature_check_version (feature, min_major, min_minor, 1671 min_micro); 1672 gst_object_unref (feature); 1673 } else { 1674 GST_DEBUG ("Could not find plugin feature '%s'", feature_name); 1675 } 1676 1677 return ret; 1678 } 1679 1680 static void 1681 load_plugin_func (gpointer data, gpointer user_data) 1682 { 1683 GstPlugin *plugin; 1684 const gchar *filename; 1685 GError *err = NULL; 1686 1687 filename = (const gchar *) data; 1688 GST_DEBUG ("Pre-loading plugin %s", filename); 1689 1690 plugin = gst_plugin_load_file (filename, &err); 1691 1692 if (plugin) { 1693 GST_INFO ("Loaded plugin: \"%s\"", filename); 1694 1695 gst_registry_add_plugin (gst_registry_get (), plugin); 1696 } else { 1697 if (err) { 1698 /* Report error to user, and free error */ 1699 GST_ERROR ("Failed to load plugin: %s", err->message); 1700 g_error_free (err); 1701 } else { 1702 GST_WARNING ("Failed to load plugin: \"%s\"", filename); 1703 } 1704 } 1705 } 1706 1707 #ifndef GST_DISABLE_REGISTRY 1708 /* Unref all plugins marked 'cached', to clear old plugins that no 1709 * longer exist. Returns %TRUE if any plugins were removed */ 1710 static gboolean 1711 gst_registry_remove_cache_plugins (GstRegistry * registry) 1712 { 1713 GList *g; 1714 GList *g_next; 1715 GstPlugin *plugin; 1716 gboolean changed = FALSE; 1717 1718 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); 1719 1720 GST_OBJECT_LOCK (registry); 1721 1722 GST_DEBUG_OBJECT (registry, "removing cached plugins"); 1723 g = registry->priv->plugins; 1724 while (g) { 1725 g_next = g->next; 1726 plugin = g->data; 1727 if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_CACHED)) { 1728 GST_DEBUG_OBJECT (registry, "removing cached plugin \"%s\"", 1729 GST_STR_NULL (plugin->filename)); 1730 registry->priv->plugins = g_list_delete_link (registry->priv->plugins, g); 1731 if (G_LIKELY (plugin->basename)) 1732 g_hash_table_remove (registry->priv->basename_hash, plugin->basename); 1733 gst_registry_remove_features_for_plugin_unlocked (registry, plugin); 1734 gst_object_unref (plugin); 1735 changed = TRUE; 1736 } 1737 g = g_next; 1738 } 1739 1740 GST_OBJECT_UNLOCK (registry); 1741 1742 return changed; 1743 } 1744 1745 typedef enum 1746 { 1747 REGISTRY_SCAN_AND_UPDATE_FAILURE = 0, 1748 REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED, 1749 REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED 1750 } GstRegistryScanAndUpdateResult; 1751 1752 /* 1753 * scan_and_update_registry: 1754 * @default_registry: the #GstRegistry 1755 * @registry_file: registry filename 1756 * @write_changes: write registry if it has changed? 1757 * 1758 * Scans for registry changes and eventually updates the registry cache. 1759 * 1760 * Return: %REGISTRY_SCAN_AND_UPDATE_FAILURE if the registry could not scanned 1761 * or updated, %REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED if the 1762 * registry is clean and %REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED if 1763 * it has been updated and the cache needs to be re-read. 1764 */ 1765 static GstRegistryScanAndUpdateResult 1766 scan_and_update_registry (GstRegistry * default_registry, 1767 const gchar * registry_file, gboolean write_changes, GError ** error) 1768 { 1769 const gchar *plugin_path; 1770 gboolean changed = FALSE; 1771 GList *l; 1772 GstRegistryScanContext context; 1773 1774 GST_INFO ("Validating plugins from registry cache: %s", registry_file); 1775 1776 #ifdef GSTREAMER_LITE 1777 #ifdef G_OS_WIN32 1778 { 1779 HMODULE hmodule = NULL; 1780 char *dir = NULL; 1781 gchar *p = NULL; 1782 wchar_t wc_fn[MAX_PATH]; 1783 1784 hmodule = GetModuleHandle(LIBGSTREAMER_LIB_NAME); 1785 if (hmodule) 1786 { 1787 if (GetModuleFileNameW(hmodule, wc_fn, MAX_PATH)) 1788 { 1789 dir = g_utf16_to_utf8(wc_fn, -1, NULL, NULL, NULL); 1790 if (dir) 1791 { 1792 if ((p = strrchr (dir, G_DIR_SEPARATOR)) != NULL) 1793 *p = '\0'; 1794 1795 changed |= gst_registry_scan_path (default_registry, dir); 1796 1797 g_free(dir); 1798 } 1799 } 1800 } 1801 } 1802 #elif defined(HAVE_OSX) 1803 { 1804 const void* pHeader = (void*) &_mh_dylib_header; 1805 const char* pImageName = 0; 1806 gchar* pBasePath = NULL; 1807 int iCount = _dyld_image_count(); 1808 int i; 1809 1810 for(i = 1; i < iCount; i++) 1811 { 1812 if (((void*)_dyld_get_image_header(i)) == pHeader) 1813 pImageName = _dyld_get_image_name(i);//contains absolute path to dylib 1814 } 1815 1816 if (NULL != pImageName) 1817 { 1818 pBasePath = g_path_get_dirname((const gchar*) pImageName); 1819 changed |= gst_registry_scan_path (default_registry, pBasePath); 1820 } 1821 } 1822 #elif defined (LINUX) 1823 { 1824 // Get base path of Gstreamer-lite lib. 1825 gchar *base_path = NULL; 1826 if (dl_iterate_phdr (dl_callback, &base_path)) 1827 { 1828 base_path = g_path_get_dirname((const gchar*) base_path); 1829 } 1830 1831 if (base_path != NULL) 1832 { 1833 changed |= gst_registry_scan_path (default_registry, base_path); 1834 } 1835 else 1836 { 1837 GST_ERROR ("Could not locate %s", LIBGSTREAMER_LIB_NAME); 1838 } 1839 } 1840 #else // other platforms ... 1841 { 1842 // Scan current path 1843 gchar *current_path = g_get_current_dir(); 1844 if (current_path != NULL) 1845 { 1846 changed |= gst_registry_scan_path (default_registry, current_path); 1847 g_free(current_path); 1848 } 1849 else 1850 { 1851 GST_ERROR ("g_get_current_dir() returned NULL"); 1852 } 1853 } 1854 #endif // other platforms 1855 #endif // GSTREAMER_LITE 1856 1857 init_scan_context (&context, default_registry); 1858 1859 /* It sounds tempting to just compare the mtime of directories with the mtime 1860 * of the registry cache, but it does not work. It would not catch updated 1861 * plugins, which might bring more or less features. 1862 */ 1863 1864 /* scan paths specified via --gst-plugin-path */ 1865 GST_DEBUG ("scanning paths added via --gst-plugin-path"); 1866 for (l = _priv_gst_plugin_paths; l != NULL; l = l->next) { 1867 GST_INFO ("Scanning plugin path: \"%s\"", (gchar *) l->data); 1868 changed |= gst_registry_scan_path_internal (&context, (gchar *) l->data); 1869 } 1870 /* keep plugin_paths around in case a re-scan is forced later on */ 1871 1872 /* GST_PLUGIN_PATH specifies a list of directories to scan for 1873 * additional plugins. These take precedence over the system plugins */ 1874 plugin_path = g_getenv ("GST_PLUGIN_PATH_1_0"); 1875 if (plugin_path == NULL) 1876 plugin_path = g_getenv ("GST_PLUGIN_PATH"); 1877 if (plugin_path) { 1878 char **list; 1879 int i; 1880 1881 GST_DEBUG ("GST_PLUGIN_PATH set to %s", plugin_path); 1882 list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0); 1883 for (i = 0; list[i]; i++) { 1884 changed |= gst_registry_scan_path_internal (&context, list[i]); 1885 } 1886 g_strfreev (list); 1887 } else { 1888 GST_DEBUG ("GST_PLUGIN_PATH not set"); 1889 } 1890 1891 /* GST_PLUGIN_SYSTEM_PATH specifies a list of plugins that are always 1892 * loaded by default. If not set, this defaults to the system-installed 1893 * path, and the plugins installed in the user's home directory */ 1894 plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH_1_0"); 1895 if (plugin_path == NULL) 1896 plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH"); 1897 if (plugin_path == NULL) { 1898 char *home_plugins; 1899 1900 GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set"); 1901 1902 /* plugins in the user's home directory take precedence over 1903 * system-installed ones */ 1904 home_plugins = g_build_filename (g_get_user_data_dir (), 1905 "gstreamer-" GST_API_VERSION, "plugins", NULL); 1906 1907 GST_DEBUG ("scanning home plugins %s", home_plugins); 1908 changed |= gst_registry_scan_path_internal (&context, home_plugins); 1909 g_free (home_plugins); 1910 1911 /* add the main (installed) library path */ 1912 1913 #ifdef G_OS_WIN32 1914 { 1915 char *base_dir; 1916 char *dir; 1917 1918 base_dir = 1919 g_win32_get_package_installation_directory_of_module 1920 (_priv_gst_dll_handle); 1921 1922 dir = g_build_filename (base_dir, 1923 #ifdef _DEBUG 1924 "debug" 1925 #endif 1926 "lib", "gstreamer-" GST_API_VERSION, NULL); 1927 GST_DEBUG ("scanning DLL dir %s", dir); 1928 1929 changed |= gst_registry_scan_path_internal (&context, dir); 1930 1931 g_free (dir); 1932 g_free (base_dir); 1933 } 1934 #else 1935 GST_DEBUG ("scanning main plugins %s", PLUGINDIR); 1936 changed |= gst_registry_scan_path_internal (&context, PLUGINDIR); 1937 #endif 1938 } else { 1939 gchar **list; 1940 gint i; 1941 1942 GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH set to %s", plugin_path); 1943 list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0); 1944 for (i = 0; list[i]; i++) { 1945 changed |= gst_registry_scan_path_internal (&context, list[i]); 1946 } 1947 g_strfreev (list); 1948 } 1949 1950 clear_scan_context (&context); 1951 changed |= context.changed; 1952 1953 /* Remove cached plugins so stale info is cleared. */ 1954 changed |= gst_registry_remove_cache_plugins (default_registry); 1955 1956 if (!changed) { 1957 GST_INFO ("Registry cache has not changed"); 1958 return REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED; 1959 } 1960 1961 if (!write_changes) { 1962 GST_INFO ("Registry cache changed, but writing is disabled. Not writing."); 1963 return REGISTRY_SCAN_AND_UPDATE_FAILURE; 1964 } 1965 1966 #ifndef GSTREAMER_LITE 1967 GST_INFO ("Registry cache changed. Writing new registry cache"); 1968 if (!priv_gst_registry_binary_write_cache (default_registry, 1969 default_registry->priv->plugins, registry_file)) { 1970 g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED, 1971 _("Error writing registry cache to %s: %s"), 1972 registry_file, g_strerror (errno)); 1973 return REGISTRY_SCAN_AND_UPDATE_FAILURE; 1974 } 1975 #endif // GSTREAMER_LITE 1976 1977 GST_INFO ("Registry cache written successfully"); 1978 return REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED; 1979 } 1980 1981 static gboolean 1982 ensure_current_registry (GError ** error) 1983 { 1984 gchar *registry_file; 1985 GstRegistry *default_registry; 1986 gboolean ret = TRUE; 1987 gboolean do_update = TRUE; 1988 gboolean have_cache = TRUE; 1989 1990 default_registry = gst_registry_get (); 1991 1992 registry_file = g_strdup (g_getenv ("GST_REGISTRY_1_0")); 1993 if (registry_file == NULL) 1994 registry_file = g_strdup (g_getenv ("GST_REGISTRY")); 1995 if (registry_file == NULL) { 1996 registry_file = g_build_filename (g_get_user_cache_dir (), 1997 "gstreamer-" GST_API_VERSION, "registry." TARGET_CPU ".bin", NULL); 1998 } 1999 2000 if (!_gst_disable_registry_cache) { 2001 GST_INFO ("reading registry cache: %s", registry_file); 2002 #ifndef GSTREAMER_LITE 2003 have_cache = priv_gst_registry_binary_read_cache (default_registry, 2004 registry_file); 2005 #else // GSTREAMER_LITE 2006 have_cache = FALSE; 2007 #endif // GSTREAMER_LITE 2008 /* Only ever read the registry cache once, then disable it for 2009 * subsequent updates during the program lifetime */ 2010 _gst_disable_registry_cache = TRUE; 2011 } 2012 2013 if (have_cache) { 2014 do_update = !_priv_gst_disable_registry_update; 2015 if (do_update) { 2016 const gchar *update_env; 2017 2018 if ((update_env = g_getenv ("GST_REGISTRY_UPDATE"))) { 2019 /* do update for any value different from "no" */ 2020 do_update = (strcmp (update_env, "no") != 0); 2021 } 2022 } 2023 } 2024 2025 if (do_update) { 2026 const gchar *reuse_env; 2027 2028 if ((reuse_env = g_getenv ("GST_REGISTRY_REUSE_PLUGIN_SCANNER"))) { 2029 /* do reuse for any value different from "no" */ 2030 __registry_reuse_plugin_scanner = (strcmp (reuse_env, "no") != 0); 2031 } 2032 /* now check registry */ 2033 GST_DEBUG ("Updating registry cache"); 2034 scan_and_update_registry (default_registry, registry_file, TRUE, error); 2035 } else { 2036 GST_DEBUG ("Not updating registry cache (disabled)"); 2037 } 2038 2039 g_free (registry_file); 2040 GST_INFO ("registry reading and updating done, result = %d", ret); 2041 2042 return ret; 2043 } 2044 #endif /* GST_DISABLE_REGISTRY */ 2045 2046 /** 2047 * gst_registry_fork_is_enabled: 2048 * 2049 * By default GStreamer will perform scanning and rebuilding of the 2050 * registry file using a helper child process. 2051 * 2052 * Applications might want to disable this behaviour with the 2053 * gst_registry_fork_set_enabled() function, in which case new plugins 2054 * are scanned (and loaded) into the application process. 2055 * 2056 * Returns: %TRUE if GStreamer will use the child helper process when 2057 * rebuilding the registry. 2058 */ 2059 gboolean 2060 gst_registry_fork_is_enabled (void) 2061 { 2062 return _gst_enable_registry_fork; 2063 } 2064 2065 /** 2066 * gst_registry_fork_set_enabled: 2067 * @enabled: whether rebuilding the registry can use a temporary child helper process. 2068 * 2069 * Applications might want to disable/enable spawning of a child helper process 2070 * when rebuilding the registry. See gst_registry_fork_is_enabled() for more 2071 * information. 2072 */ 2073 void 2074 gst_registry_fork_set_enabled (gboolean enabled) 2075 { 2076 _gst_enable_registry_fork = enabled; 2077 } 2078 2079 /** 2080 * gst_update_registry: 2081 * 2082 * Forces GStreamer to re-scan its plugin paths and update the default 2083 * plugin registry. 2084 * 2085 * Applications will almost never need to call this function, it is only 2086 * useful if the application knows new plugins have been installed (or old 2087 * ones removed) since the start of the application (or, to be precise, the 2088 * first call to gst_init()) and the application wants to make use of any 2089 * newly-installed plugins without restarting the application. 2090 * 2091 * Applications should assume that the registry update is neither atomic nor 2092 * thread-safe and should therefore not have any dynamic pipelines running 2093 * (including the playbin and decodebin elements) and should also not create 2094 * any elements or access the GStreamer registry while the update is in 2095 * progress. 2096 * 2097 * Note that this function may block for a significant amount of time. 2098 * 2099 * Returns: %TRUE if the registry has been updated successfully (does not 2100 * imply that there were changes), otherwise %FALSE. 2101 */ 2102 gboolean 2103 gst_update_registry (void) 2104 { 2105 gboolean res; 2106 2107 #ifndef GST_DISABLE_REGISTRY 2108 GError *err = NULL; 2109 2110 res = ensure_current_registry (&err); 2111 if (err) { 2112 GST_WARNING ("registry update failed: %s", err->message); 2113 g_error_free (err); 2114 } else { 2115 GST_LOG ("registry update succeeded"); 2116 } 2117 2118 #else 2119 GST_WARNING ("registry update failed: %s", "registry disabled"); 2120 res = TRUE; 2121 #endif /* GST_DISABLE_REGISTRY */ 2122 2123 if (_priv_gst_preload_plugins) { 2124 GST_DEBUG ("Preloading indicated plugins..."); 2125 g_slist_foreach (_priv_gst_preload_plugins, load_plugin_func, NULL); 2126 } 2127 2128 return res; 2129 } 2130 2131 /** 2132 * gst_registry_get_feature_list_cookie: 2133 * @registry: the registry 2134 * 2135 * Returns the registry's feature list cookie. This changes 2136 * every time a feature is added or removed from the registry. 2137 * 2138 * Returns: the feature list cookie. 2139 */ 2140 guint32 2141 gst_registry_get_feature_list_cookie (GstRegistry * registry) 2142 { 2143 g_return_val_if_fail (GST_IS_REGISTRY (registry), 0); 2144 2145 return registry->priv->cookie; 2146 }