28 |
|
|
29 |
#include "PluginLv2.h" |
#include "PluginLv2.h" |
30 |
|
|
31 |
#define NS_ATOM "http://lv2plug.in/ns/ext/atom#" |
#include <lv2/lv2plug.in/ns/ext/atom/util.h> |
32 |
|
#include <lv2/lv2plug.in/ns/ext/midi/midi.h> |
33 |
|
|
34 |
#define NS_LS "http://linuxsampler.org/schema#" |
#define NS_LS "http://linuxsampler.org/schema#" |
35 |
|
|
36 |
|
#define CHANNELS 32 |
37 |
|
|
38 |
namespace { |
namespace { |
39 |
|
|
40 |
PluginLv2::PluginLv2(const LV2_Descriptor* Descriptor, |
PluginLv2::PluginLv2(const LV2_Descriptor* Descriptor, |
41 |
double SampleRate, const char* BundlePath, |
double SampleRate, const char* BundlePath, |
42 |
const LV2_Feature* const* Features) { |
const LV2_Feature* const* Features) { |
43 |
Out[0] = 0; |
Out = new float*[CHANNELS]; |
44 |
Out[1] = 0; |
for (int i = 0 ; i < CHANNELS ; i++) { |
45 |
|
Out[i] = 0; |
46 |
|
} |
47 |
UriMap = 0; |
UriMap = 0; |
48 |
MapPath = 0; |
MapPath = 0; |
49 |
MakePath = 0; |
MakePath = 0; |
50 |
for (int i = 0 ; Features[i] ; i++) { |
for (int i = 0 ; Features[i] ; i++) { |
51 |
dmsg(2, ("linuxsampler: init feature: %s\n", Features[i]->URI)); |
dmsg(2, ("linuxsampler: init feature: %s\n", Features[i]->URI)); |
52 |
if (!strcmp(Features[i]->URI, LV2_URI_MAP_URI)) { |
if (!strcmp(Features[i]->URI, LV2_URID__map)) { |
53 |
UriMap = (LV2_URI_Map_Feature*)Features[i]->data; |
UriMap = (LV2_URID_Map*)Features[i]->data; |
54 |
} else if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) { |
} else if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) { |
55 |
MapPath = (LV2_State_Map_Path*)Features[i]->data; |
MapPath = (LV2_State_Map_Path*)Features[i]->data; |
56 |
} else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) { |
} else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) { |
58 |
} |
} |
59 |
} |
} |
60 |
|
|
61 |
Init(SampleRate, 128); |
MidiEventType = uri_to_id(LV2_MIDI__MidiEvent); |
62 |
|
|
63 |
|
Init(SampleRate, 128, CHANNELS); |
64 |
|
|
65 |
InitState(); |
InitState(); |
66 |
|
|
67 |
DefaultState = GetState(); |
DefaultState = GetState(); |
68 |
} |
} |
69 |
|
|
70 |
|
PluginLv2::~PluginLv2() { |
71 |
|
delete[] Out; |
72 |
|
} |
73 |
|
|
74 |
void PluginLv2::ConnectPort(uint32_t Port, void* DataLocation) { |
void PluginLv2::ConnectPort(uint32_t Port, void* DataLocation) { |
75 |
if (Port == 2) { |
if (Port == 0) { |
76 |
MidiBuf = static_cast<LV2_Event_Buffer*>(DataLocation); |
MidiBuf = static_cast<LV2_Atom_Sequence*>(DataLocation); |
77 |
} else if (Port < 2) { |
} else if (Port < CHANNELS + 1) { |
78 |
Out[Port] = static_cast<float*>(DataLocation); |
Out[Port - 1] = static_cast<float*>(DataLocation); |
79 |
} |
} |
80 |
} |
} |
81 |
|
|
85 |
|
|
86 |
void PluginLv2::Run(uint32_t SampleCount) { |
void PluginLv2::Run(uint32_t SampleCount) { |
87 |
int samplePos = 0; |
int samplePos = 0; |
88 |
uint8_t* events = MidiBuf->data; |
|
89 |
int eventCount = MidiBuf->event_count; |
LV2_Atom_Event* ev = lv2_atom_sequence_begin(&MidiBuf->body); |
90 |
|
|
91 |
while (SampleCount) { |
while (SampleCount) { |
92 |
int samples = std::min(SampleCount, 128U); |
int samples = std::min(SampleCount, 128U); |
93 |
|
|
94 |
for ( ; eventCount ; eventCount--) { |
for ( ; !lv2_atom_sequence_is_end(&MidiBuf->body, |
95 |
LV2_Event* event = reinterpret_cast<LV2_Event*>(events); |
MidiBuf->atom.size, ev) ; |
96 |
|
ev = lv2_atom_sequence_next(ev)) { |
97 |
|
if (ev->body.type == MidiEventType) { |
98 |
|
|
99 |
int time = event->frames - samplePos; |
int time = ev->time.frames - samplePos; |
100 |
if (time >= samples) break; |
if (time >= samples) break; |
101 |
|
|
102 |
uint8_t* data = events + sizeof(LV2_Event); |
uint8_t* data = reinterpret_cast<uint8_t*>(ev + 1); |
|
events += (sizeof(LV2_Event) + event->size + 7) & ~7; |
|
103 |
|
|
104 |
pMidiDevice->Port()->DispatchRaw(data, time); |
pMidiDevice->Port()->DispatchRaw(data, time); |
105 |
|
} |
106 |
|
} |
107 |
|
for (int i = 0 ; i < CHANNELS ; i++) { |
108 |
|
pAudioDevice->Channel(i)->SetBuffer(Out[i] + samplePos); |
109 |
} |
} |
|
pAudioDevice->Channel(0)->SetBuffer(Out[0] + samplePos); |
|
|
pAudioDevice->Channel(1)->SetBuffer(Out[1] + samplePos); |
|
110 |
pAudioDevice->Render(samples); |
pAudioDevice->Render(samples); |
111 |
|
|
112 |
samplePos += samples; |
samplePos += samples; |
151 |
} |
} |
152 |
|
|
153 |
LV2_State_Status PluginLv2::Save( |
LV2_State_Status PluginLv2::Save( |
154 |
LV2_State_Store_Function store, LV2_State_Handle handle, |
LV2_State_Store_Function store, LV2_State_Handle handle, |
155 |
uint32_t flags, const LV2_Feature* const* features) |
uint32_t flags, const LV2_Feature* const* features) |
156 |
{ |
{ |
157 |
LV2_State_Map_Path* OldMapPath = MapPath; |
LV2_State_Map_Path* OldMapPath = MapPath; |
158 |
LV2_State_Make_Path* OldMakePath = MakePath; |
LV2_State_Make_Path* OldMakePath = MakePath; |
168 |
char* path = MapPath->abstract_path(MapPath->handle, abs_path); |
char* path = MapPath->abstract_path(MapPath->handle, abs_path); |
169 |
|
|
170 |
store(handle, |
store(handle, |
171 |
uri_to_id(NULL, NS_LS "state-file"), |
uri_to_id(NS_LS "state-file"), |
172 |
path, |
path, |
173 |
strlen(path) + 1, |
strlen(path) + 1, |
174 |
uri_to_id(NULL, NS_ATOM "Path"), |
uri_to_id(LV2_ATOM__Path), |
175 |
LV2_STATE_IS_PORTABLE); |
LV2_STATE_IS_PORTABLE); |
176 |
|
|
177 |
free(path); |
free(path); |
183 |
out << GetState(); |
out << GetState(); |
184 |
|
|
185 |
store(handle, |
store(handle, |
186 |
uri_to_id(NULL, NS_LS "state-string"), |
uri_to_id(NS_LS "state-string"), |
187 |
out.str().c_str(), |
out.str().c_str(), |
188 |
out.str().length() + 1, |
out.str().length() + 1, |
189 |
uri_to_id(NULL, NS_ATOM "String"), |
uri_to_id(LV2_ATOM__String), |
190 |
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); |
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); |
191 |
} |
} |
192 |
dmsg(2, ("saving done\n")); |
dmsg(2, ("saving done\n")); |
198 |
} |
} |
199 |
|
|
200 |
LV2_State_Status PluginLv2::Restore( |
LV2_State_Status PluginLv2::Restore( |
201 |
LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, |
LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, |
202 |
uint32_t rflags, const LV2_Feature* const* features) |
uint32_t rflags, const LV2_Feature* const* features) |
203 |
{ |
{ |
204 |
LV2_State_Map_Path* OldMapPath = MapPath; |
LV2_State_Map_Path* OldMapPath = MapPath; |
205 |
LV2_State_Make_Path* OldMakePath = MakePath; |
LV2_State_Make_Path* OldMakePath = MakePath; |
211 |
|
|
212 |
const void* value = retrieve( |
const void* value = retrieve( |
213 |
handle, |
handle, |
214 |
uri_to_id(NULL, NS_LS "state-file"), |
uri_to_id(NS_LS "state-file"), |
215 |
&size, &type, &flags); |
&size, &type, &flags); |
216 |
if (value) { |
if (value) { |
217 |
// Restore from state-file |
// Restore from state-file |
218 |
assert(type == uri_to_id(NULL, NS_ATOM "Path")); |
assert(type == uri_to_id(LV2_ATOM__Path)); |
219 |
const String path((const char*)value); |
const String path((const char*)value); |
220 |
dmsg(2, ("linuxsampler: restoring from file %s\n", path.c_str())); |
dmsg(2, ("linuxsampler: restoring from file %s\n", path.c_str())); |
221 |
std::ifstream in(path.c_str()); |
std::ifstream in(path.c_str()); |
223 |
std::getline(in, state, '\0'); |
std::getline(in, state, '\0'); |
224 |
SetState(state); |
SetState(state); |
225 |
} else if ((value = retrieve(handle, |
} else if ((value = retrieve(handle, |
226 |
uri_to_id(NULL, NS_LS "state-string"), |
uri_to_id(NS_LS "state-string"), |
227 |
&size, &type, &flags))) { |
&size, &type, &flags))) { |
228 |
// Restore from state-string |
// Restore from state-string |
229 |
dmsg(2, ("linuxsampler: restoring from string\n")); |
dmsg(2, ("linuxsampler: restoring from string\n")); |
230 |
assert(type == uri_to_id(NULL, NS_ATOM "String")); |
assert(type == uri_to_id(LV2_ATOM__String)); |
231 |
String state((const char*)value); |
String state((const char*)value); |
232 |
SetState(state); |
SetState(state); |
233 |
} else { |
} else { |