/[svn]/linuxsampler/trunk/src/hostplugins/lv2/PluginLv2.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/hostplugins/lv2/PluginLv2.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2356 - (show annotations) (download)
Sun Jul 8 14:44:47 2012 UTC (11 years, 8 months ago) by persson
File size: 11029 byte(s)
* LV2: use urid and atom extensions instead of deprecated uri-map and
  event
* LV2: lv2 package 1.0 is now required to build the LV2 plugin
* LV2: changed number of output channels to 16 stereo, just like the
  VST and AU plugins

1 /***************************************************************************
2 * *
3 * Copyright (C) 2008 - 2012 Andreas Persson *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
18 * MA 02110-1301 USA *
19 ***************************************************************************/
20
21 #include <algorithm>
22 #include <cassert>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 #include <fstream>
27 #include <string>
28
29 #include "PluginLv2.h"
30
31 #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#"
35
36 #define CHANNELS 32
37
38 namespace {
39
40 PluginLv2::PluginLv2(const LV2_Descriptor* Descriptor,
41 double SampleRate, const char* BundlePath,
42 const LV2_Feature* const* Features) {
43 Out = new float*[CHANNELS];
44 for (int i = 0 ; i < CHANNELS ; i++) {
45 Out[i] = 0;
46 }
47 UriMap = 0;
48 MapPath = 0;
49 MakePath = 0;
50 for (int i = 0 ; Features[i] ; i++) {
51 dmsg(2, ("linuxsampler: init feature: %s\n", Features[i]->URI));
52 if (!strcmp(Features[i]->URI, LV2_URID__map)) {
53 UriMap = (LV2_URID_Map*)Features[i]->data;
54 } else if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) {
55 MapPath = (LV2_State_Map_Path*)Features[i]->data;
56 } else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) {
57 MakePath = (LV2_State_Make_Path*)Features[i]->data;
58 }
59 }
60
61 MidiEventType = uri_to_id(LV2_MIDI__MidiEvent);
62
63 Init(SampleRate, 128, CHANNELS);
64
65 InitState();
66
67 DefaultState = GetState();
68 }
69
70 PluginLv2::~PluginLv2() {
71 delete[] Out;
72 }
73
74 void PluginLv2::ConnectPort(uint32_t Port, void* DataLocation) {
75 if (Port == 0) {
76 MidiBuf = static_cast<LV2_Atom_Sequence*>(DataLocation);
77 } else if (Port < CHANNELS + 1) {
78 Out[Port - 1] = static_cast<float*>(DataLocation);
79 }
80 }
81
82 void PluginLv2::Activate() {
83 dmsg(2, ("linuxsampler: Activate\n"));
84 }
85
86 void PluginLv2::Run(uint32_t SampleCount) {
87 int samplePos = 0;
88
89 LV2_Atom_Event* ev = lv2_atom_sequence_begin(&MidiBuf->body);
90
91 while (SampleCount) {
92 int samples = std::min(SampleCount, 128U);
93
94 for ( ; !lv2_atom_sequence_is_end(&MidiBuf->body,
95 MidiBuf->atom.size, ev) ;
96 ev = lv2_atom_sequence_next(ev)) {
97 if (ev->body.type == MidiEventType) {
98
99 int time = ev->time.frames - samplePos;
100 if (time >= samples) break;
101
102 uint8_t* data = reinterpret_cast<uint8_t*>(ev + 1);
103
104 pMidiDevice->Port()->DispatchRaw(data, time);
105 }
106 }
107 for (int i = 0 ; i < CHANNELS ; i++) {
108 pAudioDevice->Channel(i)->SetBuffer(Out[i] + samplePos);
109 }
110 pAudioDevice->Render(samples);
111
112 samplePos += samples;
113 SampleCount -= samples;
114 }
115 }
116
117 void PluginLv2::Deactivate() {
118 dmsg(2, ("linuxsampler: Deactivate\n"));
119 }
120
121 String PluginLv2::PathToState(const String& path) {
122 if (MapPath) {
123 char* cstr = MapPath->abstract_path(MapPath->handle, path.c_str());
124 const String abstract_path(cstr);
125 free(cstr);
126 return abstract_path;
127 }
128 return path;
129 }
130
131 String PluginLv2::PathFromState(const String& path) {
132 if (MapPath) {
133 char* cstr = MapPath->absolute_path(MapPath->handle, path.c_str());
134 const String abstract_path(cstr);
135 free(cstr);
136 return abstract_path;
137 }
138 return path;
139 }
140
141 void PluginLv2::SetStateFeatures(const LV2_Feature* const* Features)
142 {
143 for (int i = 0 ; Features[i] ; i++) {
144 dmsg(2, ("linuxsampler: state feature: %s\n", Features[i]->URI));
145 if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) {
146 MapPath = (LV2_State_Map_Path*)Features[i]->data;
147 } else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) {
148 MakePath = (LV2_State_Make_Path*)Features[i]->data;
149 }
150 }
151 }
152
153 LV2_State_Status PluginLv2::Save(
154 LV2_State_Store_Function store, LV2_State_Handle handle,
155 uint32_t flags, const LV2_Feature* const* features)
156 {
157 LV2_State_Map_Path* OldMapPath = MapPath;
158 LV2_State_Make_Path* OldMakePath = MakePath;
159 SetStateFeatures(features);
160
161 if (MakePath && MapPath) {
162 char* abs_path = MakePath->path(MakePath->handle, "linuxsampler");
163 dmsg(2, ("saving to file %s\n", abs_path));
164
165 std::ofstream out(abs_path);
166 out << GetState();
167
168 char* path = MapPath->abstract_path(MapPath->handle, abs_path);
169
170 store(handle,
171 uri_to_id(NS_LS "state-file"),
172 path,
173 strlen(path) + 1,
174 uri_to_id(LV2_ATOM__Path),
175 LV2_STATE_IS_PORTABLE);
176
177 free(path);
178 free(abs_path);
179 } else {
180 dmsg(2, ("saving to string\n"));
181
182 std::ostringstream out;
183 out << GetState();
184
185 store(handle,
186 uri_to_id(NS_LS "state-string"),
187 out.str().c_str(),
188 out.str().length() + 1,
189 uri_to_id(LV2_ATOM__String),
190 LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
191 }
192 dmsg(2, ("saving done\n"));
193
194 MapPath = OldMapPath;
195 MakePath = OldMakePath;
196
197 return LV2_STATE_SUCCESS;
198 }
199
200 LV2_State_Status PluginLv2::Restore(
201 LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle,
202 uint32_t rflags, const LV2_Feature* const* features)
203 {
204 LV2_State_Map_Path* OldMapPath = MapPath;
205 LV2_State_Make_Path* OldMakePath = MakePath;
206 SetStateFeatures(features);
207
208 size_t size;
209 uint32_t type;
210 uint32_t flags;
211
212 const void* value = retrieve(
213 handle,
214 uri_to_id(NS_LS "state-file"),
215 &size, &type, &flags);
216 if (value) {
217 // Restore from state-file
218 assert(type == uri_to_id(LV2_ATOM__Path));
219 const String path((const char*)value);
220 dmsg(2, ("linuxsampler: restoring from file %s\n", path.c_str()));
221 std::ifstream in(path.c_str());
222 String state;
223 std::getline(in, state, '\0');
224 SetState(state);
225 } else if ((value = retrieve(handle,
226 uri_to_id(NS_LS "state-string"),
227 &size, &type, &flags))) {
228 // Restore from state-string
229 dmsg(2, ("linuxsampler: restoring from string\n"));
230 assert(type == uri_to_id(LV2_ATOM__String));
231 String state((const char*)value);
232 SetState(state);
233 } else {
234 // No valid state found, reset to default state
235 dmsg(2, ("linuxsampler: restoring default state\n"));
236 SetState(DefaultState);
237 }
238
239 MapPath = OldMapPath;
240 MakePath = OldMakePath;
241
242 return LV2_STATE_SUCCESS;
243 }
244
245 LV2_Handle instantiate(const LV2_Descriptor* descriptor,
246 double sample_rate, const char* bundle_path,
247 const LV2_Feature* const* features) {
248 return new PluginLv2(descriptor, sample_rate, bundle_path, features);
249 }
250
251 void connect_port(LV2_Handle instance, uint32_t port, void* data_location) {
252 static_cast<PluginLv2*>(instance)->ConnectPort(port, data_location);
253 }
254
255 void activate(LV2_Handle instance) {
256 static_cast<PluginLv2*>(instance)->Activate();
257 }
258
259 void run(LV2_Handle instance, uint32_t sample_count) {
260 static_cast<PluginLv2*>(instance)->Run(sample_count);
261 }
262
263 void deactivate(LV2_Handle instance) {
264 static_cast<PluginLv2*>(instance)->Deactivate();
265 }
266
267 void cleanup(LV2_Handle instance) {
268 delete static_cast<PluginLv2*>(instance);
269 }
270
271 LV2_State_Status save(LV2_Handle handle, LV2_State_Store_Function store,
272 LV2_State_Handle state,
273 uint32_t flags, const LV2_Feature* const* features) {
274 return static_cast<PluginLv2*>(handle)->Save(
275 store, state, flags, features);
276 }
277
278 LV2_State_Status restore(LV2_Handle handle, LV2_State_Retrieve_Function retrieve,
279 LV2_State_Handle state,
280 uint32_t flags, const LV2_Feature* const* features) {
281 return static_cast<PluginLv2*>(handle)->Restore(
282 retrieve, state, flags, features);
283 }
284
285 PluginInfo PluginInfo::Instance;
286
287 PluginInfo::PluginInfo() {
288 Lv2.URI = "http://linuxsampler.org/plugins/linuxsampler";
289 Lv2.activate = activate;
290 Lv2.cleanup = cleanup;
291 Lv2.connect_port = connect_port;
292 Lv2.deactivate = deactivate;
293 Lv2.instantiate = instantiate;
294 Lv2.run = run;
295 Lv2.extension_data = extension_data;
296 StateInterface.save = save;
297 StateInterface.restore = restore;
298 }
299
300
301 const void* extension_data(const char* uri) {
302 dmsg(2, ("linuxsampler: extension_data %s\n", uri));
303 if (strcmp(uri, LV2_STATE__interface) == 0) {
304 return PluginInfo::Lv2StateInterface();
305 }
306 return 0;
307 }
308 }
309
310
311 extern "C" {
312 LV2_SYMBOL_EXPORT
313 const LV2_Descriptor* lv2_descriptor(uint32_t index) {
314 return index == 0 ? PluginInfo::Lv2Descriptor() : 0;
315 }
316 }

  ViewVC Help
Powered by ViewVC