summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy14
-rw-r--r--.gitignore11
-rw-r--r--.gitmodules3
-rw-r--r--.reuse/dep515
-rw-r--r--COPYING16
-rw-r--r--INSTALL59
-rw-r--r--INSTALL.md80
-rw-r--r--LICENSES/0BSD.txt12
l---------LICENSES/ISC.txt1
-rw-r--r--NEWS90
-rw-r--r--PACKAGING49
-rw-r--r--PACKAGING.md34
-rw-r--r--README.md3
-rw-r--r--doc/Doxyfile.in (renamed from doc/c/Doxyfile)11
-rw-r--r--doc/api/meson.build9
-rw-r--r--doc/c/index.rst5
-rw-r--r--doc/c/reference.rst11
-rw-r--r--doc/c/wscript39
-rw-r--r--doc/conf.py.in13
-rw-r--r--doc/html/meson.build32
-rw-r--r--doc/index.rst (renamed from doc/suil.rst)9
-rw-r--r--doc/meson.build77
-rw-r--r--doc/overview.rst (renamed from doc/c/overview.rst)4
-rw-r--r--doc/singlehtml/meson.build33
-rw-r--r--doc/xml/meson.build30
-rw-r--r--include/suil/suil.h108
-rw-r--r--meson.build349
-rw-r--r--meson/suppressions/meson.build157
-rw-r--r--meson_options.txt32
-rwxr-xr-xscripts/dox_to_sphinx.py674
-rw-r--r--src/cocoa_in_gtk2.mm37
-rw-r--r--src/cocoa_in_qt5.mm28
-rw-r--r--src/dylib.h22
-rw-r--r--src/gtk2_in_qt5.cpp170
-rw-r--r--src/host.c19
-rw-r--r--src/instance.c76
-rw-r--r--src/qt5_in_gtk.cpp252
-rw-r--r--src/suil_config.h17
-rw-r--r--src/suil_internal.h49
-rw-r--r--src/warnings.h17
-rw-r--r--src/win_in_gtk2.cpp23
-rw-r--r--src/x11.c19
-rw-r--r--src/x11_in_gtk2.c17
-rw-r--r--src/x11_in_gtk3.c30
-rw-r--r--src/x11_in_qt5.cpp48
-rw-r--r--subprojects/sphinxygen.wrap14
-rw-r--r--suil.pc.in11
-rw-r--r--suil.ttl29
-rwxr-xr-xwaf27
m---------waflib0
-rw-r--r--wscript475
51 files changed, 1200 insertions, 2160 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 1a009ab..92d3c36 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,3 +1,6 @@
+# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
Checks: >
*,
-*-magic-numbers,
@@ -5,23 +8,32 @@ Checks: >
-*-no-malloc,
-*-uppercase-literal-suffix,
-*-vararg,
+ -altera-*,
+ -bugprone-easily-swappable-parameters,
-bugprone-suspicious-string-compare,
+ -cert-err33-c,
-clang-analyzer-core.CallAndMessage,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
+ -concurrency-mt-unsafe,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-cstyle-cast,
+ -cppcoreguidelines-pro-type-reinterpret-cast,
-fuchsia-default-arguments,
-fuchsia-default-arguments-calls,
-google-runtime-int,
-hicpp-signed-bitwise,
-llvm-header-guard,
-llvmlibc-*,
+ -modernize-use-nodiscard,
-modernize-use-trailing-return-type,
+ -performance-no-int-to-ptr,
+ -readability-function-cognitive-complexity,
+ -readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-non-const-parameter,
WarningsAsErrors: '*'
-HeaderFilterRegex: '.*'
+HeaderFilterRegex: ''
FormatStyle: file
diff --git a/.gitignore b/.gitignore
index 204c242..8ac4349 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,9 @@
-build/**
-.waf-*
-.lock-waf*
+# Copyright 2017-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+.meson-subproject-wrap-hash.txt
__pycache__
+build/**
+subprojects/packagecache/
+subprojects/sphinxygen-1.0.4/
+subprojects/sphinxygen/
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..f08dd19
--- /dev/null
+++ b/.reuse/dep5
@@ -0,0 +1,15 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: suil
+Upstream-Contact: David Robillard <d@drobilla.net>
+Source: https://gitlab.com/drobilla/suil
+
+Files: AUTHORS NEWS suil.ttl
+Copyright: 2011-2022 David Robillard <d@drobilla.net>
+Comment: Contributed to the Commons as a representation of simple facts
+License: 0BSD OR ISC
+
+Files: .clant.json .includes.imp
+Copyright: 2020 David Robillard <d@drobilla.net>
+Comment: Contributed to the Commons as a tool configuration
+License: 0BSD OR ISC
+
diff --git a/COPYING b/COPYING
index 51201cb..7923e98 100644
--- a/COPYING
+++ b/COPYING
@@ -1,13 +1,13 @@
-Copyright 2007-2020 David Robillard <d@drobilla.net>
+Copyright 2007-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.
+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 623cddd..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,59 +0,0 @@
-Installation Instructions
-=========================
-
-Basic Installation
-------------------
-
-Building this software requires only Python. To install with default options:
-
- ./waf configure
- ./waf
- ./waf install
-
-You may need to become root for the install stage, for example:
-
- sudo ./waf install
-
-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
-
-Installation Directories
-------------------------
-
-The --prefix option (or the PREFIX environment variable) can be used to change
-the prefix which all files are installed under. There are also several options
-allowing for more fine-tuned control, see the --help output for details.
-
-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
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000..fcba723
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,80 @@
+<!-- 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 and optionally 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.
+ * `CXX`: Path to C++ compiler.
+ * `CXXFLAGS`: 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..7d3e0ca
--- /dev/null
+++ b/LICENSES/0BSD.txt
@@ -0,0 +1,12 @@
+Copyright 2007-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 6179785..6425f79 100644
--- a/NEWS
+++ b/NEWS
@@ -1,17 +1,61 @@
-suil (0.10.11) unstable;
+suil (0.10.21) unstable; urgency=medium
+ * Fix library current_version on MacOS
+
+ -- David Robillard <d@drobilla.net> Thu, 14 Mar 2024 16:54:56 +0000
+
+suil (0.10.20) stable; urgency=medium
+
+ * Allow SUIL_API to be defined by the user
+ * Fix dependencies in pkg-config file
+ * Only check for Gtk Quartz support on MacOS
+ * Override pkg-config dependency within meson
+ * Remove Gtk in Qt and Qt in Gtk wrappers
+ * Remove junk files from documentation install
+ * Replace duplicated dox_to_sphinx script with sphinxygen dependency
+
+ -- David Robillard <d@drobilla.net> Sun, 22 Oct 2023 20:11:10 +0000
+
+suil (0.10.18) stable; urgency=medium
+
+ * Add project metadata
+ * Adopt REUSE machine-readable licensing standard
+ * Fix MacOS build when Gtk3 and Qt5 are present without X11
+ * Fix opening wrapped UIs multiple times in Gtk
+
+ -- David Robillard <d@drobilla.net> Fri, 09 Sep 2022 17:29:12 +0000
+
+suil (0.10.16) stable; urgency=medium
+
+ * Fix wrapper module installation path
+
+ -- David Robillard <d@drobilla.net> Fri, 12 Aug 2022 22:17:10 +0000
+
+suil (0.10.14) stable; urgency=medium
+
+ * Fix MacOS build
+ * Fix documentation install path
+ * Remove dead Qt4 support code
+ * Switch to meson build system
+
+ -- David Robillard <d@drobilla.net> Tue, 19 Jul 2022 01:14:05 +0000
+
+suil (0.10.12) stable; urgency=medium
+
+ * Fix build issues with newer toolchains
+ * Fix some compiler warnings
* Remove Qt4 support
- -- David Robillard <d@drobilla.net> Mon, 11 Jan 2021 03:30:34 +0000
+ -- David Robillard <d@drobilla.net> Fri, 27 May 2022 01:43:47 +0000
-suil (0.10.10) stable;
+suil (0.10.10) stable; urgency=medium
* Clean up minor code issues
* Remove the need for a generated configuration header
-- David Robillard <d@drobilla.net> Thu, 07 Jan 2021 21:40:54 +0000
-suil (0.10.8) stable;
+suil (0.10.8) stable; urgency=medium
* Fix X11 in Gtk size regressions (thanks Robin Gareus)
* Fix compilation on MacOS older than 10.12
@@ -20,21 +64,21 @@ suil (0.10.8) stable;
-- David Robillard <d@drobilla.net> Sun, 27 Sep 2020 12:22:08 +0000
-suil (0.10.6) stable;
+suil (0.10.6) stable; urgency=medium
* Add no-cocoa configure flag
* Update build system
-- David Robillard <d@drobilla.net> Sun, 10 Nov 2019 21:35:59 +0000
-suil (0.10.4) stable;
+suil (0.10.4) stable; urgency=medium
* Add support for Qt5 in Gtk3
* Add support for min/base size hints for X11 in Gtk (thanks Hermann Meyer)
-- David Robillard <d@drobilla.net> Thu, 06 Jun 2019 19:02:47 +0000
-suil (0.10.2) stable;
+suil (0.10.2) stable; urgency=medium
* Add support for Cocoa in Qt5
* Fix resizing and add idle and update rate support for Qt5 in Gtk2
@@ -42,7 +86,7 @@ suil (0.10.2) stable;
-- David Robillard <d@drobilla.net> Thu, 20 Dec 2018 17:22:19 +0000
-suil (0.10.0) stable;
+suil (0.10.0) stable; urgency=medium
* Add suil_init() to support early initialization and passing any necessary
information that may be needed in the future (thanks Stefan Westerfeld)
@@ -54,7 +98,7 @@ suil (0.10.0) stable;
-- David Robillard <d@drobilla.net> Tue, 03 Oct 2017 20:11:49 +0000
-suil (0.8.4) stable;
+suil (0.8.4) stable; urgency=medium
* Add Cocoa in Gtk wrapper (patch from Robin Gareus)
* Add Gtk2 and X11 in Qt5 wrappers (patch from Rui Nuno Capela)
@@ -71,7 +115,7 @@ suil (0.8.4) stable;
-- David Robillard <d@drobilla.net> Tue, 20 Sep 2016 02:47:44 +0000
-suil (0.8.2) stable;
+suil (0.8.2) stable; urgency=medium
* Add configure options to disable all Gtk or Qt support
* Fix embedding several Qt UIs in Gtk
@@ -79,7 +123,7 @@ suil (0.8.2) stable;
-- David Robillard <d@drobilla.net> Fri, 08 Aug 2014 22:18:00 +0000
-suil (0.8.0) stable;
+suil (0.8.0) stable; urgency=medium
* Add suil_instance_get_handle (patch from Rui Nuno Capela)
* Fix compilation errors on some systems
@@ -87,14 +131,14 @@ suil (0.8.0) stable;
-- David Robillard <d@drobilla.net> Sat, 04 Jan 2014 21:06:56 +0000
-suil (0.6.16) stable;
+suil (0.6.16) stable; urgency=medium
* Fix crashes and resizing for X11 in Qt (patch from Rui Nuno Capela)
* Fix suil_instance_extension_data() for UIs with NULL extension_data
-- David Robillard <d@drobilla.net> Tue, 17 Sep 2013 03:48:57 +0000
-suil (0.6.14) stable;
+suil (0.6.14) stable; urgency=medium
* Add support for new LV2 idle interface
* Lower dependency from Gtk 2.24 introduced in 0.6.12
@@ -104,7 +148,7 @@ suil (0.6.14) stable;
-- David Robillard <d@drobilla.net> Fri, 09 Aug 2013 04:16:48 +0000
-suil (0.6.12) stable;
+suil (0.6.12) stable; urgency=medium
* Fix compilation on BSD
* Fix crash when a broken UI returns a NULL descriptor
@@ -112,14 +156,14 @@ suil (0.6.12) stable;
-- David Robillard <d@drobilla.net> Fri, 22 Feb 2013 18:03:48 +0000
-suil (0.6.10) stable;
+suil (0.6.10) stable; urgency=medium
* Downgrade to waf 1.7.5, previous version does not build modules due to
package check breakage in waf 1.7.6
-- David Robillard <d@drobilla.net> Sun, 23 Dec 2012 04:08:06 +0000
-suil (0.6.8) stable;
+suil (0.6.8) stable; urgency=medium
* Fix crash in x11_in_gtk2 when event_filter fires before widget is realized
* Update to waf 1.7.8 and autowaf r90 (install docs to versioned directory)
@@ -128,7 +172,7 @@ suil (0.6.8) stable;
-- David Robillard <d@drobilla.net> Sun, 23 Dec 2012 02:11:23 +0000
-suil (0.6.6) stable;
+suil (0.6.6) stable; urgency=medium
* Disable timestamps in HTML documentation for reproducible build
* Fix embedding Gtk in Qt as a child widget (support reparenting)
@@ -139,14 +183,14 @@ suil (0.6.6) stable;
-- David Robillard <d@drobilla.net> Wed, 14 Nov 2012 16:17:03 +0000
-suil (0.6.4) stable;
+suil (0.6.4) stable; urgency=medium
* Correctly handle resizing for Gtk2 in Qt4
* Improve documentation
-- David Robillard <d@drobilla.net> Mon, 09 Jul 2012 19:11:06 +0000
-suil (0.6.2) stable;
+suil (0.6.2) stable; urgency=medium
* Allow run-time configuration of module directory via environment variable
SUIL_MODULE_DIR
@@ -156,7 +200,7 @@ suil (0.6.2) stable;
-- David Robillard <d@drobilla.net> Fri, 25 May 2012 03:18:18 +0000
-suil (0.6.0) stable;
+suil (0.6.0) stable; urgency=medium
* Add support for embedding X11 UIs (ui:X11UI)
* Support new LV2 UI features automatically if provided by host
@@ -164,20 +208,20 @@ suil (0.6.0) stable;
-- David Robillard <d@drobilla.net> Wed, 18 Apr 2012 23:32:43 +0000
-suil (0.4.4) stable;
+suil (0.4.4) stable; urgency=medium
* Fix embedding Gtk2 Qt4 UIs in Qt4 hosts that do not link to Gtk2
-- David Robillard <d@drobilla.net> Sat, 11 Jun 2011 15:20:11 +0000
-suil (0.4.2) stable;
+suil (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
-suil (0.4.0) stable;
+suil (0.4.0) stable; urgency=medium
* Initial release
diff --git a/PACKAGING b/PACKAGING
deleted file mode 100644
index 735a1c6..0000000
--- a/PACKAGING
+++ /dev/null
@@ -1,49 +0,0 @@
-These are generic guidelines, but please see below for important Suil specific
-information.
-
-This library is designed to allow parallel installation of different major
-versions. To facilitate this, the shared library name, include directory, and
-pkg-config file are suffixed with the major version number of the library.
-
-For example, if this library was named "foo" and at version 1.x.y:
-
-/usr/include/foo-1/foo/foo.h
-/usr/lib/foo-1.so.1.x.y
-/usr/lib/pkgconfig/foo-1.pc
-
-Dependencies check for pkg-config name "foo-1" and will build
-against a compatible version 1, regardless any other installed versions.
-
-*** IMPORTANT GUIDELINES FOR PACKAGERS ***
-
-Packages should follow the same conventions as above, i.e. include the major
-version (and only the major version) in the name of the package. Continuing the
-example above, the package(s) would be named foo-1 and foo-1-dev. This way,
-if/when version 2 comes out, it may be installed at the same time as version 1
-without breaking anything.
-
-Please do not create packages of this library that do not follow these
-guidelines, you will break things and cause unnecessary headaches. Please do
-not use any number as a suffix other than the actual major version number of the
-upstream source package.
-
-Because program and documentation names are not versioned, these should be
-included in separate packages which may replace previous versions, since
-there is little use in having parallel installations of them.
-
-*** IMPORTANT GUIDELINES FOR PACKAGING SUIL ***
-
-The purpose of Suil is to abstract plugin UI toolkits away from host code. To
-achieve this, Suil performs its magic by dynamically loading modules for each
-toolkit. The main Suil library does NOT depend on any toolkit libraries, and
-thus neither should your package. Please package the individual modules
-(e.g. libsuil_gtk2_in_qt4.so) as separate packages, which themselves depend on
-the involved toolkits. These packages should also be versioned as described
-above to support parallel installation.
-
-Please do not make the main Suil package depend on any toolkit package, this
-defeats the purpose of Suil and will severely irritate those who for whatever
-reason do not want a particular toolkit dependency. The main Suil package may
-have a weak dependency (e.g. "recommends") on the individual wrapper modules,
-and it's fine if these are installed by default, but it must be possible to
-install Suil without installing them if the user explicitly wishes to do so.
diff --git a/PACKAGING.md b/PACKAGING.md
new file mode 100644
index 0000000..6b0debb
--- /dev/null
+++ b/PACKAGING.md
@@ -0,0 +1,34 @@
+<!-- Copyright 2011-2022 David Robillard <d@drobilla.net> -->
+<!-- SPDX-License-Identifier: ISC -->
+
+Packaging Suil
+==============
+
+This library is designed to allow parallel installation of different major
+versions. To facilitate this, the shared library name, include directory, and
+pkg-config file are suffixed with the major version number of the library.
+
+Dependencies check for the pkg-config package `suil-0` and will build against a
+compatible version 0, regardless any other installed major versions.
+
+Packages should follow the same conventions as above, that is, include the
+major version (and only the major version) in the name of the package so that
+it can be installed in parallel with future major versions.
+
+Dependencies
+------------
+
+The purpose of Suil is to abstract plugin UI toolkits away from host code. To
+achieve this, Suil dynamically loads modules for the toolkits in use. The main
+Suil library does NOT depend on any toolkit libraries, and its package
+shouldn't either (otherwise, for example, every LV2 host in the distribution
+would depend directly on Gtk and Qt). Individual modules (like
+`libsuil_x11_in_gtk3.so`) should be packaged separately and themselves depend
+on the involved libraries or toolkits. These packages should also be versioned
+as described above to support parallel installation.
+
+Please do not make the main Suil package strongly depend on any toolkit
+package, this defeats the purpose of Suil and will cause problems for users who
+need to avoid a particular toolkit dependency for whatever reason. "Weak" or
+"recommended" dependencies are fine, the important thing is that users are able
+to avoid particular toolkits if they choose.
diff --git a/README.md b/README.md
index bdfc668..2273095 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,6 @@
+<!-- Copyright 2011-2019 David Robillard <d@drobilla.net> -->
+<!-- SPDX-License-Identifier: ISC -->
+
Suil
====
diff --git a/doc/c/Doxyfile b/doc/Doxyfile.in
index ee7a427..0d787bc 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 = Suil
PROJECT_BRIEF = "A library for loading LV2 plugin UIs"
@@ -19,8 +22,10 @@ XML_PROGRAMLISTING = NO
SHOW_FILES = NO
MACRO_EXPANSION = YES
-PREDEFINED = SUIL_API \
+PREDEFINED = SUIL_API
-INPUT = ../../include/suil/suil.h
+RECURSIVE = YES
+STRIP_FROM_PATH = @SUIL_SRCDIR@
+INPUT = @SUIL_SRCDIR@/include
-OUTPUT_DIRECTORY = .
+OUTPUT_DIRECTORY = @DOX_OUTPUT@
diff --git a/doc/api/meson.build b/doc/api/meson.build
new file mode 100644
index 0000000..a5cecf8
--- /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_suil_rst = custom_target(
+ 'suil.rst',
+ command: [sphinxygen, '-f', '@INPUT0@', '@OUTDIR@'],
+ input: doxygen_xml,
+ output: 'suil.rst',
+)
diff --git a/doc/c/index.rst b/doc/c/index.rst
deleted file mode 100644
index b616761..0000000
--- a/doc/c/index.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-.. toctree::
-
- suil
- overview
- reference
diff --git a/doc/c/reference.rst b/doc/c/reference.rst
deleted file mode 100644
index 893bc4f..0000000
--- a/doc/c/reference.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-#############
-API Reference
-#############
-
-This section contains the generated documentation for all symbols in the public
-API.
-
-.. toctree::
-
- api/suil
-
diff --git a/doc/c/wscript b/doc/c/wscript
deleted file mode 100644
index ae074bc..0000000
--- a/doc/c/wscript
+++ /dev/null
@@ -1,39 +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 = [
- ("../suil.rst", "sphinx/suil.rst"),
- ("index.rst", "sphinx/index.rst"),
- ("overview.rst", "sphinx/overview.rst"),
- ("reference.rst", "sphinx/reference.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",
- SERD_VERSION=bld.env.SERD_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/")
-
- # Run Sphinx to generate HTML documentation
- doc_dir = bld.env.DOCDIR + "/suil-%s/" % bld.env.SUIL_MAJOR_VERSION
- bld(features="sphinx",
- sphinx_source=bld.path.get_bld().make_node("sphinx"),
- sphinx_output_format="singlehtml",
- sphinx_options=["-E", "-q", "-t", "singlehtml"],
- install_path=doc_dir + "c/singlehtml/")
diff --git a/doc/conf.py.in b/doc/conf.py.in
index 423bbea..7b6a2db 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -1,9 +1,14 @@
+# Copyright 2020-2023 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: ISC
+
# Project information
-project = "Suil"
-copyright = "2020, David Robillard"
+project = "@SUIL_TITLE@"
+copyright = "2023, David Robillard"
author = "David Robillard"
release = "@SUIL_VERSION@"
+version = "@SUIL_VERSION@"
+desc = "A library for loading LV2 plugin UIs"
# General configuration
@@ -39,7 +44,7 @@ if tags.has("singlehtml"):
html_theme_options = {
"body_max_width": "48em",
"body_min_width": "48em",
- "description": "A library for loading LV2 plugin UIs",
+ "description": desc,
"globaltoc_collapse": False,
"globaltoc_maxdepth": 3,
"logo_name": True,
@@ -54,7 +59,7 @@ else:
html_theme_options = {
"body_max_width": "60em",
"body_min_width": "40em",
- "description": "A library for loading LV2 plugin UIs",
+ "description": desc,
"globaltoc_collapse": True,
"globaltoc_maxdepth": 1,
"logo_name": True,
diff --git a/doc/html/meson.build b/doc/html/meson.build
new file mode 100644
index 0000000..7a41dc5
--- /dev/null
+++ b/doc/html/meson.build
@@ -0,0 +1,32 @@
+# 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_suil_rst, conf_py, sphinx_input],
+ install: true,
+ install_dir: html_dir,
+ output: [
+ 'index.html',
+
+ '_static',
+ 'api',
+ 'genindex.html',
+ 'overview.html',
+ ],
+)
+
+if not meson.is_subproject()
+ summary('HTML', get_option('prefix') / html_dir, section: 'Directories')
+endif
diff --git a/doc/suil.rst b/doc/index.rst
index c5dc5ab..7f81dbd 100644
--- a/doc/suil.rst
+++ b/doc/index.rst
@@ -1,3 +1,7 @@
+..
+ Copyright 2020-2023 David Robillard <d@drobilla.net>
+ SPDX-License-Identifier: ISC
+
####
Suil
####
@@ -12,3 +16,8 @@ a Gtk host can embed a Qt UI without linking against Qt at compile time.
Suil also handles the embedding of native platform UIs (which are recommended) in common toolkits,
for example embedding an X11 UI in a Gtk host.
+
+.. toctree::
+
+ overview
+ api/suil
diff --git a/doc/meson.build b/doc/meson.build
new file mode 100644
index 0000000..4db8c74
--- /dev/null
+++ b/doc/meson.build
@@ -0,0 +1,77 @@
+# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+docdir = get_option('datadir') / 'doc'
+
+#############
+# Reference #
+#############
+
+# 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
+ # Warn if the "official" theme isn't present
+ pymod = import('python')
+ doc_modules = ['sphinx_lv2_theme']
+ py = pymod.find_installation('python3', modules: doc_modules, required: false)
+ if not py.found()
+ warning('Missing sphinx_lv2_theme module, falling back to alabaster')
+ endif
+
+ # Configure conf.py for Sphinx
+ conf_config = configuration_data()
+ conf_config.set('SUIL_SRCDIR', suil_src_root)
+ conf_config.set('SUIL_TITLE', get_option('title'))
+ conf_config.set('SUIL_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')
+ 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 e8d61b1..71937b2 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
+
########
Overview
########
diff --git a/doc/singlehtml/meson.build b/doc/singlehtml/meson.build
new file mode 100644
index 0000000..0398b32
--- /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_suil_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/xml/meson.build b/doc/xml/meson.build
new file mode 100644
index 0000000..e49aeaf
--- /dev/null
+++ b/doc/xml/meson.build
@@ -0,0 +1,30 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+doxygen = find_program('doxygen')
+
+config = configuration_data()
+config.set('SUIL_SRCDIR', suil_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__suil.xml',
+ 'group__suil__callbacks.xml',
+ 'group__suil__host.xml',
+ 'group__suil__instance.xml',
+ 'group__suil__library.xml',
+ 'suil_8h.xml',
+ ],
+)
diff --git a/include/suil/suil.h b/include/suil/suil.h
index ec2ea5e..ba55a91 100644
--- a/include/suil/suil.h
+++ b/include/suil/suil.h
@@ -1,18 +1,5 @@
-/*
- Copyright 2011-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 2011-2017 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
/// @file suil.h Public API for Suil
@@ -24,6 +11,7 @@
#include <stdbool.h>
#include <stdint.h>
+// SUIL_LIB_IMPORT and SUIL_LIB_EXPORT mark the entry points of shared libraries
#ifdef _WIN32
# define SUIL_LIB_IMPORT __declspec(dllimport)
# define SUIL_LIB_EXPORT __declspec(dllexport)
@@ -32,14 +20,15 @@
# define SUIL_LIB_EXPORT __attribute__((visibility("default")))
#endif
-#ifndef SUIL_STATIC
-# ifdef SUIL_INTERNAL
+// SUIL_API exposes symbols in the public API
+#ifndef SUIL_API
+# ifdef SUIL_STATIC
+# define SUIL_API
+# elif defined(SUIL_INTERNAL)
# define SUIL_API SUIL_LIB_EXPORT
# else
# define SUIL_API SUIL_LIB_IMPORT
# endif
-#else
-# define SUIL_API
#endif
#ifdef __cplusplus
@@ -47,27 +36,14 @@ extern "C" {
#endif
/**
- @defgroup suil Suil
+ @defgroup suil Suil C API
@{
*/
/**
- UI host descriptor.
-
- This contains the various functions that a plugin UI may use to communicate
- with the plugin. It is passed to suil_instance_new() to provide these
- functions to the UI.
+ @defgroup suil_callbacks Callbacks
+ @{
*/
-typedef struct SuilHostImpl SuilHost;
-
-/// An instance of an LV2 plugin UI
-typedef struct SuilInstanceImpl SuilInstance;
-
-/// Opaque pointer to a UI handle
-typedef void* SuilHandle;
-
-/// Opaque pointer to a UI widget
-typedef void* SuilWidget;
/**
UI controller.
@@ -112,6 +88,12 @@ typedef void (*SuilTouchFunc)( //
uint32_t port_index,
bool grabbed);
+/**
+ @}
+ @defgroup suil_library Library
+ @{
+*/
+
/// Initialization argument
typedef enum { SUIL_ARG_NONE } SuilArg;
@@ -128,6 +110,37 @@ void
suil_init(int* argc, char*** argv, SuilArg key, ...);
/**
+ Check if suil can wrap a UI type.
+
+ @param host_type_uri The URI of the desired widget type of the host,
+ corresponding to the `type_uri` parameter of suil_instance_new().
+
+ @param ui_type_uri The URI of the UI widget type.
+
+ @return 0 if wrapping is unsupported, otherwise the quality of the wrapping
+ where 1 is the highest quality (direct native embedding with no wrapping)
+ and increasing values are of a progressively lower quality and/or stability.
+*/
+SUIL_API
+unsigned
+suil_ui_supported(const char* host_type_uri, const char* ui_type_uri);
+
+/**
+ @}
+ @defgroup suil_host Host
+ @{
+*/
+
+/**
+ UI host descriptor.
+
+ This contains the various functions that a plugin UI may use to communicate
+ with the plugin. It is passed to suil_instance_new() to provide these
+ functions to the UI.
+*/
+typedef struct SuilHostImpl SuilHost;
+
+/**
Create a new UI host descriptor.
@param write_func Function to send a value to a plugin port.
@@ -159,20 +172,22 @@ void
suil_host_free(SuilHost* host);
/**
- Check if suil can wrap a UI type.
+ @}
+*/
- @param host_type_uri The URI of the desired widget type of the host,
- corresponding to the `type_uri` parameter of suil_instance_new().
+/**
+ @defgroup suil_instance Instance
+ @{
+*/
- @param ui_type_uri The URI of the UI widget type.
+/// An instance of an LV2 plugin UI
+typedef struct SuilInstanceImpl SuilInstance;
- @return 0 if wrapping is unsupported, otherwise the quality of the wrapping
- where 1 is the highest quality (direct native embedding with no wrapping)
- and increasing values are of a progressively lower quality and/or stability.
-*/
-SUIL_API
-unsigned
-suil_ui_supported(const char* host_type_uri, const char* ui_type_uri);
+/// Opaque pointer to a UI handle
+typedef void* SuilHandle;
+
+/// Opaque pointer to a UI widget
+typedef void* SuilWidget;
/**
Instantiate a UI for an LV2 plugin.
@@ -277,6 +292,7 @@ suil_instance_extension_data(SuilInstance* instance, const char* uri);
/**
@}
+ @}
*/
#ifdef __cplusplus
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..3089ce8
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,349 @@
+# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+project(
+ 'suil',
+ ['c', 'cpp'],
+ default_options: [
+ 'b_ndebug=if-release',
+ 'buildtype=release',
+ 'c_std=c99',
+ 'cpp_std=c++14',
+ ],
+ license: 'ISC',
+ meson_version: '>= 0.56.0',
+ version: '0.10.21',
+)
+
+suil_src_root = meson.current_source_dir()
+major_version = meson.project_version().split('.')[0]
+version_suffix = '-@0@'.format(major_version)
+versioned_name = 'suil' + version_suffix
+suil_module_dir = get_option('libdir') / versioned_name
+
+#######################
+# Compilers and Flags #
+#######################
+
+# Load build tools
+pkg = import('pkgconfig')
+cc = meson.get_compiler('c')
+cpp = meson.get_compiler('cpp')
+
+# Enable Objective C support if we're building for MacOS
+if host_machine.system() == 'darwin'
+ add_languages(['objcpp'], native: false)
+ objcpp = meson.get_compiler('objcpp')
+endif
+
+# Set global warning flags
+subdir('meson/suppressions')
+
+##########################
+# Platform Configuration #
+##########################
+
+suil_abs_module_dir = get_option('prefix') / suil_module_dir
+platform_defines = ['-DSUIL_MODULE_DIR="@0@"'.format(suil_abs_module_dir)]
+
+nodelete_c_link_args = cc.get_supported_link_arguments(['-Wl,-z,nodelete'])
+nodelete_cpp_link_args = cpp.get_supported_link_arguments(['-Wl,-z,nodelete'])
+
+# 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
+
+################
+# Dependencies #
+################
+
+dl_dep = cc.find_library('dl', required: false)
+
+lv2_dep = dependency('lv2', fallback: 'lv2', version: '>= 1.18.3')
+
+x11_dep = dependency(
+ 'x11',
+ include_type: 'system',
+ required: get_option('x11'),
+)
+
+gtk2_dep = dependency(
+ 'gtk+-2.0',
+ include_type: 'system',
+ version: '>=2.18.0',
+ required: get_option('gtk2').enabled(),
+)
+
+gtk2_x11_dep = dependency(
+ 'gtk+-x11-2.0',
+ include_type: 'system',
+ required: get_option('gtk2').enabled() and get_option('x11').enabled(),
+)
+
+if host_machine.system() == 'darwin'
+ gtk2_quartz_dep = dependency(
+ 'gtk+-quartz-2.0',
+ include_type: 'system',
+ required: get_option('gtk2').enabled() and get_option('cocoa').enabled(),
+ )
+else
+ gtk2_quartz_dep = disabler()
+endif
+
+gtk3_dep = dependency(
+ 'gtk+-3.0',
+ include_type: 'system',
+ version: '>=3.14.0',
+ required: get_option('gtk3'),
+)
+
+gtk3_x11_dep = dependency(
+ 'gtk+-x11-3.0',
+ include_type: 'system',
+ version: '>=3.14.0',
+ required: get_option('gtk3').enabled() and get_option('x11').enabled(),
+)
+
+qt5_dep = dependency(
+ 'Qt5Widgets',
+ include_type: 'system',
+ version: '>=5.1.0',
+ required: get_option('qt5'),
+)
+
+qt5_x11_dep = dependency(
+ 'Qt5X11Extras',
+ include_type: 'system',
+ version: '>=5.1.0',
+ required: get_option('qt5').enabled() and get_option('x11').enabled(),
+)
+
+if host_machine.system() == 'darwin' and not get_option('cocoa').disabled()
+ objcpp.has_header(
+ 'QMacCocoaViewContainer',
+ dependencies: qt5_dep,
+ required: get_option('qt5').enabled() and get_option('cocoa').enabled(),
+ )
+endif
+
+###########
+# Library #
+###########
+
+include_dirs = include_directories('include')
+c_headers = files('include/suil/suil.h')
+
+sources = files(
+ 'src/host.c',
+ 'src/instance.c',
+)
+
+# Set appropriate arguments for building against the library type
+extra_c_args = []
+if get_option('default_library') == 'static'
+ extra_c_args = ['-DSUIL_STATIC']
+endif
+
+# Build shared and/or static library
+libsuil = library(
+ versioned_name,
+ sources,
+ c_args: c_suppressions + extra_c_args + platform_defines + ['-DSUIL_INTERNAL'],
+ darwin_versions: [major_version + '.0.0', meson.project_version()],
+ dependencies: [dl_dep, lv2_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ soversion: soversion,
+ version: meson.project_version(),
+)
+
+# Declare dependency for internal meson dependants
+suil_dep = declare_dependency(
+ compile_args: extra_c_args,
+ dependencies: [dl_dep],
+ include_directories: include_dirs,
+ link_with: libsuil,
+)
+
+# Generage pkg-config file for external dependants
+pkg.generate(
+ libsuil,
+ description: 'Library for loading and wrapping LV2 plugin UIs',
+ extra_cflags: extra_c_args,
+ filebase: versioned_name,
+ name: 'Suil',
+ requires: ['lv2'],
+ subdirs: [versioned_name],
+ version: meson.project_version(),
+)
+
+# Override pkg-config dependency for internal meson dependants
+meson.override_dependency(versioned_name, suil_dep)
+
+# Install header to a versioned include directory
+install_headers(c_headers, subdir: versioned_name / 'suil')
+
+#####################
+# Host Init Modules #
+#####################
+
+if x11_dep.found()
+ shared_module(
+ 'suil_x11',
+ files('src/x11.c'),
+ c_args: c_suppressions + platform_defines,
+ dependencies: [lv2_dep, x11_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ install_dir: suil_module_dir,
+ )
+endif
+
+###################
+# Wrapper Modules #
+###################
+
+gtk_args = []
+if cc.get_id() == 'clang'
+ gtk_args += [
+ '-Wno-reserved-identifier',
+ ]
+endif
+
+gtk_c_args = cc.get_supported_arguments(gtk_args)
+gtk_cpp_args = cpp.get_supported_arguments(gtk_args)
+
+if gtk2_dep.found() and gtk2_x11_dep.found() and x11_dep.found()
+ shared_module(
+ 'suil_x11_in_gtk2',
+ files('src/x11_in_gtk2.c'),
+ c_args: c_suppressions + gtk_c_args + platform_defines,
+ dependencies: [gtk2_dep, gtk2_x11_dep, lv2_dep, x11_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ install_dir: suil_module_dir,
+ link_args: nodelete_c_link_args,
+ )
+endif
+
+if gtk3_dep.found() and gtk3_x11_dep.found() and x11_dep.found()
+ shared_module(
+ 'suil_x11_in_gtk3',
+ files('src/x11_in_gtk3.c'),
+ c_args: c_suppressions + gtk_c_args + platform_defines,
+ dependencies: [gtk3_dep, gtk3_x11_dep, lv2_dep, x11_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ install_dir: suil_module_dir,
+ link_args: nodelete_c_link_args,
+ )
+endif
+
+if gtk2_dep.found() and gtk2_quartz_dep.found()
+ shared_module(
+ 'suil_cocoa_in_gtk2',
+ files('src/cocoa_in_gtk2.mm'),
+ dependencies: [gtk2_dep, gtk2_quartz_dep, lv2_dep, qt5_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ install_dir: suil_module_dir,
+ objcpp_args: objcpp_suppressions + gtk_cpp_args + platform_defines,
+ )
+endif
+
+if gtk2_dep.found() and host_machine.system() == 'windows'
+ shared_module(
+ 'suil_win_in_gtk2',
+ files('src/win_in_gtk2.cpp'),
+ cpp_args: cpp_suppressions + gtk_cpp_args + platform_defines,
+ dependencies: [gtk2_dep, lv2_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ install_dir: suil_module_dir,
+ link_args: nodelete_cpp_link_args,
+ )
+endif
+
+if qt5_dep.found() and qt5_x11_dep.found()
+ shared_module(
+ 'suil_x11_in_qt5',
+ files('src/x11_in_qt5.cpp'),
+ cpp_args: cpp_suppressions + platform_defines,
+ dependencies: [lv2_dep, qt5_dep, qt5_x11_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ install_dir: suil_module_dir,
+ )
+endif
+
+if host_machine.system() == 'darwin'
+ if qt5_dep.found() and not get_option('cocoa').disabled()
+ cocoa_suppressions = [
+ '-Wno-deprecated-declarations',
+ ]
+
+ shared_module(
+ 'suil_cocoa_in_qt5',
+ files('src/cocoa_in_qt5.mm'),
+ dependencies: [lv2_dep, qt5_dep],
+ gnu_symbol_visibility: 'hidden',
+ include_directories: include_dirs,
+ install: true,
+ install_dir: suil_module_dir,
+ objcpp_args: cocoa_suppressions + objcpp_suppressions + platform_defines,
+ )
+ endif
+endif
+
+#########
+# Tests #
+#########
+
+if get_option('warning_level') == 'everything'
+ # Check release metadata
+ if not meson.is_subproject()
+ autoship = find_program('autoship', required: false)
+ if autoship.found()
+ test('autoship', autoship, args: ['test', suil_src_root], suite: 'data')
+ endif
+ endif
+
+ # Check licensing metadata
+ reuse = find_program('reuse', required: false)
+ if reuse.found()
+ test('REUSE', reuse, args: ['--root', suil_src_root, 'lint'], suite: 'data')
+ endif
+endif
+
+#################
+# Documentation #
+#################
+
+if not get_option('docs').disabled()
+ subdir('doc')
+endif
+
+# Display top-level summary (augmented in subdirectories)
+if not meson.is_subproject()
+ summary(
+ {
+ 'Install prefix': get_option('prefix'),
+ 'Headers': get_option('prefix') / get_option('includedir'),
+ 'Libraries': get_option('prefix') / get_option('libdir'),
+ },
+ section: 'Directories',
+ )
+endif
diff --git a/meson/suppressions/meson.build b/meson/suppressions/meson.build
new file mode 100644
index 0000000..87af4d6
--- /dev/null
+++ b/meson/suppressions/meson.build
@@ -0,0 +1,157 @@
+# Copyright 2020-2023 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+# Project-specific warning suppressions
+
+warning_level = get_option('warning_level')
+
+#####
+# C #
+#####
+
+if is_variable('cc')
+ c_suppressions = []
+
+ if cc.get_id() in ['clang', 'emscripten']
+ if warning_level == 'everything'
+ c_suppressions += [
+ '-Wno-atomic-implicit-seq-cst',
+ '-Wno-cast-function-type-strict',
+ '-Wno-cast-qual',
+ '-Wno-declaration-after-statement',
+ '-Wno-disabled-macro-expansion',
+ '-Wno-padded',
+ '-Wno-reserved-id-macro',
+ '-Wno-unsafe-buffer-usage',
+ '-Wno-variadic-macros',
+ ]
+
+ if not meson.is_cross_build()
+ c_suppressions += [
+ '-Wno-poison-system-directories',
+ ]
+ endif
+ endif
+
+ if host_machine.system() == 'windows'
+ c_suppressions += [
+ '-Wno-deprecated-declarations',
+ '-Wno-nonportable-system-include-path',
+ ]
+ endif
+
+ elif cc.get_id() == 'gcc'
+ if warning_level == 'everything'
+ c_suppressions += [
+ '-Wno-padded',
+ '-Wno-suggest-attribute=const',
+ '-Wno-suggest-attribute=pure',
+ ]
+ endif
+
+ elif cc.get_id() == 'msvc'
+ c_suppressions += [
+ '/experimental:external',
+ '/external:W0',
+ '/external:anglebrackets',
+ ]
+
+ if warning_level == 'everything'
+ c_suppressions += [
+ '/wd4191', # unsafe function conversion
+ '/wd4514', # unreferenced inline function has been removed
+ '/wd4710', # function not inlined
+ '/wd4820', # padding added after construct
+ '/wd5045', # will insert Spectre mitigation for memory load
+ ]
+ endif
+
+ if warning_level in ['everything', '3', '2']
+ c_suppressions += [
+ '/wd4996', # function or variable may be unsafe
+ ]
+ endif
+ endif
+
+ c_suppressions = cc.get_supported_arguments(c_suppressions)
+endif
+
+#######
+# C++ #
+#######
+
+if is_variable('cpp')
+ cpp_suppressions = []
+
+ if cpp.get_id() in ['clang', 'emscripten']
+ if warning_level == 'everything'
+ cpp_suppressions += [
+ '-Wno-atomic-implicit-seq-cst',
+ '-Wno-c++98-compat',
+ '-Wno-c++98-compat-pedantic',
+ '-Wno-cast-function-type-strict',
+ '-Wno-cast-qual',
+ '-Wno-disabled-macro-expansion',
+ '-Wno-old-style-cast',
+ '-Wno-padded',
+ '-Wno-reserved-id-macro',
+ '-Wno-unsafe-buffer-usage',
+ '-Wno-variadic-macros',
+ '-Wno-zero-as-null-pointer-constant',
+ ]
+ endif
+ elif cpp.get_id() == 'gcc'
+ if warning_level == 'everything'
+ cpp_suppressions += [
+ '-Wno-arith-conversion',
+ '-Wno-cast-qual',
+ '-Wno-padded',
+ '-Wno-suggest-attribute=const',
+ '-Wno-suggest-attribute=pure',
+ '-Wno-useless-cast',
+ '-Wno-volatile',
+ ]
+ endif
+ endif
+
+ cpp_suppressions = cpp.get_supported_arguments(cpp_suppressions)
+endif
+
+#################
+# Objective C++ #
+#################
+
+if is_variable('objcpp')
+ objcpp_suppressions = []
+
+ if objcpp.get_id() in ['clang', 'emscripten']
+ if warning_level == 'everything'
+ objcpp_suppressions += [
+ '-Wno-c++98-compat-pedantic',
+ '-Wno-deprecated-declarations',
+ '-Wno-old-style-cast',
+ '-Wno-padded',
+ '-Wno-reserved-id-macro',
+ '-Wno-weak-vtables',
+ '-Wno-zero-as-null-pointer-constant',
+ ]
+
+ if not meson.is_cross_build()
+ objcpp_suppressions += [
+ '-Wno-poison-system-directories',
+ ]
+ endif
+ endif
+
+ elif objcpp.get_id() == 'gcc'
+ if warning_level == 'everything'
+ objcpp_suppressions = (
+ gcc_common_warnings + [
+ '-Wno-direct-ivar-access',
+ ]
+ )
+ endif
+ endif
+
+ objcpp_suppressions = objcpp.get_supported_arguments(objcpp_suppressions)
+endif
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..b468923
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,32 @@
+# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+option('cocoa', type: 'feature', value: 'auto', yield: true,
+ description : 'Build Cocoa wrappers')
+
+option('docs', type: 'feature', value: 'auto', yield: true,
+ description: 'Build documentation')
+
+option('gtk2', type: 'feature', value: 'auto', yield: true,
+ description : 'Build Gtk2 wrappers')
+
+option('gtk3', type: 'feature', value: 'auto', yield: true,
+ description : 'Build Gtk3 wrappers')
+
+option('html', type: 'feature', value: 'auto', yield: true,
+ description: 'Build paginated HTML documentation')
+
+option('qt5', type: 'feature', value: 'auto', yield: true,
+ description : 'Build Qt5 wrappers')
+
+option('singlehtml', type: 'feature', value: 'auto', yield: true,
+ description: 'Build single-page HTML documentation')
+
+option('tests', type: 'feature', value: 'auto', yield: true,
+ description: 'Build tests')
+
+option('title', type: 'string', value: 'Suil',
+ description: 'Project title')
+
+option('x11', type: 'feature', value: 'auto', yield: true,
+ description : 'Build X11 wrappers')
diff --git a/scripts/dox_to_sphinx.py b/scripts/dox_to_sphinx.py
deleted file mode 100755
index c9d401c..0000000
--- a/scripts/dox_to_sphinx.py
+++ /dev/null
@@ -1,674 +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))
-
- 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\n%s\n%s\n\n" % (line 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 == "computeroutput":
- # assert len(node) == 0 FIXME
- 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])
- )
-
- 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])
-
-
-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"
- markup += indent(record["briefdescription"], 1)
- markup += indent(record["detaileddescription"], 1)
-
- 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"
- 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)
- markup += "\n"
-
- 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_symbols(index, lang, symbol_dir, force):
- """Write a description file for every symbol documented in the index."""
-
- for record in index.values():
- if (
- record["kind"] in ["group", "namespace"]
- or "parent" in record
- and index[record["parent"]]["kind"] != "group"
- ):
- continue
-
- name = record["name"]
- filename = os.path.join(symbol_dir, symbol_filename("%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(local_name(name), 3))
- rst.write(document_markup(index, lang, record))
-
-
-def emit_groups(index, output_dir, symbol_dir_name, 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"], 2))
-
- # Get all child group and symbol names
- group_names = []
- symbol_names = []
- for child_id in record["children"]:
- child = index[child_id]
- if child["kind"] == "group":
- group_names += [child["name"]]
- else:
- symbol_names += [child["name"]]
-
- # Emit description (document body)
- rst.write(record["briefdescription"] + "\n\n")
- rst.write(record["detaileddescription"] + "\n\n")
-
- # Emit TOC
- rst.write(".. toctree::\n")
-
- # Emit groups at the top of the TOC
- for group_name in group_names:
- rst.write("\n" + indent(group_name, 1))
-
- # Emit symbols in sorted order
- for symbol_name in sorted(symbol_names):
- path = "/".join(
- [symbol_dir_name, symbol_filename(symbol_name)]
- )
- rst.write("\n" + indent(path, 1))
-
- rst.write("\n")
-
-
-def run(index_xml_path, output_dir, symbol_dir_name, 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)
-
- # Emit output files
- symbol_dir = os.path.join(output_dir, symbol_dir_name)
- os.makedirs(symbol_dir, exist_ok=True)
- emit_symbols(index, language, symbol_dir, force)
- emit_groups(index, output_dir, symbol_dir_name, 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(
- "-s",
- "--symbol-dir-name",
- default="symbols",
- help="name for subdirectory of symbol documentation files",
- )
-
- 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/cocoa_in_gtk2.mm b/src/cocoa_in_gtk2.mm
index 0bf9fe7..8a505ed 100644
--- a/src/cocoa_in_gtk2.mm
+++ b/src/cocoa_in_gtk2.mm
@@ -1,19 +1,6 @@
-/*
- Copyright 2011-2017 David Robillard <d@drobilla.net>
- Copyright 2014 Robin Gareus <robin@gareus.org>
-
- 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-2022 David Robillard <d@drobilla.net>
+// Copyright 2014 Robin Gareus <robin@gareus.org>
+// SPDX-License-Identifier: ISC
#include "suil_internal.h"
#include "warnings.h"
@@ -132,10 +119,13 @@ suil_cocoa_size_request(GtkWidget* widget, GtkRequisition* requisition)
requisition->width = self->req_width;
requisition->height = self->req_height;
} else {
- NSView* view = (NSView*)self->instance->ui_widget;
- NSRect frame = [view frame];
- requisition->width = CGRectGetWidth(NSRectToCGRect(frame));
- requisition->height = CGRectGetHeight(NSRectToCGRect(frame));
+ NSView* view = (NSView*)self->instance->ui_widget;
+ NSRect frame = [view frame];
+
+ requisition->width =
+ static_cast<int>(CGRectGetWidth(NSRectToCGRect(frame)));
+ requisition->height =
+ static_cast<int>(CGRectGetHeight(NSRectToCGRect(frame)));
}
}
@@ -286,6 +276,8 @@ suil_cocoa_wrapper_idle(void* data)
static GdkFilterReturn
event_filter(GdkXEvent* xevent, GdkEvent* event, gpointer data)
{
+ (void)event;
+
SuilCocoaWrapper* wrap = (SuilCocoaWrapper*)data;
if (!wrap->instance || !wrap->wrapper || !wrap->wrapper->impl) {
return GDK_FILTER_CONTINUE;
@@ -382,6 +374,9 @@ suil_wrapper_new(SuilHost* host,
LV2_Feature*** features,
unsigned n_features)
{
+ (void)host;
+ (void)host_type_uri;
+
GtkWidget* parent = NULL;
for (unsigned i = 0; i < n_features; ++i) {
if (!strcmp((*features)[i]->URI, LV2_UI__parent)) {
@@ -435,7 +430,7 @@ suil_wrapper_new(SuilHost* host,
LV2_URID ui_updateRate = map->map(map->handle, LV2_UI__updateRate);
for (LV2_Options_Option* o = options; o->key; ++o) {
if (o->key == ui_updateRate) {
- wrap->idle_ms = 1000.0f / *(const float*)o->value;
+ wrap->idle_ms = static_cast<guint>(1000.0f / *(const float*)o->value);
break;
}
}
diff --git a/src/cocoa_in_qt5.mm b/src/cocoa_in_qt5.mm
index 9006c08..e0ac4e6 100644
--- a/src/cocoa_in_qt5.mm
+++ b/src/cocoa_in_qt5.mm
@@ -1,18 +1,5 @@
-/*
- Copyright 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 2011-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "suil_config.h"
#include "suil_internal.h"
@@ -51,8 +38,8 @@ public:
NSView* view = (NSView*)instance->ui_widget;
setCocoaView((NSView*)instance->ui_widget);
- setMinimumWidth([view fittingSize].width);
- setMinimumHeight([view fittingSize].height);
+ setMinimumWidth(static_cast<int>([view fittingSize].width));
+ setMinimumHeight(static_cast<int>([view fittingSize].height));
if (_idle_iface && _ui_timer == 0) {
_ui_timer = this->startTimer(30);
@@ -60,7 +47,7 @@ public:
}
protected:
- void timerEvent(QTimerEvent* event)
+ void timerEvent(QTimerEvent* event) override
{
if (event->timerId() == _ui_timer && _idle_iface) {
_idle_iface->idle(_instance->handle);
@@ -69,7 +56,7 @@ protected:
QWidget::timerEvent(event);
}
- void closeEvent(QCloseEvent* event)
+ void closeEvent(QCloseEvent* event) override
{
if (_ui_timer && _idle_iface) {
this->killTimer(_ui_timer);
@@ -133,6 +120,9 @@ suil_wrapper_new(SuilHost* host,
LV2_Feature*** features,
unsigned n_features)
{
+ (void)host;
+ (void)host_type_uri;
+
QWidget* parent = NULL;
for (unsigned i = 0; i < n_features; ++i) {
if (!strcmp((*features)[i]->URI, LV2_UI__parent)) {
diff --git a/src/dylib.h b/src/dylib.h
index 3ea98ef..ac8bfbc 100644
--- a/src/dylib.h
+++ b/src/dylib.h
@@ -1,18 +1,5 @@
-/*
- 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-2023 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef SUIL_DYLIB_H
#define SUIL_DYLIB_H
@@ -24,12 +11,13 @@
enum DylibFlags {
DYLIB_GLOBAL = 0,
DYLIB_LAZY = 1,
- DYLIB_NOW = 2,
+ DYLIB_NOW = 2
};
static inline void*
dylib_open(const char* const filename, const int flags)
{
+ (void)flags;
return LoadLibrary(filename);
}
@@ -52,7 +40,7 @@ dylib_error(void)
enum DylibFlags {
DYLIB_GLOBAL = RTLD_GLOBAL,
DYLIB_LAZY = RTLD_LAZY,
- DYLIB_NOW = RTLD_NOW,
+ DYLIB_NOW = RTLD_NOW
};
static inline void*
diff --git a/src/gtk2_in_qt5.cpp b/src/gtk2_in_qt5.cpp
deleted file mode 100644
index a5c98f1..0000000
--- a/src/gtk2_in_qt5.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- Copyright 2011-2015 David Robillard <d@drobilla.net>
- Copyright 2015 Rui Nuno Capela <rncbc@rncbc.org>
-
- 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 "dylib.h"
-#include "suil_config.h" // IWYU pragma: keep
-#include "suil_internal.h"
-#include "warnings.h"
-
-#include "lv2/core/lv2.h"
-#include "suil/suil.h"
-
-SUIL_DISABLE_QT_WARNINGS
-#include <QVBoxLayout>
-#include <QWidget>
-#include <QWindow>
-#include <Qt>
-#include <QtGui>
-SUIL_RESTORE_WARNINGS
-
-#undef signals
-
-SUIL_DISABLE_GTK_WARNINGS
-#include <gdk/gdk.h>
-#include <glib-object.h>
-#include <glib.h>
-#include <gobject/gclosure.h>
-#include <gtk/gtk.h>
-SUIL_RESTORE_WARNINGS
-
-#include <cstdlib>
-
-extern "C" {
-
-struct SuilGtk2InQt5Wrapper {
- QWidget* host_widget;
- QWindow* window;
- GtkWidget* plug;
-};
-
-static void
-on_size_request(GtkWidget*, GtkRequisition* requisition, gpointer user_data)
-{
- auto* const wrap = static_cast<QWidget*>(user_data);
- wrap->setMinimumSize(requisition->width, requisition->height);
-}
-
-static void
-on_size_allocate(GtkWidget*, GdkRectangle* allocation, gpointer user_data)
-{
- auto* const wrap = static_cast<QWidget*>(user_data);
- wrap->resize(allocation->width, allocation->height);
-}
-
-static void
-wrapper_free(SuilWrapper* wrapper)
-{
- auto* impl = static_cast<SuilGtk2InQt5Wrapper*>(wrapper->impl);
-
- if (impl->window) {
- impl->window->setParent(nullptr);
- delete impl->window;
- }
-
- if (impl->plug) {
- gtk_widget_destroy(impl->plug);
- }
-
- delete impl->host_widget;
-
- free(impl);
-}
-
-static int
-wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance)
-{
- auto* const impl = static_cast<SuilGtk2InQt5Wrapper*>(wrapper->impl);
- auto* const wrap = new QWidget(nullptr, Qt::Window);
- GtkWidget* const plug = gtk_plug_new(0);
- auto* const widget = static_cast<GtkWidget*>(instance->ui_widget);
-
- gtk_container_add(GTK_CONTAINER(plug), widget);
- gtk_widget_show_all(plug);
-
- const WId wid =
- static_cast<WId>(gtk_plug_get_id(reinterpret_cast<GtkPlug*>(plug)));
-
- QWindow* window = QWindow::fromWinId(wid);
- QWidget* container =
- QWidget::createWindowContainer(window, wrap, Qt::WindowFlags());
-
- auto* layout = new QVBoxLayout();
- layout->setMargin(0);
- layout->setSpacing(0);
- layout->addWidget(container, 0, Qt::Alignment());
- wrap->setLayout(layout);
-
-#ifdef SUIL_OLD_GTK
- wrap->resize(widget->allocation.width, widget->allocation.height);
-#else
- GtkAllocation alloc;
- gtk_widget_get_allocation(widget, &alloc);
- wrap->resize(alloc.width, alloc.height);
-#endif
-
- g_signal_connect(
- G_OBJECT(plug), "size-request", G_CALLBACK(on_size_request), wrap);
-
- g_signal_connect(
- G_OBJECT(plug), "size-allocate", G_CALLBACK(on_size_allocate), wrap);
-
- impl->host_widget = wrap;
- impl->window = window;
- impl->plug = plug;
- instance->host_widget = wrap;
-
- return 0;
-}
-
-SUIL_LIB_EXPORT
-SuilWrapper*
-suil_wrapper_new(SuilHost* host,
- const char*,
- const char*,
- LV2_Feature***,
- unsigned)
-{
- /* We have to open libgtk here, so Gtk type symbols are present and will be
- found by the introspection stuff. This is required at least to make
- GtkBuilder use in UIs work, otherwise they will cause "Invalid object
- type" errors.
- */
- if (!host->gtk_lib) {
- dylib_error();
- host->gtk_lib = dylib_open(SUIL_GTK2_LIB_NAME, DYLIB_LAZY | DYLIB_GLOBAL);
- if (!host->gtk_lib) {
- SUIL_ERRORF(
- "Failed to open %s (%s)\n", SUIL_GTK2_LIB_NAME, dylib_error());
- return nullptr;
- }
-
- gtk_init(nullptr, nullptr);
- }
-
- /* Create wrapper implementation. */
- auto* const impl =
- static_cast<SuilGtk2InQt5Wrapper*>(calloc(1, sizeof(SuilGtk2InQt5Wrapper)));
-
- auto* wrapper = static_cast<SuilWrapper*>(calloc(1, sizeof(SuilWrapper)));
- wrapper->wrap = wrapper_wrap;
- wrapper->free = wrapper_free;
- wrapper->impl = impl;
-
- return wrapper;
-}
-
-} // extern "C"
diff --git a/src/host.c b/src/host.c
index 1e64160..d53b8c3 100644
--- a/src/host.c
+++ b/src/host.c
@@ -1,19 +1,6 @@
-/*
- Copyright 2011-2017 David Robillard <d@drobilla.net>
- Copyright 2017 Stefan Westerfeld <stefan@space.twc.de>
-
- 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-2021 David Robillard <d@drobilla.net>
+// Copyright 2017 Stefan Westerfeld <stefan@space.twc.de>
+// SPDX-License-Identifier: ISC
#include "dylib.h"
#include "suil_config.h"
diff --git a/src/instance.c b/src/instance.c
index 05357b2..441176c 100644
--- a/src/instance.c
+++ b/src/instance.c
@@ -1,18 +1,5 @@
-/*
- 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-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "dylib.h"
#include "suil_internal.h"
@@ -29,7 +16,6 @@
#define GTK2_UI_URI LV2_UI__GtkUI
#define GTK3_UI_URI LV2_UI__Gtk3UI
-#define QT4_UI_URI LV2_UI__Qt4UI
#define QT5_UI_URI LV2_UI__Qt5UI
#define X11_UI_URI LV2_UI__X11UI
#define WIN_UI_URI LV2_UI_PREFIX "WindowsUI"
@@ -50,29 +36,14 @@ suil_ui_supported(const char* host_type_uri, const char* ui_type_uri)
}
if ((!strcmp(host_type_uri, GTK2_UI_URI) &&
- !strcmp(ui_type_uri, QT4_UI_URI)) ||
- (!strcmp(host_type_uri, GTK2_UI_URI) &&
- !strcmp(ui_type_uri, QT5_UI_URI)) ||
- (!strcmp(host_type_uri, QT4_UI_URI) &&
- !strcmp(ui_type_uri, GTK2_UI_URI)) ||
- (!strcmp(host_type_uri, QT5_UI_URI) &&
- !strcmp(ui_type_uri, GTK2_UI_URI)) ||
- (!strcmp(host_type_uri, GTK2_UI_URI) &&
- !strcmp(ui_type_uri, X11_UI_URI)) ||
- (!strcmp(host_type_uri, GTK3_UI_URI) &&
- !strcmp(ui_type_uri, X11_UI_URI)) ||
+ (!strcmp(ui_type_uri, COCOA_UI_URI) ||
+ !strcmp(ui_type_uri, WIN_UI_URI) ||
+ !strcmp(ui_type_uri, X11_UI_URI))) ||
(!strcmp(host_type_uri, GTK3_UI_URI) &&
- !strcmp(ui_type_uri, QT5_UI_URI)) ||
- (!strcmp(host_type_uri, GTK2_UI_URI) &&
- !strcmp(ui_type_uri, WIN_UI_URI)) ||
- (!strcmp(host_type_uri, GTK2_UI_URI) &&
- !strcmp(ui_type_uri, COCOA_UI_URI)) ||
- (!strcmp(host_type_uri, QT4_UI_URI) &&
!strcmp(ui_type_uri, X11_UI_URI)) ||
(!strcmp(host_type_uri, QT5_UI_URI) &&
- !strcmp(ui_type_uri, X11_UI_URI)) ||
- (!strcmp(host_type_uri, QT5_UI_URI) &&
- !strcmp(ui_type_uri, COCOA_UI_URI))) {
+ (!strcmp(ui_type_uri, COCOA_UI_URI) ||
+ !strcmp(ui_type_uri, X11_UI_URI)))) {
return SUIL_WRAPPING_EMBEDDED;
}
@@ -88,29 +59,6 @@ open_wrapper(SuilHost* host,
{
const char* module_name = NULL;
- if (!strcmp(container_type_uri, QT4_UI_URI) &&
- !strcmp(ui_type_uri, GTK2_UI_URI)) {
- module_name = "suil_gtk2_in_qt4";
- }
-
-
- if (!strcmp(container_type_uri, QT5_UI_URI) &&
- !strcmp(ui_type_uri, GTK2_UI_URI)) {
- module_name = "suil_gtk2_in_qt5";
- }
-
-
- if (!strcmp(container_type_uri, GTK2_UI_URI) &&
- !strcmp(ui_type_uri, QT4_UI_URI)) {
- module_name = "suil_qt4_in_gtk2";
- }
-
-
- if (!strcmp(container_type_uri, GTK2_UI_URI) &&
- !strcmp(ui_type_uri, QT5_UI_URI)) {
- module_name = "suil_qt5_in_gtk2";
- }
-
if (!strcmp(container_type_uri, GTK2_UI_URI) &&
!strcmp(ui_type_uri, X11_UI_URI)) {
module_name = "suil_x11_in_gtk2";
@@ -121,11 +69,6 @@ open_wrapper(SuilHost* host,
module_name = "suil_x11_in_gtk3";
}
- if (!strcmp(container_type_uri, GTK3_UI_URI) &&
- !strcmp(ui_type_uri, QT5_UI_URI)) {
- module_name = "suil_qt5_in_gtk3";
- }
-
if (!strcmp(container_type_uri, GTK2_UI_URI) &&
!strcmp(ui_type_uri, WIN_UI_URI)) {
module_name = "suil_win_in_gtk2";
@@ -136,11 +79,6 @@ open_wrapper(SuilHost* host,
module_name = "suil_cocoa_in_gtk2";
}
- if (!strcmp(container_type_uri, QT4_UI_URI) &&
- !strcmp(ui_type_uri, X11_UI_URI)) {
- module_name = "suil_x11_in_qt4";
- }
-
if (!strcmp(container_type_uri, QT5_UI_URI) &&
!strcmp(ui_type_uri, X11_UI_URI)) {
module_name = "suil_x11_in_qt5";
diff --git a/src/qt5_in_gtk.cpp b/src/qt5_in_gtk.cpp
deleted file mode 100644
index 6277daa..0000000
--- a/src/qt5_in_gtk.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- Copyright 2011-2017 David Robillard <d@drobilla.net>
- Copyright 2018 Rui Nuno Capela <rncbc@rncbc.org>
-
- 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 "suil_internal.h"
-#include "warnings.h"
-
-#include "lv2/core/lv2.h"
-#include "lv2/options/options.h"
-#include "lv2/ui/ui.h"
-#include "lv2/urid/urid.h"
-#include "suil/suil.h"
-
-SUIL_DISABLE_QT_WARNINGS
-#include <QVBoxLayout>
-#include <QWidget>
-#include <QWindow>
-#include <Qt>
-#include <QtGui>
-SUIL_RESTORE_WARNINGS
-
-#undef signals
-
-SUIL_DISABLE_GTK_WARNINGS
-
-#include <glib-object.h>
-#include <glib.h>
-#include <gobject/gclosure.h>
-#include <gtk/gtk.h>
-
-#if GTK_MAJOR_VERSION == 3
-# include <gtk/gtkx.h>
-#endif
-
-SUIL_RESTORE_WARNINGS
-
-#include <cstdlib>
-#include <cstring>
-
-extern "C" {
-
-struct SuilQtWrapper {
- GtkSocket socket;
- QWidget* qembed;
- SuilWrapper* wrapper;
- SuilInstance* instance;
- const LV2UI_Idle_Interface* idle_iface;
- guint idle_id;
- guint idle_ms;
-};
-
-struct SuilQtWrapperClass {
- GtkSocketClass parent_class;
-};
-
-GType
-suil_qt_wrapper_get_type(void); // Accessor for SUIL_TYPE_QT_WRAPPER
-
-#define SUIL_TYPE_QT_WRAPPER (suil_qt_wrapper_get_type())
-#define SUIL_QT_WRAPPER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_QT_WRAPPER, SuilQtWrapper))
-
-G_DEFINE_TYPE(SuilQtWrapper, suil_qt_wrapper, GTK_TYPE_SOCKET)
-
-static void
-suil_qt_wrapper_finalize(GObject* gobject)
-{
- SuilQtWrapper* const self = SUIL_QT_WRAPPER(gobject);
-
- if (self->idle_id) {
- g_source_remove(self->idle_id);
- self->idle_id = 0;
- }
-
- if (self->instance->handle) {
- self->instance->descriptor->cleanup(self->instance->handle);
- self->instance->handle = nullptr;
- }
-
- if (self->qembed) {
- self->qembed->deleteLater();
- }
-
- self->qembed = nullptr;
- self->idle_iface = nullptr;
- self->wrapper->impl = nullptr;
-
- G_OBJECT_CLASS(suil_qt_wrapper_parent_class)->finalize(gobject);
-}
-
-static void
-suil_qt_wrapper_class_init(SuilQtWrapperClass* klass)
-{
- GObjectClass* const gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = suil_qt_wrapper_finalize;
-}
-
-static void
-suil_qt_wrapper_init(SuilQtWrapper* self)
-{
- self->qembed = nullptr;
- self->wrapper = nullptr;
- self->instance = nullptr;
- self->idle_iface = nullptr;
- self->idle_id = 0;
- self->idle_ms = 1000 / 30; // 30 Hz default
-}
-
-static void
-suil_qt_wrapper_realize(GtkWidget* w, gpointer)
-{
- SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(w);
- GtkSocket* const s = GTK_SOCKET(w);
- const WId id = static_cast<WId>(gtk_socket_get_id(s));
-
- wrap->qembed->winId();
- wrap->qembed->windowHandle()->setParent(QWindow::fromWinId(id));
- wrap->qembed->show();
-}
-
-static int
-suil_qt_wrapper_resize(LV2UI_Feature_Handle handle, int width, int height)
-{
- gtk_widget_set_size_request(GTK_WIDGET(handle), width, height);
-
- return 0;
-}
-
-static gboolean
-suil_qt_wrapper_idle(void* data)
-{
- SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(data);
-
- if (wrap->idle_iface) {
- wrap->idle_iface->idle(wrap->instance->handle);
- return TRUE; // Continue calling
- }
-
- return FALSE;
-}
-
-static int
-wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance)
-{
- SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl);
-
- wrap->qembed = new QWidget(nullptr, Qt::WindowFlags());
- wrap->wrapper = wrapper;
- wrap->instance = instance;
-
- auto* qwidget = static_cast<QWidget*>(instance->ui_widget);
- auto* layout = new QVBoxLayout();
- layout->setMargin(0);
- layout->setSpacing(0);
- layout->addWidget(qwidget, 0, Qt::Alignment());
-
- wrap->qembed->setLayout(layout);
-
- g_signal_connect_after(
- G_OBJECT(wrap), "realize", G_CALLBACK(suil_qt_wrapper_realize), nullptr);
-
- instance->host_widget = GTK_WIDGET(wrap);
-
- const LV2UI_Idle_Interface* idle_iface = nullptr;
- if (instance->descriptor->extension_data) {
- idle_iface = static_cast<const LV2UI_Idle_Interface*>(
- instance->descriptor->extension_data(LV2_UI__idleInterface));
- }
-
- if (idle_iface) {
- wrap->idle_iface = idle_iface;
- wrap->idle_id = g_timeout_add(wrap->idle_ms, suil_qt_wrapper_idle, wrap);
- }
-
- return 0;
-}
-
-static void
-wrapper_free(SuilWrapper* wrapper)
-{
- if (wrapper->impl) {
- SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl);
- gtk_widget_destroy(GTK_WIDGET(wrap));
- }
-}
-
-SUIL_LIB_EXPORT
-SuilWrapper*
-suil_wrapper_new(SuilHost*,
- const char*,
- const char*,
- LV2_Feature*** features,
- unsigned n_features)
-{
- auto* wrapper = static_cast<SuilWrapper*>(calloc(1, sizeof(SuilWrapper)));
- wrapper->wrap = wrapper_wrap;
- wrapper->free = wrapper_free;
-
- SuilQtWrapper* const wrap =
- SUIL_QT_WRAPPER(g_object_new(SUIL_TYPE_QT_WRAPPER, nullptr));
-
- wrap->wrapper = nullptr;
- wrapper->impl = wrap;
-
- wrapper->resize.handle = wrap;
- wrapper->resize.ui_resize = suil_qt_wrapper_resize;
-
- suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize);
- suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr);
-
- // Scan for URID map and options
- LV2_URID_Map* map = nullptr;
- LV2_Options_Option* options = nullptr;
- for (LV2_Feature** f = *features; *f && (!map || !options); ++f) {
- if (!strcmp((*f)->URI, LV2_OPTIONS__options)) {
- options = static_cast<LV2_Options_Option*>((*f)->data);
- } else if (!strcmp((*f)->URI, LV2_URID__map)) {
- map = static_cast<LV2_URID_Map*>((*f)->data);
- }
- }
-
- if (map && options) {
- // Set UI update rate if given
- LV2_URID ui_updateRate = map->map(map->handle, LV2_UI__updateRate);
- for (LV2_Options_Option* o = options; o->key; ++o) {
- if (o->key == ui_updateRate) {
- wrap->idle_ms =
- static_cast<guint>(1000.0f / *static_cast<const float*>(o->value));
-
- break;
- }
- }
- }
-
- return wrapper;
-}
-
-} // extern "C"
diff --git a/src/suil_config.h b/src/suil_config.h
index d4a740c..ce0fe33 100644
--- a/src/suil_config.h
+++ b/src/suil_config.h
@@ -1,18 +1,5 @@
-/*
- 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.
-*/
+// Copyright 2021 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
/*
Configuration header that defines reasonable defaults at compile time.
diff --git a/src/suil_internal.h b/src/suil_internal.h
index 0a7ed92..753bfb1 100644
--- a/src/suil_internal.h
+++ b/src/suil_internal.h
@@ -1,18 +1,5 @@
-/*
- 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-2023 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef SUIL_INTERNAL_H
#define SUIL_INTERNAL_H
@@ -108,21 +95,25 @@ suil_host_init(void);
static inline void*
suil_open_module(const char* module_name)
{
+#define N_SLICES 4
+
const char* const env_dir = getenv("SUIL_MODULE_DIR");
const char* const mod_dir = env_dir ? env_dir : SUIL_MODULE_DIR;
- const size_t path_len =
- strlen(mod_dir) + strlen(SUIL_DIR_SEP SUIL_MODULE_PREFIX SUIL_MODULE_EXT) +
- strlen(module_name) + 2;
-
- char* const path = (char*)calloc(path_len, 1);
- snprintf(path,
- path_len,
- "%s%s%s%s%s",
- mod_dir,
- SUIL_DIR_SEP,
- SUIL_MODULE_PREFIX,
- module_name,
- SUIL_MODULE_EXT);
+
+ const char* const slices[N_SLICES] = {
+ mod_dir, SUIL_DIR_SEP SUIL_MODULE_PREFIX, module_name, SUIL_MODULE_EXT};
+
+ const size_t lengths[N_SLICES] = {
+ strlen(slices[0]), strlen(slices[1]), strlen(slices[2]), strlen(slices[3])};
+
+ const size_t path_len = lengths[0] + lengths[1] + lengths[2] + lengths[3];
+ char* const path = (char*)calloc(path_len + 1, 1);
+
+ size_t offset = 0;
+ for (size_t i = 0; i < N_SLICES; ++i) {
+ memcpy(path + offset, slices[i], lengths[i]);
+ offset += lengths[i];
+ }
dylib_error();
void* lib = dylib_open(path, DYLIB_NOW);
@@ -132,6 +123,8 @@ suil_open_module(const char* module_name)
free(path);
return lib;
+
+#undef N_SLICES
}
typedef void (*SuilVoidFunc)(void);
diff --git a/src/warnings.h b/src/warnings.h
index b7a03aa..0622397 100644
--- a/src/warnings.h
+++ b/src/warnings.h
@@ -1,18 +1,5 @@
-/*
- 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.
-*/
+// Copyright 2021 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#ifndef SUIL_WARNINGS_H
#define SUIL_WARNINGS_H
diff --git a/src/win_in_gtk2.cpp b/src/win_in_gtk2.cpp
index 14b82e8..9c295e2 100644
--- a/src/win_in_gtk2.cpp
+++ b/src/win_in_gtk2.cpp
@@ -1,18 +1,5 @@
-/*
- Copyright 2011-2015 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
+// Copyright 2011-2021 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "suil_internal.h"
#include "warnings.h"
@@ -40,9 +27,6 @@ extern "C" {
#define SUIL_WIN_WRAPPER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_WIN_WRAPPER, SuilWinWrapper))
-using SuilWinWrapper = _SuilWinWrapper;
-using SuilWinWrapperClass = _SuilWinWrapperClass;
-
struct _SuilWinWrapper {
GtkDrawingArea area;
SuilWrapper* wrapper;
@@ -57,6 +41,9 @@ struct _SuilWinWrapperClass {
GtkDrawingAreaClass parent_class;
};
+using SuilWinWrapper = _SuilWinWrapper;
+using SuilWinWrapperClass = _SuilWinWrapperClass;
+
GType
suil_win_wrapper_get_type(void); // Accessor for SUIL_TYPE_WIN_WRAPPER
diff --git a/src/x11.c b/src/x11.c
index 0580817..40e3289 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -1,19 +1,6 @@
-/*
- Copyright 2017 David Robillard <d@drobilla.net>
- Copyright 2017 Stefan Westerfeld <stefan@space.twc.de>
-
- 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 2017-2021 David Robillard <d@drobilla.net>
+// Copyright 2017 Stefan Westerfeld <stefan@space.twc.de>
+// SPDX-License-Identifier: ISC
#include "suil_internal.h"
diff --git a/src/x11_in_gtk2.c b/src/x11_in_gtk2.c
index 80eef1a..78164c0 100644
--- a/src/x11_in_gtk2.c
+++ b/src/x11_in_gtk2.c
@@ -1,18 +1,5 @@
-/*
- 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.
-*/
+// Copyright 2011-2021 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "suil_internal.h"
#include "warnings.h"
diff --git a/src/x11_in_gtk3.c b/src/x11_in_gtk3.c
index c93f3dd..bd0ee3b 100644
--- a/src/x11_in_gtk3.c
+++ b/src/x11_in_gtk3.c
@@ -1,18 +1,5 @@
-/*
- 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.
-*/
+// Copyright 2011-2021 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
#include "suil_internal.h"
#include "warnings.h"
@@ -50,6 +37,7 @@ typedef struct {
const LV2UI_Idle_Interface* idle_iface;
guint idle_id;
guint idle_ms;
+ guint idle_size_request_id;
int initial_width;
int initial_height;
int req_width;
@@ -114,6 +102,11 @@ on_plug_removed(GtkSocket* sock, gpointer data)
self->idle_id = 0;
}
+ if (self->idle_size_request_id) {
+ g_source_remove(self->idle_size_request_id);
+ self->idle_size_request_id = 0;
+ }
+
if (self->instance->handle) {
self->instance->descriptor->cleanup(self->instance->handle);
self->instance->handle = NULL;
@@ -207,8 +200,11 @@ forward_key_event(SuilX11Wrapper* socket, GdkEvent* gdk_event)
static gboolean
idle_size_request(gpointer user_data)
{
- GtkWidget* w = GTK_WIDGET(user_data);
+ SuilX11Wrapper* socket = (SuilX11Wrapper*)user_data;
+ GtkWidget* w = GTK_WIDGET(socket->plug);
+
gtk_widget_queue_resize(w);
+ socket->idle_size_request_id = 0;
return FALSE;
}
@@ -264,7 +260,7 @@ forward_size_request(SuilX11Wrapper* socket, GtkAllocation* allocation)
} else {
/* Child has not been realized, so unable to resize now.
Queue an idle resize. */
- g_idle_add(idle_size_request, socket->plug);
+ socket->idle_size_request_id = g_idle_add(idle_size_request, socket);
}
}
diff --git a/src/x11_in_qt5.cpp b/src/x11_in_qt5.cpp
index a288319..7e3d6ac 100644
--- a/src/x11_in_qt5.cpp
+++ b/src/x11_in_qt5.cpp
@@ -1,19 +1,6 @@
-/*
- Copyright 2011-2020 David Robillard <d@drobilla.net>
- Copyright 2015 Rui Nuno Capela <rncbc@rncbc.org>
-
- 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-2022 David Robillard <d@drobilla.net>
+// Copyright 2015 Rui Nuno Capela <rncbc@rncbc.org>
+// SPDX-License-Identifier: ISC
#include "suil_internal.h"
#include "warnings.h"
@@ -34,28 +21,23 @@ SUIL_DISABLE_QT_WARNINGS
#include <X11/Xutil.h>
SUIL_RESTORE_WARNINGS
-#include <cstdint>
#include <cstdlib>
#undef signals
-extern "C" {
+namespace {
class SuilQX11Widget : public QWidget
{
public:
SuilQX11Widget(QWidget* parent, Qt::WindowFlags wflags)
: QWidget(parent, wflags)
- , _instance(nullptr)
- , _idle_iface(nullptr)
- , _window(0)
- , _ui_timer(0)
{}
- SuilQX11Widget(const SuilQX11Widget&) = delete;
+ SuilQX11Widget(const SuilQX11Widget&) = delete;
SuilQX11Widget& operator=(const SuilQX11Widget&) = delete;
- SuilQX11Widget(SuilQX11Widget&&) = delete;
+ SuilQX11Widget(SuilQX11Widget&&) = delete;
SuilQX11Widget& operator=(SuilQX11Widget&&) = delete;
~SuilQX11Widget() override;
@@ -130,10 +112,10 @@ protected:
}
private:
- SuilInstance* _instance;
- const LV2UI_Idle_Interface* _idle_iface;
- Window _window;
- int _ui_timer;
+ SuilInstance* _instance{};
+ const LV2UI_Idle_Interface* _idle_iface{};
+ Window _window{};
+ int _ui_timer{};
};
SuilQX11Widget::~SuilQX11Widget() = default;
@@ -143,7 +125,7 @@ struct SuilX11InQt5Wrapper {
SuilQX11Widget* parent;
};
-static void
+void
wrapper_free(SuilWrapper* wrapper)
{
auto* impl = static_cast<SuilX11InQt5Wrapper*>(wrapper->impl);
@@ -153,7 +135,7 @@ wrapper_free(SuilWrapper* wrapper)
free(impl);
}
-static int
+int
wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance)
{
auto* const impl = static_cast<SuilX11InQt5Wrapper*>(wrapper->impl);
@@ -196,7 +178,7 @@ wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance)
return 0;
}
-static int
+int
wrapper_resize(LV2UI_Feature_Handle handle, int width, int height)
{
auto* const ew = static_cast<QWidget*>(handle);
@@ -204,6 +186,10 @@ wrapper_resize(LV2UI_Feature_Handle handle, int width, int height)
return 0;
}
+} // namespace
+
+extern "C" {
+
SUIL_LIB_EXPORT
SuilWrapper*
suil_wrapper_new(SuilHost*,
diff --git a/subprojects/sphinxygen.wrap b/subprojects/sphinxygen.wrap
new file mode 100644
index 0000000..9707d1a
--- /dev/null
+++ b/subprojects/sphinxygen.wrap
@@ -0,0 +1,14 @@
+# Copyright 2022-2023 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+[wrap-file]
+directory = sphinxygen-1.0.4
+source_url = https://download.drobilla.net/sphinxygen-1.0.4.tar.gz
+source_filename = sphinxygen-1.0.4.tar.gz
+source_hash = 12fa9f18ed9fca608f272520072257ba61fd9eff25613f86d83d4fce14fc01f5
+
+# [wrap-git]
+# url = https://gitlab.com/drobilla/sphinxygen.git
+# push-url = ssh://git@gitlab.com:drobilla/sphinxygen.git
+# revision = v1.0.4
+# depth = 1
diff --git a/suil.pc.in b/suil.pc.in
deleted file mode 100644
index 66810a6..0000000
--- a/suil.pc.in
+++ /dev/null
@@ -1,11 +0,0 @@
-prefix=@PREFIX@
-exec_prefix=@EXEC_PREFIX@
-libdir=@LIBDIR@
-includedir=@INCLUDEDIR@
-
-Name: Suil
-Version: @SUIL_VERSION@
-Description: LV2 plugin UI hosting library
-Requires: @SUIL_PKG_DEPS@
-Libs: -L${libdir} -l@LIB_SUIL@
-Cflags: -I${includedir}/suil-@SUIL_MAJOR_VERSION@
diff --git a/suil.ttl b/suil.ttl
new file mode 100644
index 0000000..8ee0388
--- /dev/null
+++ b/suil.ttl
@@ -0,0 +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 doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<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/suil>
+ a doap:Project ;
+ doap:blog <https://drobilla.net/category/suil/> ;
+ doap:bug-database <https://gitlab.com/lv2/suil/issues> ;
+ doap:description "Library for loading and wrapping LV2 plugin UIs" ;
+ doap:developer <http://drobilla.net/drobilla#me> ;
+ doap:download-page <http://download.drobilla.net/> ;
+ doap:homepage <http://drobilla.net/software/suil> ;
+ doap:implements <http://lv2plug.in/ns/extensions/ui> ;
+ doap:license <http://opensource.org/licenses/isc> ;
+ doap:maintainer <http://drobilla.net/drobilla#me> ;
+ doap:name "Suil" ;
+ doap:programming-language "C" ;
+ doap:repository [
+ a doap:GitBranch ;
+ doap:location <https://gitlab.com/lv2/suil.git>
+ ] .
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 1fbf185..0000000
--- a/wscript
+++ /dev/null
@@ -1,475 +0,0 @@
-#!/usr/bin/env python
-
-from waflib import Build, Logs, Options, TaskGen
-from waflib.extras import autowaf
-
-# Semver package/library version
-SUIL_VERSION = '0.10.11'
-SUIL_MAJOR_VERSION = SUIL_VERSION[0:SUIL_VERSION.find('.')]
-
-# Mandatory waf variables
-APPNAME = 'suil' # Package name for waf dist
-VERSION = SUIL_VERSION # Package version for waf dist
-top = '.' # Source directory
-out = 'build' # Build directory
-
-# Release variables
-uri = 'http://drobilla.net/sw/suil'
-dist_pattern = 'http://download.drobilla.net/suil-%d.%d.%d.tar.bz2'
-post_tags = ['Hacking', 'LAD', 'LV2', 'Suil']
-
-
-def options(ctx):
- ctx.load('compiler_c')
- ctx.load('compiler_cxx')
- opt = ctx.configuration_options()
-
- opt.add_option('--gtk2-lib-name', type='string', dest='gtk2_lib_name',
- default="libgtk-x11-2.0.so.0",
- help="Gtk2 library name [Default: libgtk-x11-2.0.so.0]")
- opt.add_option('--gtk3-lib-name', type='string', dest='gtk3_lib_name',
- default="libgtk-x11-3.0.so.0",
- help="Gtk3 library name [Default: libgtk-x11-3.0.so.0]")
-
- ctx.add_flags(
- opt,
- {'static': 'build static library',
- 'no-shared': 'do not build shared library',
- 'no-cocoa': 'do not build support for Cocoa/Quartz',
- 'no-gtk': 'do not build support for Gtk',
- 'no-qt': 'do not build support for Qt (any version)',
- 'no-qt5': 'do not build support for Qt5',
- 'no-x11': 'do not build support for X11'})
-
-
-def configure(conf):
- conf.load('compiler_c', cache=True)
- conf.load('compiler_cxx', cache=True)
- conf.load('autowaf', cache=True)
- autowaf.set_c_lang(conf, 'c99')
-
- conf.env.BUILD_SHARED = not conf.options.no_shared
- conf.env.BUILD_STATIC = conf.options.static
-
- if not conf.env.BUILD_SHARED and not conf.env.BUILD_STATIC:
- conf.fatal('Neither a shared nor a static build requested')
-
- if conf.env.DOCS:
- conf.load('sphinx')
-
- 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, '*', {
- 'gcc': [
- '-Wno-padded',
- '-Wno-suggest-attribute=const',
- '-Wno-suggest-attribute=pure',
- ],
- 'clang': [
- '-Wno-cast-qual',
- '-Wno-disabled-macro-expansion',
- '-Wno-padded',
- ]
- })
-
- autowaf.add_compiler_flags(conf.env, 'c', {
- 'msvc': [
- '/wd4514', # unreferenced inline function has been removed
- '/wd4820', # padding added after construct
- '/wd4191', # unsafe function conversion
- '/wd5045', # will insert Spectre mitigation for memory load
- ],
- })
-
- autowaf.add_compiler_flags(conf.env, 'cxx', {
- 'clang': [
- '-Wno-old-style-cast',
- '-Wno-zero-as-null-pointer-constant',
- ],
- })
-
- conf.env.NODELETE_FLAGS = []
- if (not conf.env.MSVC_COMPILER and
- conf.check(linkflags = ['-Wl,-z,nodelete'],
- msg = 'Checking for link flags -Wl,-z,-nodelete',
- mandatory = False)):
- conf.env.NODELETE_FLAGS = ['-Wl,-z,nodelete']
-
- conf.check_pkg('lv2 >= 1.16.0', uselib_store='LV2')
-
- if not conf.options.no_x11:
- conf.check_pkg('x11', uselib_store='X11', system=True, mandatory=False)
-
- def enable_module(var_name):
- conf.env[var_name] = 1
-
- if not conf.options.no_gtk:
- conf.check_pkg('gtk+-2.0 >= 2.18.0',
- uselib_store='GTK2',
- system=True,
- mandatory=False)
- if not conf.env.HAVE_GTK2:
- conf.check_pkg('gtk+-2.0',
- uselib_store='GTK2',
- system=True,
- mandatory=False)
- if conf.env.HAVE_GTK2:
- conf.define('SUIL_OLD_GTK', 1)
-
- if not conf.options.no_x11:
- conf.check_pkg('gtk+-x11-2.0',
- uselib_store='GTK2_X11',
- system=True,
- mandatory=False)
-
- if not conf.options.no_cocoa:
- conf.check_pkg('gtk+-quartz-2.0',
- uselib_store='GTK2_QUARTZ',
- system=True,
- mandatory=False)
-
- conf.check_pkg('gtk+-3.0 >= 3.14.0',
- uselib_store='GTK3',
- system=True,
- mandatory=False)
-
- if not conf.options.no_x11:
- conf.check_pkg('gtk+-x11-3.0 >= 3.14.0',
- uselib_store='GTK3_X11',
- system=True,
- mandatory=False)
-
- if not conf.options.no_qt:
- if not conf.options.no_qt5:
- conf.check_pkg('Qt5Widgets >= 5.1.0',
- uselib_store='QT5',
- system=True,
- mandatory=False)
-
- if not conf.options.no_x11:
- conf.check_pkg('Qt5X11Extras >= 5.1.0',
- uselib_store='QT5_X11',
- system=True,
- mandatory=False)
-
- if not conf.options.no_cocoa:
- if conf.check_cxx(header_name = 'QMacCocoaViewContainer',
- uselib = 'QT5_COCOA',
- system=True,
- mandatory = False):
- enable_module('SUIL_WITH_COCOA_IN_QT5')
-
- conf.check_cc(define_name = 'HAVE_LIBDL',
- lib = 'dl',
- mandatory = False)
-
- conf.define('SUIL_MODULE_DIR',
- conf.env.LIBDIR + '/suil-' + SUIL_MAJOR_VERSION)
-
- conf.define('SUIL_GTK2_LIB_NAME', conf.options.gtk2_lib_name)
- conf.define('SUIL_GTK3_LIB_NAME', conf.options.gtk3_lib_name)
-
- if conf.env.HAVE_GTK2 and conf.env.HAVE_QT5:
- enable_module('SUIL_WITH_GTK2_IN_QT5')
- enable_module('SUIL_WITH_QT5_IN_GTK2')
-
- if conf.env.HAVE_GTK2 and conf.env.HAVE_GTK2_X11:
- enable_module('SUIL_WITH_X11_IN_GTK2')
-
- if conf.env.HAVE_GTK3 and conf.env.HAVE_GTK3_X11:
- enable_module('SUIL_WITH_X11_IN_GTK3')
-
- if conf.env.HAVE_GTK3 and conf.env.HAVE_QT5:
- enable_module('SUIL_WITH_QT5_IN_GTK3')
-
- if conf.env.HAVE_GTK2 and conf.env.HAVE_GTK2_QUARTZ:
- enable_module('SUIL_WITH_COCOA_IN_GTK2')
-
- if conf.env.HAVE_GTK2 and conf.env.DEST_OS == 'win32':
- enable_module('SUIL_WITH_WIN_IN_GTK2')
-
- if conf.env.HAVE_QT5 and conf.env.HAVE_QT5_X11:
- enable_module('SUIL_WITH_X11_IN_QT5')
-
- if conf.env.HAVE_X11:
- enable_module('SUIL_WITH_X11')
-
- conf.run_env.append_unique('SUIL_MODULE_DIR', [conf.build_path()])
-
- # Set up environment for building/using as a subproject
- autowaf.set_lib_env(conf, 'suil', SUIL_VERSION,
- include_path=str(conf.path.find_node('include')))
-
- conf.define('SUIL_NO_DEFAULT_CONFIG', 1)
-
- autowaf.display_summary(
- conf,
- {'Static library': bool(conf.env.BUILD_STATIC),
- 'Shared library': bool(conf.env.BUILD_SHARED)})
-
- if conf.env.HAVE_GTK2:
- autowaf.display_msg(conf, "Gtk2 Library Name",
- conf.get_define('SUIL_GTK2_LIB_NAME'))
- if conf.env.HAVE_GTK3:
- autowaf.display_msg(conf, "Gtk3 Library Name",
- conf.get_define('SUIL_GTK3_LIB_NAME'))
-
- # Print summary message for every potentially supported wrapper
- wrappers = [('cocoa', 'gtk2'),
- ('gtk2', 'qt5'),
- ('qt5', 'gtk2'),
- ('win', 'gtk2'),
- ('x11', 'gtk2'),
- ('x11', 'gtk3'),
- ('qt5', 'gtk3'),
- ('x11', 'qt5'),
- ('cocoa', 'qt5')]
- for w in wrappers:
- var = 'SUIL_WITH_%s_IN_%s' % (w[0].upper(), w[1].upper())
- autowaf.display_msg(conf, 'Support for %s in %s' % (w[0], w[1]),
- bool(conf.env[var]))
-
-
-def build(bld):
- # C Headers
- includedir = '${INCLUDEDIR}/suil-%s/suil' % SUIL_MAJOR_VERSION
- bld.install_files(includedir, bld.path.ant_glob('include/suil/*.h'))
- TaskGen.task_gen.mappings['.mm'] = TaskGen.task_gen.mappings['.cc']
-
- # Pkgconfig file
- autowaf.build_pc(bld, 'SUIL', SUIL_VERSION, SUIL_MAJOR_VERSION, [],
- {'SUIL_MAJOR_VERSION': SUIL_MAJOR_VERSION,
- 'SUIL_PKG_DEPS': 'lv2'})
-
- cflags = []
- lib = []
- modlib = []
- if bld.env.DEST_OS == 'win32':
- modlib += ['user32']
- else:
- cflags += ['-fvisibility=hidden']
- if bld.is_defined('HAVE_LIBDL'):
- lib += ['dl']
- modlib += ['dl']
-
- module_dir = '${LIBDIR}/suil-' + SUIL_MAJOR_VERSION
-
- # Shared Library
- if bld.env.BUILD_SHARED:
- bld(features = 'c cshlib',
- export_includes = ['include'],
- source = 'src/host.c src/instance.c',
- target = 'suil-%s' % SUIL_MAJOR_VERSION,
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- name = 'libsuil',
- vnum = SUIL_VERSION,
- install_path = '${LIBDIR}',
- cflags = cflags,
- lib = lib,
- uselib = 'LV2')
-
- # Static library
- if bld.env.BUILD_STATIC:
- bld(features = 'c cstlib',
- export_includes = ['include'],
- source = 'src/host.c src/instance.c',
- target = 'suil-%s' % SUIL_MAJOR_VERSION,
- includes = ['.', 'include'],
- defines = ['SUIL_STATIC', 'SUIL_INTERNAL'],
- name = 'libsuil_static',
- vnum = SUIL_VERSION,
- install_path = '${LIBDIR}',
- cflags = cflags,
- lib = lib,
- uselib = 'LV2')
-
- if bld.env.SUIL_WITH_GTK2_IN_QT5:
- bld(features = 'cxx cxxshlib',
- source = 'src/gtk2_in_qt5.cpp',
- target = 'suil_gtk2_in_qt5',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cxxflags = cflags,
- lib = modlib,
- uselib = 'GTK2 QT5 LV2')
-
- if bld.env.SUIL_WITH_QT5_IN_GTK2:
- bld(features = 'cxx cxxshlib',
- source = 'src/qt5_in_gtk.cpp',
- target = 'suil_qt5_in_gtk2',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cxxflags = cflags,
- lib = modlib,
- uselib = 'GTK2 QT5 LV2',
- linkflags = bld.env.NODELETE_FLAGS)
-
- if bld.env.SUIL_WITH_X11_IN_GTK2:
- bld(features = 'c cshlib',
- source = 'src/x11_in_gtk2.c',
- target = 'suil_x11_in_gtk2',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib + ['X11'],
- uselib = 'GTK2 GTK2_X11 LV2',
- linkflags = bld.env.NODELETE_FLAGS)
-
- if bld.env.SUIL_WITH_X11_IN_GTK3:
- bld(features = 'c cshlib',
- source = 'src/x11_in_gtk3.c',
- target = 'suil_x11_in_gtk3',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib + ['X11'],
- uselib = 'GTK3 GTK3_X11 LV2',
- linkflags = bld.env.NODELETE_FLAGS)
-
- if bld.env.SUIL_WITH_QT5_IN_GTK3:
- bld(features = 'cxx cxxshlib',
- source = 'src/qt5_in_gtk.cpp',
- target = 'suil_qt5_in_gtk3',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib,
- uselib = 'GTK3 QT5 LV2',
- linkflags = bld.env.NODELETE_FLAGS)
-
- if bld.env.SUIL_WITH_COCOA_IN_GTK2:
- bld(features = 'cxx cshlib',
- source = 'src/cocoa_in_gtk2.mm',
- target = 'suil_cocoa_in_gtk2',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib,
- uselib = 'GTK2 LV2',
- linkflags = ['-framework', 'Cocoa'])
-
- if bld.env.SUIL_WITH_WIN_IN_GTK2:
- bld(features = 'cxx cxxshlib',
- source = 'src/win_in_gtk2.cpp',
- target = 'suil_win_in_gtk2',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib,
- uselib = 'GTK2 LV2',
- linkflags = bld.env.NODELETE_FLAGS)
-
- if bld.env.SUIL_WITH_X11_IN_QT5:
- bld(features = 'cxx cxxshlib',
- source = 'src/x11_in_qt5.cpp',
- target = 'suil_x11_in_qt5',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib,
- uselib = 'QT5 QT5_X11 LV2 X11')
-
- if bld.env.SUIL_WITH_COCOA_IN_QT5:
- bld(features = 'cxx cxxshlib',
- source = 'src/cocoa_in_qt5.mm',
- target = 'suil_cocoa_in_qt5',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib,
- uselib = 'QT5 QT5_COCOA LV2',
- linkflags = ['-framework', 'Cocoa'])
-
- if bld.env.SUIL_WITH_X11:
- bld(features = 'c cshlib',
- source = 'src/x11.c',
- target = 'suil_x11',
- includes = ['.', 'include'],
- defines = ['SUIL_INTERNAL'],
- install_path = module_dir,
- cflags = cflags,
- lib = modlib,
- uselib = 'X11 LV2')
-
- # Documentation
- if bld.env.DOCS:
- bld.recurse('doc/c')
-
- bld.add_post_fun(autowaf.run_ldconfig)
-
-
-class LintContext(Build.BuildContext):
- fun = cmd = 'lint'
-
-
-def lint(ctx):
- "checks code for style issues"
- import glob
- import os
- import subprocess
- import sys
-
- 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")
-
- qt_mapping_file = "/usr/share/include-what-you-use/qt5_11.imp"
- extra_args = []
- if os.path.exists(qt_mapping_file):
- extra_args += ["--", "-Xiwyu", "--mapping_file=" + qt_mapping_file]
-
- cmd = [ctx.env.IWYU_TOOL[0], "-o", "clang", "-p", "build"] + extra_args
- 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)
-
-
-def dist(ctx):
- ctx.base_path = ctx.path
- ctx.excl = ctx.get_excl() + ' .gitmodules'