diff options
Diffstat (limited to 'bindings/python/lilv.py')
-rw-r--r-- | bindings/python/lilv.py | 1775 |
1 files changed, 1775 insertions, 0 deletions
diff --git a/bindings/python/lilv.py b/bindings/python/lilv.py new file mode 100644 index 0000000..024bfe7 --- /dev/null +++ b/bindings/python/lilv.py @@ -0,0 +1,1775 @@ +"""Lilv Python interface""" + +__author__ = "David Robillard" +__copyright__ = "Copyright 2016 David Robillard" +__license__ = "ISC" +__version__ = "0.22.1" +__maintainer__ = "David Robillard" +__email__ = "d@drobilla.net" +__status__ = "Production" + +import ctypes +import os +import sys + +from ctypes import Structure, CDLL, POINTER, CFUNCTYPE +from ctypes import c_bool, c_double, c_float, c_int, c_size_t, c_uint, c_uint32 +from ctypes import c_char, c_char_p, c_void_p +from ctypes import byref + +# Load lilv library + +_lib = CDLL("liblilv-0.so") + +# Set namespaced aliases for all lilv functions + +class String(str): + # Wrapper for string parameters to pass as raw C UTF-8 strings + def from_param(cls, obj): + return obj.encode('utf-8') + + from_param = classmethod(from_param) + +def _as_uri(obj): + if type(obj) in [Plugin, PluginClass, UI]: + return obj.get_uri() + else: + return obj + +free = _lib.lilv_free +# uri_to_path = _lib.lilv_uri_to_path +file_uri_parse = _lib.lilv_file_uri_parse +new_uri = _lib.lilv_new_uri +new_file_uri = _lib.lilv_new_file_uri +new_string = _lib.lilv_new_string +new_int = _lib.lilv_new_int +new_float = _lib.lilv_new_float +new_bool = _lib.lilv_new_bool +node_free = _lib.lilv_node_free +node_duplicate = _lib.lilv_node_duplicate +node_equals = _lib.lilv_node_equals +node_get_turtle_token = _lib.lilv_node_get_turtle_token +node_is_uri = _lib.lilv_node_is_uri +node_as_uri = _lib.lilv_node_as_uri +node_is_blank = _lib.lilv_node_is_blank +node_as_blank = _lib.lilv_node_as_blank +node_is_literal = _lib.lilv_node_is_literal +node_is_string = _lib.lilv_node_is_string +node_as_string = _lib.lilv_node_as_string +node_get_path = _lib.lilv_node_get_path +node_is_float = _lib.lilv_node_is_float +node_as_float = _lib.lilv_node_as_float +node_is_int = _lib.lilv_node_is_int +node_as_int = _lib.lilv_node_as_int +node_is_bool = _lib.lilv_node_is_bool +node_as_bool = _lib.lilv_node_as_bool +plugin_classes_free = _lib.lilv_plugin_classes_free +plugin_classes_size = _lib.lilv_plugin_classes_size +plugin_classes_begin = _lib.lilv_plugin_classes_begin +plugin_classes_get = _lib.lilv_plugin_classes_get +plugin_classes_next = _lib.lilv_plugin_classes_next +plugin_classes_is_end = _lib.lilv_plugin_classes_is_end +plugin_classes_get_by_uri = _lib.lilv_plugin_classes_get_by_uri +scale_points_free = _lib.lilv_scale_points_free +scale_points_size = _lib.lilv_scale_points_size +scale_points_begin = _lib.lilv_scale_points_begin +scale_points_get = _lib.lilv_scale_points_get +scale_points_next = _lib.lilv_scale_points_next +scale_points_is_end = _lib.lilv_scale_points_is_end +uis_free = _lib.lilv_uis_free +uis_size = _lib.lilv_uis_size +uis_begin = _lib.lilv_uis_begin +uis_get = _lib.lilv_uis_get +uis_next = _lib.lilv_uis_next +uis_is_end = _lib.lilv_uis_is_end +uis_get_by_uri = _lib.lilv_uis_get_by_uri +nodes_free = _lib.lilv_nodes_free +nodes_size = _lib.lilv_nodes_size +nodes_begin = _lib.lilv_nodes_begin +nodes_get = _lib.lilv_nodes_get +nodes_next = _lib.lilv_nodes_next +nodes_is_end = _lib.lilv_nodes_is_end +nodes_get_first = _lib.lilv_nodes_get_first +nodes_contains = _lib.lilv_nodes_contains +nodes_merge = _lib.lilv_nodes_merge +plugins_size = _lib.lilv_plugins_size +plugins_begin = _lib.lilv_plugins_begin +plugins_get = _lib.lilv_plugins_get +plugins_next = _lib.lilv_plugins_next +plugins_is_end = _lib.lilv_plugins_is_end +plugins_get_by_uri = _lib.lilv_plugins_get_by_uri +world_new = _lib.lilv_world_new +world_set_option = _lib.lilv_world_set_option +world_free = _lib.lilv_world_free +world_load_all = _lib.lilv_world_load_all +world_load_bundle = _lib.lilv_world_load_bundle +world_load_specifications = _lib.lilv_world_load_specifications +world_load_plugin_classes = _lib.lilv_world_load_plugin_classes +world_unload_bundle = _lib.lilv_world_unload_bundle +world_load_resource = _lib.lilv_world_load_resource +world_unload_resource = _lib.lilv_world_unload_resource +world_get_plugin_class = _lib.lilv_world_get_plugin_class +world_get_plugin_classes = _lib.lilv_world_get_plugin_classes +world_get_all_plugins = _lib.lilv_world_get_all_plugins +world_find_nodes = _lib.lilv_world_find_nodes +world_get = _lib.lilv_world_get +world_ask = _lib.lilv_world_ask +plugin_verify = _lib.lilv_plugin_verify +plugin_get_uri = _lib.lilv_plugin_get_uri +plugin_get_bundle_uri = _lib.lilv_plugin_get_bundle_uri +plugin_get_data_uris = _lib.lilv_plugin_get_data_uris +plugin_get_library_uri = _lib.lilv_plugin_get_library_uri +plugin_get_name = _lib.lilv_plugin_get_name +plugin_get_class = _lib.lilv_plugin_get_class +plugin_get_value = _lib.lilv_plugin_get_value +plugin_has_feature = _lib.lilv_plugin_has_feature +plugin_get_supported_features = _lib.lilv_plugin_get_supported_features +plugin_get_required_features = _lib.lilv_plugin_get_required_features +plugin_get_optional_features = _lib.lilv_plugin_get_optional_features +plugin_has_extension_data = _lib.lilv_plugin_has_extension_data +plugin_get_extension_data = _lib.lilv_plugin_get_extension_data +plugin_get_num_ports = _lib.lilv_plugin_get_num_ports +plugin_get_port_ranges_float = _lib.lilv_plugin_get_port_ranges_float +plugin_has_latency = _lib.lilv_plugin_has_latency +plugin_get_latency_port_index = _lib.lilv_plugin_get_latency_port_index +plugin_get_port_by_index = _lib.lilv_plugin_get_port_by_index +plugin_get_port_by_symbol = _lib.lilv_plugin_get_port_by_symbol +plugin_get_port_by_designation = _lib.lilv_plugin_get_port_by_designation +plugin_get_project = _lib.lilv_plugin_get_project +plugin_get_author_name = _lib.lilv_plugin_get_author_name +plugin_get_author_email = _lib.lilv_plugin_get_author_email +plugin_get_author_homepage = _lib.lilv_plugin_get_author_homepage +plugin_is_replaced = _lib.lilv_plugin_is_replaced +plugin_get_related = _lib.lilv_plugin_get_related +port_get_node = _lib.lilv_port_get_node +port_get_value = _lib.lilv_port_get_value +port_get = _lib.lilv_port_get +port_get_properties = _lib.lilv_port_get_properties +port_has_property = _lib.lilv_port_has_property +port_supports_event = _lib.lilv_port_supports_event +port_get_index = _lib.lilv_port_get_index +port_get_symbol = _lib.lilv_port_get_symbol +port_get_name = _lib.lilv_port_get_name +port_get_classes = _lib.lilv_port_get_classes +port_is_a = _lib.lilv_port_is_a +port_get_range = _lib.lilv_port_get_range +port_get_scale_points = _lib.lilv_port_get_scale_points +state_new_from_world = _lib.lilv_state_new_from_world +state_new_from_file = _lib.lilv_state_new_from_file +state_new_from_string = _lib.lilv_state_new_from_string +state_new_from_instance = _lib.lilv_state_new_from_instance +state_free = _lib.lilv_state_free +state_equals = _lib.lilv_state_equals +state_get_num_properties = _lib.lilv_state_get_num_properties +state_get_plugin_uri = _lib.lilv_state_get_plugin_uri +state_get_uri = _lib.lilv_state_get_uri +state_get_label = _lib.lilv_state_get_label +state_set_label = _lib.lilv_state_set_label +state_set_metadata = _lib.lilv_state_set_metadata +state_emit_port_values = _lib.lilv_state_emit_port_values +state_restore = _lib.lilv_state_restore +state_save = _lib.lilv_state_save +state_to_string = _lib.lilv_state_to_string +state_delete = _lib.lilv_state_delete +scale_point_get_label = _lib.lilv_scale_point_get_label +scale_point_get_value = _lib.lilv_scale_point_get_value +plugin_class_get_parent_uri = _lib.lilv_plugin_class_get_parent_uri +plugin_class_get_uri = _lib.lilv_plugin_class_get_uri +plugin_class_get_label = _lib.lilv_plugin_class_get_label +plugin_class_get_children = _lib.lilv_plugin_class_get_children +plugin_instantiate = _lib.lilv_plugin_instantiate +instance_free = _lib.lilv_instance_free +plugin_get_uis = _lib.lilv_plugin_get_uis +ui_get_uri = _lib.lilv_ui_get_uri +ui_get_classes = _lib.lilv_ui_get_classes +ui_is_a = _lib.lilv_ui_is_a +ui_is_supported = _lib.lilv_ui_is_supported +ui_get_bundle_uri = _lib.lilv_ui_get_bundle_uri +ui_get_binary_uri = _lib.lilv_ui_get_binary_uri + +## LV2 types + +LV2_Handle = POINTER(None) +LV2_URID_Map_Handle = POINTER(None) +LV2_URID_Unmap_Handle = POINTER(None) +LV2_URID = c_uint32 + +class LV2_Feature(Structure): + __slots__ = [ 'URI', 'data' ] + _fields_ = [('URI', c_char_p), + ('data', POINTER(None))] + +class LV2_Descriptor(Structure): + __slots__ = [ 'URI', + 'instantiate', + 'connect_port', + 'activate', + 'run', + 'deactivate', + 'cleanup', + 'extension_data' ] + +LV2_Descriptor._fields_ = [ + ('URI', c_char_p), + ('instantiate', CFUNCTYPE(LV2_Handle, POINTER(LV2_Descriptor), + c_double, c_char_p, POINTER(POINTER(LV2_Feature)))), + ('connect_port', CFUNCTYPE(None, LV2_Handle, c_uint32, POINTER(None))), + ('activate', CFUNCTYPE(None, LV2_Handle)), + ('run', CFUNCTYPE(None, LV2_Handle, c_uint32)), + ('deactivate', CFUNCTYPE(None, LV2_Handle)), + ('cleanup', CFUNCTYPE(None, LV2_Handle)), + ('extension_data', CFUNCTYPE(c_void_p, c_char_p)), +] + +class LV2_URID_Map(Structure): + __slots__ = [ 'handle', 'map' ] + _fields_ = [ + ('handle', LV2_URID_Map_Handle), + ('map', CFUNCTYPE(LV2_URID, LV2_URID_Map_Handle, c_char_p)), + ] + +class LV2_URID_Unmap(Structure): + __slots__ = [ 'handle', 'unmap' ] + _fields_ = [ + ('handle', LV2_URID_Unmap_Handle), + ('unmap', CFUNCTYPE(c_char_p, LV2_URID_Unmap_Handle, LV2_URID)), + ] + +# Lilv types + +class Plugin(Structure): + """LV2 Plugin.""" + def __init__(self, world, plugin): + self.world = world + self.plugin = plugin + + def __eq__(self, other): + return self.get_uri() == other.get_uri() + + def verify(self): + """Check if `plugin` is valid. + + This is not a rigorous validator, but can be used to reject some malformed + plugins that could cause bugs (e.g. plugins with missing required fields). + + Note that normal hosts do NOT need to use this - lilv does not + load invalid plugins into plugin lists. This is included for plugin + testing utilities, etc. + """ + return plugin_verify(self.plugin) + + def get_uri(self): + """Get the URI of `plugin`. + + Any serialization that refers to plugins should refer to them by this. + Hosts SHOULD NOT save any filesystem paths, plugin indexes, etc. in saved + files pass save only the URI. + + The URI is a globally unique identifier for one specific plugin. Two + plugins with the same URI are compatible in port signature, and should + be guaranteed to work in a compatible and consistent way. If a plugin + is upgraded in an incompatible way (eg if it has different ports), it + MUST have a different URI than it's predecessor. + """ + return Node.wrap(node_duplicate(plugin_get_uri(self.plugin))) + + def get_bundle_uri(self): + """Get the (resolvable) URI of the plugin's "main" bundle. + + This returns the URI of the bundle where the plugin itself was found. Note + that the data for a plugin may be spread over many bundles, that is, + get_data_uris() may return URIs which are not within this bundle. + + Typical hosts should not need to use this function. + Note this always returns a fully qualified URI. If you want a local + filesystem path, use lilv.file_uri_parse(). + """ + return Node.wrap(node_duplicate(plugin_get_bundle_uri(self.plugin))) + + def get_data_uris(self): + """Get the (resolvable) URIs of the RDF data files that define a plugin. + + Typical hosts should not need to use this function. + Note this always returns fully qualified URIs. If you want local + filesystem paths, use lilv.file_uri_parse(). + """ + return Nodes(plugin_get_data_uris(self.plugin)) + + def get_library_uri(self): + """Get the (resolvable) URI of the shared library for `plugin`. + + Note this always returns a fully qualified URI. If you want a local + filesystem path, use lilv.file_uri_parse(). + """ + return Node.wrap(node_duplicate(plugin_get_library_uri(self.plugin))) + + def get_name(self): + """Get the name of `plugin`. + + This returns the name (doap:name) of the plugin. The name may be + translated according to the current locale, this value MUST NOT be used + as a plugin identifier (use the URI for that). + """ + return Node.wrap(plugin_get_name(self.plugin)) + + def get_class(self): + """Get the class this plugin belongs to (e.g. Filters).""" + return PluginClass(plugin_get_class(self.plugin)) + + def get_value(self, predicate): + """Get a value associated with the plugin in a plugin's data files. + + `predicate` must be either a URI or a QName. + + Returns the ?object of all triples found of the form: + + plugin-uri predicate ?object + + May return None if the property was not found, or if object(s) is not + sensibly represented as a LilvNodes (e.g. blank nodes). + """ + return Nodes(plugin_get_value(self.plugin, predicate.node)) + + def has_feature(self, feature_uri): + """Return whether a feature is supported by a plugin. + + This will return true if the feature is an optional or required feature + of the plugin. + """ + return plugin_has_feature(self.plugin, feature_uri.node) + + def get_supported_features(self): + """Get the LV2 Features supported (required or optionally) by a plugin. + + A feature is "supported" by a plugin if it is required OR optional. + + Since required features have special rules the host must obey, this function + probably shouldn't be used by normal hosts. Using get_optional_features() + and get_required_features() separately is best in most cases. + """ + return Nodes(plugin_get_supported_features(self.plugin)) + + def get_required_features(self): + """Get the LV2 Features required by a plugin. + + If a feature is required by a plugin, hosts MUST NOT use the plugin if they do not + understand (or are unable to support) that feature. + + All values returned here MUST be return plugin_(self.plugin)ed to the plugin's instantiate method + (along with data, if necessary, as defined by the feature specification) + or plugin instantiation will fail. + """ + return Nodes(plugin_get_required_features(self.plugin)) + + def get_optional_features(self): + """Get the LV2 Features optionally supported by a plugin. + + Hosts MAY ignore optional plugin features for whatever reasons. Plugins + MUST operate (at least somewhat) if they are instantiated without being + passed optional features. + """ + return Nodes(plugin_get_optional_features(self.plugin)) + + def has_extension_data(self, uri): + """Return whether or not a plugin provides a specific extension data.""" + return plugin_has_extension_data(self.plugin, uri.node) + + def get_extension_data(self): + """Get a sequence of all extension data provided by a plugin. + + This can be used to find which URIs get_extension_data() + will return a value for without instantiating the plugin. + """ + return Nodes(plugin_get_extension_data(self.plugin)) + + def get_num_ports(self): + """Get the number of ports on this plugin.""" + return plugin_get_num_ports(self.plugin) + + # def get_port_ranges_float(self, min_values, max_values, def_values): + # """Get the port ranges (minimum, maximum and default values) for all ports. + + # `min_values`, `max_values` and `def_values` must either point to an array + # of N floats, where N is the value returned by get_num_ports() + # for this plugin, or None. The elements of the array will be set to the + # the minimum, maximum and default values of the ports on this plugin, + # with array index corresponding to port index. If a port doesn't have a + # minimum, maximum or default value, or the port's type is not float, the + # corresponding array element will be set to NAN. + + # This is a convenience method for the common case of getting the range of + # all float ports on a plugin, and may be significantly faster than + # repeated calls to Port.get_range(). + # """ + # plugin_get_port_ranges_float(self.plugin, min_values, max_values, def_values) + + def get_num_ports_of_class(self, *args): + """Get the number of ports on this plugin that are members of some class(es).""" + args = list(map(lambda x: x.node, args)) + args += (None,) + return plugin_get_num_ports_of_class(self.plugin, *args) + + def has_latency(self): + """Return whether or not the plugin introduces (and reports) latency. + + The index of the latency port can be found with + get_latency_port() ONLY if this function returns true. + """ + return plugin_has_latency(self.plugin) + + def get_latency_port_index(self): + """Return the index of the plugin's latency port. + + Returns None if the plugin has no latency port. + + Any plugin that introduces unwanted latency that should be compensated for + (by hosts with the ability/need) MUST provide this port, which is a control + rate output port that reports the latency for each cycle in frames. + """ + return plugin_get_latency_port_index(self.plugin) if self.has_latency() else None + + def get_port(self, key): + """Get a port on `plugin` by index or symbol.""" + if type(key) == int: + return self.get_port_by_index(key) + else: + return self.get_port_by_symbol(key) + + def get_port_by_index(self, index): + """Get a port on `plugin` by `index`.""" + return Port.wrap(self, plugin_get_port_by_index(self.plugin, index)) + + def get_port_by_symbol(self, symbol): + """Get a port on `plugin` by `symbol`. + + Note this function is slower than get_port_by_index(), + especially on plugins with a very large number of ports. + """ + if type(symbol) == str: + symbol = self.world.new_string(symbol) + return Port.wrap(self, plugin_get_port_by_symbol(self.plugin, symbol.node)) + + def get_port_by_designation(self, port_class, designation): + """Get a port on `plugin` by its lv2:designation. + + The designation of a port describes the meaning, assignment, allocation or + role of the port, e.g. "left channel" or "gain". If found, the port with + matching `port_class` and `designation` is be returned, otherwise None is + returned. The `port_class` can be used to distinguish the input and output + ports for a particular designation. If `port_class` is None, any port with + the given designation will be returned. + """ + return Port.wrap(self, + plugin_get_port_by_designation(self.plugin, + port_class.node, + designation.node)) + + def get_project(self): + """Get the project the plugin is a part of. + + More information about the project can be read via find_nodes(), + typically using properties from DOAP (e.g. doap:name). + """ + return Node.wrap(plugin_get_project(self.plugin)) + + def get_author_name(self): + """Get the full name of the plugin's author. + + Returns None if author name is not present. + """ + return Node.wrap(plugin_get_author_name(self.plugin)) + + def get_author_email(self): + """Get the email address of the plugin's author. + + Returns None if author email address is not present. + """ + return Node.wrap(plugin_get_author_email(self.plugin)) + + def get_author_homepage(self): + """Get the address of the plugin author's home page. + + Returns None if author homepage is not present. + """ + return Node.wrap(plugin_get_author_homepage(self.plugin)) + + def is_replaced(self): + """Return true iff `plugin` has been replaced by another plugin. + + The plugin will still be usable, but hosts should hide them from their + user interfaces to prevent users from using deprecated plugins. + """ + return plugin_is_replaced(self.plugin) + + def get_related(self, resource_type): + """Get the resources related to `plugin` with lv2:appliesTo. + + Some plugin-related resources are not linked directly to the plugin with + rdfs:seeAlso and thus will not be automatically loaded along with the plugin + data (usually for performance reasons). All such resources of the given @c + type related to `plugin` can be accessed with this function. + + If `resource_type` is None, all such resources will be returned, regardless of type. + + To actually load the data for each returned resource, use world.load_resource(). + """ + return Nodes(plugin_get_related(self.plugin, resource_type)) + + def get_uis(self): + """Get all UIs for `plugin`.""" + return UIs(plugin_get_uis(self.plugin)) + +class PluginClass(Structure): + """Plugin Class (type/category).""" + def __init__(self, plugin_class): + self.plugin_class = plugin_class + + def __str__(self): + return self.get_uri().__str__() + + def get_parent_uri(self): + """Get the URI of this class' superclass. + + May return None if class has no parent. + """ + return Node.wrap(node_duplicate(plugin_class_get_parent_uri(self.plugin_class))) + + def get_uri(self): + """Get the URI of this plugin class.""" + return Node.wrap(node_duplicate(plugin_class_get_uri(self.plugin_class))) + + def get_label(self): + """Get the label of this plugin class, ie "Oscillators".""" + return Node.wrap(node_duplicate(plugin_class_get_label(self.plugin_class))) + + def get_children(self): + """Get the subclasses of this plugin class.""" + return PluginClasses(plugin_class_get_children(self.plugin_class)) + +class Port(Structure): + """Port on a Plugin.""" + @classmethod + def wrap(cls, plugin, port): + return Port(plugin, port) if plugin and port else None + + def __init__(self, plugin, port): + self.plugin = plugin + self.port = port + + def get_node(self): + """Get the RDF node of `port`. + + Ports nodes may be may be URIs or blank nodes. + """ + return Node.wrap(node_duplicate(port_get_node(self.plugin, self.port))) + + def get_value(self, predicate): + """Port analog of Plugin.get_value().""" + return Nodes(port_get_value(self.plugin.plugin, self.port, predicate.node)) + + def get(self, predicate): + """Get a single property value of a port. + + This is equivalent to lilv_nodes_get_first(lilv_port_get_value(...)) but is + simpler to use in the common case of only caring about one value. The + caller is responsible for freeing the returned node. + """ + return Node.wrap(port_get(self.plugin.plugin, self.port, predicate.node)) + + def get_properties(self): + """Return the LV2 port properties of a port.""" + return Nodes(port_get_properties(self.plugin.plugin, self.port)) + + def has_property(self, property_uri): + """Return whether a port has a certain property.""" + return port_has_property(self.plugin.plugin, self.port, property_uri.node) + + def supports_event(self, event_type): + """Return whether a port supports a certain event type. + + More precisely, this returns true iff the port has an atom:supports or an + ev:supportsEvent property with `event_type` as the value. + """ + return port_supports_event(self.plugin.plugin, self.port, event_type.node) + + def get_index(self): + """Get the index of a port. + + The index is only valid for the life of the plugin and may change between + versions. For a stable identifier, use the symbol. + """ + return port_get_index(self.plugin.plugin, self.port) + + def get_symbol(self): + """Get the symbol of a port. + + The 'symbol' is a short string, a valid C identifier. + """ + return Node.wrap(node_duplicate(port_get_symbol(self.plugin.plugin, self.port))) + + def get_name(self): + """Get the name of a port. + + This is guaranteed to return the untranslated name (the doap:name in the + data file without a language tag). + """ + return Node.wrap(port_get_name(self.plugin.plugin, self.port)) + + def get_classes(self): + """Get all the classes of a port. + + This can be used to determine if a port is an input, output, audio, + control, midi, etc, etc, though it's simpler to use is_a(). + The returned list does not include lv2:Port, which is implied. + Returned value is shared and must not be destroyed by caller. + """ + return Nodes(port_get_classes(self.plugin.plugin, self.port)) + + def is_a(self, port_class): + """Determine if a port is of a given class (input, output, audio, etc). + + For convenience/performance/extensibility reasons, hosts are expected to + create a LilvNode for each port class they "care about". Well-known type + URI strings are defined (e.g. LILV_URI_INPUT_PORT) for convenience, but + this function is designed so that Lilv is usable with any port types + without requiring explicit support in Lilv. + """ + return port_is_a(self.plugin.plugin, self.port, port_class.node) + + def get_range(self): + """Return the default, minimum, and maximum values of a port as a tuple.""" + pdef = POINTER(Node)() + pmin = POINTER(Node)() + pmax = POINTER(Node)() + port_get_range(self.plugin.plugin, self.port, byref(pdef), byref(pmin), byref(pmax)) + return (Node(pdef.contents) if pdef else None, + Node(pmin.contents) if pmin else None, + Node(pmax.contents) if pmax else None) + + def get_scale_points(self): + """Get the scale points (enumeration values) of a port. + + This returns a collection of 'interesting' named values of a port + (e.g. appropriate entries for a UI selector associated with this port). + Returned value may be None if `port` has no scale points. + """ + return ScalePoints(port_get_scale_points(self.plugin.plugin, self.port)) + +class ScalePoint(Structure): + """Scale point (detent).""" + def __init__(self, point): + self.point = point + + def get_label(self): + """Get the label of this scale point (enumeration value).""" + return Node.wrap(scale_point_get_label(self.point)) + + def get_value(self): + """Get the value of this scale point (enumeration value).""" + return Node.wrap(scale_point_get_value(self.point)) + +class UI(Structure): + """Plugin UI.""" + def __init__(self, ui): + self.ui = ui + + def __str__(self): + return str(self.get_uri()) + + def __eq__(self, other): + return self.get_uri() == _as_uri(other) + + def get_uri(self): + """Get the URI of a Plugin UI.""" + return Node.wrap(node_duplicate(ui_get_uri(self.ui))) + + def get_classes(self): + """Get the types (URIs of RDF classes) of a Plugin UI. + + Note that in most cases is_supported() should be used, which avoids + the need to use this function (and type specific logic). + """ + return Nodes(ui_get_classes(self.ui)) + + def is_a(self, class_uri): + """Check whether a plugin UI has a given type.""" + return ui_is_a(self.ui, class_uri.node) + + def get_bundle_uri(self): + """Get the URI of the UI's bundle.""" + return Node.wrap(node_duplicate(ui_get_bundle_uri(self.ui))) + + def get_binary_uri(self): + """Get the URI for the UI's shared library.""" + return Node.wrap(node_duplicate(ui_get_binary_uri(self.ui))) + +class Node(Structure): + """Data node (URI, string, integer, etc.). + + A Node can be converted to the corresponding Python datatype, and all nodes + can be converted to strings, for example:: + + >>> world = lilv.World() + >>> i = world.new_int(42) + >>> print(i) + 42 + >>> int(i) * 2 + 84 + """ + @classmethod + def wrap(cls, node): + return Node(node) if node else None + + def __init__(self, node): + self.node = node + + def __del__(self): + if hasattr(self, 'node'): + node_free(self.node) + + def __eq__(self, other): + otype = type(other) + if otype in [str, int, float]: + return otype(self) == other + return node_equals(self.node, other.node) + + def __ne__(self, other): + return not node_equals(self.node, other.node) + + def __str__(self): + return node_as_string(self.node).decode('utf-8') + + def __int__(self): + if not self.is_int(): + raise ValueError('node %s is not an integer' % str(self)) + return node_as_int(self.node) + + def __float__(self): + if not self.is_float(): + raise ValueError('node %s is not a float' % str(self)) + return node_as_float(self.node) + + def __bool__(self): + if not self.is_bool(): + raise ValueError('node %s is not a bool' % str(self)) + return node_as_bool(self.node) + __nonzero__ = __bool__ + + def get_turtle_token(self): + """Return this value as a Turtle/SPARQL token.""" + return node_get_turtle_token(self.node).decode('utf-8') + + def is_uri(self): + """Return whether the value is a URI (resource).""" + return node_is_uri(self.node) + + def is_blank(self): + """Return whether the value is a blank node (resource with no URI).""" + return node_is_blank(self.node) + + def is_literal(self): + """Return whether this value is a literal (i.e. not a URI).""" + return node_is_literal(self.node) + + def is_string(self): + """Return whether this value is a string literal. + + Returns true if value is a string value (and not numeric). + """ + return node_is_string(self.node) + + def get_path(self, hostname=None): + """Return the path of a file URI node. + + Returns None if value is not a file URI.""" + return node_get_path(self.node, hostname).decode('utf-8') + + def is_float(self): + """Return whether this value is a decimal literal.""" + return node_is_float(self.node) + + def is_int(self): + """Return whether this value is an integer literal.""" + return node_is_int(self.node) + + def is_bool(self): + """Return whether this value is a boolean.""" + return node_is_bool(self.node) + +class Iter(Structure): + """Collection iterator.""" + def __init__(self, collection, iterator, constructor, iter_get, iter_next, iter_is_end): + self.collection = collection + self.iterator = iterator + self.constructor = constructor + self.iter_get = iter_get + self.iter_next = iter_next + self.iter_is_end = iter_is_end + + def get(self): + """Get the current item.""" + return self.constructor(self.iter_get(self.collection, self.iterator)) + + def next(self): + """Move to and return the next item.""" + if self.is_end(): + raise StopIteration + elem = self.get() + self.iterator = self.iter_next(self.collection, self.iterator) + return elem + + def is_end(self): + """Return true if the end of the collection has been reached.""" + return self.iter_is_end(self.collection, self.iterator) + + __next__ = next + +class Collection(Structure): + # Base class for all lilv collection wrappers. + def __init__(self, collection, iter_begin, constructor, iter_get, iter_next, is_end): + self.collection = collection + self.constructor = constructor + self.iter_begin = iter_begin + self.iter_get = iter_get + self.iter_next = iter_next + self.is_end = is_end + + def __iter__(self): + return Iter(self.collection, self.iter_begin(self.collection), self.constructor, + self.iter_get, self.iter_next, self.is_end) + + def __getitem__(self, index): + if index >= len(self): + raise IndexError + pos = 0 + for i in self: + if pos == index: + return i + pos += 1 + + def begin(self): + return self.__iter__() + + def get(self, iterator): + return iterator.get() + +class Plugins(Collection): + """Collection of plugins.""" + def __init__(self, world, collection): + def constructor(plugin): + return Plugin(world, plugin) + + super(Plugins, self).__init__(collection, plugins_begin, constructor, plugins_get, plugins_next, plugins_is_end) + self.world = world + + def __contains__(self, key): + return bool(self.get_by_uri(_as_uri(key))) + + def __len__(self): + return plugins_size(self.collection) + + def __getitem__(self, key): + if type(key) == int: + return super(Plugins, self).__getitem__(key) + return self.get_by_uri(key) + + def get_by_uri(self, uri): + plugin = plugins_get_by_uri(self.collection, uri.node) + return Plugin(self.world, plugin) if plugin else None + +class PluginClasses(Collection): + """Collection of plugin classes.""" + def __init__(self, collection): + super(PluginClasses, self).__init__( + collection, plugin_classes_begin, PluginClass, + plugin_classes_get, plugin_classes_next, plugin_classes_is_end) + + def __contains__(self, key): + return bool(self.get_by_uri(_as_uri(key))) + + def __len__(self): + return plugin_classes_size(self.collection) + + def __getitem__(self, key): + if type(key) == int: + return super(PluginClasses, self).__getitem__(key) + return self.get_by_uri(key) + + def get_by_uri(self, uri): + plugin_class = plugin_classes_get_by_uri(self.collection, uri.node) + return PluginClass(plugin_class) if plugin_class else None + +class ScalePoints(Collection): + """Collection of scale points.""" + def __init__(self, collection): + super(ScalePoints, self).__init__( + collection, scale_points_begin, ScalePoint, + scale_points_get, scale_points_next, scale_points_is_end) + + def __len__(self): + return scale_points_size(self.collection) + +class UIs(Collection): + """Collection of plugin UIs.""" + def __init__(self, collection): + super(UIs, self).__init__(collection, uis_begin, UI, + uis_get, uis_next, uis_is_end) + + def __contains__(self, uri): + return bool(self.get_by_uri(_as_uri(uri))) + + def __len__(self): + return uis_size(self.collection) + + def __getitem__(self, key): + if type(key) == int: + return super(UIs, self).__getitem__(key) + return self.get_by_uri(key) + + def get_by_uri(self, uri): + ui = uis_get_by_uri(self.collection, uri.node) + return UI(ui) if ui else None + +class Nodes(Collection): + """Collection of data nodes.""" + @classmethod + def constructor(ignore, node): + return Node(node_duplicate(node)) + + def __init__(self, collection): + super(Nodes, self).__init__(collection, nodes_begin, Nodes.constructor, + nodes_get, nodes_next, nodes_is_end) + + def __contains__(self, value): + return nodes_contains(self.collection, value.node) + + def __len__(self): + return nodes_size(self.collection) + + def merge(self, b): + return Nodes(nodes_merge(self.collection, b.collection)) + +class Namespace(): + """Namespace prefix. + + Use attribute syntax to easily create URIs within this namespace, for + example:: + + >>> world = lilv.World() + >>> ns = Namespace(world, "http://example.org/") + >>> print(ns.foo) + http://example.org/foo + """ + def __init__(self, world, prefix): + self.world = world + self.prefix = prefix + + def __eq__(self, other): + return str(self) == str(other) + + def __str__(self): + return self.prefix + + def __getattr__(self, suffix): + return self.world.new_uri(self.prefix + suffix) + +class World(Structure): + """Library context. + + Includes a set of namespaces as the instance variable `ns`, so URIs can be constructed like:: + + uri = world.ns.lv2.Plugin + + :ivar ns: Common LV2 namespace prefixes: atom, doap, foaf, lilv, lv2, midi, owl, rdf, rdfs, ui, xsd. + """ + def __init__(self): + world = self + + # Define Namespaces class locally so available prefixes are documented + class Namespaces(): + """Set of namespaces. + + Use to easily construct uris, like: ns.lv2.InputPort""" + + atom = Namespace(world, 'http://lv2plug.in/ns/ext/atom#') + doap = Namespace(world, 'http://usefulinc.com/ns/doap#') + foaf = Namespace(world, 'http://xmlns.com/foaf/0.1/') + lilv = Namespace(world, 'http://drobilla.net/ns/lilv#') + lv2 = Namespace(world, 'http://lv2plug.in/ns/lv2core#') + midi = Namespace(world, 'http://lv2plug.in/ns/ext/midi#') + owl = Namespace(world, 'http://www.w3.org/2002/07/owl#') + rdf = Namespace(world, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#') + rdfs = Namespace(world, 'http://www.w3.org/2000/01/rdf-schema#') + ui = Namespace(world, 'http://lv2plug.in/ns/extensions/ui#') + xsd = Namespace(world, 'http://www.w3.org/2001/XMLSchema#') + + self.world = _lib.lilv_world_new() + self.ns = Namespaces() + + def __del__(self): + world_free(self.world) + + def set_option(self, uri, value): + """Set a world option. + + Currently recognized options: + lilv.OPTION_FILTER_LANG + lilv.OPTION_DYN_MANIFEST + """ + return world_set_option(self, uri, value.node) + + def load_all(self): + """Load all installed LV2 bundles on the system. + + This is the recommended way for hosts to load LV2 data. It implements the + established/standard best practice for discovering all LV2 data on the + system. The environment variable LV2_PATH may be used to control where + this function will look for bundles. + + Hosts should use this function rather than explicitly load bundles, except + in special circumstances (e.g. development utilities, or hosts that ship + with special plugin bundles which are installed to a known location). + """ + world_load_all(self.world) + + def load_bundle(self, bundle_uri): + """Load a specific bundle. + + `bundle_uri` must be a fully qualified URI to the bundle directory, + with the trailing slash, eg. file:///usr/lib/lv2/foo.lv2/ + + Normal hosts should not need this function (use load_all()). + + Hosts MUST NOT attach any long-term significance to bundle paths + (e.g. in save files), since there are no guarantees they will remain + unchanged between (or even during) program invocations. Plugins (among + other things) MUST be identified by URIs (not paths) in save files. + """ + world_load_bundle(self.world, bundle_uri.node) + + def load_specifications(self): + """Load all specifications from currently loaded bundles. + + This is for hosts that explicitly load specific bundles, its use is not + necessary when using load_all(). This function parses the + specifications and adds them to the model. + """ + world_load_specifications(self.world) + + def load_plugin_classes(self): + """Load all plugin classes from currently loaded specifications. + + Must be called after load_specifications(). This is for hosts + that explicitly load specific bundles, its use is not necessary when using + load_all(). + """ + world_load_plugin_classes(self.world) + + def unload_bundle(self, bundle_uri): + """Unload a specific bundle. + + This unloads statements loaded by load_bundle(). Note that this + is not necessarily all information loaded from the bundle. If any resources + have been separately loaded with load_resource(), they must be + separately unloaded with unload_resource(). + """ + return world_unload_bundle(self.world, bundle_uri.node) + + def load_resource(self, resource): + """Load all the data associated with the given `resource`. + + The resource must be a subject (i.e. a URI or a blank node). + Returns the number of files parsed, or -1 on error. + + All accessible data files linked to `resource` with rdfs:seeAlso will be + loaded into the world model. + """ + return world_load_resource(self.world, _as_uri(resource).node) + + def unload_resource(self, resource): + """Unload all the data associated with the given `resource`. + + The resource must be a subject (i.e. a URI or a blank node). + + This unloads all data loaded by a previous call to + load_resource() with the given `resource`. + """ + return world_unload_resource(self.world, _as_uri(resource).node) + + def get_plugin_class(self): + """Get the parent of all other plugin classes, lv2:Plugin.""" + return PluginClass(world_get_plugin_class(self.world)) + + def get_plugin_classes(self): + """Return a list of all found plugin classes.""" + return PluginClasses(world_get_plugin_classes(self.world)) + + def get_all_plugins(self): + """Return a list of all found plugins. + + The returned list contains just enough references to query + or instantiate plugins. The data for a particular plugin will not be + loaded into memory until a call to an lilv_plugin_* function results in + a query (at which time the data is cached with the LilvPlugin so future + queries are very fast). + + The returned list and the plugins it contains are owned by `world` + and must not be freed by caller. + """ + return Plugins(self, _lib.lilv_world_get_all_plugins(self.world)) + + def find_nodes(self, subject, predicate, obj): + """Find nodes matching a triple pattern. + + Either `subject` or `object` may be None (i.e. a wildcard), but not both. + Returns all matches for the wildcard field, or None. + """ + return Nodes(world_find_nodes(self.world, + subject.node if subject is not None else None, + predicate.node if predicate is not None else None, + obj.node if obj is not None else None)) + + def get(self, subject, predicate, obj): + """Find a single node that matches a pattern. + + Exactly one of `subject`, `predicate`, `object` must be None. + + Returns the first matching node, or None if no matches are found. + """ + return Node.wrap(world_get(self.world, + subject.node if subject is not None else None, + predicate.node if predicate is not None else None, + obj.node if obj is not None else None)) + + def ask(self, subject, predicate, obj): + """Return true iff a statement matching a certain pattern exists. + + This is useful for checking if particular statement exists without having to + bother with collections and memory management. + """ + return world_ask(self.world, + subject.node if subject is not None else None, + predicate.node if predicate is not None else None, + obj.node if obj is not None else None) + + def new_uri(self, uri): + """Create a new URI node.""" + return Node.wrap(_lib.lilv_new_uri(self.world, uri)) + + def new_file_uri(self, host, path): + """Create a new file URI node. The host may be None.""" + return Node.wrap(_lib.lilv_new_file_uri(self.world, host, path)) + + def new_string(self, string): + """Create a new string node.""" + return Node.wrap(_lib.lilv_new_string(self.world, string)) + + def new_int(self, val): + """Create a new int node.""" + return Node.wrap(_lib.lilv_new_int(self.world, val)) + + def new_float(self, val): + """Create a new float node.""" + return Node.wrap(_lib.lilv_new_float(self.world, val)) + + def new_bool(self, val): + """Create a new bool node.""" + return Node.wrap(_lib.lilv_new_bool(self.world, val)) + +class Instance(Structure): + """Plugin instance.""" + __slots__ = [ 'lv2_descriptor', 'lv2_handle', 'pimpl', 'plugin', 'rate', 'instance' ] + _fields_ = [ + ('lv2_descriptor', POINTER(LV2_Descriptor)), + ('lv2_handle', LV2_Handle), + ('pimpl', POINTER(None)), + ] + + def __init__(self, plugin, rate, features=None): + self.plugin = plugin + self.rate = rate + self.instance = plugin_instantiate(plugin.plugin, rate, features) + + def get_uri(self): + """Get the URI of the plugin which `instance` is an instance of. + + Returned string is shared and must not be modified or deleted. + """ + return self.get_descriptor().URI + + def connect_port(self, port_index, data): + """Connect a port to a data location. + + This may be called regardless of whether the plugin is activated, + activation and deactivation does not destroy port connections. + """ + import numpy + if data is None: + self.get_descriptor().connect_port( + self.get_handle(), + port_index, + data) + elif type(data) == numpy.ndarray: + self.get_descriptor().connect_port( + self.get_handle(), + port_index, + data.ctypes.data_as(POINTER(c_float))) + else: + raise Exception("Unsupported data type") + + def activate(self): + """Activate a plugin instance. + + This resets all state information in the plugin, except for port data + locations (as set by connect_port()). This MUST be called + before calling run(). + """ + if self.get_descriptor().activate: + self.get_descriptor().activate(self.get_handle()) + + def run(self, sample_count): + """Run `instance` for `sample_count` frames. + + If the hint lv2:hardRTCapable is set for this plugin, this function is + guaranteed not to block. + """ + self.get_descriptor().run(self.get_handle(), sample_count) + + def deactivate(self): + """Deactivate a plugin instance. + + Note that to run the plugin after this you must activate it, which will + reset all state information (except port connections). + """ + if self.get_descriptor().deactivate: + self.get_descriptor().deactivate(self.get_handle()) + + def get_extension_data(self, uri): + """Get extension data from the plugin instance. + + The type and semantics of the data returned is specific to the particular + extension, though in all cases it is shared and must not be deleted. + """ + if self.get_descriptor().extension_data: + return self.get_descriptor().extension_data(str(uri)) + + def get_descriptor(self): + """Get the LV2_Descriptor of the plugin instance. + + Normally hosts should not need to access the LV2_Descriptor directly, + use the lilv_instance_* functions. + """ + return self.instance[0].lv2_descriptor[0] + + def get_handle(self): + """Get the LV2_Handle of the plugin instance. + + Normally hosts should not need to access the LV2_Handle directly, + use the lilv_instance_* functions. + """ + return self.instance[0].lv2_handle + +class State(Structure): + """Plugin state (TODO).""" + pass + +class VariadicFunction(object): + # Wrapper for calling C variadic functions + def __init__(self, function, restype, argtypes): + self.function = function + self.function.restype = restype + self.argtypes = argtypes + + def __call__(self, *args): + fixed_args = [] + i = 0 + for argtype in self.argtypes: + fixed_args.append(argtype.from_param(args[i])) + i += 1 + return self.function(*fixed_args + list(args[i:])) + +# Set return and argument types for lilv C functions + +free.argtypes = [POINTER(None)] +free.restype = None + +# uri_to_path.argtypes = [String] +# uri_to_path.restype = c_char_p + +file_uri_parse.argtypes = [String, POINTER(POINTER(c_char))] +file_uri_parse.restype = c_char_p + +new_uri.argtypes = [POINTER(World), String] +new_uri.restype = POINTER(Node) + +new_file_uri.argtypes = [POINTER(World), c_char_p, String] +new_file_uri.restype = POINTER(Node) + +new_string.argtypes = [POINTER(World), String] +new_string.restype = POINTER(Node) + +new_int.argtypes = [POINTER(World), c_int] +new_int.restype = POINTER(Node) + +new_float.argtypes = [POINTER(World), c_float] +new_float.restype = POINTER(Node) + +new_bool.argtypes = [POINTER(World), c_bool] +new_bool.restype = POINTER(Node) + +node_free.argtypes = [POINTER(Node)] +node_free.restype = None + +node_duplicate.argtypes = [POINTER(Node)] +node_duplicate.restype = POINTER(Node) + +node_equals.argtypes = [POINTER(Node), POINTER(Node)] +node_equals.restype = c_bool + +node_get_turtle_token.argtypes = [POINTER(Node)] +node_get_turtle_token.restype = c_char_p + +node_is_uri.argtypes = [POINTER(Node)] +node_is_uri.restype = c_bool + +node_as_uri.argtypes = [POINTER(Node)] +node_as_uri.restype = c_char_p + +node_is_blank.argtypes = [POINTER(Node)] +node_is_blank.restype = c_bool + +node_as_blank.argtypes = [POINTER(Node)] +node_as_blank.restype = c_char_p + +node_is_literal.argtypes = [POINTER(Node)] +node_is_literal.restype = c_bool + +node_is_string.argtypes = [POINTER(Node)] +node_is_string.restype = c_bool + +node_as_string.argtypes = [POINTER(Node)] +node_as_string.restype = c_char_p + +node_get_path.argtypes = [POINTER(Node), POINTER(POINTER(c_char))] +node_get_path.restype = c_char_p + +node_is_float.argtypes = [POINTER(Node)] +node_is_float.restype = c_bool + +node_as_float.argtypes = [POINTER(Node)] +node_as_float.restype = c_float + +node_is_int.argtypes = [POINTER(Node)] +node_is_int.restype = c_bool + +node_as_int.argtypes = [POINTER(Node)] +node_as_int.restype = c_int + +node_is_bool.argtypes = [POINTER(Node)] +node_is_bool.restype = c_bool + +node_as_bool.argtypes = [POINTER(Node)] +node_as_bool.restype = c_bool + +plugin_classes_free.argtypes = [POINTER(PluginClasses)] +plugin_classes_free.restype = None + +plugin_classes_size.argtypes = [POINTER(PluginClasses)] +plugin_classes_size.restype = c_uint + +plugin_classes_begin.argtypes = [POINTER(PluginClasses)] +plugin_classes_begin.restype = POINTER(Iter) + +plugin_classes_get.argtypes = [POINTER(PluginClasses), POINTER(Iter)] +plugin_classes_get.restype = POINTER(PluginClass) + +plugin_classes_next.argtypes = [POINTER(PluginClasses), POINTER(Iter)] +plugin_classes_next.restype = POINTER(Iter) + +plugin_classes_is_end.argtypes = [POINTER(PluginClasses), POINTER(Iter)] +plugin_classes_is_end.restype = c_bool + +plugin_classes_get_by_uri.argtypes = [POINTER(PluginClasses), POINTER(Node)] +plugin_classes_get_by_uri.restype = POINTER(PluginClass) + +scale_points_free.argtypes = [POINTER(ScalePoints)] +scale_points_free.restype = None + +scale_points_size.argtypes = [POINTER(ScalePoints)] +scale_points_size.restype = c_uint + +scale_points_begin.argtypes = [POINTER(ScalePoints)] +scale_points_begin.restype = POINTER(Iter) + +scale_points_get.argtypes = [POINTER(ScalePoints), POINTER(Iter)] +scale_points_get.restype = POINTER(ScalePoint) + +scale_points_next.argtypes = [POINTER(ScalePoints), POINTER(Iter)] +scale_points_next.restype = POINTER(Iter) + +scale_points_is_end.argtypes = [POINTER(ScalePoints), POINTER(Iter)] +scale_points_is_end.restype = c_bool + +uis_free.argtypes = [POINTER(UIs)] +uis_free.restype = None + +uis_size.argtypes = [POINTER(UIs)] +uis_size.restype = c_uint + +uis_begin.argtypes = [POINTER(UIs)] +uis_begin.restype = POINTER(Iter) + +uis_get.argtypes = [POINTER(UIs), POINTER(Iter)] +uis_get.restype = POINTER(UI) + +uis_next.argtypes = [POINTER(UIs), POINTER(Iter)] +uis_next.restype = POINTER(Iter) + +uis_is_end.argtypes = [POINTER(UIs), POINTER(Iter)] +uis_is_end.restype = c_bool + +uis_get_by_uri.argtypes = [POINTER(UIs), POINTER(Node)] +uis_get_by_uri.restype = POINTER(UI) + +nodes_free.argtypes = [POINTER(Nodes)] +nodes_free.restype = None + +nodes_size.argtypes = [POINTER(Nodes)] +nodes_size.restype = c_uint + +nodes_begin.argtypes = [POINTER(Nodes)] +nodes_begin.restype = POINTER(Iter) + +nodes_get.argtypes = [POINTER(Nodes), POINTER(Iter)] +nodes_get.restype = POINTER(Node) + +nodes_next.argtypes = [POINTER(Nodes), POINTER(Iter)] +nodes_next.restype = POINTER(Iter) + +nodes_is_end.argtypes = [POINTER(Nodes), POINTER(Iter)] +nodes_is_end.restype = c_bool + +nodes_get_first.argtypes = [POINTER(Nodes)] +nodes_get_first.restype = POINTER(Node) + +nodes_contains.argtypes = [POINTER(Nodes), POINTER(Node)] +nodes_contains.restype = c_bool + +nodes_merge.argtypes = [POINTER(Nodes), POINTER(Nodes)] +nodes_merge.restype = POINTER(Nodes) + +plugins_size.argtypes = [POINTER(Plugins)] +plugins_size.restype = c_uint + +plugins_begin.argtypes = [POINTER(Plugins)] +plugins_begin.restype = POINTER(Iter) + +plugins_get.argtypes = [POINTER(Plugins), POINTER(Iter)] +plugins_get.restype = POINTER(Plugin) + +plugins_next.argtypes = [POINTER(Plugins), POINTER(Iter)] +plugins_next.restype = POINTER(Iter) + +plugins_is_end.argtypes = [POINTER(Plugins), POINTER(Iter)] +plugins_is_end.restype = c_bool + +plugins_get_by_uri.argtypes = [POINTER(Plugins), POINTER(Node)] +plugins_get_by_uri.restype = POINTER(Plugin) + +world_new.argtypes = [] +world_new.restype = POINTER(World) + +world_set_option.argtypes = [POINTER(World), String, POINTER(Node)] +world_set_option.restype = None + +world_free.argtypes = [POINTER(World)] +world_free.restype = None + +world_load_all.argtypes = [POINTER(World)] +world_load_all.restype = None + +world_load_bundle.argtypes = [POINTER(World), POINTER(Node)] +world_load_bundle.restype = None + +world_load_specifications.argtypes = [POINTER(World)] +world_load_specifications.restype = None + +world_load_plugin_classes.argtypes = [POINTER(World)] +world_load_plugin_classes.restype = None + +world_unload_bundle.argtypes = [POINTER(World), POINTER(Node)] +world_unload_bundle.restype = c_int + +world_load_resource.argtypes = [POINTER(World), POINTER(Node)] +world_load_resource.restype = c_int + +world_unload_resource.argtypes = [POINTER(World), POINTER(Node)] +world_unload_resource.restype = c_int + +world_get_plugin_class.argtypes = [POINTER(World)] +world_get_plugin_class.restype = POINTER(PluginClass) + +world_get_plugin_classes.argtypes = [POINTER(World)] +world_get_plugin_classes.restype = POINTER(PluginClasses) + +world_get_all_plugins.argtypes = [POINTER(World)] +world_get_all_plugins.restype = POINTER(Plugins) + +world_find_nodes.argtypes = [POINTER(World), POINTER(Node), POINTER(Node), POINTER(Node)] +world_find_nodes.restype = POINTER(Nodes) + +world_get.argtypes = [POINTER(World), POINTER(Node), POINTER(Node), POINTER(Node)] +world_get.restype = POINTER(Node) + +world_ask.argtypes = [POINTER(World), POINTER(Node), POINTER(Node), POINTER(Node)] +world_ask.restype = c_bool + +plugin_verify.argtypes = [POINTER(Plugin)] +plugin_verify.restype = c_bool + +plugin_get_uri.argtypes = [POINTER(Plugin)] +plugin_get_uri.restype = POINTER(Node) + +plugin_get_bundle_uri.argtypes = [POINTER(Plugin)] +plugin_get_bundle_uri.restype = POINTER(Node) + +plugin_get_data_uris.argtypes = [POINTER(Plugin)] +plugin_get_data_uris.restype = POINTER(Nodes) + +plugin_get_library_uri.argtypes = [POINTER(Plugin)] +plugin_get_library_uri.restype = POINTER(Node) + +plugin_get_name.argtypes = [POINTER(Plugin)] +plugin_get_name.restype = POINTER(Node) + +plugin_get_class.argtypes = [POINTER(Plugin)] +plugin_get_class.restype = POINTER(PluginClass) + +plugin_get_value.argtypes = [POINTER(Plugin), POINTER(Node)] +plugin_get_value.restype = POINTER(Nodes) + +plugin_has_feature.argtypes = [POINTER(Plugin), POINTER(Node)] +plugin_has_feature.restype = c_bool + +plugin_get_supported_features.argtypes = [POINTER(Plugin)] +plugin_get_supported_features.restype = POINTER(Nodes) + +plugin_get_required_features.argtypes = [POINTER(Plugin)] +plugin_get_required_features.restype = POINTER(Nodes) + +plugin_get_optional_features.argtypes = [POINTER(Plugin)] +plugin_get_optional_features.restype = POINTER(Nodes) + +plugin_has_extension_data.argtypes = [POINTER(Plugin), POINTER(Node)] +plugin_has_extension_data.restype = c_bool + +plugin_get_extension_data.argtypes = [POINTER(Plugin)] +plugin_get_extension_data.restype = POINTER(Nodes) + +plugin_get_num_ports.argtypes = [POINTER(Plugin)] +plugin_get_num_ports.restype = c_uint32 + +plugin_get_port_ranges_float.argtypes = [POINTER(Plugin), POINTER(c_float), POINTER(c_float), POINTER(c_float)] +plugin_get_port_ranges_float.restype = None + +plugin_get_num_ports_of_class = VariadicFunction(_lib.lilv_plugin_get_num_ports_of_class, + c_uint32, + [POINTER(Plugin), POINTER(Node)]) + +plugin_has_latency.argtypes = [POINTER(Plugin)] +plugin_has_latency.restype = c_bool + +plugin_get_latency_port_index.argtypes = [POINTER(Plugin)] +plugin_get_latency_port_index.restype = c_uint32 + +plugin_get_port_by_index.argtypes = [POINTER(Plugin), c_uint32] +plugin_get_port_by_index.restype = POINTER(Port) + +plugin_get_port_by_symbol.argtypes = [POINTER(Plugin), POINTER(Node)] +plugin_get_port_by_symbol.restype = POINTER(Port) + +plugin_get_port_by_designation.argtypes = [POINTER(Plugin), POINTER(Node), POINTER(Node)] +plugin_get_port_by_designation.restype = POINTER(Port) + +plugin_get_project.argtypes = [POINTER(Plugin)] +plugin_get_project.restype = POINTER(Node) + +plugin_get_author_name.argtypes = [POINTER(Plugin)] +plugin_get_author_name.restype = POINTER(Node) + +plugin_get_author_email.argtypes = [POINTER(Plugin)] +plugin_get_author_email.restype = POINTER(Node) + +plugin_get_author_homepage.argtypes = [POINTER(Plugin)] +plugin_get_author_homepage.restype = POINTER(Node) + +plugin_is_replaced.argtypes = [POINTER(Plugin)] +plugin_is_replaced.restype = c_bool + +plugin_get_related.argtypes = [POINTER(Plugin), POINTER(Node)] +plugin_get_related.restype = POINTER(Nodes) + +port_get_node.argtypes = [POINTER(Plugin), POINTER(Port)] +port_get_node.restype = POINTER(Node) + +port_get_value.argtypes = [POINTER(Plugin), POINTER(Port), POINTER(Node)] +port_get_value.restype = POINTER(Nodes) + +port_get.argtypes = [POINTER(Plugin), POINTER(Port), POINTER(Node)] +port_get.restype = POINTER(Node) + +port_get_properties.argtypes = [POINTER(Plugin), POINTER(Port)] +port_get_properties.restype = POINTER(Nodes) + +port_has_property.argtypes = [POINTER(Plugin), POINTER(Port), POINTER(Node)] +port_has_property.restype = c_bool + +port_supports_event.argtypes = [POINTER(Plugin), POINTER(Port), POINTER(Node)] +port_supports_event.restype = c_bool + +port_get_index.argtypes = [POINTER(Plugin), POINTER(Port)] +port_get_index.restype = c_uint32 + +port_get_symbol.argtypes = [POINTER(Plugin), POINTER(Port)] +port_get_symbol.restype = POINTER(Node) + +port_get_name.argtypes = [POINTER(Plugin), POINTER(Port)] +port_get_name.restype = POINTER(Node) + +port_get_classes.argtypes = [POINTER(Plugin), POINTER(Port)] +port_get_classes.restype = POINTER(Nodes) + +port_is_a.argtypes = [POINTER(Plugin), POINTER(Port), POINTER(Node)] +port_is_a.restype = c_bool + +port_get_range.argtypes = [POINTER(Plugin), POINTER(Port), POINTER(POINTER(Node)), POINTER(POINTER(Node)), POINTER(POINTER(Node))] +port_get_range.restype = None + +port_get_scale_points.argtypes = [POINTER(Plugin), POINTER(Port)] +port_get_scale_points.restype = POINTER(ScalePoints) + +state_new_from_world.argtypes = [POINTER(World), POINTER(LV2_URID_Map), POINTER(Node)] +state_new_from_world.restype = POINTER(State) + +state_new_from_file.argtypes = [POINTER(World), POINTER(LV2_URID_Map), POINTER(Node), String] +state_new_from_file.restype = POINTER(State) + +state_new_from_string.argtypes = [POINTER(World), POINTER(LV2_URID_Map), String] +state_new_from_string.restype = POINTER(State) + +LilvGetPortValueFunc = CFUNCTYPE(c_void_p, c_char_p, POINTER(None), POINTER(c_uint32), POINTER(c_uint32)) + +state_new_from_instance.argtypes = [POINTER(Plugin), POINTER(Instance), POINTER(LV2_URID_Map), c_char_p, c_char_p, c_char_p, String, LilvGetPortValueFunc, POINTER(None), c_uint32, POINTER(POINTER(LV2_Feature))] +state_new_from_instance.restype = POINTER(State) + +state_free.argtypes = [POINTER(State)] +state_free.restype = None + +state_equals.argtypes = [POINTER(State), POINTER(State)] +state_equals.restype = c_bool + +state_get_num_properties.argtypes = [POINTER(State)] +state_get_num_properties.restype = c_uint + +state_get_plugin_uri.argtypes = [POINTER(State)] +state_get_plugin_uri.restype = POINTER(Node) + +state_get_uri.argtypes = [POINTER(State)] +state_get_uri.restype = POINTER(Node) + +state_get_label.argtypes = [POINTER(State)] +state_get_label.restype = c_char_p + +state_set_label.argtypes = [POINTER(State), String] +state_set_label.restype = None + +state_set_metadata.argtypes = [POINTER(State), c_uint32, POINTER(None), c_size_t, c_uint32, c_uint32] +state_set_metadata.restype = c_int + +LilvSetPortValueFunc = CFUNCTYPE(None, c_char_p, POINTER(None), POINTER(None), c_uint32, c_uint32) +state_emit_port_values.argtypes = [POINTER(State), LilvSetPortValueFunc, POINTER(None)] +state_emit_port_values.restype = None + +state_restore.argtypes = [POINTER(State), POINTER(Instance), LilvSetPortValueFunc, POINTER(None), c_uint32, POINTER(POINTER(LV2_Feature))] +state_restore.restype = None + +state_save.argtypes = [POINTER(World), POINTER(LV2_URID_Map), POINTER(LV2_URID_Unmap), POINTER(State), c_char_p, c_char_p, String] +state_save.restype = c_int + +state_to_string.argtypes = [POINTER(World), POINTER(LV2_URID_Map), POINTER(LV2_URID_Unmap), POINTER(State), c_char_p, String] +state_to_string.restype = c_char_p + +state_delete.argtypes = [POINTER(World), POINTER(State)] +state_delete.restype = c_int + +scale_point_get_label.argtypes = [POINTER(ScalePoint)] +scale_point_get_label.restype = POINTER(Node) + +scale_point_get_value.argtypes = [POINTER(ScalePoint)] +scale_point_get_value.restype = POINTER(Node) + +plugin_class_get_parent_uri.argtypes = [POINTER(PluginClass)] +plugin_class_get_parent_uri.restype = POINTER(Node) + +plugin_class_get_uri.argtypes = [POINTER(PluginClass)] +plugin_class_get_uri.restype = POINTER(Node) + +plugin_class_get_label.argtypes = [POINTER(PluginClass)] +plugin_class_get_label.restype = POINTER(Node) + +plugin_class_get_children.argtypes = [POINTER(PluginClass)] +plugin_class_get_children.restype = POINTER(PluginClasses) + +plugin_instantiate.argtypes = [POINTER(Plugin), c_double, POINTER(POINTER(LV2_Feature))] +plugin_instantiate.restype = POINTER(Instance) + +instance_free.argtypes = [POINTER(Instance)] +instance_free.restype = None + +plugin_get_uis.argtypes = [POINTER(Plugin)] +plugin_get_uis.restype = POINTER(UIs) + +ui_get_uri.argtypes = [POINTER(UI)] +ui_get_uri.restype = POINTER(Node) + +ui_get_classes.argtypes = [POINTER(UI)] +ui_get_classes.restype = POINTER(Nodes) + +ui_is_a.argtypes = [POINTER(UI), POINTER(Node)] +ui_is_a.restype = c_bool + +LilvUISupportedFunc = CFUNCTYPE(c_uint, c_char_p, c_char_p) + +ui_is_supported.argtypes = [POINTER(UI), LilvUISupportedFunc, POINTER(Node), POINTER(POINTER(Node))] +ui_is_supported.restype = c_uint + +ui_get_bundle_uri.argtypes = [POINTER(UI)] +ui_get_bundle_uri.restype = POINTER(Node) + +ui_get_binary_uri.argtypes = [POINTER(UI)] +ui_get_binary_uri.restype = POINTER(Node) + +OPTION_FILTER_LANG = 'http://drobilla.net/ns/lilv#filter-lang' +OPTION_DYN_MANIFEST = 'http://drobilla.net/ns/lilv#dyn-manifest' + +# Define URI constants for compatibility with old Python bindings + +LILV_NS_DOAP = 'http://usefulinc.com/ns/doap#' +LILV_NS_FOAF = 'http://xmlns.com/foaf/0.1/' +LILV_NS_LILV = 'http://drobilla.net/ns/lilv#' +LILV_NS_LV2 = 'http://lv2plug.in/ns/lv2core#' +LILV_NS_OWL = 'http://www.w3.org/2002/07/owl#' +LILV_NS_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' +LILV_NS_RDFS = 'http://www.w3.org/2000/01/rdf-schema#' +LILV_NS_XSD = 'http://www.w3.org/2001/XMLSchema#' +LILV_URI_ATOM_PORT = 'http://lv2plug.in/ns/ext/atom#AtomPort' +LILV_URI_AUDIO_PORT = 'http://lv2plug.in/ns/lv2core#AudioPort' +LILV_URI_CONTROL_PORT = 'http://lv2plug.in/ns/lv2core#ControlPort' +LILV_URI_CV_PORT = 'http://lv2plug.in/ns/lv2core#CVPort' +LILV_URI_EVENT_PORT = 'http://lv2plug.in/ns/ext/event#EventPort' +LILV_URI_INPUT_PORT = 'http://lv2plug.in/ns/lv2core#InputPort' +LILV_URI_MIDI_EVENT = 'http://lv2plug.in/ns/ext/midi#MidiEvent' +LILV_URI_OUTPUT_PORT = 'http://lv2plug.in/ns/lv2core#OutputPort' +LILV_URI_PORT = 'http://lv2plug.in/ns/lv2core#Port' +LILV_OPTION_FILTER_LANG = 'http://drobilla.net/ns/lilv#filter-lang' +LILV_OPTION_DYN_MANIFEST = 'http://drobilla.net/ns/lilv#dyn-manifest' |