/[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 2360 - (show annotations) (download)
Thu Aug 16 17:01:35 2012 UTC (11 years, 8 months ago) by persson
File size: 11552 byte(s)
* LV2: fixed save/restore of SFZ state (patch by David Robillard)
* LV2: made LV2 plugin buildable on Windows and Mac

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 #define _BSD_SOURCE 1 /* for realpath() */
22
23 #include <algorithm>
24 #include <cassert>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
28 #include <fstream>
29 #include <string>
30
31 #include "PluginLv2.h"
32
33 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
34 #include <lv2/lv2plug.in/ns/ext/midi/midi.h>
35
36 #define NS_LS "http://linuxsampler.org/schema#"
37
38 #define CHANNELS 32
39
40 namespace {
41
42 PluginLv2::PluginLv2(const LV2_Descriptor* Descriptor,
43 double SampleRate, const char* BundlePath,
44 const LV2_Feature* const* Features) {
45 Out = new float*[CHANNELS];
46 for (int i = 0 ; i < CHANNELS ; i++) {
47 Out[i] = 0;
48 }
49 UriMap = 0;
50 MapPath = 0;
51 MakePath = 0;
52 for (int i = 0 ; Features[i] ; i++) {
53 dmsg(2, ("linuxsampler: init feature: %s\n", Features[i]->URI));
54 if (!strcmp(Features[i]->URI, LV2_URID__map)) {
55 UriMap = (LV2_URID_Map*)Features[i]->data;
56 } else if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) {
57 MapPath = (LV2_State_Map_Path*)Features[i]->data;
58 } else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) {
59 MakePath = (LV2_State_Make_Path*)Features[i]->data;
60 }
61 }
62
63 MidiEventType = uri_to_id(LV2_MIDI__MidiEvent);
64
65 Init(SampleRate, 128, CHANNELS);
66
67 InitState();
68
69 DefaultState = GetState();
70 }
71
72 PluginLv2::~PluginLv2() {
73 delete[] Out;
74 }
75
76 void PluginLv2::ConnectPort(uint32_t Port, void* DataLocation) {
77 if (Port == 0) {
78 MidiBuf = static_cast<LV2_Atom_Sequence*>(DataLocation);
79 } else if (Port < CHANNELS + 1) {
80 Out[Port - 1] = static_cast<float*>(DataLocation);
81 }
82 }
83
84 void PluginLv2::Activate() {
85 dmsg(2, ("linuxsampler: Activate\n"));
86 }
87
88 void PluginLv2::Run(uint32_t SampleCount) {
89 int samplePos = 0;
90
91 LV2_Atom_Event* ev = lv2_atom_sequence_begin(&MidiBuf->body);
92
93 while (SampleCount) {
94 int samples = std::min(SampleCount, 128U);
95
96 for ( ; !lv2_atom_sequence_is_end(&MidiBuf->body,
97 MidiBuf->atom.size, ev) ;
98 ev = lv2_atom_sequence_next(ev)) {
99 if (ev->body.type == MidiEventType) {
100
101 int time = ev->time.frames - samplePos;
102 if (time >= samples) break;
103
104 uint8_t* data = reinterpret_cast<uint8_t*>(ev + 1);
105
106 pMidiDevice->Port()->DispatchRaw(data, time);
107 }
108 }
109 for (int i = 0 ; i < CHANNELS ; i++) {
110 pAudioDevice->Channel(i)->SetBuffer(Out[i] + samplePos);
111 }
112 pAudioDevice->Render(samples);
113
114 samplePos += samples;
115 SampleCount -= samples;
116 }
117 }
118
119 void PluginLv2::Deactivate() {
120 dmsg(2, ("linuxsampler: Deactivate\n"));
121 }
122
123 static String RealPath(const String& path)
124 {
125 String out = path;
126 char* cpath = NULL;
127 #ifdef _WIN32
128 cpath = (char*)malloc(MAX_PATH);
129 GetFullPathName(path.c_str(), MAX_PATH, cpath, NULL);
130 #else
131 cpath = realpath(path.c_str(), NULL);
132 #endif
133 if (cpath) {
134 out = cpath;
135 free(cpath);
136 }
137 return out;
138 }
139
140 String PluginLv2::PathToState(const String& path) {
141 if (MapPath) {
142 char* cstr = MapPath->abstract_path(MapPath->handle, path.c_str());
143 const String abstract_path(cstr);
144 free(cstr);
145 return abstract_path;
146 }
147 return path;
148 }
149
150 String PluginLv2::PathFromState(const String& path) {
151 if (MapPath) {
152 char* cstr = MapPath->absolute_path(MapPath->handle, path.c_str());
153 // Resolve symbolic links so SFZ sample paths load correctly
154 const String absolute_path(RealPath(cstr));
155 free(cstr);
156 return absolute_path;
157 }
158 return path;
159 }
160
161 void PluginLv2::SetStateFeatures(const LV2_Feature* const* Features)
162 {
163 for (int i = 0 ; Features[i] ; i++) {
164 dmsg(2, ("linuxsampler: state feature: %s\n", Features[i]->URI));
165 if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) {
166 MapPath = (LV2_State_Map_Path*)Features[i]->data;
167 } else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) {
168 MakePath = (LV2_State_Make_Path*)Features[i]->data;
169 }
170 }
171 }
172
173 LV2_State_Status PluginLv2::Save(
174 LV2_State_Store_Function store, LV2_State_Handle handle,
175 uint32_t flags, const LV2_Feature* const* features)
176 {
177 LV2_State_Map_Path* OldMapPath = MapPath;
178 LV2_State_Make_Path* OldMakePath = MakePath;
179 SetStateFeatures(features);
180
181 if (MakePath && MapPath) {
182 char* abs_path = MakePath->path(MakePath->handle, "linuxsampler");
183 dmsg(2, ("saving to file %s\n", abs_path));
184
185 std::ofstream out(abs_path);
186 out << GetState();
187
188 char* path = MapPath->abstract_path(MapPath->handle, abs_path);
189
190 store(handle,
191 uri_to_id(NS_LS "state-file"),
192 path,
193 strlen(path) + 1,
194 uri_to_id(LV2_ATOM__Path),
195 LV2_STATE_IS_PORTABLE);
196
197 free(path);
198 free(abs_path);
199 } else {
200 dmsg(2, ("saving to string\n"));
201
202 std::ostringstream out;
203 out << GetState();
204
205 store(handle,
206 uri_to_id(NS_LS "state-string"),
207 out.str().c_str(),
208 out.str().length() + 1,
209 uri_to_id(LV2_ATOM__String),
210 LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
211 }
212 dmsg(2, ("saving done\n"));
213
214 MapPath = OldMapPath;
215 MakePath = OldMakePath;
216
217 return LV2_STATE_SUCCESS;
218 }
219
220 LV2_State_Status PluginLv2::Restore(
221 LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle,
222 uint32_t rflags, const LV2_Feature* const* features)
223 {
224 LV2_State_Map_Path* OldMapPath = MapPath;
225 LV2_State_Make_Path* OldMakePath = MakePath;
226 SetStateFeatures(features);
227
228 size_t size;
229 uint32_t type;
230 uint32_t flags;
231
232 const void* value = retrieve(
233 handle,
234 uri_to_id(NS_LS "state-file"),
235 &size, &type, &flags);
236 if (value) {
237 // Restore from state-file
238 assert(type == uri_to_id(LV2_ATOM__Path));
239 const String path((const char*)value);
240 dmsg(2, ("linuxsampler: restoring from file %s\n", path.c_str()));
241 std::ifstream in(path.c_str());
242 String state;
243 std::getline(in, state, '\0');
244 SetState(state);
245 } else if ((value = retrieve(handle,
246 uri_to_id(NS_LS "state-string"),
247 &size, &type, &flags))) {
248 // Restore from state-string
249 dmsg(2, ("linuxsampler: restoring from string\n"));
250 assert(type == uri_to_id(LV2_ATOM__String));
251 String state((const char*)value);
252 SetState(state);
253 } else {
254 // No valid state found, reset to default state
255 dmsg(2, ("linuxsampler: restoring default state\n"));
256 SetState(DefaultState);
257 }
258
259 MapPath = OldMapPath;
260 MakePath = OldMakePath;
261
262 return LV2_STATE_SUCCESS;
263 }
264
265 LV2_Handle instantiate(const LV2_Descriptor* descriptor,
266 double sample_rate, const char* bundle_path,
267 const LV2_Feature* const* features) {
268 return new PluginLv2(descriptor, sample_rate, bundle_path, features);
269 }
270
271 void connect_port(LV2_Handle instance, uint32_t port, void* data_location) {
272 static_cast<PluginLv2*>(instance)->ConnectPort(port, data_location);
273 }
274
275 void activate(LV2_Handle instance) {
276 static_cast<PluginLv2*>(instance)->Activate();
277 }
278
279 void run(LV2_Handle instance, uint32_t sample_count) {
280 static_cast<PluginLv2*>(instance)->Run(sample_count);
281 }
282
283 void deactivate(LV2_Handle instance) {
284 static_cast<PluginLv2*>(instance)->Deactivate();
285 }
286
287 void cleanup(LV2_Handle instance) {
288 delete static_cast<PluginLv2*>(instance);
289 }
290
291 LV2_State_Status save(LV2_Handle handle, LV2_State_Store_Function store,
292 LV2_State_Handle state,
293 uint32_t flags, const LV2_Feature* const* features) {
294 return static_cast<PluginLv2*>(handle)->Save(
295 store, state, flags, features);
296 }
297
298 LV2_State_Status restore(LV2_Handle handle, LV2_State_Retrieve_Function retrieve,
299 LV2_State_Handle state,
300 uint32_t flags, const LV2_Feature* const* features) {
301 return static_cast<PluginLv2*>(handle)->Restore(
302 retrieve, state, flags, features);
303 }
304
305 PluginInfo PluginInfo::Instance;
306
307 PluginInfo::PluginInfo() {
308 Lv2.URI = "http://linuxsampler.org/plugins/linuxsampler";
309 Lv2.activate = activate;
310 Lv2.cleanup = cleanup;
311 Lv2.connect_port = connect_port;
312 Lv2.deactivate = deactivate;
313 Lv2.instantiate = instantiate;
314 Lv2.run = run;
315 Lv2.extension_data = extension_data;
316 StateInterface.save = save;
317 StateInterface.restore = restore;
318 }
319
320
321 const void* extension_data(const char* uri) {
322 dmsg(2, ("linuxsampler: extension_data %s\n", uri));
323 if (strcmp(uri, LV2_STATE__interface) == 0) {
324 return PluginInfo::Lv2StateInterface();
325 }
326 return 0;
327 }
328 }
329
330
331 extern "C" {
332 LV2_SYMBOL_EXPORT
333 const LV2_Descriptor* lv2_descriptor(uint32_t index) {
334 return index == 0 ? PluginInfo::Lv2Descriptor() : 0;
335 }
336 }

  ViewVC Help
Powered by ViewVC