mirror of https://github.com/dcoredump/dexed.git
parent
04c65a5da0
commit
af19d28a2e
@ -1,12 +0,0 @@ |
|||||||
#!/bin/sh |
|
||||||
export LV2_PATH="/usr/local/lib/lv2" |
|
||||||
jackd --silent -r -d dummy & |
|
||||||
mod-host -i <<ENDOFDATA |
|
||||||
add https://github.com/dcoredump/dexed.lv2 0 |
|
||||||
add http://gareus.org/oss/lv2/stepseq#s8n8 1 |
|
||||||
connect effect_1:midiout effect_0:midi_in |
|
||||||
connect effect_0:lv2_audio_out_1 system:playback_1 |
|
||||||
connect effect_0:lv2_audio_out_1 system:playback_2 |
|
||||||
param_set 1 grid_1_1 1 |
|
||||||
param_set 1 grid_2_3 1 |
|
||||||
ENDOFDADA |
|
@ -1,22 +0,0 @@ |
|||||||
BUNDLE = lv2pftci-beep.lv2
|
|
||||||
INSTALL_DIR = /home/pi/zynthian/zynthian-plugins/mod-lv2
|
|
||||||
|
|
||||||
$(BUNDLE): manifest.ttl beep.ttl beep.so |
|
||||||
rm -rf $(BUNDLE)
|
|
||||||
mkdir $(BUNDLE)
|
|
||||||
cp $^ $(BUNDLE)
|
|
||||||
|
|
||||||
beep.so: beep.cpp beep.peg |
|
||||||
g++ -shared -fPIC -DPIC beep.cpp `pkg-config --cflags --libs lv2-plugin` -o beep.so
|
|
||||||
|
|
||||||
beep.peg: beep.ttl |
|
||||||
lv2peg beep.ttl beep.peg
|
|
||||||
|
|
||||||
install: $(BUNDLE) |
|
||||||
mkdir -p $(INSTALL_DIR)
|
|
||||||
rm -rf $(INSTALL_DIR)/$(BUNDLE)
|
|
||||||
cp -R $(BUNDLE) $(INSTALL_DIR)
|
|
||||||
|
|
||||||
clean: |
|
||||||
rm -rf $(BUNDLE) beep.so beep.peg
|
|
||||||
|
|
@ -1,61 +0,0 @@ |
|||||||
// from: http://ll-plugins.nongnu.org/lv2pftci/#A_synth
|
|
||||||
|
|
||||||
#include <lv2synth.hpp> |
|
||||||
#include "beep.peg" |
|
||||||
|
|
||||||
|
|
||||||
class BeepVoice : public LV2::Voice { |
|
||||||
public: |
|
||||||
|
|
||||||
BeepVoice(double rate)
|
|
||||||
: m_key(LV2::INVALID_KEY), m_rate(rate), m_period(10), m_counter(0) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void on(unsigned char key, unsigned char velocity) {
|
|
||||||
m_key = key; |
|
||||||
m_period = m_rate * 4.0 / LV2::key2hz(m_key); |
|
||||||
} |
|
||||||
|
|
||||||
void off(unsigned char velocity) {
|
|
||||||
m_key = LV2::INVALID_KEY; |
|
||||||
} |
|
||||||
|
|
||||||
unsigned char get_key() const {
|
|
||||||
return m_key;
|
|
||||||
} |
|
||||||
|
|
||||||
void render(uint32_t from, uint32_t to) { |
|
||||||
if (m_key == LV2::INVALID_KEY) |
|
||||||
return; |
|
||||||
for (uint32_t i = from; i < to; ++i) { |
|
||||||
float s = -0.25 + 0.5 * (m_counter > m_period / 2); |
|
||||||
m_counter = (m_counter + 1) % m_period; |
|
||||||
p(p_left)[i] += s; |
|
||||||
p(p_right)[i] += s; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
|
|
||||||
unsigned char m_key; |
|
||||||
double m_rate; |
|
||||||
uint32_t m_period; |
|
||||||
uint32_t m_counter; |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
class Beep : public LV2::Synth<BeepVoice, Beep> { |
|
||||||
public: |
|
||||||
|
|
||||||
Beep(double rate) |
|
||||||
: LV2::Synth<BeepVoice, Beep>(p_n_ports, p_midi) { |
|
||||||
add_voices(new BeepVoice(rate), new BeepVoice(rate), new BeepVoice(rate)); |
|
||||||
add_audio_outputs(p_left, p_right); |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
static int _ = Beep::register_class(p_uri); |
|
@ -1,35 +0,0 @@ |
|||||||
#ifndef beep_peg |
|
||||||
#define beep_peg |
|
||||||
|
|
||||||
|
|
||||||
#ifndef PEG_STRUCT |
|
||||||
#define PEG_STRUCT |
|
||||||
typedef struct { |
|
||||||
float min; |
|
||||||
float max; |
|
||||||
float default_value; |
|
||||||
char toggled; |
|
||||||
char integer; |
|
||||||
char logarithmic; |
|
||||||
} peg_data_t; |
|
||||||
#endif |
|
||||||
|
|
||||||
/* <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> */ |
|
||||||
|
|
||||||
static const char p_uri[] = "http://ll-plugins.nongnu.org/lv2/lv2pftci/beep"; |
|
||||||
|
|
||||||
enum p_port_enum { |
|
||||||
p_midi, |
|
||||||
p_left, |
|
||||||
p_right, |
|
||||||
p_n_ports |
|
||||||
}; |
|
||||||
|
|
||||||
static const peg_data_t p_ports[] = { |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif /* beep_peg */ |
|
@ -1,49 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin; |
|
||||||
lv2:binary <beep.so>; |
|
||||||
doap:name "Beep"; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl>; |
|
||||||
ll:pegName "p"; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a lv2:InputPort, atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
lv2:index 0; |
|
||||||
ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent>; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 1; |
|
||||||
lv2:symbol "left"; |
|
||||||
lv2:name "Left"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 2; |
|
||||||
lv2:symbol "right"; |
|
||||||
lv2:name "Right"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out>; |
|
||||||
pg:role pg:rightChannel; |
|
||||||
]; |
|
||||||
]. |
|
@ -1,49 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin; |
|
||||||
lv2:binary <beep.so>; |
|
||||||
doap:name "Beep"; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl>; |
|
||||||
ll:pegName "p"; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a lv2:InputPort, atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
lv2:index 0; |
|
||||||
ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent>; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 1; |
|
||||||
lv2:symbol "left"; |
|
||||||
lv2:name "Left"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 2; |
|
||||||
lv2:symbol "right"; |
|
||||||
lv2:name "Right"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out>; |
|
||||||
pg:role pg:rightChannel; |
|
||||||
]; |
|
||||||
]. |
|
@ -1,5 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. |
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin; |
|
||||||
rdfs:seeAlso <beep.ttl>. |
|
@ -1,5 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. |
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin; |
|
||||||
rdfs:seeAlso <beep.ttl>. |
|
@ -1,22 +0,0 @@ |
|||||||
BUNDLE = lv2pftci-beep.lv2
|
|
||||||
INSTALL_DIR = /home/pi/zynthian/zynthian-plugins/mod-lv2
|
|
||||||
|
|
||||||
$(BUNDLE): manifest.ttl beep.ttl beep.so |
|
||||||
rm -rf $(BUNDLE)
|
|
||||||
mkdir $(BUNDLE)
|
|
||||||
cp $^ $(BUNDLE)
|
|
||||||
|
|
||||||
beep.so: beep.cpp beep.peg |
|
||||||
g++ -shared -fPIC -DPIC beep.cpp -I. -I/usr/local/include/lvtk-2 -L/usr/local/lib -llvtk_plugin2 -o beep.so
|
|
||||||
|
|
||||||
beep.peg: beep.ttl |
|
||||||
lv2peg beep.ttl beep.peg
|
|
||||||
|
|
||||||
install: $(BUNDLE) |
|
||||||
mkdir -p $(INSTALL_DIR)
|
|
||||||
rm -rf $(INSTALL_DIR)/$(BUNDLE)
|
|
||||||
cp -R $(BUNDLE) $(INSTALL_DIR)
|
|
||||||
|
|
||||||
clean: |
|
||||||
rm -rf $(BUNDLE) beep.so beep.peg
|
|
||||||
|
|
@ -1,91 +0,0 @@ |
|||||||
/*
|
|
||||||
beep.cpp - LV2 Toolkit API Demonstration Plugin |
|
||||||
|
|
||||||
Copyright (C) 2004-2010 Lars Luthman |
|
||||||
Updated for LVTK by Michael Fisher <mfisher31@gmail.com> |
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or |
|
||||||
modify it under the terms of the GNU General Public License as |
|
||||||
published by the Free Software Foundation; either version 2 of |
|
||||||
the License, or (at your option) any later version. |
|
||||||
|
|
||||||
This program 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 General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program; if not, write to the Free Software |
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
||||||
|
|
||||||
*/ |
|
||||||
/** @file beep.cpp */ |
|
||||||
|
|
||||||
|
|
||||||
#include <lvtk/synth.hpp> |
|
||||||
#include "beep.peg" |
|
||||||
|
|
||||||
class BeepVoice : public lvtk::Voice |
|
||||||
{ |
|
||||||
public: |
|
||||||
|
|
||||||
BeepVoice (double rate) |
|
||||||
: m_key(lvtk::INVALID_KEY), m_rate(rate), m_period(10), m_counter(0) |
|
||||||
{ } |
|
||||||
|
|
||||||
void |
|
||||||
on (unsigned char key, unsigned char velocity) |
|
||||||
{ |
|
||||||
m_key = key; |
|
||||||
m_period = m_rate * 4.0 / lvtk::key2hz(m_key); |
|
||||||
} |
|
||||||
|
|
||||||
void |
|
||||||
off (unsigned char velocity) |
|
||||||
{ |
|
||||||
m_key = lvtk::INVALID_KEY; |
|
||||||
} |
|
||||||
|
|
||||||
unsigned char |
|
||||||
get_key() const |
|
||||||
{ |
|
||||||
return m_key; |
|
||||||
} |
|
||||||
|
|
||||||
void |
|
||||||
render(uint32_t from, uint32_t to) |
|
||||||
{ |
|
||||||
if (m_key == lvtk::INVALID_KEY) return; |
|
||||||
|
|
||||||
for (uint32_t i = from; i < to; ++i) |
|
||||||
{ |
|
||||||
float s = -0.25 + 0.5 * (m_counter > m_period / 2); |
|
||||||
m_counter = (m_counter + 1) % m_period; |
|
||||||
p(p_left)[i] += s; |
|
||||||
p(p_right)[i] += s; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
|
|
||||||
unsigned char m_key; |
|
||||||
double m_rate; |
|
||||||
uint32_t m_period; |
|
||||||
uint32_t m_counter; |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
class Beep : public lvtk::Synth<BeepVoice, Beep> |
|
||||||
{ |
|
||||||
public: |
|
||||||
|
|
||||||
Beep (double rate) : lvtk::Synth<BeepVoice, Beep> (p_n_ports, p_midi) |
|
||||||
{ |
|
||||||
add_voices (new BeepVoice(rate), new BeepVoice(rate), new BeepVoice(rate)); |
|
||||||
add_audio_outputs (p_left, p_right); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
static int _ = Beep::register_class(p_uri); |
|
@ -1,35 +0,0 @@ |
|||||||
#ifndef beep_peg |
|
||||||
#define beep_peg |
|
||||||
|
|
||||||
|
|
||||||
#ifndef PEG_STRUCT |
|
||||||
#define PEG_STRUCT |
|
||||||
typedef struct { |
|
||||||
float min; |
|
||||||
float max; |
|
||||||
float default_value; |
|
||||||
char toggled; |
|
||||||
char integer; |
|
||||||
char logarithmic; |
|
||||||
} peg_data_t; |
|
||||||
#endif |
|
||||||
|
|
||||||
/* <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> */ |
|
||||||
|
|
||||||
static const char p_uri[] = "http://ll-plugins.nongnu.org/lv2/lv2pftci/beep"; |
|
||||||
|
|
||||||
enum p_port_enum { |
|
||||||
p_midi, |
|
||||||
p_left, |
|
||||||
p_right, |
|
||||||
p_n_ports |
|
||||||
}; |
|
||||||
|
|
||||||
static const peg_data_t p_ports[] = { |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif /* beep_peg */ |
|
@ -1,67 +0,0 @@ |
|||||||
# Copyright (C) 2004-2010 Lars Luthman |
|
||||||
# Updated for LVTK by Michael Fisher <mfisher31@gmail.com> |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License as |
|
||||||
# published by the Free Software Foundation; either version 2 of |
|
||||||
# the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program 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 General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
||||||
|
|
||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . |
|
||||||
@prefix lvtkp: <http://lvtoolkit.org/plugins/> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin ; |
|
||||||
doap:name "Beep" ; |
|
||||||
lv2:project lvtkp: ; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl> ; |
|
||||||
ui:ui <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/gui> ; |
|
||||||
ll:pegName "p" ; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a atom:AtomPort , lv2:InputPort ; |
|
||||||
lv2:index 0; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
|
|
||||||
] , [ |
|
||||||
a lv2:AudioPort |
|
||||||
, lv2:OutputPort ; |
|
||||||
lv2:index 1 ; |
|
||||||
lv2:symbol "left" ; |
|
||||||
lv2:name "Left" ; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
] , [ |
|
||||||
a lv2:AudioPort , |
|
||||||
lv2:OutputPort ; |
|
||||||
lv2:index 2 ; |
|
||||||
lv2:symbol "right" ; |
|
||||||
lv2:name "Right" ; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out> ; |
|
||||||
pg:role pg:rightChannel ; |
|
||||||
] ; |
|
||||||
] . |
|
@ -1,67 +0,0 @@ |
|||||||
# Copyright (C) 2004-2010 Lars Luthman |
|
||||||
# Updated for LVTK by Michael Fisher <mfisher31@gmail.com> |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License as |
|
||||||
# published by the Free Software Foundation; either version 2 of |
|
||||||
# the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program 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 General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
||||||
|
|
||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . |
|
||||||
@prefix lvtkp: <http://lvtoolkit.org/plugins/> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin ; |
|
||||||
doap:name "Beep" ; |
|
||||||
lv2:project lvtkp: ; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl> ; |
|
||||||
ui:ui <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/gui> ; |
|
||||||
ll:pegName "p" ; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a atom:AtomPort , lv2:InputPort ; |
|
||||||
lv2:index 0; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
|
|
||||||
] , [ |
|
||||||
a lv2:AudioPort |
|
||||||
, lv2:OutputPort ; |
|
||||||
lv2:index 1 ; |
|
||||||
lv2:symbol "left" ; |
|
||||||
lv2:name "Left" ; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
] , [ |
|
||||||
a lv2:AudioPort , |
|
||||||
lv2:OutputPort ; |
|
||||||
lv2:index 2 ; |
|
||||||
lv2:symbol "right" ; |
|
||||||
lv2:name "Right" ; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep/out> ; |
|
||||||
pg:role pg:rightChannel ; |
|
||||||
] ; |
|
||||||
] . |
|
@ -1,44 +0,0 @@ |
|||||||
# Copyright (C) 2013 Michael Fisher <mfisher31@gmail.com> |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License as |
|
||||||
# published by the Free Software Foundation; either version 2 of |
|
||||||
# the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program 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 General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
||||||
|
|
||||||
@prefix doap: <http://usefulinc.com/ns/doap#> . |
|
||||||
@prefix foaf: <http://xmlns.com/foaf/0.1/> . |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . |
|
||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#> . |
|
||||||
@prefix lvtkp: <http://lvtoolkit.org/plugins/> . |
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . |
|
||||||
|
|
||||||
|
|
||||||
<http://lvtoolkit.org/people/mfisher> |
|
||||||
a foaf:Person ; |
|
||||||
foaf:name "Michael Fisher" ; |
|
||||||
foaf:mbox <mailto:mfisher31@gmail.com> ; |
|
||||||
rdfs:seeAlso <http://lvtoolkit.org> . |
|
||||||
|
|
||||||
lvtkp: |
|
||||||
a doap:Project ; |
|
||||||
lv2:symbol "lvtk" ; |
|
||||||
doap:name "LVTK Examples" ; |
|
||||||
doap:shortdesc "Example plugins demonstrating the LVTK api." ; |
|
||||||
doap:homepage <http://lvtoolkit.org> ; |
|
||||||
doap:maintainer <http://lvtoolkit.org/people/mfisher> ; |
|
||||||
doap:developer <http://lvtoolkit.org/people/mfisher> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin ; |
|
||||||
lv2:binary <beep.so> ; |
|
||||||
rdfs:seeAlso <beep.ttl> . |
|
||||||
|
|
@ -1,44 +0,0 @@ |
|||||||
# Copyright (C) 2013 Michael Fisher <mfisher31@gmail.com> |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License as |
|
||||||
# published by the Free Software Foundation; either version 2 of |
|
||||||
# the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program 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 General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
||||||
|
|
||||||
@prefix doap: <http://usefulinc.com/ns/doap#> . |
|
||||||
@prefix foaf: <http://xmlns.com/foaf/0.1/> . |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . |
|
||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#> . |
|
||||||
@prefix lvtkp: <http://lvtoolkit.org/plugins/> . |
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . |
|
||||||
|
|
||||||
|
|
||||||
<http://lvtoolkit.org/people/mfisher> |
|
||||||
a foaf:Person ; |
|
||||||
foaf:name "Michael Fisher" ; |
|
||||||
foaf:mbox <mailto:mfisher31@gmail.com> ; |
|
||||||
rdfs:seeAlso <http://lvtoolkit.org> . |
|
||||||
|
|
||||||
lvtkp: |
|
||||||
a doap:Project ; |
|
||||||
lv2:symbol "lvtk" ; |
|
||||||
doap:name "LVTK Examples" ; |
|
||||||
doap:shortdesc "Example plugins demonstrating the LVTK api." ; |
|
||||||
doap:homepage <http://lvtoolkit.org> ; |
|
||||||
doap:maintainer <http://lvtoolkit.org/people/mfisher> ; |
|
||||||
doap:developer <http://lvtoolkit.org/people/mfisher> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep> |
|
||||||
a lv2:Plugin ; |
|
||||||
lv2:binary <beep.so> ; |
|
||||||
rdfs:seeAlso <beep.ttl> . |
|
||||||
|
|
@ -1,23 +0,0 @@ |
|||||||
BUNDLE = lv2pftci-beep2.lv2
|
|
||||||
INSTALL_DIR = /home/pi/zynthian/zynthian-plugins/mod-lv2
|
|
||||||
|
|
||||||
|
|
||||||
$(BUNDLE): manifest.ttl beep2.ttl beep2.so |
|
||||||
rm -rf $(BUNDLE)
|
|
||||||
mkdir $(BUNDLE)
|
|
||||||
cp $^ $(BUNDLE)
|
|
||||||
|
|
||||||
beep2.so: beep.cpp beep.peg |
|
||||||
g++ -shared -fPIC -DPIC beep.cpp `pkg-config --cflags --libs lv2-plugin` -o beep2.so
|
|
||||||
|
|
||||||
beep.peg: beep2.ttl |
|
||||||
lv2peg beep2.ttl beep.peg
|
|
||||||
|
|
||||||
install: $(BUNDLE) |
|
||||||
mkdir -p $(INSTALL_DIR)
|
|
||||||
rm -rf $(INSTALL_DIR)/$(BUNDLE)
|
|
||||||
cp -R $(BUNDLE) $(INSTALL_DIR)
|
|
||||||
|
|
||||||
clean: |
|
||||||
rm -rf $(BUNDLE) beep2.so beep.peg
|
|
||||||
|
|
@ -1,95 +0,0 @@ |
|||||||
// from: http://ll-plugins.nongnu.org/lv2pftci/#A_synth
|
|
||||||
|
|
||||||
#include <lv2synth.hpp> |
|
||||||
#include "beep.peg" |
|
||||||
#include <cstdlib> |
|
||||||
|
|
||||||
class BeepVoice : public LV2::Voice { |
|
||||||
public: |
|
||||||
|
|
||||||
BeepVoice(double rate)
|
|
||||||
: m_key(LV2::INVALID_KEY), m_rate(rate), m_period(10), m_counter(0) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void on(unsigned char key, unsigned char velocity) {
|
|
||||||
m_key = key; |
|
||||||
m_period = m_rate * 4.0 / LV2::key2hz(m_key); |
|
||||||
m_pos = std::rand() / float(RAND_MAX); |
|
||||||
m_envelope = velocity / 128.0; |
|
||||||
} |
|
||||||
|
|
||||||
void off(unsigned char velocity) {
|
|
||||||
m_key = LV2::INVALID_KEY; |
|
||||||
} |
|
||||||
|
|
||||||
unsigned char get_key() const {
|
|
||||||
return m_key;
|
|
||||||
} |
|
||||||
|
|
||||||
void render(uint32_t from, uint32_t to) { |
|
||||||
if (m_key == LV2::INVALID_KEY) |
|
||||||
return; |
|
||||||
for (uint32_t i = from; i < to; ++i) { |
|
||||||
float pwm = *p(p_pwm) + (1 - *p(p_pwm)) * m_envelope; |
|
||||||
float s = -0.25 + 0.5 * (m_counter > m_period * (1 + pwm) / 2); |
|
||||||
m_counter = (m_counter + 1) % m_period; |
|
||||||
p(p_left)[i] += (1 - m_pos) * s; |
|
||||||
p(p_right)[i] += m_pos * s; |
|
||||||
if (m_envelope > 0) |
|
||||||
m_envelope -= 0.5 / m_rate; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
|
|
||||||
unsigned char m_key; |
|
||||||
double m_rate; |
|
||||||
uint32_t m_period; |
|
||||||
uint32_t m_counter; |
|
||||||
float m_pos; |
|
||||||
float m_envelope; |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
class Beep : public LV2::Synth<BeepVoice, Beep> { |
|
||||||
public: |
|
||||||
|
|
||||||
Beep(double rate) |
|
||||||
: LV2::Synth<BeepVoice, Beep>(p_n_ports, p_midi), |
|
||||||
m_buf_pos(0), m_delay(rate / 3),
|
|
||||||
m_l_buffer(new float[m_delay]), m_r_buffer(new float[m_delay]) { |
|
||||||
add_voices(new BeepVoice(rate), new BeepVoice(rate), new BeepVoice(rate)); |
|
||||||
add_audio_outputs(p_left, p_right); |
|
||||||
for (unsigned i = 0; i < m_delay; ++i) { |
|
||||||
m_l_buffer[i] = 0; |
|
||||||
m_r_buffer[i] = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void post_process(uint32_t from, uint32_t to) { |
|
||||||
for (uint32_t i = from; i < to; ++i) { |
|
||||||
float mono = (p(p_left)[i] + p(p_right)[i]) / 2; |
|
||||||
p(p_left)[i] += m_l_buffer[m_buf_pos]; |
|
||||||
p(p_right)[i] += m_r_buffer[m_buf_pos]; |
|
||||||
float tmp = m_l_buffer[m_buf_pos]; |
|
||||||
m_l_buffer[m_buf_pos] = 0.6 * (mono + m_r_buffer[m_buf_pos]); |
|
||||||
m_r_buffer[m_buf_pos] = 0.6 * tmp; |
|
||||||
m_buf_pos = (m_buf_pos + 1) % m_delay; |
|
||||||
p(p_left)[i] *= *p(p_gain); |
|
||||||
p(p_right)[i] *= *p(p_gain); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
|
|
||||||
unsigned m_buf_pos; |
|
||||||
unsigned m_delay; |
|
||||||
float* m_l_buffer; |
|
||||||
float* m_r_buffer; |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
static int _ = Beep::register_class(p_uri); |
|
@ -1,39 +0,0 @@ |
|||||||
#ifndef beep_peg |
|
||||||
#define beep_peg |
|
||||||
|
|
||||||
|
|
||||||
#ifndef PEG_STRUCT |
|
||||||
#define PEG_STRUCT |
|
||||||
typedef struct { |
|
||||||
float min; |
|
||||||
float max; |
|
||||||
float default_value; |
|
||||||
char toggled; |
|
||||||
char integer; |
|
||||||
char logarithmic; |
|
||||||
} peg_data_t; |
|
||||||
#endif |
|
||||||
|
|
||||||
/* <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> */ |
|
||||||
|
|
||||||
static const char p_uri[] = "http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2"; |
|
||||||
|
|
||||||
enum p_port_enum { |
|
||||||
p_midi, |
|
||||||
p_left, |
|
||||||
p_right, |
|
||||||
p_pwm, |
|
||||||
p_gain, |
|
||||||
p_n_ports |
|
||||||
}; |
|
||||||
|
|
||||||
static const peg_data_t p_ports[] = { |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ 0, 1, 0.5, 0, 0, 0 }, |
|
||||||
{ 0, 2, 1, 0, 0, 0 }, |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif /* beep_peg */ |
|
@ -1,69 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin; |
|
||||||
lv2:binary <beep2.so>; |
|
||||||
doap:name "Beep2"; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl>; |
|
||||||
ll:pegName "p"; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a lv2:InputPort, atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
lv2:index 0; |
|
||||||
ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent>; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 1; |
|
||||||
lv2:symbol "left"; |
|
||||||
lv2:name "Left"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 2; |
|
||||||
lv2:symbol "right"; |
|
||||||
lv2:name "Right"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:rightChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 3; |
|
||||||
lv2:symbol "pwm"; |
|
||||||
lv2:name "PWM"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 1; |
|
||||||
lv2:default 0.5; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 4; |
|
||||||
lv2:symbol "gain"; |
|
||||||
lv2:name "Gain"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 2; |
|
||||||
lv2:default 1; |
|
||||||
]. |
|
@ -1,69 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin; |
|
||||||
lv2:binary <beep2.so>; |
|
||||||
doap:name "Beep2"; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl>; |
|
||||||
ll:pegName "p"; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a lv2:InputPort, atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
lv2:index 0; |
|
||||||
ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent>; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 1; |
|
||||||
lv2:symbol "left"; |
|
||||||
lv2:name "Left"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 2; |
|
||||||
lv2:symbol "right"; |
|
||||||
lv2:name "Right"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:rightChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 3; |
|
||||||
lv2:symbol "pwm"; |
|
||||||
lv2:name "PWM"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 1; |
|
||||||
lv2:default 0.5; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 4; |
|
||||||
lv2:symbol "gain"; |
|
||||||
lv2:name "Gain"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 2; |
|
||||||
lv2:default 1; |
|
||||||
]. |
|
@ -1,5 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. |
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin; |
|
||||||
rdfs:seeAlso <beep2.ttl>. |
|
@ -1,5 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. |
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin; |
|
||||||
rdfs:seeAlso <beep2.ttl>. |
|
@ -1,23 +0,0 @@ |
|||||||
BUNDLE = lv2pftci-beep2.lv2
|
|
||||||
INSTALL_DIR = /home/pi/zynthian/zynthian-plugins/mod-lv2
|
|
||||||
|
|
||||||
|
|
||||||
$(BUNDLE): manifest.ttl beep2.ttl beep2.so |
|
||||||
rm -rf $(BUNDLE)
|
|
||||||
mkdir $(BUNDLE)
|
|
||||||
cp $^ $(BUNDLE)
|
|
||||||
|
|
||||||
beep2.so: beep.cpp beep.peg |
|
||||||
g++ -shared -fPIC -DPIC beep.cpp -I. -I/usr/local/include/lvtk-2 -L/usr/local/lib -llvtk_plugin2 -o beep2.so
|
|
||||||
|
|
||||||
beep.peg: beep2.ttl |
|
||||||
lv2peg beep2.ttl beep.peg
|
|
||||||
|
|
||||||
install: $(BUNDLE) |
|
||||||
mkdir -p $(INSTALL_DIR)
|
|
||||||
rm -rf $(INSTALL_DIR)/$(BUNDLE)
|
|
||||||
cp -R $(BUNDLE) $(INSTALL_DIR)
|
|
||||||
|
|
||||||
clean: |
|
||||||
rm -rf $(BUNDLE) beep2.so beep.peg
|
|
||||||
|
|
@ -1,94 +0,0 @@ |
|||||||
// from: http://ll-plugins.nongnu.org/lv2pftci/#A_synth
|
|
||||||
|
|
||||||
#include <lvtk/synth.hpp> |
|
||||||
#include "beep.peg" |
|
||||||
|
|
||||||
class BeepVoice : public lvtk::Voice { |
|
||||||
public: |
|
||||||
|
|
||||||
BeepVoice(double rate)
|
|
||||||
: m_key(lvtk::INVALID_KEY), m_rate(rate), m_period(10), m_counter(0) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void on(unsigned char key, unsigned char velocity) {
|
|
||||||
m_key = key; |
|
||||||
m_period = m_rate * 4.0 / lvtk::key2hz(m_key); |
|
||||||
m_pos = std::rand() / float(RAND_MAX); |
|
||||||
m_envelope = velocity / 128.0; |
|
||||||
} |
|
||||||
|
|
||||||
void off(unsigned char velocity) {
|
|
||||||
m_key = lvtk::INVALID_KEY; |
|
||||||
} |
|
||||||
|
|
||||||
unsigned char get_key() const {
|
|
||||||
return m_key;
|
|
||||||
} |
|
||||||
|
|
||||||
void render(uint32_t from, uint32_t to) { |
|
||||||
if (m_key == lvtk::INVALID_KEY) |
|
||||||
return; |
|
||||||
for (uint32_t i = from; i < to; ++i) { |
|
||||||
float pwm = *p(p_pwm) + (1 - *p(p_pwm)) * m_envelope; |
|
||||||
float s = -0.25 + 0.5 * (m_counter > m_period * (1 + pwm) / 2); |
|
||||||
m_counter = (m_counter + 1) % m_period; |
|
||||||
p(p_left)[i] += (1 - m_pos) * s; |
|
||||||
p(p_right)[i] += m_pos * s; |
|
||||||
if (m_envelope > 0) |
|
||||||
m_envelope -= 0.5 / m_rate; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
|
|
||||||
unsigned char m_key; |
|
||||||
double m_rate; |
|
||||||
uint32_t m_period; |
|
||||||
uint32_t m_counter; |
|
||||||
float m_pos; |
|
||||||
float m_envelope; |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
class Beep : public lvtk::Synth<BeepVoice, Beep> { |
|
||||||
public: |
|
||||||
|
|
||||||
Beep(double rate) |
|
||||||
: lvtk::Synth<BeepVoice, Beep>(p_n_ports, p_midi), |
|
||||||
m_buf_pos(0), m_delay(rate / 3),
|
|
||||||
m_l_buffer(new float[m_delay]), m_r_buffer(new float[m_delay]) { |
|
||||||
add_voices(new BeepVoice(rate), new BeepVoice(rate), new BeepVoice(rate)); |
|
||||||
add_audio_outputs(p_left, p_right); |
|
||||||
for (unsigned i = 0; i < m_delay; ++i) { |
|
||||||
m_l_buffer[i] = 0; |
|
||||||
m_r_buffer[i] = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void post_process(uint32_t from, uint32_t to) { |
|
||||||
for (uint32_t i = from; i < to; ++i) { |
|
||||||
float mono = (p(p_left)[i] + p(p_right)[i]) / 2; |
|
||||||
p(p_left)[i] += m_l_buffer[m_buf_pos]; |
|
||||||
p(p_right)[i] += m_r_buffer[m_buf_pos]; |
|
||||||
float tmp = m_l_buffer[m_buf_pos]; |
|
||||||
m_l_buffer[m_buf_pos] = 0.6 * (mono + m_r_buffer[m_buf_pos]); |
|
||||||
m_r_buffer[m_buf_pos] = 0.6 * tmp; |
|
||||||
m_buf_pos = (m_buf_pos + 1) % m_delay; |
|
||||||
p(p_left)[i] *= *p(p_gain); |
|
||||||
p(p_right)[i] *= *p(p_gain); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
|
|
||||||
unsigned m_buf_pos; |
|
||||||
unsigned m_delay; |
|
||||||
float* m_l_buffer; |
|
||||||
float* m_r_buffer; |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
static int _ = Beep::register_class(p_uri); |
|
@ -1,39 +0,0 @@ |
|||||||
#ifndef beep_peg |
|
||||||
#define beep_peg |
|
||||||
|
|
||||||
|
|
||||||
#ifndef PEG_STRUCT |
|
||||||
#define PEG_STRUCT |
|
||||||
typedef struct { |
|
||||||
float min; |
|
||||||
float max; |
|
||||||
float default_value; |
|
||||||
char toggled; |
|
||||||
char integer; |
|
||||||
char logarithmic; |
|
||||||
} peg_data_t; |
|
||||||
#endif |
|
||||||
|
|
||||||
/* <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> */ |
|
||||||
|
|
||||||
static const char p_uri[] = "http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2"; |
|
||||||
|
|
||||||
enum p_port_enum { |
|
||||||
p_midi, |
|
||||||
p_left, |
|
||||||
p_right, |
|
||||||
p_pwm, |
|
||||||
p_gain, |
|
||||||
p_n_ports |
|
||||||
}; |
|
||||||
|
|
||||||
static const peg_data_t p_ports[] = { |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ 0, 1, 0.5, 0, 0, 0 }, |
|
||||||
{ 0, 2, 1, 0, 0, 0 }, |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif /* beep_peg */ |
|
@ -1,69 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin; |
|
||||||
lv2:binary <beep2.so>; |
|
||||||
doap:name "Beep2"; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl>; |
|
||||||
ll:pegName "p"; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a lv2:InputPort, atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
lv2:index 0; |
|
||||||
ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent>; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 1; |
|
||||||
lv2:symbol "left"; |
|
||||||
lv2:name "Left"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 2; |
|
||||||
lv2:symbol "right"; |
|
||||||
lv2:name "Right"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:rightChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 3; |
|
||||||
lv2:symbol "pwm"; |
|
||||||
lv2:name "PWM"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 1; |
|
||||||
lv2:default 0.5; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 4; |
|
||||||
lv2:symbol "gain"; |
|
||||||
lv2:name "Gain"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 2; |
|
||||||
lv2:default 1; |
|
||||||
]. |
|
@ -1,69 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@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 ll: <http://ll-plugins.nongnu.org/lv2/namespace#>. |
|
||||||
@prefix pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>. |
|
||||||
@prefix ev: <http://lv2plug.in/ns/ext/event#>. |
|
||||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> . |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out> a pg:StereoGroup. |
|
||||||
|
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin, lv2:InstrumentPlugin; |
|
||||||
lv2:binary <beep2.so>; |
|
||||||
doap:name "Beep2"; |
|
||||||
doap:license <http://usefulinc.com/doap/licenses/gpl>; |
|
||||||
ll:pegName "p"; |
|
||||||
|
|
||||||
lv2:port [ |
|
||||||
a lv2:InputPort, atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ; |
|
||||||
lv2:index 0; |
|
||||||
ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent>; |
|
||||||
lv2:symbol "midi"; |
|
||||||
lv2:name "MIDI"; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 1; |
|
||||||
lv2:symbol "left"; |
|
||||||
lv2:name "Left"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:leftChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:AudioPort, lv2:OutputPort; |
|
||||||
lv2:index 2; |
|
||||||
lv2:symbol "right"; |
|
||||||
lv2:name "Right"; |
|
||||||
pg:membership [ |
|
||||||
pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2/out>; |
|
||||||
pg:role pg:rightChannel; |
|
||||||
]; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 3; |
|
||||||
lv2:symbol "pwm"; |
|
||||||
lv2:name "PWM"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 1; |
|
||||||
lv2:default 0.5; |
|
||||||
], |
|
||||||
|
|
||||||
[ |
|
||||||
a lv2:ControlPort, lv2:InputPort; |
|
||||||
lv2:index 4; |
|
||||||
lv2:symbol "gain"; |
|
||||||
lv2:name "Gain"; |
|
||||||
lv2:minimum 0; |
|
||||||
lv2:maximum 2; |
|
||||||
lv2:default 1; |
|
||||||
]. |
|
@ -1,5 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. |
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin; |
|
||||||
rdfs:seeAlso <beep2.ttl>. |
|
@ -1,5 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#>. |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. |
|
||||||
<http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2> |
|
||||||
a lv2:Plugin; |
|
||||||
rdfs:seeAlso <beep2.ttl>. |
|
@ -1,13 +0,0 @@ |
|||||||
== Sampler == |
|
||||||
|
|
||||||
This plugin loads a single sample from a .wav file and plays it back when a MIDI |
|
||||||
note on is received. Any sample on the system can be loaded via another event. |
|
||||||
A Gtk UI is included which does this, but the host can as well. |
|
||||||
|
|
||||||
This plugin illustrates: |
|
||||||
|
|
||||||
- UI <==> Plugin communication via events |
|
||||||
- Use of the worker extension for non-realtime tasks (sample loading) |
|
||||||
- Use of the log extension to print log messages via the host |
|
||||||
- Saving plugin state via the state extension |
|
||||||
- Dynamic plugin control via the same properties saved to state |
|
@ -1,40 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright 2016 David Robillard <d@drobilla.net> |
|
||||||
|
|
||||||
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. |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
A forge sink that writes to an atom buffer. |
|
||||||
|
|
||||||
It is assumed that the handle points to an LV2_Atom large enough to store |
|
||||||
the forge output. The forged result is in the body of the buffer atom. |
|
||||||
*/ |
|
||||||
static LV2_Atom_Forge_Ref |
|
||||||
atom_sink(LV2_Atom_Forge_Sink_Handle handle, const void* buf, uint32_t size) |
|
||||||
{ |
|
||||||
LV2_Atom* atom = (LV2_Atom*)handle; |
|
||||||
const uint32_t offset = lv2_atom_total_size(atom); |
|
||||||
memcpy((char*)atom + offset, buf, size); |
|
||||||
atom->size += size; |
|
||||||
return offset; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
Dereference counterpart to atom_sink(). |
|
||||||
*/ |
|
||||||
static LV2_Atom* |
|
||||||
atom_sink_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref) |
|
||||||
{ |
|
||||||
return (LV2_Atom*)((char*)handle + ref); |
|
||||||
} |
|
Binary file not shown.
@ -1,19 +0,0 @@ |
|||||||
# Unlike the previous examples, this manifest lists more than one resource: the |
|
||||||
# plugin as usual, and the UI. The descriptions are similar, but have |
|
||||||
# different types, so the host can decide from this file alone whether or not |
|
||||||
# it is interested, and avoid following the `rdfs:seeAlso` link if not (though |
|
||||||
# in this case both are described in the same file). |
|
||||||
|
|
||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#> . |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . |
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . |
|
||||||
|
|
||||||
<http://lv2plug.in/plugins/eg-sampler> |
|
||||||
a lv2:Plugin ; |
|
||||||
lv2:binary <sampler@LIB_EXT@> ; |
|
||||||
rdfs:seeAlso <sampler.ttl> . |
|
||||||
|
|
||||||
<http://lv2plug.in/plugins/eg-sampler#ui> |
|
||||||
a ui:GtkUI ; |
|
||||||
ui:binary <sampler_ui@LIB_EXT@> ; |
|
||||||
rdfs:seeAlso <sampler.ttl> . |
|
@ -1,552 +0,0 @@ |
|||||||
/*
|
|
||||||
LV2 Sampler Example Plugin |
|
||||||
Copyright 2011-2016 David Robillard <d@drobilla.net> |
|
||||||
Copyright 2011 Gabriel M. Beddingfield <gabriel@teuton.org> |
|
||||||
Copyright 2011 James Morris <jwm.art.net@gmail.com> |
|
||||||
|
|
||||||
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. |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <math.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <string.h> |
|
||||||
#ifndef __cplusplus |
|
||||||
# include <stdbool.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
#include <sndfile.h> |
|
||||||
|
|
||||||
#include "lv2/lv2plug.in/ns/ext/atom/forge.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/atom/util.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/midi/midi.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/patch/patch.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/state/state.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/urid/urid.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/worker/worker.h" |
|
||||||
#include "lv2/lv2plug.in/ns/lv2core/lv2.h" |
|
||||||
#include "lv2/lv2plug.in/ns/lv2core/lv2_util.h" |
|
||||||
|
|
||||||
#include "uris.h" |
|
||||||
#include "atom_sink.h" |
|
||||||
|
|
||||||
enum { |
|
||||||
SAMPLER_CONTROL = 0, |
|
||||||
SAMPLER_NOTIFY = 1, |
|
||||||
SAMPLER_OUT = 2 |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
SF_INFO info; // Info about sample from sndfile
|
|
||||||
float* data; // Sample data in float
|
|
||||||
char* path; // Path of file
|
|
||||||
uint32_t path_len; // Length of path
|
|
||||||
} Sample; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
// Features
|
|
||||||
LV2_URID_Map* map; |
|
||||||
LV2_Worker_Schedule* schedule; |
|
||||||
LV2_Log_Logger logger; |
|
||||||
|
|
||||||
// Forge for creating atoms
|
|
||||||
LV2_Atom_Forge forge; |
|
||||||
|
|
||||||
// Ports
|
|
||||||
const LV2_Atom_Sequence* control_port; |
|
||||||
LV2_Atom_Sequence* notify_port; |
|
||||||
float* output_port; |
|
||||||
|
|
||||||
// Forge frame for notify port (for writing worker replies)
|
|
||||||
LV2_Atom_Forge_Frame notify_frame; |
|
||||||
|
|
||||||
// URIs
|
|
||||||
SamplerURIs uris; |
|
||||||
|
|
||||||
// Playback state
|
|
||||||
Sample* sample; |
|
||||||
uint32_t frame_offset; |
|
||||||
float gain; |
|
||||||
sf_count_t frame; |
|
||||||
bool play; |
|
||||||
bool activated; |
|
||||||
bool sample_changed; |
|
||||||
} Sampler; |
|
||||||
|
|
||||||
/**
|
|
||||||
An atom-like message used internally to apply/free samples. |
|
||||||
|
|
||||||
This is only used internally to communicate with the worker, it is never |
|
||||||
sent to the outside world via a port since it is not POD. It is convenient |
|
||||||
to use an Atom header so actual atoms can be easily sent through the same |
|
||||||
ringbuffer. |
|
||||||
*/ |
|
||||||
typedef struct { |
|
||||||
LV2_Atom atom; |
|
||||||
Sample* sample; |
|
||||||
} SampleMessage; |
|
||||||
|
|
||||||
/**
|
|
||||||
Load a new sample and return it. |
|
||||||
|
|
||||||
Since this is of course not a real-time safe action, this is called in the |
|
||||||
worker thread only. The sample is loaded and returned only, plugin state is |
|
||||||
not modified. |
|
||||||
*/ |
|
||||||
static Sample* |
|
||||||
load_sample(LV2_Log_Logger* logger, const char* path) |
|
||||||
{ |
|
||||||
lv2_log_trace(logger, "Loading %s\n", path); |
|
||||||
|
|
||||||
const size_t path_len = strlen(path); |
|
||||||
Sample* const sample = (Sample*)malloc(sizeof(Sample)); |
|
||||||
SF_INFO* const info = &sample->info; |
|
||||||
SNDFILE* const sndfile = sf_open(path, SFM_READ, info); |
|
||||||
|
|
||||||
if (!sndfile || !info->frames || (info->channels != 1)) { |
|
||||||
lv2_log_error(logger, "Failed to open sample '%s'\n", path); |
|
||||||
free(sample); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
// Read data
|
|
||||||
float* const data = (float*)malloc(sizeof(float) * info->frames); |
|
||||||
if (!data) { |
|
||||||
lv2_log_error(logger, "Failed to allocate memory for sample\n"); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
sf_seek(sndfile, 0ul, SEEK_SET); |
|
||||||
sf_read_float(sndfile, data, info->frames); |
|
||||||
sf_close(sndfile); |
|
||||||
|
|
||||||
// Fill sample struct and return it
|
|
||||||
sample->data = data; |
|
||||||
sample->path = (char*)malloc(path_len + 1); |
|
||||||
sample->path_len = (uint32_t)path_len; |
|
||||||
memcpy(sample->path, path, path_len + 1); |
|
||||||
|
|
||||||
return sample; |
|
||||||
} |
|
||||||
|
|
||||||
static void |
|
||||||
free_sample(Sampler* self, Sample* sample) |
|
||||||
{ |
|
||||||
if (sample) { |
|
||||||
lv2_log_trace(&self->logger, "Freeing %s\n", sample->path); |
|
||||||
free(sample->path); |
|
||||||
free(sample->data); |
|
||||||
free(sample); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
Do work in a non-realtime thread. |
|
||||||
|
|
||||||
This is called for every piece of work scheduled in the audio thread using |
|
||||||
self->schedule->schedule_work(). A reply can be sent back to the audio |
|
||||||
thread using the provided respond function. |
|
||||||
*/ |
|
||||||
static LV2_Worker_Status |
|
||||||
work(LV2_Handle instance, |
|
||||||
LV2_Worker_Respond_Function respond, |
|
||||||
LV2_Worker_Respond_Handle handle, |
|
||||||
uint32_t size, |
|
||||||
const void* data) |
|
||||||
{ |
|
||||||
Sampler* self = (Sampler*)instance; |
|
||||||
const LV2_Atom* atom = (const LV2_Atom*)data; |
|
||||||
if (atom->type == self->uris.eg_freeSample) { |
|
||||||
// Free old sample
|
|
||||||
const SampleMessage* msg = (const SampleMessage*)data; |
|
||||||
free_sample(self, msg->sample); |
|
||||||
} else if (atom->type == self->forge.Object) { |
|
||||||
// Handle set message (load sample).
|
|
||||||
const LV2_Atom_Object* obj = (const LV2_Atom_Object*)data; |
|
||||||
const char* path = read_set_file(&self->uris, obj); |
|
||||||
if (!path) { |
|
||||||
lv2_log_error(&self->logger, "Malformed set file request\n"); |
|
||||||
return LV2_WORKER_ERR_UNKNOWN; |
|
||||||
} |
|
||||||
|
|
||||||
// Load sample.
|
|
||||||
Sample* sample = load_sample(&self->logger, path); |
|
||||||
if (sample) { |
|
||||||
// Send new sample to run() to be applied
|
|
||||||
respond(handle, sizeof(sample), &sample); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return LV2_WORKER_SUCCESS; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
Handle a response from work() in the audio thread. |
|
||||||
|
|
||||||
When running normally, this will be called by the host after run(). When |
|
||||||
freewheeling, this will be called immediately at the point the work was |
|
||||||
scheduled. |
|
||||||
*/ |
|
||||||
static LV2_Worker_Status |
|
||||||
work_response(LV2_Handle instance, |
|
||||||
uint32_t size, |
|
||||||
const void* data) |
|
||||||
{ |
|
||||||
Sampler* self = (Sampler*)instance; |
|
||||||
Sample* old_sample = self->sample; |
|
||||||
Sample* new_sample = *(Sample*const*)data; |
|
||||||
|
|
||||||
// Install the new sample
|
|
||||||
self->sample = *(Sample*const*)data; |
|
||||||
|
|
||||||
// Schedule work to free the old sample
|
|
||||||
SampleMessage msg = { { sizeof(Sample*), self->uris.eg_freeSample }, |
|
||||||
old_sample }; |
|
||||||
self->schedule->schedule_work(self->schedule->handle, sizeof(msg), &msg); |
|
||||||
|
|
||||||
if (strcmp(old_sample->path, new_sample->path)) { |
|
||||||
// Send a notification that we're using a new sample
|
|
||||||
lv2_atom_forge_frame_time(&self->forge, self->frame_offset); |
|
||||||
write_set_file(&self->forge, &self->uris, |
|
||||||
new_sample->path, |
|
||||||
new_sample->path_len); |
|
||||||
} |
|
||||||
|
|
||||||
return LV2_WORKER_SUCCESS; |
|
||||||
} |
|
||||||
|
|
||||||
static void |
|
||||||
connect_port(LV2_Handle instance, |
|
||||||
uint32_t port, |
|
||||||
void* data) |
|
||||||
{ |
|
||||||
Sampler* self = (Sampler*)instance; |
|
||||||
switch (port) { |
|
||||||
case SAMPLER_CONTROL: |
|
||||||
self->control_port = (const LV2_Atom_Sequence*)data; |
|
||||||
break; |
|
||||||
case SAMPLER_NOTIFY: |
|
||||||
self->notify_port = (LV2_Atom_Sequence*)data; |
|
||||||
break; |
|
||||||
case SAMPLER_OUT: |
|
||||||
self->output_port = (float*)data; |
|
||||||
break; |
|
||||||
default: |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static LV2_Handle |
|
||||||
instantiate(const LV2_Descriptor* descriptor, |
|
||||||
double rate, |
|
||||||
const char* path, |
|
||||||
const LV2_Feature* const* features) |
|
||||||
{ |
|
||||||
// Allocate and initialise instance structure.
|
|
||||||
Sampler* self = (Sampler*)calloc(1, sizeof(Sampler)); |
|
||||||
if (!self) { |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
// Get host features
|
|
||||||
const char* missing = lv2_features_query( |
|
||||||
features, |
|
||||||
LV2_LOG__log, &self->logger.log, false, |
|
||||||
LV2_URID__map, &self->map, true, |
|
||||||
LV2_WORKER__schedule, &self->schedule, true, |
|
||||||
NULL); |
|
||||||
lv2_log_logger_set_map(&self->logger, self->map); |
|
||||||
if (missing) { |
|
||||||
lv2_log_error(&self->logger, "Missing feature <%s>\n", missing); |
|
||||||
free(self); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
// Map URIs and initialise forge
|
|
||||||
map_sampler_uris(self->map, &self->uris); |
|
||||||
lv2_atom_forge_init(&self->forge, self->map); |
|
||||||
|
|
||||||
return (LV2_Handle)self; |
|
||||||
} |
|
||||||
|
|
||||||
static void |
|
||||||
cleanup(LV2_Handle instance) |
|
||||||
{ |
|
||||||
Sampler* self = (Sampler*)instance; |
|
||||||
free_sample(self, self->sample); |
|
||||||
free(self); |
|
||||||
} |
|
||||||
|
|
||||||
static void |
|
||||||
activate(LV2_Handle instance) |
|
||||||
{ |
|
||||||
((Sampler*)instance)->activated = true; |
|
||||||
} |
|
||||||
|
|
||||||
static void |
|
||||||
deactivate(LV2_Handle instance) |
|
||||||
{ |
|
||||||
((Sampler*)instance)->activated = false; |
|
||||||
} |
|
||||||
|
|
||||||
/** 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) |
|
||||||
|
|
||||||
static void |
|
||||||
run(LV2_Handle instance, |
|
||||||
uint32_t sample_count) |
|
||||||
{ |
|
||||||
Sampler* self = (Sampler*)instance; |
|
||||||
SamplerURIs* uris = &self->uris; |
|
||||||
sf_count_t start_frame = 0; |
|
||||||
sf_count_t pos = 0; |
|
||||||
float* output = self->output_port; |
|
||||||
|
|
||||||
// Set up forge to write directly to notify output port.
|
|
||||||
const uint32_t notify_capacity = self->notify_port->atom.size; |
|
||||||
lv2_atom_forge_set_buffer(&self->forge, |
|
||||||
(uint8_t*)self->notify_port, |
|
||||||
notify_capacity); |
|
||||||
|
|
||||||
// Start a sequence in the notify output port.
|
|
||||||
lv2_atom_forge_sequence_head(&self->forge, &self->notify_frame, 0); |
|
||||||
|
|
||||||
// Send update to UI if sample has changed due to state restore
|
|
||||||
if (self->sample_changed) { |
|
||||||
lv2_atom_forge_frame_time(&self->forge, 0); |
|
||||||
write_set_file(&self->forge, &self->uris, |
|
||||||
self->sample->path, |
|
||||||
self->sample->path_len); |
|
||||||
self->sample_changed = false; |
|
||||||
} |
|
||||||
|
|
||||||
// Read incoming events
|
|
||||||
LV2_ATOM_SEQUENCE_FOREACH(self->control_port, ev) { |
|
||||||
self->frame_offset = ev->time.frames; |
|
||||||
if (ev->body.type == uris->midi_Event) { |
|
||||||
const uint8_t* const msg = (const uint8_t*)(ev + 1); |
|
||||||
switch (lv2_midi_message_type(msg)) { |
|
||||||
case LV2_MIDI_MSG_NOTE_ON: |
|
||||||
start_frame = ev->time.frames; |
|
||||||
self->frame = 0; |
|
||||||
self->play = true; |
|
||||||
break; |
|
||||||
default: |
|
||||||
break; |
|
||||||
} |
|
||||||
} else if (lv2_atom_forge_is_object_type(&self->forge, ev->body.type)) { |
|
||||||
const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body; |
|
||||||
if (obj->body.otype == uris->patch_Set) { |
|
||||||
// Get the property and value of the set message
|
|
||||||
const LV2_Atom* property = NULL; |
|
||||||
const LV2_Atom* value = NULL; |
|
||||||
lv2_atom_object_get(obj, |
|
||||||
uris->patch_property, &property, |
|
||||||
uris->patch_value, &value, |
|
||||||
0); |
|
||||||
if (!property) { |
|
||||||
lv2_log_error(&self->logger, |
|
||||||
"patch:Set message with no property\n"); |
|
||||||
continue; |
|
||||||
} else if (property->type != uris->atom_URID) { |
|
||||||
lv2_log_error(&self->logger, |
|
||||||
"patch:Set property is not a URID\n"); |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
const uint32_t key = ((const LV2_Atom_URID*)property)->body; |
|
||||||
if (key == uris->eg_sample) { |
|
||||||
// Sample change, send it to the worker.
|
|
||||||
lv2_log_trace(&self->logger, "Scheduling sample change\n"); |
|
||||||
self->schedule->schedule_work(self->schedule->handle, |
|
||||||
lv2_atom_total_size(&ev->body), |
|
||||||
&ev->body); |
|
||||||
} else if (key == uris->param_gain) { |
|
||||||
// Gain change
|
|
||||||
if (value->type == uris->atom_Float) { |
|
||||||
self->gain = DB_CO(((LV2_Atom_Float*)value)->body); |
|
||||||
} |
|
||||||
} |
|
||||||
} else if (obj->body.otype == uris->patch_Get) { |
|
||||||
// Received a get message, emit our state (probably to UI)
|
|
||||||
lv2_atom_forge_frame_time(&self->forge, self->frame_offset); |
|
||||||
write_set_file(&self->forge, &self->uris, |
|
||||||
self->sample->path, |
|
||||||
self->sample->path_len); |
|
||||||
} else { |
|
||||||
lv2_log_trace(&self->logger, |
|
||||||
"Unknown object type %d\n", obj->body.otype); |
|
||||||
} |
|
||||||
} else { |
|
||||||
lv2_log_trace(&self->logger, |
|
||||||
"Unknown event type %d\n", ev->body.type); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Render the sample (possibly already in progress)
|
|
||||||
if (self->play) { |
|
||||||
uint32_t f = self->frame; |
|
||||||
const uint32_t lf = self->sample->info.frames; |
|
||||||
|
|
||||||
for (pos = 0; pos < start_frame; ++pos) { |
|
||||||
output[pos] = 0; |
|
||||||
} |
|
||||||
|
|
||||||
for (; pos < sample_count && f < lf; ++pos, ++f) { |
|
||||||
output[pos] = self->sample->data[f] * self->gain; |
|
||||||
} |
|
||||||
|
|
||||||
self->frame = f; |
|
||||||
|
|
||||||
if (f == lf) { |
|
||||||
self->play = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Add zeros to end if sample not long enough (or not playing)
|
|
||||||
for (; pos < sample_count; ++pos) { |
|
||||||
output[pos] = 0.0f; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static LV2_State_Status |
|
||||||
save(LV2_Handle instance, |
|
||||||
LV2_State_Store_Function store, |
|
||||||
LV2_State_Handle handle, |
|
||||||
uint32_t flags, |
|
||||||
const LV2_Feature* const* features) |
|
||||||
{ |
|
||||||
Sampler* self = (Sampler*)instance; |
|
||||||
if (!self->sample) { |
|
||||||
return LV2_STATE_SUCCESS; |
|
||||||
} |
|
||||||
|
|
||||||
LV2_State_Map_Path* map_path = (LV2_State_Map_Path*)lv2_features_data( |
|
||||||
features, LV2_STATE__mapPath); |
|
||||||
if (!map_path) { |
|
||||||
return LV2_STATE_ERR_NO_FEATURE; |
|
||||||
} |
|
||||||
|
|
||||||
// Map absolute sample path to an abstract state path
|
|
||||||
char* apath = map_path->abstract_path(map_path->handle, self->sample->path); |
|
||||||
|
|
||||||
// Store eg:sample = abstract path
|
|
||||||
store(handle, |
|
||||||
self->uris.eg_sample, |
|
||||||
apath, |
|
||||||
strlen(apath) + 1, |
|
||||||
self->uris.atom_Path, |
|
||||||
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); |
|
||||||
|
|
||||||
free(apath); |
|
||||||
return LV2_STATE_SUCCESS; |
|
||||||
} |
|
||||||
|
|
||||||
static LV2_State_Status |
|
||||||
restore(LV2_Handle instance, |
|
||||||
LV2_State_Retrieve_Function retrieve, |
|
||||||
LV2_State_Handle handle, |
|
||||||
uint32_t flags, |
|
||||||
const LV2_Feature* const* features) |
|
||||||
{ |
|
||||||
Sampler* self = (Sampler*)instance; |
|
||||||
|
|
||||||
// Get host features
|
|
||||||
LV2_Worker_Schedule* schedule = NULL; |
|
||||||
LV2_State_Map_Path* paths = NULL; |
|
||||||
const char* missing = lv2_features_query( |
|
||||||
features, |
|
||||||
LV2_STATE__mapPath, &paths, true, |
|
||||||
LV2_WORKER__schedule, &schedule, false, |
|
||||||
NULL); |
|
||||||
if (missing) { |
|
||||||
lv2_log_error(&self->logger, "Missing feature <%s>\n", missing); |
|
||||||
return LV2_STATE_ERR_NO_FEATURE; |
|
||||||
} |
|
||||||
|
|
||||||
// Get eg:sample from state
|
|
||||||
size_t size; |
|
||||||
uint32_t type; |
|
||||||
uint32_t valflags; |
|
||||||
const void* value = retrieve(handle, self->uris.eg_sample, |
|
||||||
&size, &type, &valflags); |
|
||||||
if (!value) { |
|
||||||
lv2_log_error(&self->logger, "Missing eg:sample\n"); |
|
||||||
return LV2_STATE_ERR_NO_PROPERTY; |
|
||||||
} else if (type != self->uris.atom_Path) { |
|
||||||
lv2_log_error(&self->logger, "Non-path eg:sample\n"); |
|
||||||
return LV2_STATE_ERR_BAD_TYPE; |
|
||||||
} |
|
||||||
|
|
||||||
// Map abstract state path to absolute path
|
|
||||||
const char* apath = (const char*)value; |
|
||||||
char* path = paths->absolute_path(paths->handle, apath); |
|
||||||
|
|
||||||
// Replace current sample with the new one
|
|
||||||
if (!self->activated || !schedule) { |
|
||||||
// No scheduling available, load sample immediately
|
|
||||||
lv2_log_trace(&self->logger, "Synchronous restore\n"); |
|
||||||
free_sample(self, self->sample); |
|
||||||
self->sample = load_sample(&self->logger, path); |
|
||||||
self->sample_changed = true; |
|
||||||
} else { |
|
||||||
// Schedule sample to be loaded by the provided worker
|
|
||||||
lv2_log_trace(&self->logger, "Scheduling restore\n"); |
|
||||||
LV2_Atom_Forge forge; |
|
||||||
LV2_Atom* buf = (LV2_Atom*)calloc(1, strlen(path) + 128); |
|
||||||
lv2_atom_forge_init(&forge, self->map); |
|
||||||
lv2_atom_forge_set_sink(&forge, atom_sink, atom_sink_deref, buf); |
|
||||||
write_set_file(&forge, &self->uris, path, strlen(path)); |
|
||||||
|
|
||||||
const uint32_t msg_size = lv2_atom_pad_size(buf->size); |
|
||||||
schedule->schedule_work(self->schedule->handle, msg_size, buf + 1); |
|
||||||
free(buf); |
|
||||||
} |
|
||||||
|
|
||||||
return LV2_STATE_SUCCESS; |
|
||||||
} |
|
||||||
|
|
||||||
static const void* |
|
||||||
extension_data(const char* uri) |
|
||||||
{ |
|
||||||
static const LV2_State_Interface state = { save, restore }; |
|
||||||
static const LV2_Worker_Interface worker = { work, work_response, NULL }; |
|
||||||
if (!strcmp(uri, LV2_STATE__interface)) { |
|
||||||
return &state; |
|
||||||
} else if (!strcmp(uri, LV2_WORKER__interface)) { |
|
||||||
return &worker; |
|
||||||
} |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
static const LV2_Descriptor descriptor = { |
|
||||||
EG_SAMPLER_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; |
|
||||||
} |
|
||||||
} |
|
@ -1,70 +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 patch: <http://lv2plug.in/ns/ext/patch#> . |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . |
|
||||||
@prefix state: <http://lv2plug.in/ns/ext/state#> . |
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . |
|
||||||
@prefix urid: <http://lv2plug.in/ns/ext/urid#> . |
|
||||||
@prefix work: <http://lv2plug.in/ns/ext/worker#> . |
|
||||||
@prefix param: <http://lv2plug.in/ns/ext/parameters#> . |
|
||||||
|
|
||||||
<http://lv2plug.in/plugins/eg-sampler#sample> |
|
||||||
a lv2:Parameter ; |
|
||||||
rdfs:label "sample" ; |
|
||||||
rdfs:range atom:Path . |
|
||||||
|
|
||||||
<http://lv2plug.in/plugins/eg-sampler> |
|
||||||
a lv2:Plugin ; |
|
||||||
doap:name "Example Sampler" ; |
|
||||||
doap:license <http://opensource.org/licenses/isc> ; |
|
||||||
lv2:project <http://lv2plug.in/ns/lv2> ; |
|
||||||
lv2:requiredFeature state:loadDefaultState , |
|
||||||
urid:map , |
|
||||||
work:schedule ; |
|
||||||
lv2:optionalFeature lv2:hardRTCapable , |
|
||||||
state:threadSafeRestore ; |
|
||||||
lv2:extensionData state:interface , |
|
||||||
work:interface ; |
|
||||||
ui:ui <http://lv2plug.in/plugins/eg-sampler#ui> ; |
|
||||||
patch:writable <http://lv2plug.in/plugins/eg-sampler#sample> , |
|
||||||
param:gain ; |
|
||||||
lv2:port [ |
|
||||||
a lv2:InputPort , |
|
||||||
atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> , |
|
||||||
patch:Message ; |
|
||||||
lv2:designation lv2:control ; |
|
||||||
lv2:index 0 ; |
|
||||||
lv2:symbol "control" ; |
|
||||||
lv2:name "Control" |
|
||||||
] , [ |
|
||||||
a lv2:OutputPort , |
|
||||||
atom:AtomPort ; |
|
||||||
atom:bufferType atom:Sequence ; |
|
||||||
atom:supports patch:Message ; |
|
||||||
lv2:designation lv2:control ; |
|
||||||
lv2:index 1 ; |
|
||||||
lv2:symbol "notify" ; |
|
||||||
lv2:name "Notify" |
|
||||||
] , [ |
|
||||||
a lv2:AudioPort , |
|
||||||
lv2:OutputPort ; |
|
||||||
lv2:index 2 ; |
|
||||||
lv2:symbol "out" ; |
|
||||||
lv2:name "Out" |
|
||||||
] ; |
|
||||||
state:state [ |
|
||||||
<http://lv2plug.in/plugins/eg-sampler#sample> <click.wav> |
|
||||||
] . |
|
||||||
|
|
||||||
<http://lv2plug.in/plugins/eg-sampler#ui> |
|
||||||
a ui:GtkUI ; |
|
||||||
lv2:requiredFeature urid:map ; |
|
||||||
lv2:extensionData ui:showInterface ; |
|
||||||
ui:portNotification [ |
|
||||||
ui:plugin <http://lv2plug.in/plugins/eg-sampler> ; |
|
||||||
lv2:symbol "notify" ; |
|
||||||
ui:notifyType atom:Blank |
|
||||||
] . |
|
@ -1,254 +0,0 @@ |
|||||||
/*
|
|
||||||
LV2 Sampler Example Plugin UI |
|
||||||
Copyright 2011-2016 David Robillard <d@drobilla.net> |
|
||||||
|
|
||||||
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. |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
#include <gtk/gtk.h> |
|
||||||
|
|
||||||
#include "lv2/lv2plug.in/ns/ext/atom/atom.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/atom/forge.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/atom/util.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/log/logger.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/patch/patch.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/urid/urid.h" |
|
||||||
#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" |
|
||||||
#include "lv2/lv2plug.in/ns/lv2core/lv2_util.h" |
|
||||||
|
|
||||||
#include "./uris.h" |
|
||||||
|
|
||||||
#define SAMPLER_UI_URI "http://lv2plug.in/plugins/eg-sampler#ui"
|
|
||||||
|
|
||||||
typedef struct { |
|
||||||
LV2_Atom_Forge forge; |
|
||||||
LV2_URID_Map* map; |
|
||||||
LV2_Log_Logger logger; |
|
||||||
SamplerURIs uris; |
|
||||||
|
|
||||||
LV2UI_Write_Function write; |
|
||||||
LV2UI_Controller controller; |
|
||||||
|
|
||||||
GtkWidget* box; |
|
||||||
GtkWidget* button; |
|
||||||
GtkWidget* label; |
|
||||||
GtkWidget* window; /* For optional show interface. */ |
|
||||||
} SamplerUI; |
|
||||||
|
|
||||||
static void |
|
||||||
on_load_clicked(GtkWidget* widget, |
|
||||||
void* handle) |
|
||||||
{ |
|
||||||
SamplerUI* ui = (SamplerUI*)handle; |
|
||||||
|
|
||||||
/* Create a dialog to select a sample file. */ |
|
||||||
GtkWidget* dialog = gtk_file_chooser_dialog_new( |
|
||||||
"Load Sample", |
|
||||||
NULL, |
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN, |
|
||||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
|
||||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
|
||||||
NULL); |
|
||||||
|
|
||||||
/* Run the dialog, and return if it is cancelled. */ |
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) { |
|
||||||
gtk_widget_destroy(dialog); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
/* Get the file path from the dialog. */ |
|
||||||
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); |
|
||||||
|
|
||||||
/* Got what we need, destroy the dialog. */ |
|
||||||
gtk_widget_destroy(dialog); |
|
||||||
|
|
||||||
#define OBJ_BUF_SIZE 1024 |
|
||||||
uint8_t obj_buf[OBJ_BUF_SIZE]; |
|
||||||
lv2_atom_forge_set_buffer(&ui->forge, obj_buf, OBJ_BUF_SIZE); |
|
||||||
|
|
||||||
LV2_Atom* msg = (LV2_Atom*)write_set_file(&ui->forge, &ui->uris, |
|
||||||
filename, strlen(filename)); |
|
||||||
|
|
||||||
ui->write(ui->controller, 0, lv2_atom_total_size(msg), |
|
||||||
ui->uris.atom_eventTransfer, |
|
||||||
msg); |
|
||||||
|
|
||||||
g_free(filename); |
|
||||||
} |
|
||||||
|
|
||||||
static LV2UI_Handle |
|
||||||
instantiate(const LV2UI_Descriptor* descriptor, |
|
||||||
const char* plugin_uri, |
|
||||||
const char* bundle_path, |
|
||||||
LV2UI_Write_Function write_function, |
|
||||||
LV2UI_Controller controller, |
|
||||||
LV2UI_Widget* widget, |
|
||||||
const LV2_Feature* const* features) |
|
||||||
{ |
|
||||||
SamplerUI* ui = (SamplerUI*)calloc(1, sizeof(SamplerUI)); |
|
||||||
if (!ui) { |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
ui->write = write_function; |
|
||||||
ui->controller = controller; |
|
||||||
*widget = NULL; |
|
||||||
|
|
||||||
// Get host features
|
|
||||||
const char* missing = lv2_features_query( |
|
||||||
features, |
|
||||||
LV2_LOG__log, &ui->logger.log, false, |
|
||||||
LV2_URID__map, &ui->map, true, |
|
||||||
NULL); |
|
||||||
lv2_log_logger_set_map(&ui->logger, ui->map); |
|
||||||
if (missing) { |
|
||||||
lv2_log_error(&ui->logger, "Missing feature <%s>\n", missing); |
|
||||||
free(ui); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
// Map URIs and initialise forge
|
|
||||||
map_sampler_uris(ui->map, &ui->uris); |
|
||||||
lv2_atom_forge_init(&ui->forge, ui->map); |
|
||||||
|
|
||||||
// Construct Gtk UI
|
|
||||||
ui->box = gtk_vbox_new(FALSE, 4); |
|
||||||
ui->label = gtk_label_new("?"); |
|
||||||
ui->button = gtk_button_new_with_label("Load Sample"); |
|
||||||
gtk_box_pack_start(GTK_BOX(ui->box), ui->label, TRUE, TRUE, 4); |
|
||||||
gtk_box_pack_start(GTK_BOX(ui->box), ui->button, FALSE, FALSE, 4); |
|
||||||
g_signal_connect(ui->button, "clicked", |
|
||||||
G_CALLBACK(on_load_clicked), |
|
||||||
ui); |
|
||||||
|
|
||||||
// Request state (filename) from plugin
|
|
||||||
uint8_t get_buf[512]; |
|
||||||
lv2_atom_forge_set_buffer(&ui->forge, get_buf, sizeof(get_buf)); |
|
||||||
|
|
||||||
LV2_Atom_Forge_Frame frame; |
|
||||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_object( |
|
||||||
&ui->forge, &frame, 0, ui->uris.patch_Get); |
|
||||||
lv2_atom_forge_pop(&ui->forge, &frame); |
|
||||||
|
|
||||||
ui->write(ui->controller, 0, lv2_atom_total_size(msg), |
|
||||||
ui->uris.atom_eventTransfer, |
|
||||||
msg); |
|
||||||
|
|
||||||
*widget = ui->box; |
|
||||||
|
|
||||||
return ui; |
|
||||||
} |
|
||||||
|
|
||||||
static void |
|
||||||
cleanup(LV2UI_Handle handle) |
|
||||||
{ |
|
||||||
SamplerUI* ui = (SamplerUI*)handle; |
|
||||||
gtk_widget_destroy(ui->button); |
|
||||||
free(ui); |
|
||||||
} |
|
||||||
|
|
||||||
static void |
|
||||||
port_event(LV2UI_Handle handle, |
|
||||||
uint32_t port_index, |
|
||||||
uint32_t buffer_size, |
|
||||||
uint32_t format, |
|
||||||
const void* buffer) |
|
||||||
{ |
|
||||||
SamplerUI* ui = (SamplerUI*)handle; |
|
||||||
if (format == ui->uris.atom_eventTransfer) { |
|
||||||
const LV2_Atom* atom = (const LV2_Atom*)buffer; |
|
||||||
if (lv2_atom_forge_is_object_type(&ui->forge, atom->type)) { |
|
||||||
const LV2_Atom_Object* obj = (const LV2_Atom_Object*)atom; |
|
||||||
const char* uri = read_set_file(&ui->uris, obj); |
|
||||||
if (uri) { |
|
||||||
gtk_label_set_text(GTK_LABEL(ui->label), uri); |
|
||||||
} else { |
|
||||||
lv2_log_warning(&ui->logger, "Malformed message\n"); |
|
||||||
} |
|
||||||
} else { |
|
||||||
lv2_log_error(&ui->logger, "Unknown message type\n"); |
|
||||||
} |
|
||||||
} else { |
|
||||||
lv2_log_warning(&ui->logger, "Unknown port event format\n"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* Optional non-embedded UI show interface. */ |
|
||||||
static int |
|
||||||
ui_show(LV2UI_Handle handle) |
|
||||||
{ |
|
||||||
SamplerUI* ui = (SamplerUI*)handle; |
|
||||||
|
|
||||||
int argc = 0; |
|
||||||
gtk_init(&argc, NULL); |
|
||||||
|
|
||||||
ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
|
||||||
gtk_container_add(GTK_CONTAINER(ui->window), ui->box); |
|
||||||
gtk_widget_show_all(ui->window); |
|
||||||
gtk_window_present(GTK_WINDOW(ui->window)); |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
/* Optional non-embedded UI hide interface. */ |
|
||||||
static int |
|
||||||
ui_hide(LV2UI_Handle handle) |
|
||||||
{ |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
/* Idle interface for optional non-embedded UI. */ |
|
||||||
static int |
|
||||||
ui_idle(LV2UI_Handle handle) |
|
||||||
{ |
|
||||||
SamplerUI* ui = (SamplerUI*)handle; |
|
||||||
if (ui->window) { |
|
||||||
gtk_main_iteration(); |
|
||||||
} |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
static const void* |
|
||||||
extension_data(const char* uri) |
|
||||||
{ |
|
||||||
static const LV2UI_Show_Interface show = { ui_show, ui_hide }; |
|
||||||
static const LV2UI_Idle_Interface idle = { ui_idle }; |
|
||||||
if (!strcmp(uri, LV2_UI__showInterface)) { |
|
||||||
return &show; |
|
||||||
} else if (!strcmp(uri, LV2_UI__idleInterface)) { |
|
||||||
return &idle; |
|
||||||
} |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
static const LV2UI_Descriptor descriptor = { |
|
||||||
SAMPLER_UI_URI, |
|
||||||
instantiate, |
|
||||||
cleanup, |
|
||||||
port_event, |
|
||||||
extension_data |
|
||||||
}; |
|
||||||
|
|
||||||
LV2_SYMBOL_EXPORT |
|
||||||
const LV2UI_Descriptor* |
|
||||||
lv2ui_descriptor(uint32_t index) |
|
||||||
{ |
|
||||||
switch (index) { |
|
||||||
case 0: |
|
||||||
return &descriptor; |
|
||||||
default: |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
} |
|
@ -1,139 +0,0 @@ |
|||||||
/*
|
|
||||||
LV2 Sampler Example Plugin |
|
||||||
Copyright 2011-2016 David Robillard <d@drobilla.net> |
|
||||||
|
|
||||||
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. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef SAMPLER_URIS_H |
|
||||||
#define SAMPLER_URIS_H |
|
||||||
|
|
||||||
#include "lv2/lv2plug.in/ns/ext/log/log.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/midi/midi.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/state/state.h" |
|
||||||
#include "lv2/lv2plug.in/ns/ext/parameters/parameters.h" |
|
||||||
|
|
||||||
#define EG_SAMPLER_URI "http://lv2plug.in/plugins/eg-sampler"
|
|
||||||
#define EG_SAMPLER__sample EG_SAMPLER_URI "#sample" |
|
||||||
#define EG_SAMPLER__applySample EG_SAMPLER_URI "#applySample" |
|
||||||
#define EG_SAMPLER__freeSample EG_SAMPLER_URI "#freeSample" |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
LV2_URID atom_Float; |
|
||||||
LV2_URID atom_Path; |
|
||||||
LV2_URID atom_Resource; |
|
||||||
LV2_URID atom_Sequence; |
|
||||||
LV2_URID atom_URID; |
|
||||||
LV2_URID atom_eventTransfer; |
|
||||||
LV2_URID eg_applySample; |
|
||||||
LV2_URID eg_sample; |
|
||||||
LV2_URID eg_freeSample; |
|
||||||
LV2_URID midi_Event; |
|
||||||
LV2_URID param_gain; |
|
||||||
LV2_URID patch_Get; |
|
||||||
LV2_URID patch_Set; |
|
||||||
LV2_URID patch_property; |
|
||||||
LV2_URID patch_value; |
|
||||||
} SamplerURIs; |
|
||||||
|
|
||||||
static inline void |
|
||||||
map_sampler_uris(LV2_URID_Map* map, SamplerURIs* uris) |
|
||||||
{ |
|
||||||
uris->atom_Float = map->map(map->handle, LV2_ATOM__Float); |
|
||||||
uris->atom_Path = map->map(map->handle, LV2_ATOM__Path); |
|
||||||
uris->atom_Resource = map->map(map->handle, LV2_ATOM__Resource); |
|
||||||
uris->atom_Sequence = map->map(map->handle, LV2_ATOM__Sequence); |
|
||||||
uris->atom_URID = map->map(map->handle, LV2_ATOM__URID); |
|
||||||
uris->atom_eventTransfer = map->map(map->handle, LV2_ATOM__eventTransfer); |
|
||||||
uris->eg_applySample = map->map(map->handle, EG_SAMPLER__applySample); |
|
||||||
uris->eg_freeSample = map->map(map->handle, EG_SAMPLER__freeSample); |
|
||||||
uris->eg_sample = map->map(map->handle, EG_SAMPLER__sample); |
|
||||||
uris->midi_Event = map->map(map->handle, LV2_MIDI__MidiEvent); |
|
||||||
uris->param_gain = map->map(map->handle, LV2_PARAMETERS__gain); |
|
||||||
uris->patch_Get = map->map(map->handle, LV2_PATCH__Get); |
|
||||||
uris->patch_Set = map->map(map->handle, LV2_PATCH__Set); |
|
||||||
uris->patch_property = map->map(map->handle, LV2_PATCH__property); |
|
||||||
uris->patch_value = map->map(map->handle, LV2_PATCH__value); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a message like the following to @p forge: |
|
||||||
* [] |
|
||||||
* a patch:Set ; |
|
||||||
* patch:property eg:sample ; |
|
||||||
* patch:value </home/me/foo.wav> . |
|
||||||
*/ |
|
||||||
static inline LV2_Atom_Forge_Ref |
|
||||||
write_set_file(LV2_Atom_Forge* forge, |
|
||||||
const SamplerURIs* uris, |
|
||||||
const char* filename, |
|
||||||
const uint32_t filename_len) |
|
||||||
{ |
|
||||||
LV2_Atom_Forge_Frame frame; |
|
||||||
LV2_Atom_Forge_Ref set = lv2_atom_forge_object( |
|
||||||
forge, &frame, 0, uris->patch_Set); |
|
||||||
|
|
||||||
lv2_atom_forge_key(forge, uris->patch_property); |
|
||||||
lv2_atom_forge_urid(forge, uris->eg_sample); |
|
||||||
lv2_atom_forge_key(forge, uris->patch_value); |
|
||||||
lv2_atom_forge_path(forge, filename, filename_len); |
|
||||||
|
|
||||||
lv2_atom_forge_pop(forge, &frame); |
|
||||||
return set; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the file path from a message like: |
|
||||||
* [] |
|
||||||
* a patch:Set ; |
|
||||||
* patch:property eg:sample ; |
|
||||||
* patch:value </home/me/foo.wav> . |
|
||||||
*/ |
|
||||||
static inline const char* |
|
||||||
read_set_file(const SamplerURIs* uris, |
|
||||||
const LV2_Atom_Object* obj) |
|
||||||
{ |
|
||||||
if (obj->body.otype != uris->patch_Set) { |
|
||||||
fprintf(stderr, "Ignoring unknown message type %d\n", obj->body.otype); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
/* Get property URI. */ |
|
||||||
const LV2_Atom* property = NULL; |
|
||||||
lv2_atom_object_get(obj, uris->patch_property, &property, 0); |
|
||||||
if (!property) { |
|
||||||
fprintf(stderr, "Malformed set message has no body.\n"); |
|
||||||
return NULL; |
|
||||||
} else if (property->type != uris->atom_URID) { |
|
||||||
fprintf(stderr, "Malformed set message has non-URID property.\n"); |
|
||||||
return NULL; |
|
||||||
} else if (((const LV2_Atom_URID*)property)->body != uris->eg_sample) { |
|
||||||
fprintf(stderr, "Set message for unknown property.\n"); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
/* Get value. */ |
|
||||||
const LV2_Atom* value = NULL; |
|
||||||
lv2_atom_object_get(obj, uris->patch_value, &value, 0); |
|
||||||
if (!value) { |
|
||||||
fprintf(stderr, "Malformed set message has no value.\n"); |
|
||||||
return NULL; |
|
||||||
} else if (value->type != uris->atom_Path) { |
|
||||||
fprintf(stderr, "Set message value is not a Path.\n"); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
return (const char*)LV2_ATOM_BODY_CONST(value); |
|
||||||
} |
|
||||||
|
|
||||||
#endif /* SAMPLER_URIS_H */ |
|
@ -1 +0,0 @@ |
|||||||
../../waf |
|
@ -1,83 +0,0 @@ |
|||||||
#!/usr/bin/env python |
|
||||||
from waflib.extras import autowaf as autowaf |
|
||||||
import re |
|
||||||
|
|
||||||
# Variables for 'waf dist' |
|
||||||
APPNAME = 'eg-sampler.lv2' |
|
||||||
VERSION = '1.0.0' |
|
||||||
|
|
||||||
# Mandatory variables |
|
||||||
top = '.' |
|
||||||
out = 'build' |
|
||||||
|
|
||||||
def options(opt): |
|
||||||
opt.load('compiler_c') |
|
||||||
opt.load('lv2') |
|
||||||
autowaf.set_options(opt) |
|
||||||
|
|
||||||
def configure(conf): |
|
||||||
conf.load('compiler_c') |
|
||||||
conf.load('lv2') |
|
||||||
autowaf.configure(conf) |
|
||||||
autowaf.set_c99_mode(conf) |
|
||||||
autowaf.display_header('Sampler Configuration') |
|
||||||
|
|
||||||
if not autowaf.is_child(): |
|
||||||
autowaf.check_pkg(conf, 'lv2', atleast_version='1.2.1', uselib_store='LV2') |
|
||||||
|
|
||||||
autowaf.check_pkg(conf, 'sndfile', uselib_store='SNDFILE', |
|
||||||
atleast_version='1.0.0', mandatory=True) |
|
||||||
autowaf.check_pkg(conf, 'gtk+-2.0', uselib_store='GTK2', |
|
||||||
atleast_version='2.18.0', mandatory=False) |
|
||||||
conf.check(features='c cshlib', lib='m', uselib_store='M', mandatory=False) |
|
||||||
|
|
||||||
autowaf.display_msg(conf, 'LV2 bundle directory', conf.env.LV2DIR) |
|
||||||
print('') |
|
||||||
|
|
||||||
def build(bld): |
|
||||||
bundle = 'eg-sampler.lv2' |
|
||||||
|
|
||||||
# Make a pattern for shared objects without the 'lib' prefix |
|
||||||
module_pat = re.sub('^lib', '', bld.env.cshlib_PATTERN) |
|
||||||
module_ext = module_pat[module_pat.rfind('.'):] |
|
||||||
|
|
||||||
# Build manifest.ttl by substitution (for portable lib extension) |
|
||||||
bld(features = 'subst', |
|
||||||
source = 'manifest.ttl.in', |
|
||||||
target = '%s/%s' % (bundle, 'manifest.ttl'), |
|
||||||
install_path = '${LV2DIR}/%s' % bundle, |
|
||||||
LIB_EXT = module_ext) |
|
||||||
|
|
||||||
# Copy other data files to build bundle (build/eg-sampler.lv2) |
|
||||||
for i in ['sampler.ttl', 'click.wav']: |
|
||||||
bld(features = 'subst', |
|
||||||
is_copy = True, |
|
||||||
source = i, |
|
||||||
target = '%s/%s' % (bundle, i), |
|
||||||
install_path = '${LV2DIR}/%s' % bundle) |
|
||||||
|
|
||||||
# Use LV2 headers from parent directory if building as a sub-project |
|
||||||
includes = ['.'] |
|
||||||
if autowaf.is_child: |
|
||||||
includes += ['../..'] |
|
||||||
|
|
||||||
# Build plugin library |
|
||||||
obj = bld(features = 'c cshlib', |
|
||||||
source = 'sampler.c', |
|
||||||
name = 'sampler', |
|
||||||
target = '%s/sampler' % bundle, |
|
||||||
install_path = '${LV2DIR}/%s' % bundle, |
|
||||||
use = ['M', 'SNDFILE', 'LV2'], |
|
||||||
includes = includes) |
|
||||||
obj.env.cshlib_PATTERN = module_pat |
|
||||||
|
|
||||||
# Build UI library |
|
||||||
if bld.env.HAVE_GTK2: |
|
||||||
obj = bld(features = 'c cshlib', |
|
||||||
source = 'sampler_ui.c', |
|
||||||
name = 'sampler_ui', |
|
||||||
target = '%s/sampler_ui' % bundle, |
|
||||||
install_path = '${LV2DIR}/%s' % bundle, |
|
||||||
use = ['GTK2', 'LV2'], |
|
||||||
includes = includes) |
|
||||||
obj.env.cshlib_PATTERN = module_pat |
|
File diff suppressed because it is too large
Load Diff
@ -1,26 +0,0 @@ |
|||||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#> . |
|
||||||
@prefix pset: <http://lv2plug.in/ns/ext/presets#> . |
|
||||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . |
|
||||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . |
|
||||||
@prefix mdap: <http://moddevices.com/plugins/mda/presets#> . |
|
||||||
@prefix pset: <http://lv2plug.in/ns/ext/presets#> . |
|
||||||
|
|
||||||
<https://github.com/asb2m10/dexed> |
|
||||||
a lv2:Plugin ; |
|
||||||
lv2:binary <Dexed.so> ; |
|
||||||
rdfs:seeAlso <Dexed.ttl> . |
|
||||||
|
|
||||||
<https://github.com/asb2m10/dexed#ExternalUI> |
|
||||||
a <http://kxstudio.sf.net/ns/lv2ext/external-ui#Widget> ; |
|
||||||
ui:binary <Dexed.so> ; |
|
||||||
lv2:requiredFeature <http://lv2plug.in/ns/ext/instance-access> ; |
|
||||||
lv2:extensionData <http://kxstudio.sf.net/ns/lv2ext/programs#UIInterface> . |
|
||||||
|
|
||||||
<https://github.com/asb2m10/dexed#ParentUI> |
|
||||||
a ui:X11UI ; |
|
||||||
ui:binary <Dexed.so> ; |
|
||||||
lv2:requiredFeature <http://lv2plug.in/ns/ext/instance-access> ; |
|
||||||
lv2:optionalFeature ui:noUserResize ; |
|
||||||
lv2:extensionData <http://kxstudio.sf.net/ns/lv2ext/programs#UIInterface> . |
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue