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