/* * Copyright (c) 2007 Wayne Meissner * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> * 2000 Wim Taymans <wtay@chello.be> * 2005 David A. Schleef <ds@schleef.org> * * This file is part of gstreamer-java. * * This code is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * version 3 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>. */ package org.gstreamer; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.gstreamer.lowlevel.GType; import org.gstreamer.lowlevel.GlibAPI.GList; import org.gstreamer.lowlevel.GstNative; import org.gstreamer.lowlevel.GstPluginAPI; import org.gstreamer.lowlevel.GstRegistryAPI; import com.sun.jna.Pointer; /** * Abstract base class for management of {@link Plugin} objects. * <p> * One registry holds the metadata of a set of plugins. * All registries build the RegistryPool. * <p> * <b>Design</b>: * <p> * The Registry object is a list of plugins and some methods for dealing * with them. Plugins are matched 1-1 with a file on disk, and may or may * not be loaded at a given time. There may be multiple Registry objects, * but the "default registry" is the only object that has any meaning to the * core. * <p> * The registry.xml file is actually a cache of plugin information. This is * unlike versions prior to 0.10, where the registry file was the primary source * of plugin information, and was created by the gst-register command. * <p> * The primary source, at all times, of plugin information is each plugin file * itself. Thus, if an application wants information about a particular plugin, * or wants to search for a feature that satisfies given criteria, the primary * means of doing so is to load every plugin and look at the resulting * information that is gathered in the default registry. Clearly, this is a time * consuming process, so we cache information in the registry.xml file. * <p> * On startup, plugins are searched for in the plugin search path. This path can * be set directly using the GST_PLUGIN_PATH environment variable. The registry * file is loaded from ~/.gstreamer-$GST_MAJORMINOR/registry-$ARCH.xml or the * file listed in the GST_REGISTRY environment variable. The only reason to change the * registry location is for testing. * <p> * For each plugin that is found in the plugin search path, there could be 3 * possibilities for cached information: * <ol> * <li> * <para>the cache may not contain information about a given file.</para> * </li> * <li> * <para>the cache may have stale information.</para> * </li> * <li> * <para>the cache may have current information.</para> * </li> * </ol> * <p> * In the first two cases, the plugin is loaded and the cache updated. In * addition to these cases, the cache may have entries for plugins that are not * relevant to the current process. These are marked as not available to the * current process. If the cache is updated for whatever reason, it is marked * dirty. * <p> * A dirty cache is written out at the end of initialization. Each entry is * checked to make sure the information is minimally valid. If not, the entry is * simply dropped. * <p> * <bold>Implementation notes:</bold> * <p> * The "cache" and "default registry" are different concepts and can represent * different sets of plugins. For various reasons, at init time, the cache is * stored in the default registry, and plugins not relevant to the current * process are marked with the %GST_PLUGIN_FLAG_CACHED bit. These plugins are * removed at the end of intitialization. */ public class Registry extends GstObject { public static final String GTYPE_NAME = "GstRegistry"; private static interface API extends GstPluginAPI, GstRegistryAPI { void gst_plugin_feature_list_free(GList list); GList gst_registry_get_plugin_list(Registry registry); GList gst_registry_plugin_filter(Registry registry, PluginFilter filter, boolean first, Pointer user_data); GList gst_registry_feature_filter(Registry registry, PluginFeatureFilter filter, boolean first, Pointer user_data); GList gst_registry_get_feature_list(Registry registry, GType type); GList gst_registry_get_feature_list_by_plugin(Registry registry, String name); GList gst_registry_get_path_list(Registry registry); void gst_plugin_list_free(GList list); } private static final API gst = GstNative.load(API.class); public static interface PluginFilter { public boolean accept(Plugin plugin); } public static interface PluginFeatureFilter { public boolean accept(PluginFeature feature); } /** * Retrieves the default registry. * * @return The default Registry. */ public static Registry getDefault() { // Need to handle the return value here, as it is a persistent object // i.e. the java proxy should not dispose of the underlying object when finalized return GstObject.objectFor(gst.gst_registry_get_default(), Registry.class, false, false); } /** Creates a new instance of Registry */ public Registry(Initializer init) { super(init); } /** * Find a plugin in the registry. * * @param name The plugin name to find. * @return The plugin with the given name or null if the plugin was not found. */ public Plugin findPlugin(String name) { return gst.gst_registry_find_plugin(this, name); } /** * Add the plugin to the registry. The plugin-added signal will be emitted. * * @param plugin the {@link Plugin} to add * @return true on success. */ public boolean addPlugin(Plugin plugin) { return gst.gst_registry_add_plugin(this, plugin); } /** * Remove a plugin from the registry. * * @param plugin The plugin to remove. */ public void removePlugin(Plugin plugin) { gst.gst_registry_remove_plugin(this, plugin); } /** * Find the {@link PluginFeature} with the given name and type in the registry. * * @param name The name of the plugin feature to find. * @param type The type of the plugin feature to find. * @return The pluginfeature with the given name and type or null * if the plugin was not found. */ public PluginFeature findPluginFeature(String name, GType type) { return gst.gst_registry_find_feature(this, name, type); } /** * Find a {@link PluginFeature} by name in the registry. * * @param name The name of the plugin feature to find. * @return The {@link PluginFeature} or null if not found. */ public PluginFeature findPluginFeature(String name) { return gst.gst_registry_lookup_feature(this, name); } /** * Get a list of all plugins registered in the registry. * * @return a List of {@link Plugin} */ public List<Plugin> getPluginList() { GList glist = gst.gst_registry_get_plugin_list(this); List<Plugin> list = objectList(glist, Plugin.class); gst.gst_plugin_list_free(glist); return list; } /** * Get a subset of the Plugins in the registry, filtered by filter. * * @param filter the filter to use * @param onlyReturnFirstMatch If true, only return the first plugin that matches the filter. * @return A List of {@link Plugin} objects that match the filter. */ public List<Plugin> getPluginList(final PluginFilter filter, boolean onlyReturnFirstMatch) { List<Plugin> list = new LinkedList<Plugin>(); for (Plugin plugin : getPluginList()) { if (filter.accept(plugin)) { list.add(plugin); } } return list; } /** * Retrieves a list of {@link PluginFeature} of the {@link Plugin} type. * * @param type The plugin type. * @return a List of {@link PluginFeature} for the plugin type. */ public List<PluginFeature> getPluginFeatureListByType(GType type) { GList glist = gst.gst_registry_get_feature_list(this, type); List<PluginFeature> list = objectList(glist, PluginFeature.class); gst.gst_plugin_feature_list_free(glist); return list; } /** * Retrieves a list of {@link PluginFeature} of the named {@link Plugin}. * * @param name The plugin name. * @return a List of {@link PluginFeature} for the named plugin. */ public List<PluginFeature> getPluginFeatureListByPlugin(String name) { GList glist = gst.gst_registry_get_feature_list_by_plugin(this, name); List<PluginFeature> list = objectList(glist, PluginFeature.class); gst.gst_plugin_feature_list_free(glist); return list; } /** * Add the given path to the registry. The syntax of the * path is specific to the registry. If the path has already been * added, do nothing. * * @param path The path to add to the registry. * @return true if the registry changed. */ public boolean scanPath(String path) { return gst.gst_registry_scan_path(this, path); } /** * Build a {@link java.util.List} of {@link GstObject} from the native GList. * @param glist The native list to get the objects from. * @param objectClass The proxy class to wrap the list elements in. * @return The converted list. */ private <T extends GstObject> List<T> objectList(GList glist, Class<T> objectClass) { List<T> list = new ArrayList<T>(); GList next = glist; while (next != null) { if (next.data != null) { list.add(GstObject.objectFor(next.data, objectClass, true, true)); } next = next.next(); } return list; } }