# HG changeset patch
# User František Kučera <franta-hg@frantovo.cz>
# Date 1589567557 -7200
# Node ID d6614ad97bed0fa6f739abfbb83c7503e40badc1
# Parent  2f84ed5f3abf2e3ebad5f79d490e86686e65cf54
LV2: modul zesilovače, dle oficiálního příkladu, ale bez závislosti na Pythonu – stačí gcc a make

diff -r 2f84ed5f3abf -r d6614ad97bed c++/lv2-demo-modul/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c++/lv2-demo-modul/Makefile	Fri May 15 20:32:37 2020 +0200
@@ -0,0 +1,20 @@
+all: amp.so
+
+amp.so: amp.cpp
+	g++ -g -shared -fPIC amp.cpp -o amp.so
+
+clean:
+	rm -f amp.so
+
+info: amp.so
+	nm amp.so
+	ldd amp.so
+	file amp.so
+
+install: amp.so
+	mkdir -p ~/.lv2/amp/
+	cp amp.so amp.ttl manifest.ttl ~/.lv2/amp/
+	lv2info http://lv2plug.in/plugins/eg-amp
+
+uninstall:
+	rm -rf ~/.lv2/amp/
diff -r 2f84ed5f3abf -r d6614ad97bed c++/lv2-demo-modul/amp.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c++/lv2-demo-modul/amp.cpp	Fri May 15 20:32:37 2020 +0200
@@ -0,0 +1,222 @@
+/*
+  Copyright 2006-2016 David Robillard <d@drobilla.net>
+  Copyright 2006 Steve Harris <steve@plugin.org.uk>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+   LV2 headers are based on the URI of the specification they come from, so a
+   consistent convention can be used even for unofficial extensions.  The URI
+   of the core LV2 specification is <http://lv2plug.in/ns/lv2core>, by
+   replacing `http:/` with `lv2` any header in the specification bundle can be
+   included, in this case `lv2.h`.
+ */
+#include <lv2.h>
+
+/** Include standard C headers */
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/**
+   The URI is the identifier for a plugin, and how the host associates this
+   implementation in code with its description in data.  In this plugin it is
+   only used once in the code, but defining the plugin URI at the top of the
+   file is a good convention to follow.  If this URI does not match that used
+   in the data files, the host will fail to load the plugin.
+ */
+#define AMP_URI "http://lv2plug.in/plugins/eg-amp"
+
+/**
+   In code, ports are referred to by index.  An enumeration of port indices
+   should be defined for readability.
+ */
+typedef enum {
+	AMP_GAIN = 0,
+	AMP_INPUT = 1,
+	AMP_OUTPUT = 2
+} PortIndex;
+
+/**
+   Every plugin defines a private structure for the plugin instance.  All data
+   associated with a plugin instance is stored here, and is available to
+   every instance method.  In this simple plugin, only port buffers need to be
+   stored, since there is no additional instance data.
+ */
+typedef struct {
+	// Port buffers
+	const float* gain;
+	const float* input;
+	float* output;
+} Amp;
+
+/**
+   The `instantiate()` function is called by the host to create a new plugin
+   instance.  The host passes the plugin descriptor, sample rate, and bundle
+   path for plugins that need to load additional resources (e.g. waveforms).
+   The features parameter contains host-provided features defined in LV2
+   extensions, but this simple plugin does not use any.
+
+   This function is in the ``instantiation'' threading class, so no other
+   methods on this instance will be called concurrently with it.
+ */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+		double rate,
+		const char* bundle_path,
+		const LV2_Feature * const* features) {
+	Amp* amp = (Amp*) calloc(1, sizeof (Amp));
+
+	return (LV2_Handle) amp;
+}
+
+/**
+   The `connect_port()` method is called by the host to connect a particular
+   port to a buffer.  The plugin must store the data location, but data may not
+   be accessed except in run().
+
+   This method is in the ``audio'' threading class, and is called in the same
+   context as run().
+ */
+static void
+connect_port(LV2_Handle instance,
+		uint32_t port,
+		void* data) {
+	Amp* amp = (Amp*) instance;
+
+	switch ((PortIndex) port) {
+		case AMP_GAIN:
+			amp->gain = (const float*) data;
+			break;
+		case AMP_INPUT:
+			amp->input = (const float*) data;
+			break;
+		case AMP_OUTPUT:
+			amp->output = (float*) data;
+			break;
+	}
+}
+
+/**
+   The `activate()` method is called by the host to initialise and prepare the
+   plugin instance for running.  The plugin must reset all internal state
+   except for buffer locations set by `connect_port()`.  Since this plugin has
+   no other internal state, this method does nothing.
+
+   This method is in the ``instantiation'' threading class, so no other
+   methods on this instance will be called concurrently with it.
+ */
+static void
+activate(LV2_Handle instance) {
+}
+
+/** Define a macro for converting a gain in dB to a coefficient. */
+#define DB_CO(g) ((g) > -90.0f ? powf(10.0f, (g) * 0.05f) : 0.0f)
+
+/**
+   The `run()` method is the main process function of the plugin.  It processes
+   a block of audio in the audio context.  Since this plugin is
+   `lv2:hardRTCapable`, `run()` must be real-time safe, so blocking (e.g. with
+   a mutex) or memory allocation are not allowed.
+ */
+static void
+run(LV2_Handle instance, uint32_t n_samples) {
+	const Amp* amp = (const Amp*) instance;
+
+	const float gain = *(amp->gain);
+	const float* const input = amp->input;
+	float* const output = amp->output;
+
+	const float coef = DB_CO(gain);
+
+	for (uint32_t pos = 0; pos < n_samples; pos++) {
+		output[pos] = input[pos] * coef;
+	}
+}
+
+/**
+   The `deactivate()` method is the counterpart to `activate()`, and is called by
+   the host after running the plugin.  It indicates that the host will not call
+   `run()` again until another call to `activate()` and is mainly useful for more
+   advanced plugins with ``live'' characteristics such as those with auxiliary
+   processing threads.  As with `activate()`, this plugin has no use for this
+   information so this method does nothing.
+
+   This method is in the ``instantiation'' threading class, so no other
+   methods on this instance will be called concurrently with it.
+ */
+static void
+deactivate(LV2_Handle instance) {
+}
+
+/**
+   Destroy a plugin instance (counterpart to `instantiate()`).
+
+   This method is in the ``instantiation'' threading class, so no other
+   methods on this instance will be called concurrently with it.
+ */
+static void
+cleanup(LV2_Handle instance) {
+	free(instance);
+}
+
+/**
+   The `extension_data()` function returns any extension data supported by the
+   plugin.  Note that this is not an instance method, but a function on the
+   plugin descriptor.  It is usually used by plugins to implement additional
+   interfaces.  This plugin does not have any extension data, so this function
+   returns NULL.
+
+   This method is in the ``discovery'' threading class, so no other functions
+   or methods in this plugin library will be called concurrently with it.
+ */
+static const void*
+extension_data(const char* uri) {
+	return NULL;
+}
+
+/**
+   Every plugin must define an `LV2_Descriptor`.  It is best to define
+   descriptors statically to avoid leaking memory and non-portable shared
+   library constructors and destructors to clean up properly.
+ */
+static const LV2_Descriptor descriptor = {
+	AMP_URI,
+	instantiate,
+	connect_port,
+	activate,
+	run,
+	deactivate,
+	cleanup,
+	extension_data
+};
+
+/**
+   The `lv2_descriptor()` function is the entry point to the plugin library.  The
+   host will load the library and call this function repeatedly with increasing
+   indices to find all the plugins defined in the library.  The index is not an
+   indentifier, the URI of the returned descriptor is used to determine the
+   identify of the plugin.
+
+   This method is in the ``discovery'' threading class, so no other functions
+   or methods in this plugin library will be called concurrently with it.
+ */
+LV2_SYMBOL_EXPORT
+const LV2_Descriptor*
+lv2_descriptor(uint32_t index) {
+	switch (index) {
+		case 0: return &descriptor;
+		default: return NULL;
+	}
+}
diff -r 2f84ed5f3abf -r d6614ad97bed c++/lv2-demo-modul/amp.ttl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c++/lv2-demo-modul/amp.ttl	Fri May 15 20:32:37 2020 +0200
@@ -0,0 +1,90 @@
+# The full description of the plugin is in this file, which is linked to from
+# `manifest.ttl`.  This is done so the host only needs to scan the relatively
+# small `manifest.ttl` files to quickly discover all plugins.
+
+@prefix doap:  <http://usefulinc.com/ns/doap#> .
+@prefix lv2:   <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix units: <http://lv2plug.in/ns/extensions/units#> .
+
+# First the type of the plugin is described.  All plugins must explicitly list
+# `lv2:Plugin` as a type.  A more specific type should also be given, where
+# applicable, so hosts can present a nicer UI for loading plugins.  Note that
+# this URI is the identifier of the plugin, so if it does not match the one in
+# `manifest.ttl`, the host will not discover the plugin data at all.
+<http://lv2plug.in/plugins/eg-amp>
+	a lv2:Plugin ,
+		lv2:AmplifierPlugin ;
+# Plugins are associated with a project, where common information like
+# developers, home page, and so on are described.  This plugin is part of the
+# LV2 project, which has URI <http://lv2plug.in/ns/lv2>, and is described
+# elsewhere.  Typical plugin collections will describe the project in
+# manifest.ttl
+	lv2:project <http://lv2plug.in/ns/lv2> ;
+# Every plugin must have a name, described with the doap:name property.
+# Translations to various languages can be added by putting a language tag
+# after strings as shown.
+	doap:name "Simple Amplifier" ,
+		"简单放大器"@zh ,
+		"Einfacher Verstärker"@de ,
+		"Simple Amplifier"@en-gb ,
+		"Amplificador Simple"@es ,
+		"Amplificateur de Base"@fr ,
+		"Amplificatore Semplice"@it ,
+		"簡単なアンプ"@jp ,
+		"Просто Усилитель"@ru ;
+	doap:license <http://opensource.org/licenses/isc> ;
+	lv2:optionalFeature lv2:hardRTCapable ;
+	lv2:port [
+# Every port must have at least two types, one that specifies direction
+# (lv2:InputPort or lv2:OutputPort), and another to describe the data type.
+# This port is a lv2:ControlPort, which means it contains a single float.
+		a lv2:InputPort ,
+			lv2:ControlPort ;
+		lv2:index 0 ;
+		lv2:symbol "gain" ;
+		lv2:name "Gain" ,
+			"收益"@zh ,
+			"Verstärkung"@de ,
+			"Gain"@en-gb ,
+			"Aumento"@es ,
+			"Gain"@fr ,
+			"Guadagno"@it ,
+			"利益"@jp ,
+			"Увеличение"@ru ;
+# An lv2:ControlPort should always describe its default value, and usually a
+# minimum and maximum value.  Defining a range is not strictly required, but
+# should be done wherever possible to aid host support, particularly for UIs.
+		lv2:default 0.0 ;
+		lv2:minimum -90.0 ;
+		lv2:maximum 24.0 ;
+# Ports can describe units and control detents to allow better UI generation
+# and host automation.
+		units:unit units:db ;
+		lv2:scalePoint [
+			rdfs:label "+5" ;
+			rdf:value 5.0
+		] , [
+			rdfs:label "0" ;
+			rdf:value 0.0
+		] , [
+			rdfs:label "-5" ;
+			rdf:value -5.0
+		] , [
+			rdfs:label "-10" ;
+			rdf:value -10.0
+		]
+	] , [
+		a lv2:AudioPort ,
+			lv2:InputPort ;
+		lv2:index 1 ;
+		lv2:symbol "in" ;
+		lv2:name "In"
+	] , [
+		a lv2:AudioPort ,
+			lv2:OutputPort ;
+		lv2:index 2 ;
+		lv2:symbol "out" ;
+		lv2:name "Out"
+	] .
diff -r 2f84ed5f3abf -r d6614ad97bed c++/lv2-demo-modul/manifest.ttl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c++/lv2-demo-modul/manifest.ttl	Fri May 15 20:32:37 2020 +0200
@@ -0,0 +1,68 @@
+# LV2 plugins are installed in a ``bundle'', a directory with a standard
+# structure.  Each bundle has a Turtle file named `manifest.ttl` which lists
+# the contents of the bundle.
+#
+# Hosts typically read the manifest of every installed bundle to discover
+# plugins on start-up, so it should be as small as possible for performance
+# reasons.  Details that are only useful if the host chooses to load the plugin
+# are stored in other files and linked to from `manifest.ttl`.
+#
+# ==== URIs ====
+#
+# LV2 makes use of URIs as globally-unique identifiers for resources.  For
+# example, the ID of the plugin described here is
+# `<http://lv2plug.in/plugins/eg-amp>`.  Note that URIs are only used as
+# identifiers and don't necessarily imply that something can be accessed at
+# that address on the web (though that may be the case).
+#
+# ==== Namespace Prefixes ====
+#
+# Turtle files contain many URIs, but prefixes can be defined to improve
+# readability.  For example, with the `lv2:` prefix below, `lv2:Plugin` can be
+# written instead of `<http://lv2plug.in/ns/lv2core#Plugin>`.
+
+@prefix lv2:  <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+# ==== Describing a Plugin ====
+
+# Turtle files contain a set of ``statements'' which describe resources.
+# This file contains 3 statements:
+# [options="header"]
+# |================================================================
+# | Subject                             | Predicate    | Object
+# | <http://lv2plug.in/plugins/eg-amp>  | a            | lv2:Plugin
+# | <http://lv2plug.in/plugins/eg-amp>  | lv2:binary   | <amp.so>
+# | <http://lv2plug.in/plugins/eg-amp>  | rdfs:seeAlso | <amp.ttl>
+# |================================================================
+
+# Firstly, `<http://lv2plug.in/plugins/eg-amp>` is an LV2 plugin:
+<http://lv2plug.in/plugins/eg-amp> a lv2:Plugin .
+
+# The predicate ```a`'' is a Turtle shorthand for `rdf:type`.
+
+# The binary of that plugin can be found at `<amp.ext>`:
+<http://lv2plug.in/plugins/eg-amp> lv2:binary <amp.so> .
+
+# This file is a template; the token `@LIB_EXT@` is replaced by the build
+# system with the appropriate extension for the current platform before
+# installation.  For example, in the output `manifest.ttl`, the binary would be
+# listed as `<amp.so>`.  Relative URIs in manifests are relative to the bundle
+# directory, so this refers to a binary with the given name in the same
+# directory as this manifest.
+
+# Finally, more information about this plugin can be found in `<amp.ttl>`:
+<http://lv2plug.in/plugins/eg-amp> rdfs:seeAlso <amp.ttl> .
+
+# ==== Abbreviation ====
+#
+# This file shows these statements individually for instructive purposes, but
+# the subject `<http://lv2plug.in/plugins/eg-amp>` is repetitive.  Turtle
+# allows the semicolon to be used as a delimiter that repeats the previous
+# subject.  For example, this manifest would more realistically be written like
+# so:
+
+<http://lv2plug.in/plugins/eg-amp>
+	a lv2:Plugin ;
+	lv2:binary <amp.so>  ;
+	rdfs:seeAlso <amp.ttl> .