Browse Source

parse options, add test plugin

master
parent
commit
4a66509a4f
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 2
      meson_options.txt
  2. 26
      plugins/common.h
  3. 1
      plugins/meson.build
  4. 4
      plugins/testplugin/README.md
  5. 81
      plugins/testplugin/common.h
  6. 260
      plugins/testplugin/dsp.c
  7. 92
      plugins/testplugin/ttl.h

2
meson_options.txt

@ -34,7 +34,7 @@ option ( @@ -34,7 +34,7 @@ option (
'Distortion',
'EQ', 'LFO', 'LimiterSP', 'PhaserSP',
'PitchSP', 'Saturator',
'VerbSP', 'Saw'
'VerbSP', 'Saw', 'TestPlugin',
],
description: 'Plugins to build')

26
plugins/common.h

@ -40,6 +40,7 @@ @@ -40,6 +40,7 @@
#include "lv2/log/log.h"
#include "lv2/log/logger.h"
#include "lv2/midi/midi.h"
#include "lv2/options/options.h"
#include "lv2/urid/urid.h"
#include "lv2/time/time.h"
#include "lv2/worker/worker.h"
@ -90,6 +91,8 @@ typedef struct PluginCommon @@ -90,6 +91,8 @@ typedef struct PluginCommon
/** Atom forge. */
LV2_Atom_Forge forge;
LV2_Options_Option * options;
/** URIs. */
PluginUris uris;
@ -155,12 +158,12 @@ map_common_uris ( @@ -155,12 +158,12 @@ map_common_uris (
*/
static inline int
plugin_common_instantiate (
PluginCommon * pl_common,
PluginCommon * self,
const LV2_Feature * const * features,
int with_worker)
{
#ifdef TRIAL_VER
pl_common->instantiation_time = clock ();
self->instantiation_time = clock ();
#endif
#define HAVE_FEATURE(x) \
@ -170,36 +173,41 @@ plugin_common_instantiate ( @@ -170,36 +173,41 @@ plugin_common_instantiate (
{
if (HAVE_FEATURE (LV2_URID__map))
{
pl_common->map =
self->map =
(LV2_URID_Map*) features[i]->data;
}
else if (HAVE_FEATURE (LV2_LOG__log))
{
pl_common->log =
self->log =
(LV2_Log_Log *) features[i]->data;
}
else if (HAVE_FEATURE (LV2_OPTIONS__options))
{
self->options =
(LV2_Options_Option*) features[i]->data;
}
if (with_worker)
{
if (HAVE_FEATURE (LV2_WORKER__schedule))
{
pl_common->schedule =
self->schedule =
(LV2_Worker_Schedule *) features[i]->data;
}
}
}
#undef HAVE_FEATURE
if (!pl_common->map)
if (!self->map)
{
lv2_log_error (
&pl_common->logger, "Missing feature urid:map\n");
&self->logger, "Missing feature urid:map\n");
return -1;
}
else if (with_worker && !pl_common->schedule)
else if (with_worker && !self->schedule)
{
lv2_log_error (
&pl_common->logger,
&self->logger,
"Missing feature work:schedule\n");
return -1;
}

1
plugins/meson.build

@ -26,6 +26,7 @@ plugins = [ @@ -26,6 +26,7 @@ plugins = [
#['Saturator', 'DistortionPlugin', '0.1.0'],
['Saw', 'InstrumentPlugin', '1.0.0'],
['VerbSP', 'ReverbPlugin', '0.1.0'],
['TestPlugin', 'MIDIPlugin', '0.1.0'],
]
if os_darwin

4
plugins/testplugin/README.md

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
Test Plugin
===========
Used for testing Zrythm features.

81
plugins/testplugin/common.h

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
/*
* Copyright (C) 2021 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZPlugins 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
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file
*
* Common code for both the DSP and the UI.
*/
#ifndef __Z_TEST_PLUGIN_COMMON_H__
#define __Z_TEST_PLUGIN_COMMON_H__
#include PLUGIN_CONFIG
#include "../common.h"
typedef struct TestPluginUris
{
} TestPluginUris;
typedef enum PortIndex
{
/** GUI to plugin communication. */
TEST_PLUGIN_CONTROL,
/** Plugin to UI communication. */
TEST_PLUGIN_NOTIFY,
TEST_PLUGIN_MAJOR,
/** Outputs. */
TEST_PLUGIN_MIDI_OUT,
NUM_PORTS,
} PortIndex;
/**
* Group of variables needed by both the DSP and
* the UI.
*/
typedef struct TestPluginCommon
{
/** Custom URIs. */
TestPluginUris uris;
PluginCommon pl_common;
} TestPluginCommon;
static inline void
map_uris (
LV2_URID_Map* urid_map,
TestPluginCommon * chordz_common)
{
map_common_uris (
urid_map, &chordz_common->pl_common.uris);
#define MAP(x,uri) \
chordz_common->uris.x = \
urid_map->map (urid_map->handle, uri)
/* custom URIs */
#undef MAP
}
#endif

260
plugins/testplugin/dsp.c

@ -0,0 +1,260 @@ @@ -0,0 +1,260 @@
/*
* Copyright (C) 2018, 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZPlugins 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
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
#include PLUGIN_CONFIG
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "../math.h"
#include PLUGIN_COMMON
/**
* Struct for a 3 byte MIDI event, used for writing notes.
*/
typedef struct MidiNoteEvent
{
LV2_Atom_Event event;
uint8_t msg[3];
} MidiNoteEvent;
typedef struct TestPlugin
{
/** Plugin ports. */
const LV2_Atom_Sequence* control;
LV2_Atom_Sequence* notify;
const float * major;
/* outputs */
LV2_Atom_Sequence * midi_out;
TestPluginCommon common;
} TestPlugin;
static LV2_Handle
instantiate (
const LV2_Descriptor* descriptor,
double rate,
const char* bundle_path,
const LV2_Feature* const* features)
{
TestPlugin * self = calloc (1, sizeof (TestPlugin));
SET_SAMPLERATE (self, rate);
PluginCommon * pl_common = &self->common.pl_common;
int ret =
plugin_common_instantiate (
pl_common, features, 0);
if (ret)
goto fail;
/* map uris */
map_uris (pl_common->map, &self->common);
/* init atom forge */
lv2_atom_forge_init (
&pl_common->forge, pl_common->map);
/* init logger */
lv2_log_logger_init (
&pl_common->logger, pl_common->map, pl_common->log);
/* print info */
if (pl_common->options)
{
int j = 0;
while (true)
{
LV2_Options_Option opt;
memcpy (
&opt, &pl_common->options[j++],
sizeof (LV2_Options_Option));
if (opt.key == 0 && opt.value == 0)
{
break;
}
if (opt.key ==
pl_common->map->map (
pl_common->map->handle,
"https://lv2.zrythm.org/ns/ext/host-info#name"))
{
lv2_log_note (
&pl_common->logger, "Host: %s\n",
*((const char **) opt.value));
}
if (opt.key ==
pl_common->map->map (
pl_common->map->handle,
"https://lv2.zrythm.org/ns/ext/host-info#version"))
{
lv2_log_note (
&pl_common->logger, "Host Version: %s\n",
*((const char **) opt.value));
}
}
}
return (LV2_Handle) self;
fail:
free (self);
return NULL;
}
static void
connect_port (
LV2_Handle instance,
uint32_t port,
void * data)
{
TestPlugin * self = (TestPlugin *) instance;
switch ((PortIndex) port)
{
case TEST_PLUGIN_CONTROL:
self->control =
(const LV2_Atom_Sequence *) data;
break;
case TEST_PLUGIN_NOTIFY:
self->notify =
(LV2_Atom_Sequence *) data;
break;
case TEST_PLUGIN_MAJOR:
self->major = (const float *) data;
break;
case TEST_PLUGIN_MIDI_OUT:
self->midi_out =
(LV2_Atom_Sequence *) data;
break;
default:
break;
}
}
static void
activate (
LV2_Handle instance)
{
/*TestPlugin * self = (TestPlugin*) instance;*/
}
static void
run (
LV2_Handle instance,
uint32_t n_samples)
{
TestPlugin * self = (TestPlugin *) instance;
#ifdef TRIAL_VER
if (get_time_since_instantiation (
&self->common.pl_common) > SECONDS_TO_SILENCE)
return;
#endif
const uint32_t out_capacity =
self->midi_out->atom.size;
/* write an empty Sequence header to the output */
lv2_atom_sequence_clear (self->midi_out);
self->midi_out->atom.type = self->control->atom.type;
/* read incoming events from host and UI */
LV2_ATOM_SEQUENCE_FOREACH (
self->control, ev)
{
if (ev->body.type == PL_URIS(self)->midi_MidiEvent)
{
const uint8_t * const msg =
(const uint8_t *) (ev + 1);
switch (lv2_midi_message_type(msg))
{
case LV2_MIDI_MSG_NOTE_ON:
break;
case LV2_MIDI_MSG_NOTE_OFF:
break;
case LV2_MIDI_MSG_CONTROLLER:
/* all notes off */
if (msg[1] == 0x7b)
{
}
break;
default:
/* forward all other MIDI events directly */
lv2_atom_sequence_append_event(
self->midi_out, out_capacity, ev);
break;
}
}
}
}
static void
deactivate (
LV2_Handle instance)
{
/*Saw * self = (Saw *) instance;*/
}
static void
cleanup (
LV2_Handle instance)
{
TestPlugin * self = (TestPlugin *) instance;
free (self);
}
static const void*
extension_data (
const char * uri)
{
return NULL;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
activate,
run,
deactivate,
cleanup,
extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor*
lv2_descriptor (
uint32_t index)
{
switch (index)
{
case 0:
return &descriptor;
default:
return NULL;
}
}

92
plugins/testplugin/ttl.h

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
/*
* Copyright (C) 2021 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZPlugins 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
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
static void
print_ttl (FILE * f)
{
fprintf (f,
"@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\
@prefix doap: <http://usefulinc.com/ns/doap#> .\n\
@prefix log: <http://lv2plug.in/ns/ext/log#> .\n\
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n\
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .\n\
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .\n\
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
@prefix rsz: <http://lv2plug.in/ns/ext/resize-port#> .\n\
@prefix time: <http://lv2plug.in/ns/ext/time#> .\n\
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .\n\
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n\
@prefix work: <http://lv2plug.in/ns/ext/worker#> .\n\n");
fprintf (f,
"<" PLUGIN_URI ">\n\
a lv2:Plugin,\n\
lv2:MIDIPlugin ;\n\
doap:name \"" PLUGIN_NAME "\" ;\n\
doap:license <https://www.gnu.org/licenses/agpl-3.0.html> ;\n\
lv2:project <" PROJECT_URI "> ;\n\
lv2:requiredFeature urid:map ;\n\
lv2:optionalFeature log:log ,\n\
lv2:hardRTCapable ;\n\
lv2:port [\n\
a lv2:InputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n\
rsz:minimumSize 2048 ;\n\
lv2:index 0 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"control\" ;\n\
lv2:name \"Control\" ;\n\
rdfs:comment \"GUI/host to plugin communication\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
lv2:index 1 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"notify\" ;\n\
lv2:name \"Notify\" ;\n\
rdfs:comment \"Plugin to GUI communication\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 2 ;\n\
lv2:symbol \"major\" ;\n\
lv2:name \"Major\" ;\n\
lv2:portProperty lv2:toggled ;\n\
lv2:default 1 ;\n\
lv2:minimum 0 ;\n\
lv2:maximum 1 ;\n\
] , [\n");
fprintf (f, "\
a lv2:OutputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n\
rsz:minimumSize 2048 ;\n\
lv2:index 3 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"midi_out\" ;\n\
lv2:name \"MIDI out\" ;\n\
rdfs:comment \"MIDI output\" ;\n\
] .\n\n");
}
Loading…
Cancel
Save