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 }