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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2356 - (hide annotations) (download)
Sun Jul 8 14:44:47 2012 UTC (11 years, 9 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 persson 1777 /***************************************************************************
2     * *
3 persson 2311 * Copyright (C) 2008 - 2012 Andreas Persson *
4 persson 1777 * *
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 capela 2174 #include <cassert>
23 persson 1777 #include <cstdio>
24     #include <cstdlib>
25     #include <cstring>
26     #include <fstream>
27     #include <string>
28    
29     #include "PluginLv2.h"
30    
31 persson 2356 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
32     #include <lv2/lv2plug.in/ns/ext/midi/midi.h>
33    
34 capela 2174 #define NS_LS "http://linuxsampler.org/schema#"
35    
36 persson 2356 #define CHANNELS 32
37    
38 persson 1777 namespace {
39    
40     PluginLv2::PluginLv2(const LV2_Descriptor* Descriptor,
41     double SampleRate, const char* BundlePath,
42     const LV2_Feature* const* Features) {
43 persson 2356 Out = new float*[CHANNELS];
44     for (int i = 0 ; i < CHANNELS ; i++) {
45     Out[i] = 0;
46     }
47 capela 2174 UriMap = 0;
48 capela 2291 MapPath = 0;
49     MakePath = 0;
50 persson 1777 for (int i = 0 ; Features[i] ; i++) {
51 schoenebeck 2304 dmsg(2, ("linuxsampler: init feature: %s\n", Features[i]->URI));
52 persson 2356 if (!strcmp(Features[i]->URI, LV2_URID__map)) {
53     UriMap = (LV2_URID_Map*)Features[i]->data;
54 capela 2340 } else if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) {
55 capela 2291 MapPath = (LV2_State_Map_Path*)Features[i]->data;
56 capela 2340 } else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) {
57 capela 2291 MakePath = (LV2_State_Make_Path*)Features[i]->data;
58 capela 2174 }
59 persson 1777 }
60    
61 persson 2356 MidiEventType = uri_to_id(LV2_MIDI__MidiEvent);
62 persson 1777
63 persson 2356 Init(SampleRate, 128, CHANNELS);
64    
65 persson 1777 InitState();
66 capela 2174
67     DefaultState = GetState();
68 persson 1777 }
69    
70 persson 2356 PluginLv2::~PluginLv2() {
71     delete[] Out;
72     }
73    
74 persson 1777 void PluginLv2::ConnectPort(uint32_t Port, void* DataLocation) {
75 persson 2356 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 persson 1777 }
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 persson 2356
89     LV2_Atom_Event* ev = lv2_atom_sequence_begin(&MidiBuf->body);
90    
91 persson 1777 while (SampleCount) {
92     int samples = std::min(SampleCount, 128U);
93    
94 persson 2356 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 persson 1777
99 persson 2356 int time = ev->time.frames - samplePos;
100     if (time >= samples) break;
101 persson 1777
102 persson 2356 uint8_t* data = reinterpret_cast<uint8_t*>(ev + 1);
103 persson 1777
104 persson 2356 pMidiDevice->Port()->DispatchRaw(data, time);
105     }
106 persson 1777 }
107 persson 2356 for (int i = 0 ; i < CHANNELS ; i++) {
108     pAudioDevice->Channel(i)->SetBuffer(Out[i] + samplePos);
109     }
110 persson 1777 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 capela 2174 String PluginLv2::PathToState(const String& path) {
122 capela 2291 if (MapPath) {
123 schoenebeck 2304 char* cstr = MapPath->abstract_path(MapPath->handle, path.c_str());
124 capela 2174 const String abstract_path(cstr);
125     free(cstr);
126     return abstract_path;
127     }
128     return path;
129     }
130 persson 1777
131 capela 2174 String PluginLv2::PathFromState(const String& path) {
132 capela 2291 if (MapPath) {
133 schoenebeck 2304 char* cstr = MapPath->absolute_path(MapPath->handle, path.c_str());
134 capela 2174 const String abstract_path(cstr);
135     free(cstr);
136     return abstract_path;
137     }
138     return path;
139     }
140 persson 1777
141 schoenebeck 2304 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 capela 2340 if (!strcmp(Features[i]->URI, LV2_STATE__mapPath)) {
146 schoenebeck 2304 MapPath = (LV2_State_Map_Path*)Features[i]->data;
147 capela 2340 } else if (!strcmp(Features[i]->URI, LV2_STATE__makePath)) {
148 schoenebeck 2304 MakePath = (LV2_State_Make_Path*)Features[i]->data;
149     }
150     }
151     }
152 persson 1777
153 capela 2340 LV2_State_Status PluginLv2::Save(
154 persson 2356 LV2_State_Store_Function store, LV2_State_Handle handle,
155     uint32_t flags, const LV2_Feature* const* features)
156 schoenebeck 2304 {
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 capela 2174 out << GetState();
167 persson 1777
168 schoenebeck 2304 char* path = MapPath->abstract_path(MapPath->handle, abs_path);
169    
170 capela 2291 store(handle,
171 persson 2356 uri_to_id(NS_LS "state-file"),
172 capela 2291 path,
173     strlen(path) + 1,
174 persson 2356 uri_to_id(LV2_ATOM__Path),
175 capela 2291 LV2_STATE_IS_PORTABLE);
176 schoenebeck 2304
177     free(path);
178     free(abs_path);
179 capela 2174 } else {
180     dmsg(2, ("saving to string\n"));
181 persson 1777
182 capela 2174 std::ostringstream out;
183     out << GetState();
184    
185 capela 2291 store(handle,
186 persson 2356 uri_to_id(NS_LS "state-string"),
187 capela 2174 out.str().c_str(),
188     out.str().length() + 1,
189 persson 2356 uri_to_id(LV2_ATOM__String),
190 capela 2291 LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
191 capela 2174 }
192 persson 1777 dmsg(2, ("saving done\n"));
193 schoenebeck 2304
194     MapPath = OldMapPath;
195     MakePath = OldMakePath;
196 capela 2340
197     return LV2_STATE_SUCCESS;
198 persson 1777 }
199    
200 capela 2340 LV2_State_Status PluginLv2::Restore(
201 persson 2356 LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle,
202     uint32_t rflags, const LV2_Feature* const* features)
203 schoenebeck 2304 {
204     LV2_State_Map_Path* OldMapPath = MapPath;
205     LV2_State_Make_Path* OldMakePath = MakePath;
206     SetStateFeatures(features);
207    
208 capela 2174 size_t size;
209     uint32_t type;
210     uint32_t flags;
211    
212     const void* value = retrieve(
213 capela 2291 handle,
214 persson 2356 uri_to_id(NS_LS "state-file"),
215 capela 2174 &size, &type, &flags);
216     if (value) {
217 persson 2311 // Restore from state-file
218 persson 2356 assert(type == uri_to_id(LV2_ATOM__Path));
219 capela 2291 const String path((const char*)value);
220 capela 2174 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 persson 2311 } else if ((value = retrieve(handle,
226 persson 2356 uri_to_id(NS_LS "state-string"),
227 persson 2311 &size, &type, &flags))) {
228     // Restore from state-string
229 capela 2174 dmsg(2, ("linuxsampler: restoring from string\n"));
230 persson 2356 assert(type == uri_to_id(LV2_ATOM__String));
231 capela 2174 String state((const char*)value);
232     SetState(state);
233 persson 2311 } else {
234     // No valid state found, reset to default state
235     dmsg(2, ("linuxsampler: restoring default state\n"));
236     SetState(DefaultState);
237 capela 2174 }
238    
239 persson 2311 MapPath = OldMapPath;
240     MakePath = OldMakePath;
241 schoenebeck 2304
242 capela 2340 return LV2_STATE_SUCCESS;
243 persson 1777 }
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 capela 2340 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 schoenebeck 2304 return static_cast<PluginLv2*>(handle)->Save(
275     store, state, flags, features);
276 persson 1777 }
277    
278 capela 2340 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 schoenebeck 2304 return static_cast<PluginLv2*>(handle)->Restore(
282     retrieve, state, flags, features);
283 persson 1777 }
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 capela 2291 StateInterface.save = save;
297     StateInterface.restore = restore;
298 persson 1777 }
299    
300    
301     const void* extension_data(const char* uri) {
302     dmsg(2, ("linuxsampler: extension_data %s\n", uri));
303 capela 2340 if (strcmp(uri, LV2_STATE__interface) == 0) {
304 capela 2291 return PluginInfo::Lv2StateInterface();
305 persson 1777 }
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