diff options
-rw-r--r-- | .gitattributes | 1 | ||||
-rw-r--r-- | .gitignore | 8 | ||||
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | INSTALL | 59 | ||||
-rw-r--r-- | INSTALL.md | 70 | ||||
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | icons/meson.build | 34 | ||||
-rw-r--r-- | meson.build | 256 | ||||
-rw-r--r-- | meson/suppressions/meson.build | 71 | ||||
-rw-r--r-- | meson/warnings/meson.build | 188 | ||||
-rw-r--r-- | meson_options.txt | 20 | ||||
-rw-r--r-- | patchage.desktop.in | 6 | ||||
-rw-r--r-- | src/AlsaStubDriver.cpp | 18 | ||||
-rw-r--r-- | src/JackLibDriver.cpp | 6 | ||||
-rw-r--r-- | src/JackStubDriver.cpp | 18 | ||||
-rw-r--r-- | src/Legend.cpp | 2 | ||||
-rw-r--r-- | src/UIFile.hpp | 17 | ||||
-rw-r--r-- | src/binary_location.h | 4 | ||||
-rw-r--r-- | src/make_alsa_driver.hpp | 13 | ||||
-rw-r--r-- | src/make_jack_driver.hpp | 13 | ||||
-rw-r--r-- | src/patchage.ui.in (renamed from src/patchage.ui) | 0 | ||||
-rw-r--r-- | src/patchage_config.h | 88 | ||||
-rw-r--r-- | subprojects/fmt/meson.build | 16 | ||||
-rwxr-xr-x | waf | 27 | ||||
m--------- | waflib | 0 | ||||
-rw-r--r-- | wscript | 377 |
26 files changed, 806 insertions, 515 deletions
diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index f063da3..0000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -waf binary
\ No newline at end of file @@ -1,4 +1,4 @@ -build/** -.waf-* -.lock-waf* -__pycache__ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +build/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index b2babe7..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "waflib"] - path = waflib - url = ../autowaf.git 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..7109c35 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,70 @@ +Installation Instructions +========================= + +Prerequisites +------------- + +To build from source, you will need: + + * A relatively modern C compiler (GCC, Clang, and MSVC are known to work). + + * [Meson](http://mesonbuild.com/), which depends on + [Python](http://python.org/). + +This is a brief overview of building this project with meson. See the meson +documentation for more detailed information. + +Configuration +------------- + +The build is configured with the `setup` command, which creates a new build +directory with the given name: + + meson setup build + +Some environment variables are read during `setup` and stored with the +configuration: + + * `CC`: Path to C compiler. + * `CFLAGS`: C compiler options. + * `LDFLAGS`: Linker options. + +However, it is better to use meson options for configuration. All options can +be inspected with the `configure` command from within the build directory: + + cd build + meson configure + +Options can be set by passing C-style "define" options to `configure`: + + meson configure -Dc_args="-march=native" -Dprefix="/opt/mypackage/" + +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/ @@ -1,3 +1,9 @@ +patchage (1.0.7) unstable; + + * Switch to meson build system + + -- David Robillard <d@drobilla.net> Tue, 19 Jul 2022 17:37:21 +0000 + patchage (1.0.6) stable; * Fix ALSA sequencer port subscriptions diff --git a/icons/meson.build b/icons/meson.build new file mode 100644 index 0000000..30e78b1 --- /dev/null +++ b/icons/meson.build @@ -0,0 +1,34 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +svg_icon_sizes = [ + '16x16', + '22x22', + '32x32', + '48x48', +] + +png_icon_sizes = [ + '16x16', + '22x22', + '24x24', + '32x32', + '48x48', + '128x128', + '256x256', +] + +icons_dir = get_option('prefix') / get_option('datadir') / 'icons' / 'hicolor' + +install_data('scalable/patchage.svg', + install_dir: icons_dir / 'scalable' / 'apps') + +foreach size : svg_icon_sizes + install_data(files(size / 'patchage.svg'), + install_dir: icons_dir / size / 'apps') +endforeach + +foreach size : png_icon_sizes + install_data(files(size / 'patchage.png'), + install_dir: icons_dir / size / 'apps') +endforeach diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..08a71dc --- /dev/null +++ b/meson.build @@ -0,0 +1,256 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +project('patchage', ['c', 'cpp'], + version: '1.0.7', + license: 'GPLv3+', + meson_version: '>= 0.56.0', + default_options: [ + 'b_ndebug=if-release', + 'buildtype=release', + 'cpp_std=c++17', + ]) + +patchage_src_root = meson.current_source_dir() +major_version = meson.project_version().split('.')[0] +version_suffix = '@0@-@1@'.format(meson.project_name(), major_version) + +####################### +# Compilers and Flags # +####################### + +# Required tools +cpp = meson.get_compiler('cpp') + +# Set global warning flags +if get_option('strict') and not meson.is_subproject() + subdir('meson/warnings') +endif + +# Set global warning suppressions +subdir('meson/suppressions') +add_project_arguments(cpp_suppressions, language: ['cpp']) +add_project_arguments(['-DFMT_HEADER_ONLY'], language: ['cpp']) + +########################## +# Platform Configuration # +########################## + +patchage_datadir = get_option('prefix') / get_option('datadir') / 'patchage' + +platform_defines = [ + '-DPATCHAGE_VERSION="@0@"'.format(meson.project_version()), + '-DPATCHAGE_DATA_DIR="@0@"'.format(patchage_datadir), +] + +if host_machine.system() in ['gnu', 'linux'] + platform_defines += ['-D_GNU_SOURCE'] +endif + +if get_option('checks') + platform_defines += ['-DPATCHAGE_NO_DEFAULT_CONFIG'] + + dladdr_code = '''#include <dlfcn.h> +int main(void) { Dl_info info; return dladdr(&info, &info); }''' + + jack_metadata_code = '''#include <jack/metadata.h> +int main(void) { return !!&jack_set_property; }''' + + if cpp.compiles(dladdr_code, args: platform_defines, name: 'dladdr') + platform_defines += [ + '-DHAVE_DLADDR=1', + '-DPATCHAGE_BINLOC=1', + ] + else + platform_defines += ['-DHAVE_DLADDR=0'] + endif + + platform_defines += '-DHAVE_JACK_METADATA=@0@'.format( + cpp.compiles(jack_metadata_code, + args: platform_defines, + name: 'jack_metadata').to_int()) + +endif + +################ +# Dependencies # +################ + +m_dep = cpp.find_library('m', required: false) +dl_dep = cpp.find_library('dl', required: false) +thread_dep = dependency('threads', include_type: 'system') + +fmt_dep = dependency( + 'fmt', + fallback: ['fmt', 'fmt_dep'], + include_type: 'system', + version: '>= 7.1.3', +) + +gthread_dep = dependency( + 'gthread-2.0', + include_type: 'system', + version: '>= 2.14.0', +) + +glibmm_dep = dependency( + 'glibmm-2.4', + include_type: 'system', + version: '>= 2.14.0', +) + +gtkmm_dep = dependency( + 'gtkmm-2.4', + include_type: 'system', + version: '>= 2.12.0', +) + +ganv_dep = dependency( + 'ganv-1', + fallback: ['ganv', 'ganv_dep'], + include_type: 'system', + version: '>= 1.5.2', +) + +dependencies = [ + dl_dep, + fmt_dep, + ganv_dep, + glibmm_dep, + gthread_dep, + gtkmm_dep, + m_dep, + thread_dep, +] + +####################### +# Driver Dependencies # +####################### + +# Optional ALSA sequencer support +alsa_dep = dependency( + 'alsa', + include_type: 'system', + required: get_option('alsa'), +) + +# Optional JACK support +jack_dep = dependency( + 'jack', + include_type: 'system', + required: get_option('jack'), + version: '>= 0.120.0', +) + +# Optional JACK D-Bus support + +dbus_dep = dependency( + 'dbus-1', + include_type: 'system', + required: get_option('jack_dbus'), +) + +dbus_glib_dep = dependency( + 'dbus-glib-1', + include_type: 'system', + required: get_option('jack_dbus'), +) + +if jack_dep.found() and dbus_dep.found() and dbus_glib_dep.found() + message('Both libjack and D-Bus available, defaulting to libjack') +endif + +########### +# Program # +########### + +sources = files( + 'src/Canvas.cpp', + 'src/CanvasModule.cpp', + 'src/Configuration.cpp', + 'src/Drivers.cpp', + 'src/Legend.cpp', + 'src/Metadata.cpp', + 'src/Patchage.cpp', + 'src/Reactor.cpp', + 'src/TextViewLog.cpp', + 'src/event_to_string.cpp', + 'src/handle_event.cpp', + 'src/main.cpp', +) + +if alsa_dep.found() + sources += files('src/AlsaDriver.cpp') + dependencies += [alsa_dep] +else + sources += files('src/AlsaStubDriver.cpp') +endif + +if jack_dep.found() + sources += files('src/JackLibDriver.cpp') + dependencies += [jack_dep] +elif dbus_dep.found() and dbus_glib_dep.found() + sources += files('src/JackDbusDriver.cpp') + dependencies += [dbus_dep, dbus_glib_dep] +else + sources += files('src/JackStubDriver.cpp') +endif + +executable( + 'patchage', + sources, + cpp_args: cpp_suppressions + platform_defines, + dependencies: dependencies, + install: true, +) + +######## +# Data # +######## + +subdir('icons') + +config = configuration_data() +config.set('PATCHAGE_VERSION', meson.project_version()) +config.set('BINDIR', get_option('prefix') / get_option('bindir')) + +configure_file( + configuration: config, + input: files('src/patchage.ui.in'), + install: true, + install_dir: get_option('datadir') / 'patchage', + output: 'patchage.ui', +) + +configure_file( + configuration: config, + input: files('patchage.desktop.in'), + install: true, + install_dir: get_option('datadir') / 'applications', + output: 'patchage.desktop', +) + +install_man(files('doc/patchage.1')) + +######### +# Tests # +######### + +if not get_option('tests').disabled() and not meson.is_subproject() + # Check release metadata + autoship = find_program('autoship', required: false) + if autoship.found() + test( + 'autoship', + autoship, + args: ['test', patchage_src_root], + suite: 'data', + ) + endif +endif + +if not meson.is_subproject() + summary('Install prefix', get_option('prefix')) + summary('Executables', get_option('prefix') / get_option('bindir')) + summary('Man pages', get_option('prefix') / get_option('mandir')) +endif diff --git a/meson/suppressions/meson.build b/meson/suppressions/meson.build new file mode 100644 index 0000000..ea5d66e --- /dev/null +++ b/meson/suppressions/meson.build @@ -0,0 +1,71 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +# Project-specific warning suppressions. +# +# This should be used in conjunction with the generic "warnings" sibling that +# enables all reasonable warnings for the compiler. It lives here just to keep +# the top-level meson.build more readable. + +####### +# C++ # +####### + +if is_variable('cpp') + cpp_suppressions = [] + + if get_option('strict') + if cpp.get_id() == 'clang' + cpp_suppressions += [ + '-Wno-alloca', + '-Wno-cast-qual', + '-Wno-double-promotion', + '-Wno-float-conversion', + '-Wno-float-equal', + '-Wno-implicit-float-conversion', + '-Wno-padded', + '-Wno-pedantic', + '-Wno-shorten-64-to-32', + '-Wno-sign-conversion', + '-Wno-weak-vtables', + ] + + if host_machine.system() == 'darwin' + cpp_suppressions += [ + '-Wno-documentation', # JACK + '-Wno-documentation-deprecated-sync', # JACK + '-Wno-documentation-unknown-command', # boost + '-Wno-global-constructors', # boost + '-Wno-old-style-cast', # boost + '-Wno-redundant-parens', # boost + '-Wno-reserved-id-macro', # boost + '-Wno-zero-as-null-pointer-constant', # boost + ] + endif + + elif cpp.get_id() == 'gcc' + cpp_suppressions += [ + '-Wno-abi-tag', + '-Wno-alloca', + '-Wno-conditionally-supported', + '-Wno-conversion', + '-Wno-effc++', + '-Wno-float-equal', + '-Wno-inline', + '-Wno-null-dereference', + '-Wno-padded', + '-Wno-pedantic', + '-Wno-stack-protector', + '-Wno-strict-overflow', + '-Wno-suggest-attribute=const', + '-Wno-suggest-attribute=noreturn', + '-Wno-suggest-attribute=pure', + '-Wno-suggest-final-methods', + '-Wno-suggest-final-types', + '-Wno-switch-default', + ] + endif + endif + + cpp_suppressions = cpp.get_supported_arguments(cpp_suppressions) +endif diff --git a/meson/warnings/meson.build b/meson/warnings/meson.build new file mode 100644 index 0000000..fcf06ec --- /dev/null +++ b/meson/warnings/meson.build @@ -0,0 +1,188 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +# General code to enable approximately all warnings in GCC 12, clang, and MSVC. +# +# This is trivial for clang and MSVC, but GCC doesn't have an "everything" +# option, so we need to enable everything we want explicitly. Wall is assumed, +# but Wextra is not, for stability. +# +# These are collected from common.opt and c.opt in the GCC source, and manually +# curated with the help of the GCC documentation. Warnings that are +# application-specific, historical, or about compatibility between specific +# language revisions are omitted. The intent here is to have roughly the same +# meaning as clang's Weverything: extremely strict, but general. Specifically +# omitted are: +# +# General: +# +# Wabi= +# Waggregate-return +# Walloc-size-larger-than=BYTES +# Walloca-larger-than=BYTES +# Wframe-larger-than=BYTES +# Wlarger-than=BYTES +# Wstack-usage=BYTES +# Wsystem-headers +# Wtraditional +# Wtraditional-conversion +# Wtrampolines +# Wvla-larger-than=BYTES +# +# Build specific: +# +# Wpoison-system-directories +# +# C++ Specific: +# +# Wc++0x-compat +# Wc++1z-compat +# Wc++2a-compat +# Wctad-maybe-unsupported +# Wnamespaces +# Wtemplates + +gcc_common_warnings = [ + '-Walloc-zero', + '-Walloca', + '-Wanalyzer-too-complex', + '-Warith-conversion', + '-Warray-bounds=2', + '-Wattribute-alias=2', + '-Wbidi-chars=ucn', + '-Wcast-align=strict', + '-Wcast-function-type', + '-Wcast-qual', + '-Wclobbered', + '-Wconversion', + '-Wdate-time', + '-Wdisabled-optimization', + '-Wdouble-promotion', + '-Wduplicated-branches', + '-Wduplicated-cond', + '-Wempty-body', + '-Wendif-labels', + '-Wfloat-equal', + '-Wformat-overflow=2', + '-Wformat-signedness', + '-Wformat-truncation=2', + '-Wformat=2', + '-Wignored-qualifiers', + '-Wimplicit-fallthrough=3', + '-Winit-self', + '-Winline', + '-Winvalid-pch', + '-Wlogical-op', + '-Wmissing-declarations', + '-Wmissing-field-initializers', + '-Wmissing-include-dirs', + '-Wmultichar', + '-Wnormalized=nfc', + '-Wnull-dereference', + '-Wopenacc-parallelism', + '-Woverlength-strings', + '-Wpacked', + '-Wpacked-bitfield-compat', + '-Wpadded', + '-Wpointer-arith', + '-Wredundant-decls', + '-Wshadow', + '-Wshift-negative-value', + '-Wshift-overflow=2', + '-Wstack-protector', + '-Wstrict-aliasing=3', + '-Wstrict-overflow=5', + '-Wstring-compare', + '-Wstringop-overflow=3', + '-Wsuggest-attribute=cold', + '-Wsuggest-attribute=const', + '-Wsuggest-attribute=format', + '-Wsuggest-attribute=malloc', + '-Wsuggest-attribute=noreturn', + '-Wsuggest-attribute=pure', + '-Wswitch-default', + '-Wswitch-enum', + '-Wtrampolines', + '-Wtrivial-auto-var-init', + '-Wtype-limits', + '-Wundef', + '-Wuninitialized', + '-Wunsafe-loop-optimizations', + '-Wunused', + '-Wunused-const-variable=2', + '-Wunused-macros', + '-Wvector-operation-performance', + '-Wvla', + '-Wwrite-strings', +] + +####### +# C++ # +####### + +if is_variable('cpp') + all_cpp_warnings = [] + + if cpp.get_id() == 'clang' + all_cpp_warnings += [ + '-Weverything', + '-Wno-c++98-compat', + '-Wno-c++98-compat-pedantic' + ] + + if not meson.is_cross_build() + all_cpp_warnings += [ + '-Wno-poison-system-directories', + ] + endif + + elif cpp.get_id() == 'gcc' + all_cpp_warnings += gcc_common_warnings + [ + '-Wabi-tag', + '-Waligned-new=all', + '-Wcatch-value=3', + '-Wcomma-subscript', + '-Wconditionally-supported', + '-Wctor-dtor-privacy', + '-Wdelete-non-virtual-dtor', + '-Wdeprecated', + '-Wdeprecated-copy', + '-Wdeprecated-copy-dtor', + '-Wdeprecated-enum-enum-conversion', + '-Wdeprecated-enum-float-conversion', + '-Weffc++', + '-Wexpansion-to-defined', + '-Wextra-semi', + '-Wimport', + '-Winvalid-imported-macros', + '-Wmismatched-tags', + '-Wmultiple-inheritance', + '-Wnoexcept', + '-Wnoexcept-type', + '-Wnon-virtual-dtor', + '-Wold-style-cast', + '-Woverloaded-virtual', + '-Wplacement-new=2', + '-Wredundant-move', + '-Wredundant-tags', + '-Wregister', + '-Wsign-compare', + '-Wsign-promo', + '-Wsized-deallocation', + '-Wstrict-null-sentinel', + '-Wsuggest-final-methods', + '-Wsuggest-final-types', + '-Wsuggest-override', + '-Wuseless-cast', + '-Wvirtual-inheritance', + '-Wvolatile', + '-Wzero-as-null-pointer-constant', + ] + + elif cpp.get_id() == 'msvc' + all_cpp_warnings += ['/Wall'] + endif + + all_cpp_warnings = cpp.get_supported_arguments(all_cpp_warnings) + add_global_arguments(all_cpp_warnings, language: ['cpp']) +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..6845edc --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,20 @@ +option('alsa', type: 'feature', value: 'auto', yield: true, + description: 'Build ALSA sequencer support') + +option('checks', type: 'boolean', value: true, yield: true, + description: 'Check for features with the build system') + +option('jack', type: 'feature', value: 'auto', yield: true, + description: 'Build JACK audio and MIDI support') + +option('jack_dbus', type: 'feature', value: 'auto', yield: true, + description: 'Use JACK via D-Bus') + +option('strict', type: 'boolean', value: false, yield: true, + description: 'Enable ultra-strict warnings') + +option('tests', type: 'feature', value: 'auto', yield: true, + description: 'Build tests') + +option('title', type: 'string', value: 'Patchage', + description: 'Project title') diff --git a/patchage.desktop.in b/patchage.desktop.in index 39287d9..cff8414 100644 --- a/patchage.desktop.in +++ b/patchage.desktop.in @@ -1,10 +1,10 @@ [Desktop Entry] -Name=@APP_HUMAN_NAME@ +Name=Patchage Comment=Connect audio and MIDI applications together and manage audio sessions Comment[fr]=Connecter des applications audio et MIDI entre elles, et gérer les sessions audio -Exec=@BINDIR@/@APP_INSTALL_NAME@ +Exec=@BINDIR@/patchage Terminal=false -Icon=@APP_INSTALL_NAME@ +Icon=patchage Type=Application Categories=AudioVideo;Audio; Keywords=music;midi;alsa;jack; diff --git a/src/AlsaStubDriver.cpp b/src/AlsaStubDriver.cpp new file mode 100644 index 0000000..5dc8f0b --- /dev/null +++ b/src/AlsaStubDriver.cpp @@ -0,0 +1,18 @@ +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "AudioDriver.hpp" +#include "Driver.hpp" +#include "make_alsa_driver.hpp" + +#include <memory> + +namespace patchage { + +std::unique_ptr<Driver> +make_alsa_driver(ILog&, Driver::EventSink) +{ + return nullptr; +} + +} // namespace patchage diff --git a/src/JackLibDriver.cpp b/src/JackLibDriver.cpp index 8728222..8c804ba 100644 --- a/src/JackLibDriver.cpp +++ b/src/JackLibDriver.cpp @@ -31,7 +31,7 @@ #include "patchage_config.h" #include "warnings.hpp" -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA # include <jack/metadata.h> #endif @@ -182,7 +182,7 @@ get_property(const jack_uuid_t subject, const char* const key) { std::string result; -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA char* value = nullptr; char* datatype = nullptr; if (!jack_get_property(subject, key, &value, &datatype)) { @@ -213,7 +213,7 @@ JackLibDriver::get_port_info(const jack_port_t* const port) auto label = PortNames{name}.port(); // Get pretty name to use as a label, if present -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA const auto pretty_name = get_property(uuid, JACK_METADATA_PRETTY_NAME); if (!pretty_name.empty()) { label = pretty_name; diff --git a/src/JackStubDriver.cpp b/src/JackStubDriver.cpp new file mode 100644 index 0000000..a062df1 --- /dev/null +++ b/src/JackStubDriver.cpp @@ -0,0 +1,18 @@ +// Copyright 2020-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "AudioDriver.hpp" +#include "Driver.hpp" +#include "make_jack_driver.hpp" + +#include <memory> + +namespace patchage { + +std::unique_ptr<AudioDriver> +make_jack_driver(ILog&, Driver::EventSink) +{ + return nullptr; +} + +} // namespace patchage diff --git a/src/Legend.cpp b/src/Legend.cpp index e8e4743..294f589 100644 --- a/src/Legend.cpp +++ b/src/Legend.cpp @@ -39,7 +39,7 @@ Legend::Legend(const Configuration& configuration) "Audio", configuration.get_port_color(PortType::jack_audio)); -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA add_button( PortType::jack_cv, "CV", configuration.get_port_color(PortType::jack_cv)); add_button(PortType::jack_osc, diff --git a/src/UIFile.hpp b/src/UIFile.hpp index d7f1e5c..28d7c82 100644 --- a/src/UIFile.hpp +++ b/src/UIFile.hpp @@ -47,25 +47,28 @@ public: static Glib::RefPtr<Gtk::Builder> open(const std::string& base_name) { - std::string ui_filename; + std::cout << "Base name: " << base_name << std::endl; + std::string ui_filename = base_name + ".ui"; + #ifdef PATCHAGE_BINLOC const std::string bundle = bundle_location(); if (!bundle.empty()) { - ui_filename = bundle + "/" + base_name + ".ui"; - if (is_readable(ui_filename)) { - std::cout << "Loading UI file " << ui_filename << std::endl; - return Gtk::Builder::create_from_file(ui_filename); + const std::string bundle_ui_filename = bundle + "/" + ui_filename; + if (is_readable(bundle_ui_filename)) { + std::cout << "Loading UI file " << bundle_ui_filename << std::endl; + return Gtk::Builder::create_from_file(bundle_ui_filename); } } #endif - ui_filename = std::string(PATCHAGE_DATA_DIR) + "/" + base_name + ".ui"; + + ui_filename = std::string(PATCHAGE_DATA_DIR) + "/" + ui_filename; if (is_readable(ui_filename)) { std::cout << "Loading UI file " << ui_filename << std::endl; return Gtk::Builder::create_from_file(ui_filename); } std::stringstream ss; - ss << "Unable to find " << base_name << std::endl; + ss << "Unable to find " << ui_filename << std::endl; throw std::runtime_error(ss.str()); return {}; } diff --git a/src/binary_location.h b/src/binary_location.h index 220c534..d3394f3 100644 --- a/src/binary_location.h +++ b/src/binary_location.h @@ -14,10 +14,6 @@ * along with Patchage. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - #include <dlfcn.h> #include <climits> diff --git a/src/make_alsa_driver.hpp b/src/make_alsa_driver.hpp index f72da99..cfd89c0 100644 --- a/src/make_alsa_driver.hpp +++ b/src/make_alsa_driver.hpp @@ -18,7 +18,6 @@ #define PATCHAGE_MAKE_ALSA_DRIVER_HPP #include "Driver.hpp" -#include "patchage_config.h" #include <memory> @@ -26,21 +25,9 @@ namespace patchage { class ILog; -#if defined(HAVE_ALSA) - std::unique_ptr<Driver> make_alsa_driver(ILog& log, Driver::EventSink emit_event); -#else - -inline std::unique_ptr<Driver> -make_alsa_driver(ILog&, Driver::EventSink) -{ - return nullptr; -} - -#endif - } // namespace patchage #endif // PATCHAGE_MAKE_ALSA_DRIVER_HPP diff --git a/src/make_jack_driver.hpp b/src/make_jack_driver.hpp index abd1ba1..38aef65 100644 --- a/src/make_jack_driver.hpp +++ b/src/make_jack_driver.hpp @@ -18,7 +18,6 @@ #define PATCHAGE_MAKE_JACK_DRIVER_HPP #include "Driver.hpp" -#include "patchage_config.h" #include <memory> @@ -27,21 +26,9 @@ namespace patchage { class AudioDriver; class ILog; -#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS) - std::unique_ptr<AudioDriver> make_jack_driver(ILog& log, Driver::EventSink emit_event); -#else - -inline std::unique_ptr<AudioDriver> -make_jack_driver(ILog&, Driver::EventSink) -{ - return nullptr; -} - -#endif - } // namespace patchage #endif // PATCHAGE_MAKE_JACK_DRIVER_HPP diff --git a/src/patchage.ui b/src/patchage.ui.in index d86fb80..d86fb80 100644 --- a/src/patchage.ui +++ b/src/patchage.ui.in diff --git a/src/patchage_config.h b/src/patchage_config.h new file mode 100644 index 0000000..579a253 --- /dev/null +++ b/src/patchage_config.h @@ -0,0 +1,88 @@ +// Copyright 2021-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +/* + Configuration header that defines reasonable defaults at compile time. + + This allows compile-time configuration from the command line, while still + allowing the source to be built "as-is" without any configuration. The idea + is to support an advanced build system with configuration checks, while still + allowing the code to be simply "thrown at a compiler" with features + determined from the compiler or system headers. Everything can be + overridden, so it should never be necessary to edit this file to build + successfully. + + To ensure that all configure checks are performed, the build system can + define PATCHAGE_NO_DEFAULT_CONFIG to disable defaults. In this case, it must + define all HAVE_FEATURE symbols below to 1 or 0 to enable or disable + features. Any missing definitions will generate a compiler warning. + + To ensure that this header is always included properly, all code that uses + configuration variables includes this header and checks their value with #if + (not #ifdef). Variables like USE_FEATURE are internal and should never be + defined on the command line. +*/ + +#ifndef PATCHAGE_CONFIG_H +#define PATCHAGE_CONFIG_H + +// Define version unconditionally so a warning will catch a mismatch +#define PATCHAGE_VERSION "1.0.7" + +#if !defined(PATCHAGE_NO_DEFAULT_CONFIG) + +// Classic UNIX: dladdr() +# ifndef HAVE_DLADDR +# ifdef __has_include +# if __has_include(<dlfcn.h>) +# define HAVE_DLADDR 1 +# else +# define HAVE_DLADDR 0 +# endif +# elif defined(__unix__) || defined(__APPLE__) +# define HAVE_DLADDR 1 +# else +# define HAVE_DLADDR 0 +# endif +# endif + +// JACK metadata API +# ifndef HAVE_JACK_METADATA +# ifdef __has_include +# if __has_include(<jack/metadata.h>) +# define HAVE_JACK_METADATA 1 +# else +# define HAVE_JACK_METADATA 0 +# endif +# else +# define HAVE_JACK_METADATA 0 +# endif +# endif + +#endif // !defined(PATCHAGE_NO_DEFAULT_CONFIG) + +/* + Make corresponding USE_FEATURE defines based on the HAVE_FEATURE defines from + above or the command line. The code checks for these using #if (not #ifdef), + so there will be an undefined warning if it checks for an unknown feature, + and this header is always required by any code that checks for features, even + if the build system defines them all. +*/ + +#if HAVE_DLADDR +# define USE_DLADDR 1 +#else +# define USE_DLADDR 0 +#endif + +#if HAVE_JACK_METADATA +# define USE_JACK_METADATA 1 +#else +# define USE_JACK_METADATA 0 +#endif + +#ifndef PATCHAGE_USE_LIGHT_THEME +# define PATCHAGE_USE_LIGHT_THEME 0 +#endif + +#endif // PATCHAGE_CONFIG_H diff --git a/subprojects/fmt/meson.build b/subprojects/fmt/meson.build new file mode 100644 index 0000000..4f0f3ca --- /dev/null +++ b/subprojects/fmt/meson.build @@ -0,0 +1,16 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +project('fmt', ['cpp'], + version: '7.1.3', + license: 'ISC', + meson_version: '>= 0.56.0', + default_options: [ + 'b_ndebug=if-release', + 'buildtype=release', + 'cpp_std=c++17', + ]) + +include_dirs = include_directories('include') + +fmt_dep = declare_dependency(include_directories: include_dirs) @@ -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(os.path.realpath(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 23da9bb..0000000 --- a/wscript +++ /dev/null @@ -1,377 +0,0 @@ -#!/usr/bin/env python -# Licensed under the GNU GPL v3 or later, see COPYING file for details. -# Copyright 2008-2013 David Robillard -# Copyright 2008 Nedko Arnaudov - -import os - -from waflib import Build, Logs, Options, Utils -from waflib.extras import autowaf - -# Version of this package (even if built as a child) -PATCHAGE_VERSION = '1.0.6' - -# Variables for 'waf dist' -APPNAME = 'patchage' -VERSION = PATCHAGE_VERSION - -# Mandatory variables -top = '.' -out = 'build' - -# Release variables -uri = 'http://drobilla.net/sw/patchage' -dist_pattern = 'http://download.drobilla.net/patchage-%d.%d.%d.tar.bz2' -post_tags = ['Hacking', 'LAD', 'Patchage'] - - -def options(ctx): - ctx.load('compiler_cxx') - - opt = ctx.configuration_options() - opt.add_option('--patchage-install-name', type='string', - default=APPNAME, - help='patchage install name') - opt.add_option('--patchage-human-name', type='string', - default='Patchage', - help='patchage human name') - - ctx.add_flags( - opt, - {'jack-dbus': 'use Jack via D-Bus', - 'no-alsa': 'do not build Alsa Sequencer support', - 'no-binloc': 'do not find files from executable location', - 'light-theme': 'use light coloured theme'}) - - -def configure(conf): - conf.load('compiler_cxx', cache=True) - conf.load('autowaf', cache=True) - autowaf.set_cxx_lang(conf, 'c++17') - - if Options.options.strict: - # Check for programs used by lint target - conf.find_program("flake8", var="FLAKE8", mandatory=False) - conf.find_program("clang-tidy", var="CLANG_TIDY", mandatory=False) - conf.find_program("iwyu_tool", var="IWYU_TOOL", mandatory=False) - - if Options.options.ultra_strict: - autowaf.add_compiler_flags(conf.env, '*', { - 'clang': [ - '-Wno-alloca', - '-Wno-cast-qual', - '-Wno-double-promotion', - '-Wno-float-conversion', - '-Wno-float-equal', - '-Wno-implicit-float-conversion', - '-Wno-padded', - '-Wno-pedantic', - '-Wno-reserved-identifier', - '-Wno-shorten-64-to-32', - '-Wno-sign-conversion', - ], - 'gcc': [ - '-Wno-alloca', - '-Wno-conversion', - '-Wno-float-equal', - '-Wno-inline', - '-Wno-padded', - '-Wno-pedantic', - '-Wno-stack-protector', - '-Wno-suggest-attribute=const', - '-Wno-suggest-attribute=noreturn', - '-Wno-suggest-attribute=pure', - '-Wno-suggest-final-methods', - '-Wno-suggest-final-types', - ], - }) - - autowaf.add_compiler_flags(conf.env, 'c', { - 'clang': [ - '-Wno-bad-function-cast', - '-Wno-missing-noreturn', - ], - 'gcc': [ - '-Wno-bad-function-cast', - ], - }) - - autowaf.add_compiler_flags(conf.env, 'cxx', { - 'clang': [ - '-Wno-weak-vtables', - ], - 'gcc': [ - '-Wno-conditionally-supported', - '-Wno-effc++', - ], - }) - - conf.check_pkg('dbus-1', - uselib_store='DBUS', - system=True, - mandatory=False) - - conf.check_pkg('dbus-glib-1', - uselib_store='DBUS_GLIB', - system=True, - mandatory=False) - - conf.check_pkg('gthread-2.0 >= 2.14.0', - system=True, - uselib_store='GTHREAD') - - conf.check_pkg('glibmm-2.4 >= 2.14.0', - system=True, - uselib_store='GLIBMM') - - conf.check_pkg('gtkmm-2.4 >= 2.12.0', - system=True, - uselib_store='GTKMM') - - conf.check_pkg('ganv-1 >= 1.5.2', uselib_store='GANV') - - if conf.env.DEST_OS == 'darwin': - conf.check_pkg('gtk-mac-integration', - uselib_store='GTK_OSX', - system=True, - mandatory=False) - if conf.env.HAVE_GTK_OSX: - conf.define('PATCHAGE_GTK_OSX', 1) - - # Check for dladdr - conf.check_function('cxx', 'dladdr', - header_name = 'dlfcn.h', - defines = ['_GNU_SOURCE'], - lib = ['dl'], - define_name = 'HAVE_DLADDR', - return_type = 'int', - arg_types = 'const void*,Dl_info*', - mandatory = False) - - # Use Jack D-Bus if requested (only one jack driver is allowed) - use_jack_dbus = (Options.options.jack_dbus and - conf.env.HAVE_DBUS and - conf.env.HAVE_DBUS_GLIB) - - if use_jack_dbus: - conf.define('HAVE_JACK_DBUS', 1) - else: - conf.check_pkg('jack >= 0.120.0', - uselib_store='JACK', - system=True, - mandatory=False) - - if conf.env.HAVE_JACK: - conf.define('PATCHAGE_LIBJACK', 1) - - conf.check_function('cxx', 'jack_get_property', - header_name = 'jack/metadata.h', - define_name = 'HAVE_JACK_METADATA', - uselib = 'JACK', - return_type = 'int', - arg_types = '''jack_uuid_t, - const char*, - char**, - char**''', - mandatory = False) - - # Use Alsa if present unless --no-alsa - if not Options.options.no_alsa: - conf.check_pkg('alsa', - uselib_store='ALSA', - system=True, - mandatory=False) - - # Find files at binary location if we have dladdr unless --no-binloc - if not Options.options.no_binloc and conf.is_defined('HAVE_DLADDR'): - conf.define('PATCHAGE_BINLOC', 1) - - if Options.options.light_theme: - conf.define('PATCHAGE_USE_LIGHT_THEME', 1) - - # Boost headers - conf.check_cxx(header_name='boost/optional/optional.hpp') - conf.check_cxx(header_name='boost/variant.hpp') - - # Check for system provided fmt - conf.check_pkg('fmt', - uselib_store='FMT', - system=True, - mandatory=False) - - if not conf.env.HAVE_FMT: - # Fall back to minimal bundled version if not found - Logs.warn("System fmt library not found, using bundled copy") - include_dir = conf.path.find_node('subprojects/fmt/include') - conf.define('FMT_HEADER_ONLY', 1) - conf.env.LIB_FMT = [] - conf.env.INCLUDES_FMT = [include_dir.abspath()] - - conf.env.PATCHAGE_VERSION = PATCHAGE_VERSION - - conf.env.APP_INSTALL_NAME = Options.options.patchage_install_name - conf.env.APP_HUMAN_NAME = Options.options.patchage_human_name - conf.define('PATCHAGE_DATA_DIR', os.path.join( - conf.env.DATADIR, conf.env.APP_INSTALL_NAME)) - - conf.define('PATCHAGE_VERSION', PATCHAGE_VERSION) - conf.write_config_header('patchage_config.h', remove=False) - - autowaf.display_summary( - conf, - {'Install name': conf.env.APP_INSTALL_NAME, - 'App human name': conf.env.APP_HUMAN_NAME, - 'Jack (D-Bus)': conf.is_defined('HAVE_JACK_DBUS'), - 'Jack (libjack)': conf.is_defined('PATCHAGE_LIBJACK'), - 'Jack Metadata': conf.is_defined('HAVE_JACK_METADATA'), - 'Alsa Sequencer': bool(conf.env.HAVE_ALSA)}) - - if conf.env.DEST_OS == 'darwin': - autowaf.display_msg(conf, "Mac Integration", - bool(conf.env.HAVE_GTK_OSX)) - - -def build(bld): - out_base = '' - if bld.env.DEST_OS == 'darwin': - out_base = 'Patchage.app/Contents/' - - # Program - prog = bld(features = 'cxx cxxprogram', - includes = ['.', 'src'], - target = out_base + bld.env.APP_INSTALL_NAME, - uselib = 'DBUS GANV DBUS_GLIB FMT GTKMM GTHREAD GTK_OSX', - install_path = '${BINDIR}') - prog.source = ''' - src/Canvas.cpp - src/CanvasModule.cpp - src/Configuration.cpp - src/Drivers.cpp - src/Legend.cpp - src/Metadata.cpp - src/Patchage.cpp - src/Reactor.cpp - src/TextViewLog.cpp - src/event_to_string.cpp - src/handle_event.cpp - src/main.cpp - ''' - if bld.is_defined('HAVE_JACK_DBUS'): - prog.source += ' src/JackDbusDriver.cpp ' - if bld.is_defined('PATCHAGE_LIBJACK'): - prog.source += ' src/JackLibDriver.cpp ' - prog.uselib += ' JACK NEWJACK ' - if bld.env.HAVE_ALSA: - prog.source += ' src/AlsaDriver.cpp ' - prog.uselib += ' ALSA ' - if bld.is_defined('PATCHAGE_BINLOC') and bld.is_defined('HAVE_DLADDR'): - prog.lib = ['dl'] - - # XML UI definition - bld(features = 'subst', - source = 'src/patchage.ui', - target = out_base + 'patchage.ui', - install_path = '${DATADIR}/' + bld.env.APP_INSTALL_NAME, - chmod = Utils.O644, - PATCHAGE_VERSION = PATCHAGE_VERSION) - - # 'Desktop' file (menu entry, icon, etc) - bld(features = 'subst', - source = 'patchage.desktop.in', - target = 'patchage.desktop', - install_path = '${DATADIR}/applications', - chmod = Utils.O644, - BINDIR = os.path.normpath(bld.env.BINDIR), - APP_INSTALL_NAME = bld.env.APP_INSTALL_NAME, - APP_HUMAN_NAME = bld.env.APP_HUMAN_NAME) - - if bld.env.DEST_OS == 'darwin': - # Property list - bld(features = 'subst', - source = 'osx/Info.plist.in', - target = out_base + 'Info.plist', - install_path = '', - chmod = Utils.O644) - - # Icons - bld(rule = 'cp ${SRC} ${TGT}', - source = 'osx/Patchage.icns', - target = out_base + 'Resources/Patchage.icns') - - # Gtk/Pango/etc configuration files - for i in ['pangorc', 'pango.modules', 'loaders.cache', 'gtkrc']: - bld(rule = 'cp ${SRC} ${TGT}', - source = 'osx/' + i, - target = out_base + 'Resources/' + i) - - # Icons - # After installation, icon cache should be updated using: - # gtk-update-icon-cache -f -t $(datadir)/icons/hicolor - icon_sizes = [16, 22, 24, 32, 48, 128, 256] - for s in icon_sizes: - d = '%dx%d' % (s, s) - bld.install_as( - os.path.join(bld.env.DATADIR, 'icons', 'hicolor', d, 'apps', - bld.env.APP_INSTALL_NAME + '.png'), - os.path.join('icons', d, 'patchage.png')) - - bld.install_as( - os.path.join(bld.env.DATADIR, 'icons', 'hicolor', 'scalable', 'apps', - bld.env.APP_INSTALL_NAME + '.svg'), - os.path.join('icons', 'scalable', 'patchage.svg')) - - bld.install_files('${MANDIR}/man1', bld.path.ant_glob('doc/*.1')) - - -class LintContext(Build.BuildContext): - fun = cmd = 'lint' - - -def lint(ctx): - "checks code for style issues" - import subprocess - import sys - - st = 0 - - if "FLAKE8" in ctx.env: - Logs.info("Running flake8") - st = subprocess.call([ctx.env.FLAKE8[0], - "wscript", - "--ignore", - "E221,W504,E251,E241,E741"]) - else: - Logs.warn("Not running flake8") - - if "IWYU_TOOL" in ctx.env: - Logs.info("Running include-what-you-use") - cmd = [ctx.env.IWYU_TOOL[0], "-o", "clang", "-p", "build"] - output = subprocess.check_output(cmd).decode('utf-8') - if 'error: ' in output: - sys.stdout.write(output) - st += 1 - else: - Logs.warn("Not running include-what-you-use") - - if "CLANG_TIDY" in ctx.env and "clang" in ctx.env.CXX[0]: - Logs.info("Running clang-tidy") - - import json - - with open('build/compile_commands.json', 'r') as db: - commands = json.load(db) - files = [c['file'] for c in commands] - - procs = [] - for f in files: - cmd = [ctx.env.CLANG_TIDY[0], '--quiet', '-p=.', f] - procs += [subprocess.Popen(cmd, cwd='build')] - - for proc in procs: - proc.communicate() - st += proc.returncode - else: - Logs.warn("Not running clang-tidy") - - if st != 0: - sys.exit(st) |