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