Update local LV2 libraries to latest versions

lilv-0.24.6
   lv2-1.16.0
   serd-0.30.2
   sord-0.16.4
   sratom-0.6.4
   suil-0.10.6
This commit is contained in:
Leland Lucius 2019-12-17 11:15:16 -06:00
parent 9dab0a2fee
commit be336797b3
2676 changed files with 277368 additions and 138239 deletions

3
lib-src/lv2/lilv/.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "waflib"]
path = waflib
url = ../../drobilla/autowaf

View File

@ -8,4 +8,7 @@ Dynamic manifest support:
Stefano D'Angelo
Plugin execution via Python bindings:
Kaspar Emanuel <kaspar.emanuel@gmail.com>
Kaspar Emanuel <kaspar.emanuel@gmail.com>
Python preset script:
Christopher Arndt <chris@chrisarndt.de>

View File

@ -1,4 +1,4 @@
Copyright 2011-2014 David Robillard <http://drobilla.net>
Copyright 2011-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@ -8,11 +8,7 @@ Building this software requires only Python. To install with default options:
./waf configure
./waf
./waf install
You may need to become root for the install stage, for example:
sudo ./waf install
./waf install # or sudo ./waf install
Configuration Options
---------------------
@ -40,12 +36,20 @@ invoked:
* CPPFLAGS: C preprocessor options
* LINKFLAGS: Linker options
Installation Directories
------------------------
Library Versioning
------------------
The --prefix option (or the PREFIX environment variable) can be used to change
the prefix which all files are installed under. There are also several options
allowing for more fine-tuned control, see the --help output for details.
This library uses semantic versioning <http://semver.org/>.
Several major versions can be installed in parallel. The shared library name,
include directory, and pkg-config file are suffixed with the major version
number. For example, a library named "foo" at version 1.x.y might install:
/usr/include/foo-1/foo/foo.h
/usr/lib/foo-1.so.1.x.y
/usr/lib/pkgconfig/foo-1.pc
Dependencies can check for the package "foo-1" with pkg-config.
Packaging
---------
@ -57,3 +61,6 @@ which adds a prefix to all install paths. For example:
./waf configure --prefix=/usr
./waf
./waf install --destdir=/tmp/package
Packages should allow parallel installation of several major versions. For
example, the above would be packaged as "foo-1".

View File

@ -1,150 +1,236 @@
lilv (0.24.6) stable;
* Add more strict error detection when storing plugin state properties
* Add option to override LV2_PATH in applications
* Don't print errors when saving state if correct links already exist
* Fix GCC8 warnings
* Fix creating directories across drives on Windows
* Fix issues with loading state with saved files from the model
* Fix memory errors and Python 3.4+ compatibility in Python bindings
* Fix unit tests on Windows
* Make Python bindings more Pythonic
-- David Robillard <d@drobilla.net> Sun, 10 Nov 2019 21:39:37 +0000
lilv (0.24.4) stable;
* Don't attempt to load remote or non-Turtle files
* Fix saving state when broken links are encountered
* Gracefully handle plugins with missing binary URIs
* Install Python bindings when configured without tests (thanks Clement
Skau)
* Remove use of deprecated readdir_r
* lv2apply: Activate plugin before running
* lv2apply: Use default values when they are not nan
* lv2bench: Improve support for plugins with sequence ports
* lv2bench: Support running a single plugin given on the command line
-- David Robillard <d@drobilla.net> Sun, 22 Jul 2018 18:42:00 +0000
lilv (0.24.2) stable;
* Fix comparison of restored states with paths
* Fix saving state to paths that contain URI delimiters (#, ?, etc)
-- David Robillard <d@drobilla.net> Wed, 04 Jan 2017 16:48:08 +0000
lilv (0.24.0) stable;
* Add LILV_URI_ATOM_PORT and LILV_URI_CV_PORT defines
* Add lilv_state_set_metadata() for adding state banks/comments/etc (based
on patch from Hanspeter Portner)
* Add lilv_world_get_symbol()
* Add lv2apply utility for applying plugins to audio files
* Add new hand-crafted Pythonic bindings with full test coverage
* Check lv2:binary predicate for UIs
* Do not instantiate plugin when data fails to parse
* Fix crash when NULL predicate is passed to lilv_world_find_nodes()
* Fix crash when state contains non-POD properties
* Fix documentation installation
* Fix loading dyn-manifest from bundles with spaces in their path
* Fix outdated comment references to lilv_uri_to_path()
* Fix state file versioning
* Replace bundles if bundle with newer plugin version is loaded (based on
patch from Robin Gareus)
* Support re-loading plugins
* Unload contained resources when bundle is unloaded
-- David Robillard <d@drobilla.net> Tue, 20 Sep 2016 02:24:57 +0000
lilv (0.22.0) stable;
* Add lilv_file_uri_parse() for correct URI to path conversion
* Add lilv_free() for systems picky about such things
* Add lilv_node_get_path() for convenient file URI path access
* Add lilv_state_delete() for deleting user saved presets
* Add lilv_state_emit_port_values() for special port value handling
* Add lilv_state_get_uri()
* Configure based on compiler target OS for cross-compilation
* Expose lilv_world_load_specifications() and
lilv_world_load_plugin_classes()
* Fix a few minor/unlikely memory errors
* Fix bindings for Python 3
* Fix creation of duplicate manifest entries when saving state
* Fix directory walking on some systems (thanks Matt Fischer)
* Fix lilv_realpath() on pre-POSIX-2008 systems
* Fix lilv_world_ask() to work with wildcards
* Fix loading files with spaces in their path
* Load discovered owl ontologies as specifications
* Minor documentation improvements
* Preserve absolute paths in state if no link directory is given
* Tolerate passing NULL to lilv_state_restore()
* Upgrade to waf 1.8.14
* Windows fixes (thanks John Emmas)
-- David Robillard <d@drobilla.net> Thu, 08 Oct 2015 19:39:29 +0000
lilv (0.20.0) stable;
* Add convenient lilv_new_file_uri for creating file URIs
* Add lilv_world_unload_bundle() and lilv_world_unload_resource()
* Call lv2_lib_descriptor separately for different bundle paths (fix loading
several dynamic plugins like Ingen at once)
* Don't load files multiple times if they are listed as rdfs:seeAlso for
several plugins
* Call lv2_lib_descriptor separately for different bundle paths
(fix loading several dynamic plugins like Ingen at once)
* Tolerate calling lilv_node_as_uri or lilv_node_as_blank on NULL
* Add convenient lilv_new_file_uri for creating file URIs
* Fix use of lv2info -m and -p options to write plugin data
(useful for porting plugins bridges with NASPRO)
* Fix issues with lilv_plugin_get_author_name and friends
(thanks Filipe Coelho)
* Improved/working lv2_apply.py to apply plugin to a .wav
(thanks Joe Button)
* Add lilv_world_unload_bundle() and lilv_world_unload_resource()
* Fix issues with lilv_plugin_get_author_name and friends (thanks Filipe
Coelho)
* Fix several minor memory leaks
* Fix use of lv2info -m and -p options to write plugin data (useful for
porting plugins bridges with NASPRO)
* Improve test coverage
* Improved/working lv2_apply.py to apply plugin to a .wav (thanks Joe
Button)
* Tolerate calling lilv_node_as_uri or lilv_node_as_blank on NULL
* Upgrade to waf 1.7.16
-- David Robillard <d@drobilla.net> Fri, 08 Aug 2014 18:21:32 -0400
-- David Robillard <d@drobilla.net> Fri, 08 Aug 2014 22:21:32 +0000
lilv (0.18.0) stable;
* Allow lilv_state_restore() to be used without passing an instance,
for restoring port values via a callback only
* Fix unlikely memory leak in lilv_plugin_instantiate()
* Support denoting latency ports with lv2:designation lv2:latency
* Add lilv_port_get_node() for using world query functions with ports
* Add support for running plugins from Python by Kaspar Emanuel
* Allow lilv_state_restore() to be used without passing an instance, for
restoring port values via a callback only
* Allow passing NULL port_class to lilv_plugin_get_port_by_designation
* Call GetProcAddress with correct calling convention on Windows
* Add support for running plugins from Python by Kaspar Emanuel
* Clean up after test suite so multiple runs are successful
* Add lilv_port_get_node() for using world query functions with ports
* lv2info: Don't display invalid control maxes and defaults
(patch from Robin Gareus)
* Fix unlikely memory leak in lilv_plugin_instantiate()
* Support denoting latency ports with lv2:designation lv2:latency
* lilvmm.hpp: Add wrappers for UI API
* lv2info: Don't display invalid control maxes and defaults (patch from
Robin Gareus)
-- David Robillard <d@drobilla.net> Sat, 04 Jan 2014 16:06:42 -0500
-- David Robillard <d@drobilla.net> Sat, 04 Jan 2014 21:06:42 +0000
lilv (0.16.0) stable;
* Add lilv_nodes_merge()
* Add lilv_world_ask() for easily checking if a statement exists
* Add lilv_world_get() and lilv_port_get() for easily getting one value
* Add lilv_nodes_merge()
* Make lilv_plugin_get_port_by_designation() return a const pointer
* Require a URI for lilv_state_to_string() and fail gracefully otherwise
* Fail gracefully when lilv_state_new_from_string() is called on NULL
* Make state loading functions fall back to lv2:default for port values,
so a plugin description can be loaded as default state
* Ignore state ports with no value instead of printing an error
* Support atom:supports in lilv_port_supports_event()
* Add va_list variant of lilv_plugin_get_num_ports_of_class()
* Fix several plugin functions that failed to load data if called first
* Correctly depend on serd at build time (fix compilation in odd cases)
* Disable timestamps in HTML documentation for reproducible build
* lilvmm.hpp: Support varargs for Plugin::get_num_ports_of_class()
* lilvmm.hpp: Add several missing methods
* Fail gracefully when lilv_state_new_from_string() is called on NULL
* Fix several plugin functions that failed to load data if called first
* Ignore state ports with no value instead of printing an error
* Make lilv_plugin_get_port_by_designation() return a const pointer
* Make state loading functions fall back to lv2:default for port values, so
a plugin description can be loaded as default state
* Require a URI for lilv_state_to_string() and fail gracefully otherwise
* Support atom:supports in lilv_port_supports_event()
* Update to waf 1.7.8 and autowaf r90 (install docs to versioned directory)
* lilvmm.hpp: Add several missing methods
* lilvmm.hpp: Support varargs for Plugin::get_num_ports_of_class()
-- David Robillard <d@drobilla.net> Mon, 18 Feb 2013 16:43:10 -0500
-- David Robillard <d@drobilla.net> Mon, 18 Feb 2013 21:43:10 +0000
lilv (0.14.4) stable;
* Add lv2bench utility
* Add option to build utilities as static binaries
* Deprecate old flawed Lilv::Instance constructors
* Fix documentation for ui_type parameter of lilv_ui_is_supported()
* Do not require a C++ compiler to build
* Fix crash when lv2info is run with an invalid URI argument
* Fix documentation for ui_type parameter of lilv_ui_is_supported()
* Fix various hyper-strict warnings
* Gracefully handle failure to save plugin state and print error message
* Make all 'zix' symbols private to avoid symbol clashes in static builds
* Reduce memory usage (per node)
* Simpler node implementation always backed by a SordNode
* Make all 'zix' symbols private to avoid symbol clashes in static builds
* Add lv2bench utility
* Fix various hyper-strict warnings
* Do not require a C++ compiler to build
* Add option to build utilities as static binaries
* Upgrade to waf 1.7.2
* lilvmm.hpp: Make Lilv::Instance handle features and failed instantiations
* lilvmm.hpp: Add Lilv::Instance::get_handle()
* lilvmm.hpp: Add Lilv::Instance::get_extension_data()
* lilvmm.hpp: Add Lilv::Instance::get_handle()
* lilvmm.hpp: Make Lilv::Instance handle features and failed instantiations
-- David Robillard <d@drobilla.net> Thu, 23 Aug 2012 01:38:29 -0400
-- David Robillard <d@drobilla.net> Thu, 23 Aug 2012 05:38:29 +0000
lilv (0.14.2) stable;
* Fix dynmanifest support
-- David Robillard <d@drobilla.net> Thu, 19 Apr 2012 16:11:31 -0400
-- David Robillard <d@drobilla.net> Thu, 19 Apr 2012 20:11:31 +0000
lilv (0.14.0) stable;
* Add LilvState API for handling plugin state. This makes it simple to save
and restore plugin state both in memory and on disk, as well as save
presets in a host-sharable way since the disk format is identical to the
LV2 presets format.
* Add lilv_plugin_get_extension_data
* Use path variables in pkgconfig files
* Install man page to DATADIR (e.g. PREFIX/share/man, not PREFIX/man)
* Make Lilv::uri_to_path static inline (fix linking errors)
* Use correct URI for dcterms:replaces (for hiding old plugins):
"http://purl.org/dc/terms/replaces"
* Fix compilation on BSD
* Only load dynmanifest libraries once per bundle, not once per plugin
* Fix lilv_world_find_nodes to work with wildcard subjects
* Add lilv_plugin_get_related to get resources related to plugins that
are not directly rdfs:seeAlso linked (e.g. presets)
* Add lilv_world_load_resource for related resources (e.g. presets)
* Print presets in lv2info
* Remove locale smashing kludges and use new serd functions for converting
nodes to/from numbers.
* Add LilvState API for handling plugin state. This makes it simple to
save and restore plugin state both in memory and on disk, as well as
save presets in a host-sharable way since the disk format is identical
to the LV2 presets format.
* Update old references to lv2_list (now lv2ls)
* Support compilation as C++ under MSVC++.
* Remove use of wordexp.
* Add lilv_plugin_get_port_by_designation() and lilv_port_get_index() as an
improved generic alternative to lilv_plugin_get_latency_port_index().
* Add lilv_plugin_get_project() and get author information from project if
it is not given directly on the plugin.
* Add lilv_plugin_get_related to get resources related to plugins that are
not directly rdfs:seeAlso linked (e.g. presets)
* Add lilv_world_load_resource for related resources (e.g. presets)
* Fix compilation on BSD
* Fix lilv_world_find_nodes to work with wildcard subjects
* Install man page to DATADIR (e.g. PREFIX/share/man, not PREFIX/man)
* Make Lilv::uri_to_path static inline (fix linking errors)
* Only load dynmanifest libraries once per bundle, not once per plugin
* Print presets in lv2info
* Remove locale smashing kludges and use new serd functions for converting
nodes to/from numbers.
* Remove use of wordexp.
* Support compilation as C++ under MSVC++.
* Update old references to lv2_list (now lv2ls)
* Use correct URI for dcterms:replaces (for hiding old plugins):
"http://purl.org/dc/terms/replaces"
* Use path variables in pkgconfig files
-- David Robillard <d@drobilla.net> Wed, 18 Apr 2012 20:06:28 -0400
-- David Robillard <d@drobilla.net> Thu, 19 Apr 2012 00:06:28 +0000
lilv (0.5.0) stable;
* Remove glib dependency
* Add ability to build static library
* Add lv2core as a pkg-config dependency (for lv2.h header include)
* Obey prefix when installing bash completion script
* Remove glib dependency
* Support integer minimum, maximum, and default port values in
lilv_plugin_get_port_ranges_float
* Add ability to build static library
-- David Robillard <d@drobilla.net> Thu, 29 Sep 2011 00:00:00 -0400
-- David Robillard <d@drobilla.net> Thu, 29 Sep 2011 04:00:00 +0000
lilv (0.4.4) stable;
* Fix building python bindings
* Fix lilv_ui_is_supported when Lilv is built independently
* Fix parsing extra plugin data files in other bundles
* Make free methods tolerate being called on NULL
* Remove lv2jack (replaced by jalv)
* Fix parsing extra plugin data files in other bundles
* Fix lilv_ui_is_supported when Lilv is built independently
-- David Robillard <d@drobilla.net> Sat, 11 Jun 2011 11:20:11 -0400
-- David Robillard <d@drobilla.net> Sat, 11 Jun 2011 15:20:11 +0000
lilv (0.4.2) stable;
* Fix compilation issues on some systems
* Fix build system Python 3 compatibility
* Fix compilation issues on some systems
-- David Robillard <d@drobilla.net> Wed, 25 May 2011 19:00:00 -0400
-- David Robillard <d@drobilla.net> Wed, 25 May 2011 23:00:00 +0000
lilv (0.4.0) stable;
* Initial version (forked from SLV2)
-- David Robillard <d@drobilla.net> Tue, 24 May 2011 23:00:00 -0400
-- David Robillard <d@drobilla.net> Wed, 25 May 2011 03:00:00 +0000

View File

@ -1,29 +0,0 @@
This library is designed to allow parallel installation of different major
versions. To facilitate this, the shared library name, include directory, and
pkg-config file are suffixed with the major version number of the library.
For example, if this library was named "foo" and at version 1.x.y:
/usr/include/foo-1/foo/foo.h
/usr/lib/foo-1.so.1.x.y
/usr/lib/pkgconfig/foo-1.pc
Dependencies check for pkg-config name "foo-1" and will build
against a compatible version 1, regardless any other installed versions.
*** IMPORTANT GUIDELINES FOR PACKAGERS ***
Packages should follow the same conventions as above, i.e. include the major
version (and only the major version) in the name of the package. Continuing the
example above, the package(s) would be named foo-1 and foo-1-dev. This way,
if/when version 2 comes out, it may be installed at the same time as version 1
without breaking anything.
Please do not create packages of this library that do not follow these
guidelines, you will break things and cause unnecessary headaches. Please do
not use any number as a suffix other than the actual major version number of the
upstream source package.
Because program and documentation names are not versioned, these should be
included in separate packages which may replace previous versions, since
there is little use in having parallel installations of them.

View File

@ -1,11 +0,0 @@
Lilv
----
Lilv is a library for LV2 hosts intended to make using LV2 Plugins as simple
as possible (without sacrificing capabilities).
More information about LV2 plugins can be found at <http://lv2plug.in>.
More information about Lilv can be found at <http://drobilla.net/software/lilv>.
-- David Robillard <d@drobilla.net>

View File

@ -0,0 +1,8 @@
Lilv
====
Lilv is a C library to make the use of LV2 plugins as simple as possible for
applications.
For more information, see <http://drobilla.net/software/lilv>.
-- David Robillard <d@drobilla.net>

View File

@ -1,62 +0,0 @@
%module lilv
%typedef unsigned uint32_t;
%{
#define SWIG_FILE_WITH_INIT
#include "lilv/lilv.h"
#include "lilv/lilvmm.hpp"
%}
%include "numpy.i"
%init %{
import_array();
%}
%apply (float* INPLACE_ARRAY1) {(void* data_location)}
%feature("compactdefaultargs") %{
lilv_plugin_get_num_ports_of_class;
get_num_ports_of_class;
%}
%varargs(3, LilvNode* node = NULL) lilv_plugin_get_num_ports_of_class;
%varargs(3, LilvNode* node = NULL) get_num_ports_of_class;
%typemap(in, numinputs=0) LilvNode *node3 ""; // Make sure it's NULL terminated
%include "lilv/lilv.h"
%include "lilv/lilvmm.hpp"
namespace Lilv {
%extend Plugins {
%pythoncode %{
def __iter__(self):
class Iterator(object):
def __init__(self, plugins):
self.plugins = plugins
self.iter = plugins.begin()
def next(self):
self.iter = self.plugins.next(self.iter)
if not self.plugins.is_end(self.iter):
return self.plugins.get(self.iter)
else:
raise StopIteration
return Iterator(self)
def get_by_uri(self, *args):
"""get_by_uri(self, LilvNode uri) -> PluginClass"""
ret = _lilv.Plugins_get_by_uri(self, *args)
if ret.me is None:
return None
else:
return ret
%}
};
%extend Node {
%pythoncode %{
def __str__(self):
return self.get_turtle_token()
%}
};
} /* namespace Lilv */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,263 @@
# -*- coding: utf-8 -*-
#
# Lilv documentation build configuration file, created by
# sphinx-quickstart on Sun Sep 4 18:25:58 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.ifconfig',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Lilv'
copyright = u'2016, David Robillard'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.24.2'
# The full version, including alpha/beta/rc tags.
release = '0.24.2'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#html_theme = ''
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = { 'nosidebar': True }
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Lilvdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'Lilv.tex', u'Lilv Documentation',
u'David Robillard', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'lilv', u'Lilv Documentation',
[u'David Robillard'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'Lilv', u'Lilv Documentation',
u'David Robillard', 'Lilv', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

View File

@ -0,0 +1,9 @@
Lilv Python Documentation
=========================
.. toctree::
.. automodule:: lilv
:noindex:
:members:

File diff suppressed because it is too large Load Diff

View File

@ -41,8 +41,8 @@ class WavFile(object):
data = [(i - float(range/2)) / float(range/2) for i in data]
channels = []
for i in xrange(self.nchannels):
channels.append([data[j] for j in xrange(0, len(data), self.nchannels) ])
for i in range(self.nchannels):
channels.append([data[j] for j in range(0, len(data), self.nchannels) ])
return channels
@ -57,6 +57,7 @@ def main():
# Initialise Lilv
world = lilv.World()
ns = world.ns
world.load_all()
plugin_uri = sys.argv[1]
@ -65,19 +66,14 @@ def main():
# Find plugin
plugin_uri_node = world.new_uri(plugin_uri)
plugin = world.get_all_plugins().get_by_uri(plugin_uri_node)
if not plugin:
print("Unknown plugin `%s'\n" % plugin_uri)
plugins = world.get_all_plugins()
if plugin_uri_node not in plugins:
print("Unknown plugin `%s'" % plugin_uri)
sys.exit(1)
lv2_InputPort = world.new_uri(lilv.LILV_URI_INPUT_PORT)
lv2_OutputPort = world.new_uri(lilv.LILV_URI_OUTPUT_PORT)
lv2_AudioPort = world.new_uri(lilv.LILV_URI_AUDIO_PORT)
lv2_ControlPort = world.new_uri(lilv.LILV_URI_CONTROL_PORT)
lv2_default = world.new_uri("http://lv2plug.in/ns/lv2core#default")
n_audio_in = plugin.get_num_ports_of_class(lv2_InputPort, lv2_AudioPort)
n_audio_out = plugin.get_num_ports_of_class(lv2_OutputPort, lv2_AudioPort)
plugin = plugins[plugin_uri_node]
n_audio_in = plugin.get_num_ports_of_class(ns.lv2.InputPort, ns.lv2.AudioPort)
n_audio_out = plugin.get_num_ports_of_class(ns.lv2.OutputPort, ns.lv2.AudioPort)
if n_audio_out == 0:
print("Plugin has no audio outputs\n")
sys.exit(1)
@ -120,22 +116,21 @@ def main():
control_output_buffers = []
for index in range(plugin.get_num_ports()):
port = plugin.get_port_by_index(index)
if port.is_a(lv2_InputPort):
if port.is_a(lv2_AudioPort):
if port.is_a(ns.lv2.InputPort):
if port.is_a(ns.lv2.AudioPort):
audio_input_buffers.append(numpy.array(channels[len(audio_input_buffers)], numpy.float32))
instance.connect_port(index, audio_input_buffers[-1])
elif port.is_a(lv2_ControlPort):
#if port.has_property(lv2_default): # Doesn't seem to work
default = lilv.lilv_node_as_float(lilv.lilv_nodes_get_first(port.get_value(lv2_default)))
elif port.is_a(ns.lv2.ControlPort):
default = float(port.get(ns.lv2.default))
control_input_buffers.append(numpy.array([default], numpy.float32))
instance.connect_port(index, control_input_buffers[-1])
else:
raise ValueError("Unhandled port type")
elif port.is_a(lv2_OutputPort):
if port.is_a(lv2_AudioPort):
elif port.is_a(ns.lv2.OutputPort):
if port.is_a(ns.lv2.AudioPort):
audio_output_buffers.append(numpy.array([0] * wav_in.nframes, numpy.float32))
instance.connect_port(index, audio_output_buffers[-1])
elif port.is_a(lv2_ControlPort):
elif port.is_a(ns.lv2.ControlPort):
control_output_buffers.append(numpy.array([0], numpy.float32))
instance.connect_port(index, control_output_buffers[-1])
else:
@ -156,7 +151,7 @@ def main():
# Write output file in chunks to stop memory usage getting out of hand:
CHUNK_SIZE = 8192
for chunk in numpy.array_split(data, CHUNK_SIZE):
wav_out.writeframes(wave.struct.pack("%u%s" % (len(chunk), wav_in.struct_fmt_code), *chunk))
wav_out.writeframes(wave.struct.pack("%u%s" % (len(chunk), wav_in.struct_fmt_code), *chunk.astype(int)))
wav_out.close()

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import lilv
NS_PRESETS = "http://lv2plug.in/ns/ext/presets#"
def print_presets(uri):
"""Print all presets of an LV2 plugin to stdout."""
world = lilv.World()
world.load_all()
world.ns.presets = lilv.Namespace(world, NS_PRESETS)
plugins = world.get_all_plugins()
plugin = plugins[uri]
presets = plugin.get_related(world.ns.presets.Preset)
preset_list = []
for preset in presets:
world.load_resource(preset)
labels = world.find_nodes(preset, world.ns.rdfs.label, None)
label = str(labels[0]) if len(labels) > 0 else ""
if not label:
sys.stderr.write("warning: Preset <%s> has no label\n" % preset)
preset_list.append((str(preset), str(label)))
for preset in sorted(preset_list):
print('<%s> "%s"' % preset)
if __name__ == "__main__":
if len(sys.argv) != 2:
sys.stderr.write("Usage: %s PLUGIN_URI\n" % (sys.argv[0]))
sys.exit(1)
try:
print_presets(sys.argv[1])
except ValueError as e:
sys.stderr.write("error: %s\n" % e)
except KeyError as e:
sys.stderr.write("error: %s\n" % str(e).strip("'"))

View File

@ -1,5 +1,5 @@
/*
Copyright 2006-2011 David Robillard <d@drobilla.net>
Copyright 2006-2019 David Robillard <d@drobilla.net>
Copyright 2006 Steve Harris <steve@plugin.org.uk>
Permission to use, copy, modify, and/or distribute this software for any
@ -15,10 +15,6 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** Include standard C headers */
#include <math.h>
#include <stdlib.h>
/**
LV2 headers are based on the URI of the specification they come from, so a
consistent convention can be used even for unofficial extensions. The URI
@ -26,7 +22,11 @@
replacing `http:/` with `lv2` any header in the specification bundle can be
included, in this case `lv2.h`.
*/
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
#include "lv2/core/lv2.h"
/** Include standard C headers */
#include <math.h>
#include <stdlib.h>
/**
The URI is the identifier for a plugin, and how the host associates this
@ -54,7 +54,7 @@ typedef enum {
every instance method. In this simple plugin, only port buffers need to be
stored, since there is no additional instance data. */
typedef struct {
// Port buffers
float* buf;
} Test;
/**
@ -179,7 +179,7 @@ static const LV2_Descriptor descriptor = {
indices to find all the plugins defined in the library. The index is not an
indentifier, the URI of the returned descriptor is used to determine the
identify of the plugin.
This method is in the ``discovery'' threading class, so no other functions
or methods in this plugin library will be called concurrently with it.
*/

View File

@ -1,5 +1,5 @@
# Lilv Bindings Test Plugin
# Copyright 2011 David Robillard <d@drobilla.net>
# Copyright 2011-2016 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@ -16,18 +16,27 @@
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/lilv-bindings-test-plugin>
a lv2:Plugin ;
doap:name "Lilv Bindings Test" ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
ui:ui <http://example.org/lilv-bindings-test-plugin-ui> ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
lv2:name "Input" ;
lv2:default 0.5 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
lv2:scalePoint [ rdfs:label "off" ; rdf:value 0.0 ] ;
lv2:scalePoint [ rdfs:label "on" ; rdf:value 1.0 ] ;
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
@ -47,3 +56,7 @@
lv2:symbol "audio_output" ;
lv2:name "Audio Output" ;
] .
<http://example.org/lilv-bindings-test-plugin-ui>
a ui:GtkUI ;
ui:binary <TODO> .

View File

@ -1,3 +1,4 @@
# Copyright 2016-2019 David Robillard <d@drobilla.net>
# Copyright 2013 Kaspar Emanuel <kaspar.emanuel@gmail.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
@ -12,73 +13,414 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from lilv import *
import unittest
import lilv
import os
import sys
import unittest
path = os.path.abspath("bindings/bindings_test_plugin.lv2/")
if sys.version_info[0] == 2:
import urllib
import urlparse
location = urlparse.urljoin("file:", urllib.pathname2url(path) + "/")
else:
from urllib.parse import urljoin
from urllib.request import pathname2url
location = urljoin("file:", pathname2url(path) + "/")
class NodeTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
def testNodes(self):
aint = self.world.new_int(1)
aint2 = self.world.new_int(1)
aint3 = self.world.new_int(3)
afloat = self.world.new_float(2.0)
atrue = self.world.new_bool(True)
afalse = self.world.new_bool(False)
auri = self.world.new_uri("http://example.org")
afile = self.world.new_file_uri(None, "/foo/bar")
astring = self.world.new_string("hello")
self.assertEqual(auri.get_turtle_token(), "<http://example.org>")
self.assertTrue(aint.is_int())
self.assertTrue(afloat.is_float())
self.assertTrue(auri.is_uri())
self.assertTrue(astring.is_string())
self.assertTrue(astring.is_literal())
self.assertFalse(auri.is_blank())
self.assertTrue(int(aint) == 1)
self.assertTrue(float(afloat) == 2.0)
self.assertTrue(bool(atrue))
self.assertFalse(bool(afalse))
self.assertEqual(afile.get_path(), "/foo/bar")
self.assertTrue(aint == aint2)
self.assertTrue(aint != aint3)
self.assertTrue(aint != afloat)
with self.assertRaises(ValueError):
int(atrue)
with self.assertRaises(ValueError):
float(aint)
with self.assertRaises(ValueError):
bool(astring)
class UriTests(unittest.TestCase):
def setUp(self):
self.world = lilv_world_new()
lilv_world_load_all(self.world)
self.world = lilv.World()
self.world.load_all()
def testInvalidURI(self):
self.uri = lilv_new_uri(self.world, "invalid_uri")
self.assertIsNone(self.uri)
def testInvalidURI2(self):
self.uri = lilv_new_uri(self.world, "invalid_uri")
self.assertFalse( lilv_node_is_uri(self.uri) )
with self.assertRaises(ValueError):
self.plugin_uri = self.world.new_uri("invalid_uri")
def testNonExistentURI(self):
self.uri = lilv_new_uri(self.world, "exist:does_not")
plugins = lilv_world_get_all_plugins(self.world)
self.plugin = lilv_plugins_get_by_uri(plugins, self.uri)
self.assertIsNone(self.plugin)
self.plugin_uri = self.world.new_uri("exist:does_not")
self.plugin = self.world.get_all_plugins().get_by_uri(self.plugin_uri)
self.assertEqual(self.plugin, None)
def testPortTypes(self):
self.uri = lilv_new_uri(self.world, LILV_URI_INPUT_PORT)
self.assertIsNotNone(self.uri)
self.assertIsNotNone(self.world.new_uri(lilv.LILV_URI_INPUT_PORT))
def testPortTypes2(self):
self.uri = lilv_new_uri(self.world, LILV_URI_OUTPUT_PORT)
self.assertIsNotNone(self.uri)
self.assertIsNotNone(self.world.new_uri(lilv.LILV_URI_OUTPUT_PORT))
def testPortTypes3(self):
self.uri = lilv_new_uri(self.world, LILV_URI_AUDIO_PORT)
self.assertIsNotNone(self.uri)
self.assertIsNotNone(self.world.new_uri(lilv.LILV_URI_AUDIO_PORT))
def testPortTypes4(self):
self.uri = lilv_new_uri(self.world, LILV_URI_CONTROL_PORT)
self.assertIsNotNone(self.uri)
def tearDown(self):
lilv_node_free(self.uri)
lilv_world_free(self.world)
self.assertIsNotNone(self.world.new_uri(lilv.LILV_URI_CONTROL_PORT))
class PluginClassTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
def testPluginClasses(self):
pclass = self.world.get_plugin_class()
self.assertIsNotNone(pclass)
self.assertIsNone(pclass.get_parent_uri())
self.assertIsNotNone(pclass.get_uri())
self.assertIsNotNone(pclass.get_label())
self.assertEqual(str(pclass.get_uri()), str(pclass))
for i in pclass.get_children():
self.assertIsNotNone(i)
self.assertIsNotNone(i.get_uri())
self.assertIsNotNone(i.get_label())
class PluginClassesTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
self.world.load_all()
def testPluginClasses(self):
classes = self.world.get_plugin_classes()
pclass = self.world.get_plugin_class()
self.assertIsNotNone(classes)
self.assertIsNotNone(pclass)
self.assertTrue(pclass in classes)
self.assertTrue(pclass.get_uri() in classes)
self.assertGreater(len(classes), 1)
self.assertIsNotNone(classes[0])
self.assertIsNotNone(classes[pclass.get_uri()])
with self.assertRaises(KeyError):
classes["http://example.org/notaclass"].get_uri()
class LoadTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
self.bundle_uri = self.world.new_uri(location)
self.world.load_specifications()
self.world.load_plugin_classes()
def testLoadUnload(self):
self.world.load_bundle(self.bundle_uri)
plugins = self.world.get_all_plugins()
plugin = plugins.get(plugins.begin())
self.world.load_resource(plugin)
self.world.unload_resource(plugin)
self.world.unload_bundle(self.bundle_uri)
class PluginTests(unittest.TestCase):
def setUp(self):
self.world = lilv_world_new()
location = "file://" + os.getcwd() + "/bindings/bindings_test_plugin.lv2/"
self.plugin_uri = lilv_new_uri(self.world, location)
self.assertIsNotNone(self.plugin_uri, "Invalid URI: '" + location + "'")
lilv_world_load_bundle(self.world, self.plugin_uri)
self.plugins = lilv_world_get_all_plugins(self.world)
self.plugin = lilv_plugins_get(self.plugins, lilv_plugins_begin(self.plugins))
self.assertIsNotNone(self.plugin, msg="Test plugin not found at location: '" + location + "'")
self.assertEqual(location, lilv_node_as_string(lilv_plugin_get_bundle_uri(self.plugin)))
self.instance = lilv_plugin_instantiate(self.plugin, 48000, None)
self.assertIsNotNone(self.instance)
self.lv2_InputPort = lilv_new_uri(self.world, LILV_URI_INPUT_PORT)
self.lv2_OutputPort = lilv_new_uri(self.world, LILV_URI_OUTPUT_PORT)
self.lv2_AudioPort = lilv_new_uri(self.world, LILV_URI_AUDIO_PORT)
self.lv2_ControlPort = lilv_new_uri(self.world, LILV_URI_CONTROL_PORT)
self.world = lilv.World()
self.world.set_option(
lilv.OPTION_FILTER_LANG, self.world.new_bool(True)
)
self.bundle_uri = self.world.new_uri(location)
self.assertIsNotNone(
self.bundle_uri, "Invalid URI: '" + location + "'"
)
self.world.load_bundle(self.bundle_uri)
self.plugins = self.world.get_all_plugins()
self.plugin = self.plugins.get(self.plugins.begin())
self.assertTrue(self.plugin.verify())
self.assertTrue(self.plugin in self.plugins)
self.assertTrue(self.plugin.get_uri() in self.plugins)
self.assertEqual(self.plugins[self.plugin.get_uri()], self.plugin)
with self.assertRaises(KeyError):
self.plugins["http://example.org/notaplugin"].get_uri()
self.assertIsNotNone(
self.plugin,
msg="Test plugin not found at location: '" + location + "'",
)
self.assertEqual(location, str(self.plugin.get_bundle_uri()))
self.plugin_uri = self.plugin.get_uri()
self.assertEqual(
self.plugin.get_uri(), self.plugin_uri, "URI equality broken"
)
self.lv2_InputPort = self.world.new_uri(lilv.LILV_URI_INPUT_PORT)
self.lv2_OutputPort = self.world.new_uri(lilv.LILV_URI_OUTPUT_PORT)
self.lv2_AudioPort = self.world.new_uri(lilv.LILV_URI_AUDIO_PORT)
self.lv2_ControlPort = self.world.new_uri(lilv.LILV_URI_CONTROL_PORT)
def testGetters(self):
self.assertEqual(
self.world.get_symbol(self.plugin), "lilv_bindings_test_plugin"
)
self.assertIsNotNone(self.plugin.get_bundle_uri())
self.assertGreater(len(self.plugin.get_data_uris()), 0)
self.assertIsNotNone(self.plugin.get_library_uri())
self.assertTrue(self.plugin.get_name().is_string())
self.assertTrue(self.plugin.get_class().get_uri().is_uri())
self.assertEqual(
len(self.plugin.get_value(self.world.ns.doap.license)), 1
)
licenses = self.plugin.get_value(self.world.ns.doap.license)
features = self.plugin.get_value(self.world.ns.lv2.optionalFeature)
self.assertEqual(len(licenses), 1)
self.assertTrue(licenses[0] in licenses)
with self.assertRaises(IndexError):
self.assertIsNone(licenses[len(licenses)])
self.assertEqual(
len(licenses) + len(features), len(licenses.merge(features))
)
self.assertEqual(
licenses.get(licenses.begin()),
self.world.new_uri("http://opensource.org/licenses/isc"),
)
self.assertEqual(licenses[0], licenses.get(licenses.begin()))
self.assertTrue(
self.plugin.has_feature(self.world.ns.lv2.hardRTCapable)
)
self.assertEqual(len(self.plugin.get_supported_features()), 1)
self.assertEqual(len(self.plugin.get_optional_features()), 1)
self.assertEqual(len(self.plugin.get_required_features()), 0)
self.assertFalse(
self.plugin.has_extension_data(
self.world.new_uri("http://example.org/nope")
)
)
self.assertEqual(len(self.plugin.get_extension_data()), 0)
self.assertEqual(len(self.plugin.get_extension_data()), 0)
self.assertFalse(self.plugin.has_latency())
self.assertIsNone(self.plugin.get_latency_port_index())
def testPorts(self):
n = lilv_plugin_get_num_ports_of_class(self.plugin, self.lv2_InputPort, self.lv2_AudioPort)
self.assertEqual(n, 1)
def testPorts2(self):
n = lilv_plugin_get_num_ports_of_class(self.plugin, self.lv2_OutputPort, self.lv2_AudioPort)
self.assertEqual(n, 1)
def testPorts3(self):
n = lilv_plugin_get_num_ports_of_class(self.plugin, self.lv2_OutputPort, self.lv2_ControlPort)
self.assertEqual(n, 1)
def testPorts4(self):
n = lilv_plugin_get_num_ports_of_class(self.plugin, self.lv2_InputPort, self.lv2_ControlPort)
self.assertEqual(n, 1)
def tearDown(self):
lilv_node_free(self.lv2_InputPort)
lilv_node_free(self.lv2_OutputPort)
lilv_node_free(self.lv2_AudioPort)
lilv_node_free(self.plugin_uri)
lilv_world_free(self.world)
self.assertEqual(self.plugin.get_num_ports(), 4)
self.assertIsNotNone(self.plugin.get_port(0))
self.assertIsNotNone(self.plugin.get_port(1))
self.assertIsNotNone(self.plugin.get_port(2))
self.assertIsNotNone(self.plugin.get_port(3))
self.assertIsNone(self.plugin.get_port_by_index(4))
self.assertIsNotNone(self.plugin.get_port("input"))
self.assertIsNotNone(self.plugin.get_port("output"))
self.assertIsNotNone(self.plugin.get_port("audio_input"))
self.assertIsNotNone(self.plugin.get_port("audio_output"))
self.assertIsNone(self.plugin.get_port_by_symbol("nonexistent"))
self.assertIsNone(
self.plugin.get_port_by_designation(
self.world.ns.lv2.InputPort, self.world.ns.lv2.control
)
)
self.assertIsNone(self.plugin.get_project())
self.assertIsNone(self.plugin.get_author_name())
self.assertIsNone(self.plugin.get_author_email())
self.assertIsNone(self.plugin.get_author_homepage())
self.assertFalse(self.plugin.is_replaced())
self.assertEqual(
0,
len(
self.plugin.get_related(
self.world.new_uri("http://example.org/Type")
)
),
)
self.assertEqual(
1,
self.plugin.get_num_ports_of_class(
self.lv2_InputPort, self.lv2_AudioPort
),
)
port = self.plugin.get_port("input")
self.assertEqual(self.world.get_symbol(port), "input")
self.assertTrue(port.get_node().is_blank())
self.assertEqual(0, port.get(self.world.ns.lv2.index))
self.assertEqual(1, len(port.get_value(self.world.ns.lv2.symbol)))
self.assertEqual(port.get_value(self.world.ns.lv2.symbol)[0], "input")
self.assertFalse(port.has_property(self.world.ns.lv2.latency))
self.assertFalse(port.supports_event(self.world.ns.midi.MidiEvent))
self.assertEqual(0, port.get_index())
self.assertEqual("input", port.get_symbol())
self.assertEqual("Input", port.get_name())
self.assertEqual(
[
str(self.world.ns.lv2.ControlPort),
str(self.world.ns.lv2.InputPort),
],
sorted(list(map(str, port.get_classes()))),
)
self.assertTrue(port.is_a(self.world.ns.lv2.ControlPort))
self.assertFalse(port.is_a(self.world.ns.lv2.AudioPort))
self.assertEqual((0.5, 0.0, 1.0), port.get_range())
self.assertEqual(0, len(port.get_properties()))
def testScalePoints(self):
port = self.plugin.get_port("input")
points = port.get_scale_points()
point_dict = {
float(points[0].get_value()): points[0].get_label(),
float(points[1].get_value()): points[1].get_label(),
}
self.assertEqual(point_dict, {0.0: "off", 1.0: "on"})
def testPortCount(self):
self.assertEqual(
1,
self.plugin.get_num_ports_of_class(
self.lv2_OutputPort, self.lv2_AudioPort
),
)
self.assertEqual(
1,
self.plugin.get_num_ports_of_class(
self.lv2_OutputPort, self.lv2_ControlPort
),
)
self.assertEqual(
1,
self.plugin.get_num_ports_of_class(
self.lv2_InputPort, self.lv2_AudioPort
),
)
self.assertEqual(
1,
self.plugin.get_num_ports_of_class(
self.lv2_InputPort, self.lv2_ControlPort
),
)
class QueryTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
self.world.load_all()
self.bundle_uri = self.world.new_uri(location)
self.world.load_bundle(self.bundle_uri)
self.plugins = self.world.get_all_plugins()
self.plugin = self.plugins.get(self.plugins.begin())
def testNamespaces(self):
self.assertEqual(self.world.ns.lv2, "http://lv2plug.in/ns/lv2core#")
self.assertEqual(
self.world.ns.lv2.Plugin, "http://lv2plug.in/ns/lv2core#Plugin"
)
def testQuery(self):
self.assertTrue(
self.world.ask(
None, self.world.ns.rdf.type, self.world.ns.lv2.Plugin
)
)
self.assertLess(
0,
len(
self.world.find_nodes(
None, self.world.ns.rdf.type, self.world.ns.lv2.Plugin
)
),
)
self.assertEqual(
self.plugin.get_uri(),
self.world.get(
None, self.world.ns.rdf.type, self.world.ns.lv2.Plugin
),
)
class InstanceTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
self.bundle_uri = self.world.new_uri(location)
self.world.load_bundle(self.bundle_uri)
self.plugins = self.world.get_all_plugins()
self.plugin = self.plugins[0]
self.instance = lilv.Instance(self.plugin, 48000)
self.assertEqual(self.plugin.get_uri(), self.instance.get_uri())
self.assertIsNone(
self.instance.get_extension_data(
self.world.new_uri("http://example.org/ext")
)
)
self.assertIsNone(
self.instance.get_extension_data("http://example.org/ext")
)
def testRun(self):
try:
import numpy
except ImportError:
sys.stderr.write("warning: Missing numpy, not testing instance\n")
return
n_samples = 100
buf = numpy.zeros(n_samples)
with self.assertRaises(Exception):
self.instance.connect_port(0, "hello")
self.instance.connect_port(0, None)
self.instance.connect_port(0, None)
self.instance.connect_port(2, buf)
self.instance.connect_port(3, buf)
self.instance.activate()
self.instance.run(n_samples)
self.instance.deactivate()
class UITests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
self.bundle_uri = self.world.new_uri(location)
self.world.load_bundle(self.bundle_uri)
self.plugins = self.world.get_all_plugins()
self.plugin = self.plugins[0]
def testUI(self):
uis = self.plugin.get_uis()
ui_uri = self.world.new_uri(
"http://example.org/lilv-bindings-test-plugin-ui"
)
self.assertEqual(1, len(uis))
self.assertEqual(str(uis[0]), str(ui_uri))
with self.assertRaises(KeyError):
uis["http://example.org/notaui"].get_uri()
self.assertEqual(uis[0], str(ui_uri))
self.assertEqual(uis[0].get_uri(), ui_uri)
self.assertEqual(uis[0].get_bundle_uri(), self.bundle_uri)
self.assertEqual(
uis[0].get_binary_uri(), str(self.bundle_uri) + "TODO"
)
self.assertEqual(uis[uis[0].get_uri()], uis[0])
self.assertTrue(uis[0].is_a(self.world.ns.ui.GtkUI))
self.assertTrue(uis[0] in uis)
self.assertTrue(uis[0].get_uri() in uis)
self.assertEqual([self.world.ns.ui.GtkUI], list(uis[0].get_classes()))

View File

@ -1,70 +0,0 @@
# Copyright 2013 Kaspar Emanuel <kaspar.emanuel@gmail.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import lilv
import unittest
import os
class UriTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
self.world.load_all();
def testInvalidURI(self):
self.plugin_uri = self.world.new_uri("invalid_uri")
self.assertEqual(self.plugin_uri, None)
def testInvalidURI2(self):
self.plugin_uri = self.world.new_uri("invalid_uri")
self.assertFalse( lilv.lilv_node_is_uri(self.plugin_uri) )
def testNonExistentURI(self):
self.plugin_uri = self.world.new_uri("exist:does_not")
self.plugin = self.world.get_all_plugins().get_by_uri(self.plugin_uri)
self.assertEqual(self.plugin, None)
def testPortTypes(self):
self.assertIsNotNone( self.world.new_uri(lilv.LILV_URI_INPUT_PORT) )
def testPortTypes2(self):
self.assertIsNotNone( self.world.new_uri(lilv.LILV_URI_OUTPUT_PORT) )
def testPortTypes3(self):
self.assertIsNotNone( self.world.new_uri(lilv.LILV_URI_AUDIO_PORT) )
def testPortTypes4(self):
self.assertIsNotNone( self.world.new_uri(lilv.LILV_URI_CONTROL_PORT) )
class PluginTests(unittest.TestCase):
def setUp(self):
self.world = lilv.World()
location = "file://" + os.getcwd() + "/bindings/bindings_test_plugin.lv2/"
self.plugin_uri = self.world.new_uri(location)
self.assertIsNotNone(self.plugin_uri, "Invalid URI: '" + location + "'")
self.world.load_bundle(self.plugin_uri)
self.plugins = self.world.get_all_plugins()
self.plugin = self.plugins.get(self.plugins.begin())
self.assertIsNotNone(self.plugin, msg="Test plugin not found at location: '" + location + "'")
self.assertEqual(location, self.plugin.get_bundle_uri().as_string())
self.instance = lilv.Instance(self.plugin, 48000, None)
self.assertIsNotNone(self.instance)
self.lv2_InputPort = self.world.new_uri(lilv.LILV_URI_INPUT_PORT)
self.lv2_OutputPort = self.world.new_uri(lilv.LILV_URI_OUTPUT_PORT)
self.lv2_AudioPort = self.world.new_uri(lilv.LILV_URI_AUDIO_PORT)
self.lv2_ControlPort = self.world.new_uri(lilv.LILV_URI_CONTROL_PORT)
def testPorts(self):
n = self.plugin.get_num_ports_of_class(self.lv2_InputPort, self.lv2_AudioPort)
self.assertEqual(n, 1)
def testPorts2(self):
n = self.plugin.get_num_ports_of_class(self.lv2_OutputPort, self.lv2_AudioPort)
self.assertEqual(n, 1)
def testPorts3(self):
n = self.plugin.get_num_ports_of_class(self.lv2_OutputPort, self.lv2_ControlPort)
self.assertEqual(n, 1)
def testPorts4(self):
n = self.plugin.get_num_ports_of_class(self.lv2_InputPort, self.lv2_ControlPort)
self.assertEqual(n, 1)

View File

@ -0,0 +1,20 @@
<!-- HTML footer for doxygen 1.8.15-->
<!-- start footer part -->
<!--BEGIN GENERATE_TREEVIEW-->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
$navpath
<li class="footer">$generatedby
<a href="http://www.doxygen.org/index.html">Doxygen $doxygenversion</li>
</ul>
</div>
<!--END GENERATE_TREEVIEW-->
<!--BEGIN !GENERATE_TREEVIEW-->
<div id="footer">
<address class="footer">$generatedby
<a href="http://www.doxygen.org/">Doxygen</a> $doxygenversion
</address>
</div>
<!--END !GENERATE_TREEVIEW-->
</body>
</html>

View File

@ -0,0 +1,37 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<div id="header">
<div id="titlebox">
<!--BEGIN PROJECT_LOGO-->
<div id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></div>
<!--END PROJECT_LOGO-->
<!--BEGIN PROJECT_NAME-->
<h1 id="title">$projectname</h1>
<!--END PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<div id="shortdesc">$projectbrief</div>
<!--END PROJECT_BRIEF-->
</div>
<div id="metabox">
<table id="meta">
<!--BEGIN PROJECT_NUMBER-->
<tr><th>Version</th><td>$projectnumber</td></tr>
<!--END PROJECT_NUMBER-->
</table>
</div>
</div>
</div>
<!--END TITLEAREA-->
<!-- end header part -->

View File

@ -1,4 +1,5 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.15 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
@ -8,17 +9,31 @@
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="interfaces" visible="yes" title="">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="structs" visible="yes" title="">
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
<tab type="exceptions" visible="yes" title="">
<tab type="exceptionlist" visible="yes" title="" intro=""/>
<tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="" intro=""/>
<tab type="examples" visible="yes" title="" intro=""/>
</navindex>
<!-- Layout definition for a class page -->
@ -27,10 +42,11 @@
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<allmemberslink visible="yes"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
@ -65,6 +81,8 @@
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
@ -72,6 +90,7 @@
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
@ -81,8 +100,14 @@
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@ -92,6 +117,8 @@
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@ -107,10 +134,16 @@
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@ -121,6 +154,8 @@
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@ -130,9 +165,9 @@
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="no"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<briefdescription visible="yes"/>
<detaileddescription title=""/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
@ -141,6 +176,8 @@
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
@ -159,6 +196,8 @@
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>

View File

@ -0,0 +1,34 @@
.TH LV2APPLY 1 "05 Sep 2016"
.SH NAME
.B lv2apply \- apply an LV2 plugin to an audio file
.SH SYNOPSIS
.B lv2apply [OPTION]... PLUGIN_URI
.SH OPTIONS
.TP
\fB\-i IN_FILE\fR
Input file
.TP
\fB\-o OUT_FILE\fR
Output file
.TP
\fB\-c SYM VAL\fR
Set control port SYM to VAL
.TP
\fB\-\-help\fR
Display help and exit
.TP
\fB\-\-version\fR
Display version information and exit
.SH "SEE ALSO"
.BR lv2ls(1)
.BR lv2info(1)
.SH AUTHOR
lv2apply was written by David Robillard <d@drobilla.net>

View File

@ -1,17 +1,17 @@
.TH LV2INFO 1 "8 Jan 2012"
.TH LV2INFO 1 "05 Sep 2016"
.SH NAME
.B lv2info \- print information about an installed LV2 plugin.
.B lv2info \- print information about an installed LV2 plugin
.SH SYNOPSIS
.B lv2info PLUGIN_URI
.SH OPTIONS
.TP
\fB\-p FILE
\fB\-p FILE\fR
Write Turtle description of plugin to FILE
.TP
\fB\-m FILE
\fB\-m FILE\fR
Add record of plugin to manifest FILE
.TP
@ -22,7 +22,7 @@ Display help and exit
\fB\-\-version\fR
Display version information and exit
.SH SEE ALSO
.SH "SEE ALSO"
.BR lilv(3),
.BR lv2ls(1)

View File

@ -1,7 +1,7 @@
.TH LV2LS 1 "17 Jan 2012"
.TH LV2LS 1 "26 Aug 2016"
.SH NAME
.B lv2ls \- List all installed LV2 plugins.
.B lv2ls \- list all installed LV2 plugins
.SH SYNOPSIS
.B lv2ls [OPTION]...
@ -19,7 +19,7 @@ Display help and exit
\fB\-\-version\fR
Display version information and exit
.SH SEE ALSO
.SH "SEE ALSO"
.BR lilv(3),
.BR lv2info(1)

View File

@ -0,0 +1,6 @@
Lilv is a C library to make the use of [LV2] plugins as simple as possible for
applications.
The complete API is documented in the [lilv](@ref lilv) group.
[LV2]: http://lv2plug.in/

File diff suppressed because it is too large Load Diff

View File

@ -1,83 +1,113 @@
body {
font-size: medium;
font-family: sans-serif;
background: #FFF;
color: #222;
font-style: normal;
line-height: 1.6em;
margin-left: auto;
margin-right: auto;
padding: 1em;
max-width: 60em;
font-family: "DejaVu Serif",Palatino,serif;
text-rendering: optimizeLegibility;
}
#top {
background-color: #F3F3F3;
h1, .title, #projectname, h2, h3, h4, h5, h6 {
line-height: 1.0125em;
color: #444;
font-family: "DejaVu Sans",Helvetica,Arial,sans-serif;
margin: 1em 0 0.5em 0;
}
h1, .titlearea .header .titlebox, #projectname {
font-size: 300%;
font-weight: 400;
margin-bottom: 0.25em;
margin-top: 0;
}
.header .headertitle .title {
font-size: 180%;
font-weight: 400;
margin: 0.75em 0.25em 0.5em 0;
}
.ingroups {
display: inline;
}
.title .ingroups a {
font-size: small;
margin-left: 1em;
}
#titlebox, #metabox {
display: inline-block;
}
#titlebox{
display: inline-block;
width: 75%;
left: 0;
top: 0;
}
#title {
margin-bottom: 0.25em;
}
#shortdesc {
margin: 0;
padding: 0;
border-bottom: 1px solid #DDD;
margin-bottom: 1ex;
font-size: xx-large;
font-weight: bold;
color: #666;
display: inline-block;
font-style: italic;
padding: 0;
}
div.header {
display: none;
}
.tabs {
display: none;
}
h1 h2 h3 h4 h5 h6 {
font-weight: bold;
}
h1 {
font-size: 164%;
#titlearea {
margin: 0.25em auto 0.25em auto;
padding: 0;
position: relative;
clear: both;
line-height: 1.0em;
}
h2 {
font-size: 132%;
font-size: 160%;
font-weight: 400;
}
h3 {
font-size: 124%;
font-size: 140%;
font-weight: 400;
}
h4 {
font-size: 116%;
font-size: 120%;
font-weight: 500;
}
h5 {
font-size: 108%;
h5, h6 {
font-size: 110%;
font-weight: 600;
}
h6 {
font-size: 100%;
h1 a, h1 a:link, h1 a:visited ,
h2 a, h2 a:link, h2 a:visited ,
h3 a, h3 a:link, h3 a:visited ,
h4 a, h4 a:link, h4 a:visited ,
h5 a, h5 a:link, h5 a:visited ,
h6 a, h6 a:link, h6 a:visited {
color: #444;
}
p {
margin: 0 0 1ex 0;
}
br {
display: none;
margin: 0.5em 0 0.5em 0;
}
dt {
font-weight: 700;
}
div.multicol {
}
p.startli,p.startdd,p.starttd {
margin-top: 2px;
}
p.endli {
margin-bottom: 0;
}
p.enddd {
margin-bottom: 4px;
}
p.endtd {
margin-bottom: 2px;
dd {
margin-left: 2em;
}
caption {
@ -85,12 +115,12 @@ caption {
}
span.legend {
font-size: 70%;
font-size: small;
text-align: center;
}
h3.version {
font-size: 90%;
font-size: small;
text-align: center;
}
@ -102,23 +132,18 @@ div.qindex,div.navtab {
padding: 2px;
}
div.qindex,div.navpath {
width: 100%;
line-height: 140%;
}
div.navtab {
margin-right: 15px;
}
/* @group Link Styling */
a {
color: #3D8C57;
color: #546E00;
text-decoration: none;
}
.contents a:visited {
color: #50755E;
color: #344E00;
}
a:hover {
@ -131,12 +156,8 @@ a.qindexHL {
border: 1px double #869DCA;
}
a.code {
color: #4665A2;
}
a.codeRef {
color: #4665A2;
code {
color: #444;
}
/* @end */
@ -145,18 +166,14 @@ dl.el {
}
.fragment {
font-family: monospace, fixed;
font-size: 105%;
font-family: "DejaVu Sans Mono",monospace,fixed;
}
pre.fragment {
border: 1px solid #C4C4C4;
background-color: #F9F9F9;
padding: 4px 6px;
margin: 4px 8px 4px 2px;
padding: 0.5em;
overflow: auto;
font-size: 9pt;
line-height: 125%;
}
div.ah {
@ -176,21 +193,20 @@ div.groupHeader {
font-weight: 700;
}
a + h2.groupheader {
display: none;
}
div.groupText {
margin-left: 16px;
font-style: italic;
}
body {
background: #FFF;
color: #000;
margin: 0;
}
div.contents {
margin-top: 10px;
margin-left: 10px;
margin-right: 10px;
div.contents, #content {
padding: 0 0.25em 0 0.25em;
max-width: 60em;
margin-left: auto;
margin-right: auto;
}
td.indexkey {
@ -208,6 +224,10 @@ td.indexvalue {
margin: 2px 0;
}
table.memname {
font-family: "DejaVu Sans Mono",monospace,fixed;
}
tr.memlist {
background-color: #EEF1F7;
}
@ -216,9 +236,6 @@ p.formulaDsp {
text-align: center;
}
img.formulaDsp {
}
img.formulaInl {
vertical-align: middle;
}
@ -236,7 +253,6 @@ div.center img {
address.footer {
text-align: right;
padding: 0 0.25em 0.25em 0;
}
img.footer {
@ -246,48 +262,36 @@ img.footer {
/* @group Code Colorization */
span.keyword {
color: green;
color: #586E75;
}
span.keywordtype {
color: #604020;
color: #546E00;
}
span.keywordflow {
color: #e08000;
color: #586E75;
}
span.comment {
color: maroon;
color: #6C71C4;
}
span.preprocessor {
color: #806020;
color: #D33682;
}
span.stringliteral {
color: #002080;
color: #CB4B16;
}
span.charliteral {
color: teal;
}
span.vhdldigit {
color: #F0F;
}
span.vhdlkeyword {
color: #700070;
}
span.vhdllogic {
color: red;
color: #CB4B16;
}
/* @end */
td.tiny {
font-size: 75%;
font-size: x-small;
}
.dirtab {
@ -308,20 +312,25 @@ hr {
margin: 2em 0 1em;
}
hr.footer {
height: 1px;
#footer {
bottom: 0;
clear: both;
font-size: x-small;
margin: 2em 0 0;
padding: 0 1em 1em 1em;
vertical-align: top;
color: #888;
}
/* @group Member Descriptions */
table.memberdecls {
border-spacing: 0;
font-size: small;
border-spacing: 0.125em;
line-height: 1.3em;
}
.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,.memTemplItemLeft,.memTemplItemRight,.memTemplParams {
background-color: #FBFBFB;
margin: 0;
padding: 0.25ex;
padding: 0;
}
.mdescLeft,.mdescRight {
@ -329,12 +338,18 @@ table.memberdecls {
}
.memItemLeft,.memItemRight,.memTemplParams {
border-top: 1px solid #DDD;
border: 0;
font-family: "DejaVu Sans Mono",monospace,fixed;
}
.memItemLeft,.memTemplItemLeft {
white-space: nowrap;
padding-left: 2em;
padding-right: 1em;
}
.memItemLeft a.el {
font-weight: bold;
}
.memTemplParams {
@ -342,18 +357,33 @@ table.memberdecls {
white-space: nowrap;
}
td.memSeparator {
display: none;
}
td.mlabels-right {
vertical-align: top;
padding-top: 4px;
color: #B4C342;
}
.memtitle {
display: none;
}
/* @end */
/* @group Member Details */
/* Styles for detailed member documentation */
.memtemplate {
font-size: 80%;
color: #4665A2;
font-weight: bold;
color: #888;
font-style: italic;
font-family: "DejaVu Sans Mono",monospace,fixed;
font-size: small;
}
.memnav {
background-color: #EBEFF6;
border: 1px solid #A3B4D7;
background-color: #EEE;
border: 1px solid #B4C342;
text-align: center;
margin: 2px;
margin-right: 15px;
@ -361,27 +391,25 @@ table.memberdecls {
}
.memitem {
padding: 0;
margin: 1ex 0 2ex 0;
border: 1px solid #CCC;
}
.memname {
white-space: nowrap;
font-weight: bold;
padding: 0.25em 0.5em 0.25em 0.5em;
margin: 0 0 1em 0;
border-radius: 6px;
border: 1px solid #DDD;
}
.memproto {
border-bottom: 1px solid #DDD;
padding: 0.5ex;
font-weight: bold;
background-color: #F3F3F3;
font-size: 110%;
font-weight: 400;
line-height: 1em;
color: #000;
}
.memproto .paramname {
font-style: normal;
}
.memdoc {
padding: 1ex;
background-color: #FBFBFB;
border-top-width: 0;
padding: 0 0.25em 0 0.25em;
}
.paramkey {
@ -389,16 +417,54 @@ table.memberdecls {
}
.paramtype {
color: #666;
padding-right: 0.5em;
white-space: nowrap;
}
.paramname {
color: #602020;
color: #111;
white-space: nowrap;
font-family: "DejaVu Sans Mono",monospace,fixed;
font-style: italic;
padding-right: 0.5em;
}
.paramname em {
font-style: normal;
.fieldname {
color: #000;
}
.fieldtable {
padding-top: 0.25em;
border-top: 1px dashed #DDD;
}
.fieldtable tbody tr:first-child {
display: none;
}
td.fieldname {
padding: 0 0.5em 0 0.25em;
vertical-align: top;
font-family: "DejaVu Sans Mono",monospace,fixed;
}
td.fieldtype {
color: #666;
padding: 0 0.5em 0 0;
vertical-align: top;
font-family: "DejaVu Sans Mono",monospace,fixed;
}
td.fielddoc p {
margin: 0;
vertical-align: top;
padding: 0 0.5em 0 0;
}
p.reference {
font-size: x-small;
font-style: italic;
}
/* @end */
@ -411,9 +477,8 @@ table.memberdecls {
/* these are for tree view when used as main index */
.directory {
font-size: 9pt;
font-weight: bold;
margin: 5px;
font-size: small;
margin: 0.5em;
}
.directory h3 {
@ -440,6 +505,22 @@ table.memberdecls {
vertical-align: -30%;
}
td.entry {
font-family: "DejaVu Sans",Helvetica,Arial,sans-serif;
font-weight: 400;
padding-right: 1em;
}
td.entry .arrow {
display: none;
}
td.entry b {
font-family: "DejaVu Sans",Helvetica,Arial,sans-serif;
font-weight: 400;
font-size: 130%;
}
/* these are for tree view when not used as main index */
.directory-alt {
font-size: 100%;
@ -477,12 +558,12 @@ div.dynheader {
address {
font-style: normal;
color: #2A3D61;
color: #444;
}
table.doxtable {
border-collapse: collapse;
margin: 0.5ex;
margin: 0.5em;
}
table.doxtable td,table.doxtable th {
@ -508,56 +589,151 @@ table.doxtable th {
font-size: 13px;
}
div.navpath {
color: #DDD;
}
.navpath ul {
font-size: 11px;
height: 30px;
line-height: 30px;
color: #8AA0CC;
border: 1px solid #C2CDE4;
overflow: hidden;
margin: 0;
padding: 0;
}
.navpath li {
list-style-type: none;
float: left;
padding-left: 10px;
padding-right: 15px;
color: #364D7C;
padding-left: 0;
margin-left: 0.5em;
padding-right: 1em;
}
.navpath a {
height: 32px;
display: block;
text-decoration: none;
outline: none;
}
.navpath a:hover {
color: #6884BD;
}
div.summary {
float: right;
font-size: 8pt;
padding-right: 5px;
width: 50%;
text-align: right;
font-size: small;
font-family: "DejaVu Sans",Helvetica,Arial,sans-serif;
margin: 0;
color: #FFF; /* Hide separator bars */
border-bottom: 1px solid #DDD;
padding: 0.25em 0;
}
div.summary a {
white-space: nowrap;
}
div.header {
background-color: #F3F3F3;
margin: 0;
border-bottom: 1px solid #DDD;
/* Metadata box (right aligned next to title) */
#metabox {
display: inline-block;
font-size: x-small;
margin: 0 0 0.25em 0;
position: absolute;
right: 0;
top: 0;
color: #666;
font-style: italic;
padding: 0 1em;
}
div.headertitle {
padding: 5px 5px 5px 10px;
font-size: 180%;
font-weight: bold;
#meta {
border-style: hidden;
margin-right: 0.25em;
}
#meta tr, #meta th, #meta td {
background-color: transparent;
border: 0;
margin: 0;
font-weight: normal;
}
#meta th {
text-align: right;
}
#meta th:after {
content: ":";
}
div.line {
font-family: "DejaVu Sans Mono",monospace,fixed;
line-height: 1.4em;
white-space: pre-wrap;
}
.glow {
background-color: #2AA198;
box-shadow: 0 0 10px #2AA198;
}
span.lineno {
padding-right: 4px;
text-align: right;
border-right: 2px solid #546E00;
background-color: #E8E8E8;
white-space: pre;
}
span.lineno a {
background-color: #D8D8D8;
}
span.lineno a:hover {
background-color: #C8C8C8;
}
.tabs, .tabs2, .navpath {
padding: 0.25em 0;
border-bottom: 1px solid #DDD;
font-size: small;
font-family: "DejaVu Sans",Helvetica,Arial,sans-serif;
margin: 0;
}
th {
text-align: left;
font-size: 110%;
font-weight: 500;
}
.mlabel {
padding: 0.125em;
}
/* tabs*/
.tablist {
margin: 0;
padding: 0;
display: table;
}
.tablist li {
display: table-cell;
line-height: 2em;
list-style: none;
border-bottom: 0;
}
.tablist a {
display: block;
padding: 0 1em 0 0;
font-family: "DejaVu Sans",Helvetica,Arial,sans-serif;
text-decoration: none;
outline: none;
}
.tabs3 .tablist a {
padding: 0 10px;
}
.tablist li.current a {
color: #222;
}
span.icon {
display: none;
}

View File

@ -6,6 +6,6 @@ includedir=@INCLUDEDIR@
Name: Lilv
Version: @LILV_VERSION@
Description: Simple C library for hosting LV2 plugins
Requires: lv2 @PKG_serd_0@ @PKG_sord_0@ @PKG_sratom_0@
Libs: -L${libdir} -l@LIB_LILV@ -ldl
Requires: @LILV_PKG_DEPS@
Libs: -L${libdir} -l@LIB_LILV@ @LILV_PKG_LIBS@
Cflags: -I${includedir}/lilv-@LILV_MAJOR_VERSION@

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -21,14 +21,15 @@
#ifndef LILV_LILV_H
#define LILV_LILV_H
#include "lv2/core/lv2.h"
#include "lv2/urid/urid.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#ifdef LILV_SHARED
# ifdef _WIN32
# define LILV_LIB_IMPORT __declspec(dllimport)
@ -45,11 +46,15 @@
#else
# define LILV_API
#endif
#if defined(__GNUC__) && (__GNUC__ > 3 || \
(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
# define LILV_DEPRECATED __attribute__((__deprecated__))
#else
# define LILV_DEPRECATED
#endif
#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif
#define LILV_NS_DOAP "http://usefulinc.com/ns/doap#"
@ -61,8 +66,10 @@ extern "C" {
#define LILV_NS_RDFS "http://www.w3.org/2000/01/rdf-schema#"
#define LILV_NS_XSD "http://www.w3.org/2001/XMLSchema#"
#define LILV_URI_ATOM_PORT "http://lv2plug.in/ns/ext/atom#AtomPort"
#define LILV_URI_AUDIO_PORT "http://lv2plug.in/ns/lv2core#AudioPort"
#define LILV_URI_CONTROL_PORT "http://lv2plug.in/ns/lv2core#ControlPort"
#define LILV_URI_CV_PORT "http://lv2plug.in/ns/lv2core#CVPort"
#define LILV_URI_EVENT_PORT "http://lv2plug.in/ns/ext/event#EventPort"
#define LILV_URI_INPUT_PORT "http://lv2plug.in/ns/lv2core#InputPort"
#define LILV_URI_MIDI_EVENT "http://lv2plug.in/ns/ext/midi#MidiEvent"
@ -95,6 +102,16 @@ typedef void LilvNodes; /**< set<Node>. */
@{
*/
/**
Free memory allocated by Lilv.
This function exists because some systems require memory allocated by a
library to be freed by code in the same library. It is otherwise equivalent
to the standard C free() function.
*/
LILV_API void
lilv_free(void* ptr);
/**
@name Node
@{
@ -104,11 +121,24 @@ typedef void LilvNodes; /**< set<Node>. */
Convert a file URI string to a local path string.
For example, "file://foo/bar/baz.ttl" returns "/foo/bar/baz.ttl".
Return value is shared and must not be deleted by caller.
This function does not handle escaping correctly and should not be used for
general file URIs. Use lilv_file_uri_parse() instead.
@return `uri` converted to a path, or NULL on failure (URI is not local).
*/
LILV_API const char*
LILV_API LILV_DEPRECATED const char*
lilv_uri_to_path(const char* uri);
/**
Convert a file URI string to a local path string.
For example, "file://foo/bar%20one/baz.ttl" returns "/foo/bar one/baz.ttl".
Return value must be freed by caller with lilv_free().
@param uri The file URI to parse.
@param hostname If non-NULL, set to the hostname in the URI, if any.
@return `uri` converted to a path, or NULL on failure (URI is not local).
*/
LILV_API char*
lilv_file_uri_parse(const char* uri, char** hostname);
/**
Create a new URI value.
Returned value must be freed by caller with lilv_node_free().
@ -178,15 +208,15 @@ lilv_node_equals(const LilvNode* value, const LilvNode* other);
/**
Return this value as a Turtle/SPARQL token.
Returned value must be freed by caller with free().
Returned value must be freed by caller with lilv_free().
<table>
<caption>Example Turtle Tokens</caption>
<tr><th>URI</th><td>&lt;http://example.org/foo &gt;</td></tr>
<tr><th>QName</td><td>doap:name</td></tr>
<tr><th>String</td><td>"this is a string"</td></tr>
<tr><th>Float</td><td>1.0</td></tr>
<tr><th>Integer</td><td>1</td></tr>
<tr><th>Boolean</td><td>true</td></tr>
<tr><th>QName</th><td>doap:name</td></tr>
<tr><th>String</th><td>"this is a string"</td></tr>
<tr><th>Float</th><td>1.0</td></tr>
<tr><th>Integer</th><td>1</td></tr>
<tr><th>Boolean</th><td>true</td></tr>
</table>
*/
LILV_API char*
@ -240,6 +270,14 @@ lilv_node_is_string(const LilvNode* value);
LILV_API const char*
lilv_node_as_string(const LilvNode* value);
/**
Return the path of a file URI node.
Returns NULL if `value` is not a file URI.
Returned value must be freed by caller with lilv_free().
*/
LILV_API char*
lilv_node_get_path(const LilvNode* value, char** hostname);
/**
Return whether this value is a decimal literal.
*/
@ -314,7 +352,7 @@ lilv_node_as_bool(const LilvNode* value);
@endcode
*/
#define LILV_FOREACH(colltype, iter, collection) \
for (LilvIter* (iter) = lilv_ ## colltype ## _begin(collection); \
for (LilvIter* iter = lilv_ ## colltype ## _begin(collection); \
!lilv_ ## colltype ## _is_end(collection, iter); \
(iter) = lilv_ ## colltype ## _next(collection, iter))
@ -425,7 +463,7 @@ lilv_nodes_get_first(const LilvNodes* collection);
Return whether `values` contains `value`.
*/
LILV_API bool
lilv_nodes_contains(const LilvNodes* values, const LilvNode* value);
lilv_nodes_contains(const LilvNodes* nodes, const LilvNode* value);
/**
Return a new LilvNodes that contains all nodes from both `a` and `b`.
@ -492,12 +530,20 @@ lilv_world_new(void);
*/
#define LILV_OPTION_DYN_MANIFEST "http://drobilla.net/ns/lilv#dyn-manifest"
/**
Set application-specific LV2_PATH. This overrides the LV2_PATH from the
environment, so that lilv will only look inside the given path. This can be
used to make self-contained applications.
*/
#define LILV_OPTION_LV2_PATH "http://drobilla.net/ns/lilv#lv2-path"
/**
Set an option option for `world`.
Currently recognized options:
@ref LILV_OPTION_FILTER_LANG
@ref LILV_OPTION_DYN_MANIFEST
@ref LILV_OPTION_LV2_PATH
*/
LILV_API void
lilv_world_set_option(LilvWorld* world,
@ -533,7 +579,7 @@ lilv_world_load_all(LilvWorld* world);
`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 lilv_world_load_all).
Normal hosts should not need this function (use lilv_world_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
@ -541,19 +587,39 @@ lilv_world_load_all(LilvWorld* world);
other things) MUST be identified by URIs (not paths) in save files.
*/
LILV_API void
lilv_world_load_bundle(LilvWorld* world,
LilvNode* bundle_uri);
lilv_world_load_bundle(LilvWorld* world,
const LilvNode* bundle_uri);
/**
Load all specifications from currently loaded bundles.
This is for hosts that explicitly load specific bundles, its use is not
necessary when using lilv_world_load_all(). This function parses the
specifications and adds them to the model.
*/
LILV_API void
lilv_world_load_specifications(LilvWorld* world);
/**
Load all plugin classes from currently loaded specifications.
Must be called after lilv_world_load_specifications(). This is for hosts
that explicitly load specific bundles, its use is not necessary when using
lilv_world_load_all().
*/
LILV_API void
lilv_world_load_plugin_classes(LilvWorld* world);
/**
Unload a specific bundle.
This unloads statements loaded by lilv_world_load_bundle(). Note that this
is not necessarily all information loaded from the bundle. If any resources
have been separately loaded with liv_world_load_resource(), they must be
have been separately loaded with lilv_world_load_resource(), they must be
separately unloaded with lilv_world_unload_resource().
*/
LILV_API int
lilv_world_unload_bundle(LilvWorld* world, LilvNode* bundle_uri);
lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri);
/**
Load all the data associated with the given `resource`.
@ -649,6 +715,16 @@ lilv_world_ask(LilvWorld* world,
const LilvNode* predicate,
const LilvNode* object);
/**
Get an LV2 symbol for some subject.
This will return the lv2:symbol property of the subject if it is given
explicitly, and otherwise will attempt to derive a symbol from the URI.
@return A string node that is a valid LV2 symbol, or NULL on error.
*/
LILV_API LilvNode*
lilv_world_get_symbol(LilvWorld* world, const LilvNode* subject);
/**
@}
@name Plugin
@ -687,13 +763,14 @@ lilv_plugin_get_uri(const LilvPlugin* plugin);
/**
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,
lilv_plugin_get_data_uris may return URIs which are not within this 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,
lilv_plugin_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_uri_to_path.
filesystem path, use lilv_file_uri_parse().
@return a shared string which must not be modified or freed.
*/
LILV_API const LilvNode*
@ -703,7 +780,7 @@ lilv_plugin_get_bundle_uri(const LilvPlugin* plugin);
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_uri_to_path.
filesystem paths, use lilv_file_uri_parse().
@return a list of complete URLs eg. "file:///foo/ABundle.lv2/aplug.ttl",
which is shared and must not be modified or freed.
*/
@ -713,7 +790,7 @@ lilv_plugin_get_data_uris(const LilvPlugin* plugin);
/**
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_uri_to_path.
filesystem path, use lilv_file_uri_parse().
@return a shared string which must not be modified or freed.
*/
LILV_API const LilvNode*
@ -748,7 +825,7 @@ lilv_plugin_get_class(const LilvPlugin* plugin);
Return value must be freed by caller with lilv_nodes_free().
*/
LILV_API LilvNodes*
lilv_plugin_get_value(const LilvPlugin* p,
lilv_plugin_get_value(const LilvPlugin* plugin,
const LilvNode* predicate);
/**
@ -757,21 +834,21 @@ lilv_plugin_get_value(const LilvPlugin* p,
of the plugin.
*/
LILV_API bool
lilv_plugin_has_feature(const LilvPlugin* p,
const LilvNode* feature_uri);
lilv_plugin_has_feature(const LilvPlugin* plugin,
const LilvNode* feature);
/**
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 lilv_plugin_get_optional_features
and lilv_plugin_get_required_features separately is best in most cases.
probably shouldn't be used by normal hosts. Using lilv_plugin_get_optional_features()
and lilv_plugin_get_required_features() separately is best in most cases.
Returned value must be freed by caller with lilv_nodes_free().
*/
LILV_API LilvNodes*
lilv_plugin_get_supported_features(const LilvPlugin* p);
lilv_plugin_get_supported_features(const LilvPlugin* plugin);
/**
Get the LV2 Features required by a plugin.
@ -785,7 +862,7 @@ lilv_plugin_get_supported_features(const LilvPlugin* p);
Return value must be freed by caller with lilv_nodes_free().
*/
LILV_API LilvNodes*
lilv_plugin_get_required_features(const LilvPlugin* p);
lilv_plugin_get_required_features(const LilvPlugin* plugin);
/**
Get the LV2 Features optionally supported by a plugin.
@ -796,13 +873,13 @@ lilv_plugin_get_required_features(const LilvPlugin* p);
Return value must be freed by caller with lilv_nodes_free().
*/
LILV_API LilvNodes*
lilv_plugin_get_optional_features(const LilvPlugin* p);
lilv_plugin_get_optional_features(const LilvPlugin* plugin);
/**
Return whether or not a plugin provides a specific extension data.
*/
LILV_API bool
lilv_plugin_has_extension_data(const LilvPlugin* p,
lilv_plugin_has_extension_data(const LilvPlugin* plugin,
const LilvNode* uri);
/**
@ -811,13 +888,13 @@ lilv_plugin_has_extension_data(const LilvPlugin* p,
will return a value for without instantiating the plugin.
*/
LILV_API LilvNodes*
lilv_plugin_get_extension_data(const LilvPlugin* p);
lilv_plugin_get_extension_data(const LilvPlugin* plugin);
/**
Get the number of ports on this plugin.
*/
LILV_API uint32_t
lilv_plugin_get_num_ports(const LilvPlugin* p);
lilv_plugin_get_num_ports(const LilvPlugin* plugin);
/**
Get the port ranges (minimum, maximum and default values) for all ports.
@ -831,10 +908,10 @@ lilv_plugin_get_num_ports(const LilvPlugin* p);
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 lilv_port_get_range.
repeated calls to lilv_port_get_range().
*/
LILV_API void
lilv_plugin_get_port_ranges_float(const LilvPlugin* p,
lilv_plugin_get_port_ranges_float(const LilvPlugin* plugin,
float* min_values,
float* max_values,
float* def_values);
@ -846,20 +923,18 @@ lilv_plugin_get_port_ranges_float(const LilvPlugin* p,
OF THIS FUNCTION WITH NULL OR VERY NASTY THINGS WILL HAPPEN.
*/
LILV_API uint32_t
lilv_plugin_get_num_ports_of_class(const LilvPlugin* p,
lilv_plugin_get_num_ports_of_class(const LilvPlugin* plugin,
const LilvNode* class_1, ...);
#ifndef SWIG
/**
Variant of lilv_plugin_get_num_ports_of_class() that takes a va_list.
This function calls va_arg() on `args` but does not call va_end().
*/
LILV_API uint32_t
lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* p,
lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* plugin,
const LilvNode* class_1,
va_list args);
#endif
/**
Return whether or not the plugin introduces (and reports) latency.
@ -867,19 +942,19 @@ lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* p,
lilv_plugin_get_latency_port() ONLY if this function returns true.
*/
LILV_API bool
lilv_plugin_has_latency(const LilvPlugin* p);
lilv_plugin_has_latency(const LilvPlugin* plugin);
/**
Return the index of the plugin's latency port.
It is a fatal error to call this on a plugin without checking if the port
exists by first calling lilv_plugin_has_latency.
exists by first calling lilv_plugin_has_latency().
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.
*/
LILV_API uint32_t
lilv_plugin_get_latency_port_index(const LilvPlugin* p);
lilv_plugin_get_latency_port_index(const LilvPlugin* plugin);
/**
Get a port on `plugin` by `index`.
@ -890,7 +965,7 @@ lilv_plugin_get_port_by_index(const LilvPlugin* plugin,
/**
Get a port on `plugin` by `symbol`.
Note this function is slower than lilv_plugin_get_port_by_index,
Note this function is slower than lilv_plugin_get_port_by_index(),
especially on plugins with a very large number of ports.
*/
LILV_API const LilvPort*
@ -990,7 +1065,7 @@ lilv_plugin_write_manifest_entry(LilvWorld* world,
If `type` is NULL, all such resources will be returned, regardless of type.
To actually load the data for each returned resource, use
lilv_world_load_resource.
lilv_world_load_resource().
*/
LILV_API LilvNodes*
lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type);
@ -1013,7 +1088,7 @@ lilv_port_get_node(const LilvPlugin* plugin,
const LilvPort* port);
/**
Port analog of lilv_plugin_get_value.
Port analog of lilv_plugin_get_value().
*/
LILV_API LilvNodes*
lilv_port_get_value(const LilvPlugin* plugin,
@ -1043,9 +1118,9 @@ lilv_port_get_properties(const LilvPlugin* plugin,
Return whether a port has a certain property.
*/
LILV_API bool
lilv_port_has_property(const LilvPlugin* p,
lilv_port_has_property(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* property_uri);
const LilvNode* property);
/**
Return whether a port supports a certain event type.
@ -1054,7 +1129,7 @@ lilv_port_has_property(const LilvPlugin* p,
ev:supportsEvent property with `event_type` as the value.
*/
LILV_API bool
lilv_port_supports_event(const LilvPlugin* p,
lilv_port_supports_event(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* event_type);
@ -1089,7 +1164,7 @@ lilv_port_get_name(const LilvPlugin* plugin,
/**
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 lilv_port_is_a.
control, midi, etc, etc, though it's simpler to use lilv_port_is_a().
The returned list does not include lv2:Port, which is implied.
Returned value is shared and must not be destroyed by caller.
*/
@ -1115,13 +1190,13 @@ lilv_port_is_a(const LilvPlugin* plugin,
`def`, `min`, and `max` are outputs, pass pointers to uninitialized
LilvNode* variables. These will be set to point at new values (which must
be freed by the caller using lilv_node_free), or NULL if the value does not
exist.
be freed by the caller using lilv_node_free()), or NULL if the value does
not exist.
*/
LILV_API void
lilv_port_get_range(const LilvPlugin* plugin,
const LilvPort* port,
LilvNode** deflt,
LilvNode** def,
LilvNode** min,
LilvNode** max);
@ -1148,13 +1223,13 @@ lilv_port_get_scale_points(const LilvPlugin* plugin,
the plugin URI as the `subject` parameter.
@param world The world.
@param map URID mapper.
@param subject The subject of the state description (e.g. a preset URI).
@param node The subject of the state description (e.g. a preset URI).
@return A new LilvState which must be freed with lilv_state_free(), or NULL.
*/
LILV_API LilvState*
lilv_state_new_from_world(LilvWorld* world,
LV2_URID_Map* map,
const LilvNode* subject);
const LilvNode* node);
/**
Load a state snapshot from a file.
@ -1209,32 +1284,37 @@ typedef const void* (*LilvGetPortValueFunc)(const char* port_symbol,
@param map The map to use for mapping URIs in state.
@param file_dir Directory of files created by the plugin earlier (or NULL).
This is for hosts that support file creation at any time with state
@param scratch_dir Directory of files created by the plugin earlier, or
NULL. This is for hosts that support file creation at any time with state
state:makePath. These files will be copied as necessary to `copy_dir` and
not be referred to directly in state (a temporary directory is appropriate).
@param copy_dir Directory of copies of files in `file_dir` (or NULL). This
directory will have the same structure as `file_dir` but with possibly
modified file names to distinguish different revisions. If you only care
about saving one state snapshot, it can be the same as `save_dir`. Plugin
state will refer to files in this directory.
@param copy_dir Directory of copies of files in `scratch_dir`, or NULL.
This directory will have the same structure as `scratch_dir` but with
possibly modified file names to distinguish revisions. This allows the
saved state to contain the exact contents of the scratch file at save time,
so that the state is not ruined if the file is later modified (for example,
by the plugin continuing to record). This can be the same as `save_dir` to
create a copy in the state bundle, but can also be a separate directory
which allows multiple state snapshots to share a single copy if the file has
not changed.
@param save_dir Directory of files created by plugin during save (or NULL).
If the state will be saved, this should be the bundle directory later passed
to lilv_state_save.
@param get_value Function to get port values.
@param user_data User data to pass to `get_value`.
@param link_dir Directory of links to external files (or NULL). A link will
@param link_dir Directory of links to external files, or NULL. A link will
be made in this directory to any external files referred to in plugin state.
In turn, links will be created in the save directory to these links (e.g.
save_dir/file => link_dir/file => /foo/bar/file). This allows many state
snapshots to share a single link to an external file, so archival
(e.g. with tar -h) will not create several copies of the file. If this is
not required, it can be the same as save_dir.
snapshots to share a single link to an external file, so archival (e.g. with
tar -h) will not create several copies of the file. If this is not
required, it can be the same as `save_dir`.
@param save_dir Directory of files created by plugin during save (or NULL).
This is typically the bundle directory later passed to lilv_state_save().
@param get_value Function to get port values (or NULL). If NULL, the
returned state will not represent port values. This should only be NULL in
hosts that save and restore port values via some other mechanism.
@param user_data User data to pass to `get_value`.
@param flags Bitwise OR of LV2_State_Flags values.
@ -1253,12 +1333,12 @@ typedef const void* (*LilvGetPortValueFunc)(const char* port_symbol,
saving an instances state many times while avoiding any duplication of data.
If supported (via state:makePath passed to LV2_Descriptor::instantiate()),
`file_dir` should be the directory where any files created by the plugin
`scratch_dir` should be the directory where any files created by the plugin
(not during save time, e.g. during instantiation) are stored. These files
will be copied to preserve their state at this time.plugin-created files are stored.
Lilv will assume any files within this directory (recursively) are created
by the plugin and all other files are immutable. Note that this function
does not save the state, use lilv_state_save() for that.
will be copied to preserve their state at this time.plugin-created files are
stored. Lilv will assume any files within this directory (recursively) are
created by the plugin and all other files are immutable. Note that this
function does not save the state, use lilv_state_save() for that.
See <a href="http://lv2plug.in/ns/ext/state/state.h">state.h</a> from the
LV2 State extension for details on the `flags` and `features` parameters.
@ -1267,7 +1347,7 @@ LILV_API LilvState*
lilv_state_new_from_instance(const LilvPlugin* plugin,
LilvInstance* instance,
LV2_URID_Map* map,
const char* file_dir,
const char* scratch_dir,
const char* copy_dir,
const char* link_dir,
const char* save_dir,
@ -1300,6 +1380,14 @@ lilv_state_get_num_properties(const LilvState* state);
LILV_API const LilvNode*
lilv_state_get_plugin_uri(const LilvState* state);
/**
Get the URI of `state`.
This may return NULL if the state has not been saved and has no URI.
*/
LILV_API const LilvNode*
lilv_state_get_uri(const LilvState* state);
/**
Get the label of `state`.
*/
@ -1313,6 +1401,28 @@ LILV_API void
lilv_state_set_label(LilvState* state,
const char* label);
/**
Set a metadata property on `state`.
@param state The state to set the metadata for.
@param key The key to store `value` under (URID).
@param value Pointer to the value to be stored.
@param size The size of `value` in bytes.
@param type The type of `value` (URID).
@param flags LV2_State_Flags for `value`.
@return 0 on success.
This is a generic version of lilv_state_set_label(), which sets metadata
properties visible to hosts, but not plugins. This allows storing useful
information such as comments or preset banks.
*/
LILV_API int
lilv_state_set_metadata(LilvState* state,
uint32_t key,
const void* value,
size_t size,
uint32_t type,
uint32_t flags);
/**
Function to set a port value.
@param port_symbol The symbol of the port.
@ -1327,6 +1437,22 @@ typedef void (*LilvSetPortValueFunc)(const char* port_symbol,
uint32_t size,
uint32_t type);
/**
Enumerate the port values in a state snapshot.
@param state The state to retrieve port values from.
@param set_value A function to receive port values.
@param user_data User data to pass to `set_value`.
This function is a subset of lilv_state_restore() that only fires the
`set_value` callback and does not directly affect a plugin instance. This
is useful in hosts that need to retrieve the port values in a state snapshot
for special handling.
*/
LILV_API void
lilv_state_emit_port_values(const LilvState* state,
LilvSetPortValueFunc set_value,
void* user_data);
/**
Restore a plugin instance from a state snapshot.
@param state The state to restore, which must apply to the correct plugin.
@ -1337,10 +1463,10 @@ typedef void (*LilvSetPortValueFunc)(const char* port_symbol,
@param features Features to pass LV2_State_Interface.restore().
This will set all the properties of `instance`, if given, to the values
stored in `state`. If `set_value` is provided, it will be called (with
the given `user_data`) to restore each port value, otherwise the host must
restore the port values itself (using lilv_state_get_port_value) in order to
completely restore `state`.
stored in `state`. If `set_value` is provided, it will be called (with the
given `user_data`) to restore each port value, otherwise the host must
restore the port values itself (using lilv_state_get_port_value()) in order
to completely restore `state`.
If the state has properties and `instance` is given, this function is in
the "instantiation" threading class, i.e. it MUST NOT be called
@ -1404,6 +1530,24 @@ lilv_state_to_string(LilvWorld* world,
const char* uri,
const char* base_uri);
/**
Unload a state from the world and delete all associated files.
@param world The world.
@param state State to remove from the system.
This function DELETES FILES/DIRECTORIES FROM THE FILESYSTEM! It is intended
for removing user-saved presets, but can delete any state the user has
permission to delete, including presets shipped with plugins.
The rdfs:seeAlso file for the state will be removed. The entry in the
bundle's manifest.ttl is removed, and if this results in an empty manifest,
then the manifest file is removed. If this results in an empty bundle, then
the bundle directory is removed as well.
*/
LILV_API int
lilv_state_delete(LilvWorld* world,
const LilvState* state);
/**
@}
@name Scale Point
@ -1471,7 +1615,7 @@ lilv_plugin_class_get_children(const LilvPluginClass* plugin_class);
/* Instance of a plugin.
This is exposed in the ABI to allow inlining of performance critical
functions like lilv_instance_run (simple wrappers of functions in lv2.h).
functions like lilv_instance_run() (simple wrappers of functions in lv2.h).
This is for performance reasons, user code should not use this definition
in any way (which is why it is not machine documented).
Truly private implementation details are hidden via `pimpl`.
@ -1537,14 +1681,15 @@ lilv_instance_connect_port(LilvInstance* instance,
/**
Activate a plugin instance.
This resets all state information in the plugin, except for port data
locations (as set by lilv_instance_connect_port). This MUST be called
before calling lilv_instance_run.
locations (as set by lilv_instance_connect_port()). This MUST be called
before calling lilv_instance_run().
*/
static inline void
lilv_instance_activate(LilvInstance* instance)
{
if (instance->lv2_descriptor->activate)
if (instance->lv2_descriptor->activate) {
instance->lv2_descriptor->activate(instance->lv2_handle);
}
}
/**
@ -1567,8 +1712,9 @@ lilv_instance_run(LilvInstance* instance,
static inline void
lilv_instance_deactivate(LilvInstance* instance)
{
if (instance->lv2_descriptor->deactivate)
if (instance->lv2_descriptor->deactivate) {
instance->lv2_descriptor->deactivate(instance->lv2_handle);
}
}
/**
@ -1580,10 +1726,11 @@ static inline const void*
lilv_instance_get_extension_data(const LilvInstance* instance,
const char* uri)
{
if (instance->lv2_descriptor->extension_data)
if (instance->lv2_descriptor->extension_data) {
return instance->lv2_descriptor->extension_data(uri);
else
} else {
return NULL;
}
}
/**
@ -1640,8 +1787,8 @@ lilv_ui_get_uri(const LilvUI* ui);
@param ui The Plugin UI
@return a shared value which must not be modified or freed.
Note that in most cases lilv_ui_is_supported should be used which finds the
UI type, avoding the need to use this function (and type specific logic).
Note that in most cases lilv_ui_is_supported() should be used, which avoids
the need to use this function (and type specific logic).
*/
LILV_API const LilvNodes*
lilv_ui_get_classes(const LilvUI* ui);

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2017 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -19,19 +19,28 @@
#include "lilv/lilv.h"
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
# define LILV_DEPRECATED __attribute__((__deprecated__))
#else
# define LILV_DEPRECATED
#endif
namespace Lilv {
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
LILV_DEPRECATED
static inline const char*
uri_to_path(const char* uri) {
return lilv_uri_to_path(uri);
}
#if defined(__clang__)
# pragma clang diagnostic pop
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
# pragma GCC diagnostic pop
#endif
#define LILV_WRAP0(RT, prefix, name) \
inline RT name() { return lilv_ ## prefix ## _ ## name (me); }

View File

@ -1,5 +1,5 @@
/*
Copyright 2008-2014 David Robillard <http://drobilla.net>
Copyright 2008-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -16,6 +16,15 @@
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "sord/sord.h"
#include "zix/common.h"
#include "zix/tree.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
int
lilv_ptr_cmp(const void* a, const void* b, void* user_data)
{
@ -39,16 +48,17 @@ lilv_collection_new(ZixComparator cmp, ZixDestroyFunc destructor)
}
void
lilv_collection_free(LilvCollection* coll)
lilv_collection_free(LilvCollection* collection)
{
if (coll)
zix_tree_free((ZixTree*)coll);
if (collection) {
zix_tree_free((ZixTree*)collection);
}
}
unsigned
lilv_collection_size(const LilvCollection* coll)
lilv_collection_size(const LilvCollection* collection)
{
return (coll ? zix_tree_size((const ZixTree*)coll) : 0);
return (collection ? zix_tree_size((const ZixTree*)collection) : 0);
}
LilvIter*
@ -97,17 +107,17 @@ lilv_plugin_classes_new(void)
/* URI based accessors (for collections of things with URIs) */
LILV_API const LilvPluginClass*
lilv_plugin_classes_get_by_uri(const LilvPluginClasses* coll,
lilv_plugin_classes_get_by_uri(const LilvPluginClasses* classes,
const LilvNode* uri)
{
return (LilvPluginClass*)lilv_collection_get_by_uri(
(const ZixTree*)coll, uri);
(const ZixTree*)classes, uri);
}
LILV_API const LilvUI*
lilv_uis_get_by_uri(const LilvUIs* coll, const LilvNode* uri)
lilv_uis_get_by_uri(const LilvUIs* uis, const LilvNode* uri)
{
return (LilvUI*)lilv_collection_get_by_uri((const ZixTree*)coll, uri);
return (LilvUI*)lilv_collection_get_by_uri((const ZixTree*)uis, uri);
}
/* Plugins */
@ -119,19 +129,22 @@ lilv_plugins_new(void)
}
LILV_API const LilvPlugin*
lilv_plugins_get_by_uri(const LilvPlugins* list, const LilvNode* uri)
lilv_plugins_get_by_uri(const LilvPlugins* plugins, const LilvNode* uri)
{
return (LilvPlugin*)lilv_collection_get_by_uri((const ZixTree*)list, uri);
return (LilvPlugin*)lilv_collection_get_by_uri(
(const ZixTree*)plugins, uri);
}
/* Nodes */
LILV_API bool
lilv_nodes_contains(const LilvNodes* list, const LilvNode* value)
lilv_nodes_contains(const LilvNodes* nodes, const LilvNode* value)
{
LILV_FOREACH(nodes, i, list)
if (lilv_node_equals(lilv_nodes_get(list, i), value))
LILV_FOREACH(nodes, i, nodes) {
if (lilv_node_equals(lilv_nodes_get(nodes, i), value)) {
return true;
}
}
return false;
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,44 +14,46 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "lv2/core/lv2.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lilv_internal.h"
LILV_API LilvInstance*
lilv_plugin_instantiate(const LilvPlugin* plugin,
double sample_rate,
const LV2_Feature*const* features)
{
lilv_plugin_load_if_necessary(plugin);
LilvInstance* result = NULL;
const LilvNode* const lib_uri = lilv_plugin_get_library_uri(plugin);
const LilvNode* const bundle_uri = lilv_plugin_get_bundle_uri(plugin);
const char* bundle_path = lilv_uri_to_path(
lilv_node_as_uri(lilv_plugin_get_bundle_uri(plugin)));
LilvLib* lib = lilv_lib_open(plugin->world, lib_uri, bundle_path, features);
if (!lib) {
if (plugin->parse_errors) {
return NULL;
}
// Parse bundle URI to use as base URI
const char* bundle_uri_str = lilv_node_as_uri(bundle_uri);
SerdURI base_uri;
if (serd_uri_parse((const uint8_t*)bundle_uri_str, &base_uri)) {
lilv_lib_close(lib);
LilvInstance* result = NULL;
const LilvNode* const lib_uri = lilv_plugin_get_library_uri(plugin);
const LilvNode* const bundle_uri = lilv_plugin_get_bundle_uri(plugin);
if (!lib_uri || !bundle_uri) {
return NULL;
}
char* const bundle_path = lilv_file_uri_parse(
lilv_node_as_uri(bundle_uri), NULL);
LilvLib* lib = lilv_lib_open(plugin->world, lib_uri, bundle_path, features);
if (!lib) {
serd_free(bundle_path);
return NULL;
}
const LV2_Feature** local_features = NULL;
if (features == NULL) {
local_features = (const LV2_Feature**)malloc(sizeof(LV2_Feature));
local_features = (const LV2_Feature**)malloc(sizeof(LV2_Feature*));
local_features[0] = NULL;
}
@ -66,18 +68,7 @@ lilv_plugin_instantiate(const LilvPlugin* plugin,
break; // return NULL
}
// Resolve library plugin URI against base URI
SerdURI abs_uri;
SerdNode abs_uri_node = serd_node_new_uri_from_string(
(const uint8_t*)ld->URI, &base_uri, &abs_uri);
if (!abs_uri_node.buf) {
LILV_ERRORF("Failed to parse plugin URI `%s'\n", ld->URI);
lilv_lib_close(lib);
break;
}
if (!strcmp((const char*)abs_uri_node.buf,
lilv_node_as_uri(lilv_plugin_get_uri(plugin)))) {
if (!strcmp(ld->URI, lilv_node_as_uri(lilv_plugin_get_uri(plugin)))) {
// Create LilvInstance to return
result = (LilvInstance*)malloc(sizeof(LilvInstance));
result->lv2_descriptor = ld;
@ -85,25 +76,25 @@ lilv_plugin_instantiate(const LilvPlugin* plugin,
ld, sample_rate, bundle_path,
(features) ? features : local_features);
result->pimpl = lib;
serd_node_free(&abs_uri_node);
break;
} else {
serd_node_free(&abs_uri_node);
}
}
free(local_features);
serd_free(bundle_path);
if (result) {
// Failed to instantiate
if (result->lv2_handle == NULL) {
// Failed to instantiate
free(result);
lilv_lib_close(lib);
return NULL;
}
// "Connect" all ports to NULL (catches bugs)
for (uint32_t i = 0; i < lilv_plugin_get_num_ports(plugin); ++i)
for (uint32_t i = 0; i < lilv_plugin_get_num_ports(plugin); ++i) {
result->lv2_descriptor->connect_port(result->lv2_handle, i, NULL);
}
}
return result;
@ -112,8 +103,9 @@ lilv_plugin_instantiate(const LilvPlugin* plugin,
LILV_API void
lilv_instance_free(LilvInstance* instance)
{
if (!instance)
if (!instance) {
return;
}
instance->lv2_descriptor->cleanup(instance->lv2_handle);
instance->lv2_descriptor = NULL;
@ -121,4 +113,3 @@ lilv_instance_free(LilvInstance* instance)
instance->pimpl = NULL;
free(instance);
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2012-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -16,6 +16,13 @@
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "lv2/core/lv2.h"
#include "zix/tree.h"
#include <stdint.h>
#include <stdlib.h>
LilvLib*
lilv_lib_open(LilvWorld* world,
const LilvNode* uri,
@ -33,7 +40,8 @@ lilv_lib_open(LilvWorld* world,
}
const char* const lib_uri = lilv_node_as_uri(uri);
const char* const lib_path = lilv_uri_to_path(lib_uri);
char* const lib_path = (char*)serd_file_uri_parse(
(const uint8_t*)lib_uri, NULL);
if (!lib_path) {
return NULL;
}
@ -42,13 +50,13 @@ lilv_lib_open(LilvWorld* world,
void* lib = dlopen(lib_path, RTLD_NOW);
if (!lib) {
LILV_ERRORF("Failed to open library %s (%s)\n", lib_path, dlerror());
serd_free(lib_path);
return NULL;
}
LV2_Descriptor_Function df = (LV2_Descriptor_Function)
lilv_dlfunc(lib, "lv2_descriptor");
#ifdef LILV_NEW_LV2
LV2_Lib_Descriptor_Function ldf = (LV2_Lib_Descriptor_Function)
lilv_dlfunc(lib, "lv2_lib_descriptor");
@ -56,17 +64,19 @@ lilv_lib_open(LilvWorld* world,
if (ldf) {
desc = ldf(bundle_path, features);
if (!desc) {
LILV_ERRORF("Call to `lv2_lib_descriptor' in %s failed\n", lib_path);
LILV_ERRORF("Call to %s:lv2_lib_descriptor failed\n", lib_path);
dlclose(lib);
serd_free(lib_path);
return NULL;
}
} else
#endif
if (!df) {
} else if (!df) {
LILV_ERRORF("No `lv2_descriptor' or `lv2_lib_descriptor' in %s\n",
lib_path);
dlclose(lib);
serd_free(lib_path);
return NULL;
}
serd_free(lib_path);
LilvLib* llib = (LilvLib*)malloc(sizeof(LilvLib));
llib->world = world;
@ -74,9 +84,7 @@ lilv_lib_open(LilvWorld* world,
llib->bundle_path = lilv_strdup(bundle_path);
llib->lib = lib;
llib->lv2_descriptor = df;
#ifdef LILV_NEW_LV2
llib->desc = desc;
#endif
llib->refs = 1;
zix_tree_insert(world->libs, llib, NULL);
@ -88,12 +96,9 @@ lilv_lib_get_plugin(LilvLib* lib, uint32_t index)
{
if (lib->lv2_descriptor) {
return lib->lv2_descriptor(index);
}
#ifdef LILV_NEW_LV2
if (lib->desc) {
} else if (lib->desc) {
return lib->desc->get_plugin(lib->desc->handle, index);
}
#endif
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -21,38 +21,46 @@
extern "C" {
#endif
#include "lilv_config.h"
#include "lilv/lilv.h"
#include "serd/serd.h"
#include "sord/sord.h"
#include "zix/tree.h"
#include <float.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <float.h>
#ifdef _WIN32
# include <windows.h>
# include <direct.h>
# include <stdio.h>
# define dlopen(path, flags) LoadLibrary(path)
# define dlclose(lib) FreeLibrary((HMODULE)lib)
# define unlink(path) _unlink(path)
# define rmdir(path) _rmdir(path)
# ifdef _MSC_VER
# define __func__ __FUNCTION__
# if _MSC_VER < 1800
# define INFINITY DBL_MAX + DBL_MAX
# define NAN INFINITY - INFINITY
# ifndef snprintf
# define snprintf _snprintf
# endif
# endif
static inline char* dlerror(void) { return "Unknown error"; }
#ifndef INFINITY
# define INFINITY DBL_MAX + DBL_MAX
#endif
#ifndef NAN
# define NAN INFINITY - INFINITY
#endif
static inline const char* dlerror(void) { return "Unknown error"; }
#else
# include <dlfcn.h>
# include <unistd.h>
#endif
#include "serd/serd.h"
#include "sord/sord.h"
#include "zix/tree.h"
#include "lilv_config.h"
#include "lilv/lilv.h"
#ifdef LILV_DYN_MANIFEST
# include "lv2/lv2plug.in/ns/ext/dynmanifest/dynmanifest.h"
# include "lv2/dynmanifest/dynmanifest.h"
#endif
/*
@ -104,9 +112,7 @@ typedef struct {
char* bundle_path;
void* lib;
LV2_Descriptor_Function lv2_descriptor;
#ifdef LILV_NEW_LV2
const LV2_Lib_Descriptor* desc;
#endif
uint32_t refs;
} LilvLib;
@ -123,6 +129,7 @@ struct LilvPluginImpl {
LilvPort** ports;
uint32_t num_ports;
bool loaded;
bool parse_errors;
bool replaced;
};
@ -139,8 +146,9 @@ struct LilvInstancePimpl {
};
typedef struct {
bool dyn_manifest;
bool filter_language;
bool dyn_manifest;
bool filter_language;
char* lv2_path;
} LilvOptions;
struct LilvWorldImpl {
@ -152,6 +160,7 @@ struct LilvWorldImpl {
LilvPluginClasses* plugin_classes;
LilvSpec* specs;
LilvPlugins* plugins;
LilvPlugins* zombies;
LilvNodes* loaded_files;
ZixTree* libs;
struct {
@ -168,7 +177,9 @@ struct LilvWorldImpl {
SordNode* lv2_index;
SordNode* lv2_latency;
SordNode* lv2_maximum;
SordNode* lv2_microVersion;
SordNode* lv2_minimum;
SordNode* lv2_minorVersion;
SordNode* lv2_name;
SordNode* lv2_optionalFeature;
SordNode* lv2_port;
@ -177,7 +188,7 @@ struct LilvWorldImpl {
SordNode* lv2_requiredFeature;
SordNode* lv2_symbol;
SordNode* lv2_prototype;
SordNode* null_uri;
SordNode* owl_Ontology;
SordNode* pset_value;
SordNode* rdf_a;
SordNode* rdf_value;
@ -190,6 +201,7 @@ struct LilvWorldImpl {
SordNode* xsd_decimal;
SordNode* xsd_double;
SordNode* xsd_integer;
SordNode* null_uri;
} uris;
LilvOptions opt;
};
@ -228,6 +240,11 @@ struct LilvUIImpl {
LilvNodes* classes;
};
typedef struct LilvVersion {
int minor;
int micro;
} LilvVersion;
/*
*
* Functions
@ -243,9 +260,10 @@ void lilv_port_free(const LilvPlugin* plugin, LilvPort* port);
LilvPlugin* lilv_plugin_new(LilvWorld* world,
LilvNode* uri,
LilvNode* bundle_uri);
void lilv_plugin_load_if_necessary(const LilvPlugin* p);
void lilv_plugin_clear(LilvPlugin* plugin, LilvNode* bundle_uri);
void lilv_plugin_load_if_necessary(const LilvPlugin* plugin);
void lilv_plugin_free(LilvPlugin* plugin);
LilvNode* lilv_plugin_get_unique(const LilvPlugin* p,
LilvNode* lilv_plugin_get_unique(const LilvPlugin* plugin,
const SordNode* subject,
const SordNode* predicate);
@ -256,7 +274,7 @@ void* lilv_collection_get(const LilvCollection* collection,
const LilvIter* i);
LilvPluginClass* lilv_plugin_class_new(LilvWorld* world,
const SordNode* parent_uri,
const SordNode* parent_node,
const SordNode* uri,
const char* label);
@ -277,6 +295,9 @@ LilvScalePoints* lilv_scale_points_new(void);
LilvPluginClasses* lilv_plugin_classes_new(void);
LilvUIs* lilv_uis_new(void);
LilvNode* lilv_world_get_manifest_uri(LilvWorld* world,
const LilvNode* bundle_uri);
const uint8_t* lilv_world_blank_node_prefix(LilvWorld* world);
SerdStatus lilv_world_load_file(LilvWorld* world,
@ -295,7 +316,7 @@ LilvUI* lilv_ui_new(LilvWorld* world,
void lilv_ui_free(LilvUI* ui);
LilvNode* lilv_node_new(LilvWorld* world, LilvNodeType type, const char* val);
LilvNode* lilv_node_new(LilvWorld* world, LilvNodeType type, const char* str);
LilvNode* lilv_node_new_from_node(LilvWorld* world, const SordNode* node);
int lilv_header_compare_by_uri(const void* a, const void* b, void* user_data);
@ -304,6 +325,19 @@ int lilv_lib_compare(const void* a, const void* b, void* user_data);
int lilv_ptr_cmp(const void* a, const void* b, void* user_data);
int lilv_resource_node_cmp(const void* a, const void* b, void* user_data);
static inline int
lilv_version_cmp(const LilvVersion* a, const LilvVersion* b)
{
if (a->minor == b->minor && a->micro == b->micro) {
return 0;
} else if ((a->minor < b->minor)
|| (a->minor == b->minor && a->micro < b->micro)) {
return -1;
} else {
return 1;
}
}
struct LilvHeader*
lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri);
@ -328,10 +362,18 @@ lilv_world_find_nodes_internal(LilvWorld* world,
const SordNode* predicate,
const SordNode* object);
SordModel*
lilv_world_filter_model(LilvWorld* world,
SordModel* model,
const SordNode* subject,
const SordNode* predicate,
const SordNode* object,
const SordNode* graph);
#define FOREACH_MATCH(iter) \
for (; !sord_iter_end(iter); sord_iter_next(iter))
LilvNodes* lilv_nodes_from_stream_objects(LilvWorld* w,
LilvNodes* lilv_nodes_from_stream_objects(LilvWorld* world,
SordIter* stream,
SordQuadIndex field);
@ -341,7 +383,7 @@ char* lilv_get_lang(void);
char* lilv_expand(const char* path);
char* lilv_dirname(const char* path);
int lilv_copy_file(const char* src, const char* dst);
bool lilv_path_exists(const char* path, void* ignored);
bool lilv_path_exists(const char* path, const void* ignored);
char* lilv_path_absolute(const char* path);
bool lilv_path_is_absolute(const char* path);
char* lilv_get_latest_copy(const char* path, const char* copy_path);
@ -350,13 +392,14 @@ bool lilv_path_is_child(const char* path, const char* dir);
int lilv_flock(FILE* file, bool lock);
char* lilv_realpath(const char* path);
int lilv_symlink(const char* oldpath, const char* newpath);
int lilv_mkdir_p(const char* path);
int lilv_mkdir_p(const char* dir_path);
char* lilv_path_join(const char* a, const char* b);
bool lilv_file_equals(const char* a_path, const char* b_path);
char*
lilv_find_free_path(const char* in_path,
bool (*exists)(const char*, void*), void* user_data);
bool (*exists)(const char*, const void*),
const void* user_data);
void
lilv_dir_for_each(const char* path,
@ -390,6 +433,10 @@ static const LV2_Feature* const dman_features = { NULL };
__func__)
#define LILV_WARNF(fmt, ...) fprintf(stderr, "%s(): warning: " fmt, \
__func__, __VA_ARGS__)
#define LILV_NOTE(str) fprintf(stderr, "%s(): note: " str, \
__func__)
#define LILV_NOTEF(fmt, ...) fprintf(stderr, "%s(): note: " fmt, \
__func__, __VA_ARGS__)
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,17 +14,23 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "serd/serd.h"
#include "sord/sord.h"
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lilv_internal.h"
static void
lilv_node_set_numerics_from_string(LilvNode* val, size_t len)
lilv_node_set_numerics_from_string(LilvNode* val)
{
const char* str = (const char*)sord_node_get_string(val->node);
char* endptr;
switch (val->type) {
case LILV_VALUE_URI:
@ -33,10 +39,10 @@ lilv_node_set_numerics_from_string(LilvNode* val, size_t len)
case LILV_VALUE_BLOB:
break;
case LILV_VALUE_INT:
val->val.int_val = strtol(str, &endptr, 10);
val->val.int_val = strtol(str, NULL, 10);
break;
case LILV_VALUE_FLOAT:
val->val.float_val = serd_strtod(str, &endptr);
val->val.float_val = serd_strtod(str, NULL);
break;
case LILV_VALUE_BOOL:
val->val.bool_val = !strcmp(str, "true");
@ -104,44 +110,42 @@ lilv_node_new_from_node(LilvWorld* world, const SordNode* node)
LilvNode* result = NULL;
SordNode* datatype_uri = NULL;
LilvNodeType type = LILV_VALUE_STRING;
size_t len = 0;
switch (sord_node_get_type(node)) {
case SORD_URI:
result = (LilvNode*)malloc(sizeof(LilvNode));
result->world = (LilvWorld*)world;
result->world = world;
result->type = LILV_VALUE_URI;
result->node = sord_node_copy(node);
break;
case SORD_BLANK:
result = (LilvNode*)malloc(sizeof(LilvNode));
result->world = (LilvWorld*)world;
result->world = world;
result->type = LILV_VALUE_BLANK;
result->node = sord_node_copy(node);
break;
case SORD_LITERAL:
datatype_uri = sord_node_get_datatype(node);
if (datatype_uri) {
if (sord_node_equals(datatype_uri, world->uris.xsd_boolean))
if (sord_node_equals(datatype_uri, world->uris.xsd_boolean)) {
type = LILV_VALUE_BOOL;
else if (sord_node_equals(datatype_uri, world->uris.xsd_decimal)
|| sord_node_equals(datatype_uri, world->uris.xsd_double))
} else if (sord_node_equals(datatype_uri, world->uris.xsd_decimal) ||
sord_node_equals(datatype_uri, world->uris.xsd_double)) {
type = LILV_VALUE_FLOAT;
else if (sord_node_equals(datatype_uri, world->uris.xsd_integer))
} else if (sord_node_equals(datatype_uri, world->uris.xsd_integer)) {
type = LILV_VALUE_INT;
else if (sord_node_equals(datatype_uri,
world->uris.xsd_base64Binary))
} else if (sord_node_equals(datatype_uri,
world->uris.xsd_base64Binary)) {
type = LILV_VALUE_BLOB;
else
} else {
LILV_ERRORF("Unknown datatype `%s'\n",
sord_node_get_string(datatype_uri));
}
}
result = lilv_node_new(
world, type, (const char*)sord_node_get_string_counted(node, &len));
lilv_node_set_numerics_from_string(result, len);
world, type, (const char*)sord_node_get_string(node));
lilv_node_set_numerics_from_string(result);
break;
default:
assert(false);
}
return result;
@ -228,12 +232,13 @@ lilv_node_free(LilvNode* val)
LILV_API bool
lilv_node_equals(const LilvNode* value, const LilvNode* other)
{
if (value == NULL && other == NULL)
if (value == NULL && other == NULL) {
return true;
else if (value == NULL || other == NULL)
} else if (value == NULL || other == NULL) {
return false;
else if (value->type != other->type)
} else if (value->type != other->type) {
return false;
}
switch (value->type) {
case LILV_VALUE_URI:
@ -278,11 +283,13 @@ lilv_node_get_turtle_token(const LilvNode* value)
break;
case LILV_VALUE_INT:
node = serd_node_new_integer(value->val.int_val);
result = (char*)node.buf;
result = lilv_strdup((char*)node.buf);
serd_node_free(&node);
break;
case LILV_VALUE_FLOAT:
node = serd_node_new_decimal(value->val.float_val, 8);
result = (char*)node.buf;
result = lilv_strdup((char*)node.buf);
serd_node_free(&node);
break;
}
@ -320,13 +327,15 @@ lilv_node_as_blank(const LilvNode* value)
LILV_API bool
lilv_node_is_literal(const LilvNode* value)
{
if (!value)
if (!value) {
return false;
}
switch (value->type) {
case LILV_VALUE_STRING:
case LILV_VALUE_INT:
case LILV_VALUE_FLOAT:
case LILV_VALUE_BLOB:
return true;
default:
return false;
@ -366,12 +375,12 @@ lilv_node_is_float(const LilvNode* value)
LILV_API float
lilv_node_as_float(const LilvNode* value)
{
assert(lilv_node_is_float(value) || lilv_node_is_int(value));
if (lilv_node_is_float(value)) {
return value->val.float_val;
} else { // lilv_node_is_int(value)
} else if (lilv_node_is_int(value)) {
return (float)value->val.int_val;
}
return NAN;
}
LILV_API bool
@ -385,3 +394,12 @@ lilv_node_as_bool(const LilvNode* value)
{
return lilv_node_is_bool(value) ? value->val.bool_val : false;
}
LILV_API char*
lilv_node_get_path(const LilvNode* value, char** hostname)
{
if (lilv_node_is_uri(value)) {
return lilv_file_uri_parse(lilv_node_as_uri(value), hostname);
}
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,21 +14,21 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "sord/sord.h"
#include "zix/tree.h"
#include <stdbool.h>
#include <stdlib.h>
LilvPluginClass*
lilv_plugin_class_new(LilvWorld* world,
const SordNode* parent_node,
const SordNode* uri,
const char* label)
{
if (parent_node && sord_node_get_type(parent_node) != SORD_URI) {
return NULL; // Not an LV2 plugin superclass (FIXME: discover properly)
}
LilvPluginClass* pc = (LilvPluginClass*)malloc(sizeof(LilvPluginClass));
pc->world = world;
pc->uri = lilv_node_new_from_node(world, uri);
@ -42,7 +42,10 @@ lilv_plugin_class_new(LilvWorld* world,
void
lilv_plugin_class_free(LilvPluginClass* plugin_class)
{
assert(plugin_class->uri);
if (!plugin_class) {
return;
}
lilv_node_free(plugin_class->uri);
lilv_node_free(plugin_class->parent_uri);
lilv_node_free(plugin_class->label);
@ -80,8 +83,9 @@ lilv_plugin_class_get_children(const LilvPluginClass* plugin_class)
const LilvPluginClass* c = (LilvPluginClass*)zix_tree_get(i);
const LilvNode* parent = lilv_plugin_class_get_parent_uri(c);
if (parent && lilv_node_equals(lilv_plugin_class_get_uri(plugin_class),
parent))
parent)) {
zix_tree_insert((ZixTree*)result, (LilvPluginClass*)c, NULL);
}
}
return result;

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,16 +14,21 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lilv_internal.h"
#include "lv2/atom/atom.h"
#include "lv2/core/lv2.h"
#include "lv2/event/event.h"
#include "lilv/lilv.h"
#include "sord/sord.h"
#include "zix/tree.h"
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/event/event.h"
#include "lilv_internal.h"
LilvPort*
lilv_port_new(LilvWorld* world,
@ -55,38 +60,40 @@ lilv_port_is_a(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* port_class)
{
LILV_FOREACH(nodes, i, port->classes)
if (lilv_node_equals(lilv_nodes_get(port->classes, i), port_class))
LILV_FOREACH(nodes, i, port->classes) {
if (lilv_node_equals(lilv_nodes_get(port->classes, i), port_class)) {
return true;
}
}
return false;
}
LILV_API bool
lilv_port_has_property(const LilvPlugin* p,
lilv_port_has_property(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* property)
{
return lilv_world_ask_internal(p->world,
return lilv_world_ask_internal(plugin->world,
port->node->node,
p->world->uris.lv2_portProperty,
plugin->world->uris.lv2_portProperty,
property->node);
}
LILV_API bool
lilv_port_supports_event(const LilvPlugin* p,
lilv_port_supports_event(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* event)
const LilvNode* event_type)
{
const uint8_t* predicates[] = { (const uint8_t*)LV2_EVENT__supportsEvent,
(const uint8_t*)LV2_ATOM__supports,
NULL };
for (const uint8_t** pred = predicates; *pred; ++pred) {
if (lilv_world_ask_internal(p->world,
if (lilv_world_ask_internal(plugin->world,
port->node->node,
sord_new_uri(p->world->world, *pred),
event->node)) {
sord_new_uri(plugin->world->world, *pred),
event_type->node)) {
return true;
}
}
@ -94,11 +101,11 @@ lilv_port_supports_event(const LilvPlugin* p,
}
static LilvNodes*
lilv_port_get_value_by_node(const LilvPlugin* p,
lilv_port_get_value_by_node(const LilvPlugin* plugin,
const LilvPort* port,
const SordNode* predicate)
{
return lilv_world_find_nodes_internal(p->world,
return lilv_world_find_nodes_internal(plugin->world,
port->node->node,
predicate,
NULL);
@ -112,7 +119,7 @@ lilv_port_get_node(const LilvPlugin* plugin,
}
LILV_API LilvNodes*
lilv_port_get_value(const LilvPlugin* p,
lilv_port_get_value(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* predicate)
{
@ -122,15 +129,15 @@ lilv_port_get_value(const LilvPlugin* p,
return NULL;
}
return lilv_port_get_value_by_node(p, port, predicate->node);
return lilv_port_get_value_by_node(plugin, port, predicate->node);
}
LILV_API LilvNode*
lilv_port_get(const LilvPlugin* p,
lilv_port_get(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* predicate)
{
LilvNodes* values = lilv_port_get_value(p, port, predicate);
LilvNodes* values = lilv_port_get_value(plugin, port, predicate);
LilvNode* value = lilv_node_duplicate(
values ? lilv_nodes_get_first(values) : NULL);
@ -140,50 +147,52 @@ lilv_port_get(const LilvPlugin* p,
}
LILV_API uint32_t
lilv_port_get_index(const LilvPlugin* p,
lilv_port_get_index(const LilvPlugin* plugin,
const LilvPort* port)
{
return port->index;
}
LILV_API const LilvNode*
lilv_port_get_symbol(const LilvPlugin* p,
lilv_port_get_symbol(const LilvPlugin* plugin,
const LilvPort* port)
{
return port->symbol;
}
LILV_API LilvNode*
lilv_port_get_name(const LilvPlugin* p,
lilv_port_get_name(const LilvPlugin* plugin,
const LilvPort* port)
{
LilvNodes* results = lilv_port_get_value_by_node(
p, port, p->world->uris.lv2_name);
plugin, port, plugin->world->uris.lv2_name);
LilvNode* ret = NULL;
if (results) {
LilvNode* val = lilv_nodes_get_first(results);
if (lilv_node_is_string(val))
if (lilv_node_is_string(val)) {
ret = lilv_node_duplicate(val);
}
lilv_nodes_free(results);
}
if (!ret)
if (!ret) {
LILV_WARNF("Plugin <%s> port has no (mandatory) doap:name\n",
lilv_node_as_string(lilv_plugin_get_uri(p)));
lilv_node_as_string(lilv_plugin_get_uri(plugin)));
}
return ret;
}
LILV_API const LilvNodes*
lilv_port_get_classes(const LilvPlugin* p,
lilv_port_get_classes(const LilvPlugin* plugin,
const LilvPort* port)
{
return port->classes;
}
LILV_API void
lilv_port_get_range(const LilvPlugin* p,
lilv_port_get_range(const LilvPlugin* plugin,
const LilvPort* port,
LilvNode** def,
LilvNode** min,
@ -191,7 +200,7 @@ lilv_port_get_range(const LilvPlugin* p,
{
if (def) {
LilvNodes* defaults = lilv_port_get_value_by_node(
p, port, p->world->uris.lv2_default);
plugin, port, plugin->world->uris.lv2_default);
*def = defaults
? lilv_node_duplicate(lilv_nodes_get_first(defaults))
: NULL;
@ -199,7 +208,7 @@ lilv_port_get_range(const LilvPlugin* p,
}
if (min) {
LilvNodes* minimums = lilv_port_get_value_by_node(
p, port, p->world->uris.lv2_minimum);
plugin, port, plugin->world->uris.lv2_minimum);
*min = minimums
? lilv_node_duplicate(lilv_nodes_get_first(minimums))
: NULL;
@ -207,7 +216,7 @@ lilv_port_get_range(const LilvPlugin* p,
}
if (max) {
LilvNodes* maximums = lilv_port_get_value_by_node(
p, port, p->world->uris.lv2_maximum);
plugin, port, plugin->world->uris.lv2_maximum);
*max = maximums
? lilv_node_duplicate(lilv_nodes_get_first(maximums))
: NULL;
@ -216,29 +225,30 @@ lilv_port_get_range(const LilvPlugin* p,
}
LILV_API LilvScalePoints*
lilv_port_get_scale_points(const LilvPlugin* p,
lilv_port_get_scale_points(const LilvPlugin* plugin,
const LilvPort* port)
{
SordIter* points = lilv_world_query_internal(
p->world,
plugin->world,
port->node->node,
sord_new_uri(p->world->world, (const uint8_t*)LV2_CORE__scalePoint),
sord_new_uri(plugin->world->world, (const uint8_t*)LV2_CORE__scalePoint),
NULL);
LilvScalePoints* ret = NULL;
if (!sord_iter_end(points))
if (!sord_iter_end(points)) {
ret = lilv_scale_points_new();
}
FOREACH_MATCH(points) {
const SordNode* point = sord_iter_get_node(points, SORD_OBJECT);
LilvNode* value = lilv_plugin_get_unique(p,
LilvNode* value = lilv_plugin_get_unique(plugin,
point,
p->world->uris.rdf_value);
plugin->world->uris.rdf_value);
LilvNode* label = lilv_plugin_get_unique(p,
LilvNode* label = lilv_plugin_get_unique(plugin,
point,
p->world->uris.rdfs_label);
plugin->world->uris.rdfs_label);
if (value && label) {
zix_tree_insert(
@ -252,12 +262,12 @@ lilv_port_get_scale_points(const LilvPlugin* p,
}
LILV_API LilvNodes*
lilv_port_get_properties(const LilvPlugin* p,
lilv_port_get_properties(const LilvPlugin* plugin,
const LilvPort* port)
{
LilvNode* pred = lilv_node_new_from_node(
p->world, p->world->uris.lv2_portProperty);
LilvNodes* ret = lilv_port_get_value(p, port, pred);
plugin->world, plugin->world->uris.lv2_portProperty);
LilvNodes* ret = lilv_port_get_value(plugin, port, pred);
lilv_node_free(pred);
return ret;
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,13 +14,15 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <limits.h>
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "sord/sord.h"
#include "zix/tree.h"
#include <stdlib.h>
#include <string.h>
#include "lilv_internal.h"
typedef enum {
LILV_LANG_MATCH_NONE, ///< Language does not match at all
LILV_LANG_MATCH_PARTIAL, ///< Partial (language, but not country) match

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -16,6 +16,10 @@
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include <stdlib.h>
/** Ownership of value and label is taken */
LilvScalePoint*
lilv_scale_point_new(LilvNode* value, LilvNode* label)
@ -37,13 +41,13 @@ lilv_scale_point_free(LilvScalePoint* point)
}
LILV_API const LilvNode*
lilv_scale_point_get_value(const LilvScalePoint* p)
lilv_scale_point_get_value(const LilvScalePoint* point)
{
return p->value;
return point->value;
}
LILV_API const LilvNode*
lilv_scale_point_get_label(const LilvScalePoint* p)
lilv_scale_point_get_label(const LilvScalePoint* point)
{
return p->label;
return point->label;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,12 +14,16 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "zix/tree.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "lilv_internal.h"
LilvUI*
lilv_ui_new(LilvWorld* world,
LilvNode* uri,
@ -93,9 +97,9 @@ lilv_ui_get_classes(const LilvUI* ui)
}
LILV_API bool
lilv_ui_is_a(const LilvUI* ui, const LilvNode* ui_class_uri)
lilv_ui_is_a(const LilvUI* ui, const LilvNode* class_uri)
{
return lilv_nodes_contains(ui->classes, ui_class_uri);
return lilv_nodes_contains(ui->classes, class_uri);
}
LILV_API const LilvNode*

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,45 +14,76 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define _POSIX_C_SOURCE 1 /* for fileno */
#define _BSD_SOURCE 1 /* for realpath, symlink */
#define _POSIX_C_SOURCE 200809L /* for fileno */
#define _BSD_SOURCE 1 /* for realpath, symlink */
#define _DEFAULT_SOURCE 1 /* for realpath, symlink */
#ifdef __APPLE__
# define _DARWIN_C_SOURCE 1 /* for flock */
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "lilv_config.h"
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "serd/serd.h"
#ifdef _WIN32
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0600 /* for CreateSymbolicLink */
#endif
# include <windows.h>
# include <direct.h>
# include <io.h>
# define F_OK 0
# define mkdir(path, flags) _mkdir(path)
# if (defined(_MSC_VER) && _MSC_VER <= 1400) || defined(__MINGW64__) || defined(__MINGW32__)
/** Implement 'CreateSymbolicLink()' for MSVC 8 or earlier */
#ifdef __cplusplus
extern "C"
#endif
static BOOLEAN WINAPI
CreateSymbolicLink(LPCTSTR linkpath, LPCTSTR targetpath, DWORD flags)
{
typedef BOOLEAN (WINAPI* PFUNC)(LPCTSTR, LPCTSTR, DWORD);
PFUNC pfn = (PFUNC)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
"CreateSymbolicLinkA");
return pfn ? pfn(linkpath, targetpath, flags) : 0;
}
# endif
#else
# include <dirent.h>
# include <unistd.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include "lilv_internal.h"
#if defined(HAVE_FLOCK) && defined(HAVE_FILENO)
# include <sys/file.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# define PAGE_SIZE 4096
#endif
void
lilv_free(void* ptr)
{
free(ptr);
}
char*
lilv_strjoin(const char* first, ...)
{
@ -65,16 +96,18 @@ lilv_strjoin(const char* first, ...)
va_start(args, first);
while (1) {
const char* const s = va_arg(args, const char *);
if (s == NULL)
if (s == NULL) {
break;
}
const size_t this_len = strlen(s);
if (!(result = (char*)realloc(result, len + this_len + 1))) {
const size_t this_len = strlen(s);
char* new_result = (char*)realloc(result, len + this_len + 1);
if (!new_result) {
free(result);
LILV_ERROR("realloc() failed\n");
return NULL;
}
result = new_result;
memcpy(result + len, s, this_len);
len += this_len;
}
@ -104,6 +137,12 @@ lilv_uri_to_path(const char* uri)
return (const char*)serd_uri_to_path((const uint8_t*)uri);
}
char*
lilv_file_uri_parse(const char* uri, char** hostname)
{
return (char*)serd_file_uri_parse((const uint8_t*)uri, (uint8_t**)hostname);
}
/** Return the current LANG converted to Turtle (i.e. RFC3066) style.
* For example, if LANG is set to "en_CA.utf-8", this returns "en-ca".
*/
@ -141,6 +180,8 @@ lilv_get_lang(void)
return lang;
}
#ifndef _WIN32
/** Append suffix to dst, update dst_len, and return the realloc'd result. */
static char*
strappend(char* dst, size_t* dst_len, const char* suffix, size_t suffix_len)
@ -165,6 +206,8 @@ append_var(char* dst, size_t* dst_len, const char* var)
}
}
#endif
/** Expand variables (e.g. POSIX ~ or $FOO, Windows %FOO%) in `path`. */
char*
lilv_expand(const char* path)
@ -239,14 +282,20 @@ lilv_dirname(const char* path)
}
bool
lilv_path_exists(const char* path, void* ignored)
lilv_path_exists(const char* path, const void* ignored)
{
#ifdef HAVE_LSTAT
struct stat st;
return !lstat(path, &st);
#else
return !access(path, F_OK);
#endif
}
char*
lilv_find_free_path(const char* in_path,
bool (*exists)(const char*, void*), void* user_data)
bool (*exists)(const char*, const void*),
const void* user_data)
{
const size_t in_path_len = strlen(in_path);
char* path = (char*)malloc(in_path_len + 7);
@ -267,36 +316,41 @@ lilv_copy_file(const char* src, const char* dst)
{
FILE* in = fopen(src, "r");
if (!in) {
LILV_ERRORF("error opening %s (%s)\n", src, strerror(errno));
return 1;
return errno;
}
FILE* out = fopen(dst, "w");
if (!out) {
LILV_ERRORF("error opening %s (%s)\n", dst, strerror(errno));
fclose(in);
return 2;
return errno;
}
char* page = (char*)malloc(PAGE_SIZE);
size_t n_read = 0;
int st = 0;
while ((n_read = fread(page, 1, PAGE_SIZE, in)) > 0) {
if (fwrite(page, 1, n_read, out) != n_read) {
LILV_ERRORF("write to %s failed (%s)\n", dst, strerror(errno));
st = errno;
break;
}
}
const int ret = ferror(in) || ferror(out);
if (ferror(in)) {
LILV_ERRORF("read from %s failed (%s)\n", src, strerror(errno));
if (!st && (ferror(in) || ferror(out))) {
st = EBADF;
}
free(page);
fclose(in);
fclose(out);
return ret;
return st;
}
static inline bool
is_windows_path(const char* path)
{
return (isalpha(path[0]) && (path[1] == ':' || path[1] == '|') &&
(path[2] == '/' || path[2] == '\\'));
}
bool
@ -307,7 +361,7 @@ lilv_path_is_absolute(const char* path)
}
#ifdef _WIN32
if (isalpha(path[0]) && path[1] == ':' && lilv_is_dir_sep(path[2])) {
if (is_windows_path(path)) {
return true;
}
#endif
@ -349,25 +403,8 @@ lilv_path_join(const char* a, const char* b)
return path;
}
static void
lilv_size_mtime(const char* path, off_t* size, time_t* time)
{
struct stat buf;
if (stat(path, &buf)) {
LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno));
}
if (size) {
*size = buf.st_size;
}
if (time) {
*time = buf.st_mtime;
}
}
typedef struct {
char* pattern;
off_t orig_size;
time_t time;
char* latest;
} Latest;
@ -375,16 +412,18 @@ typedef struct {
static void
update_latest(const char* path, const char* name, void* data)
{
Latest* latest = (Latest*)data;
char* entry_path = lilv_path_join(path, name);
Latest* latest = (Latest*)data;
char* entry_path = lilv_path_join(path, name);
unsigned num;
if (sscanf(entry_path, latest->pattern, &num) == 1) {
off_t entry_size = 0;
time_t entry_time = 0;
lilv_size_mtime(entry_path, &entry_size, &entry_time);
if (entry_size == latest->orig_size && entry_time >= latest->time) {
free(latest->latest);
latest->latest = entry_path;
struct stat st;
if (!stat(entry_path, &st)) {
if (st.st_mtime >= latest->time) {
free(latest->latest);
latest->latest = entry_path;
}
} else {
LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno));
}
}
if (entry_path != latest->latest) {
@ -397,8 +436,14 @@ char*
lilv_get_latest_copy(const char* path, const char* copy_path)
{
char* copy_dir = lilv_dirname(copy_path);
Latest latest = { lilv_strjoin(copy_path, "%u", NULL), 0, 0, NULL };
lilv_size_mtime(path, &latest.orig_size, &latest.time);
Latest latest = { lilv_strjoin(copy_path, ".%u", NULL), 0, NULL };
struct stat st;
if (!stat(path, &st)) {
latest.time = st.st_mtime;
} else {
LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno));
}
lilv_dir_for_each(copy_dir, &latest, update_latest);
@ -410,7 +455,11 @@ lilv_get_latest_copy(const char* path, const char* copy_path)
char*
lilv_realpath(const char* path)
{
#ifdef _WIN32
if (!path) {
return NULL;
}
#if defined(_WIN32)
char* out = (char*)malloc(MAX_PATH);
GetFullPathName(path, MAX_PATH, out, NULL);
return out;
@ -427,6 +476,9 @@ lilv_symlink(const char* oldpath, const char* newpath)
if (strcmp(oldpath, newpath)) {
#ifdef _WIN32
ret = !CreateSymbolicLink(newpath, oldpath, 0);
if (ret) {
ret = !CreateHardLink(newpath, oldpath, 0);
}
#else
ret = symlink(oldpath, newpath);
#endif
@ -517,10 +569,8 @@ lilv_dir_for_each(const char* path,
#else
DIR* dir = opendir(path);
if (dir) {
struct dirent entry;
struct dirent* result;
while (!readdir_r(dir, &entry, &result) && result) {
f(path, entry.d_name, data);
for (struct dirent* entry; (entry = readdir(dir));) {
f(path, entry->d_name, data);
}
closedir(dir);
}
@ -532,16 +582,23 @@ lilv_mkdir_p(const char* dir_path)
{
char* path = lilv_strdup(dir_path);
const size_t path_len = strlen(path);
for (size_t i = 1; i <= path_len; ++i) {
if (path[i] == LILV_DIR_SEP[0] || path[i] == '\0') {
size_t i = 1;
#ifdef _WIN32
if (is_windows_path(dir_path)) {
i = 3;
}
#endif
for (; i <= path_len; ++i) {
const char c = path[i];
if (c == LILV_DIR_SEP[0] || c == '/' || c == '\0') {
path[i] = '\0';
if (mkdir(path, 0755) && errno != EEXIST) {
LILV_ERRORF("Failed to create %s (%s)\n",
path, strerror(errno));
free(path);
return 1;
return errno;
}
path[i] = LILV_DIR_SEP[0];
path[i] = c;
}
}
@ -572,19 +629,16 @@ lilv_file_equals(const char* a_path, const char* b_path)
FILE* b_file = NULL;
char* const a_real = lilv_realpath(a_path);
char* const b_real = lilv_realpath(b_path);
if (!a_real || !b_real) {
match = false; // Missing file matches nothing
} else if (!strcmp(a_real, b_real)) {
if (!strcmp(a_real, b_real)) {
match = true; // Real paths match
} else if (lilv_file_size(a_path) != lilv_file_size(b_path)) {
match = false; // Sizes differ
} else if (!(a_file = fopen(a_real, "rb"))) {
match = false; // Missing file matches nothing
} else if (!(b_file = fopen(b_real, "rb"))) {
} else if (!(a_file = fopen(a_real, "rb")) ||
!(b_file = fopen(b_real, "rb"))) {
match = false; // Missing file matches nothing
} else {
match = true;
// TODO: Improve performance by reading chunks
match = true;
while (!feof(a_file) && !feof(b_file)) {
if (fgetc(a_file) != fgetc(b_file)) {
match = false;

View File

@ -1,5 +1,5 @@
/*
Copyright 2007-2014 David Robillard <http://drobilla.net>
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,42 +14,62 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lilv_config.h"
#include "lilv_internal.h"
#include "lilv/lilv.h"
#include "serd/serd.h"
#include "sord/sord.h"
#include "zix/common.h"
#include "zix/tree.h"
#include "lv2/core/lv2.h"
#include "lv2/presets/presets.h"
#ifdef LILV_DYN_MANIFEST
# include "lv2/dynmanifest/dynmanifest.h"
# include <dlfcn.h>
#endif
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
#include "lilv_internal.h"
static int
lilv_world_drop_graph(LilvWorld* world, const SordNode* graph);
LILV_API LilvWorld*
lilv_world_new(void)
{
LilvWorld* world = (LilvWorld*)malloc(sizeof(LilvWorld));
LilvWorld* world = (LilvWorld*)calloc(1, sizeof(LilvWorld));
world->world = sord_world_new();
if (!world->world)
if (!world->world) {
goto fail;
}
world->model = sord_new(world->world, SORD_SPO|SORD_OPS, true);
if (!world->model)
if (!world->model) {
goto fail;
}
world->specs = NULL;
world->plugin_classes = lilv_plugin_classes_new();
world->plugins = lilv_plugins_new();
world->zombies = lilv_plugins_new();
world->loaded_files = zix_tree_new(
false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free);
#ifdef LILV_NEW_LV2
world->libs = zix_tree_new(false, lilv_lib_compare, NULL, NULL);
#endif
#define NS_DCTERMS "http://purl.org/dc/terms/"
#define NS_DYNMAN "http://lv2plug.in/ns/ext/dynmanifest#"
#define NS_OWL "http://www.w3.org/2002/07/owl#"
#define NEW_URI(uri) sord_new_uri(world->world, (const uint8_t*)uri)
#define NEW_URI(uri) sord_new_uri(world->world, (const uint8_t*)(uri))
world->uris.dc_replaces = NEW_URI(NS_DCTERMS "replaces");
world->uris.dman_DynManifest = NEW_URI(NS_DYNMAN "DynManifest");
@ -64,7 +84,9 @@ lilv_world_new(void)
world->uris.lv2_index = NEW_URI(LV2_CORE__index);
world->uris.lv2_latency = NEW_URI(LV2_CORE__latency);
world->uris.lv2_maximum = NEW_URI(LV2_CORE__maximum);
world->uris.lv2_microVersion = NEW_URI(LV2_CORE__microVersion);
world->uris.lv2_minimum = NEW_URI(LV2_CORE__minimum);
world->uris.lv2_minorVersion = NEW_URI(LV2_CORE__minorVersion);
world->uris.lv2_name = NEW_URI(LV2_CORE__name);
world->uris.lv2_optionalFeature = NEW_URI(LV2_CORE__optionalFeature);
world->uris.lv2_port = NEW_URI(LV2_CORE__port);
@ -73,6 +95,7 @@ lilv_world_new(void)
world->uris.lv2_requiredFeature = NEW_URI(LV2_CORE__requiredFeature);
world->uris.lv2_symbol = NEW_URI(LV2_CORE__symbol);
world->uris.lv2_prototype = NEW_URI(LV2_CORE__prototype);
world->uris.owl_Ontology = NEW_URI(NS_OWL "Ontology");
world->uris.pset_value = NEW_URI(LV2_PRESETS__value);
world->uris.rdf_a = NEW_URI(LILV_NS_RDF "type");
world->uris.rdf_value = NEW_URI(LILV_NS_RDF "value");
@ -133,13 +156,18 @@ lilv_world_free(LilvWorld* world)
zix_tree_free((ZixTree*)world->plugins);
world->plugins = NULL;
LILV_FOREACH(plugins, i, world->zombies) {
const LilvPlugin* p = lilv_plugins_get(world->zombies, i);
lilv_plugin_free((LilvPlugin*)p);
}
zix_tree_free((ZixTree*)world->zombies);
world->zombies = NULL;
zix_tree_free((ZixTree*)world->loaded_files);
world->loaded_files = NULL;
#ifdef LILV_NEW_LV2
zix_tree_free((ZixTree*)world->libs);
zix_tree_free(world->libs);
world->libs = NULL;
#endif
zix_tree_free((ZixTree*)world->plugin_classes);
world->plugin_classes = NULL;
@ -150,26 +178,32 @@ lilv_world_free(LilvWorld* world)
sord_world_free(world->world);
world->world = NULL;
free(world->opt.lv2_path);
free(world);
}
LILV_API void
lilv_world_set_option(LilvWorld* world,
const char* option,
const char* uri,
const LilvNode* value)
{
if (!strcmp(option, LILV_OPTION_DYN_MANIFEST)) {
if (!strcmp(uri, LILV_OPTION_DYN_MANIFEST)) {
if (lilv_node_is_bool(value)) {
world->opt.dyn_manifest = lilv_node_as_bool(value);
return;
}
} else if (!strcmp(option, LILV_OPTION_FILTER_LANG)) {
} else if (!strcmp(uri, LILV_OPTION_FILTER_LANG)) {
if (lilv_node_is_bool(value)) {
world->opt.filter_language = lilv_node_as_bool(value);
return;
}
} else if (!strcmp(uri, LILV_OPTION_LV2_PATH)) {
if (lilv_node_is_string(value)) {
world->opt.lv2_path = lilv_strdup(lilv_node_as_string(value));
return;
}
}
LILV_WARNF("Unrecognized or invalid option `%s'\n", option);
LILV_WARNF("Unrecognized or invalid option `%s'\n", uri);
}
LILV_API LilvNodes*
@ -182,6 +216,9 @@ lilv_world_find_nodes(LilvWorld* world,
LILV_ERRORF("Subject `%s' is not a resource\n",
sord_node_get_string(subject->node));
return NULL;
} else if (!predicate) {
LILV_ERROR("Missing required predicate\n");
return NULL;
} else if (!lilv_node_is_uri(predicate)) {
LILV_ERRORF("Predicate `%s' is not a URI\n",
sord_node_get_string(predicate->node));
@ -190,7 +227,7 @@ lilv_world_find_nodes(LilvWorld* world,
LILV_ERROR("Both subject and object are NULL\n");
return NULL;
}
return lilv_world_find_nodes_internal(world,
subject ? subject->node : NULL,
predicate->node,
@ -237,8 +274,30 @@ lilv_world_ask(LilvWorld* world,
const LilvNode* predicate,
const LilvNode* object)
{
return sord_ask(
world->model, subject->node, predicate->node, object->node, NULL);
return sord_ask(world->model,
subject ? subject->node : NULL,
predicate ? predicate->node : NULL,
object ? object->node : NULL,
NULL);
}
SordModel*
lilv_world_filter_model(LilvWorld* world,
SordModel* model,
const SordNode* subject,
const SordNode* predicate,
const SordNode* object,
const SordNode* graph)
{
SordModel* results = sord_new(world->world, SORD_SPO, false);
SordIter* i = sord_search(model, subject, predicate, object, graph);
for (; !sord_iter_end(i); sord_iter_next(i)) {
SordQuad quad;
sord_iter_get(i, quad);
sord_add(results, quad);
}
sord_iter_free(i);
return results;
}
LilvNodes*
@ -258,12 +317,8 @@ lilv_new_uri_relative_to_base(const uint8_t* uri_str,
const uint8_t* base_uri_str)
{
SerdURI base_uri;
if (serd_uri_parse(base_uri_str, &base_uri)) {
return SERD_NODE_NULL;
}
SerdURI ignored;
return serd_node_new_uri_from_string(uri_str, &base_uri, &ignored);
serd_uri_parse(base_uri_str, &base_uri);
return serd_node_new_uri_from_string(uri_str, &base_uri, NULL);
}
const uint8_t*
@ -302,23 +357,24 @@ lilv_lib_compare(const void* a, const void* b, void* user_data)
}
/** Get an element of a collection of any object with an LilvHeader by URI. */
struct LilvHeader*
lilv_collection_get_by_uri(const ZixTree* const_seq,
const LilvNode* uri)
static ZixTreeIter*
lilv_collection_find_by_uri(const ZixTree* seq, const LilvNode* uri)
{
if (!lilv_node_is_uri(uri)) {
return NULL;
ZixTreeIter* i = NULL;
if (lilv_node_is_uri(uri)) {
struct LilvHeader key = { NULL, (LilvNode*)uri };
zix_tree_find(seq, &key, &i);
}
return i;
}
ZixTree* seq = (ZixTree*)const_seq;
struct LilvHeader key = { NULL, (LilvNode*)uri };
ZixTreeIter* i = NULL;
ZixStatus st = zix_tree_find(seq, &key, &i);
if (!st) {
return (struct LilvHeader*)zix_tree_get(i);
}
/** Get an element of a collection of any object with an LilvHeader by URI. */
struct LilvHeader*
lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri)
{
ZixTreeIter* const i = lilv_collection_find_by_uri(seq, uri);
return NULL;
return i ? (struct LilvHeader*)zix_tree_get(i) : NULL;
}
static void
@ -351,33 +407,55 @@ lilv_world_add_spec(LilvWorld* world,
}
static void
lilv_world_add_plugin(LilvWorld* world,
const SordNode* plugin_node,
const LilvNode* manifest_uri,
void* dynmanifest,
const SordNode* bundle_node)
lilv_world_add_plugin(LilvWorld* world,
const SordNode* plugin_node,
const LilvNode* manifest_uri,
void* dynmanifest,
const SordNode* bundle)
{
LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node);
LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node);
ZixTreeIter* z = NULL;
LilvPlugin* plugin = (LilvPlugin*)lilv_plugins_get_by_uri(
world->plugins, plugin_uri);
const LilvPlugin* last = lilv_plugins_get_by_uri(world->plugins,
plugin_uri);
if (last) {
LILV_ERRORF("Duplicate plugin <%s>\n", lilv_node_as_uri(plugin_uri));
LILV_ERRORF("... found in %s\n", lilv_node_as_string(
lilv_plugin_get_bundle_uri(last)));
LILV_ERRORF("... and %s\n", sord_node_get_string(bundle_node));
if (plugin) {
// Existing plugin, if this is different bundle, ignore it
// (use the first plugin found in LV2_PATH)
const LilvNode* last_bundle = lilv_plugin_get_bundle_uri(plugin);
const char* plugin_uri_str = lilv_node_as_uri(plugin_uri);
if (sord_node_equals(bundle, last_bundle->node)) {
LILV_WARNF("Reloading plugin <%s>\n", plugin_uri_str);
plugin->loaded = false;
lilv_node_free(plugin_uri);
} else {
LILV_WARNF("Duplicate plugin <%s>\n", plugin_uri_str);
LILV_WARNF("... found in %s\n", lilv_node_as_string(last_bundle));
LILV_WARNF("... and %s (ignored)\n", sord_node_get_string(bundle));
lilv_node_free(plugin_uri);
return;
}
} else if ((z = lilv_collection_find_by_uri((const ZixTree*)world->zombies,
plugin_uri))) {
// Plugin bundle has been re-loaded, move from zombies to plugins
plugin = (LilvPlugin*)zix_tree_get(z);
zix_tree_remove((ZixTree*)world->zombies, z);
zix_tree_insert((ZixTree*)world->plugins, plugin, NULL);
lilv_node_free(plugin_uri);
return;
lilv_plugin_clear(plugin, lilv_node_new_from_node(world, bundle));
} else {
// Add new plugin to the world
plugin = lilv_plugin_new(
world, plugin_uri, lilv_node_new_from_node(world, bundle));
// Add manifest as plugin data file (as if it were rdfs:seeAlso)
zix_tree_insert((ZixTree*)plugin->data_uris,
lilv_node_duplicate(manifest_uri),
NULL);
// Add plugin to world plugin sequence
zix_tree_insert((ZixTree*)world->plugins, plugin, NULL);
}
// Create LilvPlugin
LilvNode* bundle_uri = lilv_node_new_from_node(world, bundle_node);
LilvPlugin* plugin = lilv_plugin_new(world, plugin_uri, bundle_uri);
// Add manifest as plugin data file (as if it were rdfs:seeAlso)
zix_tree_insert((ZixTree*)plugin->data_uris,
lilv_node_duplicate(manifest_uri),
NULL);
#ifdef LILV_DYN_MANIFEST
// Set dynamic manifest library URI, if applicable
@ -400,9 +478,6 @@ lilv_world_add_plugin(LilvWorld* world,
NULL);
}
sord_iter_free(files);
// Add plugin to world plugin sequence
zix_tree_insert((ZixTree*)world->plugins, plugin, NULL);
}
SerdStatus
@ -430,17 +505,18 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
return;
}
typedef void* LV2_Dyn_Manifest_Handle;
LV2_Dyn_Manifest_Handle handle = NULL;
// ?dman a dynman:DynManifest
SordIter* dmanifests = sord_search(world->model,
NULL,
world->uris.rdf_a,
world->uris.dman_DynManifest,
bundle_node);
FOREACH_MATCH(dmanifests) {
const SordNode* dmanifest = sord_iter_get_node(dmanifests, SORD_SUBJECT);
// ?dman a dynman:DynManifest bundle_node
SordModel* model = lilv_world_filter_model(world,
world->model,
NULL,
world->uris.rdf_a,
world->uris.dman_DynManifest,
bundle_node);
SordIter* iter = sord_begin(model);
for (; !sord_iter_end(iter); sord_iter_next(iter)) {
const SordNode* dmanifest = sord_iter_get_node(iter, SORD_SUBJECT);
// ?dman lv2:binary ?binary
SordIter* binaries = sord_search(world->model,
@ -458,7 +534,7 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
// Get binary path
const SordNode* binary = sord_iter_get_node(binaries, SORD_OBJECT);
const uint8_t* lib_uri = sord_node_get_string(binary);
const char* lib_path = lilv_uri_to_path((const char*)lib_uri);
char* lib_path = lilv_file_uri_parse((const char*)lib_uri, 0);
if (!lib_path) {
LILV_ERROR("No dynamic manifest library path\n");
sord_iter_free(binaries);
@ -466,10 +542,13 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
}
// Open library
dlerror();
void* lib = dlopen(lib_path, RTLD_LAZY);
if (!lib) {
LILV_ERRORF("Failed to open dynmanifest library `%s'\n", lib_path);
LILV_ERRORF("Failed to open dynmanifest library `%s' (%s)\n",
lib_path, dlerror());
sord_iter_free(binaries);
lilv_free(lib_path);
continue;
}
@ -481,6 +560,7 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
LILV_ERRORF("No `lv2_dyn_manifest_open' in `%s'\n", lib_path);
sord_iter_free(binaries);
dlclose(lib);
lilv_free(lib_path);
continue;
}
@ -493,21 +573,25 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
lib_path);
sord_iter_free(binaries);
dlclose(lib);
lilv_free(lib_path);
continue;
}
LilvDynManifest* desc = malloc(sizeof(LilvDynManifest));
LilvDynManifest* desc = (LilvDynManifest*)malloc(sizeof(LilvDynManifest));
desc->bundle = lilv_node_new_from_node(world, bundle_node);
desc->lib = lib;
desc->handle = handle;
desc->refs = 0;
sord_iter_free(binaries);
// Generate data file
FILE* fd = tmpfile();
get_subjects_func(handle, fd);
rewind(fd);
// Parse generated data file
// Parse generated data file into temporary model
// FIXME
const SerdNode* base = sord_node_to_serd_node(dmanifest);
SerdEnv* env = serd_env_new(base);
SerdReader* reader = sord_new_reader(
@ -523,38 +607,101 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
fclose(fd);
// ?plugin a lv2:Plugin
SordIter* plug_results = sord_search(
world->model,
NULL,
world->uris.rdf_a,
world->uris.lv2_Plugin,
dmanifest);
FOREACH_MATCH(plug_results) {
const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT);
SordModel* plugins = lilv_world_filter_model(world,
world->model,
NULL,
world->uris.rdf_a,
world->uris.lv2_Plugin,
dmanifest);
SordIter* p = sord_begin(plugins);
FOREACH_MATCH(p) {
const SordNode* plug = sord_iter_get_node(p, SORD_SUBJECT);
lilv_world_add_plugin(world, plug, manifest, desc, bundle_node);
}
sord_iter_free(plug_results);
sord_iter_free(binaries);
if (desc->refs == 0) {
free(desc);
}
sord_iter_free(p);
sord_free(plugins);
lilv_free(lib_path);
}
sord_iter_free(dmanifests);
sord_iter_free(iter);
sord_free(model);
#endif // LILV_DYN_MANIFEST
}
static
LilvNode*
lilv_world_get_manifest_uri(LilvWorld* world, LilvNode* bundle_uri)
lilv_world_get_manifest_uri(LilvWorld* world, const LilvNode* bundle_uri)
{
SerdNode manifest_uri = lilv_new_uri_relative_to_base(
(const uint8_t*)"manifest.ttl",
(const uint8_t*)sord_node_get_string(bundle_uri->node));
sord_node_get_string(bundle_uri->node));
LilvNode* manifest = lilv_new_uri(world, (const char*)manifest_uri.buf);
serd_node_free(&manifest_uri);
return manifest;
}
static SordModel*
load_plugin_model(LilvWorld* world,
const LilvNode* bundle_uri,
const LilvNode* plugin_uri)
{
// Create model and reader for loading into it
SordNode* bundle_node = bundle_uri->node;
SordModel* model = sord_new(world->world, SORD_SPO|SORD_OPS, false);
SerdEnv* env = serd_env_new(sord_node_to_serd_node(bundle_node));
SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
// Load manifest
LilvNode* manifest_uri = lilv_world_get_manifest_uri(world, bundle_uri);
serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world));
serd_reader_read_file(
reader, (const uint8_t*)lilv_node_as_string(manifest_uri));
// Load any seeAlso files
SordModel* files = lilv_world_filter_model(
world, model, plugin_uri->node, world->uris.rdfs_seeAlso, NULL, NULL);
SordIter* f = sord_begin(files);
FOREACH_MATCH(f) {
const SordNode* file = sord_iter_get_node(f, SORD_OBJECT);
const uint8_t* file_str = sord_node_get_string(file);
if (sord_node_get_type(file) == SORD_URI) {
serd_reader_add_blank_prefix(
reader, lilv_world_blank_node_prefix(world));
serd_reader_read_file(reader, file_str);
}
}
sord_iter_free(f);
sord_free(files);
serd_reader_free(reader);
serd_env_free(env);
lilv_node_free(manifest_uri);
return model;
}
static LilvVersion
get_version(LilvWorld* world, SordModel* model, const LilvNode* subject)
{
const SordNode* minor_node = sord_get(
model, subject->node, world->uris.lv2_minorVersion, NULL, NULL);
const SordNode* micro_node = sord_get(
model, subject->node, world->uris.lv2_microVersion, NULL, NULL);
LilvVersion version = { 0, 0 };
if (minor_node && micro_node) {
version.minor = atoi((const char*)sord_node_get_string(minor_node));
version.micro = atoi((const char*)sord_node_get_string(micro_node));
}
return version;
}
LILV_API void
lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri)
lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri)
{
if (!lilv_node_is_uri(bundle_uri)) {
LILV_ERRORF("Bundle URI `%s' is not a URI\n",
@ -572,13 +719,95 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri)
lilv_node_free(manifest);
return;
}
// ?plugin a lv2:Plugin
SordIter* plug_results = sord_search(world->model,
NULL,
world->uris.rdf_a,
world->uris.lv2_Plugin,
bundle_node);
// Find any loaded plugins that will be replaced with a newer version
LilvNodes* unload_uris = lilv_nodes_new();
FOREACH_MATCH(plug_results) {
const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT);
LilvNode* plugin_uri = lilv_node_new_from_node(world, plug);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(world->plugins, plugin_uri);
const LilvNode* last_bundle = plugin ? lilv_plugin_get_bundle_uri(plugin) : NULL;
if (!plugin || sord_node_equals(bundle_node, last_bundle->node)) {
// No previously loaded version, or it's from the same bundle
lilv_node_free(plugin_uri);
continue;
}
// Compare versions
SordModel* this_model = load_plugin_model(world, bundle_uri, plugin_uri);
LilvVersion this_version = get_version(world, this_model, plugin_uri);
SordModel* last_model = load_plugin_model(world, last_bundle, plugin_uri);
LilvVersion last_version = get_version(world, last_model, plugin_uri);
sord_free(this_model);
sord_free(last_model);
const int cmp = lilv_version_cmp(&this_version, &last_version);
if (cmp > 0) {
zix_tree_insert((ZixTree*)unload_uris,
lilv_node_duplicate(plugin_uri),
NULL);
LILV_WARNF("Replacing version %d.%d of <%s> from <%s>\n",
last_version.minor, last_version.micro,
sord_node_get_string(plug),
sord_node_get_string(last_bundle->node));
LILV_NOTEF("New version %d.%d found in <%s>\n",
this_version.minor, this_version.micro,
sord_node_get_string(bundle_node));
} else if (cmp < 0) {
LILV_WARNF("Ignoring bundle <%s>\n",
sord_node_get_string(bundle_node));
LILV_NOTEF("Newer version of <%s> loaded from <%s>\n",
sord_node_get_string(plug),
sord_node_get_string(last_bundle->node));
lilv_node_free(plugin_uri);
sord_iter_free(plug_results);
lilv_world_drop_graph(world, bundle_node);
lilv_node_free(manifest);
lilv_nodes_free(unload_uris);
return;
}
lilv_node_free(plugin_uri);
}
sord_iter_free(plug_results);
// Unload any old conflicting plugins
LilvNodes* unload_bundles = lilv_nodes_new();
LILV_FOREACH(nodes, i, unload_uris) {
const LilvNode* uri = lilv_nodes_get(unload_uris, i);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(world->plugins, uri);
const LilvNode* bundle = lilv_plugin_get_bundle_uri(plugin);
// Unload plugin and record bundle for later unloading
lilv_world_unload_resource(world, uri);
zix_tree_insert((ZixTree*)unload_bundles,
lilv_node_duplicate(bundle),
NULL);
}
lilv_nodes_free(unload_uris);
// Now unload the associated bundles
// This must be done last since several plugins could be in the same bundle
LILV_FOREACH(nodes, i, unload_bundles) {
lilv_world_unload_bundle(world, lilv_nodes_get(unload_bundles, i));
}
lilv_nodes_free(unload_bundles);
// Re-search for plugin results now that old plugins are gone
plug_results = sord_search(world->model,
NULL,
world->uris.rdf_a,
world->uris.lv2_Plugin,
bundle_node);
FOREACH_MATCH(plug_results) {
const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT);
lilv_world_add_plugin(world, plug, manifest, NULL, bundle_node);
@ -587,34 +816,35 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri)
lilv_world_load_dyn_manifest(world, bundle_node, manifest);
// ?specification a lv2:Specification
SordIter* spec_results = sord_search(world->model,
NULL,
world->uris.rdf_a,
world->uris.lv2_Specification,
bundle_node);
FOREACH_MATCH(spec_results) {
const SordNode* spec = sord_iter_get_node(spec_results, SORD_SUBJECT);
lilv_world_add_spec(world, spec, bundle_node);
// ?spec a lv2:Specification
// ?spec a owl:Ontology
const SordNode* spec_preds[] = { world->uris.lv2_Specification,
world->uris.owl_Ontology,
NULL };
for (const SordNode** p = spec_preds; *p; ++p) {
SordIter* i = sord_search(
world->model, NULL, world->uris.rdf_a, *p, bundle_node);
FOREACH_MATCH(i) {
const SordNode* spec = sord_iter_get_node(i, SORD_SUBJECT);
lilv_world_add_spec(world, spec, bundle_node);
}
sord_iter_free(i);
}
sord_iter_free(spec_results);
lilv_node_free(manifest);
}
static int
lilv_world_drop_graph(LilvWorld* world, LilvNode* graph)
lilv_world_drop_graph(LilvWorld* world, const SordNode* graph)
{
SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph->node);
SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph);
while (!sord_iter_end(i)) {
// Get quad and increment iter so sord_remove doesn't invalidate it
SordQuad quad;
sord_iter_get(i, quad);
sord_iter_next(i);
// Remove quad (nodes may now be deleted, quad is invalid)
sord_remove(world->model, quad);
const SerdStatus st = sord_erase(world->model, i);
if (st) {
LILV_ERRORF("Error removing statement from <%s> (%s)\n",
sord_node_get_string(graph), serd_strerror(st));
return st;
}
}
sord_iter_free(i);
@ -623,7 +853,7 @@ lilv_world_drop_graph(LilvWorld* world, LilvNode* graph)
/** Remove loaded_files entry so file will be reloaded if requested. */
static int
lilv_world_unload_file(LilvWorld* world, LilvNode* file)
lilv_world_unload_file(LilvWorld* world, const LilvNode* file)
{
ZixTreeIter* iter;
if (!zix_tree_find((ZixTree*)world->loaded_files, file, &iter)) {
@ -634,31 +864,72 @@ lilv_world_unload_file(LilvWorld* world, LilvNode* file)
}
LILV_API int
lilv_world_unload_bundle(LilvWorld* world, LilvNode* bundle_uri)
lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri)
{
// Remove loaded_files entry for manifest.ttl
LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle_uri);
lilv_world_unload_file(world, manifest);
lilv_node_free(manifest);
if (!bundle_uri) {
return 0;
}
// Find all loaded files that are inside the bundle
LilvNodes* files = lilv_nodes_new();
LILV_FOREACH(nodes, i, world->loaded_files) {
const LilvNode* file = lilv_nodes_get(world->loaded_files, i);
if (!strncmp(lilv_node_as_string(file),
lilv_node_as_string(bundle_uri),
strlen(lilv_node_as_string(bundle_uri)))) {
zix_tree_insert((ZixTree*)files,
lilv_node_duplicate(file),
NULL);
}
}
// Unload all loaded files in the bundle
LILV_FOREACH(nodes, i, files) {
const LilvNode* file = lilv_nodes_get(world->plugins, i);
lilv_world_unload_file(world, file);
}
lilv_nodes_free(files);
/* Remove any plugins in the bundle from the plugin list. Since the
application may still have a pointer to the LilvPlugin, it can not be
destroyed here. Instead, we move it to the zombie plugin list, so it
will not be in the list returned by lilv_world_get_all_plugins() but can
still be used.
*/
ZixTreeIter* i = zix_tree_begin((ZixTree*)world->plugins);
while (i != zix_tree_end((ZixTree*)world->plugins)) {
LilvPlugin* p = (LilvPlugin*)zix_tree_get(i);
ZixTreeIter* next = zix_tree_iter_next(i);
if (lilv_node_equals(lilv_plugin_get_bundle_uri(p), bundle_uri)) {
zix_tree_remove((ZixTree*)world->plugins, i);
zix_tree_insert((ZixTree*)world->zombies, p, NULL);
}
i = next;
}
// Drop everything in bundle graph
return lilv_world_drop_graph(world, bundle_uri);
return lilv_world_drop_graph(world, bundle_uri->node);
}
static void
load_dir_entry(const char* dir, const char* name, void* data)
{
LilvWorld* world = (LilvWorld*)data;
if (!strcmp(name, ".") || !strcmp(name, ".."))
if (!strcmp(name, ".") || !strcmp(name, "..")) {
return;
}
const char* scheme = (dir[0] == '/') ? "file://" : "file:///";
char* uri = lilv_strjoin(scheme, dir, "/", name, "/", NULL);
LilvNode* uri_val = lilv_new_uri(world, uri);
char* path = lilv_strjoin(dir, "/", name, "/", NULL);
SerdNode suri = serd_node_new_file_uri((const uint8_t*)path, 0, 0, true);
LilvNode* node = lilv_new_uri(world, (const char*)suri.buf);
lilv_world_load_bundle(world, uri_val);
lilv_node_free(uri_val);
free(uri);
lilv_world_load_bundle(world, node);
lilv_node_free(node);
serd_node_free(&suri);
free(path);
}
/** Load all bundles in the directory at `dir_path`. */
@ -709,7 +980,7 @@ lilv_world_load_path(LilvWorld* world,
}
}
static void
void
lilv_world_load_specifications(LilvWorld* world)
{
for (LilvSpec* spec = world->specs; spec; spec = spec->next) {
@ -720,7 +991,7 @@ lilv_world_load_specifications(LilvWorld* world)
}
}
static void
void
lilv_world_load_plugin_classes(LilvWorld* world)
{
/* FIXME: This loads all classes, not just lv2:Plugin subclasses.
@ -766,9 +1037,13 @@ lilv_world_load_plugin_classes(LilvWorld* world)
LILV_API void
lilv_world_load_all(LilvWorld* world)
{
const char* lv2_path = getenv("LV2_PATH");
if (!lv2_path)
const char* lv2_path = world->opt.lv2_path;
if (!lv2_path) {
lv2_path = getenv("LV2_PATH");
}
if (!lv2_path) {
lv2_path = LILV_DEFAULT_LV2_PATH;
}
// Discover bundles and read all manifest files into model
lilv_world_load_path(world, lv2_path);
@ -801,14 +1076,22 @@ lilv_world_load_file(LilvWorld* world, SerdReader* reader, const LilvNode* uri)
return SERD_FAILURE; // File has already been loaded
}
size_t uri_len;
const uint8_t* const uri_str = sord_node_get_string_counted(
uri->node, &uri_len);
if (strncmp((const char*)uri_str, "file:", 5)) {
return SERD_FAILURE; // Not a local file
} else if (strcmp((const char*)uri_str + uri_len - 4, ".ttl")) {
return SERD_FAILURE; // Not a Turtle file
}
serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world));
const SerdStatus st = serd_reader_read_file(
reader, sord_node_get_string(uri->node));
const SerdStatus st = serd_reader_read_file(reader, uri_str);
if (st) {
LILV_ERRORF("Error loading file `%s'\n", lilv_node_as_string(uri));
return st;
}
zix_tree_insert((ZixTree*)world->loaded_files,
lilv_node_duplicate(uri),
NULL);
@ -825,13 +1108,16 @@ lilv_world_load_resource(LilvWorld* world,
return -1;
}
SordModel* files = lilv_world_filter_model(world,
world->model,
resource->node,
world->uris.rdfs_seeAlso,
NULL, NULL);
SordIter* f = sord_begin(files);
int n_read = 0;
SordIter* files = sord_search(world->model,
resource->node,
world->uris.rdfs_seeAlso,
NULL, NULL);
FOREACH_MATCH(files) {
const SordNode* file = sord_iter_get_node(files, SORD_OBJECT);
FOREACH_MATCH(f) {
const SordNode* file = sord_iter_get_node(f, SORD_OBJECT);
const uint8_t* file_str = sord_node_get_string(file);
LilvNode* file_node = lilv_node_new_from_node(world, file);
if (sord_node_get_type(file) != SORD_URI) {
@ -841,8 +1127,9 @@ lilv_world_load_resource(LilvWorld* world,
}
lilv_node_free(file_node);
}
sord_iter_free(files);
sord_iter_free(f);
sord_free(files);
return n_read;
}
@ -856,25 +1143,29 @@ lilv_world_unload_resource(LilvWorld* world,
return -1;
}
SordModel* files = lilv_world_filter_model(world,
world->model,
resource->node,
world->uris.rdfs_seeAlso,
NULL, NULL);
SordIter* f = sord_begin(files);
int n_dropped = 0;
SordIter* files = sord_search(world->model,
resource->node,
world->uris.rdfs_seeAlso,
NULL, NULL);
FOREACH_MATCH(files) {
const SordNode* file = sord_iter_get_node(files, SORD_OBJECT);
FOREACH_MATCH(f) {
const SordNode* file = sord_iter_get_node(f, SORD_OBJECT);
LilvNode* file_node = lilv_node_new_from_node(world, file);
if (sord_node_get_type(file) != SORD_URI) {
LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n",
sord_node_get_string(file));
} else if (!lilv_world_drop_graph(world, file_node)) {
} else if (!lilv_world_drop_graph(world, file_node->node)) {
lilv_world_unload_file(world, file_node);
++n_dropped;
}
lilv_node_free(file_node);
}
sord_iter_free(files);
sord_iter_free(f);
sord_free(files);
return n_dropped;
}
@ -895,3 +1186,51 @@ lilv_world_get_all_plugins(const LilvWorld* world)
{
return world->plugins;
}
LILV_API LilvNode*
lilv_world_get_symbol(LilvWorld* world, const LilvNode* subject)
{
// Check for explicitly given symbol
SordNode* snode = sord_get(
world->model, subject->node, world->uris.lv2_symbol, NULL, NULL);
if (snode) {
LilvNode* ret = lilv_node_new_from_node(world, snode);
sord_node_free(world->world, snode);
return ret;
}
if (!lilv_node_is_uri(subject)) {
return NULL;
}
// Find rightmost segment of URI
SerdURI uri;
serd_uri_parse((const uint8_t*)lilv_node_as_uri(subject), &uri);
const char* str = "_";
if (uri.fragment.buf) {
str = (const char*)uri.fragment.buf + 1;
} else if (uri.query.buf) {
str = (const char*)uri.query.buf;
} else if (uri.path.buf) {
const char* last_slash = strrchr((const char*)uri.path.buf, '/');
str = last_slash ? (last_slash + 1) : (const char*)uri.path.buf;
}
// Replace invalid characters
const size_t len = strlen(str);
char* const sym = (char*)calloc(1, len + 1);
for (size_t i = 0; i < len; ++i) {
const char c = str[i];
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
(c == '_') || (i > 0 && c >= '0' && c <= '9'))) {
sym[i] = '_';
} else {
sym[i] = str[i];
}
}
LilvNode* ret = lilv_new_string(world, sym);
free(sym);
return ret;
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2011 David Robillard <http://drobilla.net>
Copyright 2016 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -59,7 +59,7 @@ typedef enum {
ZIX_STATUS_NOT_FOUND,
ZIX_STATUS_EXISTS,
ZIX_STATUS_BAD_ARG,
ZIX_STATUS_BAD_PERMS,
ZIX_STATUS_BAD_PERMS
} ZixStatus;
/**

View File

@ -1,5 +1,5 @@
/*
Copyright 2011-2014 David Robillard <http://drobilla.net>
Copyright 2011-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,15 +14,14 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zix/common.h"
#include "zix/tree.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct ZixTreeNodeImpl ZixTreeNode;
struct ZixTreeImpl {

View File

@ -1,5 +1,5 @@
/*
Copyright 2011-2014 David Robillard <http://drobilla.net>
Copyright 2011-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -17,10 +17,11 @@
#ifndef ZIX_TREE_H
#define ZIX_TREE_H
#include <stddef.h>
#include "zix/common.h"
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -0,0 +1,94 @@
/*
Lilv Test Plugin - Bad syntax in plugin data file
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/bad-syntax"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{
free((Test*)instance);
}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{
Test* test = (Test*)instance;
switch (port) {
case TEST_INPUT:
test->input = (float*)data;
break;
case TEST_OUTPUT:
test->output = (float*)data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
return (LV2_Handle)test;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{
Test* test = (Test*)instance;
*test->output = *test->input;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
return (index == 0) ? &descriptor : NULL;
}

View File

@ -0,0 +1,22 @@
# Lilv Test Plugin - Bad syntax in plugin data file
# Copyright 2011-2016 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/bad-syntax>
a plugin with a clearly broken data file

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/bad-syntax>
a lv2:Plugin ;
lv2:binary <bad_syntax@SHLIB_EXT@> ;
rdfs:seeAlso <bad_syntax.ttl> .

View File

@ -0,0 +1,52 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/bad-syntax"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(!lilv_plugin_get_name(plugin));
TEST_ASSERT(!lilv_plugin_instantiate(plugin, 48000, NULL));
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,30 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://lv2plug.in/ns/lv2core>
a owl:Ontology .
lv2:PluginBase
a rdfs:Class ,
owl:Class ;
rdfs:label "Plugin Base" .
lv2:Plugin
a rdfs:Class ,
owl:Class ;
rdfs:subClassOf lv2:PluginBase ;
rdfs:label "Plugin" .
lv2:DynamicsPlugin
a rdfs:Class ,
owl:Class ;
rdfs:subClassOf lv2:Plugin ;
rdfs:label "Dynamics" .
lv2:CompressorPlugin
a rdfs:Class ,
owl:Class ;
rdfs:subClassOf lv2:DynamicsPlugin ;
rdfs:label "Compressor" .

View File

@ -1,9 +1,9 @@
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://lv2plug.in/ns/lv2core>
a lv2:Specification ;
lv2:minorVersion 12 ;
lv2:microVersion 2 ;
lv2:minorVersion 16 ;
lv2:microVersion 0 ;
rdfs:seeAlso <lv2core.ttl> .

View File

@ -0,0 +1,71 @@
/*
Lilv Test Plugin - Failed instantiation
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/failed-instantiation"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
return NULL;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
return (index == 0) ? &descriptor : NULL;
}

View File

@ -0,0 +1,40 @@
# Lilv Test Plugin - Failed instantiation
# Copyright 2011-2016 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/failed-instantiation>
a lv2:Plugin ;
doap:license <http://opensource.org/licenses/isc> ;
doap:name "New version" ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:minorVersion 2 ;
lv2:microVersion 1 ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/failed-instantiation>
a lv2:Plugin ;
lv2:binary <failed_instantiation@SHLIB_EXT@> ;
rdfs:seeAlso <failed_instantiation.ttl> .

View File

@ -0,0 +1,52 @@
#include "../src/lilv_internal.h"
#include "lilv/lilv.h"
#include "serd/serd.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/failed-instantiation"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(plugin);
TEST_ASSERT(!lilv_plugin_instantiate(plugin, 48000, NULL));
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -1,5 +1,6 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
Lilv Test Plugin - Failed lib descriptor
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,21 +15,16 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef LV2_MORPH_H
#define LV2_MORPH_H
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#define PLUGIN_URI "http://example.org/failed-lib-descriptor"
#define LV2_MORPH_URI "http://lv2plug.in/ns/ext/morph"
#define LV2_MORPH_PREFIX LV2_MORPH_URI "#"
#define LV2_MORPH__AutoMorphPort LV2_MORPH_PREFIX "AutoMorphPort"
#define LV2_MORPH__MorphPort LV2_MORPH_PREFIX "MorphPort"
#define LV2_MORPH__interface LV2_MORPH_PREFIX "interface"
#define LV2_MORPH__supportsType LV2_MORPH_PREFIX "supportsType"
#define LV2_MORPH__currentType LV2_MORPH_PREFIX "currentType"
#endif /* LV2_MORPH_H */
LV2_SYMBOL_EXPORT
const LV2_Lib_Descriptor*
lv2_lib_descriptor(const char* bundle_path,
const LV2_Feature*const* features)
{
return NULL;
}

View File

@ -0,0 +1,38 @@
# Lilv Test Plugin - Failed lib descriptor
# Copyright 2011-2015 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/failed-lib-descriptor>
a lv2:Plugin ;
doap:name "Missing descriptor test" ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/failed-lib-descriptor>
a lv2:Plugin ;
lv2:binary <failed_lib_descriptor@SHLIB_EXT@> ;
rdfs:seeAlso <failed_lib_descriptor.ttl> .

View File

@ -0,0 +1,53 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/failed-lib-descriptor"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(plugin);
LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
TEST_ASSERT(!instance);
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,113 @@
/*
Lilv Test Plugin - Missing descriptor
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/lib-descriptor"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{
free((Test*)instance);
}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{
Test* test = (Test*)instance;
switch (port) {
case TEST_INPUT:
test->input = (float*)data;
break;
case TEST_OUTPUT:
test->output = (float*)data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
return (LV2_Handle)test;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{
Test* test = (Test*)instance;
*test->output = *test->input;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
static const LV2_Descriptor*
get_plugin(LV2_Lib_Handle handle, uint32_t index)
{
switch (index) {
case 0:
return &descriptor;
default:
return NULL;
}
}
static const LV2_Lib_Descriptor lib = {
NULL,
sizeof(LV2_Lib_Descriptor),
NULL,
get_plugin };
LV2_SYMBOL_EXPORT
const LV2_Lib_Descriptor*
lv2_lib_descriptor(const char* bundle_path,
const LV2_Feature*const* features)
{
return &lib;
}

View File

@ -0,0 +1,41 @@
# Lilv Test Plugin - Missing descriptor
# Copyright 2011-2015 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<http://example.org/lib-descriptor>
a lv2:Plugin ;
doap:name "Missing descriptor test" ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
<http://example.org/blob> "aGVsbG8sIHdvcmxk"^^xsd:base64Binary ;
<http://example.org/junk> "opaque"^^<http://example.org/binary> ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/lib-descriptor>
a lv2:Plugin ;
lv2:binary <lib_descriptor@SHLIB_EXT@> ;
rdfs:seeAlso <lib_descriptor.ttl> .

View File

@ -0,0 +1,66 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/lib-descriptor"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(plugin);
LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
TEST_ASSERT(instance);
lilv_instance_free(instance);
LilvNode* eg_blob = lilv_new_uri(world, "http://example.org/blob");
LilvNode* blob = lilv_world_get(world, plugin_uri, eg_blob, NULL);
TEST_ASSERT(lilv_node_is_literal(blob));
lilv_node_free(blob);
lilv_node_free(eg_blob);
LilvNode* eg_junk = lilv_new_uri(world, "http://example.org/junk");
LilvNode* junk = lilv_world_get(world, plugin_uri, eg_junk, NULL);
TEST_ASSERT(lilv_node_is_literal(junk));
lilv_node_free(junk);
lilv_node_free(eg_junk);
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,25 @@
/*
Copyright 2017-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lilv/lilvmm.hpp"
int
main()
{
Lilv::World world;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/missing-descriptor>
a lv2:Plugin ;
lv2:binary <missing_descriptor@SHLIB_EXT@> ;
rdfs:seeAlso <missing_descriptor.ttl> .

View File

@ -0,0 +1,21 @@
/*
Lilv Test Plugin - Missing descriptor
Copyright 2011-2018 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
LV2_SYMBOL_EXPORT
const char* msg = "this is not the thing you're looking for";

View File

@ -0,0 +1,38 @@
# Lilv Test Plugin - Missing descriptor
# Copyright 2011-2015 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/missing-descriptor>
a lv2:Plugin ;
doap:name "Missing descriptor test" ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,53 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-descriptor"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(plugin);
LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
TEST_ASSERT(!instance);
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/missing-name>
a lv2:Plugin ;
lv2:binary <missing_name@SHLIB_EXT@> ;
rdfs:seeAlso <missing_name.ttl> .

View File

@ -0,0 +1,94 @@
/*
Lilv Test Plugin - Missing name
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-name"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{
free((Test*)instance);
}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{
Test* test = (Test*)instance;
switch (port) {
case TEST_INPUT:
test->input = (float*)data;
break;
case TEST_OUTPUT:
test->output = (float*)data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
return (LV2_Handle)test;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{
Test* test = (Test*)instance;
*test->output = *test->input;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
return (index == 0) ? &descriptor : NULL;
}

View File

@ -0,0 +1,37 @@
# Lilv Test Plugin - Missing plugin name
# Copyright 2011-2015 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/missing-name>
a lv2:Plugin ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,54 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-name"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(plugin);
LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
TEST_ASSERT(instance);
lilv_instance_free(instance);
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/missing-plugin>
a lv2:Plugin ;
lv2:binary <missing_plugin@SHLIB_EXT@> ;
rdfs:seeAlso <missing_plugin.ttl> .

View File

@ -1,5 +1,6 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
Lilv Test Plugin - Missing plugin
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,21 +15,30 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
@file presets.h
#include "lv2/core/lv2.h"
C definitions for the LV2 Presets extension
<http://lv2plug.in/ns/ext/presets>.
*/
#include <stdint.h>
#include <stdlib.h>
#ifndef LV2_PRESETS_H
#define LV2_PRESETS_H
#define PLUGIN_URI "http://example.org/missing-plugin"
#define LV2_PRESETS_URI "http://lv2plug.in/ns/ext/presets"
#define LV2_PRESETS_PREFIX LV2_PRESETS_URI "#"
static const LV2_Descriptor descriptor = {
"http://example.org/not-the-plugin-you-are-looking-for",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
#define LV2_PRESETS__Preset LV2_PRESETS_PREFIX "Preset"
#define LV2_PRESETS__preset LV2_PRESETS_PREFIX "preset"
#define LV2_PRESETS__value LV2_PRESETS_PREFIX "value"
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
if (index == 0) {
return &descriptor;
}
#endif /* LV2_PRESETS_H */
return NULL;
}

View File

@ -0,0 +1,38 @@
# Lilv Test Plugin - Missing plugin
# Copyright 2011-2015 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/missing-plugin>
a lv2:Plugin ;
doap:name "Missing descriptor test" ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,53 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-plugin"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(plugin);
LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
TEST_ASSERT(!instance);
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/missing-port>
a lv2:Plugin ;
lv2:binary <missing_port@SHLIB_EXT@> ;
rdfs:seeAlso <missing_port.ttl> .

View File

@ -0,0 +1,94 @@
/*
Lilv Test Plugin - Missing port
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-port"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{
free((Test*)instance);
}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{
Test* test = (Test*)instance;
switch (port) {
case TEST_INPUT:
test->input = (float*)data;
break;
case TEST_OUTPUT:
test->output = (float*)data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
return (LV2_Handle)test;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{
Test* test = (Test*)instance;
*test->output = *test->input;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
return (index == 0) ? &descriptor : NULL;
}

View File

@ -0,0 +1,31 @@
# Lilv Test Plugin - Missing plugin port
# Copyright 2011-2016 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/missing-port>
a lv2:Plugin ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:port [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,52 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-port"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
// Check that all ports are ignored
TEST_ASSERT(lilv_plugin_get_num_ports(plugin) == 0);
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/missing-port-name>
a lv2:Plugin ;
lv2:binary <missing_port_name@SHLIB_EXT@> ;
rdfs:seeAlso <missing_port_name.ttl> .

View File

@ -0,0 +1,94 @@
/*
Lilv Test Plugin - Missing port name
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-port-name"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{
free((Test*)instance);
}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{
Test* test = (Test*)instance;
switch (port) {
case TEST_INPUT:
test->input = (float*)data;
break;
case TEST_OUTPUT:
test->output = (float*)data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
return (LV2_Handle)test;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{
Test* test = (Test*)instance;
*test->output = *test->input;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
return (index == 0) ? &descriptor : NULL;
}

View File

@ -0,0 +1,30 @@
# Lilv Test Plugin - Missing port name
# Copyright 2011-2015 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/missing-port-name>
a lv2:Plugin ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
] .

View File

@ -0,0 +1,56 @@
#include "../src/lilv_internal.h"
#include "serd/serd.h"
#include "lilv/lilv.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-port-name"
#define TEST_ASSERT(check) do {\
if (!(check)) {\
fprintf(stderr, "%s:%d: failed test: %s\n", __FILE__, __LINE__, #check);\
return 1;\
}\
} while (0)
int
main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
return 1;
}
const char* bundle_path = argv[1];
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
lilv_world_load_bundle(world, bundle_uri);
free(abs_bundle);
serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
TEST_ASSERT(plugin);
const LilvPort* port = lilv_plugin_get_port_by_index(plugin, 0);
TEST_ASSERT(port);
LilvNode* name = lilv_port_get_name(plugin, port);
TEST_ASSERT(!name);
lilv_node_free(name);
lilv_node_free(plugin_uri);
lilv_world_free(world);
return 0;
}

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/versioned>
a lv2:Plugin ;
lv2:binary <new_version@SHLIB_EXT@> ;
rdfs:seeAlso <new_version.ttl> .

View File

@ -0,0 +1,94 @@
/*
Lilv Test Plugin - New version
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/versioned"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{
free((Test*)instance);
}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{
Test* test = (Test*)instance;
switch (port) {
case TEST_INPUT:
test->input = (float*)data;
break;
case TEST_OUTPUT:
test->output = (float*)data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
return (LV2_Handle)test;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{
Test* test = (Test*)instance;
*test->output = *test->input;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
return (index == 0) ? &descriptor : NULL;
}

View File

@ -0,0 +1,40 @@
# Lilv Test Plugin - New version
# Copyright 2011-2016 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/versioned>
a lv2:Plugin ;
doap:license <http://opensource.org/licenses/isc> ;
doap:name "New version" ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:minorVersion 2 ;
lv2:microVersion 1 ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -0,0 +1,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/versioned>
a lv2:Plugin ;
lv2:binary <old_version@SHLIB_EXT@> ;
rdfs:seeAlso <old_version.ttl> .

View File

@ -0,0 +1,94 @@
/*
Lilv Test Plugin - Old version
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lv2/core/lv2.h"
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/versioned"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
};
typedef struct {
float* input;
float* output;
} Test;
static void
cleanup(LV2_Handle instance)
{
free((Test*)instance);
}
static void
connect_port(LV2_Handle instance, uint32_t port, void* data)
{
Test* test = (Test*)instance;
switch (port) {
case TEST_INPUT:
test->input = (float*)data;
break;
case TEST_OUTPUT:
test->output = (float*)data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
return (LV2_Handle)test;
}
static void
run(LV2_Handle instance, uint32_t sample_count)
{
Test* test = (Test*)instance;
*test->output = *test->input;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
NULL // extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
return (index == 0) ? &descriptor : NULL;
}

View File

@ -0,0 +1,40 @@
# Lilv Test Plugin - Old version
# Copyright 2011-2016 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<http://example.org/versioned>
a lv2:Plugin ;
doap:license <http://opensource.org/licenses/isc> ;
doap:name "Old version" ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:minorVersion 1 ;
lv2:microVersion 0 ;
lv2:port [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 0 ;
lv2:symbol "input" ;
lv2:name "Input"
] , [
a lv2:OutputPort ,
lv2:ControlPort ;
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] .

View File

@ -3,5 +3,5 @@
<http://example.org/lilv-test-plugin>
a lv2:Plugin ;
lv2:binary <test_plugin@SHLIB_EXT@> ;
rdfs:seeAlso <test_plugin.ttl> .
lv2:binary <test@SHLIB_EXT@> ;
rdfs:seeAlso <test.ttl> .

View File

@ -1,6 +1,6 @@
/*
Lilv Test Plugin
Copyright 2011-2012 David Robillard <d@drobilla.net>
Copyright 2011-2019 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -15,21 +15,31 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#define _POSIX_C_SOURCE 200809L
#include "lv2/atom/atom.h"
#include "lv2/core/lv2.h"
#include "lv2/state/state.h"
#include "lv2/urid/urid.h"
#ifdef _MSC_VER
# include <io.h>
# define mkstemp(pat) _mktemp(pat)
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/state/state.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
#define TEST_URI "http://example.org/lilv-test-plugin"
#define TMP_TEMPLATE "lilv_testXXXXXX"
enum {
TEST_INPUT = 0,
TEST_OUTPUT = 1
TEST_INPUT = 0,
TEST_OUTPUT = 1,
TEST_CONTROL = 2
};
typedef struct {
@ -39,7 +49,7 @@ typedef struct {
LV2_URID atom_Float;
} uris;
char* tmp_file_path;
char tmp_file_path[sizeof(TMP_TEMPLATE)];
char* rec_file_path;
FILE* rec_file;
@ -48,6 +58,16 @@ typedef struct {
unsigned num_runs;
} Test;
static void
free_path(char* path)
{
/* FIXME: Temporary hack to avoid mismatched malloc/free crashes on
Windows. The specifications needs a feature for this. */
#ifndef _WIN32
free(path);
#endif
}
static void
cleanup(LV2_Handle instance)
{
@ -55,8 +75,7 @@ cleanup(LV2_Handle instance)
if (test->rec_file) {
fclose(test->rec_file);
}
free(test->tmp_file_path);
free(test->rec_file_path);
free_path(test->rec_file_path);
free(instance);
}
@ -73,6 +92,9 @@ connect_port(LV2_Handle instance,
case TEST_OUTPUT:
test->output = (float*)data;
break;
case TEST_CONTROL:
test->output = (float*)data;
break;
default:
break;
}
@ -84,20 +106,13 @@ instantiate(const LV2_Descriptor* descriptor,
const char* path,
const LV2_Feature* const* features)
{
Test* test = (Test*)malloc(sizeof(Test));
Test* test = (Test*)calloc(1, sizeof(Test));
if (!test) {
return NULL;
}
test->map = NULL;
test->input = NULL;
test->output = NULL;
test->num_runs = 0;
test->tmp_file_path = (char*)malloc(L_tmpnam);
test->rec_file_path = NULL;
test->rec_file = NULL;
tmpnam(test->tmp_file_path);
strncpy(test->tmp_file_path, TMP_TEMPLATE, strlen(TMP_TEMPLATE) + 1);
mkstemp(test->tmp_file_path);
LV2_State_Make_Path* make_path = NULL;
@ -187,6 +202,27 @@ save(LV2_Handle instance,
map_uri(plugin, LV2_ATOM__URID),
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
// Try to store second value for the same property (should fail)
const uint32_t urid2 = map_uri(plugin, "http://example.org/urivalue2");
if (!store(callback_data,
map_uri(plugin, "http://example.org/uri"),
&urid2,
sizeof(uint32_t),
map_uri(plugin, LV2_ATOM__URID),
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) {
return LV2_STATE_ERR_UNKNOWN;
}
// Try to store with a null key (should fail)
if (!store(callback_data,
0,
&urid2,
sizeof(uint32_t),
map_uri(plugin, LV2_ATOM__URID),
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) {
return LV2_STATE_ERR_UNKNOWN;
}
store(callback_data,
map_uri(plugin, "http://example.org/num-runs"),
&plugin->num_runs,
@ -243,10 +279,10 @@ save(LV2_Handle instance,
apath,
strlen(apath) + 1,
map_uri(plugin, LV2_ATOM__Path),
LV2_STATE_IS_PORTABLE);
LV2_STATE_IS_POD);
free(apath);
free(apath2);
free_path(apath);
free_path(apath2);
if (plugin->rec_file) {
fflush(plugin->rec_file);
@ -258,9 +294,9 @@ save(LV2_Handle instance,
apath,
strlen(apath) + 1,
map_uri(plugin, LV2_ATOM__Path),
LV2_STATE_IS_PORTABLE);
LV2_STATE_IS_POD);
free(apath);
free_path(apath);
}
if (make_path) {
@ -275,9 +311,9 @@ save(LV2_Handle instance,
apath,
strlen(apath) + 1,
map_uri(plugin, LV2_ATOM__Path),
LV2_STATE_IS_PORTABLE);
free(apath);
free(spath);
LV2_STATE_IS_POD);
free_path(apath);
free_path(spath);
}
}
@ -318,6 +354,11 @@ restore(LV2_Handle instance,
map_uri(plugin, "http://example.org/extfile"),
&size, &type, &valflags);
if (valflags != LV2_STATE_IS_POD) {
fprintf(stderr, "error: Restored bad file flags\n");
return LV2_STATE_ERR_BAD_FLAGS;
}
if (apath) {
char* path = map_path->absolute_path(map_path->handle, apath);
FILE* f = fopen(path, "r");
@ -328,7 +369,7 @@ restore(LV2_Handle instance,
fprintf(stderr, "error: Restored bad file contents `%s' != `Hello'\n",
str);
}
free(path);
free_path(path);
}
apath = (char*)retrieve(
@ -343,7 +384,7 @@ restore(LV2_Handle instance,
} else {
fclose(sfile);
}
free(spath);
free_path(spath);
} else {
fprintf(stderr, "error: Failed to restore save file.\n");
}

View File

@ -1,5 +1,5 @@
# Lilv Test Plugin
# Copyright 2011 David Robillard <d@drobilla.net>
# Copyright 2011-2015 David Robillard <d@drobilla.net>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@ -37,4 +37,10 @@
lv2:index 1 ;
lv2:symbol "output" ;
lv2:name "Output"
] , [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 2 ;
lv2:symbol "control" ;
lv2:name "Control"
] .

View File

@ -1,5 +1,5 @@
/*
Copyright 2011-2014 David Robillard <http://drobilla.net>
Copyright 2011-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -21,10 +21,10 @@
#ifndef BENCH_H
#define BENCH_H
#define _POSIX_C_SOURCE 199309L
#define _POSIX_C_SOURCE 200809L
#include <time.h>
#include <sys/time.h>
#include <time.h>
static inline double
bench_elapsed_s(const struct timespec* start, const struct timespec* end)

View File

@ -14,12 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include "lilv/lilv.h"
#include "lilv_config.h"
int
main(int argc, char** argv)
{

View File

@ -0,0 +1,357 @@
/*
Copyright 2007-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "lilv/lilv.h"
#include "lv2/core/lv2.h"
#include <math.h>
#include <sndfile.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** Control port value set from the command line */
typedef struct Param {
const char* sym; ///< Port symbol
float value; ///< Control value
} Param;
/** Port type (only float ports are supported) */
typedef enum {
TYPE_CONTROL,
TYPE_AUDIO
} PortType;
/** Runtime port information */
typedef struct {
const LilvPort* lilv_port; ///< Port description
PortType type; ///< Datatype
uint32_t index; ///< Port index
float value; ///< Control value (if applicable)
bool is_input; ///< True iff an input port
bool optional; ///< True iff connection optional
} Port;
/** Application state */
typedef struct {
LilvWorld* world;
const LilvPlugin* plugin;
LilvInstance* instance;
const char* in_path;
const char* out_path;
SNDFILE* in_file;
SNDFILE* out_file;
unsigned n_params;
Param* params;
unsigned n_ports;
unsigned n_audio_in;
unsigned n_audio_out;
Port* ports;
} LV2Apply;
static int fatal(LV2Apply* self, int status, const char* fmt, ...);
/** Open a sound file with error handling. */
static SNDFILE*
sopen(LV2Apply* self, const char* path, int mode, SF_INFO* fmt)
{
SNDFILE* file = sf_open(path, mode, fmt);
const int st = sf_error(file);
if (st) {
fatal(self, 1, "Failed to open %s (%s)\n", path, sf_error_number(st));
return NULL;
}
return file;
}
/** Close a sound file with error handling. */
static void
sclose(const char* path, SNDFILE* file)
{
int st;
if (file && (st = sf_close(file))) {
fatal(NULL, 1, "Failed to close %s (%s)\n", path, sf_error_number(st));
}
}
/**
Read a single frame from a file into an interleaved buffer.
If more channels are required than are available in the file, the remaining
channels are distributed in a round-robin fashion (LRLRL).
*/
static bool
sread(SNDFILE* file, unsigned file_chans, float* buf, unsigned buf_chans)
{
const sf_count_t n_read = sf_readf_float(file, buf, 1);
for (unsigned i = file_chans - 1; i < buf_chans; ++i) {
buf[i] = buf[i % file_chans];
}
return n_read == 1;
}
/** Clean up all resources. */
static int
cleanup(int status, LV2Apply* self)
{
sclose(self->in_path, self->in_file);
sclose(self->out_path, self->out_file);
lilv_instance_free(self->instance);
lilv_world_free(self->world);
free(self->ports);
free(self->params);
return status;
}
/** Print a fatal error and clean up for exit. */
static int
fatal(LV2Apply* self, int status, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
fprintf(stderr, "error: ");
vfprintf(stderr, fmt, args);
va_end(args);
return self ? cleanup(status, self) : status;
}
/**
Create port structures from data (via create_port()) for all ports.
*/
static int
create_ports(LV2Apply* self)
{
LilvWorld* world = self->world;
const uint32_t n_ports = lilv_plugin_get_num_ports(self->plugin);
self->n_ports = n_ports;
self->ports = (Port*)calloc(self->n_ports, sizeof(Port));
/* Get default values for all ports */
float* values = (float*)calloc(n_ports, sizeof(float));
lilv_plugin_get_port_ranges_float(self->plugin, NULL, NULL, values);
LilvNode* lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort);
LilvNode* lv2_OutputPort = lilv_new_uri(world, LV2_CORE__OutputPort);
LilvNode* lv2_AudioPort = lilv_new_uri(world, LV2_CORE__AudioPort);
LilvNode* lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort);
LilvNode* lv2_connectionOptional = lilv_new_uri(world, LV2_CORE__connectionOptional);
for (uint32_t i = 0; i < n_ports; ++i) {
Port* port = &self->ports[i];
const LilvPort* lport = lilv_plugin_get_port_by_index(self->plugin, i);
port->lilv_port = lport;
port->index = i;
port->value = isnan(values[i]) ? 0.0f : values[i];
port->optional = lilv_port_has_property(
self->plugin, lport, lv2_connectionOptional);
/* Check if port is an input or output */
if (lilv_port_is_a(self->plugin, lport, lv2_InputPort)) {
port->is_input = true;
} else if (!lilv_port_is_a(self->plugin, lport, lv2_OutputPort) &&
!port->optional) {
return fatal(self, 1, "Port %d is neither input nor output\n", i);
}
/* Check if port is an audio or control port */
if (lilv_port_is_a(self->plugin, lport, lv2_ControlPort)) {
port->type = TYPE_CONTROL;
} else if (lilv_port_is_a(self->plugin, lport, lv2_AudioPort)) {
port->type = TYPE_AUDIO;
if (port->is_input) {
++self->n_audio_in;
} else {
++self->n_audio_out;
}
} else if (!port->optional) {
return fatal(self, 1, "Port %d has unsupported type\n", i);
}
}
lilv_node_free(lv2_connectionOptional);
lilv_node_free(lv2_ControlPort);
lilv_node_free(lv2_AudioPort);
lilv_node_free(lv2_OutputPort);
lilv_node_free(lv2_InputPort);
free(values);
return 0;
}
static void
print_version(void)
{
printf(
"lv2apply (lilv) " LILV_VERSION "\n"
"Copyright 2007-2019 David Robillard <http://drobilla.net>\n"
"License: <http://www.opensource.org/licenses/isc-license>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n");
}
static int
print_usage(int status)
{
fprintf(status ? stderr : stdout,
"Usage: lv2apply [OPTION]... PLUGIN_URI\n"
"Apply an LV2 plugin to an audio file.\n\n"
" -i IN_FILE Input file\n"
" -o OUT_FILE Output file\n"
" -c SYM VAL Control value\n"
" --help Display this help and exit\n"
" --version Display version information and exit\n");
return status;
}
int
main(int argc, char** argv)
{
LV2Apply self = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL
};
/* Parse command line arguments */
const char* plugin_uri = NULL;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--version")) {
free(self.params);
print_version();
return 0;
} else if (!strcmp(argv[i], "--help")) {
free(self.params);
return print_usage(0);
} else if (!strcmp(argv[i], "-i")) {
self.in_path = argv[++i];
} else if (!strcmp(argv[i], "-o")) {
self.out_path = argv[++i];
} else if (!strcmp(argv[i], "-c")) {
if (argc < i + 3) {
return fatal(&self, 1, "Missing argument for -c\n");
}
self.params = (Param*)realloc(self.params,
++self.n_params * sizeof(Param));
self.params[self.n_params - 1].sym = argv[++i];
self.params[self.n_params - 1].value = atof(argv[++i]);
} else if (argv[i][0] == '-') {
free(self.params);
return print_usage(1);
} else if (i == argc - 1) {
plugin_uri = argv[i];
}
}
/* Check that required arguments are given */
if (!self.in_path || !self.out_path || !plugin_uri) {
free(self.params);
return print_usage(1);
}
/* Create world and plugin URI */
self.world = lilv_world_new();
LilvNode* uri = lilv_new_uri(self.world, plugin_uri);
if (!uri) {
return fatal(&self, 2, "Invalid plugin URI <%s>\n", plugin_uri);
}
/* Discover world */
lilv_world_load_all(self.world);
/* Get plugin */
const LilvPlugins* plugins = lilv_world_get_all_plugins(self.world);
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, uri);
lilv_node_free(uri);
if (!(self.plugin = plugin)) {
return fatal(&self, 3, "Plugin <%s> not found\n", plugin_uri);
}
/* Open input file */
SF_INFO in_fmt = { 0, 0, 0, 0, 0, 0 };
if (!(self.in_file = sopen(&self, self.in_path, SFM_READ, &in_fmt))) {
return 4;
}
/* Create port structures */
if (create_ports(&self)) {
return 5;
}
if (self.n_audio_in == 0 ||
(in_fmt.channels != (int)self.n_audio_in && in_fmt.channels != 1)) {
return fatal(&self, 6, "Unable to map %d inputs to %d ports\n",
in_fmt.channels, self.n_audio_in);
}
/* Set control values */
for (unsigned i = 0; i < self.n_params; ++i) {
const Param* param = &self.params[i];
LilvNode* sym = lilv_new_string(self.world, param->sym);
const LilvPort* port = lilv_plugin_get_port_by_symbol(plugin, sym);
lilv_node_free(sym);
if (!port) {
return fatal(&self, 7, "Unknown port `%s'\n", param->sym);
}
self.ports[lilv_port_get_index(plugin, port)].value = param->value;
}
/* Open output file */
SF_INFO out_fmt = in_fmt;
out_fmt.channels = self.n_audio_out;
if (!(self.out_file = sopen(&self, self.out_path, SFM_WRITE, &out_fmt))) {
return 8;
}
/* Instantiate plugin and connect ports */
const uint32_t n_ports = lilv_plugin_get_num_ports(plugin);
float in_buf[self.n_audio_in];
float out_buf[self.n_audio_out];
self.instance = lilv_plugin_instantiate(
self.plugin, in_fmt.samplerate, NULL);
for (uint32_t p = 0, i = 0, o = 0; p < n_ports; ++p) {
if (self.ports[p].type == TYPE_CONTROL) {
lilv_instance_connect_port(self.instance, p, &self.ports[p].value);
} else if (self.ports[p].type == TYPE_AUDIO) {
if (self.ports[p].is_input) {
lilv_instance_connect_port(self.instance, p, in_buf + i++);
} else {
lilv_instance_connect_port(self.instance, p, out_buf + o++);
}
} else {
lilv_instance_connect_port(self.instance, p, NULL);
}
}
/* Ports are now connected to buffers in interleaved format, so we can run
a single frame at a time and avoid having to interleave buffers to
read/write from/to sndfile. */
lilv_instance_activate(self.instance);
while (sread(self.in_file, in_fmt.channels, in_buf, self.n_audio_in)) {
lilv_instance_run(self.instance, 1);
if (sf_writef_float(self.out_file, out_buf, 1) != 1) {
return fatal(&self, 9, "Failed to write to output file\n");
}
}
lilv_instance_deactivate(self.instance);
return cleanup(0, &self);
}

Some files were not shown because too many files have changed in this diff Show More