summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS4
l---------COPYING1
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am5
-rw-r--r--NEWS0
-rw-r--r--README4
-rwxr-xr-xautogen.sh9
-rw-r--r--configure.ac100
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/mainpage.dox10
-rw-r--r--doc/reference.doxygen.in1163
-rw-r--r--examples/Makefile.am2
-rw-r--r--examples/hosts/.jack_host.c.swpbin0 -> 28672 bytes
-rw-r--r--examples/hosts/Makefile.am24
-rw-r--r--examples/hosts/jack_host.c218
-rw-r--r--examples/hosts/test_host.c231
-rw-r--r--examples/plugins/Amp-swh.lv2/Makefile10
-rw-r--r--examples/plugins/Amp-swh.lv2/amp.c96
-rwxr-xr-xexamples/plugins/Amp-swh.lv2/amp.sobin0 -> 2629 bytes
-rw-r--r--examples/plugins/Amp-swh.lv2/amp.ttl68
-rw-r--r--examples/plugins/Amp-swh.lv2/manifest.ttl9
-rw-r--r--examples/plugins/Makefile.am24
-rw-r--r--include/Makefile.am3
-rw-r--r--include/lv2.h305
-rw-r--r--include/lv2.ttl326
-rw-r--r--libslv2.pc.in10
-rw-r--r--slv2/Makefile.am11
-rw-r--r--slv2/plugin.h168
-rw-r--r--slv2/plugininstance.h205
-rw-r--r--slv2/pluginlist.h159
-rw-r--r--slv2/port.h116
-rw-r--r--slv2/private_types.h65
-rw-r--r--slv2/query.h102
-rw-r--r--slv2/slv2.h36
-rw-r--r--slv2/types.h66
-rw-r--r--src/Makefile.am14
-rw-r--r--src/plugin.c190
-rw-r--r--src/plugininstance.c100
-rw-r--r--src/pluginlist.c243
-rw-r--r--src/port.c163
-rw-r--r--src/query.c123
-rw-r--r--src/util.c121
-rw-r--r--src/util.h53
43 files changed, 4559 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..77657d6
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+Author:
+
+Dave Robillard <mailto:drobilla@connect.carleton.ca>
+
diff --git a/COPYING b/COPYING
new file mode 120000
index 0000000..7153769
--- /dev/null
+++ b/COPYING
@@ -0,0 +1 @@
+/usr/share/automake-1.9/COPYING \ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..aefe7ee
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = include src slv2 examples doc
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libslv2.pc
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..aabd9de
--- /dev/null
+++ b/README
@@ -0,0 +1,4 @@
+You should not be reading this.
+
+Tell no one!
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..a9a6c1b
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+echo 'Generating necessary files...'
+libtoolize --copy --force
+aclocal
+autoheader -Wall
+automake --gnu --add-missing -Wall
+autoconf
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..50973e5
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,100 @@
+AC_PREREQ(2.59)
+AC_INIT([libslv2],[0.0.1],[drobilla@connect.carleton.ca])
+AC_CONFIG_SRCDIR([src/plugin.c])
+AC_CONFIG_SRCDIR([slv2/plugin.h])
+AC_CONFIG_SRCDIR([include/lv2.h])
+AC_CONFIG_SRCDIR([examples/plugins/Amp-swh.lv2/amp.c])
+AC_CONFIG_SRCDIR([examples/hosts/test_host.c])
+AC_CONFIG_HEADER([config.h])
+AM_INIT_AUTOMAKE
+
+# Checks for compiler
+AC_PROG_CC
+
+# Check pedantic other stuff autoscan says we should :)
+AC_C_CONST
+AC_C_INLINE
+AC_HEADER_STDBOOL
+AC_TYPE_SIZE_T
+
+# Library building stuff
+AC_PROG_LIBTOOL
+
+# Check for debugging flag
+debug="no"
+AC_ARG_ENABLE(debug,
+ [AS_HELP_STRING(--enable-debug, [Enable debugging (false)])],
+ [debug="$enableval"])
+if test "$debug" = "yes"; then
+ CFLAGS="-O0 -g -DDEBUG"
+ CXXFLAGS="$CFLAGS"
+else
+ CFLAGS="$CFLAGS -DNDEBUG"
+ CXXFLAGS="$CXXFLAGS -DNDEBUG"
+fi
+
+# Check for strict flag
+strict="no"
+AC_ARG_ENABLE(strict,
+ [AS_HELP_STRING(--enable-strict, [Enable strict compiler warnings and errors (false)])],
+ [strict="$enableval"])
+if test "$strict" = "yes"; then
+ CFLAGS="$CFLAGS -std=c99 -pedantic -Wall -Wconversion -Winit-self"
+ CXXFLAGS="$CXXFLAGS -ansi -pedantic -Wall -Wconversion -Winit-self -Woverloaded-virtual -Wsign-promo"
+fi
+
+# Bolt on a few specific flags to CXXFLAGS that should always be used
+#CXXFLAGS="$CXXFLAGS -pipe -Wall -fmessage-length=139 -fdiagnostics-show-location=every-line"
+#CFLAGS="$CFLAGS -pipe -Wall -fmessage-length=139 -fdiagnostics-show-location=every-line"
+
+# Check plugin install directory
+AC_MSG_CHECKING([where to install LV2 plugins])
+AC_ARG_WITH(lv2-dir,
+ AS_HELP_STRING([--with-lv2-dir=DIR],
+ [directory that LV2 plugins should be installed in ($libdir/lv2)]),
+ [lv2dir=$withval], [lv2dir=$libdir/lv2])
+AC_MSG_RESULT($lv2dir)
+AC_SUBST(lv2dir)
+
+# Check for RASQAL
+PKG_CHECK_MODULES(RASQAL, rasqal >= 0.20, build_rasqal="yes", build_rasqal="no")
+AC_SUBST(JACK_CFLAGS)
+AC_SUBST(JACK_LIBS)
+
+# Check for JACK
+build_jack="yes"
+AC_ARG_ENABLE(jack,
+ [AS_HELP_STRING(--with-jack, [Build JACK clients (true)])],
+ [ if test x$with_jack = xno ; then build_jack=no ; fi ])
+if test "$build_jack" = "yes"; then
+ PKG_CHECK_MODULES(JACK, jack >= 0.99.0, build_jack="yes", build_jack="no")
+fi
+if test "$build_jack" = "yes"; then
+ AC_DEFINE(HAVE_JACK, 1, [Has JACK])
+ AC_SUBST(JACK_CFLAGS)
+ AC_SUBST(JACK_LIBS)
+else
+ AC_MSG_WARN([JACK not found, JACK clients will not be built.])
+fi
+AM_CONDITIONAL(WITH_JACK, [test "$build_jack" = "yes"])
+
+
+# Write output files
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([src/Makefile])
+AC_CONFIG_FILES([slv2/Makefile])
+AC_CONFIG_FILES([include/Makefile])
+AC_CONFIG_FILES([examples/Makefile])
+AC_CONFIG_FILES([examples/plugins/Makefile])
+AC_CONFIG_FILES([examples/hosts/Makefile])
+AC_CONFIG_FILES([libslv2.pc])
+AC_CONFIG_FILES([doc/Makefile])
+AC_CONFIG_FILES([doc/reference.doxygen])
+AC_OUTPUT
+
+
+# Display summary message
+AC_MSG_RESULT([])
+AC_MSG_RESULT([Building JACK client: $build_jack])
+AC_MSG_RESULT([])
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..78fc0af
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,2 @@
+doc: $(top_srcdir)/doc/reference.doxygen $(top_srcdir)/include/lv2.h $(top_srcdir)/slv2/*.h
+ doxygen $(top_srcdir)/doc/reference.doxygen
diff --git a/doc/mainpage.dox b/doc/mainpage.dox
new file mode 100644
index 0000000..545a92e
--- /dev/null
+++ b/doc/mainpage.dox
@@ -0,0 +1,10 @@
+/** @mainpage
+
+@section Overview
+
+LibSLV2 is a host library to simply the use of LV2 plugins.
+
+It will have a lovely wordey description here once I get around to it.
+For now click on the "Modules" tab above to get at the beef.
+
+*/
diff --git a/doc/reference.doxygen.in b/doc/reference.doxygen.in
new file mode 100644
index 0000000..f4e83c6
--- /dev/null
+++ b/doc/reference.doxygen.in
@@ -0,0 +1,1163 @@
+# @configure_input@
+
+# Doxyfile 1.3.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "LibSLV2"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = @top_srcdir@/doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of source
+# files, where putting all generated files in the same directory would otherwise
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = YES
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @top_srcdir@/doc/mainpage.dox \
+ @top_srcdir@/slv2/types.h \
+ @top_srcdir@/slv2/pluginlist.h \
+ @top_srcdir@/slv2/plugin.h \
+ @top_srcdir@/slv2/port.h \
+ @top_srcdir@/slv2/plugininstance.h #\
+ #@top_srcdir@/slv2/query.h #\
+ #@top_srcdir@/include
+
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = @top_srcdir@/examples/hosts
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *.c
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = NO
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..94939c3
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = plugins hosts
+
diff --git a/examples/hosts/.jack_host.c.swp b/examples/hosts/.jack_host.c.swp
new file mode 100644
index 0000000..eb9bb86
--- /dev/null
+++ b/examples/hosts/.jack_host.c.swp
Binary files differ
diff --git a/examples/hosts/Makefile.am b/examples/hosts/Makefile.am
new file mode 100644
index 0000000..340c962
--- /dev/null
+++ b/examples/hosts/Makefile.am
@@ -0,0 +1,24 @@
+AM_CFLAGS = -std=c99 -I. -I$(top_srcdir)/include -I$(top_srcdir) `pkg-config --cflags rasqal`
+AM_LDFLAGS = `pkg-config --libs rasqal`
+
+bin_PROGRAMS = test_host jack_host
+
+test_host_DEPENDENCIES = ../../src/libslv2.la
+test_host_LDADD = ../../src/libslv2.la
+
+test_host_SOURCES = \
+ test_host.c
+
+
+if WITH_JACK
+
+jack_host_CFLAGS = @JACK_CFLAGS@ $(AM_CFLAGS)
+#jack_host_LIBS = @JACK_LIBS@
+
+jack_host_DEPENDENCIES = ../../src/libslv2.la
+jack_host_LDADD = ../../src/libslv2.la @JACK_LIBS@
+
+jack_host_SOURCES = \
+ jack_host.c
+
+endif # WITH_JACK
diff --git a/examples/hosts/jack_host.c b/examples/hosts/jack_host.c
new file mode 100644
index 0000000..2247e03
--- /dev/null
+++ b/examples/hosts/jack_host.c
@@ -0,0 +1,218 @@
+/* LibSLV2 Jack Example Host
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <slv2/slv2.h>
+#include <jack/jack.h>
+
+
+/** This program's data */
+struct JackHost {
+ jack_client_t* jack_client; /**< Jack client */
+ SLV2Plugin* plugin; /**< Plugin "class" (actually just a few strings) */
+ SLV2Instance* instance; /**< Plugin "instance" (loaded shared lib) */
+ unsigned long num_ports; /**< Size of the two following arrays: */
+ jack_port_t** jack_ports; /**< For audio ports, otherwise NULL */
+ float* controls; /**< For control ports, otherwise 0.0f */
+};
+
+
+void die(const char* msg);
+void create_port(struct JackHost* host, unsigned long port_index);
+int jack_process_cb(jack_nframes_t nframes, void* data);
+void list_plugins(SLV2List list);
+
+
+int
+main(int argc, char** argv)
+{
+ struct JackHost host;
+ host.jack_client = NULL;
+ host.num_ports = 0;
+ host.jack_ports = NULL;
+ host.controls = NULL;
+
+ /* Find all installed plugins */
+ SLV2List plugins = slv2_list_new();
+ slv2_list_load_all(plugins);
+ //slv2_list_load_bundle(plugins, "http://www.scs.carleton.ca/~drobilla/files/Amp-swh.lv2");
+
+ /* Find the plugin to run */
+ const char* plugin_uri = (argc == 2) ? argv[1] : NULL;
+
+ if (!plugin_uri) {
+ fprintf(stderr, "\nYou must specify a plugin URI to load.\n");
+ fprintf(stderr, "\nKnown plugins:\n\n");
+ list_plugins(plugins);
+ return EXIT_FAILURE;
+ }
+
+ printf("URI:\t%s\n", plugin_uri);
+ host.plugin = slv2_list_get_plugin_by_uri(plugins, plugin_uri);
+
+ if (!host.plugin) {
+ fprintf(stderr, "Failed to find plugin %s.\n", plugin_uri);
+ slv2_list_free(plugins);
+ return EXIT_FAILURE;
+ }
+
+ /* Get the plugin's name */
+ char* name = slv2_plugin_get_name(host.plugin);
+ printf("Name:\t%s\n", name);
+
+ /* Connect to JACK (with plugin name as client name) */
+ host.jack_client = jack_client_open(name, JackNullOption, NULL);
+ free(name);
+ if (!host.jack_client)
+ die("Failed to connect to JACK.");
+ else
+ printf("Connected to JACK.\n");
+
+ /* Instantiate the plugin */
+ host.instance = slv2_plugin_instantiate(
+ host.plugin, jack_get_sample_rate(host.jack_client), NULL);
+ if (!host.instance)
+ die("Failed to instantiate plugin.\n");
+ else
+ printf("Succesfully instantiated plugin.\n");
+
+ jack_set_process_callback(host.jack_client, &jack_process_cb, (void*)(&host));
+
+ /* Create ports */
+ host.num_ports = slv2_plugin_get_num_ports(host.plugin);
+ host.jack_ports = calloc(host.num_ports, sizeof(jack_port_t*));
+ host.controls = calloc(host.num_ports, sizeof(float*));
+
+ for (unsigned long i=0; i < host.num_ports; ++i)
+ create_port(&host, i);
+
+ /* Activate plugin and JACK */
+ slv2_instance_activate(host.instance);
+ jack_activate(host.jack_client);
+
+ /* Run */
+ printf("Press enter to quit: ");
+ getc(stdin);
+ printf("\n");
+
+ /* Deactivate plugin and JACK */
+ slv2_instance_free(host.instance);
+ slv2_list_free(plugins);
+
+ printf("Shutting down JACK.\n");
+ for (unsigned long i=0; i < host.num_ports; ++i) {
+ if (host.jack_ports[i] != NULL) {
+ jack_port_unregister(host.jack_client, host.jack_ports[i]);
+ host.jack_ports[i] = NULL;
+ }
+ }
+ jack_client_close(host.jack_client);
+
+ return 0;
+}
+
+
+/** Abort and exit on error */
+void
+die(const char* msg)
+{
+ fprintf(stderr, "%s\n", msg);
+ exit(EXIT_FAILURE);
+}
+
+
+/** Creates a port and connects the plugin instance to it's data location.
+ *
+ * For audio ports, creates a jack port and connects plugin port to buffer.
+ *
+ * For control ports, sets controls array to default value and connects plugin
+ * port to that element.
+ */
+void
+create_port(struct JackHost* host,
+ unsigned long port_index)
+{
+ /* Make sure this is a float port */
+ enum SLV2DataType type = slv2_port_get_data_type(host->plugin, port_index);
+ if (type != SLV2_DATA_TYPE_FLOAT)
+ die("Unrecognized data type, aborting.");
+
+ /* Get the port symbol (label) for console printing */
+ char* symbol = slv2_port_get_symbol(host->plugin, port_index);
+
+ /* Initialize the port array elements */
+ host->jack_ports[port_index] = NULL;
+ host->controls[port_index] = 0.0f;
+
+ /* Get the 'class' of the port (control input, audio output, etc) */
+ enum SLV2PortClass class = slv2_port_get_class(host->plugin, port_index);
+
+ /* Connect the port based on it's 'class' */
+ switch (class) {
+ case SLV2_CONTROL_RATE_INPUT:
+ host->controls[port_index] = slv2_port_get_default_value(host->plugin, port_index);
+ slv2_instance_connect_port(host->instance, port_index, &host->controls[port_index]);
+ printf("Set %s to %f\n", symbol, host->controls[port_index]);
+ break;
+ case SLV2_CONTROL_RATE_OUTPUT:
+ slv2_instance_connect_port(host->instance, port_index, &host->controls[port_index]);
+ break;
+ case SLV2_AUDIO_RATE_INPUT:
+ host->jack_ports[port_index] = jack_port_register(host->jack_client,
+ symbol, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+ break;
+ case SLV2_AUDIO_RATE_OUTPUT:
+ host->jack_ports[port_index] = jack_port_register(host->jack_client,
+ symbol, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ break;
+ default:
+ die("ERROR: Unknown port type, aborting messily!");
+ }
+
+ free(symbol);
+}
+
+
+/** Jack process callback. */
+int
+jack_process_cb(jack_nframes_t nframes, void* data)
+{
+ struct JackHost* host = (struct JackHost*)data;
+
+ /* Connect plugin ports directly to JACK buffers */
+ for (unsigned long i=0; i < host->num_ports; ++i)
+ if (host->jack_ports[i] != NULL)
+ slv2_instance_connect_port(host->instance, i,
+ jack_port_get_buffer(host->jack_ports[i], nframes));
+
+ /* Run plugin for this cycle */
+ slv2_instance_run(host->instance, nframes);
+
+ return 0;
+}
+
+
+void
+list_plugins(SLV2List list)
+{
+ for (int i=0; i < slv2_list_get_length(list); ++i) {
+ const SLV2Plugin* const p = slv2_list_get_plugin_by_index(list, i);
+ printf("%s\n", slv2_plugin_get_uri(p));
+ }
+}
diff --git a/examples/hosts/test_host.c b/examples/hosts/test_host.c
new file mode 100644
index 0000000..3ec8d86
--- /dev/null
+++ b/examples/hosts/test_host.c
@@ -0,0 +1,231 @@
+/* LibSLV2 Test Host
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _XOPEN_SOURCE 500
+
+#include <rasqal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <slv2/types.h>
+#include <slv2/plugin.h>
+#include <slv2/plugininstance.h>
+#include <slv2/pluginlist.h>
+#include <slv2/port.h>
+
+
+void
+create_control_input()
+{
+ printf("Control Input\n");
+}
+
+
+void
+create_control_output()
+{
+ printf("Control Output\n");
+}
+
+
+void
+create_audio_input()
+{
+ printf("Audio Input\n");
+}
+
+
+void
+create_audio_output()
+{
+ printf("Audio Output\n");
+}
+
+
+void
+create_port(SLV2Plugin* plugin,
+ SLV2Instance* instance,
+ unsigned long port_index)
+{
+ enum SLV2PortClass class = slv2_port_get_class(plugin, port_index);
+
+ switch (class) {
+ case SLV2_CONTROL_RATE_INPUT:
+ create_control_input(port_index);
+ break;
+ case SLV2_CONTROL_RATE_OUTPUT:
+ create_control_output(port_index);
+ break;
+ case SLV2_AUDIO_RATE_INPUT:
+
+ create_audio_input(port_index);
+ break;
+ case SLV2_AUDIO_RATE_OUTPUT:
+ create_audio_output(port_index);
+ break;
+ default:
+ printf("Unknown port type, ignored.\n");
+ }
+ //printf("Port %ld class: %d\n", i, slv2_port_get_class(p, i));
+}
+
+
+int
+main()
+{
+ //const char* path = "foo";
+
+ const char* path = "/home/dave/code/libslv2/examples/plugins";
+
+ SLV2List plugins = slv2_list_new();
+ slv2_list_load_path(plugins, path);
+
+ const char* plugin_uri = "http://plugin.org.uk/swh-plugins/amp";
+ printf("URI:\t%s\n", plugin_uri);
+
+ const SLV2Plugin* p = slv2_list_get_plugin_by_uri(plugins, plugin_uri);
+ if (p) {
+ /* Get the plugin's name */
+ unsigned char* name = slv2_plugin_get_name(p);
+ printf("Name:\t%s\n", name);
+ free(name);
+
+ unsigned long num_ports = slv2_plugin_get_num_ports(p);
+ //printf("Number of ports: %ld\n", num_ports);
+
+ for (unsigned long i=0; i < num_ports; ++i) {
+ enum SLV2PortClass class = slv2_port_get_class(p, i);
+
+ switch (class) {
+ case SLV2_CONTROL_RATE_INPUT:
+ create_control_input(i);
+ break;
+ case SLV2_CONTROL_RATE_OUTPUT:
+ create_control_output(i);
+ break;
+ case SLV2_AUDIO_RATE_INPUT:
+ create_audio_input(i);
+ break;
+ case SLV2_AUDIO_RATE_OUTPUT:
+ create_audio_output(i);
+ break;
+ default:
+ printf("Unknown port type, ignored.\n");
+ }
+ //printf("Port %ld class: %d\n", i, slv2_port_get_class(p, i));
+
+
+ }
+
+ SLV2Property prop;
+ for (unsigned long i=0; i < num_ports; ++i) {
+ const char* property = "a";
+ prop = slv2_port_get_property(p, i, property);
+ if (prop)
+ printf("Port %ld %s = %s\n", i, property, prop->values[0]);
+ else
+ printf("No port %ld %s.\n", i, property);
+ free(prop);
+ }
+ printf("\n");
+
+ SLV2Instance* i = slv2_plugin_instantiate(p, 48000, NULL);
+ if (i) {
+ printf("Succesfully instantiated plugin.\n");
+
+ float gain = 2.0f;
+ float input = 0.25f;
+ float output = 0.0f;
+ slv2_instance_connect_port(i, 0, &gain);
+ slv2_instance_connect_port(i, 1, &input);
+ slv2_instance_connect_port(i, 2, &output);
+
+ slv2_instance_activate(i);
+ slv2_instance_run(i, 1);
+ slv2_instance_deactivate(i);
+
+ printf("Gain: %f, Input: %f => Output: %f\n", gain, input, output);
+ slv2_instance_free(i);
+ }
+ }
+
+ slv2_list_free(plugins);
+
+#if 0
+ /* Display all plugins found in path */
+ if (plugins)
+ printf("Plugins found: %ld\n", slv2_list_get_size(plugins));
+ else
+ printf("No plugins found in %s\n", path);
+
+ for (unsigned long i=0; 1; ++i) {
+ const SLV2Plugin* p =
+ slv2_list_get_plugin_by_index(plugins, i);
+
+ if (!p)
+ break;
+ else
+ printf("\t%s\n", slv2_plugin_get_uri(p));
+ }
+#endif
+
+#if 0
+ const uchar* bundle_url = (const uchar*)"file:/home/dave/code/ladspa2/ladspa2_sdk/examples/plugins/Amp-swh.ladspa2/";
+ LV2Bundle* b = slv2_bundle_load(bundle_url);
+
+ if (b != NULL) {
+ printf("Loaded bundle %s\n", slv2_bundle_get_url(b));
+
+ for (unsigned long i=0; i < slv2_bundle_get_num_plugins(b); ++i) {
+ const SLV2Plugin* p = slv2_bundle_get_plugin_by_index(b, i);
+ //printf("Plugin: %s\n", p->plugin_uri);
+ //printf("Lib: %s\n", p->lib_url);
+ //printf("Data: %s\n", p->data_url);
+
+ printf("\n");
+ const uchar* property = (uchar*)"doap:name";
+ printf("%s\t%s\n", slv2_plugin_get_uri(p), property);
+ struct SLV2Property* result = slv2_plugin_get_property(p, property);
+
+ if (result) {
+ for (int i=0; i < result->num_values; ++i)
+ printf("\t%s\n", result->values[i]);
+ } else {
+ printf("No results.\n");
+ }
+ printf("\n");
+
+ /* Instantiate plugin */
+ SLV2PluginInstance* instance = slv2_plugin_instantiate(
+ p, 48000, NULL);
+ if (instance != NULL) {
+ printf("Successfully instantiated %s\n", slv2_plugin_get_uri(p));
+ slv2_plugin_instance_free(instance);
+ }
+
+ }
+
+ } else {
+ printf("Failed to load bundle %s\n", bundle_url);
+ }
+#endif
+
+ return 0;
+}
+
diff --git a/examples/plugins/Amp-swh.lv2/Makefile b/examples/plugins/Amp-swh.lv2/Makefile
new file mode 100644
index 0000000..4fb858a
--- /dev/null
+++ b/examples/plugins/Amp-swh.lv2/Makefile
@@ -0,0 +1,10 @@
+CFLAGS = -Wall -I../../../include
+
+all: amp.so
+
+amp.so: amp.o
+ $(LD) amp.o -o amp.so -shared
+ rm amp.o
+
+clean:
+ rm *.o amp.so
diff --git a/examples/plugins/Amp-swh.lv2/amp.c b/examples/plugins/Amp-swh.lv2/amp.c
new file mode 100644
index 0000000..a30c4bd
--- /dev/null
+++ b/examples/plugins/Amp-swh.lv2/amp.c
@@ -0,0 +1,96 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <math.h>
+
+#include "lv2.h"
+
+#ifdef WIN32
+#define SYMBOL_EXPORT __declspec(dllexport)
+#else
+#define SYMBOL_EXPORT
+#endif
+
+#define AMP_URI "http://plugin.org.uk/swh-plugins/amp";
+#define AMP_GAIN 0
+#define AMP_INPUT 1
+#define AMP_OUTPUT 2
+
+static LV2_Descriptor *ampDescriptor = NULL;
+
+typedef struct {
+ float *gain;
+ float *input;
+ float *output;
+} Amp;
+
+static void cleanupAmp(LV2_Handle instance) {
+ free(instance);
+}
+
+static void connectPortAmp(LV2_Handle instance, unsigned long port,
+ void *data) {
+ Amp *plugin = (Amp *)instance;
+
+ switch (port) {
+ case AMP_GAIN:
+ plugin->gain = data;
+ break;
+ case AMP_INPUT:
+ plugin->input = data;
+ break;
+ case AMP_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle instantiateAmp(const LV2_Descriptor *descriptor,
+ unsigned long s_rate, const char *path , const LV2_Host_Feature **features) {
+ Amp *plugin_data = (Amp *)malloc(sizeof(Amp));
+
+ return (LV2_Handle)plugin_data;
+}
+
+#define DB_CO(g) ((g) > -90.0f ? powf(10.0f, (g) * 0.05f) : 0.0f)
+
+static void runAmp(LV2_Handle instance, unsigned long sample_count) {
+ Amp *plugin_data = (Amp *)instance;
+
+ const float gain = *(plugin_data->gain);
+ const float * const input = plugin_data->input;
+ float * const output = plugin_data->output;
+
+ unsigned long pos;
+ float coef = DB_CO(gain);
+
+ for (pos = 0; pos < sample_count; pos++) {
+ output[pos] = input[pos] * coef;
+ }
+}
+
+static void init() {
+ ampDescriptor =
+ (LV2_Descriptor *)malloc(sizeof(LV2_Descriptor));
+
+ ampDescriptor->URI = AMP_URI;
+ ampDescriptor->activate = NULL;
+ ampDescriptor->cleanup = cleanupAmp;
+ ampDescriptor->connect_port = connectPortAmp;
+ ampDescriptor->deactivate = NULL;
+ ampDescriptor->instantiate = instantiateAmp;
+ ampDescriptor->run = runAmp;
+}
+
+SYMBOL_EXPORT
+const LV2_Descriptor *lv2_descriptor(unsigned long index) {
+ if (!ampDescriptor) init();
+
+ switch (index) {
+ case 0:
+ return ampDescriptor;
+ default:
+ return NULL;
+ }
+}
+
diff --git a/examples/plugins/Amp-swh.lv2/amp.so b/examples/plugins/Amp-swh.lv2/amp.so
new file mode 100755
index 0000000..281b709
--- /dev/null
+++ b/examples/plugins/Amp-swh.lv2/amp.so
Binary files differ
diff --git a/examples/plugins/Amp-swh.lv2/amp.ttl b/examples/plugins/Amp-swh.lv2/amp.ttl
new file mode 100644
index 0000000..d44c0b9
--- /dev/null
+++ b/examples/plugins/Amp-swh.lv2/amp.ttl
@@ -0,0 +1,68 @@
+@prefix lv2: <http://lv2plug.in/ontology#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+
+<http://plugin.org.uk/swh-plugins/amp> a lv2:Plugin ;
+ a lv2:AmplifierPlugin ;
+ doap:maintainer [
+ foaf:name "Steve Harris";
+ foaf:homepage <http://plugin.org.uk/> ;
+ foaf:mbox <mailto:steve@plugin.org.uk> ;
+ ] ;
+ doap:name "Simple amplifier" ;
+ doap:name "简单放大器"@ch ;
+ doap:name "Einfacher Verstärker"@de ;
+ doap:name "Simple amp"@en-gb ;
+ doap:name "Amplificador simple"@es ;
+ doap:name "Amplificateur de base"@fr ;
+ doap:name "Amplificatore semplice"@it ;
+ doap:name "簡単なアンプ"@jp ;
+ doap:name "Просто усилитель"@ru ;
+ doap:licence <http://usefulinc.com/doap/licenses/gpl> ;
+ lv2:property lv2:hardRtCapable ;
+
+ lv2:port [
+ a lv2:InputControlRatePort ;
+ lv2:datatype lv2:float ;
+ lv2:index 0 ;
+ lv2:symbol "gain" ;
+ lv2:name "gain" ;
+ lv2:name "收益"@ch ;
+ lv2:name "gewinn"@de ;
+ lv2:name "gain"@en-gb ;
+ lv2:name "aumento"@es ;
+ lv2:name "gain"@fr ;
+ lv2:name "guadagno"@it ;
+ lv2:name "利益"@jp ;
+ lv2:name "увеличение"@ru ;
+ lv2:default 0.0 ;
+ lv2:minimum -90.0 ;
+ lv2:maximum 24.0 ;
+ lv2:scalePoint [
+ lv2:label "+5" ;
+ lv2:value 5.0 ;
+ ] , [
+ lv2:label "0" ;
+ lv2:value 0.0 ;
+ ] , [
+ lv2:label "-5" ;
+ lv2:value -5.0 ;
+ ] , [
+ lv2:label "-10" ;
+ lv2:value -10.0 ;
+ ]
+ ] , [
+ a lv2:InputAudioRatePort ;
+ lv2:datatype lv2:float ;
+ lv2:index 1 ;
+ lv2:symbol "in" ;
+ lv2:name "in" ;
+ ] , [
+ a lv2:OutputAudioRatePort ;
+ lv2:datatype lv2:float ;
+ lv2:index 2 ;
+ lv2:symbol "out" ;
+ lv2:name "out" ;
+ ]
+.
+
diff --git a/examples/plugins/Amp-swh.lv2/manifest.ttl b/examples/plugins/Amp-swh.lv2/manifest.ttl
new file mode 100644
index 0000000..a26f506
--- /dev/null
+++ b/examples/plugins/Amp-swh.lv2/manifest.ttl
@@ -0,0 +1,9 @@
+# LV2 Plugin Manifest
+# Lists where plugins' data files and shared objects reside.
+
+@prefix lv2: <http://lv2plug.in/ontology#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://plugin.org.uk/swh-plugins/amp> lv2:binary <amp.so> ;
+ rdfs:seeAlso <amp.ttl> .
+
diff --git a/examples/plugins/Makefile.am b/examples/plugins/Makefile.am
new file mode 100644
index 0000000..8044bc9
--- /dev/null
+++ b/examples/plugins/Makefile.am
@@ -0,0 +1,24 @@
+#AM_CFLAGS = -I$(top_srcdir)/include
+#AM_LDFLAGS = -module -avoidversion -Wc,-nostartfiles
+#
+#plugindir = @umpdir@
+#
+#plugin_LTLIBRARIES = \
+# test_plugin.la
+#
+## Stolen from swh-plugins, makes stupid libtool versions go away
+#install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+# mkdir -p @umpdir@
+# list='$(plugin_LTLIBRARIES)'; \
+# for file in $$list; do \
+# sofile=`basename $$file .la`.so; \
+# $(INSTALL_PROGRAM) .libs/$$sofile @umpdir@; \
+# done
+#
+#uninstall-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+# list='$(plugin_LTLIBRARIES)'; \
+# for file in $$list; do \
+# sofile=`basename $$file .la`.so; \
+# rm -f @umpdir@/$$sofile; \
+# done
+#
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..a8d9fe0
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,3 @@
+lv2includedir = $(includedir)
+
+lv2include_HEADERS = lv2.h
diff --git a/include/lv2.h b/include/lv2.h
new file mode 100644
index 0000000..7c3cec7
--- /dev/null
+++ b/include/lv2.h
@@ -0,0 +1,305 @@
+/* LV2 - LADSPA (Linux Audio Developer's Simple Plugin API) Version 2.0
+ * *** PROVISIONAL ***
+ *
+ * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, Stefan
+ * Westerfeld
+ * Copyright (C) 2006 Steve Harris, Dave Robillard.
+ *
+ * This header is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License,
+ * or (at your option) any later version.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifndef LV2_INCLUDED
+#define LV2_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ************************************************************************* */
+
+/* Overview:
+ *
+ * There are a large number of open source and free software synthesis
+ * packages in use or development at this time. This API ('LV2')
+ * attempts to give programmers the ability to write simple 'plugin'
+ * audio processors in C/C++ and link them dynamically ('plug') into
+ * a range of these packages ('hosts'). It should be possible for any
+ * host and any plugin to communicate completely through this interface.
+ *
+ * This API is deliberately as short and simple as possible.
+ * The information required to use a plugin is in a companion data
+ * (RDF) file. The shared library portion of the API (defined in this
+ * header) does not contain enough information to make use of the plugin
+ * possible - the data file is mandatory.
+ *
+ * Plugins are expected to distinguish between control rate and audio
+ * rate data. Plugins have 'ports' that are inputs or outputs for audio
+ * or control data and each plugin is 'run' for a 'block' corresponding
+ * to a short time interval measured in samples. Audio rate data is
+ * communicated using arrays with one element per sample processed,
+ * allowing a block of audio to be processed by the plugin in a single
+ * pass. Control rate data is communicated using single values. Control
+ * rate data has a single value at the start of a call to the 'run()'
+ * function, and may be considered to remain this value for its duration.
+ * Thus the 'control rate' is determined by the block size, controlled
+ * by the host. The plugin may assume that all its input and output
+ * ports have been connected to the relevant data location (see the
+ * 'connect_port()' function below) before it is asked to run.
+ *
+ * Plugins will reside in shared object files suitable for dynamic linking
+ * by dlopen() and family. The file will provide a number of 'plugin
+ * types' that can be used to instantiate actual plugins (sometimes known
+ * as 'plugin instances') that can be connected together to perform tasks.
+ *
+ * This API contains very limited error-handling.
+ */
+
+/* ************************************************************************* */
+
+
+/** Plugin Handle.
+ *
+ * This plugin handle indicates a particular instance of the plugin
+ * concerned. It is valid to compare this to NULL (0 for C++) but
+ * otherwise the host MUST not attempt to interpret it. The plugin
+ * may use it to reference internal instance data. */
+typedef void * LV2_Handle;
+
+
+/* ************************************************************************* */
+
+/** Host feature.
+ *
+ * These are passed to a plugin's instantiate method to represent a special
+ * feature the host has which the plugin may depend on. This is to allow
+ * extensions to the LV2 specification without causing any breakage. The base
+ * LV2 specification does not define any host features; hosts are not required
+ * to use this facility.
+ */
+typedef struct _LV2_Host_Feature {
+ /** A globally unique, case-sensitive identifier for this feature.
+ *
+ * This MUST be defined in the specification of any LV2 extension which
+ * defines a host feature.
+ */
+ const char * URI;
+
+ /** Pointer to arbitrary data.
+ *
+ * This is to allow hosts to pass data to a plugin (simple values, data
+ * structures, function pointers, etc) as part of a 'feature'. The LV2
+ * specification makes no restrictions on the contents of this data.
+ * The data here MUST be cleary defined by the LV2 extension which defines
+ * this feature.
+ * If no data is required, this may be set to NULL.
+ */
+ void * data;
+} LV2_Host_Feature;
+
+
+/* ************************************************************************* */
+
+
+/** Descriptor for a Type of Plugin.
+ *
+ * This structure is used to describe a plugin type. It provides a number
+ * of functions to instantiate it, link it to buffers and run it. */
+typedef struct _LV2_Descriptor {
+
+ /** A globally unique, case-sensitive identifier for this plugin type.
+ *
+ * All plugins with the same URI MUST be compatible in terms of 'port
+ * signature', meaning they have the same number of ports, same port
+ * shortnames, and roughly the same functionality. URIs should
+ * probably contain a version number (or similar) for this reason.
+ *
+ * Rationale: When serializing session/patch/etc files, hosts MUST
+ * refer to a loaded plugin by the plugin URI only. In the future
+ * loading a plugin with this URI MUST yield a plugin with the
+ * same ports (etc) which is 100% compatible. */
+ const char * URI;
+
+ /** Function pointer that instantiates a plugin.
+ *
+ * A handle is returned indicating the new plugin instance. The
+ * instantiation function accepts a sample rate as a parameter as well
+ * as the plugin descriptor from which this instantiate function was
+ * found. This function must return NULL if instantiation fails.
+ *
+ * BundlePath is a string of the path to the plugin's .lv2 bundle
+ * directory, it MUST not include the trailing /.
+ *
+ * HostFeatures is a NULL terminated array of the URIs of the LV2
+ * features that the host supports. Plugins may refuse to instantiate
+ * if required features are not found here (however hosts SHOULD NOT use
+ * this as a discovery mechanism, instead reading the data file before
+ * attempting to instantiate the plugin).
+ *
+ * Note that instance initialisation should generally occur in
+ * activate() rather than here. If a host calls instantiate, it MUST
+ * call cleanup() at some point in the future. */
+ LV2_Handle (*instantiate)(const struct _LV2_Descriptor * Descriptor,
+ unsigned long SampleRate,
+ const char * BundlePath,
+ const LV2_Host_Feature** HostFeatures);
+
+ /** Function pointer that connects a port on a plugin instance to a memory
+ * location where the block of data for the port will be read/written.
+ *
+ * The data location is expected to be an array of void * (typically
+ * float *) for audio ports or a single void * value for control
+ * ports. Memory issues are managed by the host. The plugin must
+ * read/write the data at these locations every time run() is called
+ * and the data present at the time of this connection call MUST NOT
+ * be considered meaningful.
+ *
+ * connect_port() may be called more than once for a plugin instance
+ * to allow the host to change the buffers that the plugin is reading
+ * or writing. These calls may be made before or after activate()
+ * or deactivate() calls.
+ *
+ * connect_port() must be called at least once for each port before
+ * run() is called. The plugin must pay careful attention to the block
+ * size passed to the run function as the block allocated may only just
+ * be large enough to contain the block of data (typically samples), and
+ * is not guaranteed to be constant.
+ *
+ * Plugin writers should be aware that the host may elect to use the
+ * same buffer for more than one port and even use the same buffer for
+ * both input and output (see LV2_PROPERTY_INPLACE_BROKEN (FIXME)).
+ * However, overlapped buffers or use of a single buffer for both
+ * audio and control data may result in unexpected behaviour. */
+ void (*connect_port)(LV2_Handle Instance,
+ unsigned long Port,
+ void * DataLocation);
+
+ /** Function pointer that initialises a plugin instance and activates
+ * it for use.
+ *
+ * This is separated from instantiate() to aid real-time support and so
+ * that hosts can reinitialise a plugin instance by calling deactivate()
+ * and then activate(). In this case the plugin instance must reset all
+ * state information dependent on the history of the plugin instance
+ * except for any data locations provided by connect_port(). If there
+ * is nothing for activate() to do then the plugin writer may provide
+ * a NULL rather than an empty function.
+ *
+ * When present, hosts MUST call this function once before run()
+ * is called for the first time. This call SHOULD be made as close
+ * to the run() call as possible and indicates to real-time plugins
+ * that they are now live, however plugins MUST NOT rely on a prompt
+ * call to run() after activate(). activate() may not be called again
+ * unless deactivate() is called first (after which activate() may be
+ * called again, followed by deactivate, etc. etc.). If a host calls
+ * activate, it MUST call deactivate at some point in the future.
+ *
+ * Note that connect_port() may be called before or after a call to
+ * activate(). */
+ void (*activate)(LV2_Handle Instance);
+
+ /** Function pointer that runs a plugin instance for a block.
+ *
+ * Two parameters are required: the first is a handle to the particular
+ * instance to be run and the second indicates the block size (in
+ * samples) for which the plugin instance may run.
+ *
+ * Note that if an activate() function exists then it must be called
+ * before run(). If deactivate() is called for a plugin instance then
+ * the plugin instance may not be reused until activate() has been
+ * called again.
+ *
+ * If the plugin has the property LV2_PROPERTY_HARD_RT_CAPABLE then
+ * there are various things that the plugin MUST NOT do within the run()
+ * function (see above). */
+ void (*run)(LV2_Handle Instance,
+ unsigned long SampleCount);
+
+ /** This is the counterpart to activate() (see above). If there is
+ * nothing for deactivate() to do then the plugin writer may provide
+ * a NULL rather than an empty function.
+ *
+ * Hosts must deactivate all activated units after they have been run()
+ * for the last time. This call SHOULD be made as close to the last
+ * run() call as possible and indicates to real-time plugins that
+ * they are no longer live, however plugins MUST NOT rely on prompt
+ * deactivation. Note that connect_port() may be called before or
+ * after a call to deactivate().
+ *
+ * Note that deactivation is not similar to pausing as the plugin
+ * instance will be reinitialised when activate() is called to reuse it.
+ * Hosts MUST NOT call deactivate() unless activate() was previously
+ * called. */
+ void (*deactivate)(LV2_Handle Instance);
+
+ /** This is the counterpart to instantiate() (see above). Once an instance
+ * of a plugin has been finished with it can be deleted using this
+ * function. The instance handle passed ceases to be valid after
+ * this call.
+ *
+ * If activate() was called for a plugin instance then a corresponding
+ * call to deactivate() MUST be made before cleanup() is called.
+ * Hosts MUST NOT call cleanup() unless instantiate() was previously
+ * called. */
+ void (*cleanup)(LV2_Handle Instance);
+
+} LV2_Descriptor;
+
+
+/* ****************************************************************** */
+
+
+/** Accessing a Plugin:
+ *
+ * The exact mechanism by which plugins are loaded is host-dependent,
+ * however all most hosts will need to know is the URI of the plugin they
+ * wish to load. The environment variable LV2_PATH, if present, should
+ * contain a colon-separated path indicating directories (containing
+ * plugin bundle subdirectories) that should be searched (in order)
+ * for plugins. It is expected that hosts will use a library to provide
+ * this functionality.
+ *
+ * A plugin programmer must include a function called "lv2_descriptor"
+ * with the following function prototype within the shared object
+ * file. This function will have C-style linkage (if you are using
+ * C++ this is taken care of by the 'extern "C"' clause at the top of
+ * the file).
+ *
+ * A host will find the plugin shared object file by one means or another,
+ * find the lv2_descriptor() function, call it, and proceed from there.
+ *
+ * Plugin types are accessed by index (not ID) using values from 0
+ * upwards. Out of range indexes must result in this function returning
+ * NULL, so the plugin count can be determined by checking for the least
+ * index that results in NULL being returned. Index has no meaning,
+ * hosts MUST NOT depend on it remaining constant (ie when serialising)
+ * in any way. */
+const LV2_Descriptor * lv2_descriptor(unsigned long Index);
+
+
+/** Datatype corresponding to the lv2_descriptor() function. */
+typedef const LV2_Descriptor *
+(*LV2_Descriptor_Function)(unsigned long Index);
+
+
+/* ******************************************************************** */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LV2_INCLUDED */
diff --git a/include/lv2.ttl b/include/lv2.ttl
new file mode 100644
index 0000000..47b21ae
--- /dev/null
+++ b/include/lv2.ttl
@@ -0,0 +1,326 @@
+# RDF Schema file for LV2 plugins
+# *** PROVISIONAL ***
+#
+# This document describes the classes and properties that are defined by the
+# core LV2 specification.
+
+@prefix : <http://lv2plug.in/ontology#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+
+<> dc:creator "Steve Harris" ;
+ dc:date "2006-04-26" .
+
+#
+# Classes
+#
+
+:Plugin a rdfs:Class ;
+ rdfs:label "Plugin" ;
+ rdfs:comment """
+This is the class that represents an LV2 plugin.
+
+In order for it to be used by a host it must have at least one occurance of the
+following properties:
+ rdf:type (with object :Plugin)
+ doap:name (one without language tag)
+ doap:licence
+ lv2:port
+
+This can be determined by the following SPARQL query:
+
+PREFIX : <http://lv2plug.in/ontology#>
+PREFIX doap: <http://usefulinc.com/ns/doap#>
+SELECT DISTINCT ?uri WHERE {
+ ?uri a :Plugin ;
+ doap:name ?name ;
+ doap:licence ?rights ;
+ :port ?port .
+ FILTER( LANG(?name) = "" )
+}
+""" .
+
+:Port a rdfs:Class ;
+ rdfs:label "Port" ;
+ rdfs:comment """
+This is the class that represents an LV2 port
+
+In order for it to be used by a host it must have at least the following
+properties:
+ rdf:type (where object is exactly one of :InputControlRatePort,
+ :OutputControlRatePort, :InputAudioRatePort or :OututAudioRatePort)
+ :datatype
+ :index
+ :symbol
+ :name
+""" .
+
+:InputPort a rdfs:Class ;
+ rdfs:subClassOf :Port .
+
+:OutputPort a rdfs:Class ;
+ rdfs:subClassOf :Port .
+
+:ControlRatePort a rdfs:Class ;
+ rdfs:subClassOf :Port .
+
+:AudioRatePort a rdfs:Class ;
+ rdfs:subClassOf :Port .
+
+:InputControlRatePort a rdfs:Class ;
+ rdfs:label "Input control port" ;
+ rdfs:subClassOf :ControlRatePort ;
+ rdfs:subClassOf :InputPort ;
+ rdfs:comment """
+Ports of this type will be connected to a pointer to a single value of the type
+defined by the :datatype property.
+
+Plugins will read values from this pointer during thier run method.
+""" .
+
+:OutputControlRatePort a rdfs:Class ;
+ rdfs:label "Output control port" ;
+ rdfs:subClassOf :ControlRatePort ;
+ rdfs:subClassOf :OutputPort ;
+ rdfs:comment """
+Ports of this type will be connected to a pointer to a single value of the type
+defined by the :datatype property.
+
+Plugins will write values to this pointer during thier run method.
+""" .
+
+:InputAudioRatePort a rdfs:Class ;
+ rdfs:label "Input audio port" ;
+ rdfs:subClassOf :AudioRatePort ;
+ rdfs:subClassOf :InputPort ;
+ rdfs:comment """
+Ports of this type will be connected to a an array of values of length
+SampleCount and of the type defined by the :datatype property.
+
+Plugins will read values from this array during their run method.
+""" .
+
+:OutputAudioRatePort a rdfs:Class ;
+ rdfs:label "Output audio port" ;
+ rdfs:subClassOf :AudioRatePort ;
+ rdfs:subClassOf :OutputPort ;
+ rdfs:comment """
+Ports of this type will be connected to a an array of values of length
+SampleCount and of the type defined by the :datatype property.
+
+Plugins will write values to this array during their run method.
+""" .
+
+:ScalePoint a rdfs:Class ;
+ rdfs:label "Scale point" ;
+ rdfs:comment """
+Used to describe interesting values in a Port's range.
+
+It has two properties neccesary for use, :label and :value.
+""" .
+
+:Property a rdfs:Class ;
+ rdfs:label "Property" ;
+ rdfs:comment """
+Used to inform the host of the capabilities of the Plugin.
+""" .
+
+:Hint a rdfs:Class ;
+ rdfs:label "Hint" ;
+ rdfs:comment """
+Used to hint to the host various things which can make interacting with the
+Port more natural.
+""" .
+
+:HostFeature a rdfs:Class ;
+ rdfs:label "Host feature" ;
+ rdfs:comment """
+Used to describe a host feature which plugin may use or require.
+""" .
+
+
+#
+# Properties
+#
+
+:property a rdf:Property ;
+ rdfs:domain :Plugin ;
+ rdfs:range :Property ;
+ rdfs:label "property" ;
+ rdfs:comment "Relates Plugins to Properties." .
+
+:requiredHostFeature a rdf:Property ;
+ rdfs:domain :Plugin ;
+ rdfs:range :HostFeature ;
+ rdfs:label "Required host feature" ;
+ rdfs:comment """
+Signifies that plugin requires a certain host feature to function.
+The plugin will fail to instantiate if a required host feature is not present;
+hosts SHOULD always check this before attempting to instantiate a plugin.
+""" .
+
+:hint a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:range :Hint ;
+ rdfs:label "hint" ;
+ rdfs:comment "Relates Ports to Hints." .
+
+:datatype a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:range :Datatype ;
+ rdfs:label "datatype" ;
+ rdfs:comment """
+Relates a Port to the datatype(s) is can accept. Currently the only specified
+datatype is :float, which specfies IEEE-754 32bit floating point values.
+
+Hosts that do not support a specfied datatype MUST NOT instantiate the plugin.
+
+If multiple datatypes are specfied the plugin must have some way to distinguish
+the values.
+""" .
+
+# FIXME: rdfs:range = xsd:nonNegativeInteger?
+:index a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:label "index" ;
+ rdfs:comment """
+Specifies the index of the port, passed as an argument to the connect port
+function. This number uniqely identifies the port within the plugin.
+""" .
+
+# FIXME: rdfs:range = xsd:NCName? Closest thing xsd: has..
+:symbol a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:label "symbol" ;
+ rdfs:comment """
+A short name used to identify the port in an easily machine and human readable way.
+
+The first character must be one of _, a-z or A-Z and subsequenct characters can
+be from _, a-z, A-Z and 0-9.
+
+No language tag should be used on this property.
+""" .
+
+:name a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:label "name" ;
+ rdfs:comment """
+A display name for labeling the Port in a user interface.
+
+This property is required for Ports, but should not be used by the host for
+port identification. The plugin author may change the values of this
+property without changing the Plugin URI.
+""" .
+
+:default a rdf:Property ;
+ rdfs:domain :ControlRatePort ;
+ rdfs:label "default" ;
+ rdfs:comment """
+The default value that the host SHOULD set this port to when there is not other
+information available. Only meaningful for Ports with a :datatype of :float.
+""" .
+
+:minimum a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:label "minimum" ;
+ rdfs:comment """
+A hint to the host for the minimum useful value that the port will use. The
+plugin is required to accept all values in the range of :float.
+""" .
+
+:minimum a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:label "maximum" ;
+ rdfs:comment """
+A hint to the host for the maximum useful value that the port will use. The
+plugin is required to accept all values in the range of :float.
+""" .
+
+:scalePoint a rdf:Property ;
+ rdfs:domain :Port ;
+ rdfs:range :ScalePoint ;
+ rdfs:label "scale point" ;
+ rdfs:comment "Relates a Port to its ScalePoints." .
+
+
+#
+# Instances
+#
+
+:toggled a :Hint ;
+ rdfs:label "toggled" ;
+ rdfs:comment """
+Indicates that the data item should be considered a Boolean toggle. Data less
+than or equal to zero should be considered `off' or `false,' and data above
+zero should be considered `on' or `true.'
+""" .
+
+:sampleRate a :Hint ;
+ rdfs:label "sample rate" ;
+ rdfs:comment """
+Indicates that any bounds specified should be interpreted as multiples of the
+sample rate. For instance, a frequency range from 0Hz to the Nyquist frequency
+(half the sample rate) could be requested by this hint in conjunction with
+:minimum 0.0 and :maximum 0.5. Hosts that support bounds at all must support
+this hint to retain meaning.
+""" .
+
+:integer a :Hint ;
+ rdfs:label "integer" ;
+ rdfs:comment """
+Indicates that a user interface would probably wish to provide a stepped
+control taking only integer values.
+""" .
+
+:realtime a :Property ;
+ rdfs:label "realtime" ;
+ rdfs:comment """
+Indicates that the plugin has a real-time dependency (e.g. listens to a MIDI
+device) and so its output must not be cached or subject to significant latency.
+""" .
+
+:inplaceBroken a :Property ;
+ rdfs:label "in-place broken" ;
+ rdfs:comment """
+Indicates that the plugin may cease to work correctly if the host elects to use
+the same data location for both input and output (see connect_port()). This
+should be avoided as enabling this flag makes it impossible for hosts to use
+the plugin to process audio `in-place.'
+""" .
+
+:hardRtCapable a :Property ;
+ rdfs:label "hard realtime capable" ;
+ rdfs:comment """
+Indicates that the plugin is capable of running not only in a conventional host
+but also in a `hard real-time' environment. To qualify for this the plugin must
+satisfy all of the following:
+
+ (1) The plugin must not use malloc(), free() or other heap memory
+ management within its run() or run_adding() functions. All new
+ memory used in run() must be managed via the stack. These
+ restrictions only apply to the run() function.
+
+ (2) The plugin will not attempt to make use of any library
+ functions with the exceptions of functions in the ANSI standard C
+ and C maths libraries, which the host is expected to provide.
+
+ (3) The plugin will not access files, devices, pipes, sockets, IPC
+ or any other mechanism that might result in process or thread
+ blocking.
+
+ (4) The plugin will take an amount of time to execute a run() or
+ run_adding() call approximately of form (A+B*SampleCount) where A
+ and B depend on the machine and host in use. This amount of time
+ may not depend on input signals or plugin state. The host is left
+ the responsibility to perform timings to estimate upper bounds for
+ A and B.
+""" .
+
+# FIXME: = xsd:float?
+:float a :Datatype ;
+ rdfs:label "float" ;
+ rdfs:comment """
+Represents values conforming to the 32bit IEEE-754 floating point specification.
+""" .
+
diff --git a/libslv2.pc.in b/libslv2.pc.in
new file mode 100644
index 0000000..48b02d7
--- /dev/null
+++ b/libslv2.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libslv2
+Version: @VERSION@
+Description: Convenience library for hosts to simplify LV2 plugin support
+Libs: -L${libdir} -lslv2
+Cflags: -I${includedir}
diff --git a/slv2/Makefile.am b/slv2/Makefile.am
new file mode 100644
index 0000000..fafe21d
--- /dev/null
+++ b/slv2/Makefile.am
@@ -0,0 +1,11 @@
+slv2includedir = $(includedir)/slv2
+
+slv2include_HEADERS = \
+ types.h \
+ private_types.h \
+ slv2.h \
+ plugin.h \
+ query.h \
+ port.h \
+ pluginlist.h \
+ plugininstance.h
diff --git a/slv2/plugin.h b/slv2/plugin.h
new file mode 100644
index 0000000..6af04bc
--- /dev/null
+++ b/slv2/plugin.h
@@ -0,0 +1,168 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_PLUGIN_H__
+#define __SLV2_PLUGIN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "types.h"
+
+
+typedef const struct _Plugin SLV2Plugin;
+
+
+/** \defgroup data Plugin data file access
+ *
+ * These functions work exclusively with the plugin's RDF data file. They do
+ * not load the plugin dynamic library (or access
+ * it in any way).
+ *
+ * @{
+ */
+
+
+/** Check if this plugin is valid.
+ *
+ * This is used by plugin lists to avoid loading plugins that are not valid
+ * and will not work with libslv2 (eg plugins missing required fields, or
+ * having multiple values for mandatory single-valued fields, etc.
+ *
+ * Note that normal hosts do not need to worry about list - libslv2 does not
+ * load invalid plugins in to plugin lists. This is included for plugin
+ * testing utilities, etc.
+ *
+ * \return True if \a plugin is valid.
+ */
+bool
+slv2_plugin_verify(const SLV2Plugin* plugin);
+
+
+/** Duplicate a plugin.
+ *
+ * Use this if you want to keep an SLV2Plugin around but free the list it came
+ * from.
+ *
+ * \return a newly allocated SLV2Plugin identical to \a plugin (a deep copy).
+ */
+SLV2Plugin*
+slv2_plugin_duplicate(const SLV2Plugin* plugin);
+
+
+/** Get the URI of \a plugin.
+ *
+ * Any serialization that refers to plugins should refer to them by this.
+ * Hosts SHOULD NOT save any filesystem paths, plugin indexes, etc. in saved
+ * files; save only the URI.
+ *
+ * The URI is a globally unique identifier for one specific plugin. Two
+ * plugins with the same URI are compatible in port signature, and should
+ * be guaranteed to work in a compatible and consistent way. If a plugin
+ * is upgraded in an incompatible way (eg if it has different ports), it
+ * MUST have a different URI than it's predecessor.
+ *
+ * \return a shared string which must not be modified or free()'d.
+ */
+const unsigned char*
+slv2_plugin_get_uri(const SLV2Plugin* plugin);
+
+
+/** Get the URL of the RDF data file plugin information is located in.
+ *
+ * Only file: URL's are supported at this time.
+ *
+ * \return a complete URL eg. "file:///usr/foo/SomeBundle.lv2/someplug.ttl",
+ * which is shared and must not be modified or free()'d.
+ */
+const unsigned char*
+slv2_plugin_get_data_url(const SLV2Plugin* plugin);
+
+
+/** Get the local filesystem path of the RDF data file for \a plugin.
+ *
+ * \return a valid path on the local filesystem
+ * eg. "/usr/foo/SomeBundle.lv2/someplug.ttl" which is shared and must not
+ * be free()'d; or NULL if URL is not a local filesystem path.
+ */
+const unsigned char*
+slv2_plugin_get_data_path(const SLV2Plugin* plugin);
+
+
+/** Get the URL of the shared library for \a plugin.
+ *
+ * \return a shared string which must not be modified or free()'d.
+ */
+const unsigned char*
+slv2_plugin_get_library_url(const SLV2Plugin* plugin);
+
+
+/** Get the local filesystem path of the shared library for \a plugin.
+ *
+ * \return a valid path on the local filesystem
+ * eg. "/usr/foo/SomeBundle.lv2/someplug.so" which is shared and must not
+ * be free()'d; or NULL if URL is not a local filesystem path.
+ */
+const unsigned char*
+slv2_plugin_get_library_path(const SLV2Plugin* plugin);
+
+
+/** Get the name of \a plugin.
+ *
+ * This is guaranteed to return the untranslated name (the doap:name in the
+ * data file without a language tag). Returned value must be free()'d by
+ * the caller.
+ */
+unsigned char*
+slv2_plugin_get_name(const SLV2Plugin* plugin);
+
+
+/** Request some property of the plugin.
+ *
+ * May return NULL if the property was not found (ie is not defined in the
+ * data file).
+ *
+ * Return value must be free()'d by caller.
+ *
+ * Note that some properties may have multiple values. If the property is a
+ * string with multiple languages defined, the translation according to
+ * $LANG will be returned if it is set. Otherwise all values will be
+ * returned.
+ */
+SLV2Property
+slv2_plugin_get_property(const SLV2Plugin* p,
+ const char* property);
+
+
+/** Get the number of ports on this plugin.
+ */
+unsigned long
+slv2_plugin_get_num_ports(const SLV2Plugin* p);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PLUGIN_H__ */
+
diff --git a/slv2/plugininstance.h b/slv2/plugininstance.h
new file mode 100644
index 0000000..5fd9393
--- /dev/null
+++ b/slv2/plugininstance.h
@@ -0,0 +1,205 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_PLUGININSTANCE_H__
+#define __SLV2_PLUGININSTANCE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <lv2.h>
+#include <slv2/private_types.h>
+#include <slv2/plugininstance.h>
+#include <slv2/plugin.h>
+#include <slv2/port.h>
+
+
+typedef const struct _Instance SLV2Instance;
+
+
+/** \defgroup lib Plugin library access
+ *
+ * An SLV2Instance is an instantiated SLV2Plugin (eg a loaded dynamic
+ * library). These functions interact with the binary library code only,
+ * they do not read any RDF data files whatsoever.
+ *
+ * @{
+ */
+
+
+/** Instantiate a plugin.
+ *
+ * The returned object represents shared library objects loaded into memory,
+ * it must be cleaned up with slv2instance_free when no longer
+ * needed.
+ *
+ * \a plugin is not modified or directly referenced by the returned object
+ * (instances store only a copy of the plugin's URI).
+ *
+ * \return NULL if instantiation failed.
+ */
+SLV2Instance*
+slv2_plugin_instantiate(const SLV2Plugin* plugin,
+ unsigned long sample_rate,
+ const LV2_Host_Feature** host_features);
+
+
+/** Free a plugin instance.
+ *
+ * \a instance is invalid after this call.
+ */
+void
+slv2_instance_free(SLV2Instance* instance);
+
+
+#ifndef LIBSLV2_SOURCE
+
+
+/** Get the URI of the plugin which \a instance is an instance of.
+ *
+ * Returned string is shared and must not be modified or deleted.
+ */
+inline const char*
+slv2_instance_get_uri(SLV2Instance* instance)
+{
+ assert(instance);
+ assert(instance->descriptor);
+
+ return instance->descriptor->URI;
+}
+
+
+/** Connect a port to a data location.
+ *
+ * This may be called regardless of whether the plugin is activated,
+ * activation and deactivation does not destroy port connections.
+ */
+inline void
+slv2_instance_connect_port(SLV2Instance* instance,
+ unsigned long port_index,
+ void* data_location)
+{
+ assert(instance);
+ assert(instance->descriptor);
+ assert(instance->descriptor->connect_port);
+
+ instance->descriptor->connect_port
+ (instance->lv2_handle, port_index, data_location);
+}
+
+
+/** Activate a plugin instance.
+ *
+ * This resets all state information in the plugin, except for port data
+ * locations (as set by slv2instance_connect_port). This MUST be called
+ * before calling slv2instance_run.
+ */
+inline void
+slv2_instance_activate(SLV2Instance* instance)
+{
+ assert(instance);
+ assert(instance->descriptor);
+
+ if (instance->descriptor->activate)
+ instance->descriptor->activate(instance->lv2_handle);
+}
+
+
+/** Run \a instance for \a sample_count frames.
+ *
+ * If the hint lv2:realtimeSafe is set for this plugin, this function is
+ * guaranteed not to block.
+ */
+inline void
+slv2_instance_run(SLV2Instance* instance,
+ unsigned long sample_count)
+{
+ assert(instance);
+ assert(instance->descriptor);
+ assert(instance->lv2_handle),
+ assert(instance->descriptor->run);
+
+ instance->descriptor->run(instance->lv2_handle, sample_count);
+}
+
+
+/** Deactivate a plugin instance.
+ *
+ * Note that to run the plugin after this you must activate it, which will
+ * reset all state information (except port connections).
+ */
+inline void
+slv2_instance_deactivate(SLV2Instance* instance)
+{
+ assert(instance);
+ assert(instance->descriptor);
+ assert(instance->lv2_handle);
+
+ if (instance->descriptor->deactivate)
+ instance->descriptor->deactivate(instance->lv2_handle);
+}
+
+
+/** Get the LV2_Descriptor of the plugin instance.
+ *
+ * Normally hosts should not need to access the LV2_Descriptor directly,
+ * use the slv2instance_* functions.
+ *
+ * The returned descriptor is shared and must not be deleted.
+ */
+inline const LV2_Descriptor*
+slv2_instance_get_descriptor(SLV2Instance* instance)
+{
+ assert(instance);
+ assert(instance->descriptor);
+
+ return instance->descriptor;
+}
+
+
+/** Get the LV2_Handle of the plugin instance.
+ *
+ * Normally hosts should not need to access the LV2_Handle directly,
+ * use the slv2instance_* functions.
+ *
+ * The returned handle is shared and must not be deleted.
+ */
+inline LV2_Handle
+slv2_instance_get_handle(SLV2Instance* instance)
+{
+ assert(instance);
+ assert(instance->descriptor);
+
+ return instance->lv2_handle;
+}
+
+#endif /* LIBSLV2_SOURCE */
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __SLV2_PLUGININSTANCE_H__ */
+
diff --git a/slv2/pluginlist.h b/slv2/pluginlist.h
new file mode 100644
index 0000000..d29a56d
--- /dev/null
+++ b/slv2/pluginlist.h
@@ -0,0 +1,159 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_PLUGINLIST_H__
+#define __SLV2_PLUGINLIST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct _PluginList* SLV2List;
+
+
+/** \defgroup lists Plugin lists
+ *
+ * These functions are for locating plugins installed on the system.
+ *
+ * Normal hosts which just want to easily load plugins by URI are strongly
+ * recommended to simply find all installed plugins with
+ * \ref slv2_list_load_all rather than find and load bundles manually.
+ *
+ * Functions are provided for hosts that wish to access bundles explicitly and
+ * individually for some reason, as well as make custom lists of plugins from
+ * a selection of bundles. This is mostly intended for hosts which are
+ * tied to a specific (bundled with the application) bundle.
+ *
+ * @{
+ */
+
+
+/** Create a new, empty plugin list.
+ *
+ * Returned object must be freed with slv2_list_free.
+ */
+SLV2List
+slv2_list_new();
+
+
+/** Free a plugin list.
+ *
+ * Note that all plugins in the list (eg those returned by the get_plugin
+ * functions) will be deleted as well. It is expected that hosts will
+ * keep the plugin list allocated until they are done with their plugins.
+ * If you want to keep a plugin around, but free the list it came from, you
+ * will have to copy it with slv2_plugin_duplicate().
+ *
+ * \a list is invalid after this call (though it may be used again after a
+ * "list = slv2_list_new()")
+ */
+void
+slv2_list_free(SLV2List list);
+
+
+/** Add all plugins installed on the system to \a list.
+ *
+ * This is the recommended way for hosts to access plugins. It finds all
+ * plugins on the system using the recommended mechanism. At the time, this
+ * is by searching the path defined in the environment variable LADSPA2_PATH,
+ * though this is subject to change in the future. Future versions may, for
+ * example, allow users to specify a plugin whitelist of plugins they would
+ * like to be visible in apps (or conversely a blacklist of plugins they do
+ * not wish to use).
+ *
+ * Use of any of the other functions for locating plugins is highly
+ * discouraged without specific reason to do so. Use this one.
+ */
+void
+slv2_list_load_all(SLV2List list);
+
+
+/** Add all plugins found in \a search_path to \a list.
+ *
+ * If \a search_path is NULL, \a list will be unmodified.
+ *
+ * Use of this function is not recommended. Use \ref slv2_list_load_all.
+ *
+ * Returned value must be cleaned up by slv2list_free.
+ */
+void
+slv2_list_load_path(SLV2List list,
+ const char* search_path);
+
+
+/** Add all plugins found in the bundle at \a bundle_base_url to \a list.
+ *
+ * \arg bundle_base_url is a fully qualified path to the bundle directory, eg.
+ * "file:///usr/lib/lv2/someBundle"
+ *
+ * Use of this function is <b>strongly</b> discouraged, hosts should not attach
+ * any significance to bundle paths as there are no guarantees they will
+ * remain consistent whatsoever. This function should only be used by apps
+ * which ship with a special bundle (which it knows exists at some path).
+ * It is <b>not</b> to be used by normal hosts that want to load system
+ * installed plugins. Use \ref slv2_list_load_all.
+ */
+void
+slv2_list_load_bundle(SLV2List list,
+ const unsigned char* bundle_base_url);
+
+
+/** Get the number of plugins in the list.
+ */
+unsigned long
+slv2_list_get_length(const SLV2List list);
+
+
+/** Get a plugin from the list by URI.
+ *
+ * Return value is shared (stored in \a list) and must not be freed or
+ * modified by the caller in any way.
+ *
+ * \return NULL if plugin with \a url not found in \a list.
+ */
+const SLV2Plugin*
+slv2_list_get_plugin_by_uri(const SLV2List list,
+ const unsigned char* uri);
+
+
+/** Get a plugin from the list by index.
+ *
+ * \a index has no significance. Any \a index not less than
+ * slv2list_get_length(list) will return NULL. * All plugins in a list can
+ * thus be easily enumerated by repeated calls to this function starting
+ * with \a index 0.
+ *
+ * Return value is shared (stored in \a list) and must not be freed or
+ * modified by the caller in any way.
+ *
+ * \return NULL if \a index out of range.
+ */
+const SLV2Plugin*
+slv2_list_get_plugin_by_index(const SLV2List list,
+ unsigned long index);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PLUGINLIST_H__ */
+
diff --git a/slv2/port.h b/slv2/port.h
new file mode 100644
index 0000000..749ea4e
--- /dev/null
+++ b/slv2/port.h
@@ -0,0 +1,116 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_PORT_H__
+#define __SLV2_PORT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "types.h"
+#include "plugin.h"
+
+/** \addtogroup data
+ * @{
+ */
+
+
+/** A port on a plugin.
+ *
+ * The information necessary to use the port is stored here, any extra
+ * information can be queried with slv2port_get_property.
+ */
+/*struct LV2Port {
+ unsigned long index; ///< Index in ports array
+ char* short_name; ///< Guaranteed unique identifier
+ char* type; ///< eg. lv2:InputControlPort
+ char* data_type; ///< eg. lv2:float
+};*/
+
+
+/** Get a property of a port, by port index.
+ *
+ * Return value must be free()'d by caller.
+ */
+SLV2Property
+slv2_port_get_property(SLV2Plugin* plugin,
+ unsigned long index,
+ const uchar* property);
+
+
+/** Get the symbol of a port given the index.
+ *
+ * The 'symbol' is a short string, a valid C identifier.
+ * Returned string must be free()'d by caller.
+ *
+ * \return NULL when index is out of range
+ */
+uchar*
+slv2_port_get_symbol(SLV2Plugin* plugin,
+ unsigned long index);
+
+
+/** Get the class (direction and rate) of a port.
+ */
+enum SLV2PortClass
+slv2_port_get_class(SLV2Plugin* plugin,
+ unsigned long index);
+
+
+/** Get the data type of a port.
+ */
+enum SLV2DataType
+slv2_port_get_data_type(SLV2Plugin* plugin,
+ unsigned long index);
+
+
+/** Get the default value of a port.
+ *
+ * Only valid for ports with a data type of lv2:float.
+ */
+float
+slv2_port_get_default_value(SLV2Plugin* plugin,
+ unsigned long index);
+
+
+/** Get the minimum value of a port.
+ *
+ * Only valid for ports with a data type of lv2:float.
+ */
+float
+slv2_port_get_minimum_value(SLV2Plugin* plugin,
+ unsigned long index);
+
+
+/** Get the maximum value of a port.
+ *
+ * Only valid for ports with a data type of lv2:float.
+ */
+float
+slv2_port_get_maximum_value(SLV2Plugin* plugin,
+ unsigned long index);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PORT_H__ */
diff --git a/slv2/private_types.h b/slv2/private_types.h
new file mode 100644
index 0000000..849e5a2
--- /dev/null
+++ b/slv2/private_types.h
@@ -0,0 +1,65 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_PRIVATE_TYPES_H__
+#define __SLV2_PRIVATE_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <lv2.h>
+
+
+/** Record of an installed/available plugin.
+ *
+ * A simple reference to a plugin somewhere on the system. This just holds
+ * paths of relevant files, the actual data therein isn't loaded into memory.
+ */
+struct _Plugin {
+ unsigned char* plugin_uri;
+ unsigned char* bundle_url; // Bundle directory plugin was loaded from
+ unsigned char* data_url; // rdfs::seeAlso
+ unsigned char* lib_url; // lv2:binary
+};
+
+
+/** Instance of a plugin (private type) */
+struct _Instance {
+ // FIXME: copy plugin here for convenience?
+ //struct LV2Plugin* plugin;
+ const LV2_Descriptor* descriptor;
+ void* lib_handle;
+ LV2_Handle lv2_handle;
+};
+
+
+/** List of references to plugins available for loading (private type) */
+struct _PluginList {
+ size_t num_plugins;
+ struct _Plugin** plugins;
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PRIVATE_TYPES_H__ */
+
diff --git a/slv2/query.h b/slv2/query.h
new file mode 100644
index 0000000..f1708d7
--- /dev/null
+++ b/slv2/query.h
@@ -0,0 +1,102 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_QUERY_H__
+#define __SLV2_QUERY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rasqal.h>
+#include "plugin.h"
+#include "types.h"
+
+/** \defgroup query SPARQL query helpers
+ *
+ * This part is in progress, incomplete, a random mishmash of crap that
+ * evolved along with my understanding of this rasqal library. Nothing
+ * to see here, move long now. Nothing to see here.
+ *
+ * Eventually this will contain functions that make it convenient for host
+ * authors to query plugins in ways libslv2 doesn't nicely wrap (eg. for
+ * extensions not (yet) supported by libslv2).
+ *
+ * @{
+ */
+
+/** Return a header for a SPARQL query on the given plugin.
+ *
+ * The returned header defines the namespace prefixes used in the standard
+ * (rdf: rdfs: doap: lv2:), plugin: as the plugin's URI, and data: as the
+ * URL of the plugin's RDF (Turtle) data file.
+ *
+ * Example query to get a plugin's doap:name using this header:
+ *
+ * <code>
+ * SELECT DISTINCT ?value FROM data: WHERE {
+ * plugin: doap:name ?value
+ * }
+ * </code>
+ *
+ * \return an unsigned (UTF-8) string which must be free()'d.
+ */
+unsigned char*
+slv2_query_header(const SLV2Plugin* p);
+
+
+/** Return a language filter for the given variable.
+ *
+ * If the environment variable $LANG is not set, returns NULL.
+ *
+ * \arg variable SPARQL variable, including "?" or "$" (eg "?value").
+ *
+ * This needs to be put inside the WHERE block, after the triples.
+ *
+ * eg. FILTER( LANG(?value) = "en" || LANG(?value) = "" )
+ */
+unsigned char*
+slv2_query_lang_filter(const uchar* variable);
+
+
+/** Run a SPARQL query on a plugin's data file.
+ *
+ * String arguments will be concatenated, allowing for variable substitution
+ * etc. (without having to define a token syntax and search the string for
+ * tokens, which would be slow).
+ *
+ * Header from slv2query_header will be prepended to passed query string.
+ * rasqal_init() must be called by the caller before calling this function.
+ */
+rasqal_query_results*
+slv2_plugin_run_query(const SLV2Plugin* p,
+ const uchar* query_string, ...);
+
+
+SLV2Property
+slv2_query_get_results(rasqal_query_results* results);
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_QUERY_H__ */
+
diff --git a/slv2/slv2.h b/slv2/slv2.h
new file mode 100644
index 0000000..6305f23
--- /dev/null
+++ b/slv2/slv2.h
@@ -0,0 +1,36 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_H
+#define __SLV2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <slv2/types.h>
+#include <slv2/plugin.h>
+#include <slv2/plugininstance.h>
+#include <slv2/pluginlist.h>
+#include <slv2/port.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_H */
diff --git a/slv2/types.h b/slv2/types.h
new file mode 100644
index 0000000..b6d71cc
--- /dev/null
+++ b/slv2/types.h
@@ -0,0 +1,66 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SLV2_TYPES_H__
+#define __SLV2_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+
+typedef unsigned char uchar;
+
+
+/* A property, resulting from a query.
+ *
+ * Note that properties may have many values.
+ */
+struct _Property {
+ size_t num_values;
+ unsigned char** values;
+};
+
+typedef struct _Property* SLV2Property;
+
+
+/** Class (direction and rate) of a port */
+enum SLV2PortClass {
+ SLV2_UNKNOWN_PORT_CLASS,
+ SLV2_CONTROL_RATE_INPUT, /**< One input value per block */
+ SLV2_CONTROL_RATE_OUTPUT, /**< One output value per block */
+ SLV2_AUDIO_RATE_INPUT, /**< One input value per frame */
+ SLV2_AUDIO_RATE_OUTPUT /**< One output value per frame */
+};
+
+
+/** Type contained in a port buffer. */
+enum SLV2DataType {
+ SLV2_DATA_TYPE_FLOAT, /**< IEEE-754 32-bit floating point number */
+ SLV2_UNKNOWN_DATA_TYPE
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_TYPES_H__ */
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..5f6cea2
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,14 @@
+AM_CFLAGS = -std=c99 -I$(top_srcdir)/include -I$(top_srcdir) @RASQAL_CFLAGS@ -DLIBSLV2_SOURCE
+AM_LDFLAGS = `pkg-config --libs rasqal`
+
+lib_LTLIBRARIES = libslv2.la
+libslv2_la_LIBADD = @RASQAL_LIBS@
+
+libslv2_la_SOURCES = \
+ util.h \
+ plugin.c \
+ query.c \
+ port.c \
+ pluginlist.c \
+ util.c \
+ plugininstance.c
diff --git a/src/plugin.c b/src/plugin.c
new file mode 100644
index 0000000..27fb481
--- /dev/null
+++ b/src/plugin.c
@@ -0,0 +1,190 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <rasqal.h>
+#include <slv2/private_types.h>
+#include <slv2/plugin.h>
+#include <slv2/types.h>
+#include <slv2/query.h>
+#include "util.h"
+
+
+SLV2Plugin*
+slv2_plugin_duplicate(const SLV2Plugin* p)
+{
+ assert(p);
+ struct _Plugin* result = malloc(sizeof(struct _Plugin));
+ result->plugin_uri = p->plugin_uri;
+ result->bundle_url = p->bundle_url;
+ result->data_url = p->data_url;
+ result->lib_url = p->lib_url;
+ return result;
+}
+
+
+const unsigned char*
+slv2_plugin_get_uri(const SLV2Plugin* p)
+{
+ assert(p);
+ return p->plugin_uri;
+}
+
+
+const unsigned char*
+slv2_plugin_get_data_url(const SLV2Plugin* p)
+{
+ assert(p);
+ return p->data_url;
+}
+
+
+const unsigned char*
+slv2_plugin_get_data_path(const SLV2Plugin* p)
+{
+ assert(p);
+ if (!strncmp((char*)p->data_url, "file://", 7))
+ return (p->data_url) + 7;
+ else
+ return NULL;
+}
+
+
+const unsigned char*
+slv2_plugin_get_library_url(const SLV2Plugin* p)
+{
+ assert(p);
+ return p->lib_url;
+}
+
+
+const unsigned char*
+slv2_plugin_get_library_path(const SLV2Plugin* p)
+{
+ assert(p);
+ if (!strncmp((char*)p->lib_url, "file://", 7))
+ return (p->lib_url) + 7;
+ else
+ return NULL;
+}
+
+
+bool
+slv2_plugin_verify(const SLV2Plugin* plugin)
+{
+ // FIXME: finish this (properly)
+ /*
+ size_t num_values = 0;
+
+ struct SLV2Property* prop = slv2_plugin_get_property(plugin, "doap:name");
+ if (prop) {
+ num_values = prop->num_values;
+ free(prop);
+ }
+ if (num_values < 1)
+ return false;
+
+ prop = slv2_plugin_get_property(plugin, "doap:license");
+ num_values = prop->num_values;
+ free(prop);
+ if (num_values < 1)
+ return false;
+*/
+ return true;
+}
+
+
+unsigned char*
+slv2_plugin_get_name(const SLV2Plugin* plugin)
+{
+// FIXME: leak
+ unsigned char* result = NULL;
+ struct _Property* prop = slv2_plugin_get_property(plugin, "doap:name");
+
+ // FIXME: guaranteed to be the untagged one?
+ if (prop && prop->num_values >= 1)
+ result = prop->values[0];
+
+ return result;
+}
+
+
+SLV2Property
+slv2_plugin_get_property(const SLV2Plugin* p,
+ const char* property)
+{
+ assert(p);
+ assert(property);
+
+ /*
+ uchar* header = slv2_query_header(p);
+ uchar* lang_filter = slv2_query_lang_filter(U("?value"));
+
+ uchar* query_string = ustrjoin(
+ header,
+ U("SELECT DISTINCT ?value FROM data: WHERE { \n"),
+ U("plugin: "), property, U(" ?value . \n"),
+ ((lang_filter != NULL) ? lang_filter : U("")),
+ "}", 0);
+
+ free(header);
+ free(lang_filter);*/
+
+ rasqal_init();
+
+ rasqal_query_results* results = slv2_plugin_run_query(p,
+ U("SELECT DISTINCT ?value FROM data: WHERE { \n"
+ "plugin: "), property, U(" ?value . \n"
+ "} \n"), 0);
+
+ struct _Property* result = slv2_query_get_results(results);
+
+ //free(query_string);
+ rasqal_free_query_results(results);
+ rasqal_finish();
+
+ return result;
+}
+
+
+unsigned long
+slv2_plugin_get_num_ports(const SLV2Plugin* p)
+{
+ unsigned long result = 0;
+
+ rasqal_init();
+
+
+ rasqal_query_results* results = slv2_plugin_run_query(p,
+ U("SELECT DISTINCT ?value FROM data: WHERE { \n"
+ "plugin: lv2:port ?value . \n"
+ "} \n"), 0);
+
+ while (!rasqal_query_results_finished(results)) {
+ ++result;
+ rasqal_query_results_next(results);
+ }
+
+ rasqal_free_query_results(results);
+ rasqal_finish();
+
+ return result;
+}
+
diff --git a/src/plugininstance.c b/src/plugininstance.c
new file mode 100644
index 0000000..40de08c
--- /dev/null
+++ b/src/plugininstance.c
@@ -0,0 +1,100 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <slv2/private_types.h>
+#include <slv2/types.h>
+#include <slv2/plugin.h>
+#include <slv2/plugininstance.h>
+#include "util.h"
+
+
+SLV2Instance*
+slv2_plugin_instantiate(const SLV2Plugin* plugin,
+ unsigned long sample_rate,
+ const LV2_Host_Feature** host_features)
+{
+ struct _Instance* result = NULL;
+
+ const unsigned char* const lib_path = slv2_plugin_get_library_path(plugin);
+ if (!lib_path)
+ return NULL;
+
+ void* lib = dlopen((char*)lib_path, RTLD_NOW);
+ if (!lib) {
+ printf("Unable to open library %s\n", lib_path);
+ return NULL;
+ }
+
+ LV2_Descriptor_Function df = dlsym(lib, "lv2_descriptor");
+
+ if (!df) {
+ printf("Could not find symbol 'lv2_descriptor', "
+ "%s is not a LV2 plugin.\n", lib_path);
+ dlclose(lib);
+ return NULL;
+ } else {
+ // Search for plugin by URI
+
+ const char* const bundle_path = url2path(plugin->bundle_url);
+
+ for (unsigned long i=0; 1; ++i) {
+ const LV2_Descriptor* ld = df(i);
+
+ if (!ld) {
+ printf("Did not find plugin %s in %s\n",
+ plugin->plugin_uri, plugin->lib_url);
+ dlclose(lib);
+ break; // return NULL
+ } else if (!strcmp(ld->URI, (char*)plugin->plugin_uri)) {
+ //printf("Found %s at index %ld in:\n\t%s\n\n", plugin->plugin_uri, i, lib_path);
+
+ assert(ld->instantiate);
+
+ // Create SLV2Instance to return
+ result = malloc(sizeof(struct _Instance));
+ /*result->plugin = malloc(sizeof(struct _Plugin));
+ memcpy(result->plugin, plugin, sizeof(struct _Plugin));*/
+ result->descriptor = ld;
+ result->lib_handle = lib;
+ result->lv2_handle = ld->instantiate(ld, sample_rate, (char*)bundle_path, host_features);
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+void
+slv2_instance_free(SLV2Instance* instance)
+{
+ struct _Instance* i = (struct _Instance*)instance;
+ i->descriptor->cleanup(i->lv2_handle);
+ i->descriptor = NULL;
+ dlclose(i->lib_handle);
+ i->lib_handle = NULL;
+ free(i);
+}
+
+
diff --git a/src/pluginlist.c b/src/pluginlist.c
new file mode 100644
index 0000000..61e4c4b
--- /dev/null
+++ b/src/pluginlist.c
@@ -0,0 +1,243 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _XOPEN_SOURCE 500
+#include <rasqal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <dirent.h>
+#include <slv2/private_types.h>
+#include <slv2/types.h>
+#include <slv2/plugin.h>
+#include <slv2/pluginlist.h>
+#include "util.h"
+
+
+struct _PluginList*
+slv2_list_new()
+{
+ struct _PluginList* result = malloc(sizeof(struct _PluginList));
+ result->num_plugins = 0;
+ result->plugins = NULL;
+ return result;
+}
+
+
+void
+slv2_list_free(SLV2List list)
+{
+ list->num_plugins = 0;
+ free(list->plugins);
+ free(list);
+}
+
+
+void
+slv2_list_load_all(SLV2List list)
+{
+ assert(list != NULL);
+
+ char* slv2_path = getenv("LV2_PATH");
+
+ if (!slv2_path) {
+ slv2_path = "~/.lv2:/usr/local/lib/lv2:usr/lib/lv2";
+
+ printf("$LV2_PATH is unset. Using default path %s\n",
+ slv2_path);
+ }
+
+ slv2_list_load_path(list, slv2_path);
+}
+
+
+/* This is the parser for manifest.ttl */
+void
+slv2_list_load_bundle(SLV2List list,
+ const unsigned char* bundle_base_uri)
+{
+ // FIXME: ew
+ unsigned char* manifest_uri = malloc(
+ (strlen((char*)bundle_base_uri) + strlen("manifest.ttl") + 2) * sizeof(unsigned char));
+ memcpy(manifest_uri, bundle_base_uri, strlen((char*)bundle_base_uri)+1 * sizeof(unsigned char));
+ if (bundle_base_uri[strlen((char*)bundle_base_uri)-1] == '/')
+ strcat((char*)manifest_uri, (char*)"manifest.ttl");
+ else
+ strcat((char*)manifest_uri, (char*)"/manifest.ttl");
+
+ rasqal_init();
+ rasqal_query_results *results;
+ raptor_uri *base_uri = raptor_new_uri(manifest_uri);
+ rasqal_query *rq = rasqal_new_query((const char*)"sparql", (const uchar*)base_uri);
+
+ unsigned char* query_string =
+ U("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+ "PREFIX : <http://lv2plug.in/ontology#> \n\n"
+
+ "SELECT DISTINCT $plugin_uri $data_url $lib_url FROM <> WHERE { \n"
+ "$plugin_uri :binary $lib_url ; \n"
+ " rdfs:seeAlso $data_url . \n"
+ "} \n");
+
+ //printf("%s\n\n", query_string);
+
+ rasqal_query_prepare(rq, (const uchar*)query_string, base_uri);
+ results = rasqal_query_execute(rq);
+
+ while (!rasqal_query_results_finished(results)) {
+
+ // Create a new plugin
+ struct _Plugin* new_plugin = malloc(sizeof(struct _Plugin));
+ new_plugin->bundle_url = ustrdup(bundle_base_uri);
+
+ rasqal_literal* literal = NULL;
+
+ literal = rasqal_query_results_get_binding_value_by_name(results,
+ U("plugin_uri"));
+ if (literal)
+ new_plugin->plugin_uri = ustrdup(rasqal_literal_as_string(literal));
+
+ literal = rasqal_query_results_get_binding_value_by_name(results,
+ U("data_url"));
+ if (literal)
+ new_plugin->data_url = ustrdup(rasqal_literal_as_string(literal));
+
+ literal = rasqal_query_results_get_binding_value_by_name(results,
+ U("lib_url"));
+ if (literal)
+ new_plugin->lib_url = ustrdup(rasqal_literal_as_string(literal));
+
+ /* Add the plugin if it's valid */
+ if (new_plugin->lib_url && new_plugin->data_url && new_plugin->plugin_uri
+ && slv2_plugin_verify(new_plugin)) {
+ /* Yes, this is disgusting, but it doesn't seem there's a way to know
+ * how many matches there are before iterating over them */
+ list->num_plugins++;
+ list->plugins = realloc(list->plugins,
+ list->num_plugins * sizeof(struct _Plugin*));
+ list->plugins[list->num_plugins-1] = new_plugin;
+ }
+
+ rasqal_query_results_next(results);
+ }
+
+ rasqal_free_query_results(results);
+ rasqal_free_query(rq);
+ raptor_free_uri(base_uri);
+ rasqal_finish();
+
+ free(manifest_uri);
+}
+
+
+/* Add all the plugins found in dir to list.
+ * (Private helper function, not exposed in public API)
+ */
+void
+add_plugins_from_dir(SLV2List list, const char* dir)
+{
+ DIR* pdir = opendir(dir);
+ if (!pdir)
+ return;
+
+ struct dirent* pfile;
+ while ((pfile = readdir(pdir))) {
+ if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, ".."))
+ continue;
+
+ char* bundle_path = (char*)ustrjoin(U(dir), U("/"), U(pfile->d_name), 0);
+ char* bundle_url = (char*)ustrjoin(U("file://"), U(dir), U("/"), U(pfile->d_name), 0);
+ DIR* bundle_dir = opendir(bundle_path);
+
+ if (bundle_dir != NULL) {
+ closedir(bundle_dir);
+
+ slv2_list_load_bundle(list, U(bundle_url));
+ //printf("Loaded bundle %s\n", bundle_url);
+ }
+
+ free(bundle_path);
+ }
+
+ closedir(pdir);
+}
+
+
+void
+slv2_list_load_path(SLV2List list,
+ const char* slv2_path)
+{
+
+ char* path = (char*)ustrjoin(U(slv2_path), U(":"), 0);
+
+ char* dir = path; // Pointer into path
+
+ // Go through string replacing ':' with '\0', using the substring,
+ // then replacing it with 'X' and moving on. eg strtok on crack.
+ while (strchr(path, ':') != NULL) {
+ char* delim = strchr(path, ':');
+ *delim = '\0';
+
+ add_plugins_from_dir(list, dir);
+
+ *delim = 'X';
+ dir = delim + 1;
+ }
+
+ //char* slv2_path = strdup(slv2
+
+ free(path);
+}
+
+
+unsigned long
+slv2_list_get_length(const SLV2List list)
+{
+ assert(list != NULL);
+ return list->num_plugins;
+}
+
+
+SLV2Plugin*
+slv2_list_get_plugin_by_uri(const SLV2List list, const unsigned char* uri)
+{
+ if (list->num_plugins > 0) {
+ assert(list->plugins != NULL);
+
+ for (unsigned long i=0; i < list->num_plugins; ++i)
+ if (!strcmp((char*)list->plugins[i]->plugin_uri, (char*)uri))
+ return list->plugins[i];
+ }
+
+ return NULL;
+}
+
+
+SLV2Plugin*
+slv2_list_get_plugin_by_index(const SLV2List list, unsigned long index)
+{
+ if (list->num_plugins == 0)
+ return NULL;
+
+ assert(list->plugins != NULL);
+
+ return (index < list->num_plugins) ? list->plugins[index] : NULL;
+}
+
diff --git a/src/port.c b/src/port.c
new file mode 100644
index 0000000..e25eb2f
--- /dev/null
+++ b/src/port.c
@@ -0,0 +1,163 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _XOPEN_SOURCE 500
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <slv2/port.h>
+#include <slv2/types.h>
+#include <slv2/query.h>
+#include "util.h"
+
+enum SLV2PortClass
+slv2_port_get_class(SLV2Plugin* p,
+ unsigned long index)
+{
+ struct _Property* class = slv2_port_get_property(p, index, U("rdf:type"));
+ assert(class);
+ assert(class->num_values == 1);
+ assert(class->values);
+
+ if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#InputControlRatePort"))
+ return SLV2_CONTROL_RATE_INPUT;
+ else if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#OutputControlRatePort"))
+ return SLV2_CONTROL_RATE_OUTPUT;
+ else if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#InputAudioRatePort"))
+ return SLV2_AUDIO_RATE_INPUT;
+ else if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#OutputAudioRatePort"))
+ return SLV2_AUDIO_RATE_OUTPUT;
+ else
+ return SLV2_UNKNOWN_PORT_CLASS;
+}
+
+
+enum SLV2DataType
+slv2_port_get_data_type(SLV2Plugin* p,
+ unsigned long index)
+{
+ SLV2Property type = slv2_port_get_property(p, index, U("lv2:datatype"));
+ assert(type);
+ assert(type->num_values == 1);
+ assert(type->values);
+
+ if (!strcmp((char*)type->values[0], "http://lv2plug.in/ontology#float"))
+ return SLV2_DATA_TYPE_FLOAT;
+ else
+ return SLV2_UNKNOWN_DATA_TYPE;
+}
+
+
+SLV2Property
+slv2_port_get_property(SLV2Plugin* p,
+ unsigned long index,
+ const uchar* property)
+{
+ assert(p);
+ assert(property);
+
+ char index_str[4];
+ snprintf(index_str, 4, "%ld", index);
+
+ rasqal_init();
+
+ rasqal_query_results* results = slv2_plugin_run_query(p,
+ U("SELECT DISTINCT ?value FROM data: WHERE { \n"
+ "plugin: lv2:port ?port \n"
+ "?port lv2:index "), index_str, U(" \n"
+ "?port "), property, U(" ?value . \n}\n"), 0);
+
+ SLV2Property result = slv2_query_get_results(results);
+
+ rasqal_free_query_results(results);
+ rasqal_finish();
+
+ return result;
+}
+
+
+uchar*
+slv2_port_get_symbol(SLV2Plugin* p, unsigned long index)
+{
+ // FIXME: leaks
+ uchar* result = NULL;
+
+ SLV2Property prop
+ = slv2_port_get_property(p, index, U("lv2:symbol"));
+
+ if (prop && prop->num_values == 1)
+ result = (uchar*)strdup((char*)prop->values[0]);
+ free(prop);
+
+ return result;
+}
+
+
+float
+slv2_port_get_default_value(SLV2Plugin* p,
+ unsigned long index)
+{
+ // FIXME: do casting properly in the SPARQL query
+
+ float result = 0.0f;
+
+ SLV2Property prop
+ = slv2_port_get_property(p, index, U("lv2:default"));
+
+ if (prop && prop->num_values == 1)
+ result = atof((char*)prop->values[0]);
+
+ return result;
+}
+
+
+float
+slv2_port_get_minimum_value(SLV2Plugin* p,
+ unsigned long index)
+{
+ // FIXME: do casting properly in the SPARQL query
+
+ float result = 0.0f;
+
+ SLV2Property prop
+ = slv2_port_get_property(p, index, U("lv2:minimum"));
+
+ if (prop && prop->num_values == 1)
+ result = atof((char*)prop->values[0]);
+
+ return result;
+}
+
+
+float
+slv2_port_get_maximum_value(SLV2Plugin* p,
+ unsigned long index)
+{
+ // FIXME: do casting properly in the SPARQL query
+
+ float result = 0.0f;
+
+ SLV2Property prop
+ = slv2_port_get_property(p, index, U("lv2:maximum"));
+
+ if (prop && prop->num_values == 1)
+ result = atof((char*)prop->values[0]);
+
+ return result;
+}
+
diff --git a/src/query.c b/src/query.c
new file mode 100644
index 0000000..2030735
--- /dev/null
+++ b/src/query.c
@@ -0,0 +1,123 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <util.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <slv2/plugin.h>
+#include <slv2/query.h>
+
+
+unsigned char*
+slv2_query_header(const SLV2Plugin* p)
+{
+ const unsigned char* plugin_uri = slv2_plugin_get_uri(p);
+ const unsigned char* data_file_url = slv2_plugin_get_data_url(p);
+
+ unsigned char* query_string = ustrjoin(U(
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+ "PREFIX doap: <http://usefulinc.com/ns/doap#> \n"
+ "PREFIX lv2: <http://lv2plug.in/ontology#> \n"
+ "PREFIX plugin: <"), plugin_uri, U("> \n"),
+ U("PREFIX data: <"), data_file_url, U("> \n\n"), 0);
+
+ return query_string;
+}
+
+
+unsigned char*
+slv2_query_lang_filter(const uchar* variable)
+{
+ uchar* result = NULL;
+ uchar* const lang = (uchar*)getenv("LANG");
+ if (lang) {
+ // FILTER( LANG(?value) = "en" || LANG(?value) = "" )
+ result = ustrjoin(
+ //U("FILTER (lang(?value) = \""), lang, U("\")\n"), 0);
+ U("FILTER( lang(?value) = \""), lang,
+ U("\" || lang(?value) = \"\" )\n"), 0);
+ }
+
+ return result;
+}
+
+
+rasqal_query_results*
+slv2_plugin_run_query(const SLV2Plugin* p,
+ const uchar* first, ...)
+{
+ va_list args_list;
+ va_start(args_list, first);
+ va_list args_copy;
+ va_copy(args_copy, args_list);
+
+ /* FIXME: Too much unecessary allocation */
+ uchar* header = slv2_query_header(p);
+ uchar* args_str = vstrjoin(first, args_copy);
+ uchar* query_str = ustrjoin(header, args_str, 0);
+
+ assert(p);
+ assert(query_str);
+
+ rasqal_query *rq = rasqal_new_query("sparql", NULL);
+
+ //printf("Query: \n%s\n\n", query_str);
+
+ rasqal_query_prepare(rq, query_str, NULL);
+ rasqal_query_results* results = rasqal_query_execute(rq);
+
+ rasqal_free_query(rq);
+
+ free(query_str);
+ free(args_str);
+ free(header);
+
+ return results;
+}
+
+
+SLV2Property
+slv2_query_get_results(rasqal_query_results* results)
+{
+ struct _Property* result = NULL;
+
+ if (rasqal_query_results_get_count(results) > 0) {
+ result = malloc(sizeof(struct _Property));
+ result->num_values = 0;
+ result->values = NULL;
+ }
+
+ while (!rasqal_query_results_finished(results)) {
+
+ rasqal_literal* literal =
+ rasqal_query_results_get_binding_value_by_name(results, U("value"));
+ assert(literal != NULL);
+
+ // Add value on to the array. Yes, this is disgusting.
+ result->num_values++;
+ // FIXME LEAK:
+ result->values = realloc(result->values, result->num_values * sizeof(char*));
+ result->values[result->num_values-1] = ustrdup(rasqal_literal_as_string(literal));
+
+ rasqal_query_results_next(results);
+ }
+
+ return result;
+}
+
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..55953b8
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,121 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _XOPEN_SOURCE 500
+
+#include <util.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+
+
+void
+ustrappend(uchar** dst, const uchar* suffix)
+{
+ assert(dst);
+ assert(*dst);
+ assert(suffix);
+
+ const size_t new_length = strlen((char*)*dst) + strlen((char*)suffix) + 1;
+ *dst = realloc(*dst, (new_length * sizeof(char)));
+ assert(dst);
+ strcat((char*)*dst, (char*)suffix);
+}
+
+
+uchar*
+ustrdup(const uchar* src)
+{
+ assert(src);
+ return (uchar*)strdup((char*)src);
+}
+
+
+uchar*
+ustrjoin(const uchar* first, ...)
+{
+ // FIXME: this is horribly, awfully, disgracefully slow
+
+ va_list args_list;
+ va_start(args_list, first);
+
+ va_list args_copy;
+ va_copy(args_copy, args_list);
+
+ uchar* result = vstrjoin(first, args_copy);
+
+ //va_end(args_copy);
+ va_end(args_list);
+
+ return result;
+
+ /*
+ va_list args_list;
+ uchar* arg = NULL;
+ uchar* result = ustrdup(first);
+
+ va_start(args_list, first);
+
+ while ((arg = va_arg(args_list, uchar*)) != (uchar*)0)
+ ustrappend(&result, arg);
+
+ va_end(args_list);
+
+ return result;*/
+}
+
+
+uchar*
+vstrjoin(const uchar* first, va_list args_list)
+{
+ // FIXME: this is horribly, awfully, disgracefully slow
+
+ uchar* arg = NULL;
+ uchar* result = ustrdup(first);
+
+ while ((arg = va_arg(args_list, uchar*)) != NULL)
+ ustrappend(&result, arg);
+
+ va_end(args_list);
+
+ return result;
+}
+
+
+
+/** Convert a URL to a local filesystem path (ie by chopping off the
+ * leading "file://".
+ *
+ * Returns NULL if URL is not a valid URL on the local filesystem.
+ * Result is simply a pointer in to \a url and must not be free()'d.
+ */
+const char*
+url2path(const uchar* const url)
+{
+ /*assert(strlen((char*)url) > 8);
+ char* result = calloc(strlen((char*)url)-7+1, sizeof(char));
+ strcpy(result, (char*)url+7);
+ return result;*/
+ if (!strncmp((char*)url, "file://", 7))
+ return (char*)url + 7;
+ else
+ return NULL;
+}
+
+
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..dbb7801
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,53 @@
+/* LibSLV2
+ * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __UTIL_H
+#define __UTIL_H
+
+#include <stdarg.h>
+#include <slv2/types.h>
+
+/* Cast a char* to an unsigned char* (Used for string literals) */
+#define U(x) (unsigned char*)(x)
+
+/** Append \a suffix to \a *dst, reallocating \a dst as necessary.
+ *
+ * \a dst will (possibly) be freed, it must be dynamically allocated with malloc
+ * or NULL.
+ */
+void
+ustrappend(uchar** dst, const uchar* suffix);
+
+uchar*
+ustrdup(const uchar* src);
+
+/** Join all arguments into one string.
+ *
+ * Arguments are not modified, return value must be free()'d.
+ */
+uchar*
+ustrjoin(const uchar* first, ...);
+
+uchar*
+vstrjoin(const uchar* first, va_list args_list);
+
+const char*
+url2path(const uchar* const url);
+
+
+#endif