make midimap obey channels
[galan.git] / plugins / libvst.c
blob36e62ba56f3b6a5faa9ba435249f60e4caefd454
1 /* analyseplugin.c
3 Free software by Richard W.E. Furse. Do with as you will. No
4 warranty. */
6 /*****************************************************************************/
8 #include <math.h>
9 #include <stdio.h>
10 #include <string.h>
12 /*****************************************************************************/
14 #include "ladspa.h"
16 #include "ladspa-utils.h"
18 /*****************************************************************************/
20 /* includes for galan : */
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <stddef.h>
27 #include <gdk/gdk.h>
28 #include <gtk/gtk.h>
29 #include <gmodule.h>
31 #include "global.h"
32 #include "generator.h"
33 #include "comp.h"
34 #include "control.h"
35 #include "gencomp.h"
39 /* On Win32, these headers seem to need to follow glib.h */
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
44 #define GENERATOR_CLASS_NAME "vsttest1"
45 #define GENERATOR_CLASS_PATH "Misc/VST"
46 #define GENERATOR_CLASS_PIXMAP "template.xpm"
48 #define SIG_INPUT 0
49 #define SIG_OUTPUT 0
51 #define EVT_INPUT 0
52 #define NUM_EVENT_INPUTS 1
54 #define EVT_OUTPUT 0
55 #define NUM_EVENT_OUTPUTS 1
57 #include "AEffect.h"
59 typedef AEffect *(*AEMainFunc)( audioMasterCallback cb );
61 //typedef struct VPluginData {
62 // GList *insig, *outsig, *inevent, *outevent;
63 //} VPluginData;
66 typedef struct Data {
68 AEMainFunc main_func;
69 struct AEffect *aeff;
70 //LADSPA_Handle instance_handle;
71 //VPluginData *vpdat;
72 float *inevents;
73 float *outevents;
74 float *oldoutevents;
75 float **insignals;
76 float **outsignals;
77 SAMPLETIME lastrun;
79 } Data;
81 // Globals...
83 PRIVATE GHashTable *MainFuncIndex = NULL;
84 PRIVATE GHashTable *VPluginIndex = NULL;
86 long master_callback( AEffect *fx, long opcode, long index, long value, void *ptr, float opt ) {
87 return 2;
91 PRIVATE void run_plugin( Generator *g, int buflen ) {
92 Data *data = g->data;
93 int i,j;
95 for( i=0; i<data->aeff->numInputs; i++ ) {
97 //#if SAMPLE==double
98 // SAMPLE buf[MAXIMUM_REALTIME_STEP];
100 // if( gen_read_realtime_input( g, i, -1, buf, buflen ) ) {
102 // for( j=0; j<buflen; j++ )
103 // data->insignals[i][j] = buf[j];
104 //#else
106 if( gen_read_realtime_input( g, i, -1, data->insignals[i], buflen ) ) {
108 //#endif
110 } else {
112 for( j=0; j<buflen; j++ )
113 data->insignals[i][j] = 0.0;
118 data->aeff->processReplacing( data->aeff, data->insignals, data->outsignals, buflen );
119 data->lastrun = gen_get_sampletime();
121 #if 0
122 for( i=0; i<outecount; i++ ) {
124 //printf( "oev: %f", data->outevents[i] );
125 if( data->oldoutevents[i] != data->outevents[i] ) {
127 // send event...
129 AEvent event;
131 gen_init_aevent(&event, AE_NUMBER, NULL, 0, NULL, 0, gen_get_sampletime() );
133 #ifdef G_OS_WIN32
134 event.d.number = data->outevents[i];
135 #else
136 if( isnan(data->outevents[i]) || isinf( data->outevents[i]) ) {
137 printf( "nan ... \n" );
138 event.d.number = 0.0;
139 } else {
140 event.d.number = data->outevents[i];
142 #endif //G_OS_WIN32
144 gen_send_events(g, i, -1, &event);
146 //printf( "sending ev: %f on %d \n", event.d.number, i );
148 // copy new -> old
150 data->oldoutevents[i] = data->outevents[i];
153 #endif
156 PRIVATE void realtime_handler(Generator *g, AEvent *event) {
158 //Data *data = g->data;
160 switch (event->kind)
162 case AE_REALTIME:
164 run_plugin( g, event->d.integer );
165 break;
168 default:
169 g_warning("vst module doesn't care for events of kind %d.", event->kind);
170 break;
174 #if 0
175 PRIVATE LADSPA_Data get_default( ControlDescriptor *control, LADSPA_PortRangeHintDescriptor hint ) {
177 if( LADSPA_IS_HINT_HAS_DEFAULT( hint ) ) {
179 if( LADSPA_IS_HINT_DEFAULT_MINIMUM( hint ) )
180 return control->min;
181 if( LADSPA_IS_HINT_DEFAULT_LOW( hint ) )
182 return control->min * 0.75 + control->max * 0.25;
183 if( LADSPA_IS_HINT_DEFAULT_MIDDLE( hint ) )
184 return control->min * 0.5 + control->max * 0.5;
185 if( LADSPA_IS_HINT_DEFAULT_HIGH( hint ) )
186 return control->min * 0.25 + control->max * 0.75;
187 if( LADSPA_IS_HINT_DEFAULT_MAXIMUM( hint ) )
188 return control->max;
189 if( LADSPA_IS_HINT_DEFAULT_0( hint ) )
190 return 0.0;
191 if( LADSPA_IS_HINT_DEFAULT_1( hint ) )
192 return 1.0;
193 if( LADSPA_IS_HINT_DEFAULT_100( hint ) )
194 return 100.0;
195 if( LADSPA_IS_HINT_DEFAULT_440( hint ) )
196 return 440.0;
198 printf( "plugins says it has default... but i cant find out.\n" );
199 return 0.0;
201 } else
202 return 0.0;
205 #endif
207 PRIVATE gboolean init_instance(Generator *g) {
208 Data *data = safe_malloc(sizeof(Data));
209 int inecount, inscount, outscount, i;
215 g->data = data;
219 data->main_func = g_hash_table_lookup( MainFuncIndex, g->klass->tag );
220 //printf( "retrieved: %s %x\n", g->klass->name, data->ladspa_descriptor );
221 data->aeff = data->main_func( &master_callback );
222 //printf( "got instancehandle: %x\n", data->instance_handle );
224 // Connect the ports ... pre: alloc memory for the controls...
225 // connect wird erst vor dem laufen mit outpu_generator gemacht...
227 inecount = data->aeff->numParams;
228 inscount = data->aeff->numInputs;
229 outscount = data->aeff->numOutputs;
231 data->inevents = safe_malloc( sizeof( float ) * inecount );
232 //data->outevents = safe_malloc( sizeof( LADSPA_Data ) * outecount );
233 //data->oldoutevents = safe_malloc( sizeof( LADSPA_Data ) * outecount );
234 data->insignals = safe_malloc( sizeof( float * ) * inscount );
235 data->outsignals = safe_malloc( sizeof( float * ) * outscount );
237 for( i=0; i<inecount; i++ ) {
238 data->inevents[i] = data->aeff->getParameter( data->aeff, i );
242 // for( i=0; i<outecount; i++ ) {
243 // data->outevents[i] = 0.0;
244 // data->oldoutevents[i] = 0.0;
246 // data->ladspa_descriptor->connect_port(
247 // data->instance_handle,
248 // (int) g_list_nth_data( data->lpdat->outevent, i ),
249 // &(data->outevents[i]) );
251 // }
253 for( i=0; i<outscount; i++ ) {
254 data->outsignals[i] = safe_malloc( sizeof( float ) * MAXIMUM_REALTIME_STEP );
257 for( i=0; i<inscount; i++ ) {
258 data->insignals[i] = safe_malloc( sizeof( float ) * MAXIMUM_REALTIME_STEP );
261 data->aeff->dispatcher( data->aeff, effOpen, 0, 0, NULL, 0 );
262 data->aeff->dispatcher( data->aeff, effSetSampleRate, 0, 0, NULL, (float) SAMPLE_RATE );
263 data->aeff->dispatcher( data->aeff, effSetBlockSize, 0, MAXIMUM_REALTIME_STEP, NULL, 0 );
264 data->aeff->dispatcher( data->aeff, effMainsChanged, 0, 1, NULL, 0 );
266 data->lastrun = 0;
268 if( outscount == 0 )
269 gen_register_realtime_fn(g, realtime_handler);
271 return TRUE;
274 PRIVATE void destroy_instance(Generator *g) {
275 Data *data = g->data;
276 gen_deregister_realtime_fn(g, realtime_handler);
277 data->aeff->dispatcher( data->aeff, effClose, 0, 0, 0, 0 );
278 // TODO: what a mess free it all ....
279 free(g->data);
282 #if 0
283 PRIVATE void unpickle_instance(Generator *g, ObjectStoreItem *item, ObjectStore *db) {
284 Data *data = safe_malloc(sizeof(Data));
285 int inecount, outecount, inscount, outscount, i;
286 ObjectStoreDatum *inarray, *outarray;
287 g->data = data;
289 data->ladspa_descriptor = g_hash_table_lookup( DescriptorIndex, g->klass->tag );
290 data->lpdat = g_hash_table_lookup( LPluginIndex, g->klass->tag );
291 data->instance_handle = data->ladspa_descriptor->instantiate( data->ladspa_descriptor, SAMPLE_RATE );
295 inarray = objectstore_item_get(item, "ladspa_inarray");
296 outarray = objectstore_item_get(item, "ladspa_oldoutarray");
298 inecount = g_list_length( data->lpdat->inevent );
299 outecount = g_list_length( data->lpdat->outevent );
300 inscount = g_list_length( data->lpdat->insig );
301 outscount = g_list_length( data->lpdat->outsig );
303 data->inevents = safe_malloc( sizeof( LADSPA_Data ) * inecount );
304 data->outevents = safe_malloc( sizeof( LADSPA_Data ) * outecount );
305 data->oldoutevents = safe_malloc( sizeof( LADSPA_Data ) * outecount );
306 data->insignals = safe_malloc( sizeof( LADSPA_Data * ) * inscount );
307 data->outsignals = safe_malloc( sizeof( LADSPA_Data * ) * outscount );
309 for( i=0; i<inecount; i++ ) {
311 ObjectStoreDatum *field = objectstore_datum_array_get(inarray, i);
312 if( field )
313 data->inevents[i] = objectstore_datum_double_value( field );
314 else
316 unsigned long portindex = (unsigned long) g_list_nth_data( data->lpdat->inevent, i );
317 LADSPA_PortRangeHintDescriptor hint = data->ladspa_descriptor->PortRangeHints[portindex].HintDescriptor;
318 ControlDescriptor *control = &(g->klass->controls[i]);
320 data->inevents[i] = get_default( control, hint );
323 data->ladspa_descriptor->connect_port(
324 data->instance_handle,
325 (int) g_list_nth_data( data->lpdat->inevent, i ),
326 &(data->inevents[i]) );
328 for( i=0; i<outecount; i++ ) {
329 ObjectStoreDatum *field = objectstore_datum_array_get(outarray, i);
330 if( field )
331 data->oldoutevents[i] = objectstore_datum_double_value( field );
332 else
333 data->oldoutevents[i] = 0;
335 data->ladspa_descriptor->connect_port(
336 data->instance_handle,
337 (int) g_list_nth_data( data->lpdat->outevent, i ),
338 &(data->outevents[i]) );
340 for( i=0; i<outscount; i++ ) {
341 data->outsignals[i] = safe_malloc( sizeof( LADSPA_Data ) * MAXIMUM_REALTIME_STEP );
343 data->ladspa_descriptor->connect_port(
344 data->instance_handle,
345 (int) g_list_nth_data( data->lpdat->outsig, i ),
346 data->outsignals[i] );
348 for( i=0; i<inscount; i++ ) {
349 data->insignals[i] = safe_malloc( sizeof( LADSPA_Data ) * MAXIMUM_REALTIME_STEP );
351 data->ladspa_descriptor->connect_port(
352 data->instance_handle,
353 (int) g_list_nth_data( data->lpdat->insig, i ),
354 data->insignals[i] );
357 if( data->ladspa_descriptor->activate )
358 data->ladspa_descriptor->activate( data->instance_handle );
360 data->lastrun = 0;
362 if( outscount == 0 )
363 gen_register_realtime_fn(g, realtime_handler);
366 PRIVATE void pickle_instance(Generator *g, ObjectStoreItem *item, ObjectStore *db) {
367 Data *data = g->data;
368 int incount = g_list_length( data->lpdat->inevent );
369 int outcount = g_list_length( data->lpdat->outevent );
370 int i;
372 //objectstore_item_set_integer(item, "TEMPLATE_dummy", data->dummy);
373 ObjectStoreDatum *inarray = objectstore_datum_new_array( incount );
374 ObjectStoreDatum *outarray = objectstore_datum_new_array( outcount );
375 objectstore_item_set(item, "ladspa_inarray", inarray);
376 objectstore_item_set(item, "ladspa_oldoutarray", outarray);
378 for( i=0; i<incount; i++ )
379 objectstore_datum_array_set(inarray, i, objectstore_datum_new_double( data->inevents[i] ) );
380 for( i=0; i<outcount; i++ )
381 objectstore_datum_array_set(outarray, i, objectstore_datum_new_double( data->oldoutevents[i] ) );
384 #endif
387 PRIVATE gboolean output_generator0(Generator *g, SAMPLE *buf, int buflen) {
388 Data *data = g->data;
389 int i;
391 if( data->lastrun != gen_get_sampletime() )
392 run_plugin( g, buflen );
394 for( i=0; i<buflen; i++ )
395 buf[i] = data->outsignals[0][i];
397 return TRUE;
399 PRIVATE gboolean output_generator1(Generator *g, SAMPLE *buf, int buflen) {
400 Data *data = g->data;
401 int i;
403 if( data->lastrun != gen_get_sampletime() )
404 run_plugin( g, buflen );
406 for( i=0; i<buflen; i++ )
407 buf[i] = data->outsignals[1][i];
409 return TRUE;
411 PRIVATE gboolean output_generator2(Generator *g, SAMPLE *buf, int buflen) {
412 Data *data = g->data;
413 int i;
415 if( data->lastrun != gen_get_sampletime() )
416 run_plugin( g, buflen );
418 for( i=0; i<buflen; i++ )
419 buf[i] = data->outsignals[2][i];
421 return TRUE;
423 PRIVATE gboolean output_generator3(Generator *g, SAMPLE *buf, int buflen) {
424 Data *data = g->data;
425 int i;
427 if( data->lastrun != gen_get_sampletime() )
428 run_plugin( g, buflen );
430 for( i=0; i<buflen; i++ )
431 buf[i] = data->outsignals[3][i];
433 return TRUE;
435 PRIVATE gboolean output_generator4(Generator *g, SAMPLE *buf, int buflen) {
436 Data *data = g->data;
437 int i;
439 if( data->lastrun != gen_get_sampletime() )
440 run_plugin( g, buflen );
442 for( i=0; i<buflen; i++ )
443 buf[i] = data->outsignals[4][i];
445 return TRUE;
447 PRIVATE gboolean output_generator5(Generator *g, SAMPLE *buf, int buflen) {
448 Data *data = g->data;
449 int i;
451 if( data->lastrun != gen_get_sampletime() )
452 run_plugin( g, buflen );
454 for( i=0; i<buflen; i++ )
455 buf[i] = data->outsignals[5][i];
457 return TRUE;
459 PRIVATE gboolean output_generator6(Generator *g, SAMPLE *buf, int buflen) {
460 Data *data = g->data;
461 int i;
463 if( data->lastrun != gen_get_sampletime() )
464 run_plugin( g, buflen );
466 for( i=0; i<buflen; i++ )
467 buf[i] = data->outsignals[6][i];
469 return TRUE;
471 PRIVATE gboolean output_generator7(Generator *g, SAMPLE *buf, int buflen) {
472 Data *data = g->data;
473 int i;
475 if( data->lastrun != gen_get_sampletime() )
476 run_plugin( g, buflen );
478 for( i=0; i<buflen; i++ )
479 buf[i] = data->outsignals[7][i];
481 return TRUE;
484 PRIVATE void evt_input_handler(Generator *g, AEvent *event) {
485 /* handle incoming events on queue EVT_INPUT */
486 Data *data = g->data;
487 data->inevents[event->dst_q] = event->d.number;
489 data->aeff->setParameter( data->aeff, event->dst_q, event->d.number );
491 gen_update_controls( g, event->dst_q );
498 /*****************************************************************************/
500 PRIVATE AGenerator_t output_generators[] = { output_generator0, output_generator1, output_generator2, output_generator3,
501 output_generator4, output_generator5, output_generator6, output_generator7 };
502 PRIVATE int plugin_count=0;
504 PUBLIC void control_VST_Data_updater(Control *c) {
505 Data *data=c->g->data;
507 control_set_value(c, (data->inevents[(int) c->desc->refresh_data]));
510 PRIVATE void setup_one_class( char *dllname ) {
512 unsigned long i;
513 //LPluginData *plugindata = safe_malloc( sizeof( LPluginData ) );
514 void *dll_handle;
515 AEMainFunc main_func;
516 AEffect *tmp_effect;
517 InputSignalDescriptor *inputdescr;
518 OutputSignalDescriptor *outputdescr;
519 ControlDescriptor *controls;
520 char *generatorpath;
522 GeneratorClass *k;
524 char *basename = g_path_get_basename( dllname );
525 basename[strlen(basename)-4] = 0;
527 dll_handle = WineLoadLibrary( dllname );
528 main_func = WineGetProcAddress( dll_handle, "main" );
531 tmp_effect = main_func( &master_callback );
536 // for( i=0; i<psDescriptor->PortCount; i++ ) {
538 // LADSPA_PortDescriptor PortDescriptor=psDescriptor->PortDescriptors[i];
540 // if( LADSPA_IS_PORT_INPUT( PortDescriptor ) )
542 // if( LADSPA_IS_PORT_CONTROL(PortDescriptor) )
543 // plugindata->inevent = g_list_append( plugindata->inevent, (gpointer) i );
544 // else
545 // plugindata->insig = g_list_append( plugindata->insig, (gpointer) i );
547 // else
549 // if( LADSPA_IS_PORT_CONTROL( PortDescriptor ) )
550 // plugindata->outevent = g_list_append( plugindata->outevent, (gpointer) i );
551 // else
552 // plugindata->outsig = g_list_append( plugindata->outsig, (gpointer) i );
553 // }
555 // Add 1 for NULL termination
556 inputdescr = safe_malloc( sizeof( InputSignalDescriptor ) * (tmp_effect->numInputs + 1) );
557 outputdescr= safe_malloc( sizeof( OutputSignalDescriptor ) * (tmp_effect->numOutputs + 1) );
558 controls = safe_malloc( sizeof( ControlDescriptor ) * (tmp_effect->numParams + 1) );
562 //printf( "Input Signals:\n" );
563 for( i=0; i<tmp_effect->numInputs; i++ )
565 inputdescr[i].name = g_strdup_printf( "input_%d", (int)i );
566 inputdescr[i].flags = SIG_FLAG_REALTIME;
568 inputdescr[i].name = NULL;
570 //printf( "Output Signals:\n" );
571 for( i=0; i<tmp_effect->numOutputs; i++ )
573 outputdescr[i].name = g_strdup_printf( "output_%d", (int)i );
574 outputdescr[i].flags = SIG_FLAG_REALTIME;
575 outputdescr[i].d.realtime = output_generators[i];
577 outputdescr[i].name = NULL;
579 for( i=0; i<tmp_effect->numParams; i++ )
581 controls[i].kind = CONTROL_KIND_KNOB;
583 controls[i].name = safe_malloc( 30 );
585 tmp_effect->dispatcher( tmp_effect, effGetParamName, i, 0, controls[i].name, 0 );
587 controls[i].min = 0.0;
589 controls[i].max = 1.0;
591 controls[i].step = 0.01;
592 controls[i].page = 0.01;
594 controls[i].size = 0;
595 controls[i].allow_direct_edit = TRUE;
596 controls[i].is_dst_gen = TRUE;
597 controls[i].queue_number = i;
600 controls[i].initialize = NULL;
601 controls[i].destroy = NULL;
602 controls[i].refresh = control_VST_Data_updater;
603 controls[i].refresh_data = (void *)i;
606 controls[i].kind = CONTROL_KIND_NONE;
608 //printf( "Menu : %s\n", get_lrdf_menuname( psDescriptor->UniqueID ) );
609 k = gen_new_generatorclass_with_different_tag( basename,
610 g_strdup_printf( "vst-%d", (int) tmp_effect->uniqueID ), FALSE,
611 tmp_effect->numParams, 0,
612 inputdescr, outputdescr, controls,
613 init_instance, destroy_instance,
614 init_instance, NULL);
616 for( i=0; i<tmp_effect->numParams; i++ ) {
618 gen_configure_event_input(k, i, controls[i].name, evt_input_handler);
621 //printf( "Output Events:\n" );
624 //printf( "inserting: %s %x\n", psDescriptor->Label, psDescriptor );
625 //XXX: Is it necessary to add both tags ? Should be handled by the generator resolution.
627 g_hash_table_insert(MainFuncIndex, k->tag, main_func);
630 generatorpath = g_strdup_printf( "VST%2d/%s", (plugin_count++) / 20, basename );
634 gencomp_register_generatorclass(k, FALSE, generatorpath,
635 PIXMAPDIRIFY(GENERATOR_CLASS_PIXMAP),
636 NULL);
638 free( generatorpath );
640 //printf("Plugin Name: \"%s\"\n", psDescriptor->Name);
641 //printf("Plugin Label: \"%s\"\n", psDescriptor->Label);
642 //printf("Plugin Unique ID: %lu\n", psDescriptor->UniqueID);
643 //printf("Maker: \"%s\"\n", psDescriptor->Maker);
644 //printf("Copyright: \"%s\"\n", psDescriptor->Copyright);
651 PRIVATE void setup_all( void ) {
653 //setup_one_class( "Z:/home/torbenh/xxx/vst/cesSynth1.dll" );
655 char *vst_path = getenv( "GALAN_VST_DIR" );
657 if( vst_path ) {
658 GDir *dir = g_dir_open( vst_path, 0, NULL );
659 const char *filename;
661 while( filename = g_dir_read_name( dir ) ) {
662 char *winname;
663 if( strcmp(filename+(strlen(filename)-4), ".dll" ) )
664 continue;
666 winname = g_strdup_printf( "Z:%s/%s", vst_path,filename );
668 printf( "loading plugin %s\n", winname );
669 setup_one_class( winname );
670 g_free( winname );
674 g_dir_close( dir );
675 } else {
676 g_print( "GALAN_VST_DIR is no set !!!\n" );
681 PRIVATE void setup_globals( void ) {
683 SharedWineInit();
684 MainFuncIndex = g_hash_table_new(g_str_hash, g_str_equal);
688 PUBLIC void init_plugin(void) {
689 setup_globals();
690 setup_all();
693 /*****************************************************************************/
695 /* EOF */