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