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