Mercurial > audlegacy
annotate Plugins/Effect/ladspa/ladspa.c @ 827:6812adf5ff2e trunk
[svn] Okay, we need to pinch more playback code to avoid false positives.
author | chainsaw |
---|---|
date | Sun, 12 Mar 2006 15:05:18 -0800 |
parents | 6636d328fa38 |
children | 8bdcd65a57b7 |
rev | line source |
---|---|
277 | 1 /* xmms_ladspa - use LADSPA plugins from XMMS |
2 Copyright (C) 2002,2003 Nick Lamb <njl195@zepler.org.uk> | |
3 | |
4 This program is free software; you can redistribute it and/or modify | |
5 it under the terms of the GNU General Public License as published by | |
6 the Free Software Foundation; either version 2 of the License, or | |
7 (at your option) any later version. | |
8 | |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
15 along with this program; if not, write to the Free Software | |
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 */ | |
18 | |
19 /* BMP-ladspa port by Giacomo Lozito <city_hunter@users.sf.net> */ | |
20 | |
21 #include <stdlib.h> | |
22 #include <stdio.h> | |
23 #include <string.h> | |
24 #include <float.h> | |
25 #include <dlfcn.h> | |
26 #include <dirent.h> | |
27 #include <sys/types.h> | |
28 #include <gtk/gtk.h> | |
29 | |
30 #include <audacious/plugin.h> | |
306 | 31 #include <libaudacious/configdb.h> |
277 | 32 |
33 #include "../../../config.h" | |
34 #include "ladspa.h" | |
35 | |
36 #ifndef PATH_MAX | |
37 #define PATH_MAX 4096 | |
38 #endif | |
39 | |
751 | 40 #define PLUGIN_NAME "LADSPA host " PACKAGE_VERSION |
277 | 41 |
42 #define MAX_SAMPLES 8192 | |
43 #define MAX_KNOBS 64 | |
44 | |
45 typedef struct { | |
46 char *name; | |
47 char *filename; | |
48 long int id; | |
49 long int unique_id; | |
50 gboolean stereo; | |
51 } ladspa_plugin; | |
52 | |
53 typedef struct { | |
54 void *library; | |
55 char *filename; | |
56 gboolean stereo; | |
57 gboolean restored; | |
58 const LADSPA_Descriptor *descriptor; | |
59 LADSPA_Handle *handle; /* left or mono */ | |
60 LADSPA_Handle *handle2; /* right stereo */ | |
61 GtkWidget *window; | |
62 guint timeout; | |
63 GtkAdjustment *adjustments[MAX_KNOBS]; | |
64 LADSPA_Data knobs[MAX_KNOBS]; | |
65 } plugin_instance; | |
66 | |
67 static void start (void); | |
68 static void stop (void); | |
69 static int apply_effect (gpointer *d, gint length, AFormat afmt, | |
70 gint srate, gint nch); | |
71 static void configure(void); | |
72 | |
73 static void restore (void); | |
74 static plugin_instance * add_plugin (ladspa_plugin *plugin); | |
75 static void find_all_plugins(void); | |
76 static void find_plugins(char *path_entry); | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
306
diff
changeset
|
77 static ladspa_plugin *get_plugin_by_id(long id); |
277 | 78 static plugin_instance * load (char *filename, long int num); |
79 static void reboot_plugins (void); | |
80 static void boot_plugin (plugin_instance *instance); | |
81 static void port_assign(plugin_instance *instance); | |
82 static void shutdown (plugin_instance *instance); | |
83 static void unload (plugin_instance *instance); | |
84 | |
85 static GtkWidget * make_plugin_clist(void); | |
86 static void make_run_clist(void); | |
87 static void sort_column(GtkCList *clist, gint column, gpointer user_data); | |
88 static void select_plugin(GtkCList *clist, gint row, gint column, | |
89 GdkEventButton *event, gpointer user_data); | |
90 static void unselect_plugin(GtkCList *clist, gint row, gint column, | |
91 GdkEventButton *event, gpointer user_data); | |
92 static void add_plugin_clicked (GtkButton *button, gpointer user_data); | |
93 static void remove_plugin_clicked (GtkButton *button, gpointer user_data); | |
94 static void configure_plugin_clicked (GtkButton *button, gpointer user_data); | |
95 | |
96 static void draw_plugin(plugin_instance *instance); | |
97 | |
98 static LADSPA_Data left[MAX_SAMPLES], right[MAX_SAMPLES], trash[MAX_SAMPLES]; | |
99 | |
100 G_LOCK_DEFINE_STATIC(running_plugins); | |
101 | |
102 static GSList *plugin_list, *running_plugins; | |
103 | |
104 static ladspa_plugin * selected_plugin; | |
105 static plugin_instance * selected_instance; | |
106 | |
107 static struct { | |
108 AFormat afmt; | |
109 gint srate; | |
110 gint nch; | |
111 gboolean ignore; | |
112 gboolean running; | |
113 gboolean initialised; | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
306
diff
changeset
|
114 } state = { 0, 0, 0, FALSE, FALSE, FALSE}; |
277 | 115 |
116 static GtkWidget *config_window = NULL, *run_clist = NULL; | |
117 | |
118 static EffectPlugin xmms_plugin = { | |
119 NULL, NULL, | |
120 PLUGIN_NAME, | |
121 start, | |
122 stop, | |
123 NULL, | |
124 configure, | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
306
diff
changeset
|
125 apply_effect, |
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
306
diff
changeset
|
126 NULL |
277 | 127 }; |
128 | |
129 EffectPlugin *get_eplugin_info (void) | |
130 { | |
131 return &xmms_plugin; | |
132 } | |
133 | |
134 static void start (void) | |
135 { | |
136 if (state.initialised == FALSE) { | |
137 restore(); | |
138 } else if (state.srate > 0) { | |
139 reboot_plugins(); | |
140 } | |
141 state.running = TRUE; | |
142 } | |
143 | |
144 static void restore (void) | |
145 { | |
306 | 146 ConfigDb *db; |
277 | 147 gint k, plugins= 0; |
148 | |
306 | 149 db = bmp_cfg_db_open(); |
277 | 150 |
306 | 151 bmp_cfg_db_get_int(db, "ladspa", "plugins", &plugins); |
277 | 152 for (k= 0; k < plugins; ++k) { |
153 gint id; | |
154 int port, ports= 0; | |
155 plugin_instance *instance; | |
306 | 156 gchar *section = g_strdup_printf("ladspa_plugin%d", k); |
277 | 157 |
306 | 158 bmp_cfg_db_get_int(db, section, "id", &id); |
277 | 159 instance = add_plugin(get_plugin_by_id(id)); |
160 if (!instance) continue; /* couldn't load this plugin */ | |
306 | 161 bmp_cfg_db_get_int(db, section, "ports", &ports); |
277 | 162 for (port= 0; port < ports && port < MAX_KNOBS; ++port) { |
163 gchar *key = g_strdup_printf("port%d", port); | |
306 | 164 bmp_cfg_db_get_float(db, section, key, &(instance->knobs[port])); |
277 | 165 } |
166 instance->restored = TRUE; | |
167 g_free(section); | |
168 } | |
169 | |
170 state.initialised = TRUE; | |
306 | 171 bmp_cfg_db_close(db); |
277 | 172 } |
173 | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
306
diff
changeset
|
174 static ladspa_plugin *get_plugin_by_id(long id) |
277 | 175 { |
176 GSList *list; | |
177 ladspa_plugin *plugin; | |
178 | |
179 if (plugin_list == NULL) { | |
180 find_all_plugins(); | |
181 } | |
182 | |
183 for (list= plugin_list; list != NULL; list = g_slist_next(list)) { | |
184 plugin = (ladspa_plugin *) list->data; | |
185 if (plugin->unique_id == id) { | |
186 return plugin; | |
187 } | |
188 } | |
189 | |
190 return NULL; | |
191 } | |
192 | |
193 static void find_all_plugins (void) | |
194 { | |
195 char *ladspa_path, *directory; | |
196 | |
197 plugin_list = NULL; /* empty list */ | |
198 ladspa_path= getenv("LADSPA_PATH"); | |
199 if (ladspa_path == NULL) { | |
200 /* Fallback, look in obvious places */ | |
201 find_plugins("/usr/lib/ladspa"); | |
202 find_plugins("/usr/local/lib/ladspa"); | |
203 } else { | |
204 ladspa_path = g_strdup(ladspa_path); | |
205 | |
206 directory = strtok(ladspa_path, ":"); | |
207 while (directory != NULL) { | |
208 find_plugins(directory); | |
209 directory = strtok(NULL, ":"); | |
210 } | |
211 g_free(ladspa_path); | |
212 } | |
213 } | |
214 | |
215 static plugin_instance * load (char *filename, long int num) | |
216 { | |
217 LADSPA_Descriptor_Function descriptor_fn; | |
218 plugin_instance *instance; | |
219 | |
220 instance = g_new0(plugin_instance, 1); | |
221 | |
222 instance->filename = filename; | |
223 instance->library = dlopen(filename, RTLD_NOW); | |
224 if (instance->library == NULL) { | |
225 g_free(instance); | |
226 return NULL; | |
227 } | |
228 descriptor_fn = dlsym(instance->library, "ladspa_descriptor"); | |
229 if (descriptor_fn == NULL) { | |
230 g_free(instance); | |
231 return NULL; | |
232 } | |
233 instance->descriptor = descriptor_fn(num); | |
234 | |
235 return instance; | |
236 } | |
237 | |
238 static void unload (plugin_instance * instance) | |
239 { | |
240 if (instance->window) { | |
241 gtk_widget_destroy(instance->window); | |
242 instance->window = NULL; | |
243 } | |
244 | |
245 if (instance->timeout) { | |
246 gtk_timeout_remove(instance->timeout); | |
247 } | |
248 | |
249 shutdown(instance); | |
250 | |
251 if (instance->library) { | |
252 dlclose(instance->library); | |
253 } | |
254 } | |
255 | |
256 static void stop (void) | |
257 { | |
258 GSList *list; | |
306 | 259 ConfigDb *db; |
277 | 260 gint plugins = 0; |
261 | |
262 if (state.running == FALSE) { | |
263 return; | |
264 } | |
265 state.running = FALSE; | |
306 | 266 db = bmp_cfg_db_open(); |
277 | 267 G_LOCK (running_plugins); |
268 for (list= running_plugins; list != NULL; list = g_slist_next(list)) { | |
297
6862a829540c
[svn] Use GTK_SIGNAL_FUNC() where needed and remove a totally random const qualifier.
chainsaw
parents:
280
diff
changeset
|
269 plugin_instance *instance = (plugin_instance *) list->data; |
306 | 270 gchar *section = g_strdup_printf("ladspa_plugin%d", plugins++); |
277 | 271 int port, ports= 0; |
272 | |
306 | 273 bmp_cfg_db_set_int(db, section, "id", instance->descriptor->UniqueID); |
274 bmp_cfg_db_set_string(db, section, "file", instance->filename); | |
275 bmp_cfg_db_set_string(db, section, "label", (gchar *) | |
277 | 276 instance->descriptor->Label); |
277 | |
278 ports = instance->descriptor->PortCount; | |
279 if (ports > MAX_KNOBS) ports = MAX_KNOBS; | |
280 for (port= 0; port < ports; ++port) { | |
281 gchar *key = g_strdup_printf("port%d", port); | |
306 | 282 bmp_cfg_db_set_float(db, section, key, instance->knobs[port]); |
277 | 283 g_free(key); |
284 } | |
306 | 285 bmp_cfg_db_set_int(db, section, "ports", ports); |
277 | 286 g_free(section); |
287 shutdown (instance); | |
288 } | |
289 G_UNLOCK (running_plugins); | |
290 | |
306 | 291 bmp_cfg_db_set_int(db, "ladspa", "plugins", plugins); |
292 bmp_cfg_db_close(db); | |
277 | 293 } |
294 | |
295 static void shutdown (plugin_instance *instance) | |
296 { | |
297 const LADSPA_Descriptor * descriptor= instance->descriptor; | |
298 | |
299 if (instance->handle) { | |
300 if (descriptor->deactivate) { | |
301 descriptor->deactivate(instance->handle); | |
302 } | |
303 descriptor->cleanup(instance->handle); | |
304 instance->handle = NULL; | |
305 } | |
306 if (instance->handle2) { | |
307 if (descriptor->deactivate) { | |
308 descriptor->deactivate(instance->handle2); | |
309 } | |
310 descriptor->cleanup(instance->handle2); | |
311 instance->handle2 = NULL; | |
312 } | |
313 } | |
314 | |
315 static void boot_plugin (plugin_instance *instance) | |
316 { | |
317 const LADSPA_Descriptor * descriptor = instance->descriptor; | |
318 | |
319 shutdown(instance); | |
320 instance->handle = descriptor->instantiate(descriptor, state.srate); | |
321 if (state.nch > 1 && !instance->stereo) { | |
322 /* Create an additional instance */ | |
323 instance->handle2 = descriptor->instantiate(descriptor, state.srate); | |
324 } | |
325 | |
326 port_assign(instance); | |
327 | |
328 if (descriptor->activate) { | |
329 descriptor->activate(instance->handle); | |
330 if (instance->handle2) { | |
331 descriptor->activate(instance->handle2); | |
332 } | |
333 } | |
334 } | |
335 | |
336 static void reboot_plugins (void) | |
337 { | |
338 GSList *list; | |
339 | |
340 G_LOCK (running_plugins); | |
341 for (list= running_plugins; list != NULL; list = g_slist_next(list)) { | |
342 boot_plugin ((plugin_instance *) list->data); | |
343 } | |
344 G_UNLOCK (running_plugins); | |
345 } | |
346 | |
347 static int apply_effect (gpointer *d, gint length, AFormat afmt, | |
348 gint srate, gint nch) | |
349 { | |
350 gint16 *raw16 = *d; | |
351 GSList *list; | |
352 plugin_instance *instance; | |
353 int k; | |
354 | |
355 if (running_plugins == NULL || state.running == FALSE) { | |
356 return length; | |
357 } | |
358 | |
359 if (state.afmt != afmt || state.srate != srate || state.nch != nch) { | |
360 state.afmt = afmt; | |
361 state.srate = srate; | |
362 state.nch = nch; | |
363 | |
364 if (nch < 1 || nch > 2) | |
365 state.ignore = 1; | |
366 else if (afmt == FMT_S16_NE) | |
367 state.ignore = 0; | |
368 #if G_BYTE_ORDER == G_LITTLE_ENDIAN | |
369 else if (afmt == FMT_S16_LE) | |
370 state.ignore = 0; | |
371 #elif G_BYTE_ORDER == G_BIG_ENDIAN | |
372 else if (afmt == FMT_S16_BE) | |
373 state.ignore = 0; | |
374 #endif | |
375 else | |
376 state.ignore = 1; | |
377 | |
378 reboot_plugins(); | |
379 } | |
380 | |
381 if (state.ignore || length > MAX_SAMPLES * 2) { | |
382 return length; | |
383 } | |
384 | |
385 if (state.nch == 1) { | |
386 for (k= 0; k < length / 2; ++k) { | |
387 left[k] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f); | |
388 } | |
389 G_LOCK (running_plugins); | |
390 for (list= running_plugins; list != NULL; list = g_slist_next(list)) { | |
391 instance = (plugin_instance *) list->data; | |
392 if (instance->handle) { | |
393 instance->descriptor->run(instance->handle, length / 2); | |
394 } | |
395 } | |
396 G_UNLOCK (running_plugins); | |
397 for (k= 0; k < length / 2; ++k) { | |
398 raw16[k] = CLAMP((int) (left[k] * 32768.0f), -32768, 32767); | |
399 } | |
400 } else { | |
401 for (k= 0; k < length / 2; k += 2) { | |
402 left[k/2] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f); | |
403 } | |
404 for (k= 1; k < length / 2; k += 2) { | |
405 right[k/2] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f); | |
406 } | |
407 G_LOCK (running_plugins); | |
408 for (list= running_plugins; list != NULL; list = g_slist_next(list)) { | |
409 instance = (plugin_instance *) list->data; | |
410 if (instance->handle) { | |
411 instance->descriptor->run(instance->handle, length / 4); | |
412 } | |
413 if (instance->handle2) { | |
414 instance->descriptor->run(instance->handle2, length / 4); | |
415 } | |
416 } | |
417 G_UNLOCK (running_plugins); | |
418 for (k= 0; k < length / 2; k += 2) { | |
419 raw16[k] = CLAMP((int) (left[k/2] * 32768.0f), -32768, 32767); | |
420 } | |
421 for (k= 1; k < length / 2; k += 2) { | |
422 raw16[k] = CLAMP((int) (right[k/2] * 32768.0f), -32768, 32767); | |
423 } | |
424 } | |
425 | |
426 return length; | |
427 } | |
428 | |
429 static void port_assign(plugin_instance * instance) { | |
430 unsigned long port; | |
431 unsigned long inputs= 0, outputs= 0; | |
432 const LADSPA_Descriptor * plugin = instance->descriptor; | |
433 | |
434 for (port = 0; port < plugin->PortCount; ++port) { | |
435 | |
436 if (LADSPA_IS_PORT_CONTROL(plugin->PortDescriptors[port])) { | |
437 if (port < MAX_KNOBS) { | |
438 plugin->connect_port(instance->handle, port, &(instance->knobs[port])); | |
439 if (instance->handle2) | |
440 plugin->connect_port(instance->handle2, port, &(instance->knobs[port])); | |
441 } else { | |
442 plugin->connect_port(instance->handle, port, trash); | |
443 if (instance->handle2) | |
444 plugin->connect_port(instance->handle2, port, trash); | |
445 } | |
446 | |
447 } else if (LADSPA_IS_PORT_AUDIO(plugin->PortDescriptors[port])) { | |
448 | |
449 if (LADSPA_IS_PORT_INPUT(plugin->PortDescriptors[port])) { | |
450 if (inputs == 0) { | |
451 plugin->connect_port(instance->handle, port, left); | |
452 if (instance->handle2) | |
453 plugin->connect_port(instance->handle2, port, right); | |
454 } else if (inputs == 1 && instance->stereo) { | |
455 plugin->connect_port(instance->handle, port, right); | |
456 } else { | |
457 plugin->connect_port(instance->handle, port, trash); | |
458 if (instance->handle2) | |
459 plugin->connect_port(instance->handle2, port, trash); | |
460 } | |
461 inputs++; | |
462 | |
463 } else if (LADSPA_IS_PORT_OUTPUT(plugin->PortDescriptors[port])) { | |
464 if (outputs == 0) { | |
465 plugin->connect_port(instance->handle, port, left); | |
466 if (instance->handle2) | |
467 plugin->connect_port(instance->handle2, port, right); | |
468 } else if (outputs == 1 && instance->stereo) { | |
469 plugin->connect_port(instance->handle, port, right); | |
470 } else { | |
471 plugin->connect_port(instance->handle, port, trash); | |
472 if (instance->handle2) | |
473 plugin->connect_port(instance->handle2, port, trash); | |
474 } | |
475 outputs++; | |
476 | |
477 } | |
478 } | |
479 } | |
480 | |
481 } | |
482 | |
483 static void find_plugins(char *path_entry) | |
484 { | |
485 ladspa_plugin *plugin; | |
486 void *library = NULL; | |
487 char lib_name[PATH_MAX]; | |
488 LADSPA_Descriptor_Function descriptor_fn; | |
489 const LADSPA_Descriptor *descriptor; | |
490 DIR *dir; | |
491 struct dirent *dirent; | |
492 long int k; | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
306
diff
changeset
|
493 unsigned long int port, input, output; |
277 | 494 |
495 dir= opendir(path_entry); | |
496 if (dir == NULL) return; | |
497 | |
498 while ((dirent= readdir(dir))) { | |
499 snprintf(lib_name, PATH_MAX, "%s/%s", path_entry, dirent->d_name); | |
500 library = dlopen(lib_name, RTLD_LAZY); | |
501 if (library == NULL) { | |
502 continue; | |
503 } | |
504 descriptor_fn = dlsym(library, "ladspa_descriptor"); | |
505 if (descriptor_fn == NULL) { | |
506 dlclose(library); | |
507 continue; | |
508 } | |
509 | |
510 for (k= 0;; ++k) { | |
511 descriptor= descriptor_fn(k); | |
512 if (descriptor == NULL) { | |
513 break; | |
514 } | |
515 plugin = g_new(ladspa_plugin, 1); | |
516 plugin->name= g_strdup(descriptor->Name); | |
517 plugin->filename= g_strdup(lib_name); | |
518 plugin->id= k; | |
519 plugin->unique_id= descriptor->UniqueID; | |
520 for (input = output = port = 0; port < descriptor->PortCount; ++port) { | |
521 if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[port])) { | |
522 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[port])) | |
523 input++; | |
524 if (LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[port])) | |
525 output++; | |
526 } else if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[port])) { | |
527 } | |
528 } | |
529 if (input >= 2 && output >= 2) { | |
530 plugin->stereo= TRUE; | |
531 } else { | |
532 plugin->stereo= FALSE; | |
533 } | |
534 plugin_list = g_slist_prepend(plugin_list, plugin); | |
535 } | |
536 dlclose(library); | |
537 } | |
538 | |
539 closedir(dir); | |
540 return; | |
541 } | |
542 | |
543 static void value_changed(GtkAdjustment *adjustment, gpointer *user_data) | |
544 { | |
545 LADSPA_Data *data = (LADSPA_Data *) user_data; | |
546 | |
547 G_LOCK (running_plugins); | |
548 *data = (LADSPA_Data) adjustment->value; | |
549 G_UNLOCK (running_plugins); | |
550 } | |
551 | |
552 static void toggled(GtkToggleButton *togglebutton, gpointer *user_data) | |
553 { | |
554 LADSPA_Data *data = (LADSPA_Data *) user_data; | |
555 | |
556 if (gtk_toggle_button_get_active(togglebutton)) { | |
557 G_LOCK (running_plugins); | |
558 *data = (LADSPA_Data) 1.0f; | |
559 G_UNLOCK (running_plugins); | |
560 } else { | |
561 G_LOCK (running_plugins); | |
562 *data = (LADSPA_Data) -1.0f; | |
563 G_UNLOCK (running_plugins); | |
564 } | |
565 } | |
566 | |
567 static int update_instance (gpointer data) | |
568 { | |
569 plugin_instance *instance = (plugin_instance *) data; | |
570 unsigned long k; | |
571 | |
572 G_LOCK (running_plugins); | |
573 for (k = 0; k < MAX_KNOBS && k < instance->descriptor->PortCount; ++k) { | |
574 if (LADSPA_IS_PORT_OUTPUT(instance->descriptor->PortDescriptors[k]) | |
575 && LADSPA_IS_PORT_CONTROL(instance->descriptor->PortDescriptors[k])) { | |
576 instance->adjustments[k]->value = instance->knobs[k]; | |
577 gtk_adjustment_value_changed(instance->adjustments[k]); | |
578 } | |
579 } | |
580 G_UNLOCK (running_plugins); | |
581 return TRUE; | |
582 } | |
583 | |
584 static void draw_plugin(plugin_instance *instance) | |
585 { | |
586 const LADSPA_Descriptor *plugin = instance->descriptor; | |
587 const LADSPA_PortRangeHint *hints = plugin->PortRangeHints; | |
588 LADSPA_Data fact, min, max, step, start; | |
589 int dp; | |
590 unsigned long k; | |
591 gboolean no_ui = TRUE; | |
592 GtkWidget *widget, *vbox, *hbox; | |
593 GtkObject *adjustment; | |
594 | |
595 if (instance->window != NULL) { | |
596 /* Just show window */ | |
597 gtk_widget_show(instance->window); | |
598 return; | |
599 } | |
600 | |
601 instance->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
602 gtk_window_set_title(GTK_WINDOW(instance->window), plugin->Name); | |
603 | |
604 vbox= gtk_vbox_new(FALSE, 3); | |
605 | |
606 for (k = 0; k < MAX_KNOBS && k < plugin->PortCount; ++k) { | |
607 if (! LADSPA_IS_PORT_CONTROL(plugin->PortDescriptors[k])) | |
608 continue; | |
609 no_ui = FALSE; | |
610 hbox = gtk_hbox_new(FALSE, 3); | |
611 widget = gtk_label_new(plugin->PortNames[k]); | |
612 gtk_container_add(GTK_CONTAINER(hbox), widget); | |
613 | |
614 if (LADSPA_IS_HINT_TOGGLED(hints[k].HintDescriptor)) { | |
615 widget = gtk_toggle_button_new_with_label("Press"); | |
616 gtk_signal_connect(GTK_OBJECT(widget), "toggled", | |
297
6862a829540c
[svn] Use GTK_SIGNAL_FUNC() where needed and remove a totally random const qualifier.
chainsaw
parents:
280
diff
changeset
|
617 GTK_SIGNAL_FUNC(toggled), &(instance->knobs[k])); |
277 | 618 gtk_container_add(GTK_CONTAINER(hbox), widget); |
619 gtk_container_add(GTK_CONTAINER(vbox), hbox); | |
620 continue; | |
621 } | |
622 | |
623 if (LADSPA_IS_HINT_SAMPLE_RATE(hints[k].HintDescriptor)) { | |
624 fact = state.srate ? state.srate : 44100.0f; | |
625 } else { | |
626 fact = 1.0f; | |
627 } | |
628 | |
629 if (LADSPA_IS_HINT_BOUNDED_BELOW(hints[k].HintDescriptor)) { | |
630 min= hints[k].LowerBound * fact; | |
631 } else { | |
632 min= -10000.0f; | |
633 } | |
634 | |
635 if (LADSPA_IS_HINT_BOUNDED_ABOVE(hints[k].HintDescriptor)) { | |
636 max= hints[k].UpperBound * fact; | |
637 } else { | |
638 max= 10000.0f; | |
639 } | |
640 | |
641 /* infinity */ | |
642 if (10000.0f <= max - min) { | |
643 dp = 1; | |
644 step = 5.0f; | |
645 | |
646 /* 100.0 ... lots */ | |
647 } else if (100.0f < max - min) { | |
648 dp = 0; | |
649 step = 5.0f; | |
650 | |
651 /* 10.0 ... 100.0 */ | |
652 } else if (10.0f < max - min) { | |
653 dp = 1; | |
654 step = 0.5f; | |
655 | |
656 /* 1.0 ... 10.0 */ | |
657 } else if (1.0f < max - min) { | |
658 dp = 2; | |
659 step = 0.05f; | |
660 | |
661 /* 0.0 ... 1.0 */ | |
662 } else { | |
663 dp = 3; | |
664 step = 0.005f; | |
665 } | |
666 | |
667 if (LADSPA_IS_HINT_INTEGER(hints[k].HintDescriptor)) { | |
668 dp = 0; | |
669 if (step < 1.0f) step = 1.0f; | |
670 } | |
671 | |
672 if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hints[k].HintDescriptor)) { | |
673 start = min; | |
674 } else if (LADSPA_IS_HINT_DEFAULT_LOW(hints[k].HintDescriptor)) { | |
675 start = min * 0.75f + max * 0.25f; | |
676 } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hints[k].HintDescriptor)) { | |
677 start = min * 0.5f + max * 0.5f; | |
678 } else if (LADSPA_IS_HINT_DEFAULT_HIGH(hints[k].HintDescriptor)) { | |
679 start = min * 0.25f + max * 0.75f; | |
680 } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hints[k].HintDescriptor)) { | |
681 start = max; | |
682 } else if (LADSPA_IS_HINT_DEFAULT_0(hints[k].HintDescriptor)) { | |
683 start = 0.0f; | |
684 } else if (LADSPA_IS_HINT_DEFAULT_1(hints[k].HintDescriptor)) { | |
685 start = 1.0f; | |
686 } else if (LADSPA_IS_HINT_DEFAULT_100(hints[k].HintDescriptor)) { | |
687 start = 100.0f; | |
688 } else if (LADSPA_IS_HINT_DEFAULT_440(hints[k].HintDescriptor)) { | |
689 start = 440.0f; | |
690 } else if (LADSPA_IS_HINT_INTEGER(hints[k].HintDescriptor)) { | |
691 start = min; | |
692 } else if (max >= 0.0f && min <= 0.0f) { | |
693 start = 0.0f; | |
694 } else { | |
695 start = min * 0.5f + max * 0.5f; | |
696 } | |
697 | |
698 if (instance->restored) { | |
699 start = instance->knobs[k]; | |
700 } else { | |
701 instance->knobs[k] = start; | |
702 } | |
703 adjustment = gtk_adjustment_new(start, min, max, step, step * 10.0, 0.0); | |
704 instance->adjustments[k] = GTK_ADJUSTMENT(adjustment); | |
705 widget = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), step, dp); | |
706 if (LADSPA_IS_PORT_OUTPUT(plugin->PortDescriptors[k])) { | |
707 gtk_widget_set_sensitive(widget, FALSE); | |
708 } else { | |
709 gtk_signal_connect(adjustment, "value-changed", | |
710 GTK_SIGNAL_FUNC(value_changed), &(instance->knobs[k])); | |
711 } | |
712 gtk_container_add(GTK_CONTAINER(hbox), widget); | |
713 widget = gtk_hscale_new(GTK_ADJUSTMENT(adjustment)); | |
714 gtk_scale_set_digits(GTK_SCALE(widget), dp); | |
715 if (LADSPA_IS_PORT_OUTPUT(plugin->PortDescriptors[k])) { | |
716 gtk_widget_set_sensitive(widget, FALSE); | |
717 } | |
718 gtk_container_add(GTK_CONTAINER(hbox), widget); | |
719 | |
720 gtk_container_add(GTK_CONTAINER(vbox), hbox); | |
721 } | |
722 | |
723 if (no_ui) { | |
724 widget = gtk_label_new("This LADSPA plugin has no user controls"); | |
725 gtk_container_add(GTK_CONTAINER(vbox), widget); | |
726 } | |
727 | |
728 instance->timeout = gtk_timeout_add(100, update_instance, instance); | |
729 | |
730 gtk_container_add(GTK_CONTAINER(instance->window), vbox); | |
731 | |
732 gtk_signal_connect (GTK_OBJECT (instance->window), "delete_event", | |
733 GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), NULL); | |
734 gtk_widget_show_all(instance->window); | |
735 } | |
736 | |
737 static void sort_column(GtkCList *clist, gint column, gpointer user_data) | |
738 { | |
739 gtk_clist_set_sort_column(clist, column); | |
740 gtk_clist_sort(clist); | |
741 } | |
742 | |
743 static void unselect_instance(GtkCList *clist, gint row, gint column, | |
744 GdkEventButton *event, gpointer user_data) | |
745 { | |
746 selected_instance= NULL; | |
747 } | |
748 | |
749 static void select_instance(GtkCList *clist, gint row, gint column, | |
750 GdkEventButton *event, gpointer user_data) | |
751 { | |
752 selected_instance= (plugin_instance *) gtk_clist_get_row_data(clist, row); | |
753 } | |
754 | |
755 static void reorder_instance(GtkCList *clist, gint from, gint to, | |
756 gpointer user_data) | |
757 { | |
758 void *data; | |
759 | |
760 G_LOCK (running_plugins); | |
761 data = g_slist_nth_data(running_plugins, from); | |
762 running_plugins= g_slist_remove(running_plugins, data); | |
763 running_plugins= g_slist_insert(running_plugins, data, to); | |
764 G_UNLOCK (running_plugins); | |
765 } | |
766 | |
767 static void make_run_clist(void) | |
768 { | |
769 char * titles[1] = { "Name" }; | |
770 GSList *list; | |
771 | |
772 run_clist = gtk_clist_new_with_titles(1, titles); | |
773 gtk_clist_column_titles_passive(GTK_CLIST (run_clist)); | |
774 gtk_clist_set_reorderable(GTK_CLIST (run_clist), TRUE); | |
775 gtk_signal_connect(GTK_OBJECT(run_clist), "select-row", | |
776 GTK_SIGNAL_FUNC(select_instance), NULL); | |
777 gtk_signal_connect(GTK_OBJECT(run_clist), "unselect-row", | |
778 GTK_SIGNAL_FUNC(unselect_instance), NULL); | |
779 gtk_signal_connect(GTK_OBJECT(run_clist), "row-move", | |
780 GTK_SIGNAL_FUNC(reorder_instance), NULL); | |
781 | |
782 G_LOCK (running_plugins); | |
783 for (list= running_plugins; list != NULL; list = g_slist_next(list)) { | |
784 gint row; | |
785 gchar *line[1]; | |
786 plugin_instance *instance = (plugin_instance *) list->data; | |
787 | |
788 line[0] = (char *) instance->descriptor->Name; | |
789 row = gtk_clist_append(GTK_CLIST (run_clist), line); | |
790 gtk_clist_set_row_data(GTK_CLIST (run_clist), row, (gpointer) instance); | |
791 gtk_clist_select_row(GTK_CLIST(run_clist), row, 0); | |
792 } | |
793 G_UNLOCK (running_plugins); | |
794 } | |
795 | |
796 static plugin_instance * add_plugin (ladspa_plugin *plugin) | |
797 { | |
798 plugin_instance *instance; | |
799 char * line[1]; | |
800 gint row; | |
801 | |
802 if (plugin == NULL) { | |
803 return NULL; | |
804 } | |
805 | |
806 instance = load(plugin->filename, plugin->id); | |
807 if (instance == NULL) { | |
808 return NULL; | |
809 } | |
810 | |
811 instance->stereo = plugin->stereo; | |
812 if (state.srate && state.running) { | |
813 /* Jump right in */ | |
814 boot_plugin(instance); | |
815 } | |
816 | |
817 if (run_clist) { | |
818 line[0] = (char *) instance->descriptor->Name; | |
819 row = gtk_clist_append(GTK_CLIST (run_clist), line); | |
820 gtk_clist_set_row_data(GTK_CLIST (run_clist), row, (gpointer) instance); | |
821 gtk_clist_select_row(GTK_CLIST(run_clist), row, 0); | |
822 draw_plugin(instance); | |
823 } | |
824 G_LOCK (running_plugins); | |
825 running_plugins = g_slist_append(running_plugins, instance); | |
826 G_UNLOCK (running_plugins); | |
827 | |
828 return instance; | |
829 } | |
830 | |
831 | |
832 static void unselect_plugin(GtkCList *clist, gint row, gint column, | |
833 GdkEventButton *event, gpointer user_data) | |
834 { | |
835 selected_plugin= NULL; | |
836 } | |
837 | |
838 static void select_plugin(GtkCList *clist, gint row, gint column, | |
839 GdkEventButton *event, gpointer user_data) | |
840 { | |
841 selected_plugin = (ladspa_plugin *) gtk_clist_get_row_data(clist, row); | |
842 gtk_clist_unselect_all(GTK_CLIST(run_clist)); | |
843 if (event->type == GDK_2BUTTON_PRESS) { | |
844 /* Double click */ | |
845 add_plugin(selected_plugin); | |
846 } | |
847 } | |
848 | |
849 static GtkWidget * make_plugin_clist(void) | |
850 { | |
851 ladspa_plugin *plugin; | |
852 GSList *list; | |
853 GtkWidget *clist; | |
854 char number[14]; | |
855 char * titles[2] = { "UID", "Name" }; | |
856 char * line[2]; | |
857 gint row; | |
858 | |
859 find_all_plugins(); | |
860 | |
861 clist = gtk_clist_new_with_titles(2, titles); | |
862 gtk_clist_column_titles_active(GTK_CLIST (clist)); | |
863 gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE); | |
864 gtk_clist_set_sort_column(GTK_CLIST (clist), 1); | |
865 | |
866 for (list= plugin_list; list != NULL; list = g_slist_next(list)) { | |
867 plugin = (ladspa_plugin *) list->data; | |
868 snprintf(number, sizeof(number), "%ld", plugin->unique_id); | |
869 line[0] = number; | |
870 line[1] = plugin->name; | |
871 row = gtk_clist_append(GTK_CLIST (clist), line); | |
872 gtk_clist_set_row_data(GTK_CLIST (clist), row, (gpointer) plugin); | |
873 } | |
874 gtk_clist_sort(GTK_CLIST (clist)); | |
875 | |
876 gtk_signal_connect(GTK_OBJECT(clist), "click-column", | |
877 GTK_SIGNAL_FUNC(sort_column), NULL); | |
878 gtk_signal_connect(GTK_OBJECT(clist), "select-row", | |
879 GTK_SIGNAL_FUNC(select_plugin), NULL); | |
880 gtk_signal_connect(GTK_OBJECT(clist), "unselect-row", | |
881 GTK_SIGNAL_FUNC(unselect_plugin), NULL); | |
882 | |
883 return clist; | |
884 } | |
885 | |
886 static void add_plugin_clicked (GtkButton *button, gpointer user_data) | |
887 { | |
888 add_plugin(selected_plugin); | |
889 } | |
890 | |
891 static void remove_plugin_clicked (GtkButton *button, gpointer user_data) | |
892 { | |
893 plugin_instance *instance = selected_instance; | |
894 gint row; | |
895 | |
896 if (instance == NULL) { | |
897 return; | |
898 } | |
899 row = gtk_clist_find_row_from_data(GTK_CLIST(run_clist), (gpointer) instance); | |
900 gtk_clist_remove(GTK_CLIST(run_clist), row); | |
901 | |
902 G_LOCK (running_plugins); | |
903 running_plugins = g_slist_remove(running_plugins, instance); | |
904 unload(instance); | |
905 G_UNLOCK (running_plugins); | |
906 selected_instance= NULL; | |
907 } | |
908 | |
909 static void configure_plugin_clicked (GtkButton *button, gpointer user_data) | |
910 { | |
911 if (selected_instance) { | |
912 draw_plugin(selected_instance); | |
913 } | |
914 } | |
915 | |
916 static void configure(void) | |
917 { | |
918 GtkWidget *widget, *vbox, *hbox, *bbox, *frame; | |
919 | |
920 if (config_window) { | |
921 /* just show the window */ | |
922 gtk_widget_show(config_window); | |
923 return; | |
924 } | |
925 | |
926 config_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
927 vbox= gtk_vbox_new(FALSE, 0); | |
928 hbox= gtk_hbox_new(TRUE, 0); | |
929 | |
930 frame= gtk_frame_new("Installed plugins"); | |
931 widget = gtk_scrolled_window_new(NULL, NULL); | |
932 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), | |
933 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); | |
934 gtk_container_add(GTK_CONTAINER(widget), make_plugin_clist()); | |
935 gtk_container_add(GTK_CONTAINER(frame), widget); | |
936 gtk_container_add(GTK_CONTAINER(hbox), frame); | |
937 | |
938 | |
939 frame= gtk_frame_new("Running plugins"); | |
940 widget = gtk_scrolled_window_new(NULL, NULL); | |
941 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), | |
942 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); | |
943 if (run_clist == NULL) { | |
944 make_run_clist(); | |
945 } | |
946 gtk_container_add(GTK_CONTAINER(widget), run_clist); | |
947 gtk_container_add(GTK_CONTAINER(frame), widget); | |
948 gtk_container_add(GTK_CONTAINER(hbox), frame); | |
949 gtk_container_add(GTK_CONTAINER(vbox), hbox); | |
950 | |
951 /* Buttons */ | |
952 bbox = gtk_hbutton_box_new(); | |
953 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD); | |
954 widget = gtk_button_new_with_label("Add"); | |
955 gtk_signal_connect(GTK_OBJECT(widget), "clicked", | |
956 GTK_SIGNAL_FUNC(add_plugin_clicked), NULL); | |
957 gtk_box_pack_end_defaults(GTK_BOX(bbox), widget); | |
958 widget = gtk_button_new_with_label("Remove"); | |
959 gtk_signal_connect(GTK_OBJECT(widget), "clicked", | |
960 GTK_SIGNAL_FUNC(remove_plugin_clicked), NULL); | |
961 gtk_box_pack_end_defaults(GTK_BOX(bbox), widget); | |
962 widget = gtk_button_new_with_label("Configure"); | |
963 gtk_signal_connect(GTK_OBJECT(widget), "clicked", | |
964 GTK_SIGNAL_FUNC(configure_plugin_clicked), NULL); | |
965 gtk_box_pack_end_defaults(GTK_BOX(bbox), widget); | |
966 | |
967 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); | |
968 | |
969 gtk_container_add(GTK_CONTAINER(config_window), vbox); | |
970 | |
280 | 971 gtk_window_set_title(GTK_WINDOW(config_window), "LADSPA Plugin Catalog"); |
277 | 972 gtk_widget_set_usize(config_window, 380, 400); |
973 gtk_signal_connect (GTK_OBJECT (config_window), "delete_event", | |
974 GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), NULL); | |
975 | |
976 gtk_widget_show_all(config_window); | |
977 } |