aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2018-08-03 23:08:08 +0200
committerGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2018-08-03 23:08:08 +0200
commit9d01970fd5829d8c0223c1aea7d46becf51ecf48 (patch)
treec69ce1b0685c584eddd743a542f6fd1f7d607612
downloadpianoteq_utils.lv2-9d01970fd5829d8c0223c1aea7d46becf51ecf48.zip
pianoteq_utils.lv2-9d01970fd5829d8c0223c1aea7d46becf51ecf48.tar.gz
pianoteq_utils.lv2-9d01970fd5829d8c0223c1aea7d46becf51ecf48.tar.bz2
pianoteq_utils.lv2-9d01970fd5829d8c0223c1aea7d46becf51ecf48.tar.xz
initial commit.
-rw-r--r--.gitlab-ci.yml71
-rw-r--r--COPYING201
-rw-r--r--README.md41
-rw-r--r--VERSION1
-rw-r--r--manifest.ttl.in29
-rw-r--r--meson.build65
-rw-r--r--pianoteq_utils.c31
-rw-r--r--pianoteq_utils.h99
-rw-r--r--pianoteq_utils.ttl101
-rw-r--r--pianoteq_utils_demo_unmute.c310
10 files changed, 949 insertions, 0 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..6d2a9c4
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,71 @@
+stages:
+ - build
+ - test
+ - deploy
+
+.variables_template: &variables_definition
+ variables:
+ BASE_NAME: "pianoteq_utils.lv2"
+ PKG_CONFIG_PATH: "/opt/lv2/lib/pkgconfig:/opt/${CI_BUILD_NAME}/lib/pkgconfig:/usr/lib/${CI_BUILD_NAME}/pkgconfig"
+
+.common_template: &common_definition
+ <<: *variables_definition
+ stage: build
+ artifacts:
+ name: "${BASE_NAME}-$(cat VERSION)-${CI_BUILD_NAME}"
+ paths:
+ - "${BASE_NAME}-$(cat VERSION)/"
+
+.build_template: &build_definition
+ <<: *common_definition
+ script:
+ - meson --prefix="/opt/${CI_BUILD_NAME}" --libdir="lib" --cross-file "${CI_BUILD_NAME}" build
+ - ninja -C build
+ - ninja -C build install
+ - mkdir -p "${BASE_NAME}-$(cat VERSION)/${CI_BUILD_NAME}/${BASE_NAME}"
+ - cp -r "/opt/${CI_BUILD_NAME}/lib/lv2/${BASE_NAME}/" "${BASE_NAME}-$(cat VERSION)/${CI_BUILD_NAME}/"
+
+.universal_linux_template: &universal_linux_definition
+ image: ventosus/universal-linux-gnu
+ <<: *build_definition
+
+.arm_linux_template: &arm_linux_definition
+ image: ventosus/arm-linux-gnueabihf
+ <<: *build_definition
+
+.universal_w64_template: &universal_w64_definition
+ image: ventosus/universal-w64-mingw32
+ <<: *build_definition
+
+.universal_apple_template: &universal_apple_definition
+ image: ventosus/universal-apple-darwin
+ <<: *build_definition
+
+# building in docker
+x86_64-linux-gnu:
+ <<: *universal_linux_definition
+
+i686-linux-gnu:
+ <<: *universal_linux_definition
+
+arm-linux-gnueabihf:
+ <<: *arm_linux_definition
+
+x86_64-w64-mingw32:
+ <<: *universal_w64_definition
+
+i686-w64-mingw32:
+ <<: *universal_w64_definition
+
+universal-apple-darwin:
+ <<: *universal_apple_definition
+
+pack:
+ <<: *variables_definition
+ stage: deploy
+ script:
+ - echo 'packing up...'
+ artifacts:
+ name: "${BASE_NAME}-$(cat VERSION)"
+ paths:
+ - "${BASE_NAME}-$(cat VERSION)/"
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..ddb9a46
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,201 @@
+ The Artistic License 2.0
+
+ Copyright (c) 2000-2006, The Perl Foundation.
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+Preamble
+
+This license establishes the terms under which a given free software
+Package may be copied, modified, distributed, and/or redistributed.
+The intent is that the Copyright Holder maintains some artistic
+control over the development of that Package while still keeping the
+Package available as open source and free software.
+
+You are always permitted to make arrangements wholly outside of this
+license directly with the Copyright Holder of a given Package. If the
+terms of this license do not permit the full use that you propose to
+make of the Package, you should contact the Copyright Holder and seek
+a different licensing arrangement.
+
+Definitions
+
+ "Copyright Holder" means the individual(s) or organization(s)
+ named in the copyright notice for the entire Package.
+
+ "Contributor" means any party that has contributed code or other
+ material to the Package, in accordance with the Copyright Holder's
+ procedures.
+
+ "You" and "your" means any person who would like to copy,
+ distribute, or modify the Package.
+
+ "Package" means the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection and/or of
+ those files. A given Package may consist of either the Standard
+ Version, or a Modified Version.
+
+ "Distribute" means providing a copy of the Package or making it
+ accessible to anyone else, or in the case of a company or
+ organization, to others outside of your company or organization.
+
+ "Distributor Fee" means any fee that you charge for Distributing
+ this Package or providing support for this Package to another
+ party. It does not mean licensing fees.
+
+ "Standard Version" refers to the Package if it has not been
+ modified, or has been modified only in ways explicitly requested
+ by the Copyright Holder.
+
+ "Modified Version" means the Package, if it has been changed, and
+ such changes were not explicitly requested by the Copyright
+ Holder.
+
+ "Original License" means this Artistic License as Distributed with
+ the Standard Version of the Package, in its current version or as
+ it may be modified by The Perl Foundation in the future.
+
+ "Source" form means the source code, documentation source, and
+ configuration files for the Package.
+
+ "Compiled" form means the compiled bytecode, object code, binary,
+ or any other form resulting from mechanical transformation or
+ translation of the Source form.
+
+
+Permission for Use and Modification Without Distribution
+
+(1) You are permitted to use the Standard Version and create and use
+Modified Versions for any purpose without restriction, provided that
+you do not Distribute the Modified Version.
+
+
+Permissions for Redistribution of the Standard Version
+
+(2) You may Distribute verbatim copies of the Source form of the
+Standard Version of this Package in any medium without restriction,
+either gratis or for a Distributor Fee, provided that you duplicate
+all of the original copyright notices and associated disclaimers. At
+your discretion, such verbatim copies may or may not include a
+Compiled form of the Package.
+
+(3) You may apply any bug fixes, portability changes, and other
+modifications made available from the Copyright Holder. The resulting
+Package will still be considered the Standard Version, and as such
+will be subject to the Original License.
+
+
+Distribution of Modified Versions of the Package as Source
+
+(4) You may Distribute your Modified Version as Source (either gratis
+or for a Distributor Fee, and with or without a Compiled form of the
+Modified Version) provided that you clearly document how it differs
+from the Standard Version, including, but not limited to, documenting
+any non-standard features, executables, or modules, and provided that
+you do at least ONE of the following:
+
+ (a) make the Modified Version available to the Copyright Holder
+ of the Standard Version, under the Original License, so that the
+ Copyright Holder may include your modifications in the Standard
+ Version.
+
+ (b) ensure that installation of your Modified Version does not
+ prevent the user installing or running the Standard Version. In
+ addition, the Modified Version must bear a name that is different
+ from the name of the Standard Version.
+
+ (c) allow anyone who receives a copy of the Modified Version to
+ make the Source form of the Modified Version available to others
+ under
+
+ (i) the Original License or
+
+ (ii) a license that permits the licensee to freely copy,
+ modify and redistribute the Modified Version using the same
+ licensing terms that apply to the copy that the licensee
+ received, and requires that the Source form of the Modified
+ Version, and of any works derived from it, be made freely
+ available in that license fees are prohibited but Distributor
+ Fees are allowed.
+
+
+Distribution of Compiled Forms of the Standard Version
+or Modified Versions without the Source
+
+(5) You may Distribute Compiled forms of the Standard Version without
+the Source, provided that you include complete instructions on how to
+get the Source of the Standard Version. Such instructions must be
+valid at the time of your distribution. If these instructions, at any
+time while you are carrying out such distribution, become invalid, you
+must provide new instructions on demand or cease further distribution.
+If you provide valid instructions or cease distribution within thirty
+days after you become aware that the instructions are invalid, then
+you do not forfeit any of your rights under this license.
+
+(6) You may Distribute a Modified Version in Compiled form without
+the Source, provided that you comply with Section 4 with respect to
+the Source of the Modified Version.
+
+
+Aggregating or Linking the Package
+
+(7) You may aggregate the Package (either the Standard Version or
+Modified Version) with other packages and Distribute the resulting
+aggregation provided that you do not charge a licensing fee for the
+Package. Distributor Fees are permitted, and licensing fees for other
+components in the aggregation are permitted. The terms of this license
+apply to the use and Distribution of the Standard or Modified Versions
+as included in the aggregation.
+
+(8) You are permitted to link Modified and Standard Versions with
+other works, to embed the Package in a larger work of your own, or to
+build stand-alone binary or bytecode versions of applications that
+include the Package, and Distribute the result without restriction,
+provided the result does not expose a direct interface to the Package.
+
+
+Items That are Not Considered Part of a Modified Version
+
+(9) Works (including, but not limited to, modules and scripts) that
+merely extend or make use of the Package, do not, by themselves, cause
+the Package to be a Modified Version. In addition, such works are not
+considered parts of the Package itself, and are not subject to the
+terms of this license.
+
+
+General Provisions
+
+(10) Any use, modification, and distribution of the Standard or
+Modified Versions is governed by this Artistic License. By using,
+modifying or distributing the Package, you accept this license. Do not
+use, modify, or distribute the Package, if you do not accept this
+license.
+
+(11) If your Modified Version has been derived from a Modified
+Version made by someone other than you, you are nevertheless required
+to ensure that your Modified Version complies with the requirements of
+this license.
+
+(12) This license does not grant you the right to use any trademark,
+service mark, tradename, or logo of the Copyright Holder.
+
+(13) This license includes the non-exclusive, worldwide,
+free-of-charge patent license to make, have made, use, offer to sell,
+sell, import and otherwise transfer the Package with respect to any
+patent claims licensable by the Copyright Holder that are necessarily
+infringed by the Package. If you institute patent litigation
+(including a cross-claim or counterclaim) against any party alleging
+that the Package constitutes direct or contributory patent
+infringement, then this Artistic License to you shall terminate on the
+date that such litigation is filed.
+
+(14) Disclaimer of Warranty:
+THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
+IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
+LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3a18de6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,41 @@
+# Pianoteq-Utils.lv2
+
+## LV2 Pianoteq utility plugins
+
+### Webpage
+
+Get more information at: [http://open-music-kontrollers.ch/lv2/pianoteq_utils](http://open-music-kontrollers.ch/lv2/pianoteq_utils)
+
+### Build status
+
+[![build status](https://gitlab.com/OpenMusicKontrollers/pianoteq_utils.lv2/badges/master/build.svg)](https://gitlab.com/OpenMusicKontrollers/pianoteq_utils.lv2/commits/master)
+
+### Dependencies
+
+* [LV2](http://lv2plug.in) (LV2 Plugin Standard)
+
+### Build / install
+
+ git clone https://git.open-music-kontrollers.ch/lv2/pianoteq_utils.lv2
+ cd pianoteq_utils.lv2
+ meson build
+ cd build
+ ninja -j4
+ sudo ninja install
+
+### License
+
+Copyright (c) 2018 Hanspeter Portner (dev@open-music-kontrollers.ch)
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the Artistic License 2.0 as published by
+The Perl Foundation.
+
+This source is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+Artistic License 2.0 for more details.
+
+You should have received a copy of the Artistic License 2.0
+along the source as a COPYING file. If not, obtain it from
+<http://www.perlfoundation.org/artistic_license_2_0>.
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..17e51c3
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.1.1
diff --git a/manifest.ttl.in b/manifest.ttl.in
new file mode 100644
index 0000000..5fba13e
--- /dev/null
+++ b/manifest.ttl.in
@@ -0,0 +1,29 @@
+# Copyright (c) 2018 Hanspeter Portner (dev@open-music-kontrollers.ch)
+#
+# This is free software: you can redistribute it and/or modify
+# it under the terms of the Artistic License 2.0 as published by
+# The Perl Foundation.
+#
+# This source is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Artistic License 2.0 for more details.
+#
+# You should have received a copy of the Artistic License 2.0
+# along the source as a COPYING file. If not, obtain it from
+# http://www.perlfoundation.org/artistic_license_2_0.
+
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
+
+@prefix pianoteq_utils: <http://open-music-kontrollers.ch/lv2/pianoteq_utils#> .
+
+# Demo Unmute
+pianoteq_utils:demo_unmute
+ a lv2:Plugin ;
+ lv2:minorVersion @MINOR_VERSION@ ;
+ lv2:microVersion @MICRO_VERSION@ ;
+ lv2:binary <pianoteq_utils@MODULE_SUFFIX@> ;
+ rdfs:seeAlso <pianoteq_utils.ttl> .
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..3b7c03c
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,65 @@
+project('pianoteq_utils.lv2', 'c', default_options : [
+ 'buildtype=release',
+ 'warning_level=1',
+ 'werror=false',
+ 'b_lto=true',
+ 'c_std=c11'])
+
+add_project_arguments('-D_GNU_SOURCE', language : 'c')
+
+conf_data = configuration_data()
+cc = meson.get_compiler('c')
+
+cp = find_program('cp')
+lv2_validate = find_program('lv2_validate', native : true, required : false)
+lv2lint = find_program('lv2lint', required : false)
+clone = [cp, '@INPUT@', '@OUTPUT@']
+
+m_dep = cc.find_library('m')
+lv2_dep = dependency('lv2', version : '>=1.14.0')
+
+inst_dir = join_paths(get_option('libdir'), 'lv2', meson.project_name())
+
+srcs = ['pianoteq_utils.c',
+ 'pianoteq_utils_demo_unmute.c']
+
+c_args = ['-fvisibility=hidden',
+ '-ffast-math']
+
+mod = shared_module('pianoteq_utils', srcs,
+ c_args : c_args,
+ name_prefix : '',
+ dependencies : [m_dep, lv2_dep],
+ install : true,
+ install_dir : inst_dir)
+
+version = run_command('cat', 'VERSION').stdout().strip().split('.')
+conf_data.set('MAJOR_VERSION', version[0])
+conf_data.set('MINOR_VERSION', version[1])
+conf_data.set('MICRO_VERSION', version[2])
+
+suffix = mod.full_path().strip().split('.')[-1]
+conf_data.set('MODULE_SUFFIX', '.' + suffix)
+
+manifest_ttl = configure_file(input : 'manifest.ttl.in', output : 'manifest.ttl',
+ configuration : conf_data,
+ install : true,
+ install_dir : inst_dir)
+
+dsp_ttl = custom_target('pianoteq_utils_ttl',
+ input : 'pianoteq_utils.ttl',
+ output : 'pianoteq_utils.ttl',
+ command : clone,
+ install : true,
+ install_dir : inst_dir)
+
+if lv2_validate.found()
+ test('LV2 validate', lv2_validate,
+ args : [manifest_ttl, dsp_ttl])
+endif
+
+if lv2lint.found()
+ test('LV2 lint', lv2lint,
+ args : ['-Ewarn',
+ 'http://open-music-kontrollers.ch/lv2/pianoteq_utils#demo_unmute'])
+endif
diff --git a/pianoteq_utils.c b/pianoteq_utils.c
new file mode 100644
index 0000000..dff7f5f
--- /dev/null
+++ b/pianoteq_utils.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#include <pianoteq_utils.h>
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch(index)
+ {
+ case 0:
+ return &pianoteq_utils_demo_unmute;
+
+ default:
+ return NULL;
+ }
+}
diff --git a/pianoteq_utils.h b/pianoteq_utils.h
new file mode 100644
index 0000000..f621454
--- /dev/null
+++ b/pianoteq_utils.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#ifndef _PIANOTEQ_UTILS_LV2_H
+#define _PIANOTEQ_UTILS_LV2_H
+
+#include <stdint.h>
+#if !defined(_WIN32)
+# include <sys/mman.h>
+#else
+# define mlock(...)
+# define munlock(...)
+#endif
+
+#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
+#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
+#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
+#include <lv2/lv2plug.in/ns/ext/state/state.h>
+#include <lv2/lv2plug.in/ns/ext/log/log.h>
+#include <lv2/lv2plug.in/ns/ext/log/logger.h>
+#include <lv2/lv2plug.in/ns/ext/options/options.h>
+#include <lv2/lv2plug.in/ns/ext/midi/midi.h>
+#include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define PIANOTEQ_UTILS_URI "http://open-music-kontrollers.ch/lv2/pianoteq_utils"
+#define PIANOTEQ_UTILS_PREFIX PIANOTEQ_UTILS_URI"#"
+
+// plugin uris
+#define PIANOTEQ_UTILS__demo_unmute PIANOTEQ_UTILS_PREFIX"demo_unmute"
+
+// paramer uris
+#define PIANOTEQ_UTILS__channel PIANOTEQ_UTILS_PREFIX"channel"
+
+extern const LV2_Descriptor pianoteq_utils_demo_unmute;
+
+typedef struct _craft_t craft_t;
+
+struct _craft_t {
+ union {
+ LV2_Atom_Sequence *seq;
+ uint8_t *buf;
+ };
+ LV2_Atom_Forge forge;
+ LV2_Atom_Forge_Frame frame;
+ LV2_Atom_Forge_Ref ref;
+};
+
+static inline void
+_craft_init(craft_t *craft, LV2_URID_Map *map)
+{
+ lv2_atom_forge_init(&craft->forge, map);
+}
+
+static inline void
+_craft_connect(craft_t *craft, LV2_Atom_Sequence *seq)
+{
+ craft->seq = seq;
+}
+
+static inline void
+_craft_in(craft_t *craft)
+{
+ const uint32_t capacity = craft->seq->atom.size;
+ lv2_atom_forge_set_buffer(&craft->forge, craft->buf, capacity);
+ craft->ref = lv2_atom_forge_sequence_head(&craft->forge, &craft->frame, 0);
+}
+
+static inline void
+_craft_clear(craft_t *craft)
+{
+ craft->ref = 0;
+ lv2_atom_sequence_clear(craft->seq);
+}
+
+static inline void
+_craft_out(craft_t *craft)
+{
+ if(craft->ref)
+ lv2_atom_forge_pop(&craft->forge, &craft->frame);
+ else
+ _craft_clear(craft);
+}
+
+#endif // _PIANOTEQ_UTILS_LV2_H
diff --git a/pianoteq_utils.ttl b/pianoteq_utils.ttl
new file mode 100644
index 0000000..4ce4314
--- /dev/null
+++ b/pianoteq_utils.ttl
@@ -0,0 +1,101 @@
+# Copyright (c) 2018 Hanspeter Portner (dev@open-music-kontrollers.ch)
+#
+# This is free software: you can redistribute it and/or modify
+# it under the terms of the Artistic License 2.0 as published by
+# The Perl Foundation.
+#
+# This source is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Artistic License 2.0 for more details.
+#
+# You should have received a copy of the Artistic License 2.0
+# along the source as a COPYING file. If not, obtain it from
+# http://www.perlfoundation.org/artistic_license_2_0.
+
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
+@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
+@prefix log: <http://lv2plug.in/ns/ext/log#> .
+@prefix state: <http://lv2plug.in/ns/ext/state#> .
+@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
+@prefix bufsz: <http://lv2plug.in/ns/ext/buf-size#> .
+@prefix rsz: <http://lv2plug.in/ns/ext/resize-port#> .
+@prefix opts: <http://lv2plug.in/ns/ext/options#> .
+@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
+@prefix units: <http://lv2plug.in/ns/extensions/units#> .
+
+@prefix lic: <http://opensource.org/licenses/> .
+@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
+@prefix proj: <http://open-music-kontrollers.ch/lv2/> .
+@prefix pianoteq_utils: <http://open-music-kontrollers.ch/lv2/pianoteq_utils#> .
+@prefix canvas: <http://open-music-kontrollers.ch/lv2/canvas#> .
+
+# Maintainer
+omk:me
+ a foaf:Person ;
+ foaf:name "Hanspeter Portner" ;
+ foaf:mbox <mailto:dev@open-music-kontrollers.ch> ;
+ foaf:homepage <http://open-music-kontrollers.ch> .
+
+# Project
+proj:pianoteq_utils
+ a doap:Project ;
+ doap:maintainer omk:me ;
+ doap:name "Pianoteq Utils" .
+
+# Parameters
+pianoteq_utils:channel
+ a lv2:Parameter ;
+ rdfs:label "Channel" ;
+ rdfs:comment "set channel" ;
+ rdfs:range atom:Int ;
+ lv2:minimum 0 ;
+ lv2:maximum 15 .
+
+# Demo Unmute
+pianoteq_utils:demo_unmute
+ a lv2:Plugin ,
+ lv2:AnalyserPlugin ;
+ doap:name "Pianoteq Utils Demo Unmute" ;
+ doap:license lic:Artistic-2.0 ;
+ lv2:project proj:pianoteq_utils ;
+ lv2:requiredFeature urid:map, state:loadDefaultState ;
+ lv2:optionalFeature lv2:isLive, lv2:hardRTCapable, state:threadSafeRestore, log:log ;
+ lv2:extensionData state:interface ;
+
+ lv2:port [
+ a lv2:InputPort ,
+ atom:AtomPort ;
+ atom:bufferType atom:Sequence ;
+ atom:supports patch:Message ,
+ midi:MidiEvent ;
+ lv2:index 0 ;
+ lv2:symbol "control" ;
+ lv2:name "Control" ;
+ lv2:designation lv2:control ;
+ ] , [
+ a lv2:OutputPort ,
+ atom:AtomPort ;
+ atom:bufferType atom:Sequence ;
+ atom:supports patch:Message ,
+ midi:MidiEvent ;
+ lv2:index 1 ;
+ lv2:symbol "notify" ;
+ lv2:name "Notify" ;
+ lv2:designation lv2:control ;
+ rsz:minimumSize 131072 ;
+ ] ;
+
+ patch:writable
+ pianoteq_utils:channel ;
+
+ state:state [
+ pianoteq_utils:channel 0 ;
+ ] .
diff --git a/pianoteq_utils_demo_unmute.c b/pianoteq_utils_demo_unmute.c
new file mode 100644
index 0000000..c52dd78
--- /dev/null
+++ b/pianoteq_utils_demo_unmute.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2018 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <pianoteq_utils.h>
+
+#include <props.lv2/props.h>
+
+#define MAX_NPROPS 1
+#define MAX_NMUTED 8
+
+typedef struct _msg_t msg_t;
+typedef struct _plugstate_t plugstate_t;
+typedef struct _plughandle_t plughandle_t;
+
+struct _msg_t {
+ LV2_Atom atom;
+ uint8_t msg [3];
+};
+
+struct _plugstate_t {
+ int32_t channel;
+};
+
+struct _plughandle_t {
+ LV2_URID_Map *map;
+
+ LV2_Log_Log *log;
+ LV2_Log_Logger logger;
+
+ const LV2_Atom_Sequence *control;
+ craft_t notify;
+
+ LV2_URID midi_MidiEvent;
+
+ plugstate_t state;
+ plugstate_t stash;
+
+ PROPS_T(props, MAX_NPROPS);
+};
+
+static const props_def_t defs [MAX_NPROPS] = {
+ {
+ .property = PIANOTEQ_UTILS__channel,
+ .offset = offsetof(plugstate_t, channel),
+ .type = LV2_ATOM__Int
+ }
+};
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor, double rate,
+ const char *bundle_path, const LV2_Feature *const *features)
+{
+ plughandle_t *handle = calloc(1, sizeof(plughandle_t));
+ if(!handle)
+ return NULL;
+ mlock(handle, sizeof(plughandle_t));
+
+ for(unsigned i=0; features[i]; i++)
+ {
+ if(!strcmp(features[i]->URI, LV2_URID__map))
+ handle->map = features[i]->data;
+ else if(!strcmp(features[i]->URI, LV2_LOG__log))
+ handle->log = features[i]->data;
+ }
+
+ if(!handle->map)
+ {
+ fprintf(stderr,
+ "%s: Host does not support urid:map\n", descriptor->URI);
+ free(handle);
+ return NULL;
+ }
+
+ if(handle->log)
+ {
+ lv2_log_logger_init(&handle->logger, handle->map, handle->log);
+ }
+
+ _craft_init(&handle->notify, handle->map);
+
+ handle->midi_MidiEvent = handle->map->map(handle->map->handle, LV2_MIDI__MidiEvent);
+
+ if(!props_init(&handle->props, descriptor->URI,
+ defs, MAX_NPROPS, &handle->state, &handle->stash,
+ handle->map, handle))
+ {
+ fprintf(stderr, "failed to initialize property structure\n");
+ free(handle);
+ return NULL;
+ }
+
+ return handle;
+}
+
+static void
+connect_port(LV2_Handle instance, uint32_t port, void *data)
+{
+ plughandle_t *handle = (plughandle_t *)instance;
+
+ switch(port)
+ {
+ case 0:
+ handle->control = (const void *)data;
+ break;
+ case 1:
+ _craft_connect(&handle->notify, data);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static const uint8_t muted [MAX_NMUTED] = {
+ 42, // F#+2
+ 44, // G#+2
+ 46, // A#+2
+
+ 85, // C#+6
+ 87, // D#+6
+ 90, // F#+6
+ 92, // G#+6
+ 94 // A#+6
+};
+
+static inline bool
+_is_muted(uint8_t key)
+{
+ for(unsigned i = 0; i < MAX_NMUTED; i++)
+ {
+ if(key == muted[i])
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static inline int
+_handle_midi(plughandle_t *handle, int64_t frames, const uint8_t *msg)
+{
+ const uint8_t cmd = msg[0] & 0xf0;
+
+ switch(cmd)
+ {
+ case LV2_MIDI_MSG_NOTE_ON:
+ // fall-through
+ case LV2_MIDI_MSG_NOTE_OFF:
+ // fall-through
+ case LV2_MIDI_MSG_NOTE_PRESSURE:
+ {
+ uint8_t cha = msg[0] & 0x0f;
+ uint8_t key = msg[1];
+ const uint8_t val = msg[2];
+
+ if(_is_muted(key))
+ {
+ cha = 0xf - (cha & 0x7);
+ key -= 1;
+
+ const int32_t range = 200; // cents
+ const int64_t off = 100 * 0x2000 / range;
+ const uint64_t bend = 0x1fff + off;
+ const uint8_t bend_msb = bend >> 7;
+ const uint8_t bend_lsb = bend & 0x7f;
+
+ const msg_t bnd = {
+ .atom = {
+ .size = 3,
+ .type = handle->midi_MidiEvent
+ },
+ .msg = {
+ [0] = LV2_MIDI_MSG_BENDER | cha,
+ [1] = bend_lsb,
+ [2] = bend_msb
+ }
+ };
+
+ const msg_t not = {
+ .atom = {
+ .size = 3,
+ .type = handle->midi_MidiEvent
+ },
+ .msg = {
+ [0] = cmd | cha,
+ [1] = key,
+ [2] = val
+ }
+ };
+
+ lv2_atom_forge_frame_time(&handle->notify.forge, frames);
+ lv2_atom_forge_write(&handle->notify.forge, &bnd, sizeof(msg_t));
+
+ lv2_atom_forge_frame_time(&handle->notify.forge, frames);
+ lv2_atom_forge_write(&handle->notify.forge, &not, sizeof(msg_t));
+
+ return 0; // message intercepted successfully
+ }
+
+ } break;
+ }
+
+ return 1;
+}
+
+static void
+run(LV2_Handle instance, uint32_t nsamples __attribute__((unused)))
+{
+ plughandle_t *handle = instance;
+
+ _craft_in(&handle->notify);
+
+ props_idle(&handle->props, &handle->notify.forge, 0, &handle->notify.ref);
+
+ LV2_ATOM_SEQUENCE_FOREACH(handle->control, ev)
+ {
+ const LV2_Atom *atom = &ev->body;
+
+ if(atom->type == handle->midi_MidiEvent)
+ {
+ const uint8_t *msg = LV2_ATOM_BODY_CONST(atom);
+ if(_handle_midi(handle, ev->time.frames, msg))
+ {
+ lv2_atom_forge_frame_time(&handle->notify.forge, ev->time.frames);
+ lv2_atom_forge_write(&handle->notify.forge, atom, lv2_atom_total_size(atom));
+ }
+ }
+ else
+ {
+ const LV2_Atom_Object *obj = (const LV2_Atom_Object *)atom;
+
+ props_advance(&handle->props, &handle->notify.forge, ev->time.frames, obj, &handle->notify.ref);
+ }
+ }
+
+ _craft_out(&handle->notify);
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ plughandle_t *handle = instance;
+
+ munlock(handle, sizeof(plughandle_t));
+ free(handle);
+}
+
+static LV2_State_Status
+_state_save(LV2_Handle instance, LV2_State_Store_Function store,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ plughandle_t *handle = instance;
+
+ return props_save(&handle->props, store, state, flags, features);
+}
+
+static LV2_State_Status
+_state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ plughandle_t *handle = instance;
+
+ return props_restore(&handle->props, retrieve, state, flags, features);
+}
+
+static const LV2_State_Interface state_iface = {
+ .save = _state_save,
+ .restore = _state_restore
+};
+
+static const void*
+extension_data(const char* uri)
+{
+ if(!strcmp(uri, LV2_STATE__interface))
+ return &state_iface;
+
+ return NULL;
+}
+
+const LV2_Descriptor pianoteq_utils_demo_unmute = {
+ .URI = PIANOTEQ_UTILS__demo_unmute,
+ .instantiate = instantiate,
+ .connect_port = connect_port,
+ .activate = NULL,
+ .run = run,
+ .deactivate = NULL,
+ .cleanup = cleanup,
+ .extension_data = extension_data
+};