naspro

view naspro-bridges-bad/dssi/lv2api.c @ 169:54b611b34083

Removed useless NDF bridge + a little fix in NASPRO core
author Stefano D'Angelo <zanga.mail@gmail.com>
date Thu Mar 11 05:47:49 2010 +0200 (2010-03-11)
parents 1bb57a7a5b46
children 4f7243a606b1
line source
1 /*
2 * NASPRO - NASPRO Architecture for Sound Processing
3 * LADSPA bridge
4 *
5 * Copyright (C) 2007-2009 Stefano D'Angelo <zanga.mail@gmail.com>
6 *
7 * See the COPYING file for license conditions.
8 */
10 #include <stdlib.h>
11 #include <string.h>
13 #include <alsa/seq_event.h>
14 #include <alsa/seq_midi_event.h>
16 #include <dssi.h>
17 #include <ladspa.h>
19 #include <lv2.h>
20 #include <lv2_uri_map.h>
21 #include <lv2_event.h>
23 #include <NASPRO/core/lib.h>
25 #include "pluglib.h"
26 #include "lv2api.h"
28 #define ALSA_EV_BUF_SIZE 128
29 #define DSSI_MAX_EVS 4096
31 struct ld_desc
32 {
33 LV2_Descriptor lv2_desc;
34 DSSI_Descriptor *d_desc;
35 };
37 struct instance
38 {
39 struct ld_desc *ld_desc;
40 LADSPA_Handle l_handle;
41 uint16_t midi_ev_id;
42 LV2_Event_Feature *lv2_ev_feat;
43 snd_midi_event_t *alsa_ev_parser;
44 LV2_Event_Buffer *lv2_ev_buf;
45 snd_seq_event_t dssi_evs[DSSI_MAX_EVS];
46 };
48 static struct ld_desc *descs = NULL;
49 static size_t descs_count = 0;
51 LV2_Handle
52 _nadssi_lv2api_instantiate(const LV2_Descriptor *descriptor,
53 double sample_rate, const char *bundle_path,
54 const LV2_Feature * const *features)
55 {
56 const LADSPA_Descriptor *ldesc;
57 LADSPA_Handle *handle;
58 struct instance *instance;
59 LV2_URI_Map_Feature *lv2_uri_map_feat;
60 size_t i;
62 instance = malloc(sizeof(struct instance));
63 if (instance == NULL)
64 return NULL;
66 lv2_uri_map_feat = NULL;
67 instance->lv2_ev_feat = NULL;
68 for (i = 0; features[i] != NULL; i++)
69 {
70 if (!strcmp(features[i]->URI,
71 "http://lv2plug.in/ns/ext/uri-map"))
72 {
73 lv2_uri_map_feat = features[i]->data;
74 continue;
75 }
76 if (!strcmp(features[i]->URI, "http://lv2plug.in/ns/ext/event"))
77 {
78 instance->lv2_ev_feat = features[i]->data;
79 continue;
80 }
81 }
83 if ((lv2_uri_map_feat == NULL) || (instance->lv2_ev_feat == NULL))
84 {
85 free(instance);
86 return NULL;
87 }
89 instance->midi_ev_id =
90 lv2_uri_map_feat->uri_to_id(lv2_uri_map_feat->callback_data,
91 "http://lv2plug.in/ns/ext/event",
92 "http://lv2plug.in/ns/ext/midi#MidiEvent");
93 if (instance->midi_ev_id == 0)
94 {
95 free(instance);
96 return NULL;
97 }
99 if (snd_midi_event_new(ALSA_EV_BUF_SIZE, &instance->alsa_ev_parser) < 0)
100 {
101 free(instance);
102 return NULL;
103 }
104 snd_midi_event_init(instance->alsa_ev_parser);
106 /* This should work correctly according to the ANSI C standard. */
107 ldesc = ((struct ld_desc *)descriptor)->d_desc->LADSPA_Plugin;
109 handle = ldesc->instantiate(ldesc, sample_rate);
110 if (handle == NULL)
111 {
112 snd_midi_event_free(instance->alsa_ev_parser);
113 free(instance);
114 return NULL;
115 }
117 instance->ld_desc = (struct ld_desc *)descriptor;
118 instance->l_handle = handle;
120 return (LV2_Handle)instance;
121 }
123 void
124 _nadssi_lv2api_connect_port(LV2_Handle instance, uint32_t port,
125 void *data_location)
126 {
127 struct instance *i;
129 /* This is needed to avoid a little incompatibility beetween LADSPA and
130 * LV2. LADSPA's connect_port() does not specify whether data_location
131 * is valid at the time it is being run, while LV2 mandates the plugin
132 * not to trust the memory location indicated by the pointer at the time
133 * connect_port() is run. */
134 if (data_location == NULL)
135 return;
137 i = ((struct instance *)instance);
139 if (port == i->ld_desc->d_desc->LADSPA_Plugin->PortCount)
140 i->lv2_ev_buf = (LV2_Event_Buffer *)data_location;
141 else
142 i->ld_desc->d_desc->LADSPA_Plugin->connect_port(i->l_handle,
143 port, data_location);
144 }
146 void
147 _nadssi_lv2api_activate(LV2_Handle instance)
148 {
149 struct instance *i;
151 i = (struct instance *)instance;
153 i->ld_desc->d_desc->LADSPA_Plugin->activate(i->l_handle);
154 }
156 static int
157 cmp_timestamp(const void *e1, const void *e2)
158 {
159 if (((snd_seq_event_t *)e1)->time.tick
160 < ((snd_seq_event_t *)e2)->time.tick)
161 return -1;
162 else if (((snd_seq_event_t *)e1)->time.tick
163 > ((snd_seq_event_t *)e2)->time.tick)
164 return 1;
165 else
166 return 0;
167 }
169 void
170 _nadssi_lv2api_run(LV2_Handle instance, uint32_t sample_count)
171 {
172 struct instance *i;
173 size_t j;
174 unsigned char *p, *data;
175 LV2_Event *lv2_ev;
176 snd_seq_event_t alsa_ev;
177 snd_seq_event_t *dssi_ev_p;
178 unsigned long cnt;
179 long err;
181 i = (struct instance *)instance;
183 if (i->ld_desc->d_desc->run_synth != NULL)
184 {
185 /* Convert LV2 MIDI events to ALSA sequencer events */
186 p = i->lv2_ev_buf->data;
187 dssi_ev_p = i->dssi_evs;
188 cnt = 0;
189 for (j = 0; j < (i->lv2_ev_buf->event_count)
190 && ((dssi_ev_p - i->dssi_evs) < DSSI_MAX_EVS); j++)
191 {
192 lv2_ev = (LV2_Event *)p;
193 p += sizeof(LV2_Event);
194 data = p;
195 p += lv2_ev->size + (((lv2_ev->size + 4) % 8)
196 ? (8 - (lv2_ev->size+4) % 8) : 0);
198 if (lv2_ev->type == 0)
199 {
200 i->lv2_ev_feat->lv2_event_unref(
201 i->lv2_ev_feat->callback_data, lv2_ev);
202 continue;
203 }
204 else if (lv2_ev->type != i->midi_ev_id)
205 continue;
207 err = snd_midi_event_encode(i->alsa_ev_parser, data,
208 lv2_ev->size, &alsa_ev);
209 if (err < 0)
210 {
211 snd_midi_event_reset_encode(i->alsa_ev_parser);
212 break;
213 }
215 if ((alsa_ev.type == SND_SEQ_EVENT_CONTROLLER)
216 || (alsa_ev.type == SND_SEQ_EVENT_PGMCHANGE))
217 continue;
219 alsa_ev.time.tick = lv2_ev->frames;
221 *dssi_ev_p = alsa_ev;
222 dssi_ev_p++;
223 cnt++;
224 }
226 /* Order ALSA sequencer events by timestamp */
227 qsort(i->dssi_evs, cnt, sizeof(snd_seq_event_t), cmp_timestamp);
229 i->ld_desc->d_desc->run_synth(i->l_handle, sample_count,
230 i->dssi_evs, cnt);
231 }
232 else
233 i->ld_desc->d_desc->LADSPA_Plugin->run(i->l_handle,
234 sample_count);
235 }
237 void
238 _nadssi_lv2api_deactivate(LV2_Handle instance)
239 {
240 struct instance *i;
242 i = (struct instance *)instance;
244 i->ld_desc->d_desc->LADSPA_Plugin->deactivate(i->l_handle);
245 }
247 void
248 _nadssi_lv2api_cleanup(LV2_Handle instance)
249 {
250 struct instance *i;
252 i = (struct instance *)instance;
254 i->ld_desc->d_desc->LADSPA_Plugin->cleanup(i->l_handle);
255 snd_midi_event_free(i->alsa_ev_parser);
256 free(i);
257 }
259 static void
260 generate_desc(void *content, void *data)
261 {
262 struct nacore_descriptor *ndesc;
263 DSSI_Descriptor *ddesc;
264 struct ld_desc *lddesc;
265 size_t *n;
267 n = (size_t *)data;
268 lddesc = descs + *n;
269 ndesc = (struct nacore_descriptor *)content;
270 ddesc = (DSSI_Descriptor *)ndesc->data;
272 nacore_lv2api_fill_desc(&lddesc->lv2_desc, ndesc);
273 lddesc->d_desc = ddesc;
275 (*n)++;
276 }
278 int
279 _nadssi_lv2api_generate_descs()
280 {
281 size_t n;
283 n = nacore_avl_tree_get_nodes_count(_nadssi_pluglib_desc_tree);
284 descs = malloc(n * sizeof(struct ld_desc));
285 if (descs == NULL)
286 return -1;
288 descs_count = n;
290 n = 0;
291 nacore_avl_tree_for_each(_nadssi_pluglib_desc_tree, generate_desc,
292 &n);
294 return 0;
295 }
297 void
298 _nadssi_lv2api_free_descs()
299 {
300 free(descs);
301 descs = NULL;
302 descs_count = 0;
303 }
305 const LV2_Descriptor *
306 lv2_descriptor(uint32_t index)
307 {
308 if (index >= descs_count)
309 return NULL;
311 return &descs[index].lv2_desc;
312 }