1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gstreamer.Registry; 26 27 private import glib.ListG; 28 private import glib.Str; 29 private import gobject.ObjectG; 30 private import gobject.Signals; 31 private import gstreamer.ObjectGst; 32 private import gstreamer.Plugin; 33 private import gstreamer.PluginFeature; 34 private import gstreamerc.gstreamer; 35 public import gstreamerc.gstreamertypes; 36 public import gtkc.gdktypes; 37 private import std.algorithm; 38 39 40 /** 41 * One registry holds the metadata of a set of plugins. 42 * 43 * <emphasis role="bold">Design:</emphasis> 44 * 45 * The #GstRegistry object is a list of plugins and some functions for dealing 46 * with them. Each #GstPlugin is matched 1-1 with a file on disk, and may or may 47 * not be loaded at a given time. 48 * 49 * The primary source, at all times, of plugin information is each plugin file 50 * itself. Thus, if an application wants information about a particular plugin, 51 * or wants to search for a feature that satisfies given criteria, the primary 52 * means of doing so is to load every plugin and look at the resulting 53 * information that is gathered in the default registry. Clearly, this is a time 54 * consuming process, so we cache information in the registry file. The format 55 * and location of the cache file is internal to gstreamer. 56 * 57 * On startup, plugins are searched for in the plugin search path. The following 58 * locations are checked in this order: 59 * <itemizedlist> 60 * <listitem> 61 * <para>location from --gst-plugin-path commandline option.</para> 62 * </listitem> 63 * <listitem> 64 * <para>the GST_PLUGIN_PATH environment variable.</para> 65 * </listitem> 66 * <listitem> 67 * <para>the GST_PLUGIN_SYSTEM_PATH environment variable.</para> 68 * </listitem> 69 * <listitem> 70 * <para>default locations (if GST_PLUGIN_SYSTEM_PATH is not set). Those 71 * default locations are: 72 * <filename>$XDG_DATA_HOME/gstreamer-$GST_API_VERSION/plugins/</filename> 73 * and <filename>$prefix/libs/gstreamer-$GST_API_VERSION/</filename>. 74 * <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html"> 75 * <filename>$XDG_DATA_HOME</filename></ulink> defaults to 76 * <filename>$HOME/.local/share</filename>. 77 * </para> 78 * </listitem> 79 * </itemizedlist> 80 * The registry cache file is loaded from 81 * <filename>$XDG_CACHE_HOME/gstreamer-$GST_API_VERSION/registry-$ARCH.bin</filename> 82 * (where 83 * <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html"> 84 * <filename>$XDG_CACHE_HOME</filename></ulink> defaults to 85 * <filename>$HOME/.cache</filename>) or the file listed in the GST_REGISTRY 86 * env var. One reason to change the registry location is for testing. 87 * 88 * For each plugin that is found in the plugin search path, there could be 3 89 * possibilities for cached information: 90 * <itemizedlist> 91 * <listitem> 92 * <para>the cache may not contain information about a given file.</para> 93 * </listitem> 94 * <listitem> 95 * <para>the cache may have stale information.</para> 96 * </listitem> 97 * <listitem> 98 * <para>the cache may have current information.</para> 99 * </listitem> 100 * </itemizedlist> 101 * 102 * In the first two cases, the plugin is loaded and the cache updated. In 103 * addition to these cases, the cache may have entries for plugins that are not 104 * relevant to the current process. These are marked as not available to the 105 * current process. If the cache is updated for whatever reason, it is marked 106 * dirty. 107 * 108 * A dirty cache is written out at the end of initialization. Each entry is 109 * checked to make sure the information is minimally valid. If not, the entry is 110 * simply dropped. 111 * 112 * <emphasis role="bold">Implementation notes:</emphasis> 113 * 114 * The "cache" and "registry" are different concepts and can represent 115 * different sets of plugins. For various reasons, at init time, the cache is 116 * stored in the default registry, and plugins not relevant to the current 117 * process are marked with the %GST_PLUGIN_FLAG_CACHED bit. These plugins are 118 * removed at the end of initialization. 119 */ 120 public class Registry : ObjectGst 121 { 122 /** the main Gtk struct */ 123 protected GstRegistry* gstRegistry; 124 125 /** Get the main Gtk struct */ 126 public GstRegistry* getRegistryStruct() 127 { 128 return gstRegistry; 129 } 130 131 /** the main Gtk struct as a void* */ 132 protected override void* getStruct() 133 { 134 return cast(void*)gstRegistry; 135 } 136 137 protected override void setStruct(GObject* obj) 138 { 139 gstRegistry = cast(GstRegistry*)obj; 140 super.setStruct(obj); 141 } 142 143 /** 144 * Sets our main struct and passes it to the parent class. 145 */ 146 public this (GstRegistry* gstRegistry, bool ownedRef = false) 147 { 148 this.gstRegistry = gstRegistry; 149 super(cast(GstObject*)gstRegistry, ownedRef); 150 } 151 152 153 /** */ 154 public static GType getType() 155 { 156 return gst_registry_get_type(); 157 } 158 159 /** 160 * By default GStreamer will perform scanning and rebuilding of the 161 * registry file using a helper child process. 162 * 163 * Applications might want to disable this behaviour with the 164 * gst_registry_fork_set_enabled() function, in which case new plugins 165 * are scanned (and loaded) into the application process. 166 * 167 * Return: %TRUE if GStreamer will use the child helper process when 168 * rebuilding the registry. 169 */ 170 public static bool forkIsEnabled() 171 { 172 return gst_registry_fork_is_enabled() != 0; 173 } 174 175 /** 176 * Applications might want to disable/enable spawning of a child helper process 177 * when rebuilding the registry. See gst_registry_fork_is_enabled() for more 178 * information. 179 * 180 * Params: 181 * enabled = whether rebuilding the registry can use a temporary child helper process. 182 */ 183 public static void forkSetEnabled(bool enabled) 184 { 185 gst_registry_fork_set_enabled(enabled); 186 } 187 188 /** 189 * Retrieves the singleton plugin registry. The caller does not own a 190 * reference on the registry, as it is alive as long as GStreamer is 191 * initialized. 192 * 193 * Return: the #GstRegistry. 194 */ 195 public static Registry get() 196 { 197 auto p = gst_registry_get(); 198 199 if(p is null) 200 { 201 return null; 202 } 203 204 return ObjectG.getDObject!(Registry)(cast(GstRegistry*) p); 205 } 206 207 /** 208 * Add the feature to the registry. The feature-added signal will be emitted. 209 * This function sinks @feature. 210 * 211 * Params: 212 * feature = the feature to add 213 * 214 * Return: %TRUE on success. 215 * 216 * MT safe. 217 */ 218 public bool addFeature(PluginFeature feature) 219 { 220 return gst_registry_add_feature(gstRegistry, (feature is null) ? null : feature.getPluginFeatureStruct()) != 0; 221 } 222 223 /** 224 * Add the plugin to the registry. The plugin-added signal will be emitted. 225 * This function will sink @plugin. 226 * 227 * Params: 228 * plugin = the plugin to add 229 * 230 * Return: %TRUE on success. 231 * 232 * MT safe. 233 */ 234 public bool addPlugin(Plugin plugin) 235 { 236 return gst_registry_add_plugin(gstRegistry, (plugin is null) ? null : plugin.getPluginStruct()) != 0; 237 } 238 239 /** 240 * Checks whether a plugin feature by the given name exists in 241 * @registry and whether its version is at least the 242 * version required. 243 * 244 * Params: 245 * featureName = the name of the feature (e.g. "oggdemux") 246 * minMajor = the minimum major version number 247 * minMinor = the minimum minor version number 248 * minMicro = the minimum micro version number 249 * 250 * Return: %TRUE if the feature could be found and the version is 251 * the same as the required version or newer, and %FALSE otherwise. 252 */ 253 public bool checkFeatureVersion(string featureName, uint minMajor, uint minMinor, uint minMicro) 254 { 255 return gst_registry_check_feature_version(gstRegistry, Str.toStringz(featureName), minMajor, minMinor, minMicro) != 0; 256 } 257 258 /** 259 * Runs a filter against all features of the plugins in the registry 260 * and returns a GList with the results. 261 * If the first flag is set, only the first match is 262 * returned (as a list with a single object). 263 * 264 * Params: 265 * filter = the filter to use 266 * first = only return first match 267 * userData = user data passed to the filter function 268 * 269 * Return: a #GList of 270 * #GstPluginFeature. Use gst_plugin_feature_list_free() after usage. 271 * 272 * MT safe. 273 */ 274 public ListG featureFilter(GstPluginFeatureFilter filter, bool first, void* userData) 275 { 276 auto p = gst_registry_feature_filter(gstRegistry, filter, first, userData); 277 278 if(p is null) 279 { 280 return null; 281 } 282 283 return new ListG(cast(GList*) p, true); 284 } 285 286 /** 287 * Find the pluginfeature with the given name and type in the registry. 288 * 289 * Params: 290 * name = the pluginfeature name to find 291 * type = the pluginfeature type to find 292 * 293 * Return: the pluginfeature with the 294 * given name and type or %NULL if the plugin was not 295 * found. gst_object_unref() after usage. 296 * 297 * MT safe. 298 */ 299 public PluginFeature findFeature(string name, GType type) 300 { 301 auto p = gst_registry_find_feature(gstRegistry, Str.toStringz(name), type); 302 303 if(p is null) 304 { 305 return null; 306 } 307 308 return ObjectG.getDObject!(PluginFeature)(cast(GstPluginFeature*) p, true); 309 } 310 311 /** 312 * Find the plugin with the given name in the registry. 313 * The plugin will be reffed; caller is responsible for unreffing. 314 * 315 * Params: 316 * name = the plugin name to find 317 * 318 * Return: the plugin with the given name 319 * or %NULL if the plugin was not found. gst_object_unref() after 320 * usage. 321 * 322 * MT safe. 323 */ 324 public Plugin findPlugin(string name) 325 { 326 auto p = gst_registry_find_plugin(gstRegistry, Str.toStringz(name)); 327 328 if(p is null) 329 { 330 return null; 331 } 332 333 return ObjectG.getDObject!(Plugin)(cast(GstPlugin*) p, true); 334 } 335 336 /** 337 * Retrieves a #GList of #GstPluginFeature of @type. 338 * 339 * Params: 340 * type = a #GType. 341 * 342 * Return: a #GList of 343 * #GstPluginFeature of @type. Use gst_plugin_feature_list_free() after use 344 * 345 * MT safe. 346 */ 347 public ListG getFeatureList(GType type) 348 { 349 auto p = gst_registry_get_feature_list(gstRegistry, type); 350 351 if(p is null) 352 { 353 return null; 354 } 355 356 return new ListG(cast(GList*) p, true); 357 } 358 359 /** 360 * Retrieves a #GList of features of the plugin with name @name. 361 * 362 * Params: 363 * name = a plugin name. 364 * 365 * Return: a #GList of 366 * #GstPluginFeature. Use gst_plugin_feature_list_free() after usage. 367 */ 368 public ListG getFeatureListByPlugin(string name) 369 { 370 auto p = gst_registry_get_feature_list_by_plugin(gstRegistry, Str.toStringz(name)); 371 372 if(p is null) 373 { 374 return null; 375 } 376 377 return new ListG(cast(GList*) p, true); 378 } 379 380 /** 381 * Returns the registry's feature list cookie. This changes 382 * every time a feature is added or removed from the registry. 383 * 384 * Return: the feature list cookie. 385 */ 386 public uint getFeatureListCookie() 387 { 388 return gst_registry_get_feature_list_cookie(gstRegistry); 389 } 390 391 /** 392 * Get a copy of all plugins registered in the given registry. The refcount 393 * of each element in the list in incremented. 394 * 395 * Return: a #GList of #GstPlugin. 396 * Use gst_plugin_list_free() after usage. 397 * 398 * MT safe. 399 */ 400 public ListG getPluginList() 401 { 402 auto p = gst_registry_get_plugin_list(gstRegistry); 403 404 if(p is null) 405 { 406 return null; 407 } 408 409 return new ListG(cast(GList*) p, true); 410 } 411 412 /** 413 * Look up a plugin in the given registry with the given filename. 414 * If found, plugin is reffed. 415 * 416 * Params: 417 * filename = the name of the file to look up 418 * 419 * Return: the #GstPlugin if found, or 420 * %NULL if not. gst_object_unref() after usage. 421 */ 422 public Plugin lookup(string filename) 423 { 424 auto p = gst_registry_lookup(gstRegistry, Str.toStringz(filename)); 425 426 if(p is null) 427 { 428 return null; 429 } 430 431 return ObjectG.getDObject!(Plugin)(cast(GstPlugin*) p, true); 432 } 433 434 /** 435 * Find a #GstPluginFeature with @name in @registry. 436 * 437 * Params: 438 * name = a #GstPluginFeature name 439 * 440 * Return: a #GstPluginFeature with its refcount incremented, 441 * use gst_object_unref() after usage. 442 * 443 * MT safe. 444 */ 445 public PluginFeature lookupFeature(string name) 446 { 447 auto p = gst_registry_lookup_feature(gstRegistry, Str.toStringz(name)); 448 449 if(p is null) 450 { 451 return null; 452 } 453 454 return ObjectG.getDObject!(PluginFeature)(cast(GstPluginFeature*) p, true); 455 } 456 457 /** 458 * Runs a filter against all plugins in the registry and returns a #GList with 459 * the results. If the first flag is set, only the first match is 460 * returned (as a list with a single object). 461 * Every plugin is reffed; use gst_plugin_list_free() after use, which 462 * will unref again. 463 * 464 * Params: 465 * filter = the filter to use 466 * first = only return first match 467 * userData = user data passed to the filter function 468 * 469 * Return: a #GList of #GstPlugin. 470 * Use gst_plugin_list_free() after usage. 471 * 472 * MT safe. 473 */ 474 public ListG pluginFilter(GstPluginFilter filter, bool first, void* userData) 475 { 476 auto p = gst_registry_plugin_filter(gstRegistry, filter, first, userData); 477 478 if(p is null) 479 { 480 return null; 481 } 482 483 return new ListG(cast(GList*) p, true); 484 } 485 486 /** 487 * Remove the feature from the registry. 488 * 489 * MT safe. 490 * 491 * Params: 492 * feature = the feature to remove 493 */ 494 public void removeFeature(PluginFeature feature) 495 { 496 gst_registry_remove_feature(gstRegistry, (feature is null) ? null : feature.getPluginFeatureStruct()); 497 } 498 499 /** 500 * Remove the plugin from the registry. 501 * 502 * MT safe. 503 * 504 * Params: 505 * plugin = the plugin to remove 506 */ 507 public void removePlugin(Plugin plugin) 508 { 509 gst_registry_remove_plugin(gstRegistry, (plugin is null) ? null : plugin.getPluginStruct()); 510 } 511 512 /** 513 * Scan the given path for plugins to add to the registry. The syntax of the 514 * path is specific to the registry. 515 * 516 * Params: 517 * path = the path to scan 518 * 519 * Return: %TRUE if registry changed 520 */ 521 public bool scanPath(string path) 522 { 523 return gst_registry_scan_path(gstRegistry, Str.toStringz(path)) != 0; 524 } 525 526 protected class OnFeatureAddedDelegateWrapper 527 { 528 void delegate(PluginFeature, Registry) dlg; 529 gulong handlerId; 530 ConnectFlags flags; 531 this(void delegate(PluginFeature, Registry) dlg, gulong handlerId, ConnectFlags flags) 532 { 533 this.dlg = dlg; 534 this.handlerId = handlerId; 535 this.flags = flags; 536 } 537 } 538 protected OnFeatureAddedDelegateWrapper[] onFeatureAddedListeners; 539 540 /** 541 * Signals that a feature has been added to the registry (possibly 542 * replacing a previously-added one by the same name) 543 * 544 * Params: 545 * feature = the feature that has been added 546 */ 547 gulong addOnFeatureAdded(void delegate(PluginFeature, Registry) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 548 { 549 onFeatureAddedListeners ~= new OnFeatureAddedDelegateWrapper(dlg, 0, connectFlags); 550 onFeatureAddedListeners[onFeatureAddedListeners.length - 1].handlerId = Signals.connectData( 551 this, 552 "feature-added", 553 cast(GCallback)&callBackFeatureAdded, 554 cast(void*)onFeatureAddedListeners[onFeatureAddedListeners.length - 1], 555 cast(GClosureNotify)&callBackFeatureAddedDestroy, 556 connectFlags); 557 return onFeatureAddedListeners[onFeatureAddedListeners.length - 1].handlerId; 558 } 559 560 extern(C) static void callBackFeatureAdded(GstRegistry* registryStruct, GstPluginFeature* feature,OnFeatureAddedDelegateWrapper wrapper) 561 { 562 wrapper.dlg(ObjectG.getDObject!(PluginFeature)(feature), wrapper.outer); 563 } 564 565 extern(C) static void callBackFeatureAddedDestroy(OnFeatureAddedDelegateWrapper wrapper, GClosure* closure) 566 { 567 wrapper.outer.internalRemoveOnFeatureAdded(wrapper); 568 } 569 570 protected void internalRemoveOnFeatureAdded(OnFeatureAddedDelegateWrapper source) 571 { 572 foreach(index, wrapper; onFeatureAddedListeners) 573 { 574 if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId) 575 { 576 onFeatureAddedListeners[index] = null; 577 onFeatureAddedListeners = std.algorithm.remove(onFeatureAddedListeners, index); 578 break; 579 } 580 } 581 } 582 583 584 protected class OnPluginAddedDelegateWrapper 585 { 586 void delegate(Plugin, Registry) dlg; 587 gulong handlerId; 588 ConnectFlags flags; 589 this(void delegate(Plugin, Registry) dlg, gulong handlerId, ConnectFlags flags) 590 { 591 this.dlg = dlg; 592 this.handlerId = handlerId; 593 this.flags = flags; 594 } 595 } 596 protected OnPluginAddedDelegateWrapper[] onPluginAddedListeners; 597 598 /** 599 * Signals that a plugin has been added to the registry (possibly 600 * replacing a previously-added one by the same name) 601 * 602 * Params: 603 * plugin = the plugin that has been added 604 */ 605 gulong addOnPluginAdded(void delegate(Plugin, Registry) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 606 { 607 onPluginAddedListeners ~= new OnPluginAddedDelegateWrapper(dlg, 0, connectFlags); 608 onPluginAddedListeners[onPluginAddedListeners.length - 1].handlerId = Signals.connectData( 609 this, 610 "plugin-added", 611 cast(GCallback)&callBackPluginAdded, 612 cast(void*)onPluginAddedListeners[onPluginAddedListeners.length - 1], 613 cast(GClosureNotify)&callBackPluginAddedDestroy, 614 connectFlags); 615 return onPluginAddedListeners[onPluginAddedListeners.length - 1].handlerId; 616 } 617 618 extern(C) static void callBackPluginAdded(GstRegistry* registryStruct, GstPlugin* plugin,OnPluginAddedDelegateWrapper wrapper) 619 { 620 wrapper.dlg(ObjectG.getDObject!(Plugin)(plugin), wrapper.outer); 621 } 622 623 extern(C) static void callBackPluginAddedDestroy(OnPluginAddedDelegateWrapper wrapper, GClosure* closure) 624 { 625 wrapper.outer.internalRemoveOnPluginAdded(wrapper); 626 } 627 628 protected void internalRemoveOnPluginAdded(OnPluginAddedDelegateWrapper source) 629 { 630 foreach(index, wrapper; onPluginAddedListeners) 631 { 632 if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId) 633 { 634 onPluginAddedListeners[index] = null; 635 onPluginAddedListeners = std.algorithm.remove(onPluginAddedListeners, index); 636 break; 637 } 638 } 639 } 640 641 }