Browse Source

add ttl generator

master
Alexandros Theodotou 3 years ago
parent
commit
9a1c8b2951
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 27
      meson.build
  2. 57
      zlfo.c
  3. 117
      zlfo.ttl.in
  4. 73
      zlfo_common.h
  5. 304
      zlfo_ttl_gen.c
  6. 99
      zlfo_ui.c

27
meson.build

@ -190,23 +190,34 @@ zlfo_ui_lib = shared_library ( @@ -190,23 +190,34 @@ zlfo_ui_lib = shared_library (
install_dir: zlfodir,
)
# create and install ttls
# create and install manifest ttl
manifest_ttl = configure_file (
input: 'manifest.ttl.in',
output: 'manifest.ttl',
configuration: zlfo_cdata,
)
zlfo_ttl = configure_file (
input: 'zlfo.ttl.in',
output: 'zlfo.ttl',
configuration: zlfo_cdata,
)
install_data (
manifest_ttl,
install_dir: zlfodir,
)
install_data (
zlfo_ttl,
# create and install zlfo ttl
lv2_ttl_gen = executable (
'lv2_ttl_gen',
sources: [
'zlfo_ttl_gen.c',
],
include_directories: '.',
c_args: common_cflags,
install: false,
)
zlfo_ttl = custom_target (
'zlfo.ttl',
output: 'zlfo.ttl',
input: [ lv2_ttl_gen, zlfo_config_h ],
command: [
lv2_ttl_gen, '@OUTPUT@' ],
install: true,
install_dir: zlfodir,
)

57
zlfo.c

@ -37,15 +37,18 @@ typedef struct ZLFO @@ -37,15 +37,18 @@ typedef struct ZLFO
/** Plugin ports. */
const LV2_Atom_Sequence* control;
LV2_Atom_Sequence* notify;
const float * gate;
const float * trigger;
const float * freq;
const float * phase;
const int * follow_time;
float * sine;
float * saw_up;
float * saw_down;
float * triangle;
float * square;
float * random;
const float * shift;
const float * range_min;
const float * range_max;
const float * step_mode;
const float * freerun;
/* outputs */
float * cv_out;
float * audio_out;
/** Frequency during the last run. */
float last_freq;
@ -133,38 +136,52 @@ connect_port ( @@ -133,38 +136,52 @@ connect_port (
switch ((PortIndex) port)
{
case LFO_CONTROL:
case ZLFO_CONTROL:
self->control =
(const LV2_Atom_Sequence *) data;
break;
case LFO_NOTIFY:
case ZLFO_NOTIFY:
self->notify =
(LV2_Atom_Sequence *) data;
break;
case LFO_FREQ:
case ZLFO_FREQ:
self->freq = (const float *) data;
break;
case LFO_PHASE:
self->phase = (const float *) data;
case ZLFO_SHIFT:
self->shift = (const float *) data;
break;
case ZLFO_RANGE_MIN:
self->range_min = (const float *) data;
break;
case ZLFO_RANGE_MAX:
self->range_max = (const float *) data;
break;
case ZLFO_STEP_MODE:
self->step_mode = (const float *) data;
break;
case ZLFO_FREE_RUNNING:
self->freerun = (const float *) data;
break;
case LFO_SINE:
#if 0
case ZLFO_SINE:
self->sine = (float *) data;
break;
case LFO_SAW_UP:
case ZLFO_SAW_UP:
self->saw_up = (float *) data;
break;
case LFO_SAW_DOWN:
case ZLFO_SAW_DOWN:
self->saw_down = (float *) data;
break;
case LFO_TRIANGLE:
case ZLFO_TRIANGLE:
self->triangle = (float *) data;
break;
case LFO_SQUARE:
case ZLFO_SQUARE:
self->square = (float *) data;
break;
case LFO_RANDOM:
case ZLFO_RANDOM:
self->random = (float *) data;
break;
#endif
default:
break;
}
@ -239,6 +256,7 @@ run ( @@ -239,6 +256,7 @@ run (
recalc_multipliers (self);
}
#if 0
for (uint32_t i = 0; i < n_samples; i++)
{
/* handle sine */
@ -276,6 +294,7 @@ run ( @@ -276,6 +294,7 @@ run (
self->samples_processed++;
}
#endif
/* remember frequency */
self->last_freq = *self->freq;

117
zlfo.ttl.in

@ -1,117 +0,0 @@ @@ -1,117 +0,0 @@
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix log: <http://lv2plug.in/ns/ext/log#> .
<@LFO_URI@>
a lv2:Plugin,
lv2:OscillatorPlugin ;
doap:name "ZLFO" ;
doap:maintainer [
foaf:name """Alexandros Theodotou""" ;
foaf:homepage <https://www.zrythm.org> ;
] ;
doap:license <https://www.gnu.org/licenses/agpl-3.0.html> ;
lv2:project <@PROJECT_URI@> ;
lv2:requiredFeature urid:map ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:optionalFeature log:log ;
lv2:port [
a lv2:InputPort ,
atom:AtomPort ;
atom:bufferType atom:Sequence ;
lv2:index 0 ;
lv2:designation lv2:control ;
lv2:symbol "control" ;
lv2:name "Control" ;
rdfs:comment "GUI to plugin communication" ;
] , [
a lv2:OutputPort ,
atom:AtomPort ;
atom:bufferType atom:Sequence ;
lv2:index 1 ;
lv2:designation lv2:control ;
lv2:symbol "notify" ;
lv2:name "Notify" ;
rdfs:comment "Plugin to GUI communication" ;
] , [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 2 ;
lv2:symbol "freq" ;
lv2:name "Frequency" ;
lv2:default 1.0 ;
lv2:minimum 0.0 ;
lv2:maximum 20.0 ;
] , [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3 ;
lv2:symbol "phase" ;
lv2:name "Phase" ;
lv2:default 0.5 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
] , [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 4 ;
lv2:symbol "follow_time" ;
lv2:name "Follow time" ;
lv2:default 0.1 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
] , [
a lv2:OutputPort ,
lv2:CVPort ;
lv2:index 5 ;
lv2:symbol "sine" ;
lv2:name "Sine" ;
] , [
a lv2:OutputPort ,
lv2:CVPort ;
lv2:index 6 ;
lv2:symbol "saw_up" ;
lv2:name "Saw Up" ;
] , [
a lv2:OutputPort ,
lv2:CVPort ;
lv2:index 7 ;
lv2:symbol "saw_down" ;
lv2:name "Saw Down" ;
] , [
a lv2:OutputPort ,
lv2:CVPort ;
lv2:index 8 ;
lv2:symbol "triangle" ;
lv2:name "Triangle" ;
] , [
a lv2:OutputPort ,
lv2:CVPort ;
lv2:index 9 ;
lv2:symbol "square" ;
lv2:name "Square" ;
] , [
a lv2:OutputPort ,
lv2:CVPort ;
lv2:index 10 ;
lv2:symbol "random" ;
lv2:name "Random" ;
] .
<@LFO_UI_URI@>
a ui:X11UI ;
lv2:requiredFeature urid:map ;
lv2:optionalFeature log:log ;
lv2:optionalFeature ui:noUserResize ;
lv2:extensionData ui:idleInterface ;
ui:portNotification [
ui:plugin "@LFO_URI@" ;
lv2:symbol "notify" ;
ui:notifyType atom:Blank ;
] .

73
zlfo_common.h

@ -49,18 +49,69 @@ typedef struct ZLfoUris @@ -49,18 +49,69 @@ typedef struct ZLfoUris
typedef enum PortIndex
{
/** GUI to plugin communication. */
LFO_CONTROL,
ZLFO_CONTROL,
/** Plugin to UI communication. */
LFO_NOTIFY,
LFO_FREQ,
LFO_PHASE,
LFO_FOLLOW_TIME,
LFO_SINE,
LFO_SAW_UP,
LFO_SAW_DOWN,
LFO_TRIANGLE,
LFO_SQUARE,
LFO_RANDOM,
ZLFO_NOTIFY,
ZLFO_GATE,
ZLFO_TRIGGER,
ZLFO_FREQ,
ZLFO_SHIFT,
ZLFO_RANGE_MIN,
ZLFO_RANGE_MAX,
ZLFO_STEP_MODE,
ZLFO_FREE_RUNNING,
ZLFO_NODE_1_POS,
ZLFO_NODE_1_VAL,
ZLFO_NODE_1_CURVE,
ZLFO_NODE_2_POS,
ZLFO_NODE_2_VAL,
ZLFO_NODE_2_CURVE,
ZLFO_NODE_3_POS,
ZLFO_NODE_3_VAL,
ZLFO_NODE_3_CURVE,
ZLFO_NODE_4_POS,
ZLFO_NODE_4_VAL,
ZLFO_NODE_4_CURVE,
ZLFO_NODE_5_POS,
ZLFO_NODE_5_VAL,
ZLFO_NODE_5_CURVE,
ZLFO_NODE_6_POS,
ZLFO_NODE_6_VAL,
ZLFO_NODE_6_CURVE,
ZLFO_NODE_7_POS,
ZLFO_NODE_7_VAL,
ZLFO_NODE_7_CURVE,
ZLFO_NODE_8_POS,
ZLFO_NODE_8_VAL,
ZLFO_NODE_8_CURVE,
ZLFO_NODE_9_POS,
ZLFO_NODE_9_VAL,
ZLFO_NODE_9_CURVE,
ZLFO_NODE_10_POS,
ZLFO_NODE_10_VAL,
ZLFO_NODE_10_CURVE,
ZLFO_NODE_11_POS,
ZLFO_NODE_11_VAL,
ZLFO_NODE_11_CURVE,
ZLFO_NODE_12_POS,
ZLFO_NODE_12_VAL,
ZLFO_NODE_12_CURVE,
ZLFO_NODE_13_POS,
ZLFO_NODE_13_VAL,
ZLFO_NODE_13_CURVE,
ZLFO_NODE_14_POS,
ZLFO_NODE_14_VAL,
ZLFO_NODE_14_CURVE,
ZLFO_NODE_15_POS,
ZLFO_NODE_15_VAL,
ZLFO_NODE_15_CURVE,
ZLFO_NODE_16_POS,
ZLFO_NODE_16_VAL,
ZLFO_NUM_NODES,
ZLFO_CV_OUT,
ZLFO_AUDIO_OUT,
NUM_ZLFO_PORTS,
} PortIndex;
static inline void

304
zlfo_ttl_gen.c

@ -0,0 +1,304 @@ @@ -0,0 +1,304 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZLFO
*
* ZLFO 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.
*
* ZLFO 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 ZLFO. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdio.h>
#include "zlfo_common.h"
typedef enum PortType
{
PORT_TYPE_FLOAT,
PORT_TYPE_INT,
PORT_TYPE_TOGGLE,
} PortType;
typedef enum NodeProperty
{
NODE_PROP_POS,
NODE_PROP_VAL,
NODE_PROP_CURVE,
} NodeProperty;
int main (
int argc, const char* argv[])
{
if (argc != 2)
{
fprintf (
stderr,
"Need 1 argument, received %d\n", argc - 1);
return -1;
}
FILE * f = fopen (argv[1], "w");
if (!f)
{
fprintf (
stderr, "Failed to open file %s\n", argv[1]);
return -1;
}
fprintf (f,
"@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\
@prefix doap: <http://usefulinc.com/ns/doap#> .\n\
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n\
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .\n\
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n\
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .\n\
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n\
@prefix log: <http://lv2plug.in/ns/ext/log#> .\n\n");
fprintf (f,
"<" LFO_URI ">\n\
a lv2:Plugin,\n\
lv2:OscillatorPlugin ;\n\
doap:name \"ZLFO\" ;\n\
doap:maintainer [\n\
foaf:name \"\"\"Alexandros Theodotou\"\"\" ;\n\
foaf:homepage <https://www.zrythm.org> ;\n\
] ;\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 lv2:hardRTCapable ;\n\
lv2:optionalFeature log:log ;\n\
lv2:port [\n\
a lv2:InputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
lv2:index 0 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"control\" ;\n\
lv2:name \"Control\" ;\n\
rdfs:comment \"GUI 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");
/* write input controls */
int index = ZLFO_GATE;
for (int i = index; i <= ZLFO_NUM_NODES; i++)
{
float def = 0.f;
float min = 0.f;
float max = 1.f;
int defi = 0;
int mini = 0;
int maxi = 1;
int is_trigger = 0;
PortType type = PORT_TYPE_FLOAT;
char symbol[256] = "\0";
char name[256] = "\0";
char comment[800] = "\0";
switch (i)
{
case ZLFO_GATE:
strcpy (symbol, "gate");
strcpy (name, "Gate");
strcpy (
comment, "Not used at the moment");
break;
case ZLFO_TRIGGER:
strcpy (symbol, "trigger");
strcpy (name, "Trigger");
is_trigger = 1;
break;
case ZLFO_FREQ:
strcpy (symbol, "freq");
strcpy (name, "Frequency");
strcpy (
comment, "Frequency if free running");
def = 1.f;
max = 20.f;
break;
case ZLFO_SHIFT:
strcpy (symbol, "shift");
strcpy (name, "Shift");
strcpy (comment, "Shift (phase)");
def = 0.5f;
break;
case ZLFO_RANGE_MIN:
strcpy (symbol, "range_min");
strcpy (name, "Range min");
min = -1.f;
def = -1.f;
break;
case ZLFO_RANGE_MAX:
strcpy (symbol, "range_max");
strcpy (name, "Range max");
min = -1.f;
def = 1.f;
break;
case ZLFO_STEP_MODE:
strcpy (symbol, "step_mode");
strcpy (name, "Step mode");
strcpy (comment, "Step mode enabled");
type = PORT_TYPE_TOGGLE;
break;
case ZLFO_FREE_RUNNING:
strcpy (symbol, "free_running");
strcpy (name, "Free running");
strcpy (comment, "Free run toggle");
type = PORT_TYPE_TOGGLE;
def = 1.f;
break;
case ZLFO_NUM_NODES:
strcpy (symbol, "num_nodes");
strcpy (name, "Node count");
type = PORT_TYPE_INT;
defi = 2;
mini = 2;
maxi = 16;
break;
default:
break;
}
if (i >= ZLFO_NODE_1_POS &&
i <= ZLFO_NODE_16_VAL)
{
NodeProperty prop =
(i - ZLFO_NODE_1_POS) % 3;
int node_id = (i - ZLFO_NODE_1_POS) / 3 + 1;
switch (prop)
{
case NODE_PROP_POS:
sprintf (
symbol, "node_%d_pos", node_id);
sprintf (
name, "Node %d position", node_id);
if (node_id == 2)
def = 1.f;
break;
case NODE_PROP_VAL:
sprintf (
symbol, "node_%d_val", node_id);
sprintf (
name, "Node %d value", node_id);
if (node_id == 1)
def = 1.f;
break;
case NODE_PROP_CURVE:
sprintf (
symbol, "node_%d_curve", node_id);
sprintf (
name, "Node %d curve", node_id);
break;
default:
break;
}
}
/* write port */
fprintf (f,
" a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index %d ;\n\
lv2:symbol \"%s\" ;\n\
lv2:name \"%s\" ;\n",
i, symbol, name);
if (comment[0] != '\0')
{
fprintf (f,
" rdfs:comment \"%s\" ;\n",
comment);
}
if (type == PORT_TYPE_FLOAT ||
type == PORT_TYPE_TOGGLE)
{
fprintf (f,
" lv2:default %f ;\n\
lv2:minimum %f ;\n\
lv2:maximum %f ;\n",
(double) def, (double) min, (double) max);
}
else if (type == PORT_TYPE_INT)
{
fprintf (f,
" lv2:default %d ;\n\
lv2:minimum %d ;\n\
lv2:maximum %d ;\n",
defi, mini, maxi);
}
if (is_trigger)
{
fprintf (f,
" lv2:portProperty lv2:trigger ;\n");
}
else if (type == PORT_TYPE_INT)
{
fprintf (f,
" lv2:portProperty lv2:integer ;\n");
}
else if (type == PORT_TYPE_TOGGLE)
{
fprintf (f,
" lv2:portProperty lv2:toggled ;\n");
}
fprintf (f,
" ] , [\n");
}
/* write cv out and audio out */
fprintf (f,
" a lv2:OutputPort ,\n\
lv2:CVPort ;\n\
lv2:index %d ;\n\
lv2:symbol \"cv_out\" ;\n\
lv2:name \"CV output\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\
lv2:index %d ;\n\
lv2:symbol \"audio_out\" ;\n\
lv2:name \"Audio output\" ;\n\
] .\n\n", ZLFO_CV_OUT, ZLFO_AUDIO_OUT);
/* write UI */
fprintf (f,
"<" LFO_UI_URI ">\n\
a ui:X11UI ;\n\
lv2:requiredFeature urid:map ;\n\
lv2:optionalFeature log:log ;\n\
lv2:optionalFeature ui:noUserResize ;\n\
lv2:extensionData ui:idleInterface ;\n\
ui:portNotification [\n\
ui:plugin \"" LFO_URI "\" ;\n\
lv2:symbol \"notify\" ;\n\
ui:notifyType atom:Blank ;\n\
] .");
fclose (f);
return 0;
}

99
zlfo_ui.c

@ -122,23 +122,27 @@ typedef enum DrawDataType @@ -122,23 +122,27 @@ typedef enum DrawDataType
typedef struct ZLfoUi
{
/** Port values. */
float freq;
float phase;
float freq;
float shift;
float range_min;
float range_max;
int step_mode;
int freerun;
LV2UI_Write_Function write;
LV2UI_Controller controller;
LV2UI_Controller controller;
/** Map feature. */
LV2_URID_Map * map;
LV2_URID_Map * map;
/** Atom forge. */
LV2_Atom_Forge forge;
LV2_Atom_Forge forge;
/** Log feature. */
LV2_Log_Log * log;
LV2_Log_Log * log;
/** URIs. */
ZLfoUris uris;
ZLfoUris uris;
/**
* This is the window passed in the features from
@ -146,14 +150,14 @@ typedef struct ZLfoUi @@ -146,14 +150,14 @@ typedef struct ZLfoUi
*
* The pugl window will be wrapped in here.
*/
void * parent_window;
void * parent_window;
/**
* Resize handle for the parent window.
*/
LV2UI_Resize* resize;
LV2UI_Resize* resize;
ZtkApp * app;
ZtkApp * app;
} ZLfoUi;
/**
@ -291,6 +295,47 @@ add_left_buttons ( @@ -291,6 +295,47 @@ add_left_buttons (
}
}
static int
is_btn_mode_active (
DrawData * data)
{
ZLfoUi * self = data->zlfo_ui;
switch (data->type)
{
case DATA_TYPE_BTN_TOP:
switch (data->val)
{
case TOP_BTN_CURVE:
return !self->step_mode;
break;
case TOP_BTN_STEP:
return self->step_mode;
break;
}
break;
case DATA_TYPE_BTN_LEFT:
break;
case DATA_TYPE_BTN_BOT:
switch (data->val)
{
case BOT_BTN_SYNC:
return !self->freerun;
break;
case BOT_BTN_FREE:
return self->freerun;
break;
}
break;
case DATA_TYPE_BTN_GRID:
break;
case DATA_TYPE_LBL:
break;
}
return 0;
}
static void
top_btn_draw_cb (
ZtkWidget * widget,
@ -301,7 +346,8 @@ top_btn_draw_cb ( @@ -301,7 +346,8 @@ top_btn_draw_cb (
ZtkWidgetState state = widget->state;
int is_normal = 0;
int clicked = 0;
if (state & ZTK_WIDGET_STATE_PRESSED)
if (state & ZTK_WIDGET_STATE_PRESSED ||
is_btn_mode_active (data))
{
zlfo_ui_theme_set_cr_color (cr, selected_bg);
clicked = 1;
@ -395,7 +441,8 @@ bot_btn_draw_cb ( @@ -395,7 +441,8 @@ bot_btn_draw_cb (
ZtkWidgetState state = widget->state;
int is_normal = 0;
int clicked = 0;
if (state & ZTK_WIDGET_STATE_PRESSED)
if (state & ZTK_WIDGET_STATE_PRESSED ||
is_btn_mode_active (data))
{
zlfo_ui_theme_set_cr_color (cr, selected_bg);
clicked = 1;
@ -706,7 +753,7 @@ shift_control_getter ( @@ -706,7 +753,7 @@ shift_control_getter (
ZtkControl * control,
ZLfoUi * self)
{
return self->phase;
return self->shift;
}
static void
@ -715,8 +762,8 @@ shift_control_setter ( @@ -715,8 +762,8 @@ shift_control_setter (
ZLfoUi * self,
float val)
{
self->phase = val;
SEND_PORT_EVENT (self, LFO_PHASE, self->phase);
self->shift = val;
SEND_PORT_EVENT (self, ZLFO_SHIFT, self->shift);
}
/**
@ -1134,11 +1181,27 @@ port_event ( @@ -1134,11 +1181,27 @@ port_event (
{
switch (port_index)
{
case LFO_FREQ:
case ZLFO_FREQ:
self->freq = * (const float *) buffer;
break;
case LFO_PHASE:
self->phase = * (const float *) buffer;
case ZLFO_SHIFT:
self->shift = * (const float *) buffer;
break;
case ZLFO_RANGE_MIN:
self->range_min =
* (const float *) buffer;
break;
case ZLFO_RANGE_MAX:
self->range_max =
* (const float *) buffer;
break;
case ZLFO_STEP_MODE:
self->step_mode =
(int) * (const float *) buffer;
break;
case ZLFO_FREE_RUNNING:
self->freerun =
(int) * (const float *) buffer;
break;
default:
break;

Loading…
Cancel
Save