summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format56
-rw-r--r--.clang-tidy47
-rw-r--r--.gitignore15
-rw-r--r--.gitmodules3
-rw-r--r--.reuse/dep523
-rw-r--r--.suppress.cppcheck7
-rw-r--r--COPYING16
-rw-r--r--INSTALL66
-rw-r--r--INSTALL.md77
-rw-r--r--LICENSES/0BSD.txt12
l---------LICENSES/ISC.txt1
-rw-r--r--NEWS107
-rw-r--r--README.md4
-rw-r--r--bindings/python/Makefile2
-rw-r--r--bindings/python/conf.py8
-rw-r--r--bindings/python/index.rst4
-rw-r--r--bindings/python/lilv.py7
-rwxr-xr-xbindings/python/lv2_apply.py3
-rwxr-xr-xbindings/python/lv2_list.py3
-rwxr-xr-xbindings/python/lv2_list_presets.py3
-rw-r--r--bindings/python/meson.build9
-rw-r--r--bindings/test/bindings_test_plugin.c30
-rw-r--r--bindings/test/python/test_api.py13
-rw-r--r--doc/Doxyfile.in (renamed from doc/c/Doxyfile)9
-rw-r--r--doc/api/meson.build9
-rw-r--r--doc/c/index.rst10
-rw-r--r--doc/c/wscript43
-rw-r--r--doc/conf.py.in124
-rw-r--r--doc/html/meson.build39
-rw-r--r--doc/index.rst (renamed from doc/summary.rst)14
-rw-r--r--doc/lv2apply.1100
-rw-r--r--doc/lv2bench.155
-rw-r--r--doc/lv2info.198
-rw-r--r--doc/lv2ls.189
-rw-r--r--doc/meson.build71
-rw-r--r--doc/overview.rst (renamed from doc/c/overview.rst)4
-rw-r--r--doc/plugins.rst (renamed from doc/c/plugins.rst)4
-rw-r--r--doc/singlehtml/meson.build33
-rw-r--r--doc/uis.rst (renamed from doc/c/uis.rst)4
-rw-r--r--doc/world.rst (renamed from doc/c/world.rst)4
-rw-r--r--doc/xml/meson.build36
-rw-r--r--include/lilv/lilv.h566
-rw-r--r--include/lilv/lilvmm.hpp359
-rw-r--r--lilv.pc.in11
-rw-r--r--lilv.ttl48
-rw-r--r--meson.build382
-rw-r--r--meson_options.txt32
-rwxr-xr-xscripts/dox_to_sphinx.py655
-rw-r--r--src/.clang-tidy24
-rw-r--r--src/collections.c112
-rw-r--r--src/dylib.c67
-rw-r--r--src/dylib.h35
-rw-r--r--src/filesystem.c564
-rw-r--r--src/filesystem.h182
-rw-r--r--src/instance.c23
-rw-r--r--src/lib.c46
-rw-r--r--src/lilv_config.h115
-rw-r--r--src/lilv_internal.h91
-rw-r--r--src/node.c53
-rw-r--r--src/plugin.c59
-rw-r--r--src/pluginclass.c28
-rw-r--r--src/port.c44
-rw-r--r--src/query.c30
-rw-r--r--src/scalepoint.c19
-rw-r--r--src/state.c423
-rw-r--r--src/ui.c21
-rw-r--r--src/util.c133
-rw-r--r--src/world.c156
-rw-r--r--src/zix/common.h138
-rw-r--r--src/zix/tree.c727
-rw-r--r--src/zix/tree.h164
-rw-r--r--subprojects/sphinxygen.wrap14
-rw-r--r--test/.clang-tidy38
-rw-r--r--test/bad_syntax.lv2/bad_syntax.c20
-rw-r--r--test/bad_syntax.lv2/meson.build37
-rw-r--r--test/bad_syntax.lv2/test_bad_syntax.c17
-rw-r--r--test/cpp/.clang-tidy21
-rw-r--r--test/cpp/meson.build37
-rw-r--r--test/cpp/test_lilv_hpp.cpp12
-rw-r--r--test/failed_instantiation.lv2/failed_instantiation.c27
-rw-r--r--test/failed_instantiation.lv2/meson.build37
-rw-r--r--test/failed_instantiation.lv2/test_failed_instantiation.c17
-rw-r--r--test/failed_lib_descriptor.lv2/failed_lib_descriptor.c20
-rw-r--r--test/failed_lib_descriptor.lv2/meson.build37
-rw-r--r--test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c19
-rw-r--r--test/headers/.clang-tidy15
-rw-r--r--test/headers/meson.build32
-rw-r--r--test/headers/test_headers.c13
-rw-r--r--test/lib_descriptor.lv2/lib_descriptor.c27
-rw-r--r--test/lib_descriptor.lv2/meson.build37
-rw-r--r--test/lib_descriptor.lv2/test_lib_descriptor.c17
-rw-r--r--test/lilv_cxx_test.cpp25
-rw-r--r--test/lilv_test_uri_map.h36
-rw-r--r--test/lilv_test_utils.c114
-rw-r--r--test/lilv_test_utils.h29
-rw-r--r--test/lint/meson.build38
-rw-r--r--test/lv2/core.lv2/lv2core.ttl (renamed from test/core.lv2/lv2core.ttl)0
-rw-r--r--test/lv2/core.lv2/manifest.ttl (renamed from test/core.lv2/manifest.ttl)0
-rw-r--r--test/lv2/core.lv2/meson.build11
-rw-r--r--test/meson.build103
-rw-r--r--test/missing_descriptor.lv2/meson.build37
-rw-r--r--test/missing_descriptor.lv2/missing_descriptor.c20
-rw-r--r--test/missing_descriptor.lv2/test_missing_descriptor.c19
-rw-r--r--test/missing_name.lv2/meson.build37
-rw-r--r--test/missing_name.lv2/missing_name.c20
-rw-r--r--test/missing_name.lv2/test_missing_name.c17
-rw-r--r--test/missing_plugin.lv2/meson.build37
-rw-r--r--test/missing_plugin.lv2/missing_plugin.c20
-rw-r--r--test/missing_plugin.lv2/test_missing_plugin.c19
-rw-r--r--test/missing_port.lv2/meson.build37
-rw-r--r--test/missing_port.lv2/missing_port.c20
-rw-r--r--test/missing_port.lv2/test_missing_port.c17
-rw-r--r--test/missing_port_name.lv2/meson.build37
-rw-r--r--test/missing_port_name.lv2/missing_port_name.c20
-rw-r--r--test/missing_port_name.lv2/test_missing_port_name.c17
-rw-r--r--test/new_version.lv2/meson.build24
-rw-r--r--test/new_version.lv2/new_version.c20
-rw-r--r--test/old_version.lv2/meson.build24
-rw-r--r--test/old_version.lv2/old_version.c20
-rw-r--r--test/test_bad_port_index.c23
-rw-r--r--test/test_bad_port_symbol.c23
-rw-r--r--test/test_classes.c19
-rw-r--r--test/test_discovery.c23
-rw-r--r--test/test_filesystem.c553
-rw-r--r--test/test_get_symbol.c19
-rw-r--r--test/test_no_author.c29
-rw-r--r--test/test_no_verify.c23
-rw-r--r--test/test_plugin.c29
-rw-r--r--test/test_plugin.lv2/manifest.ttl.in (renamed from test/test.lv2/manifest.ttl.in)4
-rw-r--r--test/test_plugin.lv2/meson.build24
-rw-r--r--test/test_plugin.lv2/test_plugin.c (renamed from test/test.lv2/test.c)104
-rw-r--r--test/test_plugin.lv2/test_plugin.ttl.in (renamed from test/test.lv2/test.ttl.in)0
-rw-r--r--test/test_port.c23
-rw-r--r--test/test_preset.c21
-rw-r--r--test/test_project.c23
-rw-r--r--test/test_project_no_author.c29
-rw-r--r--test/test_prototype.c23
-rw-r--r--test/test_reload_bundle.c19
-rw-r--r--test/test_replace_version.c27
-rw-r--r--test/test_state.c265
-rw-r--r--test/test_string.c56
-rw-r--r--test/test_ui.c19
-rw-r--r--test/test_util.c67
-rw-r--r--test/test_value.c21
-rw-r--r--test/test_verify.c23
-rw-r--r--test/test_world.c21
-rw-r--r--tools/.clang-tidy15
-rw-r--r--tools/bench.h38
-rw-r--r--tools/lilv.bash_completion (renamed from utils/lilv.bash_completion)14
-rw-r--r--tools/lv2apply.c (renamed from utils/lv2apply.c)58
-rw-r--r--tools/lv2bench.c (renamed from utils/lv2bench.c)131
-rw-r--r--tools/lv2info.c (renamed from utils/lv2info.c)49
-rw-r--r--tools/lv2ls.c (renamed from utils/lv2ls.c)29
-rw-r--r--tools/meson.build92
-rw-r--r--tools/uri_table.h (renamed from utils/uri_table.h)19
-rw-r--r--utils/bench.h53
-rw-r--r--utils/lilv-bench.c34
-rwxr-xr-xwaf27
m---------waflib0
-rw-r--r--wscript633
160 files changed, 3834 insertions, 6749 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..1210a39
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,56 @@
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+---
+AlignConsecutiveAssignments: true
+AlignConsecutiveDeclarations: true
+AlignEscapedNewlines: Left
+AttributeMacros:
+ - LILV_API
+ - LILV_DEPRECATED
+ - LILV_LOG_FUNC
+BasedOnStyle: Mozilla
+BraceWrapping:
+ AfterClass: true
+ AfterEnum: false
+ AfterExternBlock: false
+ AfterFunction: true
+ AfterNamespace: false
+ AfterStruct: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+BreakBeforeBraces: Custom
+Cpp11BracedListStyle: true
+FixNamespaceComments: true
+ForEachMacros:
+ - FOREACH_MATCH
+ - LILV_FOREACH
+ - LV2_ATOM_OBJECT_BODY_FOREACH
+ - LV2_ATOM_OBJECT_FOREACH
+ - LV2_ATOM_SEQUENCE_BODY_FOREACH
+ - LV2_ATOM_SEQUENCE_FOREACH
+ - LV2_ATOM_TUPLE_BODY_FOREACH
+ - LV2_ATOM_TUPLE_FOREACH
+IndentCaseLabels: false
+IndentPPDirectives: AfterHash
+KeepEmptyLinesAtTheStartOfBlocks: false
+SpacesInContainerLiterals: false
+StatementMacros:
+ - LILV_ERROR
+ - LILV_ERRORF
+ - LILV_NOTE
+ - LILV_NOTEF
+ - LILV_PORT_WRAP0
+ - LILV_PORT_WRAP1
+ - LILV_WARN
+ - LILV_WARNF
+ - LILV_WRAP0
+ - LILV_WRAP0_VOID
+ - LILV_WRAP1
+ - LILV_WRAP1_VOID
+ - LILV_WRAP2
+ - LILV_WRAP2_VOID
+ - LILV_WRAP3
+ - LILV_WRAP_CONVERSION
+ - _Pragma
+...
diff --git a/.clang-tidy b/.clang-tidy
index 9accc2c..54e9bd6 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,32 +1,25 @@
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
Checks: >
*,
- -*-magic-numbers,
- -*-uppercase-literal-suffix,
- -android-cloexec-fopen,
- -bugprone-branch-clone,
+ -*-vararg,
+ -altera-*,
+ -bugprone-assignment-in-if-condition,
+ -bugprone-easily-swappable-parameters,
-bugprone-macro-parentheses,
- -bugprone-narrowing-conversions,
- -bugprone-not-null-terminated-result,
- -bugprone-reserved-identifier,
- -bugprone-suspicious-string-compare,
- -cert-dcl37-c,
- -cert-dcl51-cpp,
- -cert-err34-c,
- -clang-analyzer-alpha.*,
- -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
- -cppcoreguidelines-avoid-non-const-global-variables,
- -cppcoreguidelines-macro-usage,
- -cppcoreguidelines-narrowing-conversions,
- -google-readability-todo,
- -hicpp-multiway-paths-covered,
- -hicpp-signed-bitwise,
- -llvm-header-guard,
+ -bugprone-multi-level-implicit-pointer-conversion,
+ -bugprone-suspicious-realloc-usage,
+ -clang-diagnostic-unused-function,
+ -clang-diagnostic-unused-macros,
-llvmlibc-*,
- -misc-no-recursion,
- -misc-non-private-member-variables-in-classes,
- -misc-unused-parameters,
- -modernize-use-trailing-return-type,
- -readability-implicit-bool-conversion,
-WarningsAsErrors: '*'
-HeaderFilterRegex: '.*'
+ -misc-include-cleaner,
+ -readability-identifier-length,
+CheckOptions:
+ - key: hicpp-uppercase-literal-suffix.NewSuffixes
+ value: 'L;U;UL;ULL'
+ - key: readability-uppercase-literal-suffix.NewSuffixes
+ value: 'L;U;UL;ULL'
FormatStyle: file
+HeaderFilterRegex: '.*/lilv/[^/]+.h'
+WarningsAsErrors: '*'
diff --git a/.gitignore b/.gitignore
index 204c242..373f228 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,11 @@
-build/**
-.waf-*
-.lock-waf*
-__pycache__
+# Copyright 2018-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+/.meson-subproject-wrap-hash.txt
+/build/
+/subprojects/packagecache/
+/subprojects/sphinxygen-1.0.10/
+/subprojects/sphinxygen/
+
+*.pyc
+__pycache__/
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index cc8b569..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "waflib"]
- path = waflib
- url = ../../drobilla/autowaf.git
diff --git a/.reuse/dep5 b/.reuse/dep5
new file mode 100644
index 0000000..1219ed7
--- /dev/null
+++ b/.reuse/dep5
@@ -0,0 +1,23 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: lilv
+Upstream-Contact: David Robillard <d@drobilla.net>
+Source: https://gitlab.com/drobilla/lilv
+
+Files: AUTHORS NEWS lilv.ttl
+Copyright: 2006-2025 David Robillard <d@drobilla.net>
+Comment: Contributed to the Commons as a representation of simple facts
+License: 0BSD OR ISC
+
+Files: .clant.json
+Copyright: 2020 David Robillard <d@drobilla.net>
+Comment: Contributed to the Commons as a tool configuration
+License: 0BSD OR ISC
+
+Files: .suppress.cppcheck
+Copyright: 2024 David Robillard <d@drobilla.net>
+Comment: Contributed to the Commons as a tool configuration
+License: 0BSD OR ISC
+
+Files: bindings/test/*.ttl.in test/*/*.ttl.in test/lv2/core.lv2/*.ttl
+Copyright: 2015-2022 David Robillard <d@drobilla.net>
+License: ISC
diff --git a/.suppress.cppcheck b/.suppress.cppcheck
new file mode 100644
index 0000000..48513d7
--- /dev/null
+++ b/.suppress.cppcheck
@@ -0,0 +1,7 @@
+CastIntegerToAddressAtReturn
+knownConditionTrueFalse
+memleakOnRealloc
+noExplicitConstructor
+normalCheckLevelMaxBranches
+redundantInitialization
+varFuncNullUB
diff --git a/COPYING b/COPYING
index 9748bb9..977d7b6 100644
--- a/COPYING
+++ b/COPYING
@@ -1,13 +1,13 @@
-Copyright 2011-2021 David Robillard <d@drobilla.net>
+Copyright 2011-2022 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
-THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 9b54f51..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,66 +0,0 @@
-Installation Instructions
-=========================
-
-Basic Installation
-------------------
-
-Building this software requires only Python. To install with default options:
-
- ./waf configure
- ./waf
- ./waf install # or sudo ./waf install
-
-Configuration Options
----------------------
-
-All supported options can be viewed using the command:
-
- ./waf --help
-
-Most options only need to be passed during the configure stage, for example:
-
- ./waf configure --prefix=/usr
- ./waf
- ./waf install
-
-Compiler Configuration
-----------------------
-
-Several standard environment variables can be used to control how compilers are
-invoked:
-
- * CC: Path to C compiler
- * CFLAGS: C compiler options
- * CXX: Path to C++ compiler
- * CXXFLAGS: C++ compiler options
- * CPPFLAGS: C preprocessor options
- * LINKFLAGS: Linker options
-
-Library Versioning
-------------------
-
-This library uses semantic versioning <http://semver.org/>.
-
-Several major versions can be installed in parallel. The shared library name,
-include directory, and pkg-config file are suffixed with the major version
-number. For example, a library named "foo" at version 1.x.y might install:
-
- /usr/include/foo-1/foo/foo.h
- /usr/lib/foo-1.so.1.x.y
- /usr/lib/pkgconfig/foo-1.pc
-
-Dependencies can check for the package "foo-1" with pkg-config.
-
-Packaging
----------
-
-Everything can be installed to a specific root directory by passing a --destdir
-option to the install stage (or setting the DESTDIR environment variable),
-which adds a prefix to all install paths. For example:
-
- ./waf configure --prefix=/usr
- ./waf
- ./waf install --destdir=/tmp/package
-
-Packages should allow parallel installation of several major versions. For
-example, the above would be packaged as "foo-1". \ No newline at end of file
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000..2adecf0
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,77 @@
+<!-- Copyright 2022 David Robillard <d@drobilla.net> -->
+<!-- SPDX-License-Identifier: ISC -->
+
+Installation Instructions
+=========================
+
+Prerequisites
+-------------
+
+To build from source, you will need:
+
+ * A relatively modern C compiler (GCC, Clang, and MSVC are known to work).
+
+ * [Meson](http://mesonbuild.com/), which depends on
+ [Python](http://python.org/).
+
+This is a brief overview of building this project with meson. See the meson
+documentation for more detailed information.
+
+Configuration
+-------------
+
+The build is configured with the `setup` command, which creates a new build
+directory with the given name:
+
+ meson setup build
+
+Some environment variables are read during `setup` and stored with the
+configuration:
+
+ * `CC`: Path to C compiler.
+ * `CFLAGS`: C compiler options.
+ * `LDFLAGS`: Linker options.
+
+However, it is better to use meson options for configuration. All options can
+be inspected with the `configure` command from within the build directory:
+
+ cd build
+ meson configure
+
+Options can be set by passing C-style "define" options to `configure`:
+
+ meson configure -Dc_args="-march=native" -Dprefix="/opt/mypackage/"
+
+Note that some options, such as `strict` and `werror` are for
+developer/maintainer use only. Please don't file issues about anything that
+happens when they are enabled.
+
+Building
+--------
+
+From within a configured build directory, everything can be built with the
+`compile` command:
+
+ meson compile
+
+Similarly, tests can be run with the `test` command:
+
+ meson test
+
+Meson can also generate a project for several popular IDEs, see the `backend`
+option for details.
+
+Installation
+------------
+
+A compiled project can be installed with the `install` command:
+
+ meson install
+
+You may need to acquire root permissions to install to a system-wide prefix.
+For packaging, the installation may be staged to a directory using the
+`DESTDIR` environment variable or the `--destdir` option:
+
+ DESTDIR=/tmp/mypackage/ meson install
+
+ meson install --destdir=/tmp/mypackage/
diff --git a/LICENSES/0BSD.txt b/LICENSES/0BSD.txt
new file mode 100644
index 0000000..b3e8cfd
--- /dev/null
+++ b/LICENSES/0BSD.txt
@@ -0,0 +1,12 @@
+Copyright 2011-2022 David Robillard <d@drobilla.net>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/LICENSES/ISC.txt b/LICENSES/ISC.txt
new file mode 120000
index 0000000..012065c
--- /dev/null
+++ b/LICENSES/ISC.txt
@@ -0,0 +1 @@
+../COPYING \ No newline at end of file
diff --git a/NEWS b/NEWS
index c911422..bac5b41 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,78 @@
-lilv (0.24.13) unstable;
+lilv (0.24.27) unstable; urgency=medium
+ * Add header warnings test
+
+ -- David Robillard <d@drobilla.net> Mon, 20 Jan 2025 18:14:00 +0000
+
+lilv (0.24.26) stable; urgency=medium
+
+ * Add lint option with project metadata and code quality tests
+ * Avoid use of VLAs in lv2apply
+ * Clean up and isolate platform-specific code
+ * Fix C++ test build on MacOS
+ * Fix library current_version on MacOS
+ * Fix test suite when TMPDIR has no trailing slash
+ * Fully separate library code from programs
+ * Improve const correctness
+ * Replace more platform-specific code with use of zix
+
+ -- David Robillard <d@drobilla.net> Sun, 19 Jan 2025 13:53:31 +0000
+
+lilv (0.24.24) stable; urgency=medium
+
+ * Avoid overriding state features passed by the host
+ * Fix null dereference when trying to load state from a missing file
+ * Fix potential null dereferences and conversion warnings
+
+ -- David Robillard <d@drobilla.net> Tue, 23 Jan 2024 19:39:29 +0000
+
+lilv (0.24.22) stable; urgency=medium
+
+ * Allow LILV_API to be defined by the user
+ * Clean up code
+ * Clean up inconsistent tool command line interfaces
+ * Convert man pages to mdoc
+ * Fix crash when plugins pass NULL to the LV2_State_Retrieve_Function
+ * Fix dependencies in pkg-config file
+ * Fix potential crash when writing state files fails
+ * Order plugin classes by URI
+ * Override pkg-config dependency within meson
+ * Remove junk files from documentation install
+ * Replace duplicated dox_to_sphinx script with sphinxygen dependency
+ * Switch to external zix dependency
+
+ -- David Robillard <d@drobilla.net> Sun, 22 Oct 2023 20:14:02 +0000
+
+lilv (0.24.20) stable; urgency=medium
+
+ * Adopt REUSE machine-readable licensing standard
+ * Update project metadata
+
+ -- David Robillard <d@drobilla.net> Fri, 09 Sep 2022 17:28:30 +0000
+
+lilv (0.24.18) stable; urgency=medium
+
+ * Allow programs to be used from subproject
+ * Fix default LV2_PATH
+
+ -- David Robillard <d@drobilla.net> Fri, 12 Aug 2022 22:15:29 +0000
+
+lilv (0.24.16) stable; urgency=medium
+
+ * Fix fallback flock() detection on MacOS
+ * Switch to meson build system
+
+ -- David Robillard <d@drobilla.net> Tue, 19 Jul 2022 01:16:26 +0000
+
+lilv (0.24.14) stable; urgency=medium
+
+ * Fix build issues with newer toolchains
* Fix unused parameter warnings
* Update zix tree
- -- David Robillard <d@drobilla.net> Mon, 11 Jan 2021 11:20:41 +0000
+ -- David Robillard <d@drobilla.net> Fri, 27 May 2022 01:38:26 +0000
-lilv (0.24.12) stable;
+lilv (0.24.12) stable; urgency=medium
* Allow connecting ports to structures in Python
* Fix potential memory error when joining filesystem paths
@@ -16,7 +83,7 @@ lilv (0.24.12) stable;
-- David Robillard <d@drobilla.net> Thu, 07 Jan 2021 21:46:06 +0000
-lilv (0.24.10) stable;
+lilv (0.24.10) stable; urgency=medium
* Fix memory leaks in lv2bench
* Fix various minor warnings and other code quality issues
@@ -25,7 +92,7 @@ lilv (0.24.10) stable;
-- David Robillard <d@drobilla.net> Sun, 27 Sep 2020 12:17:02 +0000
-lilv (0.24.8) stable;
+lilv (0.24.8) stable; urgency=medium
* Allow passing strings for URIs in Python API when unambiguous
* Fix cases where incorrect translation is used
@@ -35,7 +102,7 @@ lilv (0.24.8) stable;
-- David Robillard <d@drobilla.net> Sun, 26 Apr 2020 15:55:26 +0000
-lilv (0.24.6) stable;
+lilv (0.24.6) stable; urgency=medium
* Add more strict error detection when storing plugin state properties
* Add option to override LV2_PATH in applications
@@ -49,7 +116,7 @@ lilv (0.24.6) stable;
-- David Robillard <d@drobilla.net> Sun, 10 Nov 2019 21:39:37 +0000
-lilv (0.24.4) stable;
+lilv (0.24.4) stable; urgency=medium
* Don't attempt to load remote or non-Turtle files
* Fix saving state when broken links are encountered
@@ -64,14 +131,14 @@ lilv (0.24.4) stable;
-- David Robillard <d@drobilla.net> Sun, 22 Jul 2018 18:42:00 +0000
-lilv (0.24.2) stable;
+lilv (0.24.2) stable; urgency=medium
* Fix comparison of restored states with paths
* Fix saving state to paths that contain URI delimiters (#, ?, etc)
-- David Robillard <d@drobilla.net> Wed, 04 Jan 2017 16:48:08 +0000
-lilv (0.24.0) stable;
+lilv (0.24.0) stable; urgency=medium
* Add LILV_URI_ATOM_PORT and LILV_URI_CV_PORT defines
* Add lilv_state_set_metadata() for adding state banks/comments/etc (based
@@ -94,7 +161,7 @@ lilv (0.24.0) stable;
-- David Robillard <d@drobilla.net> Tue, 20 Sep 2016 02:24:57 +0000
-lilv (0.22.0) stable;
+lilv (0.22.0) stable; urgency=medium
* Add lilv_file_uri_parse() for correct URI to path conversion
* Add lilv_free() for systems picky about such things
@@ -121,7 +188,7 @@ lilv (0.22.0) stable;
-- David Robillard <d@drobilla.net> Thu, 08 Oct 2015 19:39:29 +0000
-lilv (0.20.0) stable;
+lilv (0.20.0) stable; urgency=medium
* Add convenient lilv_new_file_uri for creating file URIs
* Add lilv_world_unload_bundle() and lilv_world_unload_resource()
@@ -142,7 +209,7 @@ lilv (0.20.0) stable;
-- David Robillard <d@drobilla.net> Fri, 08 Aug 2014 22:21:32 +0000
-lilv (0.18.0) stable;
+lilv (0.18.0) stable; urgency=medium
* Add lilv_port_get_node() for using world query functions with ports
* Add support for running plugins from Python by Kaspar Emanuel
@@ -159,7 +226,7 @@ lilv (0.18.0) stable;
-- David Robillard <d@drobilla.net> Sat, 04 Jan 2014 21:06:42 +0000
-lilv (0.16.0) stable;
+lilv (0.16.0) stable; urgency=medium
* Add lilv_nodes_merge()
* Add lilv_world_ask() for easily checking if a statement exists
@@ -181,7 +248,7 @@ lilv (0.16.0) stable;
-- David Robillard <d@drobilla.net> Mon, 18 Feb 2013 21:43:10 +0000
-lilv (0.14.4) stable;
+lilv (0.14.4) stable; urgency=medium
* Add lv2bench utility
* Add option to build utilities as static binaries
@@ -201,13 +268,13 @@ lilv (0.14.4) stable;
-- David Robillard <d@drobilla.net> Thu, 23 Aug 2012 05:38:29 +0000
-lilv (0.14.2) stable;
+lilv (0.14.2) stable; urgency=medium
* Fix dynmanifest support
-- David Robillard <d@drobilla.net> Thu, 19 Apr 2012 20:11:31 +0000
-lilv (0.14.0) stable;
+lilv (0.14.0) stable; urgency=medium
* Add LilvState API for handling plugin state. This makes it simple to save
and restore plugin state both in memory and on disk, as well as save
@@ -238,7 +305,7 @@ lilv (0.14.0) stable;
-- David Robillard <d@drobilla.net> Thu, 19 Apr 2012 00:06:28 +0000
-lilv (0.5.0) stable;
+lilv (0.5.0) stable; urgency=medium
* Add ability to build static library
* Add lv2core as a pkg-config dependency (for lv2.h header include)
@@ -249,7 +316,7 @@ lilv (0.5.0) stable;
-- David Robillard <d@drobilla.net> Thu, 29 Sep 2011 04:00:00 +0000
-lilv (0.4.4) stable;
+lilv (0.4.4) stable; urgency=medium
* Fix building python bindings
* Fix lilv_ui_is_supported when Lilv is built independently
@@ -259,14 +326,14 @@ lilv (0.4.4) stable;
-- David Robillard <d@drobilla.net> Sat, 11 Jun 2011 15:20:11 +0000
-lilv (0.4.2) stable;
+lilv (0.4.2) stable; urgency=medium
* Fix build system Python 3 compatibility
* Fix compilation issues on some systems
-- David Robillard <d@drobilla.net> Wed, 25 May 2011 23:00:00 +0000
-lilv (0.4.0) stable;
+lilv (0.4.0) stable; urgency=medium
* Initial version (forked from SLV2)
diff --git a/README.md b/README.md
index 807fc2b..fd97a33 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,12 @@
+<!-- Copyright 2006-2019 David Robillard <d@drobilla.net> -->
+<!-- SPDX-License-Identifier: ISC -->
+
Lilv
====
Lilv is a C library to make the use of LV2 plugins as simple as possible for
applications.
+
For more information, see <http://drobilla.net/software/lilv>.
-- David Robillard <d@drobilla.net>
diff --git a/bindings/python/Makefile b/bindings/python/Makefile
index e63c124..32f199d 100644
--- a/bindings/python/Makefile
+++ b/bindings/python/Makefile
@@ -1,5 +1,7 @@
# Makefile for Sphinx documentation
#
+# Copyright 2016 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
# You can set these variables from the command line.
SPHINXOPTS =
diff --git a/bindings/python/conf.py b/bindings/python/conf.py
index 005e03a..4fc0911 100644
--- a/bindings/python/conf.py
+++ b/bindings/python/conf.py
@@ -1,4 +1,8 @@
# -*- coding: utf-8 -*-
+
+# Copyright 2016-2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
#
# Lilv documentation build configuration file, created by
# sphinx-quickstart on Sun Sep 4 18:25:58 2016.
@@ -56,9 +60,9 @@ copyright = u'2016, David Robillard'
# built documents.
#
# The short X.Y version.
-version = '0.24.12'
+version = '0.24.27'
# The full version, including alpha/beta/rc tags.
-release = '0.24.12'
+release = '0.24.27'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/bindings/python/index.rst b/bindings/python/index.rst
index 4616054..b44fa08 100644
--- a/bindings/python/index.rst
+++ b/bindings/python/index.rst
@@ -1,3 +1,7 @@
+..
+ Copyright 2016 David Robillard <d@drobilla.net>
+ SPDX-License-Identifier: ISC
+
Lilv Python Documentation
=========================
diff --git a/bindings/python/lilv.py b/bindings/python/lilv.py
index 98da72f..100b3d1 100644
--- a/bindings/python/lilv.py
+++ b/bindings/python/lilv.py
@@ -1,9 +1,12 @@
"""Lilv Python interface"""
+# Copyright 2016-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: ISC
+
__author__ = "David Robillard"
-__copyright__ = "Copyright 2016-2020 David Robillard"
+__copyright__ = "Copyright 2016-2024 David Robillard"
__license__ = "ISC"
-__version__ = "0.24.12"
+__version__ = "0.24.27"
__maintainer__ = "David Robillard"
__email__ = "d@drobilla.net"
__status__ = "Production"
diff --git a/bindings/python/lv2_apply.py b/bindings/python/lv2_apply.py
index 4c7d9b4..bb95682 100755
--- a/bindings/python/lv2_apply.py
+++ b/bindings/python/lv2_apply.py
@@ -1,6 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+# Copyright 2011-2016 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: ISC
+
import math
import lilv
import sys
diff --git a/bindings/python/lv2_list.py b/bindings/python/lv2_list.py
index babe1b4..1bb233c 100755
--- a/bindings/python/lv2_list.py
+++ b/bindings/python/lv2_list.py
@@ -1,5 +1,8 @@
#!/usr/bin/env python
+# Copyright 2007-2011 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: ISC
+
import lilv
world = lilv.World()
diff --git a/bindings/python/lv2_list_presets.py b/bindings/python/lv2_list_presets.py
index 4e0c9b1..a6439d6 100755
--- a/bindings/python/lv2_list_presets.py
+++ b/bindings/python/lv2_list_presets.py
@@ -1,6 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+# Copyright 2019-2020 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: ISC
+
import sys
import lilv
diff --git a/bindings/python/meson.build b/bindings/python/meson.build
new file mode 100644
index 0000000..1cffd71
--- /dev/null
+++ b/bindings/python/meson.build
@@ -0,0 +1,9 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+pymod = import('python')
+py = pymod.find_installation('python3', required: get_option('bindings_py'))
+
+if py.found()
+ py.install_sources(files('lilv.py'))
+endif
diff --git a/bindings/test/bindings_test_plugin.c b/bindings/test/bindings_test_plugin.c
index 2df64ea..0397db4 100644
--- a/bindings/test/bindings_test_plugin.c
+++ b/bindings/test/bindings_test_plugin.c
@@ -1,19 +1,6 @@
-/*
- Copyright 2006-2019 David Robillard <d@drobilla.net>
- Copyright 2006 Steve Harris <steve@plugin.org.uk>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2006-2019 David Robillard <d@drobilla.net>
+// Copyright 2006 Steve Harris <steve@plugin.org.uk>
+// SPDX-License-Identifier: ISC
/**
LV2 headers are based on the URI of the specification they come from, so a
@@ -22,7 +9,7 @@
replacing `http:/` with `lv2` any header in the specification bundle can be
included, in this case `lv2.h`.
*/
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
/** Include standard C headers */
#include <stdint.h>
@@ -187,7 +174,7 @@ static const LV2_Descriptor descriptor = {TEST_URI,
The lv2_descriptor() function is the entry point to the plugin library. The
host will load the library and call this function repeatedly with increasing
indices to find all the plugins defined in the library. The index is not an
- indentifier, the URI of the returned descriptor is used to determine the
+ identifier, the URI of the returned descriptor is used to determine the
identify of the plugin.
This method is in the ``discovery'' threading class, so no other functions
@@ -197,10 +184,5 @@ LV2_SYMBOL_EXPORT
const LV2_Descriptor*
lv2_descriptor(uint32_t index)
{
- switch (index) {
- case 0:
- return &descriptor;
- default:
- return NULL;
- }
+ return index ? NULL : &descriptor;
}
diff --git a/bindings/test/python/test_api.py b/bindings/test/python/test_api.py
index 8d3a94a..d70dbe6 100644
--- a/bindings/test/python/test_api.py
+++ b/bindings/test/python/test_api.py
@@ -1,17 +1,6 @@
# Copyright 2016-2020 David Robillard <d@drobilla.net>
# Copyright 2013 Kaspar Emanuel <kaspar.emanuel@gmail.com>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+# SPDX-License-Identifier: ISC
import lilv
import os
diff --git a/doc/c/Doxyfile b/doc/Doxyfile.in
index ce10524..2ca5694 100644
--- a/doc/c/Doxyfile
+++ b/doc/Doxyfile.in
@@ -1,3 +1,6 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
PROJECT_NAME = Lilv
PROJECT_BRIEF = "A library for simple use of LV2 plugins"
@@ -21,6 +24,8 @@ SHOW_FILES = NO
MACRO_EXPANSION = YES
PREDEFINED = LILV_API LILV_DEPRECATED
-INPUT = ../../include/lilv/lilv.h
+RECURSIVE = YES
+STRIP_FROM_PATH = @LILV_SRCDIR@
+INPUT = @LILV_SRCDIR@/include/lilv/lilv.h
-OUTPUT_DIRECTORY = .
+OUTPUT_DIRECTORY = @DOX_OUTPUT@
diff --git a/doc/api/meson.build b/doc/api/meson.build
new file mode 100644
index 0000000..a470564
--- /dev/null
+++ b/doc/api/meson.build
@@ -0,0 +1,9 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+api_lilv_rst = custom_target(
+ 'lilv.rst',
+ command: [sphinxygen, '-f', '@INPUT0@', '@OUTDIR@'],
+ input: doxygen_xml,
+ output: 'lilv.rst',
+)
diff --git a/doc/c/index.rst b/doc/c/index.rst
deleted file mode 100644
index 6968981..0000000
--- a/doc/c/index.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-####
-Lilv
-####
-
-.. include:: summary.rst
-
-.. toctree::
-
- overview
- api/lilv
diff --git a/doc/c/wscript b/doc/c/wscript
deleted file mode 100644
index d515ddf..0000000
--- a/doc/c/wscript
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python
-
-def build(bld):
- dox_to_sphinx = bld.path.find_node("../../scripts/dox_to_sphinx.py")
- index_xml = bld.path.get_bld().make_node("xml/index.xml")
-
- files = [
- ("../summary.rst", "sphinx/summary.rst"),
- ("index.rst", "sphinx/index.rst"),
- ("overview.rst", "sphinx/overview.rst"),
- ("plugins.rst", "sphinx/plugins.rst"),
- ("uis.rst", "sphinx/uis.rst"),
- ("world.rst", "sphinx/world.rst"),
- ]
-
- # Run Doxygen to generate XML documentation
- bld(features="doxygen", doxyfile="Doxyfile")
-
- # Substitute variables to make Sphinx configuration file
- bld(features="subst",
- source="../conf.py.in",
- target="sphinx/conf.py",
- LILV_VERSION=bld.env.LILV_VERSION)
-
- # Copy static documentation files to Sphinx build directory
- for f in files:
- bld(features="subst", is_copy=True, source=f[0], target=f[1])
-
- # Generate Sphinx markup from Doxygen XML
- bld.add_group()
- bld(rule="${PYTHON} " + dox_to_sphinx.abspath() + " -f ${SRC} ${TGT}",
- source=index_xml,
- target="sphinx/api/")
-
- doc_dir = bld.env.DOCDIR + "/lilv-%s/" % bld.env.LILV_MAJOR_VERSION
-
- # Run Sphinx to generate HTML documentation
- for builder in ["html", "singlehtml"]:
- bld(features="sphinx",
- sphinx_source=bld.path.get_bld().make_node("sphinx"),
- sphinx_output_format=builder,
- sphinx_options=["-E", "-q", "-t", builder],
- install_path=doc_dir + "c/%s/" % builder)
diff --git a/doc/conf.py.in b/doc/conf.py.in
index e62eaff..1831ded 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -1,9 +1,14 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: ISC
+
# Project information
-project = "Lilv"
-copyright = "2020, David Robillard"
+project = "@LILV_TITLE@"
+copyright = "2020-2025, David Robillard"
author = "David Robillard"
release = "@LILV_VERSION@"
+version = "@LILV_VERSION@"
+desc = "A library for loading LV2 plugins"
# General configuration
@@ -12,6 +17,13 @@ language = "en"
nitpicky = True
pygments_style = "friendly"
+try:
+ import sphinx_lv2_theme
+
+ have_lv2_theme = True
+except ModuleNotFoundError:
+ have_lv2_theme = False
+
# Ignore everything opaque or external for nitpicky mode
_opaque = [
"FILE",
@@ -38,42 +50,78 @@ nitpick_ignore = list(map(lambda x: ("c:identifier", x), _opaque))
# HTML output
-html_theme = "sphinx_lv2_theme"
html_copy_source = False
-html_short_title = "Lilv"
-
-if tags.has('singlehtml'):
- html_sidebars = {
- "**": [
- "globaltoc.html",
- ]
- }
-
- html_theme_options = {
- "body_max_width": "65em",
- "body_min_width": "50em",
- "description": "A library for loading LV2 plugins",
- "show_footer_version": True,
- "show_logo_version": False,
- "logo_name": True,
- "nosidebar": False,
- "page_width": "80em",
- "sidebar_width": "11em",
- "globaltoc_maxdepth": 3,
- "globaltoc_collapse": False,
- }
+html_secnumber_suffix = " "
+html_short_title = "@LILV_TITLE@"
+
+html_theme_options = {
+ "description": desc,
+ "logo_name": True,
+ "logo_width": "8em",
+}
+
+if tags.has("singlehtml"):
+ html_sidebars = {"**": ["globaltoc.html"]}
+ html_theme_options.update(
+ {
+ "globaltoc_collapse": False,
+ "globaltoc_maxdepth": 3,
+ "nosidebar": False,
+ "page_width": "80em",
+ }
+ )
+else:
+ html_theme_options.update(
+ {
+ "globaltoc_collapse": True,
+ "globaltoc_maxdepth": 1,
+ "nosidebar": True,
+ "page_width": "60em",
+ }
+ )
+
+if have_lv2_theme:
+ html_theme = "sphinx_lv2_theme"
+
+ html_theme_options.update(
+ {
+ "show_footer_version": True,
+ "show_logo_version": True,
+ }
+ )
+
+ if tags.has("singlehtml"):
+ html_theme_options.update(
+ {
+ "body_max_width": "64em",
+ "body_min_width": "64em",
+ "nosidebar": False,
+ "sidebar_width": "12em",
+ }
+ )
+
+ else:
+ html_theme_options.update(
+ {
+ "body_max_width": "60em",
+ "body_min_width": "40em",
+ }
+ )
else:
- html_theme_options = {
- "body_max_width": "60em",
- "body_min_width": "40em",
- "description": "A library for loading LV2 plugins",
- "show_footer_version": True,
- "show_logo_version": False,
- "logo_name": True,
- "nosidebar": True,
- "page_width": "60em",
- "sidebar_width": "14em",
- "globaltoc_maxdepth": 1,
- "globaltoc_collapse": True,
- }
+ html_theme = "alabaster"
+
+ if tags.has("singlehtml"):
+ html_theme_options = {
+ "body_max_width": "58em",
+ "body_min_width": "40em",
+ "sidebar_width": "16em",
+ }
+
+ else:
+ html_theme_options = {
+ "body_max_width": "60em",
+ "body_min_width": "40em",
+ "nosidebar": True,
+ "show_relbars": True,
+ }
diff --git a/doc/html/meson.build b/doc/html/meson.build
new file mode 100644
index 0000000..59da474
--- /dev/null
+++ b/doc/html/meson.build
@@ -0,0 +1,39 @@
+# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+html_dir = docdir / versioned_name / 'html'
+
+# TODO: Add install_tag: 'doc' after requiring meson 0.60.0
+
+custom_target(
+ 'html',
+ build_by_default: true,
+ command: sphinx_build_command + [
+ '-b', 'html',
+ '-t', 'html',
+ sphinx_in_dir,
+ '@OUTDIR@',
+ ],
+ input: [api_lilv_rst, conf_py, sphinx_input],
+ install: true,
+ install_dir: html_dir,
+ output: [
+ 'index.html',
+
+ '_static',
+ 'api',
+ 'genindex.html',
+ 'overview.html',
+ 'plugins.html',
+ 'uis.html',
+ 'world.html',
+ ],
+)
+
+if not meson.is_subproject()
+ summary(
+ 'HTML',
+ get_option('prefix') / html_dir,
+ section: 'Directories',
+ )
+endif
diff --git a/doc/summary.rst b/doc/index.rst
index 313ffa8..46a9026 100644
--- a/doc/summary.rst
+++ b/doc/index.rst
@@ -1,3 +1,11 @@
+..
+ Copyright 2020-2022 David Robillard <d@drobilla.net>
+ SPDX-License-Identifier: ISC
+
+####
+Lilv
+####
+
Lilv is a library for working with LV2_ plugins.
It provides several types and functions that can be used to discover plugins,
investigate their data, load and run them, and save and restore their state.
@@ -6,4 +14,10 @@ Lilv is the standard implementation used by nearly all LV2 hosts.
It implements the details of the LV2 specification on POSIX, MacOS, and Windows,
and provides a simpler portable API for applications.
+.. toctree::
+
+ overview
+ api/lilv
+
.. _LV2: http://lv2plug.in/
+
diff --git a/doc/lv2apply.1 b/doc/lv2apply.1
index 4877aba..e34a6c6 100644
--- a/doc/lv2apply.1
+++ b/doc/lv2apply.1
@@ -1,34 +1,66 @@
-.TH LV2APPLY 1 "05 Sep 2016"
-
-.SH NAME
-.B lv2apply \- apply an LV2 plugin to an audio file
-.SH SYNOPSIS
-.B lv2apply [OPTION]... PLUGIN_URI
-
-.SH OPTIONS
-.TP
-\fB\-i IN_FILE\fR
-Input file
-
-.TP
-\fB\-o OUT_FILE\fR
-Output file
-
-.TP
-\fB\-c SYM VAL\fR
-Set control port SYM to VAL
-
-.TP
-\fB\-\-help\fR
-Display help and exit
-
-.TP
-\fB\-\-version\fR
-Display version information and exit
-
-.SH "SEE ALSO"
-.BR lv2ls(1)
-.BR lv2info(1)
-
-.SH AUTHOR
-lv2apply was written by David Robillard <d@drobilla.net>
+.\" # Copyright 2010-2025 David Robillard <d@drobilla.net>
+.\" # SPDX-License-Identifier: ISC
+.Dd January 20, 2025
+.Dt LV2APPLY 1
+.Os
+.Sh NAME
+.Nm lv2apply
+.Nd apply an LV2 plugin to an audio file
+.Sh SYNOPSIS
+.Nm lv2apply
+.Op Fl Vh
+.Op Fl c Ar symbol value
+.Op Fl i Ar in_file
+.Op Fl o Ar out_file
+.Op Fl Fl help
+.Op Fl Fl version
+.Ar plugin_uri
+.Sh DESCRIPTION
+.Nm
+runs an LV2 plugin on an audio file and writes the processed output to another.
+.Pp
+The options are as follows:
+.Pp
+.Bl -tag -compact -width 3n
+.It Fl V , Fl Fl version
+Display version information and exit.
+.Pp
+.It Fl c Ar symbol value
+Set control port
+.Ar symbol
+to
+.Ar value.
+.Pp
+.It Fl h , Fl Fl help
+Print the command line options.
+.Pp
+.It Fl i Ar in_file
+Input file path.
+.Pp
+.It Fl o Ar out_file
+Output file path.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width LV2_PATH -compact
+.It Ev LV2_PATH
+List of directories to search for LV2 plugin bundles,
+in the style of
+.Ev PATH .
+.El
+.Sh EXIT STATUS
+.Nm
+exits with a status of 0, or non-zero if an error occurred.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Xr lv2bench 1
+.It
+.Xr lv2info 1
+.It
+.Xr lv2ls 1
+.El
+.Sh AUTHORS
+.Nm
+is a part of lilv, by
+.An David Robillard
+.Aq Mt d@drobilla.net .
diff --git a/doc/lv2bench.1 b/doc/lv2bench.1
new file mode 100644
index 0000000..78e1340
--- /dev/null
+++ b/doc/lv2bench.1
@@ -0,0 +1,55 @@
+.\" # Copyright 2024-2025 David Robillard <d@drobilla.net>
+.\" # SPDX-License-Identifier: ISC
+.Dd January 20, 2025
+.Dt LV2BENCH 1
+.Os
+.Sh NAME
+.Nm lv2bench
+.Nd benchmark all installed and supported LV2 plugins
+.Sh SYNOPSIS
+.Nm lv2bench
+.Op Fl fhV
+.Op Fl b Ar block_size
+.Op Fl n Ar frames
+.Op Fl Fl full
+.Op Fl Fl help
+.Op Fl Fl version
+.Sh DESCRIPTION
+.Nm
+is a simple utility for running basic benchmarks of installed LV2 plugins.
+.Pp
+The options are as follows:
+.Pp
+.Bl -tag -compact -width 3n
+.It Fl V , Fl Fl version
+Display version information and exit.
+.Pp
+.It Fl b Ar block_size
+Block size, in audio frames.
+.Pp
+.It Fl f , Fl Fl full
+Emit full plottable output with values for every block.
+.Pp
+.It Fl h , Fl Fl help
+Print the command line options.
+.Pp
+.It Fl n Ar frames
+Total number of audio frames to process.
+.El
+.Sh EXIT STATUS
+.Nm
+exits with a status of 0, or non-zero if an error occurred.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Xr lv2apply 1
+.It
+.Xr lv2info 1
+.It
+.Xr lv2ls 1
+.El
+.Sh AUTHORS
+.Nm
+is a part of lilv, by
+.An David Robillard
+.Aq Mt d@drobilla.net .
diff --git a/doc/lv2info.1 b/doc/lv2info.1
index 32a3bec..8f82f8f 100644
--- a/doc/lv2info.1
+++ b/doc/lv2info.1
@@ -1,33 +1,65 @@
-.TH LV2INFO 1 "05 Sep 2016"
-
-.SH NAME
-.B lv2info \- print information about an installed LV2 plugin
-.SH SYNOPSIS
-.B lv2info PLUGIN_URI
-
-.SH OPTIONS
-.TP
-\fB\-p FILE\fR
-Write Turtle description of plugin to FILE
-
-.TP
-\fB\-m FILE\fR
-Add record of plugin to manifest FILE
-
-.TP
-\fB\-\-help\fR
-Display help and exit
-
-.TP
-\fB\-\-version\fR
-Display version information and exit
-
-.SH "SEE ALSO"
-.BR lilv(3),
-.BR lv2ls(1)
-
-.SH AUTHOR
-lv2info was written by David Robillard <d@drobilla.net>
-.PP
-This manual page was written by Jaromír Mikes <mira.mikes@seznam.cz>
-and David Robillard <d@drobilla.net>
+.\" # Copyright 2009-2025 David Robillard <d@drobilla.net>
+.\" # SPDX-License-Identifier: ISC
+.Dd January 20, 2025
+.Dt LV2INFO 1
+.Os
+.Sh NAME
+.Nm lv2info
+.Nd print information about an installed LV2 plugin
+.Sh SYNOPSIS
+.Nm lv2info
+.Op Fl hV
+.Op Fl m Ar file
+.Op Fl p Ar file
+.Ar plugin_uri
+.Sh DESCRIPTION
+.Nm
+prints a human-readable summary of information about an LV2 plugin.
+.Pp
+The plugin must be installed;
+.Nm
+will search for one with the given
+.Ar plugin_uri
+in the LV2 path.
+.Pp
+The options are as follows:
+.Pp
+.Bl -tag -compact -width 3n
+.It Fl V , Fl Fl version
+Display version information and exit.
+.Pp
+.It Fl h , Fl Fl help
+Print the command line options.
+.Pp
+.It Fl m Ar file
+Add record of plugin to Turtle manifest
+.Ar file .
+.Pp
+.It Fl p Ar file
+Write description of plugin to Turtle
+.Ar file .
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width LV2_PATH -compact
+.It Ev LV2_PATH
+List of directories to search for LV2 plugin bundles,
+in the style of
+.Ev PATH .
+.El
+.Sh EXIT STATUS
+.Nm
+exits with a status of 0, or non-zero if an error occurred.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Xr lv2apply 1
+.It
+.Xr lv2bench 1
+.It
+.Xr lv2ls 1
+.El
+.Sh AUTHORS
+.Nm
+is a part of lilv, by
+.An David Robillard
+.Aq Mt d@drobilla.net .
diff --git a/doc/lv2ls.1 b/doc/lv2ls.1
index 320b71c..7cefb06 100644
--- a/doc/lv2ls.1
+++ b/doc/lv2ls.1
@@ -1,30 +1,59 @@
-.TH LV2LS 1 "26 Aug 2016"
-
-.SH NAME
-.B lv2ls \- list all installed LV2 plugins
-
-.SH SYNOPSIS
-.B lv2ls [OPTION]...
-
-.SH OPTIONS
-.TP
-\fB\-n\fR, \fB\-\-names\fR
-Show names instead of URIs
-
-.TP
-\fB\-\-help\fR
-Display help and exit
-
-.TP
-\fB\-\-version\fR
-Display version information and exit
-
-.SH "SEE ALSO"
-.BR lilv(3),
-.BR lv2info(1)
-
-.SH AUTHOR
-lv2ls was written by David Robillard <d@drobilla.net>
-.PP
-This manual page was written by Jaromír Mikes <mira.mikes@seznam.cz>
-and David Robillard <d@drobilla.net>
+.\" # Copyright 2010-2025 David Robillard <d@drobilla.net>
+.\" # SPDX-License-Identifier: ISC
+.Dd January 20, 2025
+.Dt LV2LS 1
+.Os
+.Sh NAME
+.Nm lv2ls
+.Nd list all installed LV2 plugins
+.Sh SYNOPSIS
+.Nm lv2ls
+.Op Fl Vhn
+.Op Fl Fl help
+.Op Fl Fl names
+.Op Fl Fl version
+.Sh DESCRIPTION
+.Nm
+prints the URI of every installed LV2 plugin to stdout.
+.Pp
+Plugins are discovered with the same mechanism used by most hosts.
+The default path can be overridden by setting the
+.Ev LV2_PATH
+environment variable.
+.Pp
+The options are as follows:
+.Pp
+.Bl -tag -compact -width 3n
+.It Fl V , Fl Fl version
+Display version information and exit.
+.Pp
+.It Fl h , Fl Fl help
+Print the command line options.
+.Pp
+.It Fl n , Fl Fl names
+Show names instead of URIs.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width LV2_PATH -compact
+.It Ev LV2_PATH
+List of directories to search for LV2 plugin bundles,
+in the style of
+.Ev PATH .
+.El
+.Sh EXIT STATUS
+.Nm
+exits with a status of 0, or non-zero if an error occurred.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Xr lv2apply 1
+.It
+.Xr lv2bench 1
+.It
+.Xr lv2info 1
+.El
+.Sh AUTHORS
+.Nm
+is a part of lilv, by
+.An David Robillard
+.Aq Mt d@drobilla.net .
diff --git a/doc/meson.build b/doc/meson.build
new file mode 100644
index 0000000..32a885b
--- /dev/null
+++ b/doc/meson.build
@@ -0,0 +1,71 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+docdir = get_option('datadir') / 'doc'
+
+# Find required programs
+doxygen = find_program('doxygen', required: get_option('docs'))
+sphinx_build = find_program('sphinx-build', required: get_option('docs'))
+
+# Find sphinxygen or fall back to subproject
+sphinxygen = disabler()
+if doxygen.found() and sphinx_build.found()
+ sphinxygen = find_program('sphinxygen', required: false)
+ if not sphinxygen.found()
+ subproject('sphinxygen')
+ sphinxygen = find_program('sphinxygen', required: get_option('docs'))
+ endif
+endif
+
+# Build documentation if all required tools are found
+build_docs = doxygen.found() and sphinxygen.found() and sphinx_build.found()
+if build_docs
+ # Configure conf.py for Sphinx
+ conf_config = configuration_data()
+ conf_config.set('LILV_SRCDIR', lilv_src_root)
+ conf_config.set('LILV_TITLE', get_option('title'))
+ conf_config.set('LILV_VERSION', meson.project_version())
+ conf_py = configure_file(
+ configuration: conf_config,
+ input: files('conf.py.in'),
+ output: 'conf.py',
+ )
+
+ # Copy hand-written documentation files
+ rst_sources = files(
+ 'index.rst',
+ 'overview.rst',
+ 'plugins.rst',
+ 'uis.rst',
+ 'world.rst',
+ )
+ sphinx_input = []
+ foreach f : rst_sources
+ sphinx_input += [
+ configure_file(copy: true, input: f, output: '@PLAINNAME@'),
+ ]
+ endforeach
+
+ # Generate reference documentation input with Doxygen and Sphinxygen
+ subdir('xml')
+ subdir('api')
+
+ # Build strict Sphinx flags, with termination on warnings if werror=true
+ sphinx_in_dir = meson.current_build_dir()
+ sphinx_flags = ['-E', '-a', '-q']
+ if get_option('werror')
+ sphinx_flags += ['-W']
+ endif
+
+ # Run Sphinx to generate final documentation for each format
+ sphinx_build_command = [sphinx_build] + sphinx_flags
+ foreach format : ['html', 'singlehtml']
+ if not get_option(format).disabled()
+ subdir(format)
+ endif
+ endforeach
+endif
+
+if not meson.is_subproject()
+ summary('Documentation', build_docs, bool_yn: true, section: 'Components')
+endif
diff --git a/doc/c/overview.rst b/doc/overview.rst
index 6abc123..17ebec9 100644
--- a/doc/c/overview.rst
+++ b/doc/overview.rst
@@ -1,3 +1,7 @@
+..
+ Copyright 2020-2022 David Robillard <d@drobilla.net>
+ SPDX-License-Identifier: ISC
+
.. default-domain:: c
.. highlight:: c
diff --git a/doc/c/plugins.rst b/doc/plugins.rst
index c86431e..c7ad547 100644
--- a/doc/c/plugins.rst
+++ b/doc/plugins.rst
@@ -1,3 +1,7 @@
+..
+ Copyright 2020-2022 David Robillard <d@drobilla.net>
+ SPDX-License-Identifier: ISC
+
.. default-domain:: c
.. highlight:: c
diff --git a/doc/singlehtml/meson.build b/doc/singlehtml/meson.build
new file mode 100644
index 0000000..ed4bb71
--- /dev/null
+++ b/doc/singlehtml/meson.build
@@ -0,0 +1,33 @@
+# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+singlehtml_dir = docdir / versioned_name / 'singlehtml'
+
+# TODO: Add install_tag: 'doc' after requiring meson 0.60.0
+
+custom_target(
+ 'singlehtml',
+ build_by_default: true,
+ command: sphinx_build_command + [
+ '-b', 'singlehtml',
+ '-t', 'singlehtml',
+ sphinx_in_dir,
+ '@OUTDIR@',
+ ],
+ input: [api_lilv_rst, conf_py, sphinx_input],
+ install: true,
+ install_dir: singlehtml_dir,
+ output: [
+ 'index.html',
+
+ '_static',
+ ],
+)
+
+if not meson.is_subproject()
+ summary(
+ 'Single HTML',
+ get_option('prefix') / singlehtml_dir,
+ section: 'Directories',
+ )
+endif
diff --git a/doc/c/uis.rst b/doc/uis.rst
index 5abaa2c..1169060 100644
--- a/doc/c/uis.rst
+++ b/doc/uis.rst
@@ -1,3 +1,7 @@
+..
+ Copyright 2020-2022 David Robillard <d@drobilla.net>
+ SPDX-License-Identifier: ISC
+
.. default-domain:: c
.. highlight:: c
diff --git a/doc/c/world.rst b/doc/world.rst
index 4128f77..8b71165 100644
--- a/doc/c/world.rst
+++ b/doc/world.rst
@@ -1,3 +1,7 @@
+..
+ Copyright 2020-2022 David Robillard <d@drobilla.net>
+ SPDX-License-Identifier: ISC
+
.. default-domain:: c
.. highlight:: c
diff --git a/doc/xml/meson.build b/doc/xml/meson.build
new file mode 100644
index 0000000..eb66325
--- /dev/null
+++ b/doc/xml/meson.build
@@ -0,0 +1,36 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+doxygen = find_program('doxygen')
+
+config = configuration_data()
+config.set('LILV_SRCDIR', lilv_src_root)
+config.set('DOX_OUTPUT', meson.current_build_dir() / '..')
+
+doxyfile = configure_file(
+ configuration: config,
+ input: files('../Doxyfile.in'),
+ output: 'Doxyfile',
+)
+
+doxygen_xml = custom_target(
+ 'index.xml',
+ command: [doxygen, '@INPUT0@'],
+ input: [doxyfile] + c_headers,
+ output: [
+ 'index.xml',
+
+ 'group__lilv.xml',
+ 'group__lilv__class.xml',
+ 'group__lilv__collections.xml',
+ 'group__lilv__instance.xml',
+ 'group__lilv__node.xml',
+ 'group__lilv__plugin.xml',
+ 'group__lilv__port.xml',
+ 'group__lilv__scalepoint.xml',
+ 'group__lilv__state.xml',
+ 'group__lilv__ui.xml',
+ 'group__lilv__world.xml',
+ 'lilv_8h.xml',
+ ],
+)
diff --git a/include/lilv/lilv.h b/include/lilv/lilv.h
index 5fd7a9f..6dc42d4 100644
--- a/include/lilv/lilv.h
+++ b/include/lilv/lilv.h
@@ -1,40 +1,30 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
/// @file lilv.h API for Lilv, a lightweight LV2 host library.
#ifndef LILV_LILV_H
#define LILV_LILV_H
-#include "lv2/core/lv2.h"
-#include "lv2/urid/urid.h"
+#include <lv2/core/lv2.h>
+#include <lv2/urid/urid.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
-#if defined(_WIN32) && !defined(LILV_STATIC) && defined(LILV_INTERNAL)
-# define LILV_API __declspec(dllexport)
-#elif defined(_WIN32) && !defined(LILV_STATIC)
-# define LILV_API __declspec(dllimport)
-#elif defined(__GNUC__)
-# define LILV_API __attribute__((visibility("default")))
-#else
-# define LILV_API
+// LILV_API must be used to decorate things in the public API
+#ifndef LILV_API
+# if defined(_WIN32) && !defined(LILV_STATIC) && defined(LILV_INTERNAL)
+# define LILV_API __declspec(dllexport)
+# elif defined(_WIN32) && !defined(LILV_STATIC)
+# define LILV_API __declspec(dllimport)
+# elif defined(__GNUC__)
+# define LILV_API __attribute__((visibility("default")))
+# else
+# define LILV_API
+# endif
#endif
#if defined(__GNUC__) && \
@@ -103,8 +93,7 @@ typedef void LilvNodes; /**< A set of #LilvNode. */
library to be freed by code in the same library. It is otherwise equivalent
to the standard C free() function.
*/
-LILV_API
-void
+LILV_API void
lilv_free(void* ptr);
/**
@@ -122,9 +111,7 @@ lilv_free(void* ptr);
@return `uri` converted to a path, or NULL on failure (URI is not local).
*/
-LILV_API
-LILV_DEPRECATED
-const char*
+LILV_API LILV_DEPRECATED const char*
lilv_uri_to_path(const char* uri);
/**
@@ -137,8 +124,7 @@ lilv_uri_to_path(const char* uri);
@param hostname If non-NULL, set to the hostname in the URI, if any.
@return `uri` converted to a path, or NULL on failure (URI is not local).
*/
-LILV_API
-char*
+LILV_API char*
lilv_file_uri_parse(const char* uri, char** hostname);
/**
@@ -146,8 +132,7 @@ lilv_file_uri_parse(const char* uri, char** hostname);
Returned value must be freed by caller with lilv_node_free().
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_new_uri(LilvWorld* world, const char* uri);
/**
@@ -161,8 +146,7 @@ lilv_new_uri(LilvWorld* world, const char* uri);
@param path Path on host.
@return A new node that must be freed by caller.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_new_file_uri(LilvWorld* world, const char* host, const char* path);
/**
@@ -170,8 +154,7 @@ lilv_new_file_uri(LilvWorld* world, const char* host, const char* path);
Returned value must be freed by caller with lilv_node_free().
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_new_string(LilvWorld* world, const char* str);
/**
@@ -179,8 +162,7 @@ lilv_new_string(LilvWorld* world, const char* str);
Returned value must be freed by caller with lilv_node_free().
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_new_int(LilvWorld* world, int val);
/**
@@ -188,8 +170,7 @@ lilv_new_int(LilvWorld* world, int val);
Returned value must be freed by caller with lilv_node_free().
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_new_float(LilvWorld* world, float val);
/**
@@ -197,8 +178,7 @@ lilv_new_float(LilvWorld* world, float val);
Returned value must be freed by caller with lilv_node_free().
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_new_bool(LilvWorld* world, bool val);
/**
@@ -206,22 +186,19 @@ lilv_new_bool(LilvWorld* world, bool val);
It is safe to call this function on NULL.
*/
-LILV_API
-void
+LILV_API void
lilv_node_free(LilvNode* val);
/**
Duplicate a LilvNode.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_node_duplicate(const LilvNode* val);
/**
Return whether two values are equivalent.
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_equals(const LilvNode* value, const LilvNode* other);
/**
@@ -238,15 +215,13 @@ lilv_node_equals(const LilvNode* value, const LilvNode* other);
- Integer: 1
- Boolean: true
*/
-LILV_API
-char*
+LILV_API char*
lilv_node_get_turtle_token(const LilvNode* value);
/**
Return whether the value is a URI (resource).
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_is_uri(const LilvNode* value);
/**
@@ -255,15 +230,13 @@ lilv_node_is_uri(const LilvNode* value);
Valid to call only if `lilv_node_is_uri(value)` returns true.
Returned value is owned by `value` and must not be freed by caller.
*/
-LILV_API
-const char*
+LILV_API const char*
lilv_node_as_uri(const LilvNode* value);
/**
Return whether the value is a blank node (resource with no URI).
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_is_blank(const LilvNode* value);
/**
@@ -272,8 +245,7 @@ lilv_node_is_blank(const LilvNode* value);
Valid to call only if `lilv_node_is_blank(value)` returns true.
Returned value is owned by `value` and must not be freed by caller.
*/
-LILV_API
-const char*
+LILV_API const char*
lilv_node_as_blank(const LilvNode* value);
/**
@@ -281,8 +253,7 @@ lilv_node_as_blank(const LilvNode* value);
Returns true if `value` is a string or numeric value.
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_is_literal(const LilvNode* value);
/**
@@ -290,15 +261,13 @@ lilv_node_is_literal(const LilvNode* value);
Returns true if `value` is a string value (and not numeric).
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_is_string(const LilvNode* value);
/**
Return `value` as a string.
*/
-LILV_API
-const char*
+LILV_API const char*
lilv_node_as_string(const LilvNode* value);
/**
@@ -307,15 +276,13 @@ lilv_node_as_string(const LilvNode* value);
Returns NULL if `value` is not a file URI.
Returned value must be freed by caller with lilv_free().
*/
-LILV_API
-char*
+LILV_API char*
lilv_node_get_path(const LilvNode* value, char** hostname);
/**
Return whether this value is a decimal literal.
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_is_float(const LilvNode* value);
/**
@@ -324,15 +291,13 @@ lilv_node_is_float(const LilvNode* value);
Valid to call only if `lilv_node_is_float(value)` or
`lilv_node_is_int(value)` returns true.
*/
-LILV_API
-float
+LILV_API float
lilv_node_as_float(const LilvNode* value);
/**
Return whether this value is an integer literal.
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_is_int(const LilvNode* value);
/**
@@ -340,15 +305,13 @@ lilv_node_is_int(const LilvNode* value);
Valid to call only if `lilv_node_is_int(value)` returns true.
*/
-LILV_API
-int
+LILV_API int
lilv_node_as_int(const LilvNode* value);
/**
Return whether this value is a boolean.
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_is_bool(const LilvNode* value);
/**
@@ -356,8 +319,7 @@ lilv_node_is_bool(const LilvNode* value);
Valid to call only if `lilv_node_is_bool(value)` returns true.
*/
-LILV_API
-bool
+LILV_API bool
lilv_node_as_bool(const LilvNode* value);
/**
@@ -396,35 +358,31 @@ lilv_node_as_bool(const LilvNode* value);
@endcode
*/
#define LILV_FOREACH(colltype, iter, collection) \
+ /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
for (LilvIter* iter = lilv_##colltype##_begin(collection); \
!lilv_##colltype##_is_end(collection, iter); \
(iter) = lilv_##colltype##_next(collection, iter))
/* LilvPluginClasses */
-LILV_API
-void
+LILV_API void
lilv_plugin_classes_free(LilvPluginClasses* collection);
-LILV_API
-unsigned
+LILV_API unsigned
lilv_plugin_classes_size(const LilvPluginClasses* collection);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_plugin_classes_begin(const LilvPluginClasses* collection);
-LILV_API
-const LilvPluginClass*
-lilv_plugin_classes_get(const LilvPluginClasses* collection, LilvIter* i);
+LILV_API const LilvPluginClass*
+lilv_plugin_classes_get(const LilvPluginClasses* collection, const LilvIter* i);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_plugin_classes_next(const LilvPluginClasses* collection, LilvIter* i);
-LILV_API
-bool
-lilv_plugin_classes_is_end(const LilvPluginClasses* collection, LilvIter* i);
+LILV_API bool
+lilv_plugin_classes_is_end(const LilvPluginClasses* collection,
+ const LilvIter* i);
/**
Get a plugin class from `classes` by URI.
@@ -434,62 +392,49 @@ lilv_plugin_classes_is_end(const LilvPluginClasses* collection, LilvIter* i);
@return NULL if no plugin class with `uri` is found in `classes`.
*/
-LILV_API
-const LilvPluginClass*
+LILV_API const LilvPluginClass*
lilv_plugin_classes_get_by_uri(const LilvPluginClasses* classes,
const LilvNode* uri);
/* ScalePoints */
-LILV_API
-void
+LILV_API void
lilv_scale_points_free(LilvScalePoints* collection);
-LILV_API
-unsigned
+LILV_API unsigned
lilv_scale_points_size(const LilvScalePoints* collection);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_scale_points_begin(const LilvScalePoints* collection);
-LILV_API
-const LilvScalePoint*
-lilv_scale_points_get(const LilvScalePoints* collection, LilvIter* i);
+LILV_API const LilvScalePoint*
+lilv_scale_points_get(const LilvScalePoints* collection, const LilvIter* i);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_scale_points_next(const LilvScalePoints* collection, LilvIter* i);
-LILV_API
-bool
-lilv_scale_points_is_end(const LilvScalePoints* collection, LilvIter* i);
+LILV_API bool
+lilv_scale_points_is_end(const LilvScalePoints* collection, const LilvIter* i);
/* UIs */
-LILV_API
-void
+LILV_API void
lilv_uis_free(LilvUIs* collection);
-LILV_API
-unsigned
+LILV_API unsigned
lilv_uis_size(const LilvUIs* collection);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_uis_begin(const LilvUIs* collection);
-LILV_API
-const LilvUI*
-lilv_uis_get(const LilvUIs* collection, LilvIter* i);
+LILV_API const LilvUI*
+lilv_uis_get(const LilvUIs* collection, const LilvIter* i);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_uis_next(const LilvUIs* collection, LilvIter* i);
-LILV_API
-bool
-lilv_uis_is_end(const LilvUIs* collection, LilvIter* i);
+LILV_API bool
+lilv_uis_is_end(const LilvUIs* collection, const LilvIter* i);
/**
Get a UI from `uis` by URI.
@@ -499,75 +444,60 @@ lilv_uis_is_end(const LilvUIs* collection, LilvIter* i);
@return NULL if no UI with `uri` is found in `list`.
*/
-LILV_API
-const LilvUI*
+LILV_API const LilvUI*
lilv_uis_get_by_uri(const LilvUIs* uis, const LilvNode* uri);
/* Nodes */
-LILV_API
-void
+LILV_API void
lilv_nodes_free(LilvNodes* collection);
-LILV_API
-unsigned
+LILV_API unsigned
lilv_nodes_size(const LilvNodes* collection);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_nodes_begin(const LilvNodes* collection);
-LILV_API
-const LilvNode*
-lilv_nodes_get(const LilvNodes* collection, LilvIter* i);
+LILV_API const LilvNode*
+lilv_nodes_get(const LilvNodes* collection, const LilvIter* i);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_nodes_next(const LilvNodes* collection, LilvIter* i);
-LILV_API
-bool
-lilv_nodes_is_end(const LilvNodes* collection, LilvIter* i);
+LILV_API bool
+lilv_nodes_is_end(const LilvNodes* collection, const LilvIter* i);
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_nodes_get_first(const LilvNodes* collection);
/**
Return whether `values` contains `value`.
*/
-LILV_API
-bool
+LILV_API bool
lilv_nodes_contains(const LilvNodes* nodes, const LilvNode* value);
/**
Return a new LilvNodes that contains all nodes from both `a` and `b`.
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_nodes_merge(const LilvNodes* a, const LilvNodes* b);
/* Plugins */
-LILV_API
-unsigned
+LILV_API unsigned
lilv_plugins_size(const LilvPlugins* collection);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_plugins_begin(const LilvPlugins* collection);
-LILV_API
-const LilvPlugin*
-lilv_plugins_get(const LilvPlugins* collection, LilvIter* i);
+LILV_API const LilvPlugin*
+lilv_plugins_get(const LilvPlugins* collection, const LilvIter* i);
-LILV_API
-LilvIter*
+LILV_API LilvIter*
lilv_plugins_next(const LilvPlugins* collection, LilvIter* i);
-LILV_API
-bool
-lilv_plugins_is_end(const LilvPlugins* collection, LilvIter* i);
+LILV_API bool
+lilv_plugins_is_end(const LilvPlugins* collection, const LilvIter* i);
/**
Get a plugin from `plugins` by URI.
@@ -577,8 +507,7 @@ lilv_plugins_is_end(const LilvPlugins* collection, LilvIter* i);
@return NULL if no plugin with `uri` is found in `plugins`.
*/
-LILV_API
-const LilvPlugin*
+LILV_API const LilvPlugin*
lilv_plugins_get_by_uri(const LilvPlugins* plugins, const LilvNode* uri);
/**
@@ -598,8 +527,7 @@ lilv_plugins_get_by_uri(const LilvPlugins* plugins, const LilvNode* uri);
If initialization fails, NULL is returned.
*/
-LILV_API
-LilvWorld*
+LILV_API LilvWorld*
lilv_world_new(void);
/**
@@ -637,8 +565,7 @@ lilv_world_new(void);
- #LILV_OPTION_DYN_MANIFEST
- #LILV_OPTION_LV2_PATH
*/
-LILV_API
-void
+LILV_API void
lilv_world_set_option(LilvWorld* world, const char* uri, const LilvNode* value);
/**
@@ -648,8 +575,7 @@ lilv_world_set_option(LilvWorld* world, const char* uri, const LilvNode* value);
destroy all the objects it contains. Do not destroy the world until you are
finished with all objects that came from it.
*/
-LILV_API
-void
+LILV_API void
lilv_world_free(LilvWorld* world);
/**
@@ -664,8 +590,7 @@ lilv_world_free(LilvWorld* world);
in special circumstances such as development utilities, or hosts that ship
with special plugin bundles which are installed to a known location.
*/
-LILV_API
-void
+LILV_API void
lilv_world_load_all(LilvWorld* world);
/**
@@ -681,8 +606,7 @@ lilv_world_load_all(LilvWorld* world);
unchanged between (or even during) program invocations. Plugins (among
other things) MUST be identified by URIs (not paths) in save files.
*/
-LILV_API
-void
+LILV_API void
lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri);
/**
@@ -692,8 +616,7 @@ lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri);
necessary when using lilv_world_load_all(). This function parses the
specifications and adds them to the model.
*/
-LILV_API
-void
+LILV_API void
lilv_world_load_specifications(LilvWorld* world);
/**
@@ -703,8 +626,7 @@ lilv_world_load_specifications(LilvWorld* world);
that explicitly load specific bundles, its use is not necessary when using
lilv_world_load_all().
*/
-LILV_API
-void
+LILV_API void
lilv_world_load_plugin_classes(LilvWorld* world);
/**
@@ -715,8 +637,7 @@ lilv_world_load_plugin_classes(LilvWorld* world);
have been separately loaded with lilv_world_load_resource(), they must be
separately unloaded with lilv_world_unload_resource().
*/
-LILV_API
-int
+LILV_API int
lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri);
/**
@@ -729,8 +650,7 @@ lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri);
@param resource Must be a subject (a URI or a blank node).
@return The number of files parsed, or -1 on error
*/
-LILV_API
-int
+LILV_API int
lilv_world_load_resource(LilvWorld* world, const LilvNode* resource);
/**
@@ -742,15 +662,13 @@ lilv_world_load_resource(LilvWorld* world, const LilvNode* resource);
@param world The world.
@param resource Must be a subject (a URI or a blank node).
*/
-LILV_API
-int
+LILV_API int
lilv_world_unload_resource(LilvWorld* world, const LilvNode* resource);
/**
Get the parent of all other plugin classes, lv2:Plugin.
*/
-LILV_API
-const LilvPluginClass*
+LILV_API const LilvPluginClass*
lilv_world_get_plugin_class(const LilvWorld* world);
/**
@@ -758,8 +676,7 @@ lilv_world_get_plugin_class(const LilvWorld* world);
Returned list is owned by world and must not be freed by the caller.
*/
-LILV_API
-const LilvPluginClasses*
+LILV_API const LilvPluginClasses*
lilv_world_get_plugin_classes(const LilvWorld* world);
/**
@@ -774,8 +691,7 @@ lilv_world_get_plugin_classes(const LilvWorld* world);
The returned list and the plugins it contains are owned by `world`
and must not be freed by caller.
*/
-LILV_API
-const LilvPlugins*
+LILV_API const LilvPlugins*
lilv_world_get_all_plugins(const LilvWorld* world);
/**
@@ -785,8 +701,7 @@ lilv_world_get_all_plugins(const LilvWorld* world);
@return All matches for the wildcard field, or NULL.
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_world_find_nodes(LilvWorld* world,
const LilvNode* subject,
const LilvNode* predicate,
@@ -802,8 +717,7 @@ lilv_world_find_nodes(LilvWorld* world,
@return The first matching node, or NULL if no matches are found.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_world_get(LilvWorld* world,
const LilvNode* subject,
const LilvNode* predicate,
@@ -820,8 +734,7 @@ lilv_world_get(LilvWorld* world,
@param predicate Predicate (key) of statement, or NULL for anything.
@param object Object (value) of statement, or NULL for anything.
*/
-LILV_API
-bool
+LILV_API bool
lilv_world_ask(LilvWorld* world,
const LilvNode* subject,
const LilvNode* predicate,
@@ -835,8 +748,7 @@ lilv_world_ask(LilvWorld* world,
@return A string node that is a valid LV2 symbol, or NULL on error.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_world_get_symbol(LilvWorld* world, const LilvNode* subject);
/**
@@ -858,8 +770,7 @@ lilv_world_get_symbol(LilvWorld* world, const LilvNode* subject);
@return True iff `plugin` is valid.
*/
-LILV_API
-bool
+LILV_API bool
lilv_plugin_verify(const LilvPlugin* plugin);
/**
@@ -877,8 +788,7 @@ lilv_plugin_verify(const LilvPlugin* plugin);
@return A shared URI value which must not be modified or freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_plugin_get_uri(const LilvPlugin* plugin);
/**
@@ -895,8 +805,7 @@ lilv_plugin_get_uri(const LilvPlugin* plugin);
@return A shared string which must not be modified or freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_plugin_get_bundle_uri(const LilvPlugin* plugin);
/**
@@ -909,8 +818,7 @@ lilv_plugin_get_bundle_uri(const LilvPlugin* plugin);
@return A list of complete URLs eg. "file:///foo/ABundle.lv2/aplug.ttl",
which is shared and must not be modified or freed.
*/
-LILV_API
-const LilvNodes*
+LILV_API const LilvNodes*
lilv_plugin_get_data_uris(const LilvPlugin* plugin);
/**
@@ -921,8 +829,7 @@ lilv_plugin_get_data_uris(const LilvPlugin* plugin);
@return A shared string which must not be modified or freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_plugin_get_library_uri(const LilvPlugin* plugin);
/**
@@ -934,15 +841,13 @@ lilv_plugin_get_library_uri(const LilvPlugin* plugin);
Returned value must be freed by the caller.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_plugin_get_name(const LilvPlugin* plugin);
/**
Get the class this plugin belongs to (like "Filters" or "Effects").
*/
-LILV_API
-const LilvPluginClass*
+LILV_API const LilvPluginClass*
lilv_plugin_get_class(const LilvPlugin* plugin);
/**
@@ -959,8 +864,7 @@ lilv_plugin_get_class(const LilvPlugin* plugin);
Return value must be freed by caller with lilv_nodes_free().
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_plugin_get_value(const LilvPlugin* plugin, const LilvNode* predicate);
/**
@@ -969,8 +873,7 @@ lilv_plugin_get_value(const LilvPlugin* plugin, const LilvNode* predicate);
This will return true if the feature is an optional or required feature
of the plugin.
*/
-LILV_API
-bool
+LILV_API bool
lilv_plugin_has_feature(const LilvPlugin* plugin, const LilvNode* feature);
/**
@@ -985,8 +888,7 @@ lilv_plugin_has_feature(const LilvPlugin* plugin, const LilvNode* feature);
Returned value must be freed by caller with lilv_nodes_free().
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_plugin_get_supported_features(const LilvPlugin* plugin);
/**
@@ -1001,8 +903,7 @@ lilv_plugin_get_supported_features(const LilvPlugin* plugin);
Return value must be freed by caller with lilv_nodes_free().
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_plugin_get_required_features(const LilvPlugin* plugin);
/**
@@ -1014,15 +915,13 @@ lilv_plugin_get_required_features(const LilvPlugin* plugin);
Return value must be freed by caller with lilv_nodes_free().
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_plugin_get_optional_features(const LilvPlugin* plugin);
/**
Return whether or not a plugin provides a specific extension data.
*/
-LILV_API
-bool
+LILV_API bool
lilv_plugin_has_extension_data(const LilvPlugin* plugin, const LilvNode* uri);
/**
@@ -1031,15 +930,13 @@ lilv_plugin_has_extension_data(const LilvPlugin* plugin, const LilvNode* uri);
This can be used to find which URIs lilv_instance_get_extension_data()
will return a value for without instantiating the plugin.
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_plugin_get_extension_data(const LilvPlugin* plugin);
/**
Get the number of ports on this plugin.
*/
-LILV_API
-uint32_t
+LILV_API uint32_t
lilv_plugin_get_num_ports(const LilvPlugin* plugin);
/**
@@ -1057,8 +954,7 @@ lilv_plugin_get_num_ports(const LilvPlugin* plugin);
all float ports on a plugin, and may be significantly faster than
repeated calls to lilv_port_get_range().
*/
-LILV_API
-void
+LILV_API void
lilv_plugin_get_port_ranges_float(const LilvPlugin* plugin,
float* min_values,
float* max_values,
@@ -1071,8 +967,7 @@ lilv_plugin_get_port_ranges_float(const LilvPlugin* plugin,
desired can be found quickly. REMEMBER TO TERMINATE THE PARAMETER LIST
OF THIS FUNCTION WITH NULL OR VERY NASTY THINGS WILL HAPPEN.
*/
-LILV_API
-uint32_t
+LILV_API uint32_t
lilv_plugin_get_num_ports_of_class(const LilvPlugin* plugin,
const LilvNode* class_1,
...);
@@ -1082,8 +977,7 @@ lilv_plugin_get_num_ports_of_class(const LilvPlugin* plugin,
This function calls va_arg() on `args` but does not call va_end().
*/
-LILV_API
-uint32_t
+LILV_API uint32_t
lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* plugin,
const LilvNode* class_1,
va_list args);
@@ -1094,8 +988,7 @@ lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* plugin,
The index of the latency port can be found with
lilv_plugin_get_latency_port() ONLY if this function returns true.
*/
-LILV_API
-bool
+LILV_API bool
lilv_plugin_has_latency(const LilvPlugin* plugin);
/**
@@ -1108,15 +1001,13 @@ lilv_plugin_has_latency(const LilvPlugin* plugin);
(by hosts with the ability/need) MUST provide this port, which is a control
rate output port that reports the latency for each cycle in frames.
*/
-LILV_API
-uint32_t
+LILV_API uint32_t
lilv_plugin_get_latency_port_index(const LilvPlugin* plugin);
/**
Get a port on `plugin` by `index`.
*/
-LILV_API
-const LilvPort*
+LILV_API const LilvPort*
lilv_plugin_get_port_by_index(const LilvPlugin* plugin, uint32_t index);
/**
@@ -1125,8 +1016,7 @@ lilv_plugin_get_port_by_index(const LilvPlugin* plugin, uint32_t index);
Note this function is slower than lilv_plugin_get_port_by_index(),
especially on plugins with a very large number of ports.
*/
-LILV_API
-const LilvPort*
+LILV_API const LilvPort*
lilv_plugin_get_port_by_symbol(const LilvPlugin* plugin,
const LilvNode* symbol);
@@ -1140,8 +1030,7 @@ lilv_plugin_get_port_by_symbol(const LilvPlugin* plugin,
ports for a particular designation. If `port_class` is NULL, any port with
the given designation will be returned.
*/
-LILV_API
-const LilvPort*
+LILV_API const LilvPort*
lilv_plugin_get_port_by_designation(const LilvPlugin* plugin,
const LilvNode* port_class,
const LilvNode* designation);
@@ -1152,8 +1041,7 @@ lilv_plugin_get_port_by_designation(const LilvPlugin* plugin,
More information about the project can be read via lilv_world_find_nodes(),
typically using properties from DOAP (such as doap:name).
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_plugin_get_project(const LilvPlugin* plugin);
/**
@@ -1162,8 +1050,7 @@ lilv_plugin_get_project(const LilvPlugin* plugin);
Returns NULL if author name is not present.
Returned value must be freed by caller.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_plugin_get_author_name(const LilvPlugin* plugin);
/**
@@ -1172,8 +1059,7 @@ lilv_plugin_get_author_name(const LilvPlugin* plugin);
Returns NULL if author email address is not present.
Returned value must be freed by caller.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_plugin_get_author_email(const LilvPlugin* plugin);
/**
@@ -1182,8 +1068,7 @@ lilv_plugin_get_author_email(const LilvPlugin* plugin);
Returns NULL if author homepage is not present.
Returned value must be freed by caller.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_plugin_get_author_homepage(const LilvPlugin* plugin);
/**
@@ -1192,8 +1077,7 @@ lilv_plugin_get_author_homepage(const LilvPlugin* plugin);
The plugin will still be usable, but hosts should hide them from their
user interfaces to prevent users from using deprecated plugins.
*/
-LILV_API
-bool
+LILV_API bool
lilv_plugin_is_replaced(const LilvPlugin* plugin);
/**
@@ -1202,8 +1086,7 @@ lilv_plugin_is_replaced(const LilvPlugin* plugin);
This function is particularly useful for porting plugins in conjunction with
an LV2 bridge such as NASPRO.
*/
-LILV_API
-void
+LILV_API void
lilv_plugin_write_description(LilvWorld* world,
const LilvPlugin* plugin,
const LilvNode* base_uri,
@@ -1215,8 +1098,7 @@ lilv_plugin_write_description(LilvWorld* world,
This function is intended for use with lilv_plugin_write_description() to
write a complete description of a plugin to a bundle.
*/
-LILV_API
-void
+LILV_API void
lilv_plugin_write_manifest_entry(LilvWorld* world,
const LilvPlugin* plugin,
const LilvNode* base_uri,
@@ -1236,8 +1118,7 @@ lilv_plugin_write_manifest_entry(LilvWorld* world,
To actually load the data for each returned resource, use
lilv_world_load_resource().
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type);
/**
@@ -1253,15 +1134,13 @@ lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type);
@return A shared node which must not be modified or freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_port_get_node(const LilvPlugin* plugin, const LilvPort* port);
/**
Port analog of lilv_plugin_get_value().
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_port_get_value(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* predicate);
@@ -1273,8 +1152,7 @@ lilv_port_get_value(const LilvPlugin* plugin,
simpler to use in the common case of only caring about one value. The
caller is responsible for freeing the returned node.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_port_get(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* predicate);
@@ -1282,15 +1160,13 @@ lilv_port_get(const LilvPlugin* plugin,
/**
Return the LV2 port properties of a port.
*/
-LILV_API
-LilvNodes*
+LILV_API LilvNodes*
lilv_port_get_properties(const LilvPlugin* plugin, const LilvPort* port);
/**
Return whether a port has a certain property.
*/
-LILV_API
-bool
+LILV_API bool
lilv_port_has_property(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* property);
@@ -1301,8 +1177,7 @@ lilv_port_has_property(const LilvPlugin* plugin,
More precisely, this returns true iff the port has an atom:supports or an
ev:supportsEvent property with `event_type` as the value.
*/
-LILV_API
-bool
+LILV_API bool
lilv_port_supports_event(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* event_type);
@@ -1313,8 +1188,7 @@ lilv_port_supports_event(const LilvPlugin* plugin,
The index is only valid for the life of the plugin and may change between
versions. For a stable identifier, use the symbol.
*/
-LILV_API
-uint32_t
+LILV_API uint32_t
lilv_port_get_index(const LilvPlugin* plugin, const LilvPort* port);
/**
@@ -1323,8 +1197,7 @@ lilv_port_get_index(const LilvPlugin* plugin, const LilvPort* port);
The 'symbol' is a short string, a valid C identifier.
Returned value is owned by `port` and must not be freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_port_get_symbol(const LilvPlugin* plugin, const LilvPort* port);
/**
@@ -1334,8 +1207,7 @@ lilv_port_get_symbol(const LilvPlugin* plugin, const LilvPort* port);
data file without a language tag). Returned value must be freed by
the caller.
*/
-LILV_API
-LilvNode*
+LILV_API LilvNode*
lilv_port_get_name(const LilvPlugin* plugin, const LilvPort* port);
/**
@@ -1346,8 +1218,7 @@ lilv_port_get_name(const LilvPlugin* plugin, const LilvPort* port);
The returned list does not include lv2:Port, which is implied.
Returned value is shared and must not be destroyed by caller.
*/
-LILV_API
-const LilvNodes*
+LILV_API const LilvNodes*
lilv_port_get_classes(const LilvPlugin* plugin, const LilvPort* port);
/**
@@ -1359,8 +1230,7 @@ lilv_port_get_classes(const LilvPlugin* plugin, const LilvPort* port);
this function is designed so that Lilv is usable with any port types
without requiring explicit support in Lilv.
*/
-LILV_API
-bool
+LILV_API bool
lilv_port_is_a(const LilvPlugin* plugin,
const LilvPort* port,
const LilvNode* port_class);
@@ -1373,8 +1243,7 @@ lilv_port_is_a(const LilvPlugin* plugin,
be freed by the caller using lilv_node_free()), or NULL if the value does
not exist.
*/
-LILV_API
-void
+LILV_API void
lilv_port_get_range(const LilvPlugin* plugin,
const LilvPort* port,
LilvNode** def,
@@ -1390,8 +1259,7 @@ lilv_port_get_range(const LilvPlugin* plugin,
Returned value may be NULL if `port` has no scale points, otherwise it
must be freed by caller with lilv_scale_points_free().
*/
-LILV_API
-LilvScalePoints*
+LILV_API LilvScalePoints*
lilv_port_get_scale_points(const LilvPlugin* plugin, const LilvPort* port);
/**
@@ -1411,8 +1279,7 @@ lilv_port_get_scale_points(const LilvPlugin* plugin, const LilvPort* port);
@param node The subject of the state description (such as a preset URI).
@return A new LilvState which must be freed with lilv_state_free(), or NULL.
*/
-LILV_API
-LilvState*
+LILV_API LilvState*
lilv_state_new_from_world(LilvWorld* world,
LV2_URID_Map* map,
const LilvNode* node);
@@ -1433,8 +1300,7 @@ lilv_state_new_from_world(LilvWorld* world,
@param path The path of the file containing the state description.
@return A new LilvState which must be freed with lilv_state_free().
*/
-LILV_API
-LilvState*
+LILV_API LilvState*
lilv_state_new_from_file(LilvWorld* world,
LV2_URID_Map* map,
const LilvNode* subject,
@@ -1443,8 +1309,7 @@ lilv_state_new_from_file(LilvWorld* world,
/**
Load a state snapshot from a string made by lilv_state_to_string().
*/
-LILV_API
-LilvState*
+LILV_API LilvState*
lilv_state_new_from_string(LilvWorld* world,
LV2_URID_Map* map,
const char* str);
@@ -1541,8 +1406,7 @@ typedef const void* (*LilvGetPortValueFunc)(const char* port_symbol,
@return A new LilvState which must be freed with lilv_state_free().
*/
-LILV_API
-LilvState*
+LILV_API LilvState*
lilv_state_new_from_instance(const LilvPlugin* plugin,
LilvInstance* instance,
LV2_URID_Map* map,
@@ -1558,29 +1422,25 @@ lilv_state_new_from_instance(const LilvPlugin* plugin,
/**
Free `state`.
*/
-LILV_API
-void
+LILV_API void
lilv_state_free(LilvState* state);
/**
Return true iff `a` is equivalent to `b`.
*/
-LILV_API
-bool
+LILV_API bool
lilv_state_equals(const LilvState* a, const LilvState* b);
/**
Return the number of properties in `state`.
*/
-LILV_API
-unsigned
+LILV_API unsigned
lilv_state_get_num_properties(const LilvState* state);
/**
Get the URI of the plugin `state` applies to.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_state_get_plugin_uri(const LilvState* state);
/**
@@ -1588,22 +1448,19 @@ lilv_state_get_plugin_uri(const LilvState* state);
This may return NULL if the state has not been saved and has no URI.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_state_get_uri(const LilvState* state);
/**
Get the label of `state`.
*/
-LILV_API
-const char*
+LILV_API const char*
lilv_state_get_label(const LilvState* state);
/**
Set the label of `state`.
*/
-LILV_API
-void
+LILV_API void
lilv_state_set_label(LilvState* state, const char* label);
/**
@@ -1621,8 +1478,7 @@ lilv_state_set_label(LilvState* state, const char* label);
@param flags LV2_State_Flags for `value`.
@return Zero on success.
*/
-LILV_API
-int
+LILV_API int
lilv_state_set_metadata(LilvState* state,
uint32_t key,
const void* value,
@@ -1657,8 +1513,7 @@ typedef void (*LilvSetPortValueFunc)(const char* port_symbol,
@param set_value A function to receive port values.
@param user_data User data to pass to `set_value`.
*/
-LILV_API
-void
+LILV_API void
lilv_state_emit_port_values(const LilvState* state,
LilvSetPortValueFunc set_value,
void* user_data);
@@ -1687,8 +1542,7 @@ lilv_state_emit_port_values(const LilvState* state,
@param flags Bitwise OR of LV2_State_Flags values.
@param features Features to pass LV2_State_Interface.restore().
*/
-LILV_API
-void
+LILV_API void
lilv_state_restore(const LilvState* state,
LilvInstance* instance,
LilvSetPortValueFunc set_value,
@@ -1714,8 +1568,7 @@ lilv_state_restore(const LilvState* state,
@param dir Path of the bundle directory to save into.
@param filename Path of the state file relative to `dir`.
*/
-LILV_API
-int
+LILV_API int
lilv_state_save(LilvWorld* world,
LV2_URID_Map* map,
LV2_URID_Unmap* unmap,
@@ -1743,8 +1596,7 @@ lilv_state_save(LilvWorld* world,
doing, pass NULL for this, otherwise the state may not be restorable via
lilv_state_new_from_string().
*/
-LILV_API
-char*
+LILV_API char*
lilv_state_to_string(LilvWorld* world,
LV2_URID_Map* map,
LV2_URID_Unmap* unmap,
@@ -1767,8 +1619,7 @@ lilv_state_to_string(LilvWorld* world,
@param world The world.
@param state State to remove from the system.
*/
-LILV_API
-int
+LILV_API int
lilv_state_delete(LilvWorld* world, const LilvState* state);
/**
@@ -1782,8 +1633,7 @@ lilv_state_delete(LilvWorld* world, const LilvState* state);
Returned value is owned by `point` and must not be freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_scale_point_get_label(const LilvScalePoint* point);
/**
@@ -1791,8 +1641,7 @@ lilv_scale_point_get_label(const LilvScalePoint* point);
Returned value is owned by `point` and must not be freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_scale_point_get_value(const LilvScalePoint* point);
/**
@@ -1807,8 +1656,7 @@ lilv_scale_point_get_value(const LilvScalePoint* point);
Returned value is owned by `plugin_class` and must not be freed by caller.
Returned value may be NULL, if class has no parent.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_plugin_class_get_parent_uri(const LilvPluginClass* plugin_class);
/**
@@ -1816,8 +1664,7 @@ lilv_plugin_class_get_parent_uri(const LilvPluginClass* plugin_class);
Returned value is owned by `plugin_class` and must not be freed by caller.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_plugin_class_get_uri(const LilvPluginClass* plugin_class);
/**
@@ -1825,8 +1672,7 @@ lilv_plugin_class_get_uri(const LilvPluginClass* plugin_class);
Returned value is owned by `plugin_class` and must not be freed by caller.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_plugin_class_get_label(const LilvPluginClass* plugin_class);
/**
@@ -1834,8 +1680,7 @@ lilv_plugin_class_get_label(const LilvPluginClass* plugin_class);
Returned value must be freed by caller with lilv_plugin_classes_free().
*/
-LILV_API
-LilvPluginClasses*
+LILV_API LilvPluginClasses*
lilv_plugin_class_get_children(const LilvPluginClass* plugin_class);
/**
@@ -1875,10 +1720,12 @@ struct LilvInstanceImpl {
`features` is a NULL-terminated array of features the host supports.
NULL may be passed if the host supports no additional features.
+ This function is in the "discovery" threading class: it isn't real-time
+ safe, and may not be called concurrently with itself for the same plugin.
+
@return NULL if instantiation failed.
*/
-LILV_API
-LilvInstance*
+LILV_API LilvInstance*
lilv_plugin_instantiate(const LilvPlugin* plugin,
double sample_rate,
const LV2_Feature* const* features);
@@ -1886,11 +1733,14 @@ lilv_plugin_instantiate(const LilvPlugin* plugin,
/**
Free a plugin instance.
- It is safe to call this function on NULL.
- `instance` is invalid after this call.
+ It is safe to call this function on NULL. The `instance` is invalid after
+ this call.
+
+ This function is in the "discovery" threading class: it isn't real-time
+ safe, and may not be called concurrently with any other function for the
+ same instance, or with lilv_plugin_instantiate() for the same plugin.
*/
-LILV_API
-void
+LILV_API void
lilv_instance_free(LilvInstance* instance);
#ifndef LILV_INTERNAL
@@ -1898,7 +1748,8 @@ lilv_instance_free(LilvInstance* instance);
/**
Get the URI of the plugin which `instance` is an instance of.
- Returned string is shared and must not be modified or deleted.
+ This function is a simple accessor and may be called at any time. The
+ returned string is shared and must not be modified or deleted.
*/
static inline const char*
lilv_instance_get_uri(const LilvInstance* instance)
@@ -1911,6 +1762,10 @@ lilv_instance_get_uri(const LilvInstance* instance)
This may be called regardless of whether the plugin is activated,
activation and deactivation does not destroy port connections.
+
+ This function is in the "audio" threading class: it's real-time safe if the
+ plugin is <http://lv2plug.in/ns/lv2core#hardRTCapable>, but may not be
+ called concurrently with any other function for the same instance.
*/
static inline void
lilv_instance_connect_port(LilvInstance* instance,
@@ -1927,6 +1782,10 @@ lilv_instance_connect_port(LilvInstance* instance,
This resets all state information in the plugin, except for port data
locations (as set by lilv_instance_connect_port()). This MUST be called
before calling lilv_instance_run().
+
+ This function is in the "instantiation" threading class: it isn't real-time
+ safe, and may not be called concurrently with any other function for the
+ same instance.
*/
static inline void
lilv_instance_activate(LilvInstance* instance)
@@ -1941,6 +1800,10 @@ lilv_instance_activate(LilvInstance* instance)
If the hint lv2:hardRTCapable is set for this plugin, this function is
guaranteed not to block.
+
+ This function is in the "audio" threading class: it's real-time safe if the
+ plugin is <http://lv2plug.in/ns/lv2core#hardRTCapable>, but may not be
+ called concurrently with any other function for the same instance.
*/
static inline void
lilv_instance_run(LilvInstance* instance, uint32_t sample_count)
@@ -1953,6 +1816,10 @@ lilv_instance_run(LilvInstance* instance, uint32_t sample_count)
Note that to run the plugin after this you must activate it, which will
reset all state information (except port connections).
+
+ This function is in the "instantiation" threading class: it isn't real-time
+ safe and may not be called concurrently with any other function for the same
+ instance.
*/
static inline void
lilv_instance_deactivate(LilvInstance* instance)
@@ -1967,6 +1834,10 @@ lilv_instance_deactivate(LilvInstance* instance)
The type and semantics of the data returned is specific to the particular
extension, though in all cases it is shared and must not be deleted.
+
+ This function is in the "discovery" threading class: it isn't real-time safe
+ and may not be called concurrently with any other function for the same
+ instance.
*/
static inline const void*
lilv_instance_get_extension_data(const LilvInstance* instance, const char* uri)
@@ -1985,6 +1856,8 @@ lilv_instance_get_extension_data(const LilvInstance* instance, const char* uri)
use the lilv_instance_* functions.
The returned descriptor is shared and must not be deleted.
+
+ This function is a simple accessor and may be called at any time.
*/
static inline const LV2_Descriptor*
lilv_instance_get_descriptor(const LilvInstance* instance)
@@ -1999,6 +1872,8 @@ lilv_instance_get_descriptor(const LilvInstance* instance)
use the lilv_instance_* functions.
The returned handle is shared and must not be deleted.
+
+ This function is a simple accessor and may be called at any time.
*/
static inline LV2_Handle
lilv_instance_get_handle(const LilvInstance* instance)
@@ -2019,8 +1894,7 @@ lilv_instance_get_handle(const LilvInstance* instance)
Returned value must be freed by caller using lilv_uis_free().
*/
-LILV_API
-LilvUIs*
+LILV_API LilvUIs*
lilv_plugin_get_uis(const LilvPlugin* plugin);
/**
@@ -2028,8 +1902,7 @@ lilv_plugin_get_uis(const LilvPlugin* plugin);
@return A shared value which must not be modified or freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_ui_get_uri(const LilvUI* ui);
/**
@@ -2040,8 +1913,7 @@ lilv_ui_get_uri(const LilvUI* ui);
@return A shared value which must not be modified or freed.
*/
-LILV_API
-const LilvNodes*
+LILV_API const LilvNodes*
lilv_ui_get_classes(const LilvUI* ui);
/**
@@ -2050,8 +1922,7 @@ lilv_ui_get_classes(const LilvUI* ui);
@param ui The Plugin UI
@param class_uri The URI of the LV2 UI type to check this UI against
*/
-LILV_API
-bool
+LILV_API bool
lilv_ui_is_a(const LilvUI* ui, const LilvNode* class_uri);
/**
@@ -2077,8 +1948,7 @@ typedef unsigned (*LilvUISupportedFunc)(const char* container_type_uri,
@return The embedding quality level returned by `supported_func`.
*/
-LILV_API
-unsigned
+LILV_API unsigned
lilv_ui_is_supported(const LilvUI* ui,
LilvUISupportedFunc supported_func,
const LilvNode* container_type,
@@ -2089,8 +1959,7 @@ lilv_ui_is_supported(const LilvUI* ui,
@return A shared value which must not be modified or freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_ui_get_bundle_uri(const LilvUI* ui);
/**
@@ -2098,8 +1967,7 @@ lilv_ui_get_bundle_uri(const LilvUI* ui);
@return A shared value which must not be modified or freed.
*/
-LILV_API
-const LilvNode*
+LILV_API const LilvNode*
lilv_ui_get_binary_uri(const LilvUI* ui);
/**
diff --git a/include/lilv/lilvmm.hpp b/include/lilv/lilvmm.hpp
index 0ac802d..0d268d9 100644
--- a/include/lilv/lilvmm.hpp
+++ b/include/lilv/lilvmm.hpp
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2017 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2017 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef LILV_LILVMM_HPP
#define LILV_LILVMM_HPP
-#include "lilv/lilv.h"
-#include "lv2/core/lv2.h"
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
#include <cstdarg>
#include <cstdint>
@@ -47,8 +34,7 @@ struct UI;
struct UIs;
struct World;
-LILV_DEPRECATED
-static inline const char*
+LILV_DEPRECATED static inline const char*
uri_to_path(const char* uri)
{
return lilv_uri_to_path(uri);
@@ -60,20 +46,35 @@ uri_to_path(const char* uri)
# pragma GCC diagnostic pop
#endif
-#define LILV_WRAP0(RT, prefix, name) \
- inline RT name() { return lilv_##prefix##_##name(me); }
+#define LILV_WRAP0(RT, prefix, name) \
+ inline RT name() \
+ { \
+ return lilv_##prefix##_##name(me); \
+ }
#define LILV_WRAP0_VOID(prefix, name) \
- inline void name() { lilv_##prefix##_##name(me); }
+ inline void name() \
+ { \
+ lilv_##prefix##_##name(me); \
+ }
#define LILV_WRAP1(RT, prefix, name, T1, a1) \
- inline RT name(T1 a1) { return lilv_##prefix##_##name(me, a1); }
+ inline RT name(T1 a1) \
+ { \
+ return lilv_##prefix##_##name(me, a1); \
+ }
#define LILV_WRAP1_VOID(prefix, name, T1, a1) \
- inline void name(T1 a1) { lilv_##prefix##_##name(me, a1); }
+ inline void name(T1 a1) \
+ { \
+ lilv_##prefix##_##name(me, a1); \
+ }
#define LILV_WRAP2(RT, prefix, name, T1, a1, T2, a2) \
- inline RT name(T1 a1, T2 a2) { return lilv_##prefix##_##name(me, a1, a2); }
+ inline RT name(T1 a1, T2 a2) \
+ { \
+ return lilv_##prefix##_##name(me, a1, a2); \
+ }
#define LILV_WRAP3(RT, prefix, name, T1, a1, T2, a2, T3, a3) \
inline RT name(T1 a1, T2 a2, T3 a3) \
@@ -82,25 +83,31 @@ uri_to_path(const char* uri)
}
#define LILV_WRAP2_VOID(prefix, name, T1, a1, T2, a2) \
- inline void name(T1 a1, T2 a2) { lilv_##prefix##_##name(me, a1, a2); }
+ inline void name(T1 a1, T2 a2) \
+ { \
+ lilv_##prefix##_##name(me, a1, a2); \
+ }
#ifndef SWIG
# define LILV_WRAP_CONVERSION(CT) \
- inline operator CT*() const { return me; }
+ inline operator CT*() const \
+ { \
+ return me; \
+ }
#else
# define LILV_WRAP_CONVERSION(CT)
#endif
struct Node {
- inline Node(const LilvNode* node)
+ Node(const LilvNode* node)
: me(lilv_node_duplicate(node))
{}
- inline Node(const Node& copy)
+ Node(const Node& copy)
: me(lilv_node_duplicate(copy.me))
{}
- inline Node& operator=(const Node& rhs)
+ Node& operator=(const Node& rhs)
{
if (&rhs != this) {
lilv_node_free(me);
@@ -109,13 +116,13 @@ struct Node {
return *this;
}
- inline Node(Node&& other) noexcept
+ Node(Node&& other) noexcept
: me(other.me)
{
other.me = nullptr;
}
- inline Node& operator=(Node&& rhs) noexcept
+ Node& operator=(Node&& rhs) noexcept
{
if (&rhs != this) {
me = rhs.me;
@@ -124,121 +131,121 @@ struct Node {
return *this;
}
- inline ~Node() { lilv_node_free(me); }
+ ~Node() { lilv_node_free(me); }
- inline bool equals(const Node& other) const
+ bool equals(const Node& other) const
{
return lilv_node_equals(me, other.me);
}
- inline bool operator==(const Node& other) const { return equals(other); }
-
- LILV_WRAP_CONVERSION(LilvNode);
-
- LILV_WRAP0(char*, node, get_turtle_token);
- LILV_WRAP0(bool, node, is_uri);
- LILV_WRAP0(const char*, node, as_uri);
- LILV_WRAP0(bool, node, is_blank);
- LILV_WRAP0(const char*, node, as_blank);
- LILV_WRAP0(bool, node, is_literal);
- LILV_WRAP0(bool, node, is_string);
- LILV_WRAP0(const char*, node, as_string);
- LILV_WRAP0(bool, node, is_float);
- LILV_WRAP0(float, node, as_float);
- LILV_WRAP0(bool, node, is_int);
- LILV_WRAP0(int, node, as_int);
- LILV_WRAP0(bool, node, is_bool);
- LILV_WRAP0(bool, node, as_bool);
+ bool operator==(const Node& other) const { return equals(other); }
+
+ LILV_WRAP_CONVERSION(LilvNode)
+
+ LILV_WRAP0(char*, node, get_turtle_token)
+ LILV_WRAP0(bool, node, is_uri)
+ LILV_WRAP0(const char*, node, as_uri)
+ LILV_WRAP0(bool, node, is_blank)
+ LILV_WRAP0(const char*, node, as_blank)
+ LILV_WRAP0(bool, node, is_literal)
+ LILV_WRAP0(bool, node, is_string)
+ LILV_WRAP0(const char*, node, as_string)
+ LILV_WRAP0(bool, node, is_float)
+ LILV_WRAP0(float, node, as_float)
+ LILV_WRAP0(bool, node, is_int)
+ LILV_WRAP0(int, node, as_int)
+ LILV_WRAP0(bool, node, is_bool)
+ LILV_WRAP0(bool, node, as_bool)
LilvNode* me;
};
struct ScalePoint {
- inline ScalePoint(const LilvScalePoint* c_obj)
+ ScalePoint(const LilvScalePoint* c_obj)
: me(c_obj)
{}
- LILV_WRAP_CONVERSION(const LilvScalePoint);
+ LILV_WRAP_CONVERSION(const LilvScalePoint)
- LILV_WRAP0(const LilvNode*, scale_point, get_label);
- LILV_WRAP0(const LilvNode*, scale_point, get_value);
+ LILV_WRAP0(const LilvNode*, scale_point, get_label)
+ LILV_WRAP0(const LilvNode*, scale_point, get_value)
const LilvScalePoint* me;
};
struct PluginClass {
- inline PluginClass(const LilvPluginClass* c_obj)
+ PluginClass(const LilvPluginClass* c_obj)
: me(c_obj)
{}
- LILV_WRAP_CONVERSION(const LilvPluginClass);
+ LILV_WRAP_CONVERSION(const LilvPluginClass)
- LILV_WRAP0(Node, plugin_class, get_parent_uri);
- LILV_WRAP0(Node, plugin_class, get_uri);
- LILV_WRAP0(Node, plugin_class, get_label);
- LILV_WRAP0(LilvPluginClasses*, plugin_class, get_children);
+ LILV_WRAP0(Node, plugin_class, get_parent_uri)
+ LILV_WRAP0(Node, plugin_class, get_uri)
+ LILV_WRAP0(Node, plugin_class, get_label)
+ LILV_WRAP0(LilvPluginClasses*, plugin_class, get_children)
const LilvPluginClass* me;
};
-#define LILV_WRAP_COLL(CT, ET, prefix) \
- inline CT(const Lilv##CT* c_obj) \
- : me(c_obj) \
- {} \
- LILV_WRAP_CONVERSION(const Lilv##CT); \
- LILV_WRAP0(unsigned, prefix, size); \
- LILV_WRAP1(ET, prefix, get, LilvIter*, i); \
- LILV_WRAP0(LilvIter*, prefix, begin); \
- LILV_WRAP1(LilvIter*, prefix, next, LilvIter*, i); \
- LILV_WRAP1(bool, prefix, is_end, LilvIter*, i); \
+#define LILV_WRAP_COLL(CT, ET, prefix) \
+ inline CT(const Lilv##CT* c_obj) \
+ : me(c_obj) \
+ {} \
+ LILV_WRAP_CONVERSION(const Lilv##CT) \
+ LILV_WRAP0(unsigned, prefix, size) \
+ LILV_WRAP1(ET, prefix, get, const LilvIter*, i) \
+ LILV_WRAP0(LilvIter*, prefix, begin) \
+ LILV_WRAP1(LilvIter*, prefix, next, LilvIter*, i) \
+ LILV_WRAP1(bool, prefix, is_end, const LilvIter*, i) \
const Lilv##CT* me;
struct PluginClasses {
- LILV_WRAP_COLL(PluginClasses, PluginClass, plugin_classes);
- LILV_WRAP1(PluginClass, plugin_classes, get_by_uri, const LilvNode*, uri);
+ LILV_WRAP_COLL(PluginClasses, PluginClass, plugin_classes)
+ LILV_WRAP1(PluginClass, plugin_classes, get_by_uri, const LilvNode*, uri)
};
struct ScalePoints {
- LILV_WRAP_COLL(ScalePoints, ScalePoint, scale_points);
+ LILV_WRAP_COLL(ScalePoints, ScalePoint, scale_points)
};
struct Nodes {
- LILV_WRAP_COLL(Nodes, Node, nodes);
- LILV_WRAP1(bool, nodes, contains, const Node&, node);
- LILV_WRAP0(Node, nodes, get_first);
+ LILV_WRAP_COLL(Nodes, Node, nodes)
+ LILV_WRAP1(bool, nodes, contains, const Node&, node)
+ LILV_WRAP0(Node, nodes, get_first)
};
struct UI {
- inline UI(const LilvUI* c_obj)
+ UI(const LilvUI* c_obj)
: me(c_obj)
{}
- LILV_WRAP_CONVERSION(const LilvUI);
+ LILV_WRAP_CONVERSION(const LilvUI)
- LILV_WRAP0(const LilvNode*, ui, get_uri);
- LILV_WRAP0(const LilvNode*, ui, get_bundle_uri);
- LILV_WRAP0(const LilvNode*, ui, get_binary_uri);
- LILV_WRAP0(const LilvNodes*, ui, get_classes);
+ LILV_WRAP0(const LilvNode*, ui, get_uri)
+ LILV_WRAP0(const LilvNode*, ui, get_bundle_uri)
+ LILV_WRAP0(const LilvNode*, ui, get_binary_uri)
+ LILV_WRAP0(const LilvNodes*, ui, get_classes)
/*LILV_WRAP3(bool, ui, is_supported,
LilvUISupportedFunc, supported_func,
const LilvNode*, container_type,
const LilvNode**, ui_type);*/
- LILV_WRAP1(bool, ui, is_a, const LilvNode*, class_uri);
+ LILV_WRAP1(bool, ui, is_a, const LilvNode*, class_uri)
const LilvUI* me;
};
struct UIs {
- LILV_WRAP_COLL(UIs, UI, uis);
+ LILV_WRAP_COLL(UIs, UI, uis)
};
struct Port {
- inline Port(const LilvPlugin* p, const LilvPort* c_obj)
+ Port(const LilvPlugin* p, const LilvPort* c_obj)
: parent(p)
, me(c_obj)
{}
- LILV_WRAP_CONVERSION(const LilvPort);
+ LILV_WRAP_CONVERSION(const LilvPort)
#define LILV_PORT_WRAP0(RT, name) \
inline RT name() { return lilv_port_##name(parent, me); }
@@ -246,15 +253,15 @@ struct Port {
#define LILV_PORT_WRAP1(RT, name, T1, a1) \
inline RT name(T1 a1) { return lilv_port_##name(parent, me, a1); }
- LILV_PORT_WRAP1(LilvNodes*, get_value, LilvNode*, predicate);
+ LILV_PORT_WRAP1(LilvNodes*, get_value, const LilvNode*, predicate)
LILV_PORT_WRAP0(LilvNodes*, get_properties)
- LILV_PORT_WRAP1(bool, has_property, LilvNode*, property_uri);
- LILV_PORT_WRAP1(bool, supports_event, LilvNode*, event_uri);
- LILV_PORT_WRAP0(const LilvNode*, get_symbol);
- LILV_PORT_WRAP0(LilvNode*, get_name);
- LILV_PORT_WRAP0(const LilvNodes*, get_classes);
- LILV_PORT_WRAP1(bool, is_a, LilvNode*, port_class);
- LILV_PORT_WRAP0(LilvScalePoints*, get_scale_points);
+ LILV_PORT_WRAP1(bool, has_property, const LilvNode*, property_uri)
+ LILV_PORT_WRAP1(bool, supports_event, const LilvNode*, event_uri)
+ LILV_PORT_WRAP0(const LilvNode*, get_symbol)
+ LILV_PORT_WRAP0(LilvNode*, get_name)
+ LILV_PORT_WRAP0(const LilvNodes*, get_classes)
+ LILV_PORT_WRAP1(bool, is_a, const LilvNode*, port_class)
+ LILV_PORT_WRAP0(LilvScalePoints*, get_scale_points)
// TODO: get_range (output parameters)
@@ -263,56 +270,55 @@ struct Port {
};
struct Plugin {
- inline Plugin(const LilvPlugin* c_obj)
+ Plugin(const LilvPlugin* c_obj)
: me(c_obj)
{}
- LILV_WRAP_CONVERSION(const LilvPlugin);
-
- LILV_WRAP0(bool, plugin, verify);
- LILV_WRAP0(Node, plugin, get_uri);
- LILV_WRAP0(Node, plugin, get_bundle_uri);
- LILV_WRAP0(Nodes, plugin, get_data_uris);
- LILV_WRAP0(Node, plugin, get_library_uri);
- LILV_WRAP0(Node, plugin, get_name);
- LILV_WRAP0(PluginClass, plugin, get_class);
- LILV_WRAP1(Nodes, plugin, get_value, const Node&, pred);
- LILV_WRAP1(bool, plugin, has_feature, const Node&, feature_uri);
- LILV_WRAP0(Nodes, plugin, get_supported_features);
- LILV_WRAP0(Nodes, plugin, get_required_features);
- LILV_WRAP0(Nodes, plugin, get_optional_features);
- LILV_WRAP0(unsigned, plugin, get_num_ports);
- LILV_WRAP0(bool, plugin, has_latency);
- LILV_WRAP0(unsigned, plugin, get_latency_port_index);
- LILV_WRAP0(Node, plugin, get_author_name);
- LILV_WRAP0(Node, plugin, get_author_email);
- LILV_WRAP0(Node, plugin, get_author_homepage);
- LILV_WRAP0(bool, plugin, is_replaced);
- LILV_WRAP0(Nodes, plugin, get_extension_data);
- LILV_WRAP0(UIs, plugin, get_uis);
- LILV_WRAP1(Nodes, plugin, get_related, const Node&, type);
-
- inline Port get_port_by_index(unsigned index) const
+ LILV_WRAP_CONVERSION(const LilvPlugin)
+
+ LILV_WRAP0(bool, plugin, verify)
+ LILV_WRAP0(Node, plugin, get_uri)
+ LILV_WRAP0(Node, plugin, get_bundle_uri)
+ LILV_WRAP0(Nodes, plugin, get_data_uris)
+ LILV_WRAP0(Node, plugin, get_library_uri)
+ LILV_WRAP0(Node, plugin, get_name)
+ LILV_WRAP0(PluginClass, plugin, get_class)
+ LILV_WRAP1(Nodes, plugin, get_value, const Node&, pred)
+ LILV_WRAP1(bool, plugin, has_feature, const Node&, feature_uri)
+ LILV_WRAP0(Nodes, plugin, get_supported_features)
+ LILV_WRAP0(Nodes, plugin, get_required_features)
+ LILV_WRAP0(Nodes, plugin, get_optional_features)
+ LILV_WRAP0(unsigned, plugin, get_num_ports)
+ LILV_WRAP0(bool, plugin, has_latency)
+ LILV_WRAP0(unsigned, plugin, get_latency_port_index)
+ LILV_WRAP0(Node, plugin, get_author_name)
+ LILV_WRAP0(Node, plugin, get_author_email)
+ LILV_WRAP0(Node, plugin, get_author_homepage)
+ LILV_WRAP0(bool, plugin, is_replaced)
+ LILV_WRAP0(Nodes, plugin, get_extension_data)
+ LILV_WRAP0(UIs, plugin, get_uis)
+ LILV_WRAP1(Nodes, plugin, get_related, const Node&, type)
+
+ Port get_port_by_index(unsigned index) const
{
return Port(me, lilv_plugin_get_port_by_index(me, index));
}
- inline Port get_port_by_symbol(LilvNode* symbol) const
+ Port get_port_by_symbol(const LilvNode* symbol) const
{
return Port(me, lilv_plugin_get_port_by_symbol(me, symbol));
}
- inline void get_port_ranges_float(float* min_values,
- float* max_values,
- float* def_values) const
+ void get_port_ranges_float(float* min_values,
+ float* max_values,
+ float* def_values) const
{
- return lilv_plugin_get_port_ranges_float(
- me, min_values, max_values, def_values);
+ lilv_plugin_get_port_ranges_float(me, min_values, max_values, def_values);
}
- inline unsigned get_num_ports_of_class(LilvNode* class_1, ...) const
+ unsigned get_num_ports_of_class(LilvNode* class_1, ...) const
{
- va_list args;
+ va_list args; // NOLINT(cppcoreguidelines-init-variables)
va_start(args, class_1);
const uint32_t count =
@@ -326,111 +332,102 @@ struct Plugin {
};
struct Plugins {
- LILV_WRAP_COLL(Plugins, Plugin, plugins);
- LILV_WRAP1(Plugin, plugins, get_by_uri, const LilvNode*, uri);
+ LILV_WRAP_COLL(Plugins, Plugin, plugins)
+ LILV_WRAP1(Plugin, plugins, get_by_uri, const LilvNode*, uri)
};
struct Instance {
- inline Instance(LilvInstance* instance)
+ Instance(LilvInstance* instance)
: me(instance)
{}
- LILV_DEPRECATED
- inline Instance(Plugin plugin, double sample_rate)
- {
- me = lilv_plugin_instantiate(plugin, sample_rate, nullptr);
- }
+ LILV_DEPRECATED Instance(Plugin plugin, double sample_rate)
+ : me(lilv_plugin_instantiate(plugin, sample_rate, nullptr))
+ {}
- LILV_DEPRECATED inline Instance(Plugin plugin,
- double sample_rate,
- LV2_Feature* const* features)
- {
- me = lilv_plugin_instantiate(plugin, sample_rate, features);
- }
+ LILV_DEPRECATED Instance(Plugin plugin,
+ double sample_rate,
+ LV2_Feature* const* features)
+ : me(lilv_plugin_instantiate(plugin, sample_rate, features))
+ {}
- static inline Instance* create(Plugin plugin,
- double sample_rate,
- LV2_Feature* const* features)
+ static Instance* create(Plugin plugin,
+ double sample_rate,
+ LV2_Feature* const* features)
{
LilvInstance* me = lilv_plugin_instantiate(plugin, sample_rate, features);
return me ? new Instance(me) : nullptr;
}
- LILV_WRAP_CONVERSION(LilvInstance);
+ LILV_WRAP_CONVERSION(LilvInstance)
LILV_WRAP2_VOID(instance,
connect_port,
unsigned,
port_index,
void*,
- data_location);
+ data_location)
- LILV_WRAP0_VOID(instance, activate);
- LILV_WRAP1_VOID(instance, run, unsigned, sample_count);
- LILV_WRAP0_VOID(instance, deactivate);
+ LILV_WRAP0_VOID(instance, activate)
+ LILV_WRAP1_VOID(instance, run, unsigned, sample_count)
+ LILV_WRAP0_VOID(instance, deactivate)
- inline const void* get_extension_data(const char* uri) const
+ const void* get_extension_data(const char* uri) const
{
return lilv_instance_get_extension_data(me, uri);
}
- inline const LV2_Descriptor* get_descriptor() const
+ const LV2_Descriptor* get_descriptor() const
{
return lilv_instance_get_descriptor(me);
}
- inline LV2_Handle get_handle() const { return lilv_instance_get_handle(me); }
+ LV2_Handle get_handle() const { return lilv_instance_get_handle(me); }
LilvInstance* me;
};
struct World {
- inline World()
+ World()
: me(lilv_world_new())
{}
- inline ~World() { lilv_world_free(me); }
+ ~World() { lilv_world_free(me); }
- World(const World&) = delete;
+ World(const World&) = delete;
World& operator=(const World&) = delete;
- World(World&&) = delete;
+ World(World&&) = delete;
World& operator=(World&&) = delete;
- inline LilvNode* new_uri(const char* uri) const
- {
- return lilv_new_uri(me, uri);
- }
+ LilvNode* new_uri(const char* uri) const { return lilv_new_uri(me, uri); }
- inline LilvNode* new_string(const char* str) const
+ LilvNode* new_string(const char* str) const
{
return lilv_new_string(me, str);
}
- inline LilvNode* new_int(int val) const { return lilv_new_int(me, val); }
+ LilvNode* new_int(int val) const { return lilv_new_int(me, val); }
- inline LilvNode* new_float(float val) const
- {
- return lilv_new_float(me, val);
- }
+ LilvNode* new_float(float val) const { return lilv_new_float(me, val); }
- inline LilvNode* new_bool(bool val) const { return lilv_new_bool(me, val); }
+ LilvNode* new_bool(bool val) const { return lilv_new_bool(me, val); }
- inline Nodes find_nodes(const LilvNode* subject,
- const LilvNode* predicate,
- const LilvNode* object) const
+ Nodes find_nodes(const LilvNode* subject,
+ const LilvNode* predicate,
+ const LilvNode* object) const
{
return lilv_world_find_nodes(me, subject, predicate, object);
}
- LILV_WRAP2_VOID(world, set_option, const char*, uri, LilvNode*, value);
- LILV_WRAP0_VOID(world, load_all);
- LILV_WRAP1_VOID(world, load_bundle, LilvNode*, bundle_uri);
- LILV_WRAP0(const LilvPluginClass*, world, get_plugin_class);
- LILV_WRAP0(const LilvPluginClasses*, world, get_plugin_classes);
- LILV_WRAP0(Plugins, world, get_all_plugins);
- LILV_WRAP1(int, world, load_resource, const LilvNode*, resource);
+ LILV_WRAP2_VOID(world, set_option, const char*, uri, const LilvNode*, value)
+ LILV_WRAP0_VOID(world, load_all)
+ LILV_WRAP1_VOID(world, load_bundle, const LilvNode*, bundle_uri)
+ LILV_WRAP0(const LilvPluginClass*, world, get_plugin_class)
+ LILV_WRAP0(const LilvPluginClasses*, world, get_plugin_classes)
+ LILV_WRAP0(Plugins, world, get_all_plugins)
+ LILV_WRAP1(int, world, load_resource, const LilvNode*, resource)
LilvWorld* me;
};
diff --git a/lilv.pc.in b/lilv.pc.in
deleted file mode 100644
index 97f4f8c..0000000
--- a/lilv.pc.in
+++ /dev/null
@@ -1,11 +0,0 @@
-prefix=@PREFIX@
-exec_prefix=@EXEC_PREFIX@
-libdir=@LIBDIR@
-includedir=@INCLUDEDIR@
-
-Name: Lilv
-Version: @LILV_VERSION@
-Description: Simple C library for hosting LV2 plugins
-Requires: @LILV_PKG_DEPS@
-Libs: -L${libdir} -l@LIB_LILV@ @LILV_PKG_LIBS@
-Cflags: -I${includedir}/lilv-@LILV_MAJOR_VERSION@
diff --git a/lilv.ttl b/lilv.ttl
index edfb0e5..9bdd56d 100644
--- a/lilv.ttl
+++ b/lilv.ttl
@@ -1,29 +1,29 @@
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix : <http://usefulinc.com/ns/doap#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
-<http://drobilla.net/software/lilv>
- a :Project ;
- :bug-database <http://dev.drobilla.net/query?status=new&status=assigned&status=reopened&component=LILV&order=priority> ;
- :developer [
- a foaf:Person ;
- rdfs:seeAlso <http://drobilla.net/drobilla.rdf> ;
- foaf:homepage <http://drobilla.net> ;
- foaf:mbox_sha1sum "253b3c58086250260bac1232d744d150274ad308" ;
- foaf:name "David Robillard"
- ] ;
- :download-page <http://download.drobilla.net> ;
- :homepage <http://drobilla.net/software/lilv> ;
- :license <http://usefulinc.com/doap/licenses/gpl> ;
- :name "LILV" ;
- :programming-language "C", "Turtle" ;
- :repository [
- :browse <http://dev.drobilla.net/browser/trunk/lilv> ;
- :location <http://svn.drobilla.net/lad/trunk/lilv> ;
- a :SVNRepository
- ] ;
- :shortdesc "Library for simple use of LV2 plugins" ;
- :shortname "LILV" .
-
+<http://drobilla.net/drobilla#me>
+ a foaf:Person ;
+ rdfs:seeAlso <http://drobilla.net/drobilla> ;
+ foaf:mbox <mailto:d@drobilla.net> ;
+ foaf:name "David Robillard" ;
+ foaf:nick "drobilla" .
+<http://drobilla.net/software/lilv>
+ a doap:Project ;
+ doap:blog <https://drobilla.net/category/lilv/> ;
+ doap:bug-database <https://gitlab.com/lv2/lilv/issues> ;
+ doap:description "C library for hosting LV2 plugins" ;
+ doap:developer <http://drobilla.net/drobilla#me> ;
+ doap:download-page <http://download.drobilla.net/> ;
+ doap:homepage <http://drobilla.net/software/lilv> ;
+ doap:implements <http://lv2plug.in/ns/lv2core> ;
+ doap:license <http://opensource.org/licenses/isc> ;
+ doap:maintainer <http://drobilla.net/drobilla#me> ;
+ doap:name "Lilv" ;
+ doap:programming-language "C" ;
+ doap:repository [
+ a doap:GitBranch ;
+ doap:location <https://gitlab.com/lv2/lilv.git>
+ ] .
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..755b42d
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,382 @@
+# Copyright 2021-2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+project(
+ 'lilv',
+ ['c'],
+ default_options: [
+ 'b_ndebug=if-release',
+ 'buildtype=release',
+ 'c_std=c99',
+ 'cpp_std=c++11',
+ ],
+ license: 'ISC',
+ meson_version: '>= 0.56.0',
+ version: '0.24.27',
+)
+
+lilv_src_root = meson.current_source_dir()
+lilv_build_root = meson.current_build_dir()
+major_version = meson.project_version().split('.')[0]
+version_suffix = '-@0@'.format(major_version)
+versioned_name = 'lilv' + version_suffix
+
+#######################
+# Compilers and Flags #
+#######################
+
+# Required tools
+pkg = import('pkgconfig')
+cc = meson.get_compiler('c')
+
+# Enable C++ support if bindings aren't disabled
+if not get_option('bindings_cpp').disabled()
+ if add_languages(['cpp'], native: false, required: false)
+ cpp = meson.get_compiler('cpp')
+ endif
+endif
+
+# Set global warning suppressions
+warning_level = get_option('warning_level')
+c_suppressions = []
+if cc.get_id() in ['clang', 'emscripten']
+ if warning_level == 'everything'
+ c_suppressions += [
+ '-Wno-cast-align',
+ '-Wno-cast-function-type-strict',
+ '-Wno-cast-qual',
+ '-Wno-declaration-after-statement',
+ '-Wno-documentation-unknown-command',
+ '-Wno-double-promotion',
+ '-Wno-float-equal',
+ '-Wno-format-nonliteral',
+ '-Wno-implicit-float-conversion',
+ '-Wno-implicit-int-conversion',
+ '-Wno-padded',
+ '-Wno-reserved-id-macro',
+ '-Wno-shorten-64-to-32',
+ '-Wno-sign-conversion',
+ '-Wno-switch-default',
+ '-Wno-switch-enum',
+ '-Wno-unsafe-buffer-usage',
+ ]
+
+ if not meson.is_cross_build()
+ c_suppressions += ['-Wno-poison-system-directories']
+ endif
+ endif
+
+ if warning_level in ['everything', '3']
+ c_suppressions += ['-Wno-nullability-extension']
+
+ if host_machine.system() == 'freebsd'
+ c_suppressions += ['-Wno-c11-extensions']
+ elif host_machine.system() == 'darwin'
+ c_suppressions += ['-Wno-unused-macros']
+ elif host_machine.system() == 'windows'
+ c_suppressions += [
+ '-Wno-deprecated-declarations',
+ '-Wno-nonportable-system-include-path',
+ '-Wno-unused-macros',
+ ]
+ endif
+ endif
+
+elif cc.get_id() == 'gcc'
+ if warning_level == 'everything'
+ c_suppressions += [
+ '-Wno-cast-align',
+ '-Wno-cast-qual',
+ '-Wno-conversion',
+ '-Wno-double-promotion',
+ '-Wno-float-equal',
+ '-Wno-format-nonliteral',
+ '-Wno-format-truncation',
+ '-Wno-inline',
+ '-Wno-padded',
+ '-Wno-stack-protector',
+ '-Wno-strict-overflow',
+ '-Wno-suggest-attribute=const',
+ '-Wno-suggest-attribute=pure',
+ '-Wno-switch-default',
+ '-Wno-switch-enum',
+ '-Wno-unsuffixed-float-constants',
+ '-Wno-unused-const-variable',
+ '-Wno-unused-parameter',
+ ]
+ endif
+
+ if warning_level in ['everything', '3']
+ c_suppressions += ['-Wno-pedantic']
+ endif
+
+ if host_machine.system() == 'windows'
+ c_suppressions += [
+ '-Wno-bad-function-cast',
+ '-Wno-unused-macros',
+ ]
+ endif
+
+elif cc.get_id() == 'msvc'
+ c_suppressions += [
+ '/experimental:external',
+ '/external:W0',
+ '/external:anglebrackets',
+ ]
+
+ if warning_level == 'everything'
+ c_suppressions += [
+ '/wd4061', # enumerator in switch is not explicitly handled
+ '/wd4191', # unsafe conversion from FARPROC
+ '/wd4365', # signed/unsigned mismatch
+ '/wd4514', # unreferenced inline function has been removed
+ '/wd4710', # function not inlined
+ '/wd4711', # function selected for automatic inline expansion
+ '/wd4774', # format string is not a string literal
+ '/wd4800', # implicit conversion to bool
+ '/wd4820', # padding added after construct
+ '/wd5045', # will insert Spectre mitigation for memory load
+ ]
+ endif
+
+ if warning_level in ['everything', '3']
+ c_suppressions += [
+ '/wd4090', # different const qualifiers
+ '/wd4706', # assignment within conditional expression
+ ]
+ endif
+
+ if warning_level in ['everything', '3', '2']
+ c_suppressions += [
+ '/wd4244', # conversion from floating point, possible loss of data
+ '/wd4267', # conversion from size_t, possible loss of data
+ '/wd4996', # POSIX name for this item is deprecated
+ ]
+ endif
+endif
+
+c_suppressions = cc.get_supported_arguments(c_suppressions)
+
+##########################
+# Platform Configuration #
+##########################
+
+platform_defines = ['-DLILV_VERSION="@0@"'.format(meson.project_version())]
+if host_machine.system() in ['gnu', 'linux']
+ platform_defines += [
+ '-D_POSIX_C_SOURCE=200809L',
+ ]
+endif
+
+default_lv2_path = get_option('default_lv2_path')
+if default_lv2_path == ''
+ if host_machine.system() == 'darwin'
+ lv2_dirs = [
+ '~/.lv2',
+ '~/Library/Audio/Plug-Ins/LV2',
+ '/usr/local/lib/lv2',
+ '/usr/lib/lv2',
+ '/Library/Audio/Plug-Ins/LV2',
+ ]
+
+ default_lv2_path = ':'.join(lv2_dirs)
+
+ elif host_machine.system() == 'haiku'
+ default_lv2_path = ':'.join(['~/.lv2', '/boot/common/add-ons/lv2'])
+
+ elif host_machine.system() == 'windows'
+ lv2_dirs = ['%%APPDATA%%\\\\LV2', '%%COMMONPROGRAMFILES%%\\\\LV2']
+ default_lv2_path = ';'.join(lv2_dirs)
+
+ else
+ lv2_dirs = [
+ '~' / '.lv2',
+ '/usr/local' / get_option('libdir') / 'lv2',
+ '/usr' / get_option('libdir') / 'lv2',
+ ]
+
+ default_lv2_path = ':'.join(lv2_dirs)
+ endif
+endif
+
+platform_defines += ['-DLILV_DEFAULT_LV2_PATH="@0@"'.format(default_lv2_path)]
+
+# Use versioned name everywhere to support parallel major version installations
+if host_machine.system() == 'windows'
+ if get_option('default_library') == 'both'
+ error('default_library=both is not supported on Windows')
+ endif
+ soversion = ''
+else
+ soversion = meson.project_version().split('.')[0]
+endif
+
+add_project_arguments(platform_defines, language: ['c'])
+
+################
+# Dependencies #
+################
+
+m_dep = cc.find_library('m', required: false)
+dl_dep = cc.find_library('dl', required: false)
+
+zix_dep = dependency(
+ 'zix-0',
+ include_type: 'system',
+ version: '>= 0.6.0',
+)
+serd_dep = dependency(
+ 'serd-0',
+ include_type: 'system',
+ version: '>= 0.30.10',
+)
+sord_dep = dependency(
+ 'sord-0',
+ include_type: 'system',
+ version: '>= 0.16.16',
+)
+lv2_dep = dependency(
+ 'lv2',
+ include_type: 'system',
+ version: '>= 1.18.2',
+)
+sratom_dep = dependency(
+ 'sratom-0',
+ include_type: 'system',
+ version: '>= 0.6.10',
+)
+
+###########
+# Library #
+###########
+
+c_headers = files('include/lilv/lilv.h')
+cpp_headers = files('include/lilv/lilvmm.hpp')
+
+sources = files(
+ 'src/collections.c',
+ 'src/dylib.c',
+ 'src/instance.c',
+ 'src/lib.c',
+ 'src/node.c',
+ 'src/plugin.c',
+ 'src/pluginclass.c',
+ 'src/port.c',
+ 'src/query.c',
+ 'src/scalepoint.c',
+ 'src/state.c',
+ 'src/ui.c',
+ 'src/util.c',
+ 'src/world.c',
+)
+
+common_dependencies = [
+ dl_dep,
+ lv2_dep,
+ m_dep,
+ serd_dep,
+ sord_dep,
+ sratom_dep,
+ zix_dep,
+]
+
+# Set appropriate arguments for building against the library type
+extra_c_args = []
+if get_option('default_library') == 'static'
+ extra_c_args = ['-DLILV_STATIC']
+endif
+
+# Build main shared and/or static library
+liblilv = library(
+ versioned_name,
+ sources,
+ c_args: c_suppressions + extra_c_args + ['-DLILV_INTERNAL'],
+ darwin_versions: [major_version + '.0.0', meson.project_version()],
+ dependencies: common_dependencies,
+ gnu_symbol_visibility: 'hidden',
+ implicit_include_directories: false,
+ include_directories: include_directories('include'),
+ install: true,
+ soversion: soversion,
+ version: meson.project_version(),
+)
+
+# Declare dependency for internal meson dependants
+lilv_dep = declare_dependency(
+ compile_args: extra_c_args,
+ dependencies: common_dependencies,
+ include_directories: include_directories('include'),
+ link_with: liblilv,
+)
+
+# Generate pkg-config file for external dependants
+pkg.generate(
+ liblilv,
+ description: 'Library for hosting LV2 plugins',
+ extra_cflags: extra_c_args,
+ filebase: versioned_name,
+ name: 'Lilv',
+ requires: ['lv2'],
+ subdirs: [versioned_name],
+ version: meson.project_version(),
+)
+
+# Override pkg-config dependency for internal meson dependants
+meson.override_dependency(versioned_name, lilv_dep)
+
+# Install headers to a versioned include directory
+install_headers(c_headers, subdir: versioned_name / 'lilv')
+install_headers(cpp_headers, subdir: versioned_name / 'lilv')
+
+# Display top-level summary (before subdirectories to appear first)
+if not meson.is_subproject()
+ summary(
+ {
+ 'Tests': not get_option('tests').disabled(),
+ 'Tools': not get_option('tools').disabled(),
+ },
+ bool_yn: true,
+ section: 'Components',
+ )
+
+ summary('Default LV2_PATH', default_lv2_path, section: 'Configuration')
+
+ summary(
+ {
+ 'Install prefix': get_option('prefix'),
+ 'Headers': get_option('prefix') / get_option('includedir'),
+ 'Libraries': get_option('prefix') / get_option('libdir'),
+ 'Executables': get_option('prefix') / get_option('bindir'),
+ 'Man pages': get_option('prefix') / get_option('mandir'),
+ },
+ section: 'Directories',
+ )
+endif
+
+#########
+# Tools #
+#########
+
+if not get_option('tools').disabled()
+ subdir('tools')
+endif
+
+############
+# Bindings #
+############
+
+if not get_option('bindings_py').disabled()
+ subdir('bindings/python')
+endif
+
+###########
+# Support #
+###########
+
+if not get_option('docs').disabled()
+ subdir('doc')
+endif
+
+if not get_option('tests').disabled()
+ subdir('test')
+endif
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..a8cec45
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,32 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+option('bindings_py', type: 'feature', yield: true,
+ description: 'Build Python bindings')
+
+option('bindings_cpp', type: 'feature', yield: true,
+ description: 'Build C++ bindings')
+
+option('default_lv2_path', type: 'string', value: '', yield: true,
+ description: 'Default LV2_PATH to use if it is unset')
+
+option('docs', type: 'feature', yield: true,
+ description: 'Build documentation')
+
+option('html', type: 'feature', yield: true,
+ description: 'Build paginated HTML documentation')
+
+option('lint', type: 'boolean', value: false, yield: true,
+ description: 'Run code quality checks')
+
+option('singlehtml', type: 'feature', yield: true,
+ description: 'Build single-page HTML documentation')
+
+option('tests', type: 'feature', yield: true,
+ description: 'Build tests')
+
+option('title', type: 'string', value: 'Lilv',
+ description: 'Project title')
+
+option('tools', type: 'feature', yield: true,
+ description: 'Build command line utilities')
diff --git a/scripts/dox_to_sphinx.py b/scripts/dox_to_sphinx.py
deleted file mode 100755
index 024f125..0000000
--- a/scripts/dox_to_sphinx.py
+++ /dev/null
@@ -1,655 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2020 David Robillard <d@drobilla.net>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-"""
-Write Sphinx markup from Doxygen XML.
-
-Takes a path to a directory of XML generated by Doxygen, and emits a directory
-with a reStructuredText file for every documented symbol.
-"""
-
-import argparse
-import os
-import sys
-import textwrap
-import xml.etree.ElementTree
-
-__author__ = "David Robillard"
-__date__ = "2020-11-18"
-__email__ = "d@drobilla.net"
-__license__ = "ISC"
-__version__ = __date__.replace("-", ".")
-
-
-def load_index(index_path):
- """
- Load the index from XML.
-
- :returns: A dictionary from ID to skeleton records with basic information
- for every documented entity. Some records have an ``xml_filename`` key
- with the filename of a definition file. These files will be loaded later
- to flesh out the records in the index.
- """
-
- root = xml.etree.ElementTree.parse(index_path).getroot()
- index = {}
-
- for compound in root:
- compound_id = compound.get("refid")
- compound_kind = compound.get("kind")
- compound_name = compound.find("name").text
- if compound_kind in ["dir", "file", "page"]:
- continue
-
- # Add record for compound (compounds appear only once in the index)
- assert compound_id not in index
- index[compound_id] = {
- "kind": compound_kind,
- "name": compound_name,
- "xml_filename": compound_id + ".xml",
- "children": [],
- }
-
- name_prefix = (
- ("%s::" % compound_name) if compound_kind == "namespace" else ""
- )
-
- for child in compound.findall("member"):
- if child.get("refid") in index:
- assert compound_kind == "group"
- continue
-
- # Everything has a kind and a name
- child_record = {
- "kind": child.get("kind"),
- "name": name_prefix + child.find("name").text,
- }
-
- if child.get("kind") == "enum":
- # Enums are not compounds, but we want to resolve the parent of
- # their values so they are not written as top level documents
- child_record["children"] = []
-
- if child.get("kind") == "enumvalue":
- # Remove namespace prefix
- child_record["name"] = child.find("name").text
-
- index[child.get("refid")] = child_record
-
- return index
-
-
-def resolve_index(index, root):
- """
- Walk a definition document and extend the index for linking.
-
- This does two things: sets the "parent" and "children" fields of all
- applicable records, and sets the "strong" field of enums so that the
- correct Sphinx role can be used when referring to them.
- """
-
- def add_child(index, parent_id, child_id):
- parent = index[parent_id]
- child = index[child_id]
-
- if child["kind"] == "enumvalue":
- assert parent["kind"] == "enum"
- assert "parent" not in child or child["parent"] == parent_id
- child["parent"] = parent_id
-
- else:
- if parent["kind"] in ["class", "struct", "union"]:
- assert "parent" not in child or child["parent"] == parent_id
- child["parent"] = parent_id
-
- if child_id not in parent["children"]:
- parent["children"] += [child_id]
-
- compound = root.find("compounddef")
- compound_kind = compound.get("kind")
-
- if compound_kind == "group":
- for subgroup in compound.findall("innergroup"):
- add_child(index, compound.get("id"), subgroup.get("refid"))
-
- for klass in compound.findall("innerclass"):
- add_child(index, compound.get("id"), klass.get("refid"))
-
- for section in compound.findall("sectiondef"):
- if section.get("kind").startswith("private"):
- for member in section.findall("memberdef"):
- if member.get("id") in index:
- del index[member.get("id")]
- else:
- for member in section.findall("memberdef"):
- member_id = member.get("id")
- add_child(index, compound.get("id"), member_id)
-
- if member.get("kind") == "enum":
- index[member_id]["strong"] = member.get("strong") == "yes"
- for value in member.findall("enumvalue"):
- add_child(index, member_id, value.get("id"))
-
-
-def sphinx_role(record, lang):
- """
- Return the Sphinx role used for a record.
-
- This is used for the description directive like ".. c:function::", and
- links like ":c:func:`foo`.
- """
-
- kind = record["kind"]
-
- if kind in ["class", "function", "namespace", "struct", "union"]:
- return lang + ":" + kind
-
- if kind == "define":
- return "c:macro"
-
- if kind == "enum":
- return lang + (":enum-class" if record["strong"] else ":enum")
-
- if kind == "typedef":
- return lang + ":type"
-
- if kind == "enumvalue":
- return lang + ":enumerator"
-
- if kind == "variable":
- return lang + (":member" if "parent" in record else ":var")
-
- raise RuntimeError("No known role for kind '%s'" % kind)
-
-
-def child_identifier(lang, parent_name, child_name):
- """
- Return the identifier for an enum value or struct member.
-
- Sphinx, for some reason, uses a different syntax for this in C and C++.
- """
-
- separator = "::" if lang == "cpp" else "."
-
- return "%s%s%s" % (parent_name, separator, child_name)
-
-
-def link_markup(index, lang, refid):
- """Return a Sphinx link for a Doxygen reference."""
-
- record = index[refid]
- kind, name = record["kind"], record["name"]
- role = sphinx_role(record, lang)
-
- if kind in ["class", "enum", "struct", "typedef", "union"]:
- return ":%s:`%s`" % (role, name)
-
- if kind == "function":
- return ":%s:func:`%s`" % (lang, name)
-
- if kind == "enumvalue":
- parent_name = index[record["parent"]]["name"]
- return ":%s:`%s`" % (role, child_identifier(lang, parent_name, name))
-
- if kind == "variable":
- if "parent" not in record:
- return ":%s:var:`%s`" % (lang, name)
-
- parent_name = index[record["parent"]]["name"]
- return ":%s:`%s`" % (role, child_identifier(lang, parent_name, name))
-
- if kind == "define":
- return ":%s:macro:`%s`" % (lang, name)
-
- raise RuntimeError("Unknown link target kind: %s" % kind)
-
-
-def indent(markup, depth):
- """
- Indent markup to a depth level.
-
- Like textwrap.indent() but takes an integer and works in reST indentation
- levels for clarity."
- """
-
- return textwrap.indent(markup, " " * depth)
-
-
-def heading(text, level):
- """
- Return a ReST heading at a given level.
-
- Follows the style in the Python documentation guide, see
- <https://devguide.python.org/documenting/#sections>.
- """
-
- assert 1 <= level <= 6
-
- chars = ("#", "*", "=", "-", "^", '"')
- line = chars[level] * len(text)
-
- return "%s%s\n%s\n\n" % (line + "\n" if level < 3 else "", text, line)
-
-
-def dox_to_rst(index, lang, node):
- """
- Convert documentation commands (docCmdGroup) to Sphinx markup.
-
- This is used to convert the content of descriptions in the documentation.
- It recursively parses all children tags and raises a RuntimeError if any
- unknown tag is encountered.
- """
-
- def field_value(markup):
- """Return a value for a field as a single line or indented block."""
- if "\n" in markup.strip():
- return "\n" + indent(markup, 1)
-
- return " " + markup.strip()
-
- if node.tag == "lsquo":
- return "‘"
-
- if node.tag == "rsquo":
- return "’"
-
- if node.tag == "computeroutput":
- assert len(node) == 0
- return "``%s``" % node.text
-
- if node.tag == "itemizedlist":
- markup = ""
- for item in node.findall("listitem"):
- assert len(item) == 1
- markup += "\n- %s" % dox_to_rst(index, lang, item[0])
-
- return markup
-
- if node.tag == "para":
- markup = node.text if node.text is not None else ""
- for child in node:
- markup += dox_to_rst(index, lang, child)
- markup += child.tail if child.tail is not None else ""
-
- return markup.strip() + "\n\n"
-
- if node.tag == "parameterlist":
- markup = ""
- for item in node.findall("parameteritem"):
- name = item.find("parameternamelist/parametername")
- description = item.find("parameterdescription")
- assert len(description) == 1
- markup += "\n\n:param %s:%s" % (
- name.text,
- field_value(dox_to_rst(index, lang, description[0])),
- )
-
- return markup + "\n"
-
- if node.tag == "programlisting":
- return "\n.. code-block:: %s\n\n%s" % (
- lang,
- indent(plain_text(node), 1),
- )
-
- if node.tag == "ref":
- refid = node.get("refid")
- if refid not in index:
- sys.stderr.write("warning: Unresolved link: %s\n" % refid)
- return node.text
-
- assert len(node) == 0
- assert len(link_markup(index, lang, refid)) > 0
- return link_markup(index, lang, refid)
-
- if node.tag == "simplesect":
- assert len(node) == 1
-
- if node.get("kind") == "return":
- return "\n:returns:" + field_value(
- dox_to_rst(index, lang, node[0])
- ) + "\n"
-
- if node.get("kind") == "see":
- return dox_to_rst(index, lang, node[0])
-
- raise RuntimeError("Unknown simplesect kind: %s" % node.get("kind"))
-
- if node.tag == "ulink":
- return "`%s <%s>`_" % (node.text, node.get("url"))
-
- raise RuntimeError("Unknown documentation command: %s" % node.tag)
-
-
-def description_markup(index, lang, node):
- """Return the markup for a brief or detailed description."""
-
- assert node.tag == "briefdescription" or node.tag == "detaileddescription"
- assert not (node.tag == "briefdescription" and len(node) > 1)
- assert len(node.text.strip()) == 0
-
- return "".join([dox_to_rst(index, lang, child) for child in node]).strip()
-
-
-def set_descriptions(index, lang, definition, record):
- """Set a record's brief/detailed descriptions from the XML definition."""
-
- for tag in ["briefdescription", "detaileddescription"]:
- node = definition.find(tag)
- if node is not None:
- record[tag] = description_markup(index, lang, node)
-
-
-def set_template_params(node, record):
- """Set a record's template_params from the XML definition."""
-
- template_param_list = node.find("templateparamlist")
- if template_param_list is not None:
- params = []
- for param in template_param_list.findall("param"):
- if param.find("declname") is not None:
- # Value parameter
- type_text = plain_text(param.find("type"))
- name_text = plain_text(param.find("declname"))
-
- params += ["%s %s" % (type_text, name_text)]
- else:
- # Type parameter
- params += ["%s" % (plain_text(param.find("type")))]
-
- record["template_params"] = "%s" % ", ".join(params)
-
-
-def plain_text(node):
- """
- Return the plain text of a node with all tags ignored.
-
- This is needed where Doxygen may include refs but Sphinx needs plain text
- because it parses things itself to generate links.
- """
-
- if node.tag == "sp":
- markup = " "
- elif node.text is not None:
- markup = node.text
- else:
- markup = ""
-
- for child in node:
- markup += plain_text(child)
- markup += child.tail if child.tail is not None else ""
-
- return markup
-
-
-def local_name(name):
- """Return a name with all namespace prefixes stripped."""
-
- return name[name.rindex("::") + 2 :] if "::" in name else name
-
-
-def read_definition_doc(index, lang, root):
- """Walk a definition document and update described records in the index."""
-
- # Set descriptions for the compound itself
- compound = root.find("compounddef")
- compound_record = index[compound.get("id")]
- set_descriptions(index, lang, compound, compound_record)
- set_template_params(compound, compound_record)
-
- if compound.find("title") is not None:
- compound_record["title"] = compound.find("title").text.strip()
-
- # Set documentation for all children
- for section in compound.findall("sectiondef"):
- if section.get("kind").startswith("private"):
- continue
-
- for member in section.findall("memberdef"):
- kind = member.get("kind")
- record = index[member.get("id")]
- set_descriptions(index, lang, member, record)
- set_template_params(member, record)
-
- if compound.get("kind") in ["class", "struct", "union"]:
- assert kind in ["function", "typedef", "variable"]
- record["type"] = plain_text(member.find("type"))
-
- if kind == "enum":
- for value in member.findall("enumvalue"):
- set_descriptions(
- index, lang, value, index[value.get("id")]
- )
-
- elif kind == "function":
- record["prototype"] = "%s %s%s" % (
- plain_text(member.find("type")),
- member.find("name").text,
- member.find("argsstring").text,
- )
-
- elif kind == "typedef":
- name = local_name(record["name"])
- args_text = member.find("argsstring").text
- target_text = plain_text(member.find("type"))
- if args_text is not None: # Function pointer
- assert target_text[-2:] == "(*" and args_text[0] == ")"
- record["type"] = target_text + args_text
- record["definition"] = target_text + name + args_text
- else: # Normal named typedef
- assert target_text is not None
- record["type"] = target_text
- if member.find("definition").text.startswith("using"):
- record["definition"] = "%s = %s" % (
- name,
- target_text,
- )
- else:
- record["definition"] = "%s %s" % (
- target_text,
- name,
- )
-
- elif kind == "variable":
- record["definition"] = member.find("definition").text
-
-
-def declaration_string(record):
- """
- Return the string that describes a declaration.
-
- This is what follows the directive, and is in C/C++ syntax, except without
- keywords like "typedef" and "using" as expected by Sphinx. For example,
- "struct ThingImpl Thing" or "void run(int value)".
- """
-
- kind = record["kind"]
- result = ""
-
- if "template_params" in record:
- result = "template <%s> " % record["template_params"]
-
- if kind == "function":
- result += record["prototype"]
- elif kind == "typedef":
- result += record["definition"]
- elif kind == "variable":
- if "parent" in record:
- result += "%s %s" % (record["type"], local_name(record["name"]))
- else:
- result += record["definition"]
- elif "type" in record:
- result += "%s %s" % (record["type"], local_name(record["name"]))
- else:
- result += local_name(record["name"])
-
- return result
-
-
-def document_markup(index, lang, record):
- """Return the complete document that describes some documented entity."""
-
- kind = record["kind"]
- role = sphinx_role(record, lang)
- name = record["name"]
- markup = ""
-
- if name != local_name(name):
- markup += ".. cpp:namespace:: %s\n\n" % name[0 : name.rindex("::")]
-
- # Write top-level directive
- markup += ".. %s:: %s\n" % (role, declaration_string(record))
-
- # Write main description blurb
- markup += "\n" + indent(record["briefdescription"] + "\n", 1)
- if len(record["detaileddescription"]) > 0:
- markup += "\n" + indent(record["detaileddescription"], 1) + "\n"
-
- assert (
- kind in ["class", "enum", "namespace", "struct", "union"]
- or "children" not in record
- )
-
- # Sphinx C++ namespaces work by setting a scope, they have no content
- child_indent = 0 if kind == "namespace" else 1
-
- # Write inline children if applicable
- markup += "\n" if "children" in record else ""
- for child_id in record.get("children", []):
- child_record = index[child_id]
- child_role = sphinx_role(child_record, lang)
-
- child_header = ".. %s:: %s\n\n" % (
- child_role,
- declaration_string(child_record),
- )
-
- markup += "\n"
- markup += indent(child_header, child_indent)
- markup += indent(child_record["briefdescription"], child_indent + 1)
- markup += indent(child_record["detaileddescription"], child_indent + 1)
-
- return markup
-
-
-def symbol_filename(name):
- """Adapt the name of a symbol to be suitable for use as a filename."""
-
- return name.replace("::", "__")
-
-
-def emit_groups(index, lang, output_dir, force):
- """Write a description file for every group documented in the index."""
-
- for record in index.values():
- if record["kind"] != "group":
- continue
-
- name = record["name"]
- filename = os.path.join(output_dir, "%s.rst" % name)
- if not force and os.path.exists(filename):
- raise FileExistsError("File already exists: '%s'" % filename)
-
- with open(filename, "w") as rst:
- rst.write(heading(record["title"], 1))
-
- # Get all child group and symbol names
- child_groups = {}
- child_symbols = {}
- for child_id in record["children"]:
- child = index[child_id]
- if child["kind"] == "group":
- child_groups[child["name"]] = child
- else:
- child_symbols[child["name"]] = child
-
- # Emit description (document body)
- if len(record["briefdescription"]) > 0:
- rst.write(record["briefdescription"] + "\n\n")
- if len(record["detaileddescription"]) > 0:
- rst.write(record["detaileddescription"] + "\n\n")
-
- if len(child_groups) > 0:
- # Emit TOC for child groups
- rst.write(".. toctree::\n\n")
- for name, group in child_groups.items():
- rst.write(indent(group["name"], 1) + "\n")
-
- # Emit symbols in sorted order
- for name, symbol in child_symbols.items():
- rst.write("\n")
- rst.write(document_markup(index, lang, symbol))
- rst.write("\n")
-
-
-def run(index_xml_path, output_dir, language, force):
- """Write a directory of Sphinx files from a Doxygen XML directory."""
-
- # Build skeleton index from index.xml
- xml_dir = os.path.dirname(index_xml_path)
- index = load_index(index_xml_path)
-
- # Load all definition documents
- definition_docs = []
- for record in index.values():
- if "xml_filename" in record:
- xml_path = os.path.join(xml_dir, record["xml_filename"])
- definition_docs += [xml.etree.ElementTree.parse(xml_path)]
-
- # Do an initial pass of the definition documents to resolve the index
- for root in definition_docs:
- resolve_index(index, root)
-
- # Finally read the documentation from definition documents
- for root in definition_docs:
- read_definition_doc(index, language, root)
-
- # Create output directory
- try:
- os.makedirs(output_dir)
- except OSError:
- pass
-
- # Emit output files
- emit_groups(index, language, output_dir, force)
-
-
-if __name__ == "__main__":
- ap = argparse.ArgumentParser(
- usage="%(prog)s [OPTION]... XML_DIR OUTPUT_DIR",
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
-
- ap.add_argument(
- "-f",
- "--force",
- action="store_true",
- help="overwrite files",
- )
-
- ap.add_argument(
- "-l",
- "--language",
- default="c",
- choices=["c", "cpp"],
- help="language domain for output",
- )
-
- ap.add_argument("index_xml_path", help="path index.xml from Doxygen")
- ap.add_argument("output_dir", help="output directory")
-
- run(**vars(ap.parse_args(sys.argv[1:])))
diff --git a/src/.clang-tidy b/src/.clang-tidy
new file mode 100644
index 0000000..0d90367
--- /dev/null
+++ b/src/.clang-tidy
@@ -0,0 +1,24 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+Checks: >
+ -*-magic-numbers,
+ -android-cloexec-fopen,
+ -bugprone-narrowing-conversions,
+ -cert-err33-c,
+ -clang-analyzer-optin.core.EnumCastOutOfRange,
+ -clang-analyzer-optin.taint.TaintedAlloc,
+ -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
+ -clang-analyzer-valist.Uninitialized,
+ -concurrency-mt-unsafe,
+ -cppcoreguidelines-narrowing-conversions,
+ -google-readability-todo,
+ -hicpp-multiway-paths-covered,
+ -hicpp-signed-bitwise,
+ -llvm-header-guard,
+ -performance-no-int-to-ptr,
+ -readability-avoid-nested-conditional-operator,
+ -readability-function-cognitive-complexity,
+ -readability-redundant-casting,
+ -readability-suspicious-call-argument,
+InheritParentConfig: true
diff --git a/src/collections.c b/src/collections.c
index c2c752a..6d143a7 100644
--- a/src/collections.c
+++ b/src/collections.c
@@ -1,36 +1,23 @@
-/*
- Copyright 2008-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2008-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "sord/sord.h"
-#include "zix/common.h"
-#include "zix/tree.h"
+#include <lilv/lilv.h>
+#include <sord/sord.h>
+#include <zix/tree.h>
#include <stdbool.h>
#include <stddef.h>
-#include <stdint.h>
+
+typedef void (*LilvFreeFunc)(void* ptr);
int
lilv_ptr_cmp(const void* a, const void* b, const void* user_data)
{
(void)user_data;
- return (intptr_t)a - (intptr_t)b;
+ return a < b ? -1 : b < a ? 1 : 0;
}
int
@@ -41,18 +28,26 @@ lilv_resource_node_cmp(const void* a, const void* b, const void* user_data)
const SordNode* an = ((const LilvNode*)a)->node;
const SordNode* bn = ((const LilvNode*)b)->node;
- return (intptr_t)an - (intptr_t)bn;
+ return an < bn ? -1 : bn < an ? 1 : 0;
}
/* Generic collection functions */
+static void
+destroy(void* const ptr, const void* const user_data)
+{
+ if (user_data) {
+ ((LilvFreeFunc)user_data)(ptr);
+ }
+}
+
static inline LilvCollection*
-lilv_collection_new(ZixComparator cmp, ZixDestroyFunc destructor)
+lilv_collection_new(ZixTreeCompareFunc cmp, LilvFreeFunc free_func)
{
- return zix_tree_new(false, cmp, NULL, destructor);
+ return zix_tree_new(NULL, false, cmp, NULL, destroy, (const void*)free_func);
}
-void
+static void
lilv_collection_free(LilvCollection* collection)
{
if (collection) {
@@ -60,13 +55,13 @@ lilv_collection_free(LilvCollection* collection)
}
}
-unsigned
+static unsigned
lilv_collection_size(const LilvCollection* collection)
{
return (collection ? zix_tree_size((const ZixTree*)collection) : 0);
}
-LilvIter*
+static LilvIter*
lilv_collection_begin(const LilvCollection* collection)
{
return collection ? (LilvIter*)zix_tree_begin((ZixTree*)collection) : NULL;
@@ -85,28 +80,27 @@ lilv_collection_get(const LilvCollection* collection, const LilvIter* i)
LilvScalePoints*
lilv_scale_points_new(void)
{
- return lilv_collection_new(lilv_ptr_cmp,
- (ZixDestroyFunc)lilv_scale_point_free);
+ return lilv_collection_new(lilv_ptr_cmp, (LilvFreeFunc)lilv_scale_point_free);
}
LilvNodes*
lilv_nodes_new(void)
{
- return lilv_collection_new(lilv_ptr_cmp, (ZixDestroyFunc)lilv_node_free);
+ return lilv_collection_new(lilv_ptr_cmp, (LilvFreeFunc)lilv_node_free);
}
LilvUIs*
lilv_uis_new(void)
{
return lilv_collection_new(lilv_header_compare_by_uri,
- (ZixDestroyFunc)lilv_ui_free);
+ (LilvFreeFunc)lilv_ui_free);
}
LilvPluginClasses*
lilv_plugin_classes_new(void)
{
return lilv_collection_new(lilv_header_compare_by_uri,
- (ZixDestroyFunc)lilv_plugin_class_free);
+ (LilvFreeFunc)lilv_plugin_class_free);
}
/* URI based accessors (for collections of things with URIs) */
@@ -173,33 +167,33 @@ lilv_nodes_merge(const LilvNodes* a, const LilvNodes* b)
/* Iterator */
-#define LILV_COLLECTION_IMPL(prefix, CT, ET) \
- \
- unsigned prefix##_size(const CT* collection) \
- { \
- return lilv_collection_size(collection); \
- } \
- \
- LilvIter* prefix##_begin(const CT* collection) \
- { \
- return lilv_collection_begin(collection); \
- } \
- \
- const ET* prefix##_get(const CT* collection, LilvIter* i) \
- { \
- return (ET*)lilv_collection_get(collection, i); \
- } \
- \
- LilvIter* prefix##_next(const CT* collection, LilvIter* i) \
- { \
- (void)collection; \
- return zix_tree_iter_next((ZixTreeIter*)i); \
- } \
- \
- bool prefix##_is_end(const CT* collection, LilvIter* i) \
- { \
- (void)collection; \
- return zix_tree_iter_is_end((ZixTreeIter*)i); \
+#define LILV_COLLECTION_IMPL(prefix, CT, ET) \
+ \
+ unsigned prefix##_size(const CT* collection) \
+ { \
+ return lilv_collection_size(collection); \
+ } \
+ \
+ LilvIter* prefix##_begin(const CT* collection) \
+ { \
+ return lilv_collection_begin(collection); \
+ } \
+ \
+ const ET* prefix##_get(const CT* collection, const LilvIter* i) \
+ { \
+ return (ET*)lilv_collection_get(collection, i); \
+ } \
+ \
+ LilvIter* prefix##_next(const CT* collection, LilvIter* i) \
+ { \
+ (void)collection; \
+ return zix_tree_iter_next((ZixTreeIter*)i); \
+ } \
+ \
+ bool prefix##_is_end(const CT* collection, const LilvIter* i) \
+ { \
+ (void)collection; \
+ return zix_tree_iter_is_end((const ZixTreeIter*)i); \
}
LILV_COLLECTION_IMPL(lilv_plugin_classes, LilvPluginClasses, LilvPluginClass)
diff --git a/src/dylib.c b/src/dylib.c
new file mode 100644
index 0000000..4c6c219
--- /dev/null
+++ b/src/dylib.c
@@ -0,0 +1,67 @@
+// Copyright 2020-2024 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include "dylib.h"
+
+#ifdef _WIN32
+
+# include <windows.h>
+
+void*
+dylib_open(const char* const filename, const unsigned flags)
+{
+ (void)flags;
+ return LoadLibrary(filename);
+}
+
+int
+dylib_close(DylibLib* const handle)
+{
+ return !FreeLibrary((HMODULE)handle);
+}
+
+const char*
+dylib_error(void)
+{
+ return "Unknown error";
+}
+
+DylibFunc
+dylib_func(DylibLib* handle, const char* symbol)
+{
+ return (DylibFunc)GetProcAddress((HMODULE)handle, symbol);
+}
+
+#else
+
+# include <dlfcn.h>
+
+void*
+dylib_open(const char* const filename, const unsigned flags)
+{
+ return dlopen(filename, flags == DYLIB_LAZY ? RTLD_LAZY : RTLD_NOW);
+}
+
+int
+dylib_close(DylibLib* const handle)
+{
+ return dlclose(handle);
+}
+
+const char*
+dylib_error(void)
+{
+ return dlerror();
+}
+
+DylibFunc
+dylib_func(DylibLib* handle, const char* symbol)
+{
+ typedef DylibFunc (*VoidFuncGetter)(void*, const char*);
+
+ VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym;
+
+ return dlfunc(handle, symbol);
+}
+
+#endif
diff --git a/src/dylib.h b/src/dylib.h
new file mode 100644
index 0000000..f2faade
--- /dev/null
+++ b/src/dylib.h
@@ -0,0 +1,35 @@
+// Copyright 2020-2024 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#ifndef LILV_DYLIB_H
+#define LILV_DYLIB_H
+
+/// Flags for dylib_open()
+enum DylibFlags {
+ DYLIB_LAZY = 1U << 0U, ///< Resolve symbols only when referenced
+ DYLIB_NOW = 1U << 1U, ///< Resolve all symbols on library load
+};
+
+/// An opaque dynamically loaded shared library
+typedef void DylibLib;
+
+/// A function from a shared library
+typedef void (*DylibFunc)(void);
+
+/// Open a shared library
+DylibLib*
+dylib_open(const char* filename, unsigned flags);
+
+/// Close a shared library opened with dylib_open()
+int
+dylib_close(DylibLib* handle);
+
+/// Return a human-readable description of any error since the last call
+const char*
+dylib_error(void);
+
+/// Return a pointer to a function in a shared library, or null
+DylibFunc
+dylib_func(DylibLib* handle, const char* symbol);
+
+#endif // LILV_DYLIB_H
diff --git a/src/filesystem.c b/src/filesystem.c
deleted file mode 100644
index 03614ce..0000000
--- a/src/filesystem.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- Copyright 2007-2021 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#define _POSIX_C_SOURCE 200809L /* for fileno */
-#define _BSD_SOURCE 1 /* for realpath, symlink */
-#define _DEFAULT_SOURCE 1 /* for realpath, symlink */
-
-#ifdef __APPLE__
-# define _DARWIN_C_SOURCE 1 /* for flock */
-#endif
-
-#include "filesystem.h"
-#include "lilv_config.h"
-#include "lilv_internal.h"
-
-#ifdef _WIN32
-# include <direct.h>
-# include <io.h>
-# include <windows.h>
-# define F_OK 0
-# define mkdir(path, flags) _mkdir(path)
-# define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
-#else
-# include <dirent.h>
-# include <unistd.h>
-#endif
-
-#if USE_FLOCK && USE_FILENO
-# include <sys/file.h>
-#endif
-
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef PAGE_SIZE
-# define PAGE_SIZE 4096
-#endif
-
-static bool
-lilv_is_dir_sep(const char c)
-{
- return c == '/' || c == LILV_DIR_SEP[0];
-}
-
-#ifdef _WIN32
-static inline bool
-is_windows_path(const char* path)
-{
- return (isalpha(path[0]) && (path[1] == ':' || path[1] == '|') &&
- (path[2] == '/' || path[2] == '\\'));
-}
-#endif
-
-char*
-lilv_temp_directory_path(void)
-{
-#ifdef _WIN32
- DWORD len = GetTempPath(0, NULL);
- char* buf = (char*)calloc(len, 1);
- if (GetTempPath(len, buf) == 0) {
- free(buf);
- return NULL;
- }
-
- return buf;
-#else
- const char* const tmpdir = getenv("TMPDIR");
-
- return tmpdir ? lilv_strdup(tmpdir) : lilv_strdup("/tmp");
-#endif
-}
-
-bool
-lilv_path_is_absolute(const char* path)
-{
- if (lilv_is_dir_sep(path[0])) {
- return true;
- }
-
-#ifdef _WIN32
- if (is_windows_path(path)) {
- return true;
- }
-#endif
-
- return false;
-}
-
-bool
-lilv_path_is_child(const char* path, const char* dir)
-{
- if (path && dir) {
- const size_t path_len = strlen(path);
- const size_t dir_len = strlen(dir);
- return dir && path_len >= dir_len && !strncmp(path, dir, dir_len);
- }
- return false;
-}
-
-char*
-lilv_path_current(void)
-{
- return getcwd(NULL, 0);
-}
-
-char*
-lilv_path_absolute(const char* path)
-{
- if (lilv_path_is_absolute(path)) {
- return lilv_strdup(path);
- }
-
- char* cwd = getcwd(NULL, 0);
- char* abs_path = lilv_path_join(cwd, path);
- free(cwd);
- return abs_path;
-}
-
-char*
-lilv_path_absolute_child(const char* path, const char* parent)
-{
- if (lilv_path_is_absolute(path)) {
- return lilv_strdup(path);
- }
-
- return lilv_path_join(parent, path);
-}
-
-char*
-lilv_path_relative_to(const char* path, const char* base)
-{
- const size_t path_len = strlen(path);
- const size_t base_len = strlen(base);
- const size_t min_len = (path_len < base_len) ? path_len : base_len;
-
- // Find the last separator common to both paths
- size_t last_shared_sep = 0;
- for (size_t i = 0; i < min_len && path[i] == base[i]; ++i) {
- if (lilv_is_dir_sep(path[i])) {
- last_shared_sep = i;
- }
- }
-
- if (last_shared_sep == 0) {
- // No common components, return path
- return lilv_strdup(path);
- }
-
- // Find the number of up references ("..") required
- size_t up = 0;
- for (size_t i = last_shared_sep + 1; i < base_len; ++i) {
- if (lilv_is_dir_sep(base[i])) {
- ++up;
- }
- }
-
-#ifdef _WIN32
- const bool use_slash = strchr(path, '/');
-#else
- static const bool use_slash = true;
-#endif
-
- // Write up references
- const size_t suffix_len = path_len - last_shared_sep;
- char* rel = (char*)calloc(1, suffix_len + (up * 3) + 1);
- for (size_t i = 0; i < up; ++i) {
- if (use_slash) {
- memcpy(rel + (i * 3), "../", 3);
- } else {
- memcpy(rel + (i * 3), "..\\", 3);
- }
- }
-
- // Write suffix
- memcpy(rel + (up * 3), path + last_shared_sep + 1, suffix_len);
- return rel;
-}
-
-char*
-lilv_path_parent(const char* path)
-{
- const char* s = path + strlen(path) - 1; // Last character
-
- // Last non-slash
- for (; s > path && lilv_is_dir_sep(*s); --s) {
- }
-
- // Last internal slash
- for (; s > path && !lilv_is_dir_sep(*s); --s) {
- }
-
- // Skip duplicates
- for (; s > path && lilv_is_dir_sep(*s); --s) {
- }
-
- if (s == path) { // Hit beginning
- return lilv_is_dir_sep(*s) ? lilv_strdup("/") : lilv_strdup(".");
- }
-
- // Pointing to the last character of the result (inclusive)
- char* dirname = (char*)malloc(s - path + 2);
- memcpy(dirname, path, s - path + 1);
- dirname[s - path + 1] = '\0';
- return dirname;
-}
-
-char*
-lilv_path_filename(const char* path)
-{
- const size_t path_len = strlen(path);
- size_t last_sep = path_len;
- for (size_t i = 0; i < path_len; ++i) {
- if (lilv_is_dir_sep(path[i])) {
- last_sep = i;
- }
- }
-
- if (last_sep >= path_len) {
- return lilv_strdup(path);
- }
-
- const size_t ret_len = path_len - last_sep;
- char* const ret = (char*)calloc(ret_len + 1, 1);
-
- strncpy(ret, path + last_sep + 1, ret_len);
- return ret;
-}
-
-char*
-lilv_path_join(const char* a, const char* b)
-{
- if (!a) {
- return (b && b[0]) ? lilv_strdup(b) : NULL;
- }
-
- const size_t a_len = strlen(a);
- const size_t b_len = b ? strlen(b) : 0;
- const bool a_end_is_sep = a_len > 0 && lilv_is_dir_sep(a[a_len - 1]);
- const size_t pre_len = a_len - (a_end_is_sep ? 1 : 0);
- char* path = (char*)calloc(1, a_len + b_len + 2);
- memcpy(path, a, pre_len);
-
-#ifdef _WIN32
- // Use forward slash if it seems that the input paths do
- const bool a_has_slash = strchr(a, '/');
- const bool b_has_slash = b && strchr(b, '/');
- if (a_has_slash || b_has_slash) {
- path[pre_len] = '/';
- } else {
- path[pre_len] = '\\';
- }
-#else
- path[pre_len] = '/';
-#endif
-
- if (b) {
- memcpy(path + pre_len + 1,
- b + (lilv_is_dir_sep(b[0]) ? 1 : 0),
- lilv_is_dir_sep(b[0]) ? b_len - 1 : b_len);
- }
- return path;
-}
-
-char*
-lilv_path_canonical(const char* path)
-{
- if (!path) {
- return NULL;
- }
-
-#if defined(_WIN32)
- char* out = (char*)malloc(MAX_PATH);
- GetFullPathName(path, MAX_PATH, out, NULL);
- return out;
-#else
- char* real_path = realpath(path, NULL);
- return real_path ? real_path : lilv_strdup(path);
-#endif
-}
-
-bool
-lilv_path_exists(const char* path)
-{
-#if USE_LSTAT
- struct stat st;
- return !lstat(path, &st);
-#else
- return !access(path, F_OK);
-#endif
-}
-
-bool
-lilv_is_directory(const char* path)
-{
- struct stat st;
- return !stat(path, &st) && S_ISDIR(st.st_mode);
-}
-
-int
-lilv_copy_file(const char* src, const char* dst)
-{
- FILE* in = fopen(src, "r");
- if (!in) {
- return errno;
- }
-
- FILE* out = fopen(dst, "w");
- if (!out) {
- fclose(in);
- return errno;
- }
-
- char* page = (char*)malloc(PAGE_SIZE);
- size_t n_read = 0;
- int st = 0;
- while ((n_read = fread(page, 1, PAGE_SIZE, in)) > 0) {
- if (fwrite(page, 1, n_read, out) != n_read) {
- st = errno;
- break;
- }
- }
-
- if (!st && fflush(out)) {
- st = errno;
- }
-
- if (!st && (ferror(in) || ferror(out))) {
- st = EBADF;
- }
-
- free(page);
- fclose(in);
- fclose(out);
-
- return st;
-}
-
-int
-lilv_symlink(const char* oldpath, const char* newpath)
-{
- int ret = 0;
- if (strcmp(oldpath, newpath)) {
-#ifdef _WIN32
- ret = !CreateHardLink(newpath, oldpath, 0);
-#else
- char* target = lilv_path_relative_to(oldpath, newpath);
-
- ret = symlink(target, newpath);
-
- free(target);
-#endif
- }
- return ret;
-}
-
-int
-lilv_flock(FILE* file, bool lock, bool block)
-{
-#ifdef _WIN32
- HANDLE handle = (HANDLE)_get_osfhandle(fileno(file));
- OVERLAPPED overlapped = {0};
-
- if (lock) {
- const DWORD flags =
- (LOCKFILE_EXCLUSIVE_LOCK | (block ? 0 : LOCKFILE_FAIL_IMMEDIATELY));
-
- return !LockFileEx(handle, flags, 0, UINT32_MAX, UINT32_MAX, &overlapped);
- } else {
- return !UnlockFileEx(handle, 0, UINT32_MAX, UINT32_MAX, &overlapped);
- }
-#elif USE_FLOCK && USE_FILENO
- return flock(fileno(file),
- (lock ? LOCK_EX : LOCK_UN) | (block ? 0 : LOCK_NB));
-#else
- return 0;
-#endif
-}
-
-void
-lilv_dir_for_each(const char* path,
- void* data,
- void (*f)(const char* path, const char* name, void* data))
-{
-#ifdef _WIN32
- char* pat = lilv_path_join(path, "*");
- WIN32_FIND_DATA fd;
- HANDLE fh = FindFirstFile(pat, &fd);
- if (fh != INVALID_HANDLE_VALUE) {
- do {
- if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) {
- f(path, fd.cFileName, data);
- }
- } while (FindNextFile(fh, &fd));
- }
- FindClose(fh);
- free(pat);
-#else
- DIR* dir = opendir(path);
- if (dir) {
- for (struct dirent* entry = NULL; (entry = readdir(dir));) {
- if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
- f(path, entry->d_name, data);
- }
- }
- closedir(dir);
- }
-#endif
-}
-
-char*
-lilv_create_temporary_directory_in(const char* pattern, const char* parent)
-{
-#ifdef _WIN32
- static const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- static const int n_chars = sizeof(chars) - 1;
-
- const size_t pattern_len = strlen(pattern);
- if (pattern_len < 7 || strcmp(pattern + pattern_len - 6, "XXXXXX")) {
- errno = EINVAL;
- return NULL;
- }
-
- char* const path_pattern = lilv_path_join(parent, pattern);
- const size_t path_pattern_len = strlen(path_pattern);
- char* const suffix = path_pattern + path_pattern_len - 6;
-
- for (unsigned attempt = 0; attempt < 128; ++attempt) {
- for (unsigned i = 0; i < 6; ++i) {
- suffix[i] = chars[rand() % n_chars];
- }
-
- if (!mkdir(path_pattern, 0700)) {
- return path_pattern;
- }
- }
-
- return NULL;
-#else
- char* const path_pattern = lilv_path_join(parent, pattern);
-
- return mkdtemp(path_pattern); // NOLINT (not a leak)
-#endif
-}
-
-char*
-lilv_create_temporary_directory(const char* pattern)
-{
- char* const tmpdir = lilv_temp_directory_path();
- char* const result = lilv_create_temporary_directory_in(pattern, tmpdir);
-
- free(tmpdir);
-
- return result;
-}
-
-int
-lilv_create_directories(const char* dir_path)
-{
- char* path = lilv_strdup(dir_path);
- const size_t path_len = strlen(path);
- size_t i = 1;
-
-#ifdef _WIN32
- if (is_windows_path(dir_path)) {
- i = 3;
- }
-#endif
-
- for (; i <= path_len; ++i) {
- const char c = path[i];
- if (c == LILV_DIR_SEP[0] || c == '/' || c == '\0') {
- path[i] = '\0';
- if (mkdir(path, 0755) && (errno != EEXIST || !lilv_is_directory(path))) {
- free(path);
- return errno;
- }
- path[i] = c;
- }
- }
-
- free(path);
- return 0;
-}
-
-static off_t
-lilv_file_size(const char* path)
-{
- struct stat buf;
- if (stat(path, &buf)) {
- return 0;
- }
- return buf.st_size;
-}
-
-int
-lilv_remove(const char* path)
-{
-#ifdef _WIN32
- if (lilv_is_directory(path)) {
- return !RemoveDirectory(path);
- }
-#endif
-
- return remove(path);
-}
-
-bool
-lilv_file_equals(const char* a_path, const char* b_path)
-{
- if (!strcmp(a_path, b_path)) {
- return true; // Paths match
- }
-
- bool match = false;
- FILE* a_file = NULL;
- FILE* b_file = NULL;
- char* const a_real = lilv_path_canonical(a_path);
- char* const b_real = lilv_path_canonical(b_path);
- if (!strcmp(a_real, b_real)) {
- match = true; // Real paths match
- } else if (lilv_file_size(a_path) != lilv_file_size(b_path)) {
- match = false; // Sizes differ
- } else if (!(a_file = fopen(a_real, "rb")) ||
- !(b_file = fopen(b_real, "rb"))) {
- match = false; // Missing file matches nothing
- } else {
- // TODO: Improve performance by reading chunks
- match = true;
- while (!feof(a_file) && !feof(b_file)) {
- if (fgetc(a_file) != fgetc(b_file)) {
- match = false;
- break;
- }
- }
- }
-
- if (a_file) {
- fclose(a_file);
- }
- if (b_file) {
- fclose(b_file);
- }
- free(a_real);
- free(b_real);
- return match;
-}
diff --git a/src/filesystem.h b/src/filesystem.h
deleted file mode 100644
index 1a8dc68..0000000
--- a/src/filesystem.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include <stdbool.h>
-#include <stdio.h>
-
-/// Return the path to a directory suitable for making temporary files
-char*
-lilv_temp_directory_path(void);
-
-/// Return true iff `path` is an absolute path
-bool
-lilv_path_is_absolute(const char* path);
-
-/// Return true iff `path` is a child of `dir`
-bool
-lilv_path_is_child(const char* path, const char* dir);
-
-/// Return the current working directory
-char*
-lilv_path_current(void);
-
-/**
- Return `path` as an absolute path.
-
- If `path` is absolute, an identical copy of it is returned. Otherwise, the
- returned path is relative to the current working directory.
-*/
-char*
-lilv_path_absolute(const char* path);
-
-/**
- Return `path` as an absolute path relative to `parent`.
-
- If `path` is absolute, an identical copy of it is returned. Otherwise, the
- returned path is relative to `parent`.
-*/
-char*
-lilv_path_absolute_child(const char* path, const char* parent);
-
-/**
- Return `path` relative to `base` if possible.
-
- If `path` is not within `base`, a copy is returned. Otherwise, an
- equivalent path relative to `base` is returned (which may contain
- up-references).
-*/
-char*
-lilv_path_relative_to(const char* path, const char* base);
-
-/**
- Return the path to the directory that contains `path`.
-
- Returns the root path if `path` is the root path.
-*/
-char*
-lilv_path_parent(const char* path);
-
-/**
- Return the filename component of `path` without any directories.
-
- Returns the empty string if `path` is the root path.
-*/
-char*
-lilv_path_filename(const char* path);
-
-/// Join path `a` and path `b` with a single directory separator between them
-char*
-lilv_path_join(const char* a, const char* b);
-
-/**
- Return `path` as a canonicalized absolute path.
-
- This expands all symbolic links, relative references, and removes extra
- directory separators.
-*/
-char*
-lilv_path_canonical(const char* path);
-
-/// Return true iff `path` points to an existing file system entry
-bool
-lilv_path_exists(const char* path);
-
-/// Return true iff `path` points to an existing directory
-bool
-lilv_is_directory(const char* path);
-
-/**
- Copy the file at path `src` to path `dst`.
-
- @return Zero on success, or a standard `errno` error code.
-*/
-int
-lilv_copy_file(const char* src, const char* dst);
-
-/**
- Create a symlink at `newpath` that points to `oldpath`.
-
- @return Zero on success, otherwise non-zero and `errno` is set.
-*/
-int
-lilv_symlink(const char* oldpath, const char* newpath);
-
-/**
- Set or remove an advisory exclusive lock on `file`.
-
- If the `lock` is true and the file is already locked by another process, or
- by this process via a different file handle, then this will not succeed and
- non-zero will be returned.
-
- @param file Handle for open file to lock.
- @param lock True to set lock, false to release lock.
- @param block If true, then this call will block until the lock is acquired.
- @return Zero on success.
-*/
-int
-lilv_flock(FILE* file, bool lock, bool block);
-
-/**
- Visit every file in the directory at `path`.
-
- @param path A path to a directory.
-
- @param data Opaque user data that is passed to `f`.
-
- @param f A function called on every entry in the directory. The `path`
- parameter is always the directory path passed to this function, the `name`
- parameter is the name of the directory entry (not its full path).
-*/
-void
-lilv_dir_for_each(const char* path,
- void* data,
- void (*f)(const char* path, const char* name, void* data));
-
-/**
- Create a unique temporary directory in a specific directory.
-
- The last six characters of `pattern` must be `XXXXXX` and will be replaced
- with random characters. This works roughly like mkdtemp, except the pattern
- should only be a directory name, not a full path. The created path will be
- a child of the given parent directory.
-*/
-char*
-lilv_create_temporary_directory_in(const char* pattern, const char* parent);
-
-/**
- Create a unique temporary directory.
-
- This is like lilv_create_temporary_directory_in(), except it creates the
- directory in the system temporary directory.
-*/
-char*
-lilv_create_temporary_directory(const char* pattern);
-
-/**
- Create the directory `dir_path` and any parent directories if necessary.
-
- @return Zero on success, or an `errno` error code.
-*/
-int
-lilv_create_directories(const char* dir_path);
-
-/// Remove the file or empty directory at `path`
-int
-lilv_remove(const char* path);
-
-/// Return true iff the given paths point to files with identical contents
-bool
-lilv_file_equals(const char* a_path, const char* b_path);
diff --git a/src/instance.c b/src/instance.c
index 6a2b856..335984b 100644
--- a/src/instance.c
+++ b/src/instance.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "lv2/core/lv2.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
+#include <serd/serd.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/src/lib.c b/src/lib.c
index adba732..ac676bd 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -1,29 +1,13 @@
-/*
- Copyright 2012-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2012-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+#include "dylib.h"
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "lv2/core/lv2.h"
-#include "serd/serd.h"
-#include "zix/tree.h"
-
-#ifndef _WIN32
-# include <dlfcn.h>
-#endif
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
+#include <serd/serd.h>
+#include <zix/tree.h>
#include <stdint.h>
#include <stdlib.h>
@@ -50,33 +34,33 @@ lilv_lib_open(LilvWorld* world,
return NULL;
}
- dlerror();
- void* lib = dlopen(lib_path, RTLD_NOW);
+ dylib_error();
+ void* lib = dylib_open(lib_path, DYLIB_NOW);
if (!lib) {
- LILV_ERRORF("Failed to open library %s (%s)\n", lib_path, dlerror());
+ LILV_ERRORF("Failed to open library %s (%s)\n", lib_path, dylib_error());
serd_free(lib_path);
return NULL;
}
LV2_Descriptor_Function df =
- (LV2_Descriptor_Function)lilv_dlfunc(lib, "lv2_descriptor");
+ (LV2_Descriptor_Function)dylib_func(lib, "lv2_descriptor");
LV2_Lib_Descriptor_Function ldf =
- (LV2_Lib_Descriptor_Function)lilv_dlfunc(lib, "lv2_lib_descriptor");
+ (LV2_Lib_Descriptor_Function)dylib_func(lib, "lv2_lib_descriptor");
const LV2_Lib_Descriptor* desc = NULL;
if (ldf) {
desc = ldf(bundle_path, features);
if (!desc) {
LILV_ERRORF("Call to %s:lv2_lib_descriptor failed\n", lib_path);
- dlclose(lib);
+ dylib_close(lib);
serd_free(lib_path);
return NULL;
}
} else if (!df) {
LILV_ERRORF("No `lv2_descriptor' or `lv2_lib_descriptor' in %s\n",
lib_path);
- dlclose(lib);
+ dylib_close(lib);
serd_free(lib_path);
return NULL;
}
@@ -113,7 +97,7 @@ void
lilv_lib_close(LilvLib* lib)
{
if (--lib->refs == 0) {
- dlclose(lib->lib);
+ dylib_close(lib->lib);
ZixTreeIter* i = NULL;
if (lib->world->libs && !zix_tree_find(lib->world->libs, lib, &i)) {
diff --git a/src/lilv_config.h b/src/lilv_config.h
index 10231c5..1198ce2 100644
--- a/src/lilv_config.h
+++ b/src/lilv_config.h
@@ -1,102 +1,11 @@
-/*
- Copyright 2021 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/*
- Configuration header that defines reasonable defaults at compile time.
-
- This allows compile-time configuration from the command line (typically via
- the build system) while still allowing the source to be built without any
- configuration. The build system can define LILV_NO_DEFAULT_CONFIG to disable
- defaults, in which case it must define things like HAVE_FEATURE to enable
- features. The design here ensures that compiler warnings or
- include-what-you-use will catch any mistakes.
-*/
+// Copyright 2021-2024 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef LILV_CONFIG_H
#define LILV_CONFIG_H
// Define version unconditionally so a warning will catch a mismatch
-#define LILV_VERSION "0.24.13"
-
-#if !defined(LILV_NO_DEFAULT_CONFIG)
-
-// We need unistd.h to check _POSIX_VERSION
-# ifndef LILV_NO_POSIX
-# ifdef __has_include
-# if __has_include(<unistd.h>)
-# include <unistd.h>
-# endif
-# elif defined(__unix__)
-# include <unistd.h>
-# endif
-# endif
-
-// POSIX.1-2001: fileno()
-# ifndef HAVE_FILENO
-# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
-# define HAVE_FILENO
-# endif
-# endif
-
-// Classic UNIX: flock()
-# ifndef HAVE_FLOCK
-# if defined(__unix__)
-# define HAVE_FLOCK
-# endif
-# endif
-
-// POSIX.1-2001: lstat()
-# ifndef HAVE_LSTAT
-# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
-# define HAVE_LSTAT
-# endif
-# endif
-
-#endif // !defined(LILV_NO_DEFAULT_CONFIG)
-
-/*
- Make corresponding USE_FEATURE defines based on the HAVE_FEATURE defines from
- above or the command line. The code checks for these using #if (not #ifdef),
- so there will be an undefined warning if it checks for an unknown feature,
- and this header is always required by any code that checks for features, even
- if the build system defines them all.
-*/
-
-#ifdef HAVE_FILENO
-# define USE_FILENO 1
-#else
-# define USE_FILENO 0
-#endif
-
-#ifdef HAVE_FLOCK
-# define USE_FLOCK 1
-#else
-# define USE_FLOCK 0
-#endif
-
-#ifdef HAVE_LSTAT
-# define USE_LSTAT 1
-#else
-# define USE_LSTAT 0
-#endif
-
-/*
- Define required values. These are always used as a fallback, even with
- LILV_NO_DEFAULT_CONFIG, since they must be defined for the build to work.
-*/
+#define LILV_VERSION "0.24.27"
// Separator between entries in variables like PATH
#ifndef LILV_PATH_SEP
@@ -107,21 +16,17 @@
# endif
#endif
-// Separator between directories in a path
-#ifndef LILV_DIR_SEP
-# ifdef _WIN32
-# define LILV_DIR_SEP "\\"
-# else
-# define LILV_DIR_SEP "/"
-# endif
-#endif
-
// Default value for LV2_PATH environment variable
#ifndef LILV_DEFAULT_LV2_PATH
-# ifdef _WIN32
+# if defined(__APPLE__)
+# define LILV_DEFAULT_LV2_PATH \
+ "~/.lv2:~/Library/Audio/Plug-Ins/LV2:" \
+ "/usr/local/lib/lv2:/usr/lib/lv2:" \
+ "/Library/Audio/Plug-Ins/LV2"
+# elif defined(_WIN32)
# define LILV_DEFAULT_LV2_PATH "%APPDATA%\\LV2;%COMMONPROGRAMFILES%\\LV2"
# else
-# define LILV_DEFAULT_LV2_PATH "~/.lv2:/usr/lib/lv2:/usr/local/lib/lv2"
+# define LILV_DEFAULT_LV2_PATH "~/.lv2:/usr/local/lib/lv2:/usr/lib/lv2"
# endif
#endif
diff --git a/src/lilv_internal.h b/src/lilv_internal.h
index 12b56de..2cef3aa 100644
--- a/src/lilv_internal.h
+++ b/src/lilv_internal.h
@@ -1,18 +1,5 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef LILV_INTERNAL_H
#define LILV_INTERNAL_H
@@ -21,47 +8,18 @@
extern "C" {
#endif
-#include "lilv_config.h" // IWYU pragma: keep
-
-#include "lilv/lilv.h"
-#include "lv2/core/lv2.h"
-#include "serd/serd.h"
-#include "sord/sord.h"
-#include "zix/tree.h"
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
+#include <serd/serd.h>
+#include <sord/sord.h>
+#include <zix/tree.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
-#ifdef _WIN32
-# include <direct.h>
-# include <stdio.h>
-# include <windows.h>
-# define dlopen(path, flags) LoadLibrary(path)
-# define dlclose(lib) FreeLibrary((HMODULE)lib)
-# ifdef _MSC_VER
-# define __func__ __FUNCTION__
-# ifndef snprintf
-# define snprintf _snprintf
-# endif
-# endif
-# ifndef INFINITY
-# define INFINITY DBL_MAX + DBL_MAX
-# endif
-# ifndef NAN
-# define NAN INFINITY - INFINITY
-# endif
-static inline const char*
-dlerror(void)
-{
- return "Unknown error";
-}
-#else
-# include <dlfcn.h>
-#endif
-
#ifdef LILV_DYN_MANIFEST
-# include "lv2/dynmanifest/dynmanifest.h"
+# include <lv2/dynmanifest/dynmanifest.h>
#endif
/*
@@ -275,15 +233,6 @@ lilv_plugin_get_unique(const LilvPlugin* plugin,
const SordNode* subject,
const SordNode* predicate);
-void
-lilv_collection_free(LilvCollection* collection);
-
-unsigned
-lilv_collection_size(const LilvCollection* collection);
-
-LilvIter*
-lilv_collection_begin(const LilvCollection* collection);
-
void*
lilv_collection_get(const LilvCollection* collection, const LilvIter* i);
@@ -332,9 +281,6 @@ lilv_world_blank_node_prefix(LilvWorld* world);
SerdStatus
lilv_world_load_file(LilvWorld* world, SerdReader* reader, const LilvNode* uri);
-SerdStatus
-lilv_world_load_graph(LilvWorld* world, SordNode* graph, const LilvNode* uri);
-
LilvUI*
lilv_ui_new(LilvWorld* world,
LilvNode* uri,
@@ -354,9 +300,6 @@ int
lilv_header_compare_by_uri(const void* a, const void* b, const void* user_data);
int
-lilv_lib_compare(const void* a, const void* b, const void* user_data);
-
-int
lilv_ptr_cmp(const void* a, const void* b, const void* user_data);
int
@@ -428,9 +371,6 @@ char*
lilv_get_lang(void);
char*
-lilv_expand(const char* path);
-
-char*
lilv_get_latest_copy(const char* path, const char* copy_path);
char*
@@ -438,21 +378,6 @@ lilv_find_free_path(const char* in_path,
bool (*exists)(const char*, const void*),
const void* user_data);
-typedef void (*LilvVoidFunc)(void);
-
-/** dlsym wrapper to return a function pointer (without annoying warning) */
-static inline LilvVoidFunc
-lilv_dlfunc(void* handle, const char* symbol)
-{
-#ifdef _WIN32
- return (LilvVoidFunc)GetProcAddress((HMODULE)handle, symbol);
-#else
- typedef LilvVoidFunc (*VoidFuncGetter)(void*, const char*);
- VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym;
- return dlfunc(handle, symbol);
-#endif
-}
-
#ifdef LILV_DYN_MANIFEST
static const LV2_Feature* const dman_features = {NULL};
diff --git a/src/node.c b/src/node.c
index ac47e80..42c2b56 100644
--- a/src/node.c
+++ b/src/node.c
@@ -1,25 +1,14 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "filesystem.h"
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "serd/serd.h"
-#include "sord/sord.h"
+#include <lilv/lilv.h>
+#include <serd/serd.h>
+#include <sord/sord.h>
+#include <zix/allocator.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
#include <math.h>
#include <stdbool.h>
@@ -108,9 +97,9 @@ lilv_node_new_from_node(LilvWorld* world, const SordNode* node)
return NULL;
}
- LilvNode* result = NULL;
- SordNode* datatype_uri = NULL;
- LilvNodeType type = LILV_VALUE_STRING;
+ LilvNode* result = NULL;
+ const SordNode* datatype_uri = NULL;
+ LilvNodeType type = LILV_VALUE_STRING;
switch (sord_node_get_type(node)) {
case SORD_URI:
@@ -160,13 +149,23 @@ lilv_new_uri(LilvWorld* world, const char* uri)
LilvNode*
lilv_new_file_uri(LilvWorld* world, const char* host, const char* path)
{
- char* abs_path = lilv_path_absolute(path);
- SerdNode s = serd_node_new_file_uri(
- (const uint8_t*)abs_path, (const uint8_t*)host, NULL, true);
+ SerdNode s = SERD_NODE_NULL;
+ if (zix_path_root_directory(path).length) {
+ s = serd_node_new_file_uri(
+ (const uint8_t*)path, (const uint8_t*)host, NULL, true);
+ } else {
+ char* const cwd = zix_current_path(NULL);
+ char* const abs_path = zix_path_join(NULL, cwd, path);
+
+ s = serd_node_new_file_uri(
+ (const uint8_t*)abs_path, (const uint8_t*)host, NULL, true);
+
+ zix_free(NULL, abs_path);
+ zix_free(NULL, cwd);
+ }
LilvNode* ret = lilv_node_new(world, LILV_VALUE_URI, (const char*)s.buf);
serd_node_free(&s);
- free(abs_path);
return ret;
}
diff --git a/src/plugin.c b/src/plugin.c
index 9c7cbfd..c82bb65 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -1,33 +1,20 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "serd/serd.h"
-#include "sord/sord.h"
-#include "zix/tree.h"
-
-#include "lv2/core/lv2.h"
-#include "lv2/ui/ui.h"
-
#ifdef LILV_DYN_MANIFEST
-# include "lv2/dynmanifest/dynmanifest.h"
+# include "dylib.h"
+# include <lv2/dynmanifest/dynmanifest.h>
#endif
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
+#include <lv2/ui/ui.h>
+#include <serd/serd.h>
+#include <sord/sord.h>
+#include <zix/tree.h>
+
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -225,8 +212,8 @@ lilv_plugin_load(LilvPlugin* plugin)
// Load and parse dynamic manifest data, if this is a library
if (plugin->dynmanifest) {
typedef int (*GetDataFunc)(
- LV2_Dyn_Manifest_Handle handle, FILE * fp, const char* uri);
- GetDataFunc get_data_func = (GetDataFunc)lilv_dlfunc(
+ LV2_Dyn_Manifest_Handle handle, FILE* fp, const char* uri);
+ GetDataFunc get_data_func = (GetDataFunc)dylib_func(
plugin->dynmanifest->lib, "lv2_dyn_manifest_get_data");
if (get_data_func) {
const SordNode* bundle = plugin->dynmanifest->bundle->node;
@@ -320,7 +307,7 @@ lilv_plugin_load_ports_if_necessary(const LilvPlugin* const_plugin)
plugin->num_ports = this_index + 1;
}
- // Havn't seen this port yet, add it to array
+ // Haven't seen this port yet, add it to array
if (!this_port) {
this_port = lilv_port_new(
plugin->world, port, this_index, lilv_node_as_string(symbol));
@@ -502,7 +489,7 @@ lilv_plugin_get_name(const LilvPlugin* plugin)
LilvNode* ret = NULL;
if (results) {
- LilvNode* val = lilv_nodes_get_first(results);
+ const LilvNode* val = lilv_nodes_get_first(results);
if (lilv_node_is_string(val)) {
ret = lilv_node_duplicate(val);
}
@@ -580,9 +567,11 @@ lilv_plugin_get_port_ranges_float(const LilvPlugin* plugin,
}
uint32_t
-lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* plugin,
- const LilvNode* class_1,
- va_list args)
+lilv_plugin_get_num_ports_of_class_va(
+ const LilvPlugin* plugin,
+ const LilvNode* class_1,
+ va_list args // NOLINT(readability-non-const-parameter)
+)
{
lilv_plugin_load_ports_if_necessary(plugin);
@@ -599,7 +588,7 @@ lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* plugin,
// Check each port against every type
for (unsigned i = 0; i < plugin->num_ports; ++i) {
- LilvPort* port = plugin->ports[i];
+ const LilvPort* port = plugin->ports[i];
if (port && lilv_port_is_a(plugin, port, class_1)) {
bool matches = true;
for (size_t j = 0; j < n_classes; ++j) {
@@ -624,7 +613,7 @@ lilv_plugin_get_num_ports_of_class(const LilvPlugin* plugin,
const LilvNode* class_1,
...)
{
- va_list args;
+ va_list args; // NOLINT(cppcoreguidelines-init-variables)
va_start(args, class_1);
uint32_t count = lilv_plugin_get_num_ports_of_class_va(plugin, class_1, args);
@@ -1008,7 +997,7 @@ lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type)
LilvNodes* matches = lilv_nodes_new();
LILV_FOREACH (nodes, i, related) {
- LilvNode* node = (LilvNode*)lilv_collection_get((ZixTree*)related, i);
+ const LilvNode* node = (LilvNode*)lilv_collection_get((ZixTree*)related, i);
if (lilv_world_ask_internal(
world, node->node, world->uris.rdf_a, type->node)) {
zix_tree_insert(
@@ -1039,7 +1028,7 @@ new_lv2_env(const SerdNode* base)
}
static void
-maybe_write_prefixes(SerdWriter* writer, SerdEnv* env, FILE* file)
+maybe_write_prefixes(SerdWriter* writer, const SerdEnv* env, FILE* file)
{
fseek(file, 0, SEEK_END);
if (ftell(file) == 0) {
diff --git a/src/pluginclass.c b/src/pluginclass.c
index 2f0afe7..fceae2c 100644
--- a/src/pluginclass.c
+++ b/src/pluginclass.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "sord/sord.h"
-#include "zix/tree.h"
+#include <lilv/lilv.h>
+#include <sord/sord.h>
+#include <zix/tree.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -73,8 +60,9 @@ LilvPluginClasses*
lilv_plugin_class_get_children(const LilvPluginClass* plugin_class)
{
// Returned list doesn't own categories
- LilvPluginClasses* all = plugin_class->world->plugin_classes;
- LilvPluginClasses* result = zix_tree_new(false, lilv_ptr_cmp, NULL, NULL);
+ LilvPluginClasses* all = plugin_class->world->plugin_classes;
+ LilvPluginClasses* result =
+ zix_tree_new(NULL, false, lilv_header_compare_by_uri, NULL, NULL, NULL);
for (ZixTreeIter* i = zix_tree_begin((ZixTree*)all);
i != zix_tree_end((ZixTree*)all);
diff --git a/src/port.c b/src/port.c
index 71edaf1..a04298c 100644
--- a/src/port.c
+++ b/src/port.c
@@ -1,28 +1,14 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lv2/atom/atom.h"
-#include "lv2/core/lv2.h"
-#include "lv2/event/event.h"
-
-#include "lilv/lilv.h"
-#include "sord/sord.h"
-#include "zix/tree.h"
+#include <lilv/lilv.h>
+#include <lv2/atom/atom.h>
+#include <lv2/core/lv2.h>
+#include <lv2/event/event.h>
+#include <sord/sord.h>
+#include <zix/tree.h>
#include <assert.h>
#include <stdbool.h>
@@ -173,7 +159,7 @@ lilv_port_get_name(const LilvPlugin* plugin, const LilvPort* port)
LilvNode* ret = NULL;
if (results) {
- LilvNode* val = lilv_nodes_get_first(results);
+ const LilvNode* val = lilv_nodes_get_first(results);
if (lilv_node_is_string(val)) {
ret = lilv_node_duplicate(val);
}
@@ -237,11 +223,12 @@ lilv_port_get_scale_points(const LilvPlugin* plugin, const LilvPort* port)
sord_new_uri(plugin->world->world, (const uint8_t*)LV2_CORE__scalePoint),
NULL);
- LilvScalePoints* ret = NULL;
- if (!sord_iter_end(points)) {
- ret = lilv_scale_points_new();
+ if (!points) {
+ return NULL;
}
+ LilvScalePoints* ret = lilv_scale_points_new();
+
FOREACH_MATCH (points) {
const SordNode* point = sord_iter_get_node(points, SORD_OBJECT);
@@ -253,11 +240,14 @@ lilv_port_get_scale_points(const LilvPlugin* plugin, const LilvPort* port)
if (value && label) {
zix_tree_insert((ZixTree*)ret, lilv_scale_point_new(value, label), NULL);
+ } else {
+ lilv_node_free(label);
+ lilv_node_free(value);
}
}
sord_iter_free(points);
- assert(!ret || lilv_nodes_size(ret) > 0);
+ assert(lilv_nodes_size(ret) > 0);
return ret;
}
diff --git a/src/query.c b/src/query.c
index eb179f2..6781fc6 100644
--- a/src/query.c
+++ b/src/query.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "sord/sord.h"
-#include "zix/tree.h"
+#include <lilv/lilv.h>
+#include <sord/sord.h>
+#include <zix/tree.h>
#include <stdlib.h>
#include <string.h>
@@ -96,12 +83,7 @@ lilv_nodes_from_stream_objects_i18n(LilvWorld* world,
}
const SordNode* best = nolang;
- if (syslang && partial) {
- // Partial language match for system language
- best = partial;
- } else if (!best) {
- // No languages matches at all, and no untranslated value
- // Use any value, if possible
+ if ((syslang && partial) || !best) {
best = partial;
}
diff --git a/src/scalepoint.c b/src/scalepoint.c
index e2db948..f1dc763 100644
--- a/src/scalepoint.c
+++ b/src/scalepoint.c
@@ -1,22 +1,9 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <stdlib.h>
diff --git a/src/state.c b/src/state.c
index a4a50a9..5eb44a4 100644
--- a/src/state.c
+++ b/src/state.c
@@ -1,34 +1,24 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "filesystem.h"
-#include "lilv_internal.h"
+// Copyright 2007-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "lilv/lilv.h"
-#include "serd/serd.h"
-#include "sord/sord.h"
-#include "sratom/sratom.h"
-#include "zix/tree.h"
+#include "lilv_internal.h"
-#include "lv2/atom/atom.h"
-#include "lv2/atom/forge.h"
-#include "lv2/core/lv2.h"
-#include "lv2/presets/presets.h"
-#include "lv2/state/state.h"
-#include "lv2/urid/urid.h"
+#include <lilv/lilv.h>
+#include <lv2/atom/atom.h>
+#include <lv2/atom/forge.h>
+#include <lv2/core/lv2.h>
+#include <lv2/presets/presets.h>
+#include <lv2/state/state.h>
+#include <lv2/urid/urid.h>
+#include <serd/serd.h>
+#include <sord/sord.h>
+#include <sratom/sratom.h>
+#include <zix/allocator.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
+#include <zix/status.h>
+#include <zix/string_view.h>
+#include <zix/tree.h>
#include <assert.h>
#include <errno.h>
@@ -120,8 +110,9 @@ value_cmp(const void* a, const void* b)
}
static void
-path_rel_free(void* ptr)
+map_free(void* ptr, const void* user_data)
{
+ (void)user_data;
free(((PathMap*)ptr)->abs);
free(((PathMap*)ptr)->rel);
free(ptr);
@@ -161,13 +152,13 @@ lilv_state_rel2abs(const LilvState* state, const char* path)
}
static void
-append_property(LilvState* state,
- PropertyArray* array,
- uint32_t key,
- const void* value,
- size_t size,
- uint32_t type,
- uint32_t flags)
+append_property(const LilvState* state,
+ PropertyArray* array,
+ uint32_t key,
+ const void* value,
+ size_t size,
+ uint32_t type,
+ uint32_t flags)
{
array->props =
(Property*)realloc(array->props, (++array->n) * sizeof(Property));
@@ -234,9 +225,15 @@ retrieve_callback(LV2_State_Handle handle,
const Property* const prop = find_property((const LilvState*)handle, key);
if (prop) {
- *size = prop->size;
- *type = prop->type;
- *flags = prop->flags;
+ if (size) {
+ *size = prop->size;
+ }
+ if (type) {
+ *type = prop->type;
+ }
+ if (flags) {
+ *flags = prop->flags;
+ }
return prop->value;
}
return NULL;
@@ -247,7 +244,7 @@ path_exists(const char* path, const void* ignored)
{
(void)ignored;
- return lilv_path_exists(path);
+ return zix_file_type(path) != ZIX_FILE_TYPE_NONE;
}
static bool
@@ -259,20 +256,35 @@ lilv_state_has_path(const char* path, const void* state)
static char*
make_path(LV2_State_Make_Path_Handle handle, const char* path)
{
- LilvState* state = (LilvState*)handle;
- lilv_create_directories(state->dir);
+ const LilvState* state = (const LilvState*)handle;
+ return !zix_create_directories(NULL, state->dir)
+ ? zix_path_join(NULL, state->dir, path)
+ : NULL;
+}
- return lilv_path_join(state->dir, path);
+static bool
+path_is_child(const char* path, const char* dir)
+{
+ if (path && dir) {
+ const size_t path_len = strlen(path);
+ const size_t dir_len = strlen(dir);
+ return path_len >= dir_len && !strncmp(path, dir, dir_len);
+ }
+ return false;
}
static char*
abstract_path(LV2_State_Map_Path_Handle handle, const char* abs_path)
{
- LilvState* state = (LilvState*)handle;
- char* path = NULL;
- char* real_path = lilv_path_canonical(abs_path);
- const PathMap key = {real_path, NULL};
- ZixTreeIter* iter = NULL;
+ LilvState* state = (LilvState*)handle;
+ char* path = NULL;
+ char* real_path = zix_canonical_path(NULL, abs_path);
+ if (!real_path) {
+ real_path = zix_path_lexically_normal(NULL, abs_path);
+ }
+
+ const PathMap key = {real_path, NULL};
+ ZixTreeIter* iter = NULL;
if (abs_path[0] == '\0') {
return lilv_strdup(abs_path);
@@ -280,48 +292,48 @@ abstract_path(LV2_State_Map_Path_Handle handle, const char* abs_path)
if (!zix_tree_find(state->abs2rel, &key, &iter)) {
// Already mapped path in a previous call
- PathMap* pm = (PathMap*)zix_tree_get(iter);
- free(real_path);
+ const PathMap* pm = (const PathMap*)zix_tree_get(iter);
+ zix_free(NULL, real_path);
return lilv_strdup(pm->rel);
}
- if (lilv_path_is_child(real_path, state->dir)) {
+ if (path_is_child(real_path, state->dir)) {
// File in state directory (loaded, or created by plugin during save)
- path = lilv_path_relative_to(real_path, state->dir);
- } else if (lilv_path_is_child(real_path, state->scratch_dir)) {
+ path = zix_path_lexically_relative(NULL, real_path, state->dir);
+ } else if (path_is_child(real_path, state->scratch_dir)) {
// File created by plugin earlier
- path = lilv_path_relative_to(real_path, state->scratch_dir);
+ path = zix_path_lexically_relative(NULL, real_path, state->scratch_dir);
if (state->copy_dir) {
- int st = lilv_create_directories(state->copy_dir);
+ ZixStatus st = zix_create_directories(NULL, state->copy_dir);
if (st) {
- LILV_ERRORF(
- "Error creating directory %s (%s)\n", state->copy_dir, strerror(st));
+ LILV_ERRORF("Error creating directory %s (%s)\n",
+ state->copy_dir,
+ zix_strerror(st));
}
- char* cpath = lilv_path_join(state->copy_dir, path);
+ char* cpath = zix_path_join(NULL, state->copy_dir, path);
char* copy = lilv_get_latest_copy(real_path, cpath);
- if (!copy || !lilv_file_equals(real_path, copy)) {
+ if (!copy || !zix_file_equals(NULL, real_path, copy)) {
// No recent enough copy, make a new one
free(copy);
copy = lilv_find_free_path(cpath, path_exists, NULL);
- if ((st = lilv_copy_file(real_path, copy))) {
- LILV_ERRORF("Error copying state file %s (%s)\n", copy, strerror(st));
+ if ((st = zix_copy_file(NULL, real_path, copy, 0U))) {
+ LILV_ERRORF(
+ "Error copying state file %s (%s)\n", copy, zix_strerror(st));
}
}
- free(real_path);
- free(cpath);
+ zix_free(NULL, real_path);
+ zix_free(NULL, cpath);
// Refer to the latest copy in plugin state
real_path = copy;
}
} else if (state->link_dir) {
// New path outside state directory, make a link
- char* const name = lilv_path_filename(real_path);
+ const ZixStringView name = zix_path_filename(real_path);
// Find a free name in the (virtual) state directory
- path = lilv_find_free_path(name, lilv_state_has_path, state);
-
- free(name);
+ path = lilv_find_free_path(name.data, lilv_state_has_path, state);
} else {
// No link directory, preserve absolute path
path = lilv_strdup(abs_path);
@@ -340,14 +352,14 @@ abstract_path(LV2_State_Map_Path_Handle handle, const char* abs_path)
static char*
absolute_path(LV2_State_Map_Path_Handle handle, const char* state_path)
{
- LilvState* state = (LilvState*)handle;
- char* path = NULL;
- if (lilv_path_is_absolute(state_path)) {
+ const LilvState* state = (const LilvState*)handle;
+ char* path = NULL;
+ if (zix_path_is_absolute(state_path)) {
// Absolute path, return identical path
path = lilv_strdup(state_path);
} else if (state->dir) {
// Relative path inside state directory
- path = lilv_path_join(state->dir, state_path);
+ path = zix_path_join(NULL, state->dir, state_path);
} else {
// State has not been saved, unmap
path = lilv_strdup(lilv_state_rel2abs(state, state_path));
@@ -365,6 +377,15 @@ add_features(const LV2_Feature* const* features,
{
size_t n_features = 0;
for (; features && features[n_features]; ++n_features) {
+ if (!strcmp(features[n_features]->URI, LV2_STATE__mapPath)) {
+ map = NULL;
+ }
+ if (!strcmp(features[n_features]->URI, LV2_STATE__makePath)) {
+ make = NULL;
+ }
+ if (!strcmp(features[n_features]->URI, LV2_STATE__freePath)) {
+ free = NULL;
+ }
}
const LV2_Feature** ret =
@@ -388,14 +409,15 @@ add_features(const LV2_Feature* const* features,
return ret;
}
-/// Return the canonical path for a directory with a trailing separator
+/// Return a normal path for a directory with a trailing separator
static char*
-real_dir(const char* path)
+normal_dir(const char* path)
{
- char* abs_path = lilv_path_canonical(path);
- char* base = lilv_path_join(abs_path, NULL);
- free(abs_path);
- return base;
+ char* const normal_path = zix_path_lexically_normal(NULL, path);
+ char* const base_path = zix_path_join(NULL, normal_path, NULL);
+
+ zix_free(NULL, normal_path);
+ return base_path;
}
static const char*
@@ -442,12 +464,12 @@ lilv_state_new_from_instance(const LilvPlugin* plugin,
LilvWorld* const world = plugin->world;
LilvState* const state = (LilvState*)calloc(1, sizeof(LilvState));
state->plugin_uri = lilv_node_duplicate(lilv_plugin_get_uri(plugin));
- state->abs2rel = zix_tree_new(false, abs_cmp, NULL, path_rel_free);
- state->rel2abs = zix_tree_new(false, rel_cmp, NULL, NULL);
- state->scratch_dir = scratch_dir ? real_dir(scratch_dir) : NULL;
- state->copy_dir = copy_dir ? real_dir(copy_dir) : NULL;
- state->link_dir = link_dir ? real_dir(link_dir) : NULL;
- state->dir = save_dir ? real_dir(save_dir) : NULL;
+ state->abs2rel = zix_tree_new(NULL, false, abs_cmp, NULL, map_free, NULL);
+ state->rel2abs = zix_tree_new(NULL, false, rel_cmp, NULL, NULL, NULL);
+ state->scratch_dir = scratch_dir ? normal_dir(scratch_dir) : NULL;
+ state->copy_dir = copy_dir ? normal_dir(copy_dir) : NULL;
+ state->link_dir = link_dir ? normal_dir(link_dir) : NULL;
+ state->dir = save_dir ? normal_dir(save_dir) : NULL;
state->atom_Path = map->map(map->handle, LV2_ATOM__Path);
LV2_State_Map_Path pmap = {state, abstract_path, absolute_path};
@@ -571,10 +593,10 @@ set_state_dir_from_model(LilvState* state, const SordNode* graph)
const char* uri = (const char*)sord_node_get_string(graph);
char* path = lilv_file_uri_parse(uri, NULL);
- state->dir = lilv_path_join(path, NULL);
+ state->dir = zix_path_join(NULL, path, NULL);
free(path);
}
- assert(!state->dir || lilv_path_is_absolute(state->dir));
+ assert(!state->dir || zix_path_is_absolute(state->dir));
}
static LilvState*
@@ -591,7 +613,7 @@ new_state_from_model(LilvWorld* world,
// Allocate state
LilvState* const state = (LilvState*)calloc(1, sizeof(LilvState));
- state->dir = lilv_path_join(dir, NULL);
+ state->dir = dir ? zix_path_join(NULL, dir, NULL) : NULL;
state->atom_Path = map->map(map->handle, LV2_ATOM__Path);
state->uri = lilv_node_new_from_node(world, node);
@@ -647,12 +669,13 @@ new_state_from_model(LilvWorld* world,
chunk.len = 0;
sratom_read(sratom, &forge, world->world, model, value);
const LV2_Atom* atom = (const LV2_Atom*)chunk.buf;
-
- append_port_value(state,
- (const char*)sord_node_get_string(symbol),
- LV2_ATOM_BODY_CONST(atom),
- atom->size,
- atom->type);
+ if (atom) {
+ append_port_value(state,
+ (const char*)sord_node_get_string(symbol),
+ LV2_ATOM_BODY_CONST(atom),
+ atom->size,
+ atom->type);
+ }
if (label) {
lilv_state_set_label(state, (const char*)sord_node_get_string(label));
@@ -682,6 +705,9 @@ new_state_from_model(LilvWorld* world,
const LV2_Atom* atom = (const LV2_Atom*)chunk.buf;
uint32_t flags = LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE;
Property prop = {NULL, 0, 0, 0, flags};
+ if (!atom) {
+ continue;
+ }
prop.key = map->map(map->handle, key);
prop.type = atom->type;
@@ -742,29 +768,35 @@ lilv_state_new_from_file(LilvWorld* world,
return NULL;
}
- uint8_t* abs_path = (uint8_t*)lilv_path_absolute(path);
- SerdNode node = serd_node_new_file_uri(abs_path, NULL, NULL, true);
- SerdEnv* env = serd_env_new(&node);
- SordModel* model = sord_new(world->world, SORD_SPO, false);
- SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
+ uint8_t* const abs_path = (uint8_t*)zix_canonical_path(NULL, path);
+ if (!abs_path) {
+ return NULL;
+ }
+
+ SerdNode node = serd_node_new_file_uri(abs_path, NULL, NULL, true);
+ SerdEnv* env = serd_env_new(&node);
+ SordModel* model = sord_new(world->world, SORD_SPO, false);
+ SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
- serd_reader_read_file(reader, node.buf);
+ serd_reader_read_file(reader, (const uint8_t*)node.buf);
- SordNode* subject_node =
+ const SordNode* subject_node =
(subject) ? subject->node
: sord_node_from_serd_node(world->world, env, &node, NULL, NULL);
- char* dirname = lilv_path_parent(path);
- char* real_path = lilv_path_canonical(dirname);
- char* dir_path = lilv_path_join(real_path, NULL);
- LilvState* state =
+ char* const dirname = zix_string_view_copy(NULL, zix_path_parent_path(path));
+ char* const real_path = zix_canonical_path(NULL, dirname);
+ char* const dir_path = zix_path_join(NULL, real_path, NULL);
+
+ LilvState* const state =
new_state_from_model(world, map, model, subject_node, dir_path);
- free(dir_path);
- free(real_path);
- free(dirname);
+
+ zix_free(NULL, dir_path);
+ zix_free(NULL, real_path);
+ zix_free(NULL, dirname);
serd_node_free(&node);
- free(abs_path);
+ zix_free(NULL, abs_path);
serd_reader_free(reader);
sord_free(model);
serd_env_free(env);
@@ -818,7 +850,7 @@ ttl_writer(SerdSink sink, void* stream, const SerdNode* base, SerdEnv** new_env)
{
SerdURI base_uri = SERD_URI_NULL;
if (base && base->buf) {
- serd_uri_parse(base->buf, &base_uri);
+ serd_uri_parse((const uint8_t*)base->buf, &base_uri);
}
SerdEnv* env = *new_env ? *new_env : serd_env_new(base);
@@ -881,7 +913,7 @@ remove_manifest_entry(SordWorld* world, SordModel* model, const char* subject)
SordNode* s = sord_new_uri(world, USTR(subject));
SordIter* i = sord_search(model, s, NULL, NULL, NULL);
while (!sord_iter_end(i)) {
- sord_erase(model, i);
+ (void)sord_erase(model, i);
}
sord_iter_free(i);
sord_node_free(world, s);
@@ -895,11 +927,12 @@ write_manifest(LilvWorld* world,
{
(void)world;
- char* const path = (char*)serd_file_uri_parse(file_uri->buf, NULL);
- FILE* const wfd = fopen(path, "w");
+ char* const path =
+ (char*)serd_file_uri_parse((const uint8_t*)file_uri->buf, NULL);
+
+ FILE* const wfd = path ? fopen(path, "w") : NULL;
if (!wfd) {
LILV_ERRORF("Failed to open %s for writing (%s)\n", path, strerror(errno));
-
serd_free(path);
return 1;
}
@@ -925,10 +958,11 @@ add_state_to_manifest(LilvWorld* lworld,
SerdEnv* env = serd_env_new(&manifest);
SordModel* model = sord_new(world, SORD_SPO, false);
- if (lilv_path_exists(manifest_path)) {
+ const uint8_t* const manifest_uri = manifest.buf;
+ if (manifest_uri && zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR) {
// Read manifest into model
SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
- SerdStatus st = serd_reader_read_file(reader, manifest.buf);
+ SerdStatus st = serd_reader_read_file(reader, manifest_uri);
if (st) {
LILV_WARNF("Failed to read manifest (%s)\n", serd_strerror(st));
}
@@ -988,15 +1022,15 @@ add_state_to_manifest(LilvWorld* lworld,
LILV_ERRORF(
"Failed to open %s for writing (%s)\n", manifest_path, strerror(errno));
r = 1;
+ } else {
+ SerdWriter* writer = ttl_file_writer(wfd, &manifest, &env);
+ zix_file_lock(wfd, ZIX_FILE_LOCK_BLOCK);
+ sord_write(model, writer, NULL);
+ zix_file_unlock(wfd, ZIX_FILE_LOCK_BLOCK);
+ serd_writer_free(writer);
+ fclose(wfd);
}
- SerdWriter* writer = ttl_file_writer(wfd, &manifest, &env);
- lilv_flock(wfd, true, true);
- sord_write(model, writer, NULL);
- lilv_flock(wfd, false, true);
- serd_writer_free(writer);
- fclose(wfd);
-
sord_free(model);
serd_node_free(&file);
serd_node_free(&manifest);
@@ -1009,31 +1043,44 @@ static bool
link_exists(const char* path, const void* data)
{
const char* target = (const char*)data;
- if (!lilv_path_exists(path)) {
+ if (zix_file_type(path) == ZIX_FILE_TYPE_NONE) {
return false;
}
- char* real_path = lilv_path_canonical(path);
- bool matches = !strcmp(real_path, target);
- free(real_path);
+
+ char* const real_path = zix_canonical_path(NULL, path);
+ const bool matches = real_path && !strcmp(real_path, target);
+ zix_free(NULL, real_path);
return !matches;
}
-static int
-maybe_symlink(const char* oldpath, const char* newpath)
+static ZixStatus
+create_link(const char* oldpath, const char* newpath)
{
- if (link_exists(newpath, oldpath)) {
- return 0;
- }
+ const ZixStringView parent_path = zix_path_parent_path(newpath);
+ char* const parent = zix_string_view_copy(NULL, parent_path);
- const int st = lilv_symlink(oldpath, newpath);
- if (st) {
- LILV_ERRORF(
- "Failed to link %s => %s (%s)\n", newpath, oldpath, strerror(errno));
+ char* const relpath = zix_path_lexically_relative(NULL, oldpath, parent);
+
+ ZixStatus st = ZIX_STATUS_SUCCESS;
+ if ((st = zix_create_symlink(relpath, newpath))) {
+ if ((st = zix_create_hard_link(oldpath, newpath))) {
+ LILV_ERRORF(
+ "Failed to link %s => %s (%s)\n", newpath, oldpath, zix_strerror(st));
+ }
}
+ zix_free(NULL, relpath);
+ zix_free(NULL, parent);
return st;
}
+static ZixStatus
+maybe_symlink(const char* oldpath, const char* newpath)
+{
+ return link_exists(newpath, oldpath) ? ZIX_STATUS_SUCCESS
+ : create_link(oldpath, newpath);
+}
+
static void
write_property_array(const LilvState* state,
const PropertyArray* array,
@@ -1104,7 +1151,7 @@ lilv_state_write(LilvWorld* world,
serd_writer_write_statement(writer, 0, NULL, &subject, &p, &o, NULL, NULL);
}
- SerdEnv* env = serd_writer_get_env(writer);
+ const SerdEnv* env = serd_writer_get_env(writer);
const SerdNode* base = serd_env_get_base_uri(env, NULL);
Sratom* sratom = sratom_new(map);
@@ -1122,7 +1169,7 @@ lilv_state_write(LilvWorld* world,
// Write port values
sratom_set_pretty_numbers(sratom, true); // Use pretty numbers
for (uint32_t i = 0; i < state->n_values; ++i) {
- PortValue* const value = &state->values[i];
+ const PortValue* const value = &state->values[i];
const SerdNode port =
serd_node_from_string(SERD_BLANK, USTR(value->symbol));
@@ -1178,34 +1225,36 @@ lilv_state_make_links(const LilvState* state, const char* dir)
for (ZixTreeIter* i = zix_tree_begin(state->abs2rel);
i != zix_tree_end(state->abs2rel);
i = zix_tree_iter_next(i)) {
- const PathMap* pm = (const PathMap*)zix_tree_get(i);
+ const PathMap* const pm = (const PathMap*)zix_tree_get(i);
+ char* const path = zix_path_join(NULL, dir, pm->rel);
- char* path = lilv_path_absolute_child(pm->rel, dir);
- if (lilv_path_is_child(pm->abs, state->copy_dir) &&
- strcmp(state->copy_dir, dir)) {
+ if (state->copy_dir && path_is_child(pm->abs, state->copy_dir) &&
+ !!strcmp(state->copy_dir, dir)) {
// Link directly to snapshot in the copy directory
maybe_symlink(pm->abs, path);
- } else if (!lilv_path_is_child(pm->abs, dir)) {
+ } else if (!path_is_child(pm->abs, dir)) {
const char* link_dir = state->link_dir ? state->link_dir : dir;
- char* pat = lilv_path_absolute_child(pm->rel, link_dir);
+ char* pat = zix_path_join(NULL, link_dir, pm->rel);
+
if (!strcmp(dir, link_dir)) {
// Link directory is save directory, make link at exact path
- remove(pat);
+ (void)zix_remove(pat);
maybe_symlink(pm->abs, pat);
} else {
// Make a link in the link directory to external file
char* lpath = lilv_find_free_path(pat, link_exists, pm->abs);
- if (!lilv_path_exists(lpath)) {
- if (lilv_symlink(pm->abs, lpath)) {
+ if (zix_file_type(lpath) == ZIX_FILE_TYPE_NONE) {
+ const ZixStatus st = create_link(pm->abs, lpath);
+ if (st) {
LILV_ERRORF("Failed to link %s => %s (%s)\n",
pm->abs,
lpath,
- strerror(errno));
+ zix_strerror(st));
}
}
// Make a link in the save directory to the external link
- char* target = lilv_path_relative_to(lpath, dir);
+ char* target = zix_path_lexically_relative(NULL, lpath, dir);
maybe_symlink(lpath, path);
free(target);
free(lpath);
@@ -1225,17 +1274,21 @@ lilv_state_save(LilvWorld* world,
const char* dir,
const char* filename)
{
- if (!filename || !dir || lilv_create_directories(dir)) {
+ if (!filename || !dir || zix_create_directories(NULL, dir)) {
return 1;
}
- char* abs_dir = real_dir(dir);
- char* const path = lilv_path_join(abs_dir, filename);
- FILE* fd = fopen(path, "w");
+ char* const abs_dir = zix_canonical_path(NULL, dir);
+ if (!abs_dir) {
+ return 2;
+ }
+
+ char* const path = zix_path_join(NULL, abs_dir, filename);
+ FILE* fd = path ? fopen(path, "w") : NULL;
if (!fd) {
LILV_ERRORF("Failed to open %s (%s)\n", path, strerror(errno));
- free(abs_dir);
- free(path);
+ zix_free(NULL, abs_dir);
+ zix_free(NULL, path);
return 4;
}
@@ -1251,9 +1304,9 @@ lilv_state_save(LilvWorld* world,
lilv_state_write(world, map, unmap, state, ttl, (const char*)node.buf, dir);
// Set saved dir and uri (FIXME: const violation)
- free(state->dir);
+ zix_free(NULL, state->dir);
lilv_node_free(state->uri);
- ((LilvState*)state)->dir = lilv_strdup(abs_dir);
+ ((LilvState*)state)->dir = zix_path_join(NULL, abs_dir, "");
((LilvState*)state)->uri = lilv_new_uri(world, (const char*)node.buf);
serd_node_free(&file);
@@ -1263,15 +1316,15 @@ lilv_state_save(LilvWorld* world,
// Add entry to manifest
if (!ret) {
- char* const manifest = lilv_path_join(abs_dir, "manifest.ttl");
+ char* const manifest = zix_path_join(NULL, abs_dir, "manifest.ttl");
ret = add_state_to_manifest(world, state->plugin_uri, manifest, uri, path);
- free(manifest);
+ zix_free(NULL, manifest);
}
- free(abs_dir);
- free(path);
+ zix_free(NULL, abs_dir);
+ zix_free(NULL, path);
return ret;
}
@@ -1307,7 +1360,7 @@ static void
try_unlink(const char* state_dir, const char* path)
{
if (!strncmp(state_dir, path, strlen(state_dir))) {
- if (lilv_path_exists(path) && lilv_remove(path)) {
+ if (zix_file_type(path) != ZIX_FILE_TYPE_NONE && zix_remove(path)) {
LILV_ERRORF("Failed to remove %s (%s)\n", path, strerror(errno));
}
}
@@ -1317,7 +1370,7 @@ static char*
get_canonical_path(const LilvNode* const node)
{
char* const path = lilv_node_get_path(node, NULL);
- char* const real_path = lilv_path_canonical(path);
+ char* const real_path = zix_canonical_path(NULL, path);
free(path);
return real_path;
@@ -1334,8 +1387,10 @@ lilv_state_delete(LilvWorld* world, const LilvState* state)
LilvNode* bundle = lilv_new_file_uri(world, NULL, state->dir);
LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle);
char* manifest_path = get_canonical_path(manifest);
- const bool has_manifest = lilv_path_exists(manifest_path);
- SordModel* model = sord_new(world->world, SORD_SPO, false);
+ const bool has_manifest =
+ manifest_path && zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR;
+
+ SordModel* model = sord_new(world->world, SORD_SPO, false);
if (has_manifest) {
// Read manifest into temporary local model
@@ -1347,17 +1402,17 @@ lilv_state_delete(LilvWorld* world, const LilvState* state)
}
if (state->uri) {
- SordNode* file =
+ const SordNode* file =
sord_get(model, state->uri->node, world->uris.rdfs_seeAlso, NULL, NULL);
if (file) {
// Remove state file
const uint8_t* uri = sord_node_get_string(file);
char* path = (char*)serd_file_uri_parse(uri, NULL);
- char* real_path = lilv_path_canonical(path);
- if (path) {
+ char* real_path = zix_canonical_path(NULL, path);
+ if (real_path) {
try_unlink(state->dir, real_path);
}
- serd_free(real_path);
+ zix_free(NULL, real_path);
serd_free(path);
}
@@ -1383,9 +1438,9 @@ lilv_state_delete(LilvWorld* world, const LilvState* state)
i != zix_tree_end(state->abs2rel);
i = zix_tree_iter_next(i)) {
const PathMap* pm = (const PathMap*)zix_tree_get(i);
- char* path = lilv_path_join(state->dir, pm->rel);
+ char* path = zix_path_join(NULL, state->dir, pm->rel);
try_unlink(state->dir, path);
- free(path);
+ zix_free(NULL, path);
}
} else {
// State loaded from model, get paths from loaded properties
@@ -1397,7 +1452,7 @@ lilv_state_delete(LilvWorld* world, const LilvState* state)
}
}
- if (lilv_remove(state->dir)) {
+ if (zix_remove(state->dir)) {
LILV_ERRORF(
"Failed to remove directory %s (%s)\n", state->dir, strerror(errno));
}
@@ -1412,7 +1467,7 @@ lilv_state_delete(LilvWorld* world, const LilvState* state)
}
sord_free(model);
- lilv_free(manifest_path);
+ zix_free(NULL, manifest_path);
lilv_node_free(manifest);
lilv_node_free(bundle);
@@ -1420,7 +1475,7 @@ lilv_state_delete(LilvWorld* world, const LilvState* state)
}
static void
-free_property_array(LilvState* state, PropertyArray* array)
+free_property_array(const LilvState* state, PropertyArray* array)
{
for (uint32_t i = 0; i < array->n; ++i) {
Property* prop = &array->props[i];
@@ -1460,34 +1515,36 @@ lilv_state_equals(const LilvState* a, const LilvState* b)
{
if (!lilv_node_equals(a->plugin_uri, b->plugin_uri) ||
(a->label && !b->label) || (b->label && !a->label) ||
- (a->label && b->label && strcmp(a->label, b->label)) ||
+ (a->label && b->label && !!strcmp(a->label, b->label)) ||
a->props.n != b->props.n || a->n_values != b->n_values) {
return false;
}
for (uint32_t i = 0; i < a->n_values; ++i) {
- PortValue* const av = &a->values[i];
- PortValue* const bv = &b->values[i];
+ const PortValue* const av = &a->values[i];
+ const PortValue* const bv = &b->values[i];
if (av->atom->size != bv->atom->size || av->atom->type != bv->atom->type ||
- strcmp(av->symbol, bv->symbol) ||
- memcmp(av->atom + 1, bv->atom + 1, av->atom->size)) {
+ !!strcmp(av->symbol, bv->symbol) ||
+ !!memcmp(av->atom + 1, bv->atom + 1, av->atom->size)) {
return false;
}
}
for (uint32_t i = 0; i < a->props.n; ++i) {
- Property* const ap = &a->props.props[i];
- Property* const bp = &b->props.props[i];
+ const Property* const ap = &a->props.props[i];
+ const Property* const bp = &b->props.props[i];
if (ap->key != bp->key || ap->type != bp->type || ap->flags != bp->flags) {
return false;
}
if (ap->type == a->atom_Path) {
- if (!lilv_file_equals(lilv_state_rel2abs(a, (char*)ap->value),
- lilv_state_rel2abs(b, (char*)bp->value))) {
+ if (!zix_file_equals(NULL,
+ lilv_state_rel2abs(a, (char*)ap->value),
+ lilv_state_rel2abs(b, (char*)bp->value))) {
return false;
}
- } else if (ap->size != bp->size || memcmp(ap->value, bp->value, ap->size)) {
+ } else if (ap->size != bp->size ||
+ !!memcmp(ap->value, bp->value, ap->size)) {
return false;
}
}
diff --git a/src/ui.c b/src/ui.c
index 84f8cef..9e97091 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -1,23 +1,10 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "zix/tree.h"
+#include <lilv/lilv.h>
+#include <zix/tree.h>
#include <assert.h>
#include <stdbool.h>
diff --git a/src/util.c b/src/util.c
index 92f72b9..d159c78 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,37 +1,25 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "filesystem.h"
#include "lilv_internal.h"
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
+#include <serd/serd.h>
+#include <zix/allocator.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
+#include <zix/string_view.h>
#include <sys/stat.h>
-#include <sys/types.h>
-#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
-#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
void
lilv_free(void* ptr)
@@ -47,7 +35,7 @@ lilv_strjoin(const char* first, ...)
memcpy(result, first, len);
- va_list args;
+ va_list args; // NOLINT(cppcoreguidelines-init-variables)
va_start(args, first);
while (1) {
const char* const s = va_arg(args, const char*);
@@ -127,10 +115,9 @@ lilv_get_lang(void)
lang[i] = '-'; // Convert _ to -
} else if (env_lang[i] >= 'A' && env_lang[i] <= 'Z') {
lang[i] = env_lang[i] + ('a' - 'A'); // Convert to lowercase
- } else if (env_lang[i] >= 'a' && env_lang[i] <= 'z') {
- lang[i] = env_lang[i]; // Lowercase letter, copy verbatim
- } else if (env_lang[i] >= '0' && env_lang[i] <= '9') {
- lang[i] = env_lang[i]; // Digit, copy verbatim
+ } else if ((env_lang[i] >= 'a' && env_lang[i] <= 'z') ||
+ (env_lang[i] >= '0' && env_lang[i] <= '9')) {
+ lang[i] = env_lang[i]; // Lowercase letter or digit, copy verbatim
} else if (env_lang[i] == '\0' || env_lang[i] == '.') {
// End, or start of suffix (e.g. en_CA.utf-8), finished
lang[i] = '\0';
@@ -145,83 +132,6 @@ lilv_get_lang(void)
return lang;
}
-#ifndef _WIN32
-
-/** Append suffix to dst, update dst_len, and return the realloc'd result. */
-static char*
-strappend(char* dst, size_t* dst_len, const char* suffix, size_t suffix_len)
-{
- dst = (char*)realloc(dst, *dst_len + suffix_len + 1);
- memcpy(dst + *dst_len, suffix, suffix_len);
- dst[(*dst_len += suffix_len)] = '\0';
- return dst;
-}
-
-/** Append the value of the environment variable var to dst. */
-static char*
-append_var(char* dst, size_t* dst_len, const char* var)
-{
- // Get value from environment
- const char* val = getenv(var);
- if (val) { // Value found, append it
- return strappend(dst, dst_len, val, strlen(val));
- }
-
- // No value found, append variable reference as-is
- return strappend(strappend(dst, dst_len, "$", 1), dst_len, var, strlen(var));
-}
-
-#endif
-
-/** Expand variables (e.g. POSIX ~ or $FOO, Windows %FOO%) in `path`. */
-char*
-lilv_expand(const char* path)
-{
-#ifdef _WIN32
- char* out = (char*)malloc(MAX_PATH);
- ExpandEnvironmentStrings(path, out, MAX_PATH);
-#else
- char* out = NULL;
- size_t len = 0;
-
- const char* start = path; // Start of current chunk to copy
- for (const char* s = path; *s;) {
- if (*s == '$') {
- // Hit $ (variable reference, e.g. $VAR_NAME)
- for (const char* t = s + 1;; ++t) {
- if (!*t || (!isupper(*t) && !isdigit(*t) && *t != '_')) {
- // Append preceding chunk
- out = strappend(out, &len, start, s - start);
-
- // Append variable value (or $VAR_NAME if not found)
- char* var = (char*)calloc(t - s, 1);
- memcpy(var, s + 1, t - s - 1);
- out = append_var(out, &len, var);
- free(var);
-
- // Continue after variable reference
- start = s = t;
- break;
- }
- }
- } else if (*s == '~' && (*(s + 1) == '/' || !*(s + 1))) {
- // Hit ~ before slash or end of string (home directory reference)
- out = strappend(out, &len, start, s - start);
- out = append_var(out, &len, "HOME");
- start = ++s;
- } else {
- ++s;
- }
- }
-
- if (*start) {
- out = strappend(out, &len, start, strlen(start));
- }
-#endif
-
- return out;
-}
-
char*
lilv_find_free_path(const char* in_path,
bool (*exists)(const char*, const void*),
@@ -231,7 +141,7 @@ lilv_find_free_path(const char* in_path,
char* path = (char*)malloc(in_path_len + 7);
memcpy(path, in_path, in_path_len + 1);
- for (unsigned i = 2; i < 1000000u; ++i) {
+ for (unsigned i = 2U; i < 1000000U; ++i) {
if (!exists(path, user_data)) {
return path;
}
@@ -251,13 +161,13 @@ static void
update_latest(const char* path, const char* name, void* data)
{
Latest* latest = (Latest*)data;
- char* entry_path = lilv_path_join(path, name);
+ char* entry_path = zix_path_join(NULL, path, name);
unsigned num = 0;
if (sscanf(entry_path, latest->pattern, &num) == 1) {
struct stat st;
if (!stat(entry_path, &st)) {
if (st.st_mtime >= latest->time) {
- free(latest->latest);
+ zix_free(NULL, latest->latest);
latest->latest = entry_path;
}
} else {
@@ -265,7 +175,7 @@ update_latest(const char* path, const char* name, void* data)
}
}
if (entry_path != latest->latest) {
- free(entry_path);
+ zix_free(NULL, entry_path);
}
}
@@ -273,8 +183,9 @@ update_latest(const char* path, const char* name, void* data)
char*
lilv_get_latest_copy(const char* path, const char* copy_path)
{
- char* copy_dir = lilv_path_parent(copy_path);
- Latest latest = {lilv_strjoin(copy_path, ".%u", NULL), 0, NULL};
+ char* copy_dir = zix_string_view_copy(NULL, zix_path_parent_path(copy_path));
+
+ Latest latest = {lilv_strjoin(copy_path, ".%u", NULL), 0, NULL};
struct stat st;
if (!stat(path, &st)) {
@@ -283,9 +194,9 @@ lilv_get_latest_copy(const char* path, const char* copy_path)
LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno));
}
- lilv_dir_for_each(copy_dir, &latest, update_latest);
+ zix_dir_for_each(copy_dir, &latest, update_latest);
free(latest.pattern);
- free(copy_dir);
+ zix_free(NULL, copy_dir);
return latest.latest;
}
diff --git a/src/world.c b/src/world.c
index 47dc147..73f19a9 100644
--- a/src/world.c
+++ b/src/world.c
@@ -1,38 +1,25 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "filesystem.h"
-#include "lilv_config.h" // IWYU pragma: keep
-#include "lilv_internal.h"
-
-#include "lilv/lilv.h"
-#include "serd/serd.h"
-#include "sord/sord.h"
-#include "zix/common.h"
-#include "zix/tree.h"
+// Copyright 2007-2024 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "lv2/core/lv2.h"
-#include "lv2/presets/presets.h"
+#include "lilv_config.h"
+#include "lilv_internal.h"
#ifdef LILV_DYN_MANIFEST
-# include "lv2/dynmanifest/dynmanifest.h"
-# include <dlfcn.h>
+# include "dylib.h"
+# include <lv2/dynmanifest/dynmanifest.h>
#endif
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
+#include <lv2/presets/presets.h>
+#include <serd/serd.h>
+#include <sord/sord.h>
+#include <zix/environment.h>
+#include <zix/filesystem.h>
+#include <zix/tree.h>
+
#include <assert.h>
+#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -42,6 +29,16 @@
static int
lilv_world_drop_graph(LilvWorld* world, const SordNode* graph);
+static int
+lilv_lib_compare(const void* a, const void* b, const void* user_data);
+
+static void
+destroy_node(void* const ptr, const void* const user_data)
+{
+ (void)user_data;
+ lilv_node_free((LilvNode*)ptr);
+}
+
LilvWorld*
lilv_world_new(void)
{
@@ -61,10 +58,11 @@ lilv_world_new(void)
world->plugin_classes = lilv_plugin_classes_new();
world->plugins = lilv_plugins_new();
world->zombies = lilv_plugins_new();
- world->loaded_files = zix_tree_new(
- false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free);
- world->libs = zix_tree_new(false, lilv_lib_compare, NULL, NULL);
+ world->loaded_files =
+ zix_tree_new(NULL, false, lilv_resource_node_cmp, NULL, destroy_node, NULL);
+
+ world->libs = zix_tree_new(NULL, false, lilv_lib_compare, NULL, NULL, NULL);
#define NS_DCTERMS "http://purl.org/dc/terms/"
#define NS_DYNMAN "http://lv2plug.in/ns/ext/dynmanifest#"
@@ -268,7 +266,7 @@ lilv_world_get(LilvWorld* world,
SordNode* snode = sord_get(world->model,
subject ? subject->node : NULL,
predicate ? predicate->node : NULL,
- object ? object->node : NULL,
+ object->node,
NULL);
LilvNode* lnode = lilv_node_new_from_node(world, snode);
sord_node_free(world->world, snode);
@@ -337,15 +335,6 @@ lilv_world_find_nodes_internal(LilvWorld* world,
(object == NULL) ? SORD_OBJECT : SORD_SUBJECT);
}
-static SerdNode
-lilv_new_uri_relative_to_base(const uint8_t* uri_str,
- const uint8_t* base_uri_str)
-{
- SerdURI base_uri;
- serd_uri_parse(base_uri_str, &base_uri);
- return serd_node_new_uri_from_string(uri_str, &base_uri, NULL);
-}
-
const uint8_t*
lilv_world_blank_node_prefix(LilvWorld* world)
{
@@ -374,7 +363,7 @@ lilv_header_compare_by_uri(const void* a, const void* b, const void* user_data)
handle the case where the same library is loaded with different bundles, and
consequently different contents (mainly plugins).
*/
-int
+static int
lilv_lib_compare(const void* a, const void* b, const void* user_data)
{
(void)user_data;
@@ -395,7 +384,7 @@ lilv_collection_find_by_uri(const ZixTree* seq, const LilvNode* uri)
ZixTreeIter* i = NULL;
if (lilv_node_is_uri(uri)) {
struct LilvHeader key = {NULL, (LilvNode*)uri};
- zix_tree_find(seq, &key, &i);
+ (void)zix_tree_find(seq, &key, &i);
}
return i;
}
@@ -404,7 +393,7 @@ lilv_collection_find_by_uri(const ZixTree* seq, const LilvNode* uri)
struct LilvHeader*
lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri)
{
- ZixTreeIter* const i = lilv_collection_find_by_uri(seq, uri);
+ const ZixTreeIter* const i = lilv_collection_find_by_uri(seq, uri);
return i ? (struct LilvHeader*)zix_tree_get(i) : NULL;
}
@@ -506,7 +495,7 @@ lilv_world_add_plugin(LilvWorld* world,
sord_iter_free(files);
}
-SerdStatus
+static SerdStatus
lilv_world_load_graph(LilvWorld* world, SordNode* graph, const LilvNode* uri)
{
const SerdNode* base = sord_node_to_serd_node(uri->node);
@@ -564,8 +553,8 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
}
// Open library
- dlerror();
- void* lib = dlopen(lib_path, RTLD_LAZY);
+ dylib_error();
+ void* lib = dylib_open(lib_path, DYLIB_LAZY);
if (!lib) {
LILV_ERRORF(
"Failed to open dynmanifest library `%s' (%s)\n", lib_path, dlerror());
@@ -577,11 +566,11 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
// Open dynamic manifest
typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*,
const LV2_Feature* const*);
- OpenFunc dmopen = (OpenFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_open");
+ OpenFunc dmopen = (OpenFunc)dylib_func(lib, "lv2_dyn_manifest_open");
if (!dmopen || dmopen(&handle, &dman_features)) {
LILV_ERRORF("No `lv2_dyn_manifest_open' in `%s'\n", lib_path);
sord_iter_free(binaries);
- dlclose(lib);
+ dylib_close(lib);
lilv_free(lib_path);
continue;
}
@@ -589,11 +578,11 @@ lilv_world_load_dyn_manifest(LilvWorld* world,
// Get subjects (the data that would be in manifest.ttl)
typedef int (*GetSubjectsFunc)(LV2_Dyn_Manifest_Handle, FILE*);
GetSubjectsFunc get_subjects_func =
- (GetSubjectsFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_get_subjects");
+ (GetSubjectsFunc)dylib_func(lib, "lv2_dyn_manifest_get_subjects");
if (!get_subjects_func) {
LILV_ERRORF("No `lv2_dyn_manifest_get_subjects' in `%s'\n", lib_path);
sord_iter_free(binaries);
- dlclose(lib);
+ dylib_close(lib);
lilv_free(lib_path);
continue;
}
@@ -660,12 +649,12 @@ lilv_dynmanifest_free(LilvDynManifest* dynmanifest)
{
typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle);
CloseFunc close_func =
- (CloseFunc)lilv_dlfunc(dynmanifest->lib, "lv2_dyn_manifest_close");
+ (CloseFunc)dylib_func(dynmanifest->lib, "lv2_dyn_manifest_close");
if (close_func) {
close_func(dynmanifest->handle);
}
- dlclose(dynmanifest->lib);
+ dylib_close(dynmanifest->lib);
lilv_node_free(dynmanifest->bundle);
free(dynmanifest);
}
@@ -674,10 +663,24 @@ lilv_dynmanifest_free(LilvDynManifest* dynmanifest)
LilvNode*
lilv_world_get_manifest_uri(LilvWorld* world, const LilvNode* bundle_uri)
{
- SerdNode manifest_uri = lilv_new_uri_relative_to_base(
- (const uint8_t*)"manifest.ttl", sord_node_get_string(bundle_uri->node));
- LilvNode* manifest = lilv_new_uri(world, (const char*)manifest_uri.buf);
- serd_node_free(&manifest_uri);
+ // Get the string and length of the given bundle URI
+ size_t bundle_uri_length = 0U;
+ const char* const bundle_uri_string =
+ (const char*)sord_node_get_string_counted(bundle_uri->node,
+ &bundle_uri_length);
+ if (bundle_uri_length < 1U) {
+ return NULL;
+ }
+
+ // Build the manifest URI by inserting a separating "/" if necessary
+ const char last = bundle_uri_string[bundle_uri_length - 1U];
+ char* const manifest_uri_string =
+ (last == '/') ? lilv_strjoin(bundle_uri_string, "manifest.ttl", NULL)
+ : lilv_strjoin(bundle_uri_string, "/", "manifest.ttl", NULL);
+
+ // Make a node from the manifeset URI to return
+ LilvNode* const manifest = lilv_new_uri(world, manifest_uri_string);
+ free(manifest_uri_string);
return manifest;
}
@@ -687,10 +690,10 @@ load_plugin_model(LilvWorld* world,
const LilvNode* plugin_uri)
{
// Create model and reader for loading into it
- SordNode* bundle_node = bundle_uri->node;
- SordModel* model = sord_new(world->world, SORD_SPO | SORD_OPS, false);
- SerdEnv* env = serd_env_new(sord_node_to_serd_node(bundle_node));
- SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
+ const SordNode* bundle_node = bundle_uri->node;
+ SordModel* model = sord_new(world->world, SORD_SPO | SORD_OPS, false);
+ SerdEnv* env = serd_env_new(sord_node_to_serd_node(bundle_node));
+ SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
// Load manifest
LilvNode* manifest_uri = lilv_world_get_manifest_uri(world, bundle_uri);
@@ -722,7 +725,7 @@ load_plugin_model(LilvWorld* world,
}
static LilvVersion
-get_version(LilvWorld* world, SordModel* model, const LilvNode* subject)
+get_version(const LilvWorld* world, SordModel* model, const LilvNode* subject)
{
const SordNode* minor_node =
sord_get(model, subject->node, world->uris.lv2_minorVersion, NULL, NULL);
@@ -731,8 +734,14 @@ get_version(LilvWorld* world, SordModel* model, const LilvNode* subject)
LilvVersion version = {0, 0};
if (minor_node && micro_node) {
- version.minor = atoi((const char*)sord_node_get_string(minor_node));
- version.micro = atoi((const char*)sord_node_get_string(micro_node));
+ const char* const minor_str = (const char*)sord_node_get_string(minor_node);
+ const char* const micro_str = (const char*)sord_node_get_string(micro_node);
+ const long minor = strtol(minor_str, NULL, 10);
+ const long micro = strtol(micro_str, NULL, 10);
+ if (minor >= 0 && minor < INT_MAX && micro >= 0 && micro < INT_MAX) {
+ version.minor = (int)minor;
+ version.micro = (int)micro;
+ }
}
return version;
@@ -749,6 +758,9 @@ lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri)
SordNode* bundle_node = bundle_uri->node;
LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle_uri);
+ if (!manifest) {
+ return;
+ }
// Read manifest into model with graph = bundle_node
SerdStatus st = lilv_world_load_graph(world, bundle_node, manifest);
@@ -872,6 +884,7 @@ lilv_world_drop_graph(LilvWorld* world, const SordNode* graph)
while (!sord_iter_end(i)) {
const SerdStatus st = sord_erase(world->model, i);
if (st) {
+ sord_iter_free(i);
LILV_ERRORF("Error removing statement from <%s> (%s)\n",
sord_node_get_string(graph),
serd_strerror(st));
@@ -928,7 +941,7 @@ lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri)
still be used.
*/
ZixTreeIter* i = zix_tree_begin((ZixTree*)world->plugins);
- while (i != zix_tree_end((ZixTree*)world->plugins)) {
+ while (i && i != zix_tree_end((ZixTree*)world->plugins)) {
LilvPlugin* p = (LilvPlugin*)zix_tree_get(i);
ZixTreeIter* next = zix_tree_iter_next(i);
@@ -962,9 +975,9 @@ load_dir_entry(const char* dir, const char* name, void* data)
static void
lilv_world_load_directory(LilvWorld* world, const char* dir_path)
{
- char* path = lilv_expand(dir_path);
+ char* const path = zix_expand_environment_strings(NULL, dir_path);
if (path) {
- lilv_dir_for_each(path, world, load_dir_entry);
+ zix_dir_for_each(path, world, load_dir_entry);
free(path);
}
}
@@ -1010,7 +1023,8 @@ lilv_world_load_specifications(LilvWorld* world)
{
for (LilvSpec* spec = world->specs; spec; spec = spec->next) {
LILV_FOREACH (nodes, f, spec->data_uris) {
- LilvNode* file = (LilvNode*)lilv_collection_get(spec->data_uris, f);
+ const LilvNode* file =
+ (const LilvNode*)lilv_collection_get(spec->data_uris, f);
lilv_world_load_graph(world, NULL, file);
}
}
@@ -1100,11 +1114,11 @@ lilv_world_load_file(LilvWorld* world, SerdReader* reader, const LilvNode* uri)
size_t uri_len = 0;
const uint8_t* const uri_str =
sord_node_get_string_counted(uri->node, &uri_len);
- if (strncmp((const char*)uri_str, "file:", 5)) {
+ if (!!strncmp((const char*)uri_str, "file:", 5)) {
return SERD_FAILURE; // Not a local file
}
- if (strcmp((const char*)uri_str + uri_len - 4, ".ttl")) {
+ if (!!strcmp((const char*)uri_str + uri_len - 4, ".ttl")) {
return SERD_FAILURE; // Not a Turtle file
}
diff --git a/src/zix/common.h b/src/zix/common.h
deleted file mode 100644
index d47586c..0000000
--- a/src/zix/common.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- Copyright 2016-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef ZIX_COMMON_H
-#define ZIX_COMMON_H
-
-#include <stdbool.h>
-
-/**
- @addtogroup zix
- @{
-*/
-
-/** @cond */
-#if defined(_WIN32) && !defined(ZIX_STATIC) && defined(ZIX_INTERNAL)
-# define ZIX_API __declspec(dllexport)
-#elif defined(_WIN32) && !defined(ZIX_STATIC)
-# define ZIX_API __declspec(dllimport)
-#elif defined(__GNUC__)
-# define ZIX_API __attribute__((visibility("default")))
-#else
-# define ZIX_API
-#endif
-
-#ifdef __GNUC__
-# define ZIX_PURE_FUNC __attribute__((pure))
-# define ZIX_CONST_FUNC __attribute__((const))
-# define ZIX_MALLOC_FUNC __attribute__((malloc))
-#else
-# define ZIX_PURE_FUNC
-# define ZIX_CONST_FUNC
-# define ZIX_MALLOC_FUNC
-#endif
-
-#define ZIX_PURE_API \
- ZIX_API \
- ZIX_PURE_FUNC
-
-#define ZIX_CONST_API \
- ZIX_API \
- ZIX_CONST_FUNC
-
-#define ZIX_MALLOC_API \
- ZIX_API \
- ZIX_MALLOC_FUNC
-
-/** @endcond */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __GNUC__
-# define ZIX_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
-#else
-# define ZIX_LOG_FUNC(fmt, arg1)
-#endif
-
-// Unused parameter macro to suppresses warnings and make it impossible to use
-#if defined(__cplusplus)
-# define ZIX_UNUSED(name)
-#elif defined(__GNUC__)
-# define ZIX_UNUSED(name) name##_unused __attribute__((__unused__))
-#else
-# define ZIX_UNUSED(name) name
-#endif
-
-typedef enum {
- ZIX_STATUS_SUCCESS,
- ZIX_STATUS_ERROR,
- ZIX_STATUS_NO_MEM,
- ZIX_STATUS_NOT_FOUND,
- ZIX_STATUS_EXISTS,
- ZIX_STATUS_BAD_ARG,
- ZIX_STATUS_BAD_PERMS
-} ZixStatus;
-
-static inline const char*
-zix_strerror(const ZixStatus status)
-{
- switch (status) {
- case ZIX_STATUS_SUCCESS:
- return "Success";
- case ZIX_STATUS_ERROR:
- return "Unknown error";
- case ZIX_STATUS_NO_MEM:
- return "Out of memory";
- case ZIX_STATUS_NOT_FOUND:
- return "Not found";
- case ZIX_STATUS_EXISTS:
- return "Exists";
- case ZIX_STATUS_BAD_ARG:
- return "Bad argument";
- case ZIX_STATUS_BAD_PERMS:
- return "Bad permissions";
- }
- return "Unknown error";
-}
-
-/**
- Function for comparing two elements.
-*/
-typedef int (*ZixComparator)(const void* a,
- const void* b,
- const void* user_data);
-
-/**
- Function for testing equality of two elements.
-*/
-typedef bool (*ZixEqualFunc)(const void* a, const void* b);
-
-/**
- Function to destroy an element.
-*/
-typedef void (*ZixDestroyFunc)(void* ptr);
-
-/**
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ZIX_COMMON_H */
diff --git a/src/zix/tree.c b/src/zix/tree.c
deleted file mode 100644
index 9faf13c..0000000
--- a/src/zix/tree.c
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- Copyright 2011-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "zix/tree.h"
-
-#include "zix/common.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-typedef struct ZixTreeNodeImpl ZixTreeNode;
-
-struct ZixTreeImpl {
- ZixTreeNode* root;
- ZixDestroyFunc destroy;
- ZixComparator cmp;
- void* cmp_data;
- size_t size;
- bool allow_duplicates;
-};
-
-struct ZixTreeNodeImpl {
- void* data;
- struct ZixTreeNodeImpl* left;
- struct ZixTreeNodeImpl* right;
- struct ZixTreeNodeImpl* parent;
- int balance;
-};
-
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-
-// Uncomment these for debugging features
-// #define ZIX_TREE_DUMP 1
-// #define ZIX_TREE_VERIFY 1
-// #define ZIX_TREE_HYPER_VERIFY 1
-
-#if defined(ZIX_TREE_VERIFY) || defined(ZIX_TREE_HYPER_VERIFY)
-# include "tree_debug.h"
-# define ASSERT_BALANCE(n) assert(verify_balance(n))
-#else
-# define ASSERT_BALANCE(n)
-#endif
-
-#ifdef ZIX_TREE_DUMP
-# include "tree_debug.h"
-# define DUMP(t) zix_tree_print(t->root, 0)
-# define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
-#else
-# define DUMP(t)
-# define DEBUG_PRINTF(fmt, ...)
-#endif
-
-ZixTree*
-zix_tree_new(bool allow_duplicates,
- ZixComparator cmp,
- void* cmp_data,
- ZixDestroyFunc destroy)
-{
- ZixTree* t = (ZixTree*)malloc(sizeof(ZixTree));
- t->root = NULL;
- t->destroy = destroy;
- t->cmp = cmp;
- t->cmp_data = cmp_data;
- t->size = 0;
- t->allow_duplicates = allow_duplicates;
- return t;
-}
-
-static void
-zix_tree_free_rec(ZixTree* t, ZixTreeNode* n)
-{
- if (n) {
- zix_tree_free_rec(t, n->left);
- zix_tree_free_rec(t, n->right);
- if (t->destroy) {
- t->destroy(n->data);
- }
- free(n);
- }
-}
-
-void
-zix_tree_free(ZixTree* t)
-{
- if (t) {
- zix_tree_free_rec(t, t->root);
- free(t);
- }
-}
-
-size_t
-zix_tree_size(const ZixTree* t)
-{
- return t->size;
-}
-
-static void
-rotate(ZixTreeNode* p, ZixTreeNode* q)
-{
- assert(q->parent == p);
- assert(p->left == q || p->right == q);
-
- q->parent = p->parent;
- if (q->parent) {
- if (q->parent->left == p) {
- q->parent->left = q;
- } else {
- q->parent->right = q;
- }
- }
-
- if (p->right == q) {
- // Rotate left
- p->right = q->left;
- q->left = p;
- if (p->right) {
- p->right->parent = p;
- }
- } else {
- // Rotate right
- assert(p->left == q);
- p->left = q->right;
- q->right = p;
- if (p->left) {
- p->left->parent = p;
- }
- }
-
- p->parent = q;
-}
-
-/**
- * Rotate left about `p`.
- *
- * p q
- * / \ / \
- * A q => p C
- * / \ / \
- * B C A B
- */
-static ZixTreeNode*
-rotate_left(ZixTreeNode* p, int* height_change)
-{
- ZixTreeNode* const q = p->right;
- *height_change = (q->balance == 0) ? 0 : -1;
-
- DEBUG_PRINTF("LL %ld\n", (intptr_t)p->data);
-
- assert(p->balance == 2);
- assert(q->balance == 0 || q->balance == 1);
-
- rotate(p, q);
-
- // p->balance -= 1 + MAX(0, q->balance);
- // q->balance -= 1 - MIN(0, p->balance);
- --q->balance;
- p->balance = -(q->balance);
-
- ASSERT_BALANCE(p);
- ASSERT_BALANCE(q);
- return q;
-}
-
-/**
- * Rotate right about `p`.
- *
- * p q
- * / \ / \
- * q C => A p
- * / \ / \
- * A B B C
- *
- */
-static ZixTreeNode*
-rotate_right(ZixTreeNode* p, int* height_change)
-{
- ZixTreeNode* const q = p->left;
- *height_change = (q->balance == 0) ? 0 : -1;
-
- DEBUG_PRINTF("RR %ld\n", (intptr_t)p->data);
-
- assert(p->balance == -2);
- assert(q->balance == 0 || q->balance == -1);
-
- rotate(p, q);
-
- // p->balance += 1 - MIN(0, q->balance);
- // q->balance += 1 + MAX(0, p->balance);
- ++q->balance;
- p->balance = -(q->balance);
-
- ASSERT_BALANCE(p);
- ASSERT_BALANCE(q);
- return q;
-}
-
-/**
- * Rotate left about `p->left` then right about `p`.
- *
- * p r
- * / \ / \
- * q D => q p
- * / \ / \ / \
- * A r A B C D
- * / \
- * B C
- *
- */
-static ZixTreeNode*
-rotate_left_right(ZixTreeNode* p, int* height_change)
-{
- ZixTreeNode* const q = p->left;
- ZixTreeNode* const r = q->right;
-
- assert(p->balance == -2);
- assert(q->balance == 1);
- assert(r->balance == -1 || r->balance == 0 || r->balance == 1);
-
- DEBUG_PRINTF("LR %ld P: %2d Q: %2d R: %2d\n",
- (intptr_t)p->data,
- p->balance,
- q->balance,
- r->balance);
-
- rotate(q, r);
- rotate(p, r);
-
- q->balance -= 1 + MAX(0, r->balance);
- p->balance += 1 - MIN(MIN(0, r->balance) - 1, r->balance + q->balance);
- // r->balance += MAX(0, p->balance) + MIN(0, q->balance);
-
- // p->balance = (p->left && p->right) ? -MIN(r->balance, 0) : 0;
- // q->balance = - MAX(r->balance, 0);
- r->balance = 0;
-
- *height_change = -1;
-
- ASSERT_BALANCE(p);
- ASSERT_BALANCE(q);
- ASSERT_BALANCE(r);
- return r;
-}
-
-/**
- * Rotate right about `p->right` then right about `p`.
- *
- * p r
- * / \ / \
- * A q => p q
- * / \ / \ / \
- * r D A B C D
- * / \
- * B C
- *
- */
-static ZixTreeNode*
-rotate_right_left(ZixTreeNode* p, int* height_change)
-{
- ZixTreeNode* const q = p->right;
- ZixTreeNode* const r = q->left;
-
- assert(p->balance == 2);
- assert(q->balance == -1);
- assert(r->balance == -1 || r->balance == 0 || r->balance == 1);
-
- DEBUG_PRINTF("RL %ld P: %2d Q: %2d R: %2d\n",
- (intptr_t)p->data,
- p->balance,
- q->balance,
- r->balance);
-
- rotate(q, r);
- rotate(p, r);
-
- q->balance += 1 - MIN(0, r->balance);
- p->balance -= 1 + MAX(MAX(0, r->balance) + 1, r->balance + q->balance);
- // r->balance += MAX(0, q->balance) + MIN(0, p->balance);
-
- // p->balance = (p->left && p->right) ? -MAX(r->balance, 0) : 0;
- // q->balance = - MIN(r->balance, 0);
- r->balance = 0;
- // assert(r->balance == 0);
-
- *height_change = -1;
-
- ASSERT_BALANCE(p);
- ASSERT_BALANCE(q);
- ASSERT_BALANCE(r);
- return r;
-}
-
-static ZixTreeNode*
-zix_tree_rebalance(ZixTree* t, ZixTreeNode* node, int* height_change)
-{
-#ifdef ZIX_TREE_HYPER_VERIFY
- const size_t old_height = height(node);
-#endif
- DEBUG_PRINTF("REBALANCE %ld (%d)\n", (intptr_t)node->data, node->balance);
- *height_change = 0;
- const bool is_root = !node->parent;
- assert((is_root && t->root == node) || (!is_root && t->root != node));
- ZixTreeNode* replacement = node;
- if (node->balance == -2) {
- assert(node->left);
- if (node->left->balance == 1) {
- replacement = rotate_left_right(node, height_change);
- } else {
- replacement = rotate_right(node, height_change);
- }
- } else if (node->balance == 2) {
- assert(node->right);
- if (node->right->balance == -1) {
- replacement = rotate_right_left(node, height_change);
- } else {
- replacement = rotate_left(node, height_change);
- }
- }
- if (is_root) {
- assert(!replacement->parent);
- t->root = replacement;
- }
- DUMP(t);
-#ifdef ZIX_TREE_HYPER_VERIFY
- assert(old_height + *height_change == height(replacement));
-#endif
- return replacement;
-}
-
-ZixStatus
-zix_tree_insert(ZixTree* t, void* e, ZixTreeIter** ti)
-{
- DEBUG_PRINTF("**** INSERT %ld\n", (intptr_t)e);
- int cmp = 0;
- ZixTreeNode* n = t->root;
- ZixTreeNode* p = NULL;
-
- // Find the parent p of e
- while (n) {
- p = n;
- cmp = t->cmp(e, n->data, t->cmp_data);
- if (cmp < 0) {
- n = n->left;
- } else if (cmp > 0 || t->allow_duplicates) {
- n = n->right;
- } else {
- if (ti) {
- *ti = n;
- }
- DEBUG_PRINTF("%ld EXISTS!\n", (intptr_t)e);
- return ZIX_STATUS_EXISTS;
- }
- }
-
- // Allocate a new node n
- if (!(n = (ZixTreeNode*)malloc(sizeof(ZixTreeNode)))) {
- return ZIX_STATUS_NO_MEM;
- }
- memset(n, '\0', sizeof(ZixTreeNode));
- n->data = e;
- n->balance = 0;
- if (ti) {
- *ti = n;
- }
-
- bool p_height_increased = false;
-
- // Make p the parent of n
- n->parent = p;
- if (!p) {
- t->root = n;
- } else {
- if (cmp < 0) {
- assert(!p->left);
- assert(p->balance == 0 || p->balance == 1);
- p->left = n;
- --p->balance;
- p_height_increased = !p->right;
- } else {
- assert(!p->right);
- assert(p->balance == 0 || p->balance == -1);
- p->right = n;
- ++p->balance;
- p_height_increased = !p->left;
- }
- }
-
- DUMP(t);
-
- // Rebalance if necessary (at most 1 rotation)
- assert(!p || p->balance == -1 || p->balance == 0 || p->balance == 1);
- if (p && p_height_increased) {
- int height_change = 0;
- for (ZixTreeNode* i = p; i && i->parent; i = i->parent) {
- if (i == i->parent->left) {
- if (--i->parent->balance == -2) {
- zix_tree_rebalance(t, i->parent, &height_change);
- break;
- }
- } else {
- assert(i == i->parent->right);
- if (++i->parent->balance == 2) {
- zix_tree_rebalance(t, i->parent, &height_change);
- break;
- }
- }
-
- if (i->parent->balance == 0) {
- break;
- }
- }
- }
-
- DUMP(t);
-
- ++t->size;
-
-#ifdef ZIX_TREE_VERIFY
- if (!verify(t, t->root)) {
- return ZIX_STATUS_ERROR;
- }
-#endif
-
- return ZIX_STATUS_SUCCESS;
-}
-
-ZixStatus
-zix_tree_remove(ZixTree* t, ZixTreeIter* ti)
-{
- ZixTreeNode* const n = ti;
- ZixTreeNode** pp = NULL; // parent pointer
- ZixTreeNode* to_balance = n->parent; // lowest node to balance
- int d_balance = 0; // delta(balance) for n->parent
-
- DEBUG_PRINTF("*** REMOVE %ld\n", (intptr_t)n->data);
-
- if ((n == t->root) && !n->left && !n->right) {
- t->root = NULL;
- if (t->destroy) {
- t->destroy(n->data);
- }
- free(n);
- --t->size;
- assert(t->size == 0);
- return ZIX_STATUS_SUCCESS;
- }
-
- // Set pp to the parent pointer to n, if applicable
- if (n->parent) {
- assert(n->parent->left == n || n->parent->right == n);
- if (n->parent->left == n) { // n is left child
- pp = &n->parent->left;
- d_balance = 1;
- } else { // n is right child
- assert(n->parent->right == n);
- pp = &n->parent->right;
- d_balance = -1;
- }
- }
-
- assert(!pp || *pp == n);
-
- int height_change = 0;
- if (!n->left && !n->right) {
- // n is a leaf, just remove it
- if (pp) {
- *pp = NULL;
- to_balance = n->parent;
- height_change = (!n->parent->left && !n->parent->right) ? -1 : 0;
- }
-
- } else if (!n->left) {
- // Replace n with right (only) child
- if (pp) {
- *pp = n->right;
- to_balance = n->parent;
- } else {
- t->root = n->right;
- }
- n->right->parent = n->parent;
- height_change = -1;
-
- } else if (!n->right) {
- // Replace n with left (only) child
- if (pp) {
- *pp = n->left;
- to_balance = n->parent;
- } else {
- t->root = n->left;
- }
- n->left->parent = n->parent;
- height_change = -1;
-
- } else {
- // Replace n with in-order successor (leftmost child of right subtree)
- ZixTreeNode* replace = n->right;
- while (replace->left) {
- assert(replace->left->parent == replace);
- replace = replace->left;
- }
-
- // Remove replace from parent (replace_p)
- if (replace->parent->left == replace) {
- height_change = replace->parent->right ? 0 : -1;
- d_balance = 1;
- to_balance = replace->parent;
- replace->parent->left = replace->right;
- } else {
- assert(replace->parent == n);
- height_change = replace->parent->left ? 0 : -1;
- d_balance = -1;
- to_balance = replace->parent;
- replace->parent->right = replace->right;
- }
-
- if (to_balance == n) {
- to_balance = replace;
- }
-
- if (replace->right) {
- replace->right->parent = replace->parent;
- }
-
- replace->balance = n->balance;
-
- // Swap node to delete with replace
- if (pp) {
- *pp = replace;
- } else {
- assert(t->root == n);
- t->root = replace;
- }
-
- replace->parent = n->parent;
- replace->left = n->left;
- n->left->parent = replace;
- replace->right = n->right;
- if (n->right) {
- n->right->parent = replace;
- }
-
- assert(!replace->parent || replace->parent->left == replace ||
- replace->parent->right == replace);
- }
-
- // Rebalance starting at to_balance upwards.
- for (ZixTreeNode* i = to_balance; i; i = i->parent) {
- i->balance += d_balance;
- if (d_balance == 0 || i->balance == -1 || i->balance == 1) {
- break;
- }
-
- assert(i != n);
- i = zix_tree_rebalance(t, i, &height_change);
- if (i->balance == 0) {
- height_change = -1;
- }
-
- if (i->parent) {
- if (i == i->parent->left) {
- d_balance = height_change * -1;
- } else {
- assert(i == i->parent->right);
- d_balance = height_change;
- }
- }
- }
-
- DUMP(t);
-
- if (t->destroy) {
- t->destroy(n->data);
- }
- free(n);
-
- --t->size;
-
-#ifdef ZIX_TREE_VERIFY
- if (!verify(t, t->root)) {
- return ZIX_STATUS_ERROR;
- }
-#endif
-
- return ZIX_STATUS_SUCCESS;
-}
-
-ZixStatus
-zix_tree_find(const ZixTree* t, const void* e, ZixTreeIter** ti)
-{
- ZixTreeNode* n = t->root;
- while (n) {
- const int cmp = t->cmp(e, n->data, t->cmp_data);
- if (cmp == 0) {
- break;
- }
-
- if (cmp < 0) {
- n = n->left;
- } else {
- n = n->right;
- }
- }
-
- *ti = n;
- return (n) ? ZIX_STATUS_SUCCESS : ZIX_STATUS_NOT_FOUND;
-}
-
-void*
-zix_tree_get(const ZixTreeIter* ti)
-{
- return ti ? ti->data : NULL;
-}
-
-ZixTreeIter*
-zix_tree_begin(ZixTree* t)
-{
- if (!t->root) {
- return NULL;
- }
-
- ZixTreeNode* n = t->root;
- while (n->left) {
- n = n->left;
- }
-
- return n;
-}
-
-ZixTreeIter*
-zix_tree_end(ZixTree* ZIX_UNUSED(t))
-{
- return NULL;
-}
-
-ZixTreeIter*
-zix_tree_rbegin(ZixTree* t)
-{
- if (!t->root) {
- return NULL;
- }
-
- ZixTreeNode* n = t->root;
- while (n->right) {
- n = n->right;
- }
-
- return n;
-}
-
-ZixTreeIter*
-zix_tree_rend(ZixTree* ZIX_UNUSED(t))
-{
- return NULL;
-}
-
-bool
-zix_tree_iter_is_end(const ZixTreeIter* i)
-{
- return !i;
-}
-
-bool
-zix_tree_iter_is_rend(const ZixTreeIter* i)
-{
- return !i;
-}
-
-ZixTreeIter*
-zix_tree_iter_next(ZixTreeIter* i)
-{
- if (!i) {
- return NULL;
- }
-
- if (i->right) {
- i = i->right;
- while (i->left) {
- i = i->left;
- }
- } else {
- while (i->parent && i->parent->right == i) { // i is a right child
- i = i->parent;
- }
-
- i = i->parent;
- }
-
- return i;
-}
-
-ZixTreeIter*
-zix_tree_iter_prev(ZixTreeIter* i)
-{
- if (!i) {
- return NULL;
- }
-
- if (i->left) {
- i = i->left;
- while (i->right) {
- i = i->right;
- }
-
- } else {
- while (i->parent && i->parent->left == i) { // i is a left child
- i = i->parent;
- }
-
- i = i->parent;
- }
-
- return i;
-}
diff --git a/src/zix/tree.h b/src/zix/tree.h
deleted file mode 100644
index a2d5fe7..0000000
--- a/src/zix/tree.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- Copyright 2011-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef ZIX_TREE_H
-#define ZIX_TREE_H
-
-#include "zix/common.h"
-
-#include <stdbool.h>
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- @addtogroup zix
- @{
- @name Tree
- @{
-*/
-
-/**
- A balanced binary search tree.
-*/
-typedef struct ZixTreeImpl ZixTree;
-
-/**
- An iterator over a @ref ZixTree.
-*/
-typedef struct ZixTreeNodeImpl ZixTreeIter;
-
-/**
- Create a new (empty) tree.
-*/
-ZIX_API
-ZixTree*
-zix_tree_new(bool allow_duplicates,
- ZixComparator cmp,
- void* cmp_data,
- ZixDestroyFunc destroy);
-
-/**
- Free `t`.
-*/
-ZIX_API
-void
-zix_tree_free(ZixTree* t);
-
-/**
- Return the number of elements in `t`.
-*/
-ZIX_PURE_API
-size_t
-zix_tree_size(const ZixTree* t);
-
-/**
- Insert the element `e` into `t` and point `ti` at the new element.
-*/
-ZIX_API
-ZixStatus
-zix_tree_insert(ZixTree* t, void* e, ZixTreeIter** ti);
-
-/**
- Remove the item pointed at by `ti` from `t`.
-*/
-ZIX_API
-ZixStatus
-zix_tree_remove(ZixTree* t, ZixTreeIter* ti);
-
-/**
- Set `ti` to an element equal to `e` in `t`.
- If no such item exists, `ti` is set to NULL.
-*/
-ZIX_API
-ZixStatus
-zix_tree_find(const ZixTree* t, const void* e, ZixTreeIter** ti);
-
-/**
- Return the data associated with the given tree item.
-*/
-ZIX_PURE_API
-void*
-zix_tree_get(const ZixTreeIter* ti);
-
-/**
- Return an iterator to the first (smallest) element in `t`.
-*/
-ZIX_PURE_API
-ZixTreeIter*
-zix_tree_begin(ZixTree* t);
-
-/**
- Return an iterator the the element one past the last element in `t`.
-*/
-ZIX_CONST_API
-ZixTreeIter*
-zix_tree_end(ZixTree* t);
-
-/**
- Return true iff `i` is an iterator to the end of its tree.
-*/
-ZIX_CONST_API
-bool
-zix_tree_iter_is_end(const ZixTreeIter* i);
-
-/**
- Return an iterator to the last (largest) element in `t`.
-*/
-ZIX_PURE_API
-ZixTreeIter*
-zix_tree_rbegin(ZixTree* t);
-
-/**
- Return an iterator the the element one before the first element in `t`.
-*/
-ZIX_CONST_API
-ZixTreeIter*
-zix_tree_rend(ZixTree* t);
-
-/**
- Return true iff `i` is an iterator to the reverse end of its tree.
-*/
-ZIX_CONST_API
-bool
-zix_tree_iter_is_rend(const ZixTreeIter* i);
-
-/**
- Return an iterator that points to the element one past `i`.
-*/
-ZIX_PURE_API
-ZixTreeIter*
-zix_tree_iter_next(ZixTreeIter* i);
-
-/**
- Return an iterator that points to the element one before `i`.
-*/
-ZIX_PURE_API
-ZixTreeIter*
-zix_tree_iter_prev(ZixTreeIter* i);
-
-/**
- @}
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ZIX_TREE_H */
diff --git a/subprojects/sphinxygen.wrap b/subprojects/sphinxygen.wrap
new file mode 100644
index 0000000..898ee52
--- /dev/null
+++ b/subprojects/sphinxygen.wrap
@@ -0,0 +1,14 @@
+# Copyright 2022-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+[wrap-file]
+directory = sphinxygen-1.0.10
+source_url = https://download.drobilla.net/sphinxygen-1.0.10.tar.gz
+source_filename = sphinxygen-1.0.10.tar.gz
+source_hash = 4b5eeb1ff47d43ee1ddae9327c2b49bab1e49363538c569bc544705284f3695d
+
+# [wrap-git]
+# url = https://gitlab.com/drobilla/sphinxygen.git
+# push-url = ssh://git@gitlab.com:drobilla/sphinxygen.git
+# revision = v1.0.10
+# depth = 1
diff --git a/test/.clang-tidy b/test/.clang-tidy
index a6f6844..729db52 100644
--- a/test/.clang-tidy
+++ b/test/.clang-tidy
@@ -1,42 +1,20 @@
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
Checks: >
- *,
- -*-else-after-return,
-*-magic-numbers,
- -*-uppercase-literal-suffix,
- -*-vararg,
-android-cloexec-fopen,
-bugprone-assert-side-effect,
-bugprone-branch-clone,
- -bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
- -bugprone-not-null-terminated-result,
- -bugprone-reserved-identifier,
- -bugprone-suspicious-string-compare,
- -cert-dcl37-c,
- -cert-dcl50-cpp,
- -cert-dcl51-cpp,
- -cert-err34-c,
- -clang-analyzer-alpha.*,
+ -cert-err33-c,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
+ -concurrency-mt-unsafe,
-cppcoreguidelines-avoid-non-const-global-variables,
- -cppcoreguidelines-macro-usage,
-cppcoreguidelines-narrowing-conversions,
- -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
- -fuchsia-overloaded-operator,
- -google-explicit-constructor,
- -google-readability-todo,
- -hicpp-explicit-conversions,
-hicpp-multiway-paths-covered,
- -hicpp-no-array-decay,
-hicpp-signed-bitwise,
-llvm-header-guard,
- -llvmlibc-*,
- -misc-no-recursion,
- -misc-non-private-member-variables-in-classes,
- -misc-unused-parameters,
- -modernize-return-braced-init-list,
- -modernize-use-trailing-return-type,
- -readability-implicit-bool-conversion,
-WarningsAsErrors: '*'
-HeaderFilterRegex: '.*'
-FormatStyle: file
+ -readability-function-cognitive-complexity,
+ -readability-suspicious-call-argument,
+InheritParentConfig: true
diff --git a/test/bad_syntax.lv2/bad_syntax.c b/test/bad_syntax.lv2/bad_syntax.c
index da9c041..692fc33 100644
--- a/test/bad_syntax.lv2/bad_syntax.c
+++ b/test/bad_syntax.lv2/bad_syntax.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Bad syntax in plugin data file
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/bad_syntax.lv2/meson.build b/test/bad_syntax.lv2/meson.build
new file mode 100644
index 0000000..48df70e
--- /dev/null
+++ b/test/bad_syntax.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'bad_syntax',
+ files('bad_syntax.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'bad_syntax.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ configuration: config,
+ input: files(f + '.in'),
+ output: f,
+ )
+endforeach
+
+test(
+ 'bad_syntax',
+ executable(
+ 'test_bad_syntax',
+ files('test_bad_syntax.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/bad_syntax.lv2/test_bad_syntax.c b/test/bad_syntax.lv2/test_bad_syntax.c
index 5f10828..1e42ef3 100644
--- a/test/bad_syntax.lv2/test_bad_syntax.c
+++ b/test/bad_syntax.lv2/test_bad_syntax.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/bad-syntax"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
diff --git a/test/cpp/.clang-tidy b/test/cpp/.clang-tidy
new file mode 100644
index 0000000..a087a3d
--- /dev/null
+++ b/test/cpp/.clang-tidy
@@ -0,0 +1,21 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+Checks: >
+ -*-nullptr,
+ -cert-dcl50-cpp,
+ -cppcoreguidelines-macro-usage,
+ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+ -fuchsia-overloaded-operator,
+ -google-explicit-constructor,
+ -google-readability-todo,
+ -hicpp-explicit-conversions,
+ -hicpp-no-array-decay,
+ -misc-non-private-member-variables-in-classes,
+ -modernize-return-braced-init-list,
+ -modernize-use-nodiscard,
+ -modernize-use-trailing-return-type,
+ -modernize-use-using,
+ -readability-implicit-bool-conversion,
+HeaderFilterRegex: '.*/lilvmm\.hpp'
+InheritParentConfig: true
diff --git a/test/cpp/meson.build b/test/cpp/meson.build
new file mode 100644
index 0000000..b810e39
--- /dev/null
+++ b/test/cpp/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+cpp_suppressions = []
+if cpp.get_id() == 'gcc'
+ cpp_suppressions += [
+ '-Wno-cast-align',
+ '-Wno-padded',
+ ]
+elif cpp.get_id() == 'clang'
+ cpp_suppressions += [
+ '-Wno-c++98-compat',
+ '-Wno-cast-align',
+ '-Wno-cast-qual',
+ '-Wno-documentation-unknown-command',
+ '-Wno-padded',
+ '-Wno-poison-system-directories',
+ '-Wno-reserved-id-macro',
+ ]
+elif cpp.get_id() == 'msvc'
+ cpp_suppressions += [
+ '/wd4514', # unreferenced inline function has been removed
+ '/wd4820', # padding added after construct
+ ]
+endif
+
+test(
+ 'lilv_hpp',
+ executable(
+ 'test_lilv_hpp',
+ files('test_lilv_hpp.cpp'),
+ cpp_args: test_args + cpp_suppressions,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ suite: 'unit',
+)
diff --git a/test/cpp/test_lilv_hpp.cpp b/test/cpp/test_lilv_hpp.cpp
new file mode 100644
index 0000000..228fe1d
--- /dev/null
+++ b/test/cpp/test_lilv_hpp.cpp
@@ -0,0 +1,12 @@
+// Copyright 2017-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include <lilv/lilvmm.hpp>
+
+int
+main()
+{
+ const Lilv::World world{};
+
+ return 0;
+}
diff --git a/test/failed_instantiation.lv2/failed_instantiation.c b/test/failed_instantiation.lv2/failed_instantiation.c
index ecab647..e4e0efe 100644
--- a/test/failed_instantiation.lv2/failed_instantiation.c
+++ b/test/failed_instantiation.lv2/failed_instantiation.c
@@ -1,34 +1,13 @@
-/*
- Lilv Test Plugin - Failed instantiation
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
#define PLUGIN_URI "http://example.org/failed-instantiation"
-enum { TEST_INPUT = 0, TEST_OUTPUT = 1 };
-
-typedef struct {
- float* input;
- float* output;
-} Test;
-
static void
cleanup(LV2_Handle instance)
{
diff --git a/test/failed_instantiation.lv2/meson.build b/test/failed_instantiation.lv2/meson.build
new file mode 100644
index 0000000..0719d53
--- /dev/null
+++ b/test/failed_instantiation.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'failed_instantiation',
+ files('failed_instantiation.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'failed_instantiation.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ configuration: config,
+ input: files(f + '.in'),
+ output: f,
+ )
+endforeach
+
+test(
+ 'failed_instantiation',
+ executable(
+ 'test_failed_instantiation',
+ files('test_failed_instantiation.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/failed_instantiation.lv2/test_failed_instantiation.c b/test/failed_instantiation.lv2/test_failed_instantiation.c
index 8dbefc3..9e677cf 100644
--- a/test/failed_instantiation.lv2/test_failed_instantiation.c
+++ b/test/failed_instantiation.lv2/test_failed_instantiation.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/failed-instantiation"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
diff --git a/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c b/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c
index c7c08cf..4de2ebe 100644
--- a/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c
+++ b/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Failed lib descriptor
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdlib.h>
diff --git a/test/failed_lib_descriptor.lv2/meson.build b/test/failed_lib_descriptor.lv2/meson.build
new file mode 100644
index 0000000..8c5907a
--- /dev/null
+++ b/test/failed_lib_descriptor.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'failed_lib_descriptor',
+ files('failed_lib_descriptor.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'failed_lib_descriptor.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
+test(
+ 'failed_lib_descriptor',
+ executable(
+ 'test_failed_lib_descriptor',
+ files('test_failed_lib_descriptor.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c b/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c
index 71a3b96..dc37244 100644
--- a/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c
+++ b/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/failed-lib-descriptor"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
@@ -38,7 +31,7 @@ main(int argc, char** argv)
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
assert(plugin);
- LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
+ const LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
assert(!instance);
lilv_node_free(plugin_uri);
diff --git a/test/headers/.clang-tidy b/test/headers/.clang-tidy
new file mode 100644
index 0000000..a42a718
--- /dev/null
+++ b/test/headers/.clang-tidy
@@ -0,0 +1,15 @@
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+Checks: >
+ *,
+ -altera-*,
+ -llvmlibc-*,
+CheckOptions:
+ - key: readability-function-cognitive-complexity.Threshold
+ value: '1'
+ - key: readability-identifier-length.IgnoredParameterNames
+ value: '^(a)|(b)|(ui)|(i)$'
+WarningsAsErrors: '*'
+HeaderFilterRegex: '.*'
+FormatStyle: file
diff --git a/test/headers/meson.build b/test/headers/meson.build
new file mode 100644
index 0000000..c81ffaa
--- /dev/null
+++ b/test/headers/meson.build
@@ -0,0 +1,32 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+header_c_suppressions = []
+
+if get_option('warning_level') == 'everything'
+ if cc.get_id() == 'clang'
+ if not meson.is_cross_build()
+ header_c_suppressions += ['-Wno-poison-system-directories']
+ endif
+ elif cc.get_id() == 'msvc'
+ header_c_suppressions += [
+ '/wd4820', # padding added after construct
+ ]
+ endif
+endif
+
+if cc.get_id() == 'clang'
+ header_c_suppressions += ['-Wno-nullability-extension']
+endif
+
+test(
+ 'headers',
+ executable(
+ 'test_headers',
+ files('test_headers.c'),
+ c_args: header_c_suppressions,
+ dependencies: lilv_dep,
+ implicit_include_directories: false,
+ ),
+ suite: 'unit',
+)
diff --git a/test/headers/test_headers.c b/test/headers/test_headers.c
new file mode 100644
index 0000000..b0d4aa5
--- /dev/null
+++ b/test/headers/test_headers.c
@@ -0,0 +1,13 @@
+// Copyright 2022-2025 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include <lilv/lilv.h> // IWYU pragma: keep
+
+#ifdef __GNUC__
+__attribute__((const))
+#endif
+int
+main(void)
+{
+ return 0;
+}
diff --git a/test/lib_descriptor.lv2/lib_descriptor.c b/test/lib_descriptor.lv2/lib_descriptor.c
index ab27c2b..5a269ad 100644
--- a/test/lib_descriptor.lv2/lib_descriptor.c
+++ b/test/lib_descriptor.lv2/lib_descriptor.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Missing descriptor
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
@@ -96,12 +82,7 @@ get_plugin(LV2_Lib_Handle handle, uint32_t index)
{
(void)handle;
- switch (index) {
- case 0:
- return &descriptor;
- default:
- return NULL;
- }
+ return index ? NULL : &descriptor;
}
static const LV2_Lib_Descriptor lib = {NULL,
diff --git a/test/lib_descriptor.lv2/meson.build b/test/lib_descriptor.lv2/meson.build
new file mode 100644
index 0000000..217b907
--- /dev/null
+++ b/test/lib_descriptor.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'lib_descriptor',
+ files('lib_descriptor.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'lib_descriptor.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
+test(
+ 'lib_descriptor',
+ executable(
+ 'test_lib_descriptor',
+ files('test_lib_descriptor.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/lib_descriptor.lv2/test_lib_descriptor.c b/test/lib_descriptor.lv2/test_lib_descriptor.c
index bf79be8..29a51fd 100644
--- a/test/lib_descriptor.lv2/test_lib_descriptor.c
+++ b/test/lib_descriptor.lv2/test_lib_descriptor.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/lib-descriptor"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
diff --git a/test/lilv_cxx_test.cpp b/test/lilv_cxx_test.cpp
deleted file mode 100644
index 31d5e4e..0000000
--- a/test/lilv_cxx_test.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- Copyright 2017-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lilv/lilvmm.hpp"
-
-int
-main()
-{
- Lilv::World world;
-
- return 0;
-}
diff --git a/test/lilv_test_uri_map.h b/test/lilv_test_uri_map.h
index 5f85c86..00b5226 100644
--- a/test/lilv_test_uri_map.h
+++ b/test/lilv_test_uri_map.h
@@ -1,36 +1,20 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef LILV_TEST_URI_MAP_H
#define LILV_TEST_URI_MAP_H
-#include "../src/lilv_internal.h"
-
-#include "lv2/urid/urid.h"
-#include "serd/serd.h"
+#include <lv2/urid/urid.h>
+#include <serd/serd.h>
#include <assert.h>
-#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
- char** uris;
- size_t n_uris;
+ char** uris;
+ uint32_t n_uris;
} LilvTestUriMap;
static inline void
@@ -43,7 +27,7 @@ lilv_test_uri_map_init(LilvTestUriMap* const map)
static inline void
lilv_test_uri_map_clear(LilvTestUriMap* const map)
{
- for (size_t i = 0; i < map->n_uris; ++i) {
+ for (uint32_t i = 0; i < map->n_uris; ++i) {
free(map->uris[i]);
}
@@ -57,16 +41,18 @@ map_uri(LV2_URID_Map_Handle handle, const char* uri)
{
LilvTestUriMap* map = (LilvTestUriMap*)handle;
- for (size_t i = 0; i < map->n_uris; ++i) {
+ for (uint32_t i = 0; i < map->n_uris; ++i) {
if (!strcmp(map->uris[i], uri)) {
return i + 1;
}
}
+ const size_t uri_len = strlen(uri);
assert(serd_uri_string_has_scheme((const uint8_t*)uri));
map->uris = (char**)realloc(map->uris, ++map->n_uris * sizeof(char*));
- map->uris[map->n_uris - 1] = lilv_strdup(uri);
+ map->uris[map->n_uris - 1] = (char*)calloc(1, uri_len + 1);
+ memcpy(map->uris[map->n_uris - 1], uri, uri_len + 1);
return map->n_uris;
}
diff --git a/test/lilv_test_utils.c b/test/lilv_test_utils.c
index f658f1b..ba291d7 100644
--- a/test/lilv_test_utils.c
+++ b/test/lilv_test_utils.c
@@ -1,28 +1,14 @@
-/*
- Copyright 2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#define _POSIX_C_SOURCE 200809L /* for setenv */
+// Copyright 2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "lilv_test_utils.h"
-#include "../src/filesystem.h"
-#include "../src/lilv_internal.h"
-
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
+#include <serd/serd.h>
+#include <zix/allocator.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
+#include <zix/status.h>
#include <errno.h>
#include <stdbool.h>
@@ -46,13 +32,13 @@ lilv_test_env_new(void)
env->plugin2_uri = lilv_new_uri(world, "http://example.org/foobar");
// Set custom LV2_PATH in build directory to only use test data
- char* test_path = lilv_path_canonical(LILV_TEST_DIR);
- char* lv2_path = lilv_strjoin(test_path, "/test_lv2_path", NULL);
+ char* test_path = zix_canonical_path(NULL, LILV_TEST_DIR);
+ char* lv2_path = zix_path_join(NULL, test_path, "lv2");
LilvNode* path = lilv_new_string(world, lv2_path);
lilv_world_set_option(world, LILV_OPTION_LV2_PATH, path);
- free(lv2_path);
- free(test_path);
lilv_node_free(path);
+ zix_free(NULL, lv2_path);
+ zix_free(NULL, test_path);
return env;
}
@@ -60,10 +46,10 @@ lilv_test_env_new(void)
void
lilv_test_env_free(LilvTestEnv* env)
{
- free(env->test_content_path);
- free(env->test_manifest_path);
- free(env->test_bundle_uri);
- free(env->test_bundle_path);
+ zix_free(NULL, env->test_content_path);
+ zix_free(NULL, env->test_manifest_path);
+ lilv_node_free(env->test_bundle_uri);
+ zix_free(NULL, env->test_bundle_path);
lilv_node_free(env->plugin2_uri);
lilv_node_free(env->plugin1_uri);
lilv_world_free(env->world);
@@ -77,16 +63,16 @@ create_bundle(LilvTestEnv* env,
const char* plugin)
{
{
- char* const test_dir = lilv_path_canonical(LILV_TEST_DIR);
- char* const bundle_dir = lilv_path_join(test_dir, name);
+ char* const test_dir = zix_canonical_path(NULL, LILV_TEST_DIR);
+ char* const bundle_dir = zix_path_join(NULL, test_dir, name);
- env->test_bundle_path = lilv_path_join(bundle_dir, "");
+ env->test_bundle_path = zix_path_join(NULL, bundle_dir, "");
- lilv_free(bundle_dir);
- lilv_free(test_dir);
+ zix_free(NULL, bundle_dir);
+ zix_free(NULL, test_dir);
}
- if (lilv_create_directories(env->test_bundle_path)) {
+ if (zix_create_directories(NULL, env->test_bundle_path)) {
fprintf(stderr,
"Failed to create directory '%s' (%s)\n",
env->test_bundle_path,
@@ -98,9 +84,12 @@ create_bundle(LilvTestEnv* env,
(const uint8_t*)env->test_bundle_path, NULL, NULL, true);
env->test_bundle_uri = lilv_new_uri(env->world, (const char*)s.buf);
+
env->test_manifest_path =
- lilv_path_join(env->test_bundle_path, "manifest.ttl");
- env->test_content_path = lilv_path_join(env->test_bundle_path, "plugin.ttl");
+ zix_path_join(NULL, env->test_bundle_path, "manifest.ttl");
+
+ env->test_content_path =
+ zix_path_join(NULL, env->test_bundle_path, "plugin.ttl");
serd_node_free(&s);
@@ -148,25 +137,34 @@ start_bundle(LilvTestEnv* env,
return 0;
}
+static void
+remove_temporary(const char* const path)
+{
+ const ZixStatus st = zix_remove(path);
+ if (st) {
+ fprintf(stderr, "Failed to remove '%s' (%s)\n", path, zix_strerror(st));
+ }
+}
+
void
delete_bundle(LilvTestEnv* env)
{
if (env->test_content_path) {
- lilv_remove(env->test_content_path);
+ remove_temporary(env->test_content_path);
}
if (env->test_manifest_path) {
- lilv_remove(env->test_manifest_path);
+ remove_temporary(env->test_manifest_path);
}
if (env->test_bundle_path) {
- remove(env->test_bundle_path);
+ remove_temporary(env->test_bundle_path);
}
- free(env->test_content_path);
- free(env->test_manifest_path);
- free(env->test_bundle_uri);
- free(env->test_bundle_path);
+ zix_free(NULL, env->test_content_path);
+ zix_free(NULL, env->test_manifest_path);
+ lilv_node_free(env->test_bundle_uri);
+ zix_free(NULL, env->test_bundle_path);
env->test_content_path = NULL;
env->test_manifest_path = NULL;
@@ -188,3 +186,29 @@ set_env(const char* name, const char* value)
setenv(name, value, 1);
#endif
}
+
+char*
+lilv_create_temporary_directory(const char* pattern)
+{
+ char* const tmpdir = zix_temp_directory_path(NULL);
+ char* const path_pattern = zix_path_join(NULL, tmpdir, pattern);
+ char* const result = zix_create_temporary_directory(NULL, path_pattern);
+
+ zix_free(NULL, path_pattern);
+ zix_free(NULL, tmpdir);
+
+ return result;
+}
+
+char*
+string_concat(const char* const head, const char* const tail)
+{
+ const size_t head_len = strlen(head);
+ const size_t tail_len = strlen(tail);
+ char* const result = (char*)calloc(1U, head_len + tail_len + 1U);
+ if (result) {
+ memcpy(result, head, head_len + 1U);
+ memcpy(result + head_len, tail, tail_len + 1U);
+ }
+ return result;
+}
diff --git a/test/lilv_test_utils.h b/test/lilv_test_utils.h
index 76d9bc1..0943238 100644
--- a/test/lilv_test_utils.h
+++ b/test/lilv_test_utils.h
@@ -1,23 +1,11 @@
-/*
- Copyright 2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef LILV_TEST_UTILS_H
#define LILV_TEST_UTILS_H
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
+#include <zix/attributes.h>
#define MANIFEST_PREFIXES \
"\
@@ -92,4 +80,13 @@ delete_bundle(LilvTestEnv* env);
void
set_env(const char* name, const char* value);
+// Create a unique temporary directory
+ZIX_MALLOC_FUNC
+char*
+lilv_create_temporary_directory(const char* pattern);
+
+// Return a new string that is a concatenation of two given strings
+char*
+string_concat(const char* head, const char* tail);
+
#endif // LILV_TEST_UTILS_H
diff --git a/test/lint/meson.build b/test/lint/meson.build
new file mode 100644
index 0000000..04214f1
--- /dev/null
+++ b/test/lint/meson.build
@@ -0,0 +1,38 @@
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+# Check licensing metadata
+reuse = find_program('reuse', required: false)
+if reuse.found()
+ reuse_args = ['--root', lilv_src_root, 'lint']
+ test('REUSE', reuse, args: reuse_args, suite: 'data')
+endif
+
+if not meson.is_subproject()
+ # Check release metadata
+ autoship = find_program('autoship', required: false)
+ if autoship.found()
+ test('autoship', autoship, args: ['test', lilv_src_root], suite: 'data')
+ endif
+
+ # Check code with cppcheck
+ cppcheck = find_program('cppcheck', required: false)
+ if cppcheck.found()
+ compdb_path = join_paths(lilv_build_root, 'compile_commands.json')
+ suppress_path = join_paths(lilv_src_root, '.suppress.cppcheck')
+ test(
+ 'cppcheck',
+ cppcheck,
+ args: [
+ '--cppcheck-build-dir=' + meson.current_build_dir(),
+ '--enable=warning,style,performance,portability',
+ '--error-exitcode=1',
+ '--project=' + compdb_path,
+ '--suppressions-list=' + suppress_path,
+ '-DLILV_VERSION="\"@0@\""'.format(meson.project_version()),
+ '-q',
+ ],
+ suite: 'code',
+ )
+ endif
+endif
diff --git a/test/core.lv2/lv2core.ttl b/test/lv2/core.lv2/lv2core.ttl
index 5659487..5659487 100644
--- a/test/core.lv2/lv2core.ttl
+++ b/test/lv2/core.lv2/lv2core.ttl
diff --git a/test/core.lv2/manifest.ttl b/test/lv2/core.lv2/manifest.ttl
index a77ad71..a77ad71 100644
--- a/test/core.lv2/manifest.ttl
+++ b/test/lv2/core.lv2/manifest.ttl
diff --git a/test/lv2/core.lv2/meson.build b/test/lv2/core.lv2/meson.build
new file mode 100644
index 0000000..0d02ae1
--- /dev/null
+++ b/test/lv2/core.lv2/meson.build
@@ -0,0 +1,11 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+ttl_files = files(
+ 'lv2core.ttl',
+ 'manifest.ttl',
+)
+
+foreach file : ttl_files
+ configure_file(copy: true, input: file, output: '@PLAINNAME@')
+endforeach
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 0000000..ce0c708
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,103 @@
+# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+###################
+# Header Warnings #
+###################
+
+subdir('headers')
+
+##############
+# Test Setup #
+##############
+
+test_args = []
+if cc.get_id() == 'msvc'
+ test_args += [
+ '/wd4464', # relative include path contains '..'
+ ]
+endif
+
+subdir('lv2/core.lv2')
+
+################
+# Bundle Tests #
+################
+
+subdir('bad_syntax.lv2')
+subdir('failed_instantiation.lv2')
+subdir('failed_lib_descriptor.lv2')
+subdir('lib_descriptor.lv2')
+subdir('missing_descriptor.lv2')
+subdir('missing_name.lv2')
+subdir('missing_plugin.lv2')
+subdir('missing_port.lv2')
+subdir('missing_port_name.lv2')
+subdir('new_version.lv2')
+subdir('old_version.lv2')
+subdir('test_plugin.lv2')
+
+################
+# C++ Bindings #
+################
+
+if not get_option('bindings_cpp').disabled()
+ subdir('cpp')
+endif
+
+##############
+# Unit Tests #
+##############
+
+unit_tests = [
+ 'bad_port_index',
+ 'bad_port_symbol',
+ 'classes',
+ 'discovery',
+ 'get_symbol',
+ 'no_author',
+ 'no_verify',
+ 'plugin',
+ 'port',
+ 'preset',
+ 'project',
+ 'project_no_author',
+ 'prototype',
+ 'reload_bundle',
+ 'replace_version',
+ 'state',
+ 'ui',
+ 'util',
+ 'value',
+ 'verify',
+ 'world',
+]
+
+define_args = [
+ '-DLILV_TEST_BUNDLE="@0@/"'.format(
+ meson.current_build_dir() / 'test_plugin.lv2',
+ ),
+ '-DLILV_TEST_DIR="@0@/"'.format(meson.current_build_dir()),
+]
+
+foreach unit : unit_tests
+ test(
+ unit,
+ executable(
+ 'test_@0@'.format(unit),
+ files('lilv_test_utils.c', 'test_@0@.c'.format(unit)),
+ c_args: define_args + test_args + c_suppressions,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ suite: 'unit',
+ )
+endforeach
+
+########
+# Lint #
+########
+
+if get_option('lint')
+ subdir('lint')
+endif
diff --git a/test/missing_descriptor.lv2/meson.build b/test/missing_descriptor.lv2/meson.build
new file mode 100644
index 0000000..92c5145
--- /dev/null
+++ b/test/missing_descriptor.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'missing_descriptor',
+ files('missing_descriptor.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'missing_descriptor.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
+test(
+ 'missing_descriptor',
+ executable(
+ 'test_missing_descriptor',
+ files('test_missing_descriptor.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/missing_descriptor.lv2/missing_descriptor.c b/test/missing_descriptor.lv2/missing_descriptor.c
index ec1b473..c1fa47a 100644
--- a/test/missing_descriptor.lv2/missing_descriptor.c
+++ b/test/missing_descriptor.lv2/missing_descriptor.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Missing descriptor
- Copyright 2011-2018 David Robillard <d@drobilla.net>
+// Copyright 2011-2018 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
LV2_SYMBOL_EXPORT
extern const char* msg;
diff --git a/test/missing_descriptor.lv2/test_missing_descriptor.c b/test/missing_descriptor.lv2/test_missing_descriptor.c
index 330e534..ed7b868 100644
--- a/test/missing_descriptor.lv2/test_missing_descriptor.c
+++ b/test/missing_descriptor.lv2/test_missing_descriptor.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-descriptor"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
@@ -38,7 +31,7 @@ main(int argc, char** argv)
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
assert(plugin);
- LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
+ const LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
assert(!instance);
lilv_node_free(plugin_uri);
diff --git a/test/missing_name.lv2/meson.build b/test/missing_name.lv2/meson.build
new file mode 100644
index 0000000..da9759e
--- /dev/null
+++ b/test/missing_name.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'missing_name',
+ files('missing_name.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'missing_name.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
+test(
+ 'missing_name',
+ executable(
+ 'test_missing_name',
+ files('test_missing_name.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/missing_name.lv2/missing_name.c b/test/missing_name.lv2/missing_name.c
index 8c6e6fe..8099cc4 100644
--- a/test/missing_name.lv2/missing_name.c
+++ b/test/missing_name.lv2/missing_name.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Missing name
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/missing_name.lv2/test_missing_name.c b/test/missing_name.lv2/test_missing_name.c
index 5cb069a..368ad5f 100644
--- a/test/missing_name.lv2/test_missing_name.c
+++ b/test/missing_name.lv2/test_missing_name.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-name"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
diff --git a/test/missing_plugin.lv2/meson.build b/test/missing_plugin.lv2/meson.build
new file mode 100644
index 0000000..f28fc9f
--- /dev/null
+++ b/test/missing_plugin.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'missing_plugin',
+ files('missing_plugin.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'missing_plugin.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
+test(
+ 'missing_plugin',
+ executable(
+ 'test_missing_plugin',
+ files('test_missing_plugin.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/missing_plugin.lv2/missing_plugin.c b/test/missing_plugin.lv2/missing_plugin.c
index 8ca146c..15b790f 100644
--- a/test/missing_plugin.lv2/missing_plugin.c
+++ b/test/missing_plugin.lv2/missing_plugin.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Missing plugin
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/missing_plugin.lv2/test_missing_plugin.c b/test/missing_plugin.lv2/test_missing_plugin.c
index 861fcba..e62b236 100644
--- a/test/missing_plugin.lv2/test_missing_plugin.c
+++ b/test/missing_plugin.lv2/test_missing_plugin.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-plugin"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
@@ -38,7 +31,7 @@ main(int argc, char** argv)
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
assert(plugin);
- LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
+ const LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
assert(!instance);
lilv_node_free(plugin_uri);
diff --git a/test/missing_port.lv2/meson.build b/test/missing_port.lv2/meson.build
new file mode 100644
index 0000000..3bf892b
--- /dev/null
+++ b/test/missing_port.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'missing_port',
+ files('missing_port.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'missing_port.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
+test(
+ 'missing_port',
+ executable(
+ 'test_missing_port',
+ files('test_missing_port.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/missing_port.lv2/missing_port.c b/test/missing_port.lv2/missing_port.c
index c567d55..d85af8c 100644
--- a/test/missing_port.lv2/missing_port.c
+++ b/test/missing_port.lv2/missing_port.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Missing port
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/missing_port.lv2/test_missing_port.c b/test/missing_port.lv2/test_missing_port.c
index ec6713c..4d5323d 100644
--- a/test/missing_port.lv2/test_missing_port.c
+++ b/test/missing_port.lv2/test_missing_port.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-port"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
diff --git a/test/missing_port_name.lv2/meson.build b/test/missing_port_name.lv2/meson.build
new file mode 100644
index 0000000..68fe629
--- /dev/null
+++ b/test/missing_port_name.lv2/meson.build
@@ -0,0 +1,37 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'missing_port_name',
+ files('missing_port_name.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'missing_port_name.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
+test(
+ 'missing_port_name',
+ executable(
+ 'test_missing_port_name',
+ files('test_missing_port_name.c'),
+ c_args: c_suppressions + test_args,
+ dependencies: [lv2_dep, lilv_dep],
+ implicit_include_directories: false,
+ ),
+ args: [meson.current_build_dir() / ''],
+ suite: 'plugin',
+)
+
diff --git a/test/missing_port_name.lv2/missing_port_name.c b/test/missing_port_name.lv2/missing_port_name.c
index 7a00945..6f14ba3 100644
--- a/test/missing_port_name.lv2/missing_port_name.c
+++ b/test/missing_port_name.lv2/missing_port_name.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Missing port name
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/missing_port_name.lv2/test_missing_port_name.c b/test/missing_port_name.lv2/test_missing_port_name.c
index 4d017d9..b483b84 100644
--- a/test/missing_port_name.lv2/test_missing_port_name.c
+++ b/test/missing_port_name.lv2/test_missing_port_name.c
@@ -1,15 +1,12 @@
-#undef NDEBUG
+// Copyright 2015-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "../src/filesystem.h"
+#undef NDEBUG
-#include "lilv/lilv.h"
-#include "serd/serd.h"
+#include <lilv/lilv.h>
#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#define PLUGIN_URI "http://example.org/missing-port-name"
@@ -25,12 +22,8 @@ main(int argc, char** argv)
LilvWorld* world = lilv_world_new();
// Load test plugin bundle
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path);
lilv_world_load_bundle(world, bundle_uri);
- free(abs_bundle);
- serd_node_free(&bundle);
lilv_node_free(bundle_uri);
LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI);
diff --git a/test/new_version.lv2/meson.build b/test/new_version.lv2/meson.build
new file mode 100644
index 0000000..bd90443
--- /dev/null
+++ b/test/new_version.lv2/meson.build
@@ -0,0 +1,24 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'new_version',
+ files('new_version.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'new_version.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
diff --git a/test/new_version.lv2/new_version.c b/test/new_version.lv2/new_version.c
index 4de48e7..3521c6e 100644
--- a/test/new_version.lv2/new_version.c
+++ b/test/new_version.lv2/new_version.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - New version
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/old_version.lv2/meson.build b/test/old_version.lv2/meson.build
new file mode 100644
index 0000000..09434b1
--- /dev/null
+++ b/test/old_version.lv2/meson.build
@@ -0,0 +1,24 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'old_version',
+ files('old_version.c'),
+ c_args: c_suppressions,
+ dependencies: lv2_dep,
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'old_version.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
diff --git a/test/old_version.lv2/old_version.c b/test/old_version.lv2/old_version.c
index 7f97dad..3521c6e 100644
--- a/test/old_version.lv2/old_version.c
+++ b/test/old_version.lv2/old_version.c
@@ -1,21 +1,7 @@
-/*
- Lilv Test Plugin - Old version
- Copyright 2011-2019 David Robillard <d@drobilla.net>
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lv2/core/lv2.h"
+#include <lv2/core/lv2.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/test_bad_port_index.c b/test/test_bad_port_index.c
index 985d74e..6177dbb 100644
--- a/test/test_bad_port_index.c
+++ b/test/test_bad_port_index.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <stdint.h>
@@ -38,8 +25,8 @@ static const char* const plugin_ttl = "\
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(
env, "bad_port_index.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
diff --git a/test/test_bad_port_symbol.c b/test/test_bad_port_symbol.c
index ae34ad0..3f01c82 100644
--- a/test/test_bad_port_symbol.c
+++ b/test/test_bad_port_symbol.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <stdint.h>
@@ -38,8 +25,8 @@ static const char* const plugin_ttl = "\
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(
env, "bad_port_symbol.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
diff --git a/test/test_classes.c b/test/test_classes.c
index 332d847..52dd711 100644
--- a/test/test_classes.c
+++ b/test/test_classes.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <string.h>
diff --git a/test/test_discovery.c b/test/test_discovery.c
index f7f30ea..be9cde8 100644
--- a/test/test_discovery.c
+++ b/test/test_discovery.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <string.h>
@@ -56,8 +43,8 @@ discovery_verify_plugin(const LilvTestEnv* env, const LilvPlugin* plugin)
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(env, "discovery.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
return 1;
diff --git a/test/test_filesystem.c b/test/test_filesystem.c
deleted file mode 100644
index 0a4aa4d..0000000
--- a/test/test_filesystem.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- Copyright 2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#undef NDEBUG
-
-#include "lilv_internal.h"
-
-#include "../src/filesystem.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static bool
-equals(char* string, const char* expected)
-{
- const bool result = !strcmp(string, expected);
- free(string);
- return result;
-}
-
-static void
-test_temp_directory_path(void)
-{
- char* tmpdir = lilv_temp_directory_path();
-
- assert(lilv_is_directory(tmpdir));
-
- free(tmpdir);
-}
-
-static void
-test_path_is_absolute(void)
-{
- assert(lilv_path_is_absolute("/a/b"));
- assert(lilv_path_is_absolute("/a"));
- assert(lilv_path_is_absolute("/"));
-
- assert(!lilv_path_is_absolute("a/b"));
- assert(!lilv_path_is_absolute("a"));
- assert(!lilv_path_is_absolute("."));
-
-#ifdef _WIN32
- assert(lilv_path_is_absolute("C:/a/b"));
- assert(lilv_path_is_absolute("C:\\a\\b"));
- assert(lilv_path_is_absolute("D:/a/b"));
- assert(lilv_path_is_absolute("D:\\a\\b"));
-#endif
-}
-
-static void
-test_path_is_child(void)
-{
- assert(lilv_path_is_child("/a/b", "/a"));
- assert(lilv_path_is_child("/a/b", "/a/"));
- assert(lilv_path_is_child("/a/b/", "/a"));
- assert(lilv_path_is_child("/a/b/", "/a/"));
-
- assert(!lilv_path_is_child("/a/b", "/a/c"));
- assert(!lilv_path_is_child("/a/b", "/a/c/"));
- assert(!lilv_path_is_child("/a/b/", "/a/c"));
- assert(!lilv_path_is_child("/a/b/", "/a/c/"));
-
- assert(!lilv_path_is_child("/a/b", "/c"));
- assert(!lilv_path_is_child("/a/b", "/c/"));
- assert(!lilv_path_is_child("/a/b/", "/c"));
- assert(!lilv_path_is_child("/a/b/", "/c/"));
-}
-
-static void
-test_path_current(void)
-{
- char* cwd = lilv_path_current();
-
- assert(lilv_is_directory(cwd));
-
- free(cwd);
-}
-
-static void
-test_path_absolute(void)
-{
- const char* const short_path = "a";
- const char* const long_path = "a/b/c";
-
- char* const cwd = lilv_path_current();
- char* const expected_short = lilv_path_join(cwd, short_path);
- char* const expected_long = lilv_path_join(cwd, long_path);
-
- assert(equals(lilv_path_absolute(short_path), expected_short));
- assert(equals(lilv_path_absolute(long_path), expected_long));
-
- free(expected_long);
- free(expected_short);
- free(cwd);
-}
-
-static void
-test_path_absolute_child(void)
-{
- const char* const parent = "/parent";
- const char* const short_path = "a";
- const char* const long_path = "a/b/c";
-
- char* const expected_short = lilv_path_join(parent, short_path);
- char* const expected_long = lilv_path_join(parent, long_path);
-
- assert(equals(lilv_path_absolute_child(short_path, parent), expected_short));
-
- assert(equals(lilv_path_absolute_child(long_path, parent), expected_long));
-
- free(expected_long);
- free(expected_short);
-}
-
-static void
-test_path_relative_to(void)
-{
- assert(equals(lilv_path_relative_to("/a/b", "/a/"), "b"));
- assert(equals(lilv_path_relative_to("/a", "/b/c/"), "/a"));
- assert(equals(lilv_path_relative_to("/a/b/c", "/a/b/d/"), "../c"));
- assert(equals(lilv_path_relative_to("/a/b/c", "/a/b/d/e/"), "../../c"));
-
-#ifdef _WIN32
- assert(equals(lilv_path_relative_to("C:/a/b", "C:/a/"), "b"));
- assert(equals(lilv_path_relative_to("C:/a", "C:/b/c/"), "../../a"));
- assert(equals(lilv_path_relative_to("C:/a/b/c", "C:/a/b/d/"), "../c"));
- assert(equals(lilv_path_relative_to("C:/a/b/c", "C:/a/b/d/e/"), "../../c"));
-
- assert(equals(lilv_path_relative_to("C:\\a\\b", "C:\\a\\"), "b"));
- assert(equals(lilv_path_relative_to("C:\\a", "C:\\b\\c\\"), "..\\..\\a"));
- assert(
- equals(lilv_path_relative_to("C:\\a\\b\\c", "C:\\a\\b\\d\\"), "..\\c"));
- assert(equals(lilv_path_relative_to("C:\\a\\b\\c", "C:\\a\\b\\d\\e\\"),
- "..\\..\\c"));
-#endif
-}
-
-static void
-test_path_parent(void)
-{
- assert(equals(lilv_path_parent("/"), "/"));
- assert(equals(lilv_path_parent("//"), "/"));
- assert(equals(lilv_path_parent("/a"), "/"));
- assert(equals(lilv_path_parent("/a/"), "/"));
- assert(equals(lilv_path_parent("/a///b/"), "/a"));
- assert(equals(lilv_path_parent("/a///b//"), "/a"));
- assert(equals(lilv_path_parent("/a/b"), "/a"));
- assert(equals(lilv_path_parent("/a/b/"), "/a"));
- assert(equals(lilv_path_parent("/a/b/c"), "/a/b"));
- assert(equals(lilv_path_parent("/a/b/c/"), "/a/b"));
- assert(equals(lilv_path_parent("a"), "."));
-}
-
-static void
-test_path_filename(void)
-{
- // Cases from cppreference.com for std::filesystem::path::filename
- assert(equals(lilv_path_filename("/foo/bar.txt"), "bar.txt"));
- assert(equals(lilv_path_filename("/foo/.bar"), ".bar"));
- assert(equals(lilv_path_filename("/foo/bar/"), ""));
- assert(equals(lilv_path_filename("/foo/."), "."));
- assert(equals(lilv_path_filename("/foo/.."), ".."));
- assert(equals(lilv_path_filename("."), "."));
- assert(equals(lilv_path_filename(".."), ".."));
- assert(equals(lilv_path_filename("/"), ""));
- assert(equals(lilv_path_filename("//host"), "host"));
-
-#ifdef _WIN32
- assert(equals(lilv_path_filename("C:/foo/bar.txt"), "bar.txt"));
- assert(equals(lilv_path_filename("C:\\foo\\bar.txt"), "bar.txt"));
- assert(equals(lilv_path_filename("foo/bar.txt"), "bar.txt"));
- assert(equals(lilv_path_filename("foo\\bar.txt"), "bar.txt"));
-#endif
-}
-
-static void
-test_path_join(void)
-{
- assert(lilv_path_join(NULL, NULL) == NULL);
- assert(lilv_path_join(NULL, "") == NULL);
-
-#ifdef _WIN32
- assert(equals(lilv_path_join("", NULL), "\\"));
- assert(equals(lilv_path_join("", ""), "\\"));
- assert(equals(lilv_path_join("a", ""), "a\\"));
- assert(equals(lilv_path_join("a", NULL), "a\\"));
- assert(equals(lilv_path_join("a", "b"), "a\\b"));
-#else
- assert(equals(lilv_path_join("", NULL), "/"));
- assert(equals(lilv_path_join("", ""), "/"));
- assert(equals(lilv_path_join("a", ""), "a/"));
- assert(equals(lilv_path_join("a", NULL), "a/"));
- assert(equals(lilv_path_join("a", "b"), "a/b"));
-#endif
-
- assert(equals(lilv_path_join("/a", ""), "/a/"));
- assert(equals(lilv_path_join("/a/b", ""), "/a/b/"));
- assert(equals(lilv_path_join("/a/", ""), "/a/"));
- assert(equals(lilv_path_join("/a/b/", ""), "/a/b/"));
- assert(equals(lilv_path_join("a/b", ""), "a/b/"));
- assert(equals(lilv_path_join("a/", ""), "a/"));
- assert(equals(lilv_path_join("a/b/", ""), "a/b/"));
-
- assert(equals(lilv_path_join("/a", NULL), "/a/"));
- assert(equals(lilv_path_join("/a/b", NULL), "/a/b/"));
- assert(equals(lilv_path_join("/a/", NULL), "/a/"));
- assert(equals(lilv_path_join("/a/b/", NULL), "/a/b/"));
- assert(equals(lilv_path_join("a/b", NULL), "a/b/"));
- assert(equals(lilv_path_join("a/", NULL), "a/"));
- assert(equals(lilv_path_join("a/b/", NULL), "a/b/"));
-
- assert(equals(lilv_path_join("/a", "b"), "/a/b"));
- assert(equals(lilv_path_join("/a/", "b"), "/a/b"));
- assert(equals(lilv_path_join("a/", "b"), "a/b"));
-
- assert(equals(lilv_path_join("/a", "b/"), "/a/b/"));
- assert(equals(lilv_path_join("/a/", "b/"), "/a/b/"));
- assert(equals(lilv_path_join("a", "b/"), "a/b/"));
- assert(equals(lilv_path_join("a/", "b/"), "a/b/"));
-
-#ifdef _WIN32
- assert(equals(lilv_path_join("C:/a", "b"), "C:/a/b"));
- assert(equals(lilv_path_join("C:\\a", "b"), "C:\\a\\b"));
- assert(equals(lilv_path_join("C:/a", "b/"), "C:/a/b/"));
- assert(equals(lilv_path_join("C:\\a", "b\\"), "C:\\a\\b\\"));
-#endif
-}
-
-static void
-test_path_canonical(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
- char* const file_path = lilv_path_join(temp_dir, "lilv_test_file");
-
- FILE* f = fopen(file_path, "w");
- fprintf(f, "test\n");
- fclose(f);
-
-#ifndef _WIN32
- // Test symlink resolution
-
- char* const link_path = lilv_path_join(temp_dir, "lilv_test_link");
-
- assert(!lilv_symlink(file_path, link_path));
-
- char* const real_file_path = lilv_path_canonical(file_path);
- char* const real_link_path = lilv_path_canonical(link_path);
-
- assert(!strcmp(real_file_path, real_link_path));
-
- assert(!lilv_remove(link_path));
- free(real_link_path);
- free(real_file_path);
- free(link_path);
-#endif
-
- // Test dot segment resolution
-
- char* const parent_dir_1 = lilv_path_join(temp_dir, "..");
- char* const parent_dir_2 = lilv_path_parent(temp_dir);
- char* const real_parent_dir_1 = lilv_path_canonical(parent_dir_1);
- char* const real_parent_dir_2 = lilv_path_canonical(parent_dir_2);
-
- assert(!strcmp(real_parent_dir_1, real_parent_dir_2));
-
- // Clean everything up
-
- assert(!lilv_remove(file_path));
- assert(!lilv_remove(temp_dir));
-
- free(real_parent_dir_2);
- free(real_parent_dir_1);
- free(parent_dir_2);
- free(parent_dir_1);
- free(file_path);
- free(temp_dir);
-}
-
-static void
-test_path_exists(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
- char* const file_path = lilv_path_join(temp_dir, "lilv_test_file");
-
- assert(!lilv_path_exists(file_path));
-
- FILE* f = fopen(file_path, "w");
- fprintf(f, "test\n");
- fclose(f);
-
- assert(lilv_path_exists(file_path));
-
- assert(!lilv_remove(file_path));
- assert(!lilv_remove(temp_dir));
-
- free(file_path);
- free(temp_dir);
-}
-
-static void
-test_is_directory(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
- char* const file_path = lilv_path_join(temp_dir, "lilv_test_file");
-
- assert(lilv_is_directory(temp_dir));
- assert(!lilv_is_directory(file_path)); // Nonexistent
-
- FILE* f = fopen(file_path, "w");
- fprintf(f, "test\n");
- fclose(f);
-
- assert(!lilv_is_directory(file_path)); // File
-
- assert(!lilv_remove(file_path));
- assert(!lilv_remove(temp_dir));
-
- free(file_path);
- free(temp_dir);
-}
-
-static void
-test_copy_file(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
- char* const file_path = lilv_path_join(temp_dir, "lilv_test_file");
- char* const copy_path = lilv_path_join(temp_dir, "lilv_test_copy");
-
- FILE* f = fopen(file_path, "w");
- fprintf(f, "test\n");
- fclose(f);
-
- assert(!lilv_copy_file(file_path, copy_path));
- assert(lilv_file_equals(file_path, copy_path));
-
- if (lilv_path_exists("/dev/full")) {
- // Copy short file (error after flushing)
- assert(lilv_copy_file(file_path, "/dev/full") == ENOSPC);
-
- // Copy long file (error during writing)
- f = fopen(file_path, "w");
- for (size_t i = 0; i < 4096; ++i) {
- fprintf(f, "test\n");
- }
- fclose(f);
- assert(lilv_copy_file(file_path, "/dev/full") == ENOSPC);
- }
-
- assert(!lilv_remove(copy_path));
- assert(!lilv_remove(file_path));
- assert(!lilv_remove(temp_dir));
-
- free(copy_path);
- free(file_path);
- free(temp_dir);
-}
-
-static void
-test_flock(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
- char* const file_path = lilv_path_join(temp_dir, "lilv_test_file");
-
- FILE* const f1 = fopen(file_path, "w");
- FILE* const f2 = fopen(file_path, "w");
-
- assert(!lilv_flock(f1, true, false));
- assert(lilv_flock(f2, true, false));
- assert(!lilv_flock(f1, false, false));
-
- fclose(f2);
- fclose(f1);
- assert(!lilv_remove(file_path));
- assert(!lilv_remove(temp_dir));
- free(file_path);
- free(temp_dir);
-}
-
-typedef struct {
- size_t n_names;
- char** names;
-} FileList;
-
-static void
-visit(const char* const path, const char* const name, void* const data)
-{
- (void)path;
-
- FileList* file_list = (FileList*)data;
-
- file_list->names =
- (char**)realloc(file_list->names, sizeof(char*) * ++file_list->n_names);
-
- file_list->names[file_list->n_names - 1] = lilv_strdup(name);
-}
-
-static void
-test_dir_for_each(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
- char* const path1 = lilv_path_join(temp_dir, "lilv_test_1");
- char* const path2 = lilv_path_join(temp_dir, "lilv_test_2");
-
- FILE* const f1 = fopen(path1, "w");
- FILE* const f2 = fopen(path2, "w");
- fprintf(f1, "test\n");
- fprintf(f2, "test\n");
- fclose(f2);
- fclose(f1);
-
- FileList file_list = {0, NULL};
- lilv_dir_for_each(temp_dir, &file_list, visit);
-
- assert((!strcmp(file_list.names[0], "lilv_test_1") &&
- !strcmp(file_list.names[1], "lilv_test_2")) ||
- (!strcmp(file_list.names[0], "lilv_test_2") &&
- !strcmp(file_list.names[1], "lilv_test_1")));
-
- assert(!lilv_remove(path2));
- assert(!lilv_remove(path1));
- assert(!lilv_remove(temp_dir));
-
- free(file_list.names[0]);
- free(file_list.names[1]);
- free(file_list.names);
- free(path2);
- free(path1);
- free(temp_dir);
-}
-
-static void
-test_create_temporary_directory(void)
-{
- char* const path1 = lilv_create_temporary_directory("lilvXXXXXX");
-
- assert(lilv_is_directory(path1));
-
- char* const path2 = lilv_create_temporary_directory("lilvXXXXXX");
-
- assert(strcmp(path1, path2));
- assert(lilv_is_directory(path2));
-
- assert(!lilv_remove(path2));
- assert(!lilv_remove(path1));
- free(path2);
- free(path1);
-}
-
-static void
-test_create_directories(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
-
- assert(lilv_is_directory(temp_dir));
-
- char* const child_dir = lilv_path_join(temp_dir, "child");
- char* const grandchild_dir = lilv_path_join(child_dir, "grandchild");
-
- assert(!lilv_create_directories(grandchild_dir));
- assert(lilv_is_directory(grandchild_dir));
- assert(lilv_is_directory(child_dir));
-
- char* const file_path = lilv_path_join(temp_dir, "lilv_test_file");
- FILE* const f = fopen(file_path, "w");
-
- fprintf(f, "test\n");
- fclose(f);
-
- assert(lilv_create_directories(file_path));
-
- assert(!lilv_remove(file_path));
- assert(!lilv_remove(grandchild_dir));
- assert(!lilv_remove(child_dir));
- assert(!lilv_remove(temp_dir));
- free(file_path);
- free(child_dir);
- free(grandchild_dir);
- free(temp_dir);
-}
-
-static void
-test_file_equals(void)
-{
- char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX");
- char* const path1 = lilv_path_join(temp_dir, "lilv_test_1");
- char* const path2 = lilv_path_join(temp_dir, "lilv_test_2");
-
- FILE* const f1 = fopen(path1, "w");
- FILE* const f2 = fopen(path2, "w");
- fprintf(f1, "test\n");
- fprintf(f2, "test\n");
-
- assert(lilv_file_equals(path1, path2));
-
- fprintf(f2, "diff\n");
- fflush(f2);
-
- assert(!lilv_file_equals(path1, path2));
-
- fclose(f2);
- fclose(f1);
-
- assert(!lilv_remove(path2));
- assert(!lilv_remove(path1));
- assert(!lilv_remove(temp_dir));
-
- free(path2);
- free(path1);
- free(temp_dir);
-}
-
-int
-main(void)
-{
- test_temp_directory_path();
- test_path_is_absolute();
- test_path_is_child();
- test_path_current();
- test_path_absolute();
- test_path_absolute_child();
- test_path_relative_to();
- test_path_parent();
- test_path_filename();
- test_path_join();
- test_path_canonical();
- test_path_exists();
- test_is_directory();
- test_copy_file();
- test_flock();
- test_dir_for_each();
- test_create_temporary_directory();
- test_create_directories();
- test_file_equals();
-
- return 0;
-}
diff --git a/test/test_get_symbol.c b/test/test_get_symbol.c
index 5337c63..2236df8 100644
--- a/test/test_get_symbol.c
+++ b/test/test_get_symbol.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <string.h>
diff --git a/test/test_no_author.c b/test/test_no_author.c
index aa91198..70991c2 100644
--- a/test/test_no_author.c
+++ b/test/test_no_author.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
@@ -60,8 +47,8 @@ static const char* const plugin_ttl = "\
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(env, "no_author.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
return 1;
@@ -74,13 +61,13 @@ main(void)
const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri);
assert(plug);
- LilvNode* author_name = lilv_plugin_get_author_name(plug);
+ const LilvNode* author_name = lilv_plugin_get_author_name(plug);
assert(!author_name);
- LilvNode* author_email = lilv_plugin_get_author_email(plug);
+ const LilvNode* author_email = lilv_plugin_get_author_email(plug);
assert(!author_email);
- LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug);
+ const LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug);
assert(!author_homepage);
delete_bundle(env);
diff --git a/test/test_no_verify.c b/test/test_no_verify.c
index e71c483..9c63ea2 100644
--- a/test/test_no_verify.c
+++ b/test/test_no_verify.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
@@ -27,8 +14,8 @@ static const char* const plugin_ttl = ":plug a lv2:Plugin .\n";
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(env, "no_verify.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
return 1;
diff --git a/test/test_plugin.c b/test/test_plugin.c
index 2a427dc..0bd1870 100644
--- a/test/test_plugin.c
+++ b/test/test_plugin.c
@@ -1,26 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "../src/lilv_internal.h"
-
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <float.h>
@@ -114,14 +99,14 @@ main(void)
const LilvNodes* data_uris = lilv_plugin_get_data_uris(plug);
assert(lilv_nodes_size(data_uris) == 2);
- LilvNode* project = lilv_plugin_get_project(plug);
+ const LilvNode* project = lilv_plugin_get_project(plug);
assert(!project);
char* manifest_uri =
- lilv_strjoin(lilv_node_as_string(plug_bundle_uri), "manifest.ttl", NULL);
+ string_concat(lilv_node_as_string(plug_bundle_uri), "manifest.ttl");
char* data_uri =
- lilv_strjoin(lilv_node_as_string(plug_bundle_uri), "plugin.ttl", NULL);
+ string_concat(lilv_node_as_string(plug_bundle_uri), "plugin.ttl");
LilvNode* manifest_uri_val = lilv_new_uri(world, manifest_uri);
assert(lilv_nodes_contains(data_uris, manifest_uri_val));
@@ -231,7 +216,7 @@ main(void)
LilvNode* blank_p = lilv_new_uri(world, "http://example.org/blank");
LilvNodes* blanks = lilv_plugin_get_value(plug, blank_p);
assert(lilv_nodes_size(blanks) == 1);
- LilvNode* blank = lilv_nodes_get_first(blanks);
+ const LilvNode* blank = lilv_nodes_get_first(blanks);
assert(lilv_node_is_blank(blank));
const char* blank_str = lilv_node_as_blank(blank);
char* blank_tok = lilv_node_get_turtle_token(blank);
diff --git a/test/test.lv2/manifest.ttl.in b/test/test_plugin.lv2/manifest.ttl.in
index bc3952c..48b009b 100644
--- a/test/test.lv2/manifest.ttl.in
+++ b/test/test_plugin.lv2/manifest.ttl.in
@@ -3,5 +3,5 @@
<http://example.org/lilv-test-plugin>
a lv2:Plugin ;
- lv2:binary <test@SHLIB_EXT@> ;
- rdfs:seeAlso <test.ttl> .
+ lv2:binary <test_plugin@SHLIB_EXT@> ;
+ rdfs:seeAlso <test_plugin.ttl> .
diff --git a/test/test_plugin.lv2/meson.build b/test/test_plugin.lv2/meson.build
new file mode 100644
index 0000000..e6c54cf
--- /dev/null
+++ b/test/test_plugin.lv2/meson.build
@@ -0,0 +1,24 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+module = shared_module(
+ 'test_plugin',
+ files('test_plugin.c'),
+ c_args: c_suppressions,
+ dependencies: [lv2_dep, zix_dep],
+ gnu_symbol_visibility: 'hidden',
+ name_prefix: '',
+)
+
+extension = '.' + module.full_path().split('.')[-1]
+config = configuration_data({'SHLIB_EXT': extension})
+ttl_files = ['manifest.ttl', 'test_plugin.ttl']
+
+foreach f : ttl_files
+ configure_file(
+ input: files(f + '.in'),
+ output: f,
+ configuration: config,
+ )
+endforeach
+
diff --git a/test/test.lv2/test.c b/test/test_plugin.lv2/test_plugin.c
index 2be34b4..c8851d4 100644
--- a/test/test.lv2/test.c
+++ b/test/test_plugin.lv2/test_plugin.c
@@ -1,31 +1,12 @@
-/*
- Lilv Test Plugin
- Copyright 2011-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#define _POSIX_C_SOURCE 200809L
-
-#include "lv2/atom/atom.h"
-#include "lv2/core/lv2.h"
-#include "lv2/state/state.h"
-#include "lv2/urid/urid.h"
-
-#ifdef _MSC_VER
-# include <io.h>
-# define mkstemp(pat) _mktemp(pat)
-#endif
+// Copyright 2011-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include <lv2/atom/atom.h>
+#include <lv2/core/lv2.h>
+#include <lv2/state/state.h>
+#include <lv2/urid/urid.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
#include <stdint.h>
#include <stdio.h>
@@ -34,8 +15,6 @@
#define TEST_URI "http://example.org/lilv-test-plugin"
-#define TMP_TEMPLATE "lilv_testXXXXXX"
-
enum { TEST_INPUT = 0, TEST_OUTPUT = 1, TEST_CONTROL = 2 };
typedef struct {
@@ -46,7 +25,7 @@ typedef struct {
LV2_URID atom_Float;
} uris;
- char tmp_file_path[sizeof(TMP_TEMPLATE)];
+ char* tmp_dir_path;
char* rec_file_path;
FILE* rec_file;
@@ -67,6 +46,7 @@ cleanup(LV2_Handle instance)
test->free_path->free_path(test->free_path->handle, test->rec_file_path);
}
+ free(test->tmp_dir_path);
free(instance);
}
@@ -104,8 +84,7 @@ instantiate(const LV2_Descriptor* descriptor,
return NULL;
}
- strncpy(test->tmp_file_path, TMP_TEMPLATE, strlen(TMP_TEMPLATE) + 1);
- mkstemp(test->tmp_file_path);
+ test->tmp_dir_path = zix_temp_directory_path(NULL);
LV2_State_Make_Path* make_path = NULL;
@@ -137,8 +116,9 @@ instantiate(const LV2_Descriptor* descriptor,
test->rec_file_path = make_path->path(make_path->handle, "recfile");
if (!(test->rec_file = fopen(test->rec_file_path, "w"))) {
fprintf(stderr, "ERROR: Failed to open rec file\n");
+ } else {
+ fprintf(test->rec_file, "instantiate\n");
}
- fprintf(test->rec_file, "instantiate\n");
}
return (LV2_Handle)test;
@@ -272,15 +252,26 @@ save(LV2_Handle instance,
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
if (map_path) {
- FILE* file = fopen(plugin->tmp_file_path, "w");
+ const char* const file_name = "temp_file.txt";
+
+ char* const tmp_file_path =
+ zix_path_join(NULL, plugin->tmp_dir_path, file_name);
+
+ FILE* file = fopen(tmp_file_path, "w");
+ if (!file) {
+ fprintf(stderr, "error: Failed to open file %s\n", tmp_file_path);
+ free(tmp_file_path);
+ return LV2_STATE_ERR_UNKNOWN;
+ }
+
fprintf(file, "Hello\n");
fclose(file);
- char* apath =
- map_path->abstract_path(map_path->handle, plugin->tmp_file_path);
- char* apath2 =
- map_path->abstract_path(map_path->handle, plugin->tmp_file_path);
- if (strcmp(apath, apath2)) {
- fprintf(stderr, "ERROR: Path %s != %s\n", apath, apath2);
+
+ char* apath = map_path->abstract_path(map_path->handle, tmp_file_path);
+ char* apath2 = map_path->abstract_path(map_path->handle, tmp_file_path);
+ free(tmp_file_path);
+ if (!!strcmp(apath, apath2)) {
+ fprintf(stderr, "error: Path %s != %s\n", apath, apath2);
}
store(callback_data,
@@ -310,8 +301,10 @@ save(LV2_Handle instance,
if (make_path) {
char* spath = make_path->path(make_path->handle, "save");
FILE* sfile = fopen(spath, "w");
- fprintf(sfile, "save");
- fclose(sfile);
+ if (sfile) {
+ fprintf(sfile, "save");
+ fclose(sfile);
+ }
apath = map_path->abstract_path(map_path->handle, spath);
store(callback_data,
@@ -376,14 +369,16 @@ restore(LV2_Handle instance,
}
if (apath) {
- char* path = map_path->absolute_path(map_path->handle, apath);
- FILE* f = fopen(path, "r");
- char str[8];
- size_t n_read = fread(str, 1, sizeof(str), f);
- fclose(f);
- if (strncmp(str, "Hello\n", n_read)) {
- fprintf(
- stderr, "error: Restored bad file contents `%s' != `Hello'\n", str);
+ char* path = map_path->absolute_path(map_path->handle, apath);
+ FILE* f = fopen(path, "r");
+ if (f) {
+ char str[8] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
+ size_t n_read = fread(str, 1, 6, f);
+ fclose(f);
+
+ if (!!strncmp(str, "Hello\n", n_read)) {
+ fprintf(stderr, "error: Restored bad file `%s' != `Hello'\n", str);
+ }
}
free_path->free_path(free_path->handle, path);
}
@@ -432,10 +427,5 @@ LV2_SYMBOL_EXPORT
const LV2_Descriptor*
lv2_descriptor(uint32_t index)
{
- switch (index) {
- case 0:
- return &descriptor;
- default:
- return NULL;
- }
+ return index ? NULL : &descriptor;
}
diff --git a/test/test.lv2/test.ttl.in b/test/test_plugin.lv2/test_plugin.ttl.in
index 1c16b4c..1c16b4c 100644
--- a/test/test.lv2/test.ttl.in
+++ b/test/test_plugin.lv2/test_plugin.ttl.in
diff --git a/test/test_port.c b/test/test_port.c
index 3ea0abc..ac115a6 100644
--- a/test/test_port.c
+++ b/test/test_port.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <stdbool.h>
@@ -105,8 +92,8 @@ main(void)
lilv_node_free(nopsym);
// Try getting an invalid property
- LilvNode* num = lilv_new_int(world, 1);
- LilvNodes* nothing = lilv_port_get_value(plug, p, num);
+ LilvNode* num = lilv_new_int(world, 1);
+ const LilvNodes* nothing = lilv_port_get_value(plug, p, num);
assert(!nothing);
lilv_node_free(num);
diff --git a/test/test_preset.c b/test/test_preset.c
index 151b0e6..f282097 100644
--- a/test/test_preset.c
+++ b/test/test_preset.c
@@ -1,25 +1,12 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
-#include "lv2/presets/presets.h"
+#include <lilv/lilv.h>
+#include <lv2/presets/presets.h>
#include <assert.h>
diff --git a/test/test_project.c b/test/test_project.c
index 7da42bd..43a23a2 100644
--- a/test/test_project.c
+++ b/test/test_project.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <string.h>
@@ -66,8 +53,8 @@ static const char* const plugin_ttl = "\
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(env, "project.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
return 1;
diff --git a/test/test_project_no_author.c b/test/test_project_no_author.c
index 3ee9c85..44ce728 100644
--- a/test/test_project_no_author.c
+++ b/test/test_project_no_author.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
@@ -60,8 +47,8 @@ static const char* const plugin_ttl = "\
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(
env, "project_no_author.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
@@ -75,13 +62,13 @@ main(void)
const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri);
assert(plug);
- LilvNode* author_name = lilv_plugin_get_author_name(plug);
+ const LilvNode* author_name = lilv_plugin_get_author_name(plug);
assert(!author_name);
- LilvNode* author_email = lilv_plugin_get_author_email(plug);
+ const LilvNode* author_email = lilv_plugin_get_author_email(plug);
assert(!author_email);
- LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug);
+ const LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug);
assert(!author_homepage);
delete_bundle(env);
diff --git a/test/test_prototype.c b/test/test_prototype.c
index 10a3657..3225ffa 100644
--- a/test/test_prototype.c
+++ b/test/test_prototype.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <string.h>
@@ -73,8 +60,8 @@ static const char* const plugin_ttl = "\
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(env, "prototype.lv2", manifest_ttl, plugin_ttl)) {
return 1;
diff --git a/test/test_reload_bundle.c b/test/test_reload_bundle.c
index a8f9044..779adeb 100644
--- a/test/test_reload_bundle.c
+++ b/test/test_reload_bundle.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <string.h>
diff --git a/test/test_replace_version.c b/test/test_replace_version.c
index 7ec5519..4465e3c 100644
--- a/test/test_replace_version.c
+++ b/test/test_replace_version.c
@@ -1,27 +1,12 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "../src/lilv_internal.h"
-
-#include "lilv/lilv.h"
-#include "lv2/core/lv2.h"
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
#include <assert.h>
#include <stdlib.h>
@@ -39,7 +24,7 @@ main(void)
LilvNode* minor = NULL;
LilvNode* micro = NULL;
- char* old_bundle_path = lilv_strjoin(LILV_TEST_DIR, "old_version.lv2/", 0);
+ char* old_bundle_path = string_concat(LILV_TEST_DIR, "old_version.lv2/");
// Load plugin from old bundle
LilvNode* old_bundle = lilv_new_file_uri(world, NULL, old_bundle_path);
@@ -57,7 +42,7 @@ main(void)
lilv_node_free(micro);
lilv_node_free(minor);
- char* new_bundle_path = lilv_strjoin(LILV_TEST_DIR, "new_version.lv2/", 0);
+ char* new_bundle_path = string_concat(LILV_TEST_DIR, "new_version.lv2/");
// Load plugin from new bundle
LilvNode* new_bundle = lilv_new_file_uri(world, NULL, new_bundle_path);
diff --git a/test/test_state.c b/test/test_state.c
index 533c3a9..aeb3f02 100644
--- a/test/test_state.c
+++ b/test/test_state.c
@@ -1,38 +1,19 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_uri_map.h"
#include "lilv_test_utils.h"
-#include "../src/filesystem.h"
-
-#include "lilv/lilv.h"
-#include "lv2/core/lv2.h"
-#include "lv2/state/state.h"
-#include "lv2/urid/urid.h"
-#include "serd/serd.h"
-
-#ifdef _WIN32
-# include <direct.h>
-# define mkdir(path, flags) _mkdir(path)
-#else
-# include <sys/stat.h>
-#endif
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
+#include <lv2/state/state.h>
+#include <lv2/urid/urid.h>
+#include <serd/serd.h>
+#include <zix/allocator.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
#include <assert.h>
#include <stdbool.h>
@@ -128,16 +109,22 @@ create_test_directories(void)
/* On MacOS, temporary directories from mkdtemp involve symlinks, so
resolve it here so that path comparisons in tests work. */
- dirs.top = lilv_path_canonical(top);
- dirs.shared = lilv_path_join(dirs.top, "shared");
- dirs.scratch = lilv_path_join(dirs.shared, "scratch");
- dirs.copy = lilv_path_join(dirs.shared, "copy");
- dirs.link = lilv_path_join(dirs.shared, "link");
+ dirs.top = zix_canonical_path(NULL, top);
+ dirs.shared = zix_path_join(NULL, dirs.top, "shared");
+ dirs.scratch = zix_path_join(NULL, dirs.shared, "scratch");
+ dirs.copy = zix_path_join(NULL, dirs.shared, "copy");
+ dirs.link = zix_path_join(NULL, dirs.shared, "link");
+
+ assert(dirs.top);
+ assert(dirs.shared);
+ assert(dirs.scratch);
+ assert(dirs.copy);
+ assert(dirs.link);
- assert(!mkdir(dirs.shared, 0700));
- assert(!mkdir(dirs.scratch, 0700));
- assert(!mkdir(dirs.copy, 0700));
- assert(!mkdir(dirs.link, 0700));
+ assert(!zix_create_directory(dirs.shared));
+ assert(!zix_create_directory(dirs.scratch));
+ assert(!zix_create_directory(dirs.copy));
+ assert(!zix_create_directory(dirs.link));
free(top);
@@ -157,28 +144,28 @@ remove_file(const char* path, const char* name, void* data)
{
(void)data;
- char* const full_path = lilv_path_join(path, name);
- assert(!lilv_remove(full_path));
+ char* const full_path = zix_path_join(NULL, path, name);
+ assert(!zix_remove(full_path));
free(full_path);
}
static void
cleanup_test_directories(const TestDirectories dirs)
{
- lilv_dir_for_each(dirs.scratch, NULL, remove_file);
- lilv_dir_for_each(dirs.copy, NULL, remove_file);
- lilv_dir_for_each(dirs.link, NULL, remove_file);
-
- assert(!lilv_remove(dirs.link));
- assert(!lilv_remove(dirs.copy));
- assert(!lilv_remove(dirs.scratch));
- assert(!lilv_remove(dirs.shared));
- assert(!lilv_remove(dirs.top));
-
- free(dirs.link);
- free(dirs.copy);
- free(dirs.scratch);
- free(dirs.shared);
+ zix_dir_for_each(dirs.scratch, NULL, remove_file);
+ zix_dir_for_each(dirs.copy, NULL, remove_file);
+ zix_dir_for_each(dirs.link, NULL, remove_file);
+
+ assert(!zix_remove(dirs.link));
+ assert(!zix_remove(dirs.copy));
+ assert(!zix_remove(dirs.scratch));
+ assert(!zix_remove(dirs.shared));
+ assert(!zix_remove(dirs.top));
+
+ zix_free(NULL, dirs.link);
+ zix_free(NULL, dirs.copy);
+ zix_free(NULL, dirs.scratch);
+ zix_free(NULL, dirs.shared);
free(dirs.top);
}
@@ -194,20 +181,24 @@ get_port_value(const char* port_symbol,
*size = sizeof(float);
*type = ctx->atom_Float;
return &ctx->in;
- } else if (!strcmp(port_symbol, "output")) {
+ }
+
+ if (!strcmp(port_symbol, "output")) {
*size = sizeof(float);
*type = ctx->atom_Float;
return &ctx->out;
- } else if (!strcmp(port_symbol, "control")) {
+ }
+
+ if (!strcmp(port_symbol, "control")) {
*size = sizeof(float);
*type = ctx->atom_Float;
return &ctx->control;
- } else {
- fprintf(
- stderr, "error: get_port_value for nonexistent port `%s'\n", port_symbol);
- *size = *type = 0;
- return NULL;
}
+
+ fprintf(
+ stderr, "error: get_port_value for nonexistent port `%s'\n", port_symbol);
+ *size = *type = 0;
+ return NULL;
}
static void
@@ -237,18 +228,16 @@ set_port_value(const char* port_symbol,
static char*
make_scratch_path(LV2_State_Make_Path_Handle handle, const char* path)
{
- TestDirectories* dirs = (TestDirectories*)handle;
+ const TestDirectories* dirs = (TestDirectories*)handle;
- return lilv_path_join(dirs->scratch, path);
+ return zix_path_join(NULL, dirs->scratch, path);
}
static const LilvPlugin*
load_test_plugin(const TestContext* const ctx)
{
LilvWorld* world = ctx->env->world;
- uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(LILV_TEST_BUNDLE);
- SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true);
- LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, LILV_TEST_BUNDLE);
LilvNode* plugin_uri = lilv_new_uri(world, TEST_PLUGIN_URI);
lilv_world_load_bundle(world, bundle_uri);
@@ -258,8 +247,6 @@ load_test_plugin(const TestContext* const ctx)
lilv_node_free(plugin_uri);
lilv_node_free(bundle_uri);
- serd_node_free(&bundle);
- free(abs_bundle);
assert(plugin);
return plugin;
@@ -565,7 +552,8 @@ count_statements(const char* path)
SerdNode uri = serd_node_new_file_uri((const uint8_t*)path, NULL, NULL, true);
- assert(!serd_reader_read_file(reader, uri.buf));
+ assert(uri.buf);
+ assert(!serd_reader_read_file(reader, (const uint8_t*)uri.buf));
serd_node_free(&uri);
serd_reader_free(reader);
@@ -601,11 +589,11 @@ test_to_files(void)
assert(ctx->out == 1.0);
// Check that the test plugin has made its recording scratch file
- char* const recfile_path = lilv_path_join(dirs.scratch, "recfile");
- assert(lilv_path_exists(recfile_path));
+ char* const recfile_path = zix_path_join(NULL, dirs.scratch, "recfile");
+ assert(zix_file_type(recfile_path) == ZIX_FILE_TYPE_REGULAR);
// Get state
- char* const bundle_1_path = lilv_path_join(dirs.top, "state1.lv2");
+ char* const bundle_1_path = zix_path_join(NULL, dirs.top, "state1.lv2");
LilvState* const state_1 =
state_from_instance(plugin, instance, ctx, &dirs, bundle_1_path);
@@ -613,8 +601,8 @@ test_to_files(void)
assert(lilv_state_get_num_properties(state_1) == 10);
// Check that a snapshop of the recfile was created
- char* const recfile_copy_1 = lilv_path_join(dirs.copy, "recfile");
- assert(lilv_path_exists(recfile_copy_1));
+ char* const recfile_copy_1 = zix_path_join(NULL, dirs.copy, "recfile");
+ assert(zix_file_type(recfile_copy_1) == ZIX_FILE_TYPE_REGULAR);
// Save state to a bundle
assert(!lilv_state_save(ctx->env->world,
@@ -626,24 +614,28 @@ test_to_files(void)
"state.ttl"));
// Check that a manifest exists
- char* const manifest_path = lilv_path_join(bundle_1_path, "manifest.ttl");
- assert(lilv_path_exists(manifest_path));
+ char* const manifest_path =
+ zix_path_join(NULL, bundle_1_path, "manifest.ttl");
+ assert(zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR);
// Check that the expected statements are in the manifest file
assert(count_statements(manifest_path) == 3);
// Check that a link to the recfile exists in the saved bundle
- char* const recfile_link_1 = lilv_path_join(bundle_1_path, "recfile");
- assert(lilv_path_exists(recfile_link_1));
+ char* const recfile_link_1 = zix_path_join(NULL, bundle_1_path, "recfile");
+ assert(zix_file_type(recfile_link_1) == ZIX_FILE_TYPE_REGULAR);
+#ifndef _WIN32
+ assert(zix_symlink_type(recfile_link_1) == ZIX_FILE_TYPE_SYMLINK);
+#endif
// Check that link points to the corresponding copy
- assert(lilv_file_equals(recfile_link_1, recfile_copy_1));
+ assert(zix_file_equals(NULL, recfile_link_1, recfile_copy_1));
// Run plugin again to modify recording file data
lilv_instance_run(instance, 2);
// Get updated state
- char* const bundle_2_path = lilv_path_join(dirs.top, "state2.lv2");
+ char* const bundle_2_path = zix_path_join(NULL, dirs.top, "state2.lv2");
LilvState* const state_2 =
state_from_instance(plugin, instance, ctx, &dirs, bundle_2_path);
@@ -657,33 +649,36 @@ test_to_files(void)
"state.ttl"));
// Check that a new snapshop of the recfile was created
- char* const recfile_copy_2 = lilv_path_join(dirs.copy, "recfile.2");
- assert(lilv_path_exists(recfile_copy_2));
+ char* const recfile_copy_2 = zix_path_join(NULL, dirs.copy, "recfile.2");
+ assert(zix_file_type(recfile_copy_2) == ZIX_FILE_TYPE_REGULAR);
// Check that a link to the recfile exists in the updated bundle
- char* const recfile_link_2 = lilv_path_join(bundle_2_path, "recfile");
- assert(lilv_path_exists(recfile_link_2));
+ char* const recfile_link_2 = zix_path_join(NULL, bundle_2_path, "recfile");
+ assert(zix_file_type(recfile_link_2) == ZIX_FILE_TYPE_REGULAR);
+#ifndef _WIN32
+ assert(zix_symlink_type(recfile_link_2) == ZIX_FILE_TYPE_SYMLINK);
+#endif
// Check that link points to the corresponding copy
- assert(lilv_file_equals(recfile_link_2, recfile_copy_2));
+ assert(zix_file_equals(NULL, recfile_link_2, recfile_copy_2));
lilv_instance_free(instance);
- lilv_dir_for_each(bundle_2_path, NULL, remove_file);
- lilv_dir_for_each(bundle_1_path, NULL, remove_file);
- assert(!lilv_remove(bundle_2_path));
- assert(!lilv_remove(bundle_1_path));
+ zix_dir_for_each(bundle_2_path, NULL, remove_file);
+ zix_dir_for_each(bundle_1_path, NULL, remove_file);
+ assert(!zix_remove(bundle_2_path));
+ assert(!zix_remove(bundle_1_path));
cleanup_test_directories(dirs);
- free(recfile_link_2);
- free(recfile_copy_2);
+ zix_free(NULL, recfile_link_2);
+ zix_free(NULL, recfile_copy_2);
lilv_state_free(state_2);
- free(bundle_2_path);
- free(recfile_link_1);
- free(manifest_path);
- free(recfile_copy_1);
+ zix_free(NULL, bundle_2_path);
+ zix_free(NULL, recfile_link_1);
+ zix_free(NULL, manifest_path);
+ zix_free(NULL, recfile_copy_1);
lilv_state_free(state_1);
- free(bundle_1_path);
- free(recfile_path);
+ zix_free(NULL, bundle_1_path);
+ zix_free(NULL, recfile_path);
test_context_free(ctx);
}
@@ -706,7 +701,7 @@ test_multi_save(void)
assert(instance);
// Get state
- char* const bundle_1_path = lilv_path_join(dirs.top, "state1.lv2");
+ char* const bundle_1_path = zix_path_join(NULL, dirs.top, "state1.lv2");
LilvState* const state_1 =
state_from_instance(plugin, instance, ctx, &dirs, bundle_1_path);
@@ -720,12 +715,13 @@ test_multi_save(void)
"state.ttl"));
// Check that a manifest exists
- char* const manifest_path = lilv_path_join(bundle_1_path, "manifest.ttl");
- assert(lilv_path_exists(manifest_path));
+ char* const manifest_path =
+ zix_path_join(NULL, bundle_1_path, "manifest.ttl");
+ assert(zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR);
// Check that the state file exists
- char* const state_path = lilv_path_join(bundle_1_path, "state.ttl");
- assert(lilv_path_exists(state_path));
+ char* const state_path = zix_path_join(NULL, bundle_1_path, "state.ttl");
+ assert(zix_file_type(state_path) == ZIX_FILE_TYPE_REGULAR);
// Check that the expected statements are in the files
assert(count_statements(manifest_path) == 3);
@@ -741,14 +737,14 @@ test_multi_save(void)
"state.ttl"));
// Check that everything is the same
- assert(lilv_path_exists(manifest_path));
- assert(lilv_path_exists(state_path));
+ assert(zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR);
+ assert(zix_file_type(state_path) == ZIX_FILE_TYPE_REGULAR);
assert(count_statements(manifest_path) == 3);
assert(count_statements(state_path) == 21);
lilv_instance_free(instance);
- lilv_dir_for_each(bundle_1_path, NULL, remove_file);
- lilv_remove(bundle_1_path);
+ zix_dir_for_each(bundle_1_path, NULL, remove_file);
+ assert(!zix_remove(bundle_1_path));
cleanup_test_directories(dirs);
free(state_path);
@@ -786,7 +782,7 @@ test_files_round_trip(void)
assert(ctx->out == 1.0);
// Save first state to a bundle
- char* const bundle_1_1_path = lilv_path_join(dirs.top, "state1_1.lv2");
+ char* const bundle_1_1_path = zix_path_join(NULL, dirs.top, "state1_1.lv2");
LilvState* const state_1_1 =
state_from_instance(plugin, instance, ctx, &dirs, bundle_1_1_path);
@@ -799,7 +795,7 @@ test_files_round_trip(void)
"state.ttl"));
// Save first state to another bundle
- char* const bundle_1_2_path = lilv_path_join(dirs.top, "state1_2.lv2");
+ char* const bundle_1_2_path = zix_path_join(NULL, dirs.top, "state1_2.lv2");
LilvState* const state_1_2 =
state_from_instance(plugin, instance, ctx, &dirs, bundle_1_2_path);
@@ -812,8 +808,10 @@ test_files_round_trip(void)
"state.ttl"));
// Load both first state bundles and check that the results are equal
- char* const state_1_1_path = lilv_path_join(bundle_1_1_path, "state.ttl");
- char* const state_1_2_path = lilv_path_join(bundle_1_2_path, "state.ttl");
+ char* const state_1_1_path =
+ zix_path_join(NULL, bundle_1_1_path, "state.ttl");
+ char* const state_1_2_path =
+ zix_path_join(NULL, bundle_1_2_path, "state.ttl");
LilvState* state_1_1_loaded =
lilv_state_new_from_file(ctx->env->world, &ctx->map, NULL, state_1_1_path);
@@ -829,7 +827,7 @@ test_files_round_trip(void)
lilv_instance_run(instance, 2);
// Save updated state to a bundle
- char* const bundle_2_path = lilv_path_join(dirs.top, "state2.lv2");
+ char* const bundle_2_path = zix_path_join(NULL, dirs.top, "state2.lv2");
LilvState* const state_2 =
state_from_instance(plugin, instance, ctx, &dirs, bundle_2_path);
@@ -842,7 +840,7 @@ test_files_round_trip(void)
"state.ttl"));
// Load updated state bundle and check that it differs from the others
- char* const state_2_path = lilv_path_join(bundle_2_path, "state.ttl");
+ char* const state_2_path = zix_path_join(NULL, bundle_2_path, "state.ttl");
LilvState* state_2_loaded =
lilv_state_new_from_file(ctx->env->world, &ctx->map, NULL, state_2_path);
@@ -851,12 +849,12 @@ test_files_round_trip(void)
assert(!lilv_state_equals(state_1_1_loaded, state_2_loaded));
lilv_instance_free(instance);
- lilv_dir_for_each(bundle_1_1_path, NULL, remove_file);
- lilv_dir_for_each(bundle_1_2_path, NULL, remove_file);
- lilv_dir_for_each(bundle_2_path, NULL, remove_file);
- lilv_remove(bundle_1_1_path);
- lilv_remove(bundle_1_2_path);
- lilv_remove(bundle_2_path);
+ zix_dir_for_each(bundle_1_1_path, NULL, remove_file);
+ zix_dir_for_each(bundle_1_2_path, NULL, remove_file);
+ zix_dir_for_each(bundle_2_path, NULL, remove_file);
+ assert(!zix_remove(bundle_1_1_path));
+ assert(!zix_remove(bundle_1_2_path));
+ assert(!zix_remove(bundle_2_path));
cleanup_test_directories(dirs);
lilv_state_free(state_2_loaded);
@@ -904,7 +902,7 @@ test_world_round_trip(void)
assert(ctx->out == 1.0);
// Save state to a bundle
- char* const bundle_path = lilv_path_join(dirs.top, "state.lv2/");
+ char* const bundle_path = zix_path_join(NULL, dirs.top, "state.lv2/");
LilvState* const start_state =
state_from_instance(plugin, instance, ctx, &dirs, bundle_path);
@@ -969,7 +967,7 @@ test_label_round_trip(void)
lilv_state_set_label(state, "Monopoly on violence");
// Save to a bundle
- char* const bundle_path = lilv_path_join(dirs.top, "state.lv2/");
+ char* const bundle_path = zix_path_join(NULL, dirs.top, "state.lv2/");
assert(!lilv_state_save(ctx->env->world,
&ctx->map,
&ctx->unmap,
@@ -979,7 +977,7 @@ test_label_round_trip(void)
"state.ttl"));
// Load bundle and check the label and that the states are equal
- char* const state_path = lilv_path_join(bundle_path, "state.ttl");
+ char* const state_path = zix_path_join(NULL, bundle_path, "state.ttl");
LilvState* const loaded =
lilv_state_new_from_file(ctx->env->world, &ctx->map, NULL, state_path);
@@ -1005,12 +1003,12 @@ test_bad_subject(void)
TestContext* const ctx = test_context_new();
LilvNode* const string = lilv_new_string(ctx->env->world, "Not a URI");
- LilvState* const file_state = lilv_state_new_from_file(
+ const LilvState* const file_state = lilv_state_new_from_file(
ctx->env->world, &ctx->map, string, "/I/do/not/matter");
assert(!file_state);
- LilvState* const world_state =
+ const LilvState* const world_state =
lilv_state_new_from_world(ctx->env->world, &ctx->map, string);
assert(!world_state);
@@ -1020,6 +1018,18 @@ test_bad_subject(void)
}
static void
+test_missing_path(void)
+{
+ TestContext* const ctx = test_context_new();
+ const LilvState* const state = lilv_state_new_from_file(
+ ctx->env->world, &ctx->map, NULL, "/does/not/exist");
+
+ assert(!state);
+
+ test_context_free(ctx);
+}
+
+static void
count_file(const char* path, const char* name, void* data)
{
(void)path;
@@ -1056,7 +1066,7 @@ test_delete(void)
assert(ctx->out == 1.0);
// Save state to a bundle
- char* const bundle_path = lilv_path_join(dirs.top, "state.lv2/");
+ char* const bundle_path = zix_path_join(NULL, dirs.top, "state.lv2/");
LilvState* const state =
state_from_instance(plugin, instance, ctx, &dirs, bundle_path);
@@ -1070,7 +1080,7 @@ test_delete(void)
// Count the number of shared files before doing anything
unsigned n_shared_files_before = 0;
- lilv_dir_for_each(dirs.shared, &n_shared_files_before, count_file);
+ zix_dir_for_each(dirs.shared, &n_shared_files_before, count_file);
lilv_instance_free(instance);
@@ -1079,11 +1089,11 @@ test_delete(void)
// Ensure the number of shared files is the same after deletion
unsigned n_shared_files_after = 0;
- lilv_dir_for_each(dirs.shared, &n_shared_files_after, count_file);
+ zix_dir_for_each(dirs.shared, &n_shared_files_after, count_file);
assert(n_shared_files_before == n_shared_files_after);
// Ensure the state directory has been deleted
- assert(!lilv_path_exists(bundle_path));
+ assert(zix_file_type(bundle_path) == ZIX_FILE_TYPE_NONE);
cleanup_test_directories(dirs);
@@ -1107,6 +1117,7 @@ main(void)
test_world_round_trip();
test_label_round_trip();
test_bad_subject();
+ test_missing_path();
test_delete();
return 0;
diff --git a/test/test_string.c b/test/test_string.c
deleted file mode 100644
index 2d610bb..0000000
--- a/test/test_string.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#define _POSIX_C_SOURCE 200809L /* for setenv */
-
-#undef NDEBUG
-
-#include "../src/lilv_internal.h"
-
-#ifdef _WIN32
-# include <windows.h>
-# define setenv(n, v, r) SetEnvironmentVariable((n), (v))
-# define unsetenv(n) SetEnvironmentVariable((n), NULL)
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-int
-main(void)
-{
-#ifndef _WIN32
- char* s = NULL;
-
- setenv("LILV_TEST_1", "test", 1);
- char* home_foo = lilv_strjoin(getenv("HOME"), "/foo", NULL);
- assert(!strcmp((s = lilv_expand("$LILV_TEST_1")), "test"));
- free(s);
- assert(!strcmp((s = lilv_expand("~")), getenv("HOME")));
- free(s);
- assert(!strcmp((s = lilv_expand("~foo")), "~foo"));
- free(s);
- assert(!strcmp((s = lilv_expand("~/foo")), home_foo));
- free(s);
- assert(!strcmp((s = lilv_expand("$NOT_A_VAR")), "$NOT_A_VAR"));
- free(s);
- free(home_foo);
- unsetenv("LILV_TEST_1");
-#endif
-
- return 0;
-}
diff --git a/test/test_ui.c b/test/test_ui.c
index d14f54f..73b32fe 100644
--- a/test/test_ui.c
+++ b/test/test_ui.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <stdio.h>
diff --git a/test/test_util.c b/test/test_util.c
index 8c8f36a..3063aa7 100644
--- a/test/test_util.c
+++ b/test/test_util.c
@@ -1,67 +1,40 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#define _XOPEN_SOURCE 600 /* for mkstemp */
+// Copyright 2007-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
-#ifdef _WIN32
-# include "lilv_internal.h"
-#endif
+#include "lilv_test_utils.h"
-#include "../src/filesystem.h"
-
-#ifdef _WIN32
-# include <io.h>
-# define mkstemp(pat) _mktemp(pat)
-#endif
+#include <lilv/lilv.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
#include <assert.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
int
main(void)
{
- assert(!lilv_path_canonical(NULL));
+ char* const dir = lilv_create_temporary_directory("lilv_test_util_XXXXXX");
- char a_path[16];
- char b_path[16];
- strncpy(a_path, "copy_a_XXXXXX", sizeof(a_path));
- strncpy(b_path, "copy_b_XXXXXX", sizeof(b_path));
- mkstemp(a_path);
- mkstemp(b_path);
+ char* const a_path = zix_path_join(NULL, dir, "copy_a_XXXXXX");
+ char* const b_path = zix_path_join(NULL, dir, "copy_b_XXXXXX");
- FILE* fa = fopen(a_path, "w");
- FILE* fb = fopen(b_path, "w");
+ FILE* const fa = fopen(a_path, "w");
+ FILE* const fb = fopen(b_path, "w");
+ assert(fa);
+ assert(fb);
fprintf(fa, "AA\n");
fprintf(fb, "AB\n");
- fclose(fa);
fclose(fb);
+ fclose(fa);
- assert(lilv_copy_file("does/not/exist", "copy"));
- assert(lilv_copy_file(a_path, "not/a/dir/copy"));
- assert(!lilv_copy_file(a_path, "copy_c"));
- assert(!lilv_file_equals(a_path, b_path));
- assert(lilv_file_equals(a_path, a_path));
- assert(lilv_file_equals(a_path, "copy_c"));
- assert(!lilv_file_equals("does/not/exist", b_path));
- assert(!lilv_file_equals(a_path, "does/not/exist"));
- assert(!lilv_file_equals("does/not/exist", "/does/not/either"));
+ assert(!zix_remove(a_path));
+ assert(!zix_remove(b_path));
+ assert(!zix_remove(dir));
+ lilv_free(b_path);
+ lilv_free(a_path);
+ lilv_free(dir);
return 0;
}
diff --git a/test/test_value.c b/test/test_value.c
index 8061029..90d167d 100644
--- a/test/test_value.c
+++ b/test/test_value.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <float.h>
@@ -146,7 +133,7 @@ main(void)
assert(!lilv_node_equals(ival, ifval));
lilv_node_free(ifval);
- LilvNode* nil = NULL;
+ const LilvNode* nil = NULL;
assert(!lilv_node_equals(uval, nil));
assert(!lilv_node_equals(nil, uval));
assert(lilv_node_equals(nil, nil));
diff --git a/test/test_verify.c b/test/test_verify.c
index d20712e..55149c5 100644
--- a/test/test_verify.c
+++ b/test/test_verify.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
@@ -36,8 +23,8 @@ static const char* const plugin_ttl = "\
int
main(void)
{
- LilvTestEnv* const env = lilv_test_env_new();
- LilvWorld* const world = env->world;
+ LilvTestEnv* const env = lilv_test_env_new();
+ const LilvWorld* const world = env->world;
if (create_bundle(env, "verify.lv2", SIMPLE_MANIFEST_TTL, plugin_ttl)) {
return 1;
diff --git a/test/test_world.c b/test/test_world.c
index 762907f..29bfeaf 100644
--- a/test/test_world.c
+++ b/test/test_world.c
@@ -1,24 +1,11 @@
-/*
- Copyright 2007-2020 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2007-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "lilv_test_utils.h"
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <assert.h>
#include <stddef.h>
@@ -32,7 +19,7 @@ main(void)
LilvNode* num = lilv_new_int(env->world, 4);
LilvNode* uri = lilv_new_uri(env->world, "http://example.org/object");
- LilvNodes* matches = lilv_world_find_nodes(world, num, NULL, NULL);
+ const LilvNodes* matches = lilv_world_find_nodes(world, num, NULL, NULL);
assert(!matches);
matches = lilv_world_find_nodes(world, NULL, num, NULL);
diff --git a/tools/.clang-tidy b/tools/.clang-tidy
new file mode 100644
index 0000000..406be48
--- /dev/null
+++ b/tools/.clang-tidy
@@ -0,0 +1,15 @@
+# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+Checks: >
+ -*-magic-numbers,
+ -android-cloexec-fopen,
+ -bugprone-narrowing-conversions,
+ -cert-err33-c,
+ -cppcoreguidelines-avoid-non-const-global-variables,
+ -cppcoreguidelines-narrowing-conversions,
+ -hicpp-signed-bitwise,
+ -llvm-header-guard,
+ -misc-no-recursion,
+ -readability-function-cognitive-complexity,
+InheritParentConfig: true
diff --git a/tools/bench.h b/tools/bench.h
new file mode 100644
index 0000000..d87102e
--- /dev/null
+++ b/tools/bench.h
@@ -0,0 +1,38 @@
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+/**
+ @file bench.h A simple real-time benchmarking API.
+*/
+
+#ifndef BENCH_H
+#define BENCH_H
+
+#include <time.h>
+
+typedef struct timespec BenchmarkTime;
+
+static inline double
+bench_elapsed_s(const BenchmarkTime* start, const BenchmarkTime* end)
+{
+ return ((end->tv_sec - start->tv_sec) +
+ ((end->tv_nsec - start->tv_nsec) * 0.000000001));
+}
+
+static inline BenchmarkTime
+bench_start(void)
+{
+ BenchmarkTime start_t;
+ clock_gettime(CLOCK_REALTIME, &start_t);
+ return start_t;
+}
+
+static inline double
+bench_end(const BenchmarkTime* start_t)
+{
+ BenchmarkTime end_t;
+ clock_gettime(CLOCK_REALTIME, &end_t);
+ return bench_elapsed_s(start_t, &end_t);
+}
+
+#endif /* BENCH_H */
diff --git a/utils/lilv.bash_completion b/tools/lilv.bash_completion
index 4a553a7..d5de5e2 100644
--- a/utils/lilv.bash_completion
+++ b/tools/lilv.bash_completion
@@ -1,10 +1,9 @@
-# Bash auto-completion script written for lv2info and lv2jack.
-# Could be adapted to any other program that takes an
-# LV2 plugin URI as parameter.
+# Copyright 2012-2022 David Robillard <d@drobilla.net>
+# Copyright 2009 Lars Luthman <lars.luthman@gmail.com>
+# SPDX-License-Identifier: 0BSD OR ISC
-# Updated for Lilv by David Robillard <d@drobilla.net> on 2012-01-08.
-# Written by Lars Luthman <lars.luthman@gmail.com> on 2009-10-12.
-# No copyright claimed for this script. Do what you want with it.
+# Bash auto-completion script written for lv2info. Could be adapted to any
+# other program that takes an LV2 plugin URI as parameter.
# For some reason Bash splits the command line not only at whitespace
# but also at ':' signs before putting the parts into COMP_WORDS.
@@ -54,6 +53,3 @@ function _lv2info() {
}
complete -F _lv2info lv2info
-
-# And the same for lv2jack.
-complete -F _lv2info lv2jack
diff --git a/utils/lv2apply.c b/tools/lv2apply.c
index e042999..3caf49a 100644
--- a/utils/lv2apply.c
+++ b/tools/lv2apply.c
@@ -1,22 +1,8 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lilv/lilv.h"
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
-#include "lv2/core/lv2.h"
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
#include <math.h>
#include <sndfile.h>
@@ -125,8 +111,7 @@ cleanup(int status, LV2Apply* self)
}
/** Print a fatal error and clean up for exit. */
-LILV_LOG_FUNC(3, 4)
-static int
+LILV_LOG_FUNC(3, 4) static int
fatal(LV2Apply* self, int status, const char* fmt, ...)
{
va_list args;
@@ -219,14 +204,20 @@ print_usage(int status)
fprintf(status ? stderr : stdout,
"Usage: lv2apply [OPTION]... PLUGIN_URI\n"
"Apply an LV2 plugin to an audio file.\n\n"
- " -i IN_FILE Input file\n"
- " -o OUT_FILE Output file\n"
- " -c SYM VAL Control value\n"
- " --help Display this help and exit\n"
- " --version Display version information and exit\n");
+ " -V, --version Display version information and exit\n"
+ " -c SYM VAL Control value\n"
+ " -h, --help Display this help and exit\n"
+ " -i IN_FILE Input file\n"
+ " -o OUT_FILE Output file\n");
return status;
}
+static float*
+alloc_audio_buffer(size_t n_channels)
+{
+ return (float*)calloc(n_channels ? n_channels : 1, sizeof(float));
+}
+
int
main(int argc, char** argv)
{
@@ -236,13 +227,13 @@ main(int argc, char** argv)
/* Parse command line arguments */
const char* plugin_uri = NULL;
for (int i = 1; i < argc; ++i) {
- if (!strcmp(argv[i], "--version")) {
+ if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) {
free(self.params);
print_version();
return 0;
}
- if (!strcmp(argv[i], "--help")) {
+ if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
free(self.params);
return print_usage(0);
}
@@ -258,7 +249,7 @@ main(int argc, char** argv)
self.params =
(Param*)realloc(self.params, ++self.n_params * sizeof(Param));
self.params[self.n_params - 1].sym = argv[++i];
- self.params[self.n_params - 1].value = atof(argv[++i]);
+ self.params[self.n_params - 1].value = strtof(argv[++i], NULL);
} else if (argv[i][0] == '-') {
free(self.params);
return print_usage(1);
@@ -334,8 +325,8 @@ main(int argc, char** argv)
/* Instantiate plugin and connect ports */
const uint32_t n_ports = lilv_plugin_get_num_ports(plugin);
- float in_buf[self.n_audio_in > 0 ? self.n_audio_in : 1];
- float out_buf[self.n_audio_out > 0 ? self.n_audio_out : 1];
+ float* const in_buf = alloc_audio_buffer(self.n_audio_in);
+ float* const out_buf = alloc_audio_buffer(self.n_audio_out);
self.instance = lilv_plugin_instantiate(self.plugin, in_fmt.samplerate, NULL);
for (uint32_t p = 0, i = 0, o = 0; p < n_ports; ++p) {
if (self.ports[p].type == TYPE_CONTROL) {
@@ -356,13 +347,16 @@ main(int argc, char** argv)
read/write from/to sndfile. */
lilv_instance_activate(self.instance);
+ int st = 0;
while (sread(self.in_file, in_fmt.channels, in_buf, self.n_audio_in)) {
lilv_instance_run(self.instance, 1);
if (sf_writef_float(self.out_file, out_buf, 1) != 1) {
- return fatal(&self, 9, "Failed to write to output file\n");
+ st = fatal(&self, 9, "Failed to write to output file\n");
}
}
lilv_instance_deactivate(self.instance);
- return cleanup(0, &self);
+ free(out_buf);
+ free(in_buf);
+ return st ? st : cleanup(0, &self);
}
diff --git a/utils/lv2bench.c b/tools/lv2bench.c
index c355727..21519ed 100644
--- a/utils/lv2bench.c
+++ b/tools/lv2bench.c
@@ -1,30 +1,14 @@
-/*
- Copyright 2012-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#define _POSIX_C_SOURCE 200809L
-
-#include "lilv/lilv.h"
-#include "lv2/atom/atom.h"
-#include "lv2/core/lv2.h"
-#include "lv2/urid/urid.h"
+// Copyright 2012-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "bench.h"
-#include "lilv_config.h"
#include "uri_table.h"
+#include <lilv/lilv.h>
+#include <lv2/atom/atom.h>
+#include <lv2/core/lv2.h>
+#include <lv2/urid/urid.h>
+
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
@@ -60,14 +44,14 @@ print_usage(void)
printf("lv2bench - Benchmark all installed and supported LV2 plugins.\n");
printf("Usage: lv2bench [OPTIONS] [PLUGIN_URI]\n");
printf("\n");
- printf(" -b BLOCK_SIZE Specify block size, in audio frames.\n");
- printf(" -f, --full Full plottable output.\n");
- printf(" -h, --help Display this help and exit.\n");
+ printf(" -V, --version Display version information and exit\n");
+ printf(" -b BLOCK_SIZE Specify block size, in audio frames\n");
+ printf(" -f, --full Full plottable output\n");
+ printf(" -h, --help Display this help and exit\n");
printf(" -n FRAMES Total number of audio frames to process\n");
- printf(" --version Display version information and exit\n");
}
-static double
+static int
bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
{
URITable uri_table;
@@ -79,14 +63,15 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
LV2_Feature unmap_feature = {LV2_URID_UNMAP_URI, &unmap};
const LV2_Feature* features[] = {&map_feature, &unmap_feature, NULL};
- float* const buf = (float*)calloc(block_size * 2, sizeof(float));
- float* const in = buf;
- float* const out = buf + block_size;
+ float* const buf = (float*)calloc(block_size * 2UL, sizeof(float));
if (!buf) {
fprintf(stderr, "Out of memory\n");
- return 0.0;
+ return 1;
}
+ float* const in = buf;
+ float* const out = buf + block_size;
+
const size_t atom_capacity = 1024;
LV2_Atom_Sequence seq_in = {{sizeof(LV2_Atom_Sequence_Body),
@@ -96,8 +81,8 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
LV2_Atom_Sequence* seq_out =
(LV2_Atom_Sequence*)malloc(sizeof(LV2_Atom_Sequence) + atom_capacity);
- const char* uri = lilv_node_as_string(lilv_plugin_get_uri(p));
- LilvNodes* required = lilv_plugin_get_required_features(p);
+ const char* uri = lilv_node_as_string(lilv_plugin_get_uri(p));
+ const LilvNodes* required = lilv_plugin_get_required_features(p);
LILV_FOREACH (nodes, i, required) {
const LilvNode* feature = lilv_nodes_get(required, i);
if (!lilv_node_equals(feature, urid_map)) {
@@ -108,7 +93,7 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
free(seq_out);
free(buf);
uri_table_destroy(&uri_table);
- return 0.0;
+ return 1;
}
}
@@ -120,7 +105,7 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
free(seq_out);
free(buf);
uri_table_destroy(&uri_table);
- return 0.0;
+ return 1;
}
const uint32_t n_ports = lilv_plugin_get_num_ports(p);
@@ -129,7 +114,8 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
float* const controls = (float*)calloc(n_ports, sizeof(float));
lilv_plugin_get_port_ranges_float(p, mins, maxes, controls);
- for (uint32_t index = 0; index < n_ports; ++index) {
+ bool skip_plugin = false;
+ for (uint32_t index = 0; !skip_plugin && index < n_ports; ++index) {
const LilvPort* port = lilv_plugin_get_port_by_index(p, index);
if (lilv_port_is_a(p, port, lv2_ControlPort)) {
if (isnan(controls[index])) {
@@ -153,12 +139,7 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
"<%s> port %u neither input nor output, skipping\n",
uri,
index);
- lilv_instance_free(instance);
- free(seq_out);
- free(buf);
- free(controls);
- uri_table_destroy(&uri_table);
- return 0.0;
+ skip_plugin = true;
}
} else if (lilv_port_is_a(p, port, atom_AtomPort)) {
if (lilv_port_is_a(p, port, lv2_InputPort)) {
@@ -168,44 +149,42 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
}
} else {
fprintf(stderr, "<%s> port %u has unknown type, skipping\n", uri, index);
- lilv_instance_free(instance);
- free(seq_out);
- free(buf);
- free(controls);
- uri_table_destroy(&uri_table);
- return 0.0;
+ skip_plugin = true;
}
}
- lilv_instance_activate(instance);
+ if (!skip_plugin) {
+ lilv_instance_activate(instance);
+
+ struct timespec ts = bench_start();
+
+ for (uint32_t i = 0; i < (sample_count / block_size); ++i) {
+ seq_in.atom.size = sizeof(LV2_Atom_Sequence_Body);
+ seq_in.atom.type = uri_table_map(&uri_table, LV2_ATOM__Sequence);
+ seq_out->atom.size = atom_capacity;
+ seq_out->atom.type = uri_table_map(&uri_table, LV2_ATOM__Chunk);
- struct timespec ts = bench_start();
- for (uint32_t i = 0; i < (sample_count / block_size); ++i) {
- seq_in.atom.size = sizeof(LV2_Atom_Sequence_Body);
- seq_in.atom.type = uri_table_map(&uri_table, LV2_ATOM__Sequence);
- seq_out->atom.size = atom_capacity;
- seq_out->atom.type = uri_table_map(&uri_table, LV2_ATOM__Chunk);
+ lilv_instance_run(instance, block_size);
+ }
+
+ const double elapsed = bench_end(&ts);
+
+ if (full_output) {
+ printf("%u %u ", block_size, sample_count);
+ }
+ printf("%lf %s\n", elapsed, uri);
- lilv_instance_run(instance, block_size);
+ lilv_instance_deactivate(instance);
}
- const double elapsed = bench_end(&ts);
- lilv_instance_deactivate(instance);
- lilv_instance_free(instance);
free(controls);
free(maxes);
free(mins);
+ lilv_instance_free(instance);
free(seq_out);
-
- uri_table_destroy(&uri_table);
-
- if (full_output) {
- printf("%u %u ", block_size, sample_count);
- }
- printf("%lf %s\n", elapsed, uri);
-
free(buf);
- return elapsed;
+ uri_table_destroy(&uri_table);
+ return 0;
}
int
@@ -216,12 +195,12 @@ main(int argc, char** argv)
int a = 1;
for (; a < argc; ++a) {
- if (!strcmp(argv[a], "--version")) {
+ if (!strcmp(argv[a], "-V") || !strcmp(argv[a], "--version")) {
print_version();
return 0;
}
- if (!strcmp(argv[a], "--help")) {
+ if (!strcmp(argv[a], "-h") || !strcmp(argv[a], "--help")) {
print_usage();
return 0;
}
@@ -229,9 +208,15 @@ main(int argc, char** argv)
if (!strcmp(argv[a], "-f")) {
full_output = true;
} else if (!strcmp(argv[a], "-n") && (a + 1 < argc)) {
- sample_count = atoi(argv[++a]);
+ const long l = strtol(argv[++a], NULL, 10);
+ if (l > 0 && l < (1L << 28L)) {
+ sample_count = (uint32_t)l;
+ }
} else if (!strcmp(argv[a], "-b") && (a + 1 < argc)) {
- block_size = atoi(argv[++a]);
+ const long l = strtol(argv[++a], NULL, 10);
+ if (l > 0 && l < 16384) {
+ block_size = (uint32_t)l;
+ }
} else if (argv[a][0] != '-') {
break;
} else {
diff --git a/utils/lv2info.c b/tools/lv2info.c
index 81a3ed4..b56415e 100644
--- a/utils/lv2info.c
+++ b/tools/lv2info.c
@@ -1,26 +1,11 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lilv_config.h"
-
-#include "lilv/lilv.h"
-#include "lv2/core/lv2.h"
-#include "lv2/event/event.h"
-#include "lv2/port-groups/port-groups.h"
-#include "lv2/presets/presets.h"
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include <lilv/lilv.h>
+#include <lv2/core/lv2.h>
+#include <lv2/event/event.h>
+#include <lv2/port-groups/port-groups.h>
+#include <lv2/presets/presets.h>
#include <math.h>
#include <stdbool.h>
@@ -41,9 +26,9 @@ static LilvNode* supports_event_pred = NULL;
static void
print_port(const LilvPlugin* p,
uint32_t index,
- float* mins,
- float* maxes,
- float* defaults)
+ const float* mins,
+ const float* maxes,
+ const float* defaults)
{
const LilvPort* port = lilv_plugin_get_port_by_index(p, index);
@@ -343,10 +328,10 @@ print_usage(void)
{
printf("Usage: lv2info [OPTION]... PLUGIN_URI\n"
"Print information about an installed LV2 plugin.\n\n"
- " -p FILE Write Turtle description of plugin to FILE\n"
- " -m FILE Add record of plugin to manifest FILE\n"
- " --help Display this help and exit\n"
- " --version Display version information and exit\n\n"
+ " -V, --version Display version information and exit\n"
+ " -h, --help Display this help and exit\n"
+ " -m FILE Add record of plugin to manifest FILE\n"
+ " -p FILE Write Turtle description of plugin to FILE\n\n"
"For -p and -m, Turtle files are appended to (not overwritten),\n"
"and @prefix directives are only written if the file was empty.\n"
"This allows several plugins to be added to a single file.\n");
@@ -364,12 +349,12 @@ main(int argc, char** argv)
const char* manifest_file = NULL;
const char* plugin_uri = NULL;
for (int i = 1; i < argc; ++i) {
- if (!strcmp(argv[i], "--version")) {
+ if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) {
print_version();
return 0;
}
- if (!strcmp(argv[i], "--help")) {
+ if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
print_usage();
return 0;
}
diff --git a/utils/lv2ls.c b/tools/lv2ls.c
index 9226b89..27c5ec7 100644
--- a/utils/lv2ls.c
+++ b/tools/lv2ls.c
@@ -1,22 +1,7 @@
-/*
- Copyright 2007-2019 David Robillard <d@drobilla.net>
+// Copyright 2007-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lilv_config.h"
-
-#include "lilv/lilv.h"
+#include <lilv/lilv.h>
#include <stdbool.h>
#include <stdio.h>
@@ -53,9 +38,9 @@ print_usage(void)
printf("Usage: lv2ls [OPTION]...\n");
printf("List all installed LV2 plugins.\n");
printf("\n");
+ printf(" -V, --version Display version information and exit\n");
+ printf(" -h, --help Display this help and exit\n");
printf(" -n, --names Show names instead of URIs\n");
- printf(" --help Display this help and exit\n");
- printf(" --version Display version information and exit\n");
printf("\n");
printf("The environment variable LV2_PATH can be used to control where\n");
printf(
@@ -69,10 +54,10 @@ main(int argc, char** argv)
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--names") || !strcmp(argv[i], "-n")) {
show_names = true;
- } else if (!strcmp(argv[i], "--version")) {
+ } else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) {
print_version();
return 0;
- } else if (!strcmp(argv[i], "--help")) {
+ } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
print_usage();
return 0;
} else {
diff --git a/tools/meson.build b/tools/meson.build
new file mode 100644
index 0000000..199f7d7
--- /dev/null
+++ b/tools/meson.build
@@ -0,0 +1,92 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+tool_args = ['-DLILV_VERSION=@0@'.format(meson.project_version())]
+
+#############################
+# "Basic" (Lilv-Only) Tools #
+#############################
+
+basic_tools = [
+ 'lv2info',
+ 'lv2ls',
+]
+
+foreach tool : basic_tools
+ exe = executable(
+ tool,
+ files(tool + '.c'),
+ c_args: c_suppressions,
+ dependencies: lilv_dep,
+ implicit_include_directories: false,
+ install: true,
+ )
+
+ meson.override_find_program(tool, exe)
+
+ install_man(files('..' / 'doc' / tool + '.1'))
+endforeach
+
+install_data(
+ files('lilv.bash_completion'),
+ install_dir: get_option('sysconfdir') / 'bash_completion.d',
+ rename: 'lilv',
+)
+
+###########################
+# lv2apply (uses sndfile) #
+###########################
+
+sndfile_dep = dependency(
+ 'sndfile',
+ include_type: 'system',
+ required: get_option('tools'),
+ version: '>= 1.0.0',
+)
+
+if sndfile_dep.found()
+ lv2apply = executable(
+ 'lv2apply',
+ files('lv2apply.c'),
+ c_args: c_suppressions,
+ dependencies: [lilv_dep, sndfile_dep],
+ implicit_include_directories: false,
+ install: true,
+ )
+
+ meson.override_find_program('lv2apply', lv2apply)
+
+ install_man(files('..' / 'doc' / 'lv2apply.1'))
+endif
+
+#################################
+# lv2bench (uses clock_gettime) #
+#################################
+
+if host_machine.system() != 'windows'
+ rt_dep = cc.find_library('rt', required: false)
+
+ clock_gettime_code = '''#include <time.h>
+int main(void) { struct timespec t; return clock_gettime(CLOCK_MONOTONIC, &t); }
+'''
+
+ if cc.compiles(
+ clock_gettime_code,
+ args: platform_defines,
+ dependencies: [rt_dep],
+ name: 'clock_gettime',
+ )
+ lv2bench = executable(
+ 'lv2bench',
+ files('lv2bench.c'),
+ c_args: c_suppressions,
+ dependencies: [lilv_dep, rt_dep, sndfile_dep],
+ implicit_include_directories: false,
+ install: true,
+ )
+
+ meson.override_find_program('lv2bench', lv2bench)
+
+ install_man(files('..' / 'doc' / 'lv2bench.1'))
+ endif
+endif
diff --git a/utils/uri_table.h b/tools/uri_table.h
index 5a337a3..9a5a192 100644
--- a/utils/uri_table.h
+++ b/tools/uri_table.h
@@ -1,18 +1,5 @@
-/*
- Copyright 2011-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2011-2019 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
/**
@file uri_table.h A toy URI map/unmap implementation.
@@ -23,7 +10,7 @@
#ifndef URI_TABLE_H
#define URI_TABLE_H
-#include "lv2/urid/urid.h"
+#include <lv2/urid/urid.h>
#include <stdlib.h>
#include <string.h>
diff --git a/utils/bench.h b/utils/bench.h
deleted file mode 100644
index 505631f..0000000
--- a/utils/bench.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- Copyright 2011-2019 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/**
- @file bench.h A simple real-time benchmarking API.
-*/
-
-#ifndef BENCH_H
-#define BENCH_H
-
-#define _POSIX_C_SOURCE 200809L
-
-#include <time.h>
-
-typedef struct timespec BenchmarkTime;
-
-static inline double
-bench_elapsed_s(const BenchmarkTime* start, const BenchmarkTime* end)
-{
- return ((end->tv_sec - start->tv_sec) +
- ((end->tv_nsec - start->tv_nsec) * 0.000000001));
-}
-
-static inline BenchmarkTime
-bench_start(void)
-{
- BenchmarkTime start_t;
- clock_gettime(CLOCK_REALTIME, &start_t);
- return start_t;
-}
-
-static inline double
-bench_end(const BenchmarkTime* start_t)
-{
- BenchmarkTime end_t;
- clock_gettime(CLOCK_REALTIME, &end_t);
- return bench_elapsed_s(start_t, &end_t);
-}
-
-#endif /* BENCH_H */
diff --git a/utils/lilv-bench.c b/utils/lilv-bench.c
deleted file mode 100644
index 56b7fee..0000000
--- a/utils/lilv-bench.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- Copyright 2007-2012 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "lilv/lilv.h"
-
-int
-main(void)
-{
- LilvWorld* world = lilv_world_new();
- lilv_world_load_all(world);
-
- const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
- LILV_FOREACH (plugins, p, plugins) {
- const LilvPlugin* plugin = lilv_plugins_get(plugins, p);
- lilv_plugin_get_class(plugin);
- }
-
- lilv_world_free(world);
-
- return 0;
-}
diff --git a/waf b/waf
deleted file mode 100755
index 887215c..0000000
--- a/waf
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python
-
-# Minimal waf script for projects that include waflib directly
-
-import sys
-import inspect
-import os
-
-try:
- from waflib import Context, Scripting
-except Exception as e:
- sys.stderr.write('error: Failed to import waf (%s)\n' % e)
- if os.path.exists('.git'):
- sys.stderr.write("Are submodules up to date? "
- "Try 'git submodule update --init --recursive'\n")
-
- sys.exit(1)
-
-
-def main():
- script_path = os.path.abspath(inspect.getfile(inspect.getmodule(main)))
- project_path = os.path.dirname(script_path)
- Scripting.waf_entry_point(os.getcwd(), Context.WAFVERSION, project_path)
-
-
-if __name__ == '__main__':
- main()
diff --git a/waflib b/waflib
deleted file mode 160000
-Subproject b600c928b221a001faeab7bd92786d0b25714bc
diff --git a/wscript b/wscript
deleted file mode 100644
index 7005967..0000000
--- a/wscript
+++ /dev/null
@@ -1,633 +0,0 @@
-#!/usr/bin/env python
-
-import glob
-import os
-import shutil
-import sys
-
-from waflib import Build, Options, Logs
-from waflib.extras import autowaf
-
-# Library and package version (UNIX style major, minor, micro)
-# major increment <=> incompatible changes
-# minor increment <=> compatible changes (additions)
-# micro increment <=> no interface changes
-LILV_VERSION = '0.24.13'
-LILV_MAJOR_VERSION = '0'
-
-# Mandatory waf variables
-APPNAME = 'lilv' # Package name for waf dist
-VERSION = LILV_VERSION # Package version for waf dist
-top = '.' # Source directory
-out = 'build' # Build directory
-
-# Release variables
-uri = 'http://drobilla.net/sw/lilv'
-dist_pattern = 'http://download.drobilla.net/lilv-%d.%d.%d.tar.bz2'
-post_tags = ['Hacking', 'LAD', 'LV2', 'Lilv']
-
-tests = [
- 'test_bad_port_index',
- 'test_bad_port_symbol',
- 'test_classes',
- 'test_discovery',
- 'test_filesystem',
- 'test_get_symbol',
- 'test_no_author',
- 'test_no_verify',
- 'test_plugin',
- 'test_port',
- 'test_preset',
- 'test_project',
- 'test_project_no_author',
- 'test_prototype',
- 'test_reload_bundle',
- 'test_replace_version',
- 'test_state',
- 'test_string',
- 'test_ui',
- 'test_util',
- 'test_value',
- 'test_verify',
- 'test_world',
-]
-
-test_plugins = [
- 'bad_syntax',
- 'failed_instantiation',
- 'failed_lib_descriptor',
- 'lib_descriptor',
- 'missing_descriptor',
- 'missing_name',
- 'missing_plugin',
- 'missing_port',
- 'missing_port_name',
- 'new_version',
- 'old_version'
-]
-
-
-def options(ctx):
- ctx.load('compiler_c')
- ctx.load('compiler_cxx')
- ctx.load('python')
- opt = ctx.configuration_options()
- ctx.add_flags(
- opt,
- {'no-utils': 'do not build command line utilities',
- 'no-bindings': 'do not build python bindings',
- 'dyn-manifest': 'build support for dynamic manifests',
- 'no-bash-completion': 'do not install bash completion script',
- 'static': 'build static library',
- 'no-shared': 'do not build shared library',
- 'static-progs': 'build programs as static binaries'})
-
- opt.add_option('--default-lv2-path', type='string', default='',
- dest='default_lv2_path',
- help='default LV2 path to use if LV2_PATH is unset')
-
-
-def configure(conf):
- conf.load('compiler_c', cache=True)
- try:
- conf.load('compiler_cxx', cache=True)
- conf.define('LILV_CXX', True)
- except Exception:
- pass
-
- if not Options.options.no_bindings:
- try:
- conf.load('python', cache=True)
- conf.check_python_version((2, 6, 0))
- conf.env.LILV_PYTHON = 1
- except Exception as e:
- Logs.warn('Failed to configure Python (%s)\n' % e)
-
- conf.load('autowaf', cache=True)
- autowaf.set_c_lang(conf, 'c99')
-
- if conf.env.DOCS:
- conf.load('sphinx')
-
- conf.env.BASH_COMPLETION = not Options.options.no_bash_completion
- conf.env.BUILD_UTILS = not Options.options.no_utils
- conf.env.BUILD_SHARED = not Options.options.no_shared
- conf.env.STATIC_PROGS = Options.options.static_progs
- conf.env.BUILD_STATIC = (Options.options.static or
- Options.options.static_progs)
-
- if not conf.env.BUILD_SHARED and not conf.env.BUILD_STATIC:
- conf.fatal('Neither a shared nor a static build requested')
-
- if Options.options.strict:
- # Check for programs used by lint target
- conf.find_program("flake8", var="FLAKE8", mandatory=False)
- conf.find_program("clang-tidy", var="CLANG_TIDY", mandatory=False)
- conf.find_program("iwyu_tool", var="IWYU_TOOL", mandatory=False)
-
- if Options.options.ultra_strict:
- autowaf.add_compiler_flags(conf.env, '*', {
- 'clang': [
- '-Wno-documentation-unknown-command',
- '-Wno-nullability-extension',
- ]
- })
-
- autowaf.add_compiler_flags(conf.env, 'c', {
- 'clang': [
- '-Wno-cast-align',
- '-Wno-cast-qual',
- '-Wno-double-promotion',
- '-Wno-float-equal',
- '-Wno-format-nonliteral',
- '-Wno-implicit-float-conversion',
- '-Wno-implicit-int-conversion',
- '-Wno-padded',
- '-Wno-reserved-id-macro',
- '-Wno-shorten-64-to-32',
- '-Wno-sign-conversion',
- '-Wno-switch-enum',
- '-Wno-vla',
- ],
- 'gcc': [
- '-Wno-cast-align',
- '-Wno-cast-qual',
- '-Wno-conversion',
- '-Wno-double-promotion',
- '-Wno-float-equal',
- '-Wno-padded',
- '-Wno-stack-protector',
- '-Wno-suggest-attribute=const',
- '-Wno-suggest-attribute=pure',
- '-Wno-switch-enum',
- '-Wno-vla',
- ],
- 'msvc': [
- '/wd4061', # enumerator in switch is not explicitly handled
- '/wd4365', # signed/unsigned mismatch
- '/wd4514', # unreferenced inline function has been removed
- '/wd4774', # format string is not a string literal
- '/wd4820', # padding added after construct
- '/wd4996', # POSIX name for this item is deprecated
- ],
- })
-
- autowaf.add_compiler_flags(conf.env, 'cxx', {
- 'clang': [
- '-Wno-extra-semi',
- ],
- 'gcc': [
- '-Wno-effc++',
- '-Wno-extra-semi',
- '-Wno-pedantic',
- ],
- })
-
- conf.check_pkg('lv2 >= 1.18.0', uselib_store='LV2')
- conf.check_pkg('serd-0 >= 0.30.0', uselib_store='SERD')
- conf.check_pkg('sord-0 >= 0.14.0', uselib_store='SORD')
- conf.check_pkg('sratom-0 >= 0.4.0', uselib_store='SRATOM')
- conf.check_pkg('sndfile >= 1.0.0', uselib_store='SNDFILE', mandatory=False)
-
- defines = ['_POSIX_C_SOURCE=200809L', '_BSD_SOURCE', '_DEFAULT_SOURCE']
- if conf.env.DEST_OS == 'darwin':
- defines += ['_DARWIN_C_SOURCE']
-
- rt_lib = ['rt']
- if conf.env.DEST_OS == 'darwin' or conf.env.DEST_OS == 'win32':
- rt_lib = []
-
- conf.check_function('c', 'lstat',
- header_name = ['sys/stat.h'],
- defines = defines,
- define_name = 'HAVE_LSTAT',
- return_type = 'int',
- arg_types = 'const char*, struct stat*',
- mandatory = False)
-
- conf.check_function('c', 'flock',
- header_name = 'sys/file.h',
- defines = defines,
- define_name = 'HAVE_FLOCK',
- return_type = 'int',
- arg_types = 'int, int',
- mandatory = False)
-
- conf.check_function('c', 'fileno',
- header_name = 'stdio.h',
- defines = defines,
- define_name = 'HAVE_FILENO',
- return_type = 'int',
- arg_types = 'FILE*',
- mandatory = False)
-
- conf.check_function('c', 'clock_gettime',
- header_name = ['sys/time.h', 'time.h'],
- defines = ['_POSIX_C_SOURCE=200809L'],
- define_name = 'HAVE_CLOCK_GETTIME',
- uselib_store = 'CLOCK_GETTIME',
- lib = rt_lib,
- return_type = 'int',
- arg_types = 'clockid_t, struct timespec*',
- mandatory = False)
-
- conf.check_cc(define_name = 'HAVE_LIBDL',
- lib = 'dl',
- mandatory = False)
-
- if Options.options.dyn_manifest:
- conf.define('LILV_DYN_MANIFEST', 1)
-
- lilv_path_sep = ':'
- lilv_dir_sep = '/'
- if conf.env.DEST_OS == 'win32':
- lilv_path_sep = ';'
- lilv_dir_sep = '\\\\'
-
- conf.define('LILV_PATH_SEP', lilv_path_sep)
- conf.define('LILV_DIR_SEP', lilv_dir_sep)
-
- # Set default LV2 path
- lv2_path = Options.options.default_lv2_path
- if lv2_path == '':
- if conf.env.DEST_OS == 'darwin':
- lv2_path = lilv_path_sep.join(['~/Library/Audio/Plug-Ins/LV2',
- '~/.lv2',
- '/usr/local/lib/lv2',
- '/usr/lib/lv2',
- '/Library/Audio/Plug-Ins/LV2'])
- elif conf.env.DEST_OS == 'haiku':
- lv2_path = lilv_path_sep.join(['~/.lv2',
- '/boot/common/add-ons/lv2'])
- elif conf.env.DEST_OS == 'win32':
- lv2_path = lilv_path_sep.join(['%APPDATA%\\\\LV2',
- '%COMMONPROGRAMFILES%\\\\LV2'])
- else:
- libdirname = os.path.basename(conf.env.LIBDIR)
- lv2_path = lilv_path_sep.join(['~/.lv2',
- '/usr/%s/lv2' % libdirname,
- '/usr/local/%s/lv2' % libdirname])
-
- if sys.platform == 'win32':
- lv2_path = lv2_path.replace('%', '%%')
-
- conf.define('LILV_DEFAULT_LV2_PATH', lv2_path)
-
- # Set up environment for building/using as a subproject
- autowaf.set_lib_env(conf, 'lilv', LILV_VERSION,
- include_path=str(conf.path.find_node('include')))
-
- conf.define('LILV_NO_DEFAULT_CONFIG', 1)
-
- autowaf.display_summary(
- conf,
- {'Default LV2_PATH': lv2_path,
- 'Utilities': bool(conf.env.BUILD_UTILS),
- 'Unit tests': bool(conf.env.BUILD_TESTS),
- 'Dynamic manifest support': conf.is_defined('LILV_DYN_MANIFEST'),
- 'Python bindings': bool(conf.env.LILV_PYTHON)})
-
-
-def build_util(bld, name, defines, libs=''):
- obj = bld(features = 'c cprogram',
- source = name + '.c',
- includes = ['.', 'include', './src', './utils'],
- use = 'liblilv',
- uselib = 'SERD SORD SRATOM LV2 ' + libs,
- target = name,
- defines = defines,
- install_path = '${BINDIR}')
- if not bld.env.BUILD_SHARED or bld.env.STATIC_PROGS:
- obj.use = 'liblilv_static'
- if bld.env.STATIC_PROGS:
- if not bld.env.MSVC_COMPILER:
- obj.lib = ['m']
- obj.env.SHLIB_MARKER = obj.env.STLIB_MARKER
- obj.linkflags = ['-static', '-Wl,--start-group']
- return obj
-
-
-def build(bld):
- # C/C++ Headers
- includedir = '${INCLUDEDIR}/lilv-%s/lilv' % LILV_MAJOR_VERSION
- bld.install_files(includedir, bld.path.ant_glob('include/lilv/*.h'))
- bld.install_files(includedir, bld.path.ant_glob('include/lilv/*.hpp'))
-
- lib_source = '''
- src/collections.c
- src/filesystem.c
- src/instance.c
- src/lib.c
- src/node.c
- src/plugin.c
- src/pluginclass.c
- src/port.c
- src/query.c
- src/scalepoint.c
- src/state.c
- src/ui.c
- src/util.c
- src/world.c
- src/zix/tree.c
- '''.split()
-
- lib = []
- libflags = ['-fvisibility=hidden']
- defines = []
- if bld.is_defined('HAVE_LIBDL'):
- lib += ['dl']
- if bld.env.DEST_OS == 'win32':
- lib = []
- if bld.env.MSVC_COMPILER:
- libflags = []
-
- # Pkgconfig file
- autowaf.build_pc(bld, 'LILV', LILV_VERSION, LILV_MAJOR_VERSION, [],
- {'LILV_MAJOR_VERSION': LILV_MAJOR_VERSION,
- 'LILV_PKG_DEPS': 'lv2 serd-0 sord-0 sratom-0',
- 'LILV_PKG_LIBS': ' -l'.join([''] + lib)})
-
- # Shared Library
- if bld.env.BUILD_SHARED:
- obj = bld(features = 'c cshlib',
- export_includes = ['.', 'include'],
- source = lib_source,
- includes = ['.', 'include', './src'],
- name = 'liblilv',
- target = 'lilv-%s' % LILV_MAJOR_VERSION,
- vnum = LILV_VERSION,
- install_path = '${LIBDIR}',
- defines = ['LILV_INTERNAL'],
- cflags = libflags,
- lib = lib,
- uselib = 'SERD SORD SRATOM LV2')
-
- # Static library
- if bld.env.BUILD_STATIC:
- obj = bld(features = 'c cstlib',
- export_includes = ['.', 'include'],
- source = lib_source,
- includes = ['.', 'include', './src'],
- name = 'liblilv_static',
- target = 'lilv-%s' % LILV_MAJOR_VERSION,
- vnum = LILV_VERSION,
- install_path = '${LIBDIR}',
- defines = defines + ['LILV_STATIC', 'LILV_INTERNAL'],
- uselib = 'SERD SORD SRATOM LV2')
-
- # Python bindings
- if bld.env.LILV_PYTHON:
- bld(features = 'subst',
- is_copy = True,
- source = 'bindings/python/lilv.py',
- target = 'lilv.py',
- install_path = '${PYTHONDIR}')
-
- if bld.env.BUILD_TESTS:
- import re
-
- test_libs = lib
- test_cflags = ['']
- test_linkflags = ['']
- if not bld.env.NO_COVERAGE:
- test_cflags += ['--coverage']
- test_linkflags += ['--coverage']
-
- # Copy skeleton LV2 bundle for tests
- for name in ('manifest.ttl', 'lv2core.ttl'):
- bld(features = 'subst',
- is_copy = True,
- source = 'test/core.lv2/' + name,
- target = 'test/test_lv2_path/core.lv2/' + name,
- install_path = None)
-
- # Make a pattern for shared objects without the 'lib' prefix
- module_pattern = re.sub('^lib', '', bld.env.cshlib_PATTERN)
- shlib_ext = module_pattern[module_pattern.rfind('.'):]
-
- for p in ['test'] + test_plugins:
- obj = bld(features = 'c cshlib',
- source = 'test/%s.lv2/%s.c' % (p, p),
- name = p,
- target = 'test/%s.lv2/%s' % (p, p),
- install_path = None,
- defines = defines + ['LILV_STATIC'],
- cflags = test_cflags,
- linkflags = test_linkflags,
- lib = test_libs,
- uselib = 'LV2')
- obj.env.cshlib_PATTERN = module_pattern
-
- for p in test_plugins:
- if not bld.path.find_node('test/%s.lv2/test_%s.c' % (p, p)):
- continue
-
- obj = bld(features = 'c cprogram',
- source = 'test/%s.lv2/test_%s.c' % (p, p),
- target = 'test/test_%s' % p,
- includes = ['.', 'include', './src'],
- use = 'liblilv_profiled',
- install_path = None,
- defines = defines + ['LILV_STATIC'],
- cflags = test_cflags,
- linkflags = test_linkflags,
- lib = test_libs,
- uselib = 'SERD SORD SRATOM LV2')
-
- # Test plugin data files
- for p in ['test'] + test_plugins:
- for i in ['manifest.ttl.in', p + '.ttl.in']:
- bundle = 'test/%s.lv2/' % p
- bld(features = 'subst',
- source = bundle + i,
- target = bundle + i.replace('.in', ''),
- install_path = None,
- SHLIB_EXT = shlib_ext)
-
- # Static profiled library (for unit test code coverage)
- obj = bld(features = 'c cstlib',
- source = lib_source,
- includes = ['.', 'include', './src'],
- name = 'liblilv_profiled',
- target = 'lilv_profiled',
- install_path = None,
- defines = defines + ['LILV_STATIC', 'LILV_INTERNAL'],
- cflags = test_cflags,
- linkflags = test_linkflags,
- lib = test_libs,
- uselib = 'SERD SORD SRATOM LV2')
-
- # Unit test program
- testdir = bld.path.get_bld().make_node('test').abspath()
- bpath = os.path.join(testdir, 'test.lv2')
- bpath = bpath.replace('\\', '/')
- testdir = testdir.replace('\\', '/')
- for test in tests:
- obj = bld(features = 'c cprogram',
- source = ['test/%s.c' % test,
- 'test/lilv_test_utils.c'],
- includes = ['.', 'include', './src'],
- use = 'liblilv_profiled',
- lib = test_libs,
- uselib = 'SERD SORD SRATOM LV2',
- target = 'test/' + test,
- install_path = None,
- defines = (defines +
- ['LILV_STATIC'] +
- ['LILV_TEST_BUNDLE=\"%s/\"' % bpath] +
- ['LILV_TEST_DIR=\"%s/\"' % testdir]),
- cflags = test_cflags,
- linkflags = test_linkflags)
-
- # C++ API test
- if 'COMPILER_CXX' in bld.env:
- obj = bld(features = 'cxx cxxprogram',
- source = 'test/lilv_cxx_test.cpp',
- includes = ['.', 'include', './src'],
- use = 'liblilv_profiled',
- lib = test_libs,
- uselib = 'SERD SORD SRATOM LV2',
- target = 'test/lilv_cxx_test',
- install_path = None,
- defines = ['LILV_STATIC'],
- cxxflags = test_cflags,
- linkflags = test_linkflags)
-
- if bld.env.LILV_PYTHON:
- test_bundle = 'bindings/bindings_test_plugin.lv2/'
-
- # Copy Python unittest files
- for i in ['test_api.py']:
- bld(features = 'subst',
- is_copy = True,
- source = 'bindings/test/python/' + i,
- target = 'bindings/' + i,
- install_path = None)
-
- # Build bindings test plugin
- obj = bld(features = 'c cshlib',
- source = 'bindings/test/bindings_test_plugin.c',
- name = 'bindings_test_plugin',
- target = test_bundle + '/bindings_test_plugin',
- install_path = None,
- defines = defines,
- cflags = test_cflags,
- linkflags = test_linkflags,
- lib = test_libs,
- uselib = 'LV2')
- obj.env.cshlib_PATTERN = module_pattern
-
- # Bindings test plugin data files
- for i in ['manifest.ttl.in', 'bindings_test_plugin.ttl.in']:
- bld(features = 'subst',
- source = 'bindings/test/' + i,
- target = test_bundle + i.replace('.in', ''),
- install_path = None,
- SHLIB_EXT = shlib_ext)
-
- # Utilities
- if bld.env.BUILD_UTILS:
- utils = '''
- utils/lilv-bench
- utils/lv2info
- utils/lv2ls
- '''
- for i in utils.split():
- build_util(bld, i, defines)
-
- if bld.env.HAVE_SNDFILE:
- obj = build_util(bld, 'utils/lv2apply', defines, 'SNDFILE')
-
- # lv2bench (less portable than other utilities)
- if (bld.env.DEST_OS != 'win32' and
- bld.is_defined('HAVE_CLOCK_GETTIME') and
- not bld.env.STATIC_PROGS):
- obj = build_util(bld, 'utils/lv2bench', defines)
- if bld.env.DEST_OS != 'darwin':
- obj.lib = ['rt']
-
- # Documentation
- if bld.env.DOCS:
- bld.recurse('doc/c')
-
- # Man pages
- bld.install_files('${MANDIR}/man1', bld.path.ant_glob('doc/*.1'))
-
- # Bash completion
- if bld.env.BASH_COMPLETION:
- bld.install_as('${SYSCONFDIR}/bash_completion.d/lilv',
- 'utils/lilv.bash_completion')
-
- bld.add_post_fun(autowaf.run_ldconfig)
-
-
-def test(tst):
- with tst.group('unit') as check:
- for test in tests:
- check(['./test/' + test])
-
- if tst.is_defined('LILV_CXX'):
- check(['./test/lilv_cxx_test'])
-
- if tst.env.LILV_PYTHON:
- with tst.group('python') as check:
- check(['python', '-m', 'unittest', 'discover', 'bindings/'])
-
- with tst.group('plugin') as check:
- for p in test_plugins:
- prog_name = tst.env.cprogram_PATTERN % ('test_' + p)
- if os.path.exists(os.path.join('test', prog_name)):
- check(['./test/test_' + p, 'test/%s.lv2/' % p])
-
- try:
- shutil.rmtree('state')
- except Exception:
- pass
-
-
-class LintContext(Build.BuildContext):
- fun = cmd = 'lint'
-
-
-def lint(ctx):
- "checks code for style issues"
- import subprocess
-
- st = 0
-
- if "FLAKE8" in ctx.env:
- Logs.info("Running flake8")
- st = subprocess.call([ctx.env.FLAKE8[0],
- "wscript",
- "--ignore",
- "E101,E129,W191,E221,W504,E251,E241,E741"])
- else:
- Logs.warn("Not running flake8")
-
- if "IWYU_TOOL" in ctx.env:
- Logs.info("Running include-what-you-use")
- cmd = [ctx.env.IWYU_TOOL[0], "-o", "clang", "-p", "build"]
- output = subprocess.check_output(cmd).decode('utf-8')
- if 'error: ' in output:
- sys.stdout.write(output)
- st += 1
- else:
- Logs.warn("Not running include-what-you-use")
-
- if "CLANG_TIDY" in ctx.env and "clang" in ctx.env.CC[0]:
- Logs.info("Running clang-tidy")
- sources = glob.glob('src/*.c') + glob.glob('tests/*.c')
- sources = list(map(os.path.abspath, sources))
- procs = []
- for source in sources:
- cmd = [ctx.env.CLANG_TIDY[0], "--quiet", "-p=.", source]
- procs += [subprocess.Popen(cmd, cwd="build")]
-
- for proc in procs:
- stdout, stderr = proc.communicate()
- st += proc.returncode
- else:
- Logs.warn("Not running clang-tidy")
-
- if st != 0:
- sys.exit(st)