switch to using jack_set_thread_creator() and dont mess with winaudio thread
[fst.git] / jfst.c
blob936f28ec51ea51c0eab7befdd65c824b07e12fb7
1 /*
2 Copyright (C) 2004 Paul Davis <paul@linuxaudiosystems.com>
3 Torben Hohn <torbenh@informatik.uni-bremen.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <sys/types.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <fst.h>
24 #include <glib.h>
25 #include <semaphore.h>
26 #include <vestige/aeffectx.h>
28 #include "jackvst.h"
29 #include "jack/midiport.h"
31 #ifdef HAVE_LASH
32 #include <lash/lash.h>
33 #endif
34 #include <windows.h>
36 /* audiomaster.c */
38 extern long jack_host_callback (struct AEffect*, long, long, long, void*, float);
40 /* gtk.c */
42 extern void gui_init (int* argc, char** argv[]);
43 extern int manage_vst_plugin (JackVST*);
45 /* Prototype for plugin "canDo" helper function*/
46 int canDo(struct AEffect* plugin, char* feature);
48 /* Structures & Prototypes for midi output and associated queue */
49 typedef struct _MidiMessage MidiMessage;
51 struct _MidiMessage {
52 jack_nframes_t time;
53 int len; /* Length of MIDI message, in bytes. */
54 unsigned char data[3];
56 #define RINGBUFFER_SIZE 1024*sizeof(MidiMessage)
57 void process_midi_output(JackVST* jvst, jack_nframes_t nframes);
58 void queue_midi_message(JackVST* jvst, int status, int d1, int d2, jack_nframes_t delta);
61 #ifdef HAVE_LASH
62 lash_client_t * lash_client;
63 #endif
66 static void *(*the_function)(void*);
67 static void *the_arg;
68 static pthread_t the_thread_id;
69 static sem_t sema;
71 static DWORD WINAPI wine_thread_aux( LPVOID arg )
73 the_thread_id = pthread_self();
74 sem_post( &sema );
75 the_function( the_arg );
76 return 0;
79 int wine_pthread_create (pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg)
81 sem_init( &sema, 0, 0 );
82 the_function = function;
83 the_arg = arg;
85 CreateThread( NULL, 0, wine_thread_aux, arg, 0,0 );
86 sem_wait( &sema );
88 *thread_id = the_thread_id;
89 return 0;
92 static pthread_t audio_thread = 0;
94 void process_midi_output(JackVST* jvst, jack_nframes_t nframes)
96 /* This jack ringbuffer consume code was largely taken from jack-keyboard */
97 /* written by Edward Tomasz Napierala <trasz@FreeBSD.org> */
98 int read, t;
99 unsigned char *buffer;
100 void *port_buffer;
101 jack_nframes_t last_frame_time;
102 jack_ringbuffer_t* ringbuffer;
103 MidiMessage ev;
105 last_frame_time = jack_last_frame_time(jvst->client);
107 port_buffer = jack_port_get_buffer(jvst->midi_outport, nframes);
108 if (port_buffer == NULL) {
109 fst_error("jack_port_get_buffer failed, cannot send anything.");
110 return;
113 ringbuffer = jvst->ringbuffer;
114 while (jack_ringbuffer_read_space(ringbuffer)) {
115 read = jack_ringbuffer_peek(ringbuffer, (char*)&ev, sizeof(ev));
116 if (read != sizeof(ev)) {
117 fst_error("Short read from the ringbuffer, possible note loss.");
118 jack_ringbuffer_read_advance(ringbuffer, read);
119 continue;
122 t = ev.time + nframes - last_frame_time;
124 /* If computed time is too much into the future, we'll send it later. */
125 if (t >= (int)nframes) break;
127 /* If computed time is < 0, we missed a cycle because of xrun. */
128 if (t < 0) t = 0;
130 jack_ringbuffer_read_advance(ringbuffer, sizeof(ev));
132 buffer = jack_midi_event_reserve(port_buffer, t, ev.len);
133 if (buffer == NULL) {
134 fst_error("queue: jack_midi_event_reserve failed, NOTE LOST.");
135 break;
138 memcpy(buffer, ev.data, ev.len);
142 void queue_midi_message(JackVST* jvst, int status, int d1, int d2, jack_nframes_t delta )
144 jack_ringbuffer_t* ringbuffer;
145 int written;
146 int statusHi = (status >> 4) & 0xF;
147 int statusLo = status & 0xF;
148 MidiMessage ev;
150 /*fst_error("queue_new_message = 0x%hhX, %d, %d\n", status, d1, d2);*/
151 /* fst_error("statusHi = %d, statusLo = %d\n", statusHi, statusLo);*/
153 ev.data[0] = status;
154 if (statusHi == 0xC || statusHi == 0xD) {
155 ev.len = 2;
156 ev.data[1] = d1;
157 } else if (statusHi == 0xF) {
158 if (statusLo == 0 || statusLo == 2) {
159 ev.len = 3;
160 ev.data[1] = d1;
161 ev.data[2] = d2;
162 } else if (statusLo == 1 || statusLo == 3) {
163 ev.len = 2;
164 ev.data[1] = d1;
165 } else ev.len = 1;
166 } else {
167 ev.len = 3;
168 ev.data[1] = d1;
169 ev.data[2] = d2;
172 if( pthread_self() == audio_thread ) {
173 unsigned char *buffer;
174 void *port_buffer;
175 port_buffer = jack_port_get_buffer(jvst->midi_outport, jack_get_buffer_size( jvst->client ) );
176 if (port_buffer == NULL) {
177 fst_error("jack_port_get_buffer failed, cannot send anything.");
178 return;
181 buffer = jack_midi_event_reserve(port_buffer, delta, ev.len);
182 if (buffer == NULL) {
183 fst_error("jack_midi_event_reserve failed, NOTE LOST.");
184 return;
186 memcpy(buffer, ev.data, ev.len);
188 return;
191 ev.time = jack_frame_time(jvst->client) + delta;
193 ringbuffer = jvst->ringbuffer;
194 if (jack_ringbuffer_write_space(ringbuffer) < sizeof(ev)) {
195 fst_error("Not enough space in the ringbuffer, NOTE LOST.");
196 return;
199 written = jack_ringbuffer_write(ringbuffer, (char*)&ev, sizeof(ev));
200 if (written != sizeof(ev)) {
201 fst_error("jack_ringbuffer_write failed, NOTE LOST.");
205 int process_callback( jack_nframes_t nframes, void* data)
207 int i, o;
208 JackVST* jvst = (JackVST*) data;
209 struct AEffect* plugin = jvst->fst->plugin;
211 audio_thread = pthread_self();
213 if( !jvst->resume_called ) {
214 jvst->resume_called = TRUE;
215 plugin->dispatcher (plugin, effMainsChanged, 0, 1, NULL, 0.0f);
217 for (i = 0; i < plugin->numInputs; ++i) {
218 jvst->ins[i] = (float *) jack_port_get_buffer (jvst->inports[i], nframes);
221 for (i = 0; i < plugin->numOutputs; ++i) {
222 jvst->outs[i] = (float *) jack_port_get_buffer (jvst->outports[i], nframes);
225 if (jvst->bypassed) {
227 if (plugin->numInputs) {
228 for (o = 0, i = 0; o < plugin->numOutputs; ++o) {
229 memcpy (jvst->outs[o], jvst->ins[i], sizeof (float) * nframes);
231 if (i < plugin->numOutputs - 1) {
232 ++i;
235 } else {
236 for (o = 0, i = 0; o < plugin->numOutputs; ++o) {
237 if (jvst->outs[o]) {
238 memset (jvst->outs[o], 0, sizeof (float) * nframes);
243 } else if (jvst->muted) {
245 for (o = 0, i = 0; o < plugin->numOutputs; ++o) {
246 if (jvst->outs[o]) {
247 memset (jvst->outs[o], 0, sizeof (float) * nframes);
251 } else {
253 if (jvst->midi_outport) {
254 void *port_buffer = jack_port_get_buffer(jvst->midi_outport, nframes);
255 if (port_buffer == NULL) {
256 fst_error("jack_port_get_buffer failed, cannot send anything.");
257 return;
259 jack_midi_clear_buffer(port_buffer);
262 if (jvst->midi_inport) {
263 void *port_buffer = jack_port_get_buffer( jvst->midi_inport, nframes );
264 jack_nframes_t num_jackevents = jack_midi_get_event_count( port_buffer );
265 jack_midi_event_t jackevent;
266 int j,stuffed_events = 0;
268 if( num_jackevents >= MIDI_EVENT_MAX )
269 num_jackevents = MIDI_EVENT_MAX;
271 for( i=0; i<num_jackevents; i++ ) {
272 if( jack_midi_event_get( &jackevent, port_buffer, i ) != 0 )
273 break;
275 if( (jackevent.buffer[0] & 0xf0) == 0xb0 && jvst->midi_learn ) {
276 jvst->midi_learn_CC = jackevent.buffer[1];
277 } else if( (jackevent.buffer[0] & 0xf0) == 0xb0 && jvst->midi_map[jackevent.buffer[1]] != -1 ) {
278 // midi mapped.
279 int parameter = jvst->midi_map[jackevent.buffer[1]];
280 float value = 1.0/127.0 * (float) jackevent.buffer[2];
281 plugin->setParameter( plugin, parameter, value );
283 } else if( jvst->want_midi_in ) {
284 jvst->event_array[stuffed_events].type = kVstMidiType;
285 jvst->event_array[stuffed_events].byteSize = 24;
286 jvst->event_array[stuffed_events].deltaFrames = jackevent.time;
288 for( j=0; (j<4); j++ ) {
289 jvst->event_array[stuffed_events].midiData[j] =
290 (j<jackevent.size) ? jackevent.buffer[j] : 0;
292 stuffed_events += 1;
296 if( stuffed_events > 0 ) {
297 jvst->events->numEvents = stuffed_events;
298 plugin->dispatcher (plugin, effProcessEvents, 0, 0, jvst->events, 0.0f);
302 jvst->current_program = plugin->dispatcher( plugin, effGetProgram, 0, 0, NULL, 0.0f );
304 if (plugin->flags & effFlagsCanReplacing) {
306 for (i = 0; i < plugin->numOutputs; ++i) {
307 memset (jvst->outs[i], 0, sizeof (float) * nframes);
309 plugin->processReplacing (plugin, jvst->ins, jvst->outs, nframes);
311 } else {
313 for (i = 0; i < plugin->numOutputs; ++i) {
314 memset (jvst->outs[i], 0, sizeof (float) * nframes);
316 plugin->process (plugin, jvst->ins, jvst->outs, nframes);
318 if (jvst->midi_outport) {
319 process_midi_output(jvst, nframes);
323 return 0;
326 enum ParseMode {
327 MODE_NORMAL,
328 MODE_QUOTE,
329 MODE_DOUBLEQUOTE,
330 MODE_ESCAPED,
331 MODE_WHITESPACE,
332 MODE_EOL
335 void create_argc_argv_from_cmdline( char *cmdline, char *argv0, int *argc, char ***argv ) {
336 // first count argc
337 char *pos = cmdline;
338 enum ParseMode parseMode = MODE_WHITESPACE;
339 enum ParseMode parseMode_before_ESC = MODE_NORMAL;
340 int i;
342 int myargc = 1;
343 char **myargv;
345 while( parseMode != MODE_EOL ) {
346 switch( parseMode ) {
347 case MODE_NORMAL:
348 switch( *pos ) {
349 case '\"':
350 parseMode = MODE_DOUBLEQUOTE;
351 break;
352 case '\'':
353 parseMode = MODE_QUOTE;
354 break;
355 case '\\':
356 parseMode_before_ESC = parseMode;
357 parseMode = MODE_ESCAPED;
358 break;
359 case ' ': // First Space after an arg;
360 parseMode = MODE_WHITESPACE;
361 myargc++;
362 break;
363 case 0: // EOL after arg.
364 parseMode = MODE_EOL;
365 break;
366 default:
367 // Normal char;
368 break;
370 break;
371 case MODE_QUOTE:
372 switch( *pos ) {
373 case '\'':
374 parseMode = MODE_NORMAL;
375 break;
376 case '\\':
377 parseMode_before_ESC = parseMode;
378 parseMode = MODE_ESCAPED;
379 break;
380 case 0:
381 fst_error( "parse Error on cmdline" );
382 parseMode = MODE_EOL;
383 break;
384 default:
385 // Normal char;
386 break;
388 break;
389 case MODE_DOUBLEQUOTE:
390 switch( *pos ) {
391 case '\"':
392 parseMode = MODE_NORMAL;
393 break;
394 case '\\':
395 parseMode_before_ESC = parseMode;
396 parseMode = MODE_ESCAPED;
397 break;
398 case 0:
399 fst_error( "parse Error on cmdline" );
400 parseMode = MODE_EOL;
401 break;
402 default:
403 // Normal char;
404 break;
406 break;
407 case MODE_ESCAPED:
408 switch( *pos ) {
409 case '\"':
410 // emit escaped char;
411 parseMode = parseMode_before_ESC;
412 break;
413 case '\'':
414 // emit escaped char;
415 parseMode = parseMode_before_ESC;
416 break;
417 case '\\':
418 // emit escaped char;
419 parseMode = parseMode_before_ESC;
420 break;
421 case 0:
422 fst_error( "EOL after escape: ignored" );
423 parseMode = MODE_EOL;
424 break;
425 default:
426 fst_error( "Unknown Escapecharacter: ignored" );
427 parseMode = parseMode_before_ESC;
428 // Normal char;
429 break;
431 break;
432 case MODE_WHITESPACE:
433 switch( *pos ) {
434 case '\"':
435 parseMode = MODE_DOUBLEQUOTE;
436 myargc++;
437 break;
438 case '\'':
439 parseMode = MODE_QUOTE;
440 myargc++;
441 break;
442 case '\\':
443 parseMode_before_ESC = MODE_NORMAL;
444 parseMode = MODE_ESCAPED;
445 myargc++;
446 break;
447 case ' ':
448 parseMode = MODE_WHITESPACE;
449 break;
450 case 0:
451 parseMode = MODE_EOL;
452 break;
453 default:
455 parseMode = MODE_NORMAL;
456 // Normal char;
457 myargc++;
458 break;
460 break;
462 pos++;
465 myargv = malloc( myargc * sizeof( char * ) );
466 if( !myargv ) {
467 fst_error( "cant alloc memory" );
468 exit( 10 );
471 // alloc strlen(cmdline) + 1 for each argv.
472 // this avoids another parsing pass.
473 for( i=0; i<myargc; i++ ) {
474 myargv[i] = malloc( strlen(cmdline) + 1 );
475 if( !myargv[i] ) {
476 fst_error( "cant alloc memory" );
477 exit( 10 );
479 myargv[i][0] = 0;
482 // Now rerun theparser and actually emit chars.
483 pos = cmdline;
484 parseMode = MODE_WHITESPACE;
485 parseMode_before_ESC = MODE_NORMAL;
486 int current_arg = 0;
487 char *emit_pos = myargv[0];
489 while( parseMode != MODE_EOL ) {
490 switch( parseMode ) {
491 case MODE_NORMAL:
492 switch( *pos ) {
493 case '\"':
494 parseMode = MODE_DOUBLEQUOTE;
495 break;
496 case '\'':
497 parseMode = MODE_QUOTE;
498 break;
499 case '\\':
500 parseMode_before_ESC = parseMode;
501 parseMode = MODE_ESCAPED;
502 break;
503 case ' ': // First Space after an arg;
504 parseMode = MODE_WHITESPACE;
505 *emit_pos = 0;
507 break;
508 case 0: // EOL after arg.
509 parseMode = MODE_EOL;
510 *emit_pos = 0;
511 break;
512 default:
514 *(emit_pos++) = *pos;
515 break;
517 break;
518 case MODE_QUOTE:
519 switch( *pos ) {
520 case '\'':
521 parseMode = MODE_NORMAL;
522 break;
523 case '\\':
524 parseMode_before_ESC = parseMode;
525 parseMode = MODE_ESCAPED;
526 break;
527 case 0:
528 fst_error( "parse Error on cmdline" );
529 parseMode = MODE_EOL;
530 *emit_pos = 0;
531 break;
532 default:
533 // Normal char;
534 *(emit_pos++) = *pos;
535 break;
537 break;
538 case MODE_DOUBLEQUOTE:
539 switch( *pos ) {
540 case '"':
541 parseMode = MODE_NORMAL;
542 break;
543 case '\\':
544 parseMode_before_ESC = parseMode;
545 parseMode = MODE_ESCAPED;
546 break;
547 case 0:
548 fst_error( "parse Error on cmdline" );
549 parseMode = MODE_EOL;
550 *emit_pos = 0;
551 break;
552 default:
553 // Normal char;
554 *(emit_pos++) = *pos;
555 break;
557 break;
558 case MODE_ESCAPED:
559 switch( *pos ) {
560 case '\"':
561 // emit escaped char;
562 parseMode = parseMode_before_ESC;
563 *(emit_pos++) = *pos;
564 break;
565 case '\'':
566 // emit escaped char;
567 parseMode = parseMode_before_ESC;
568 *(emit_pos++) = *pos;
569 break;
570 case '\\':
571 // emit escaped char;
572 parseMode = parseMode_before_ESC;
573 *(emit_pos++) = *pos;
574 break;
575 case 0:
576 fst_error( "EOL after escape: ignored" );
577 parseMode = MODE_EOL;
578 *emit_pos = 0;
579 break;
580 default:
581 fst_error( "Unknown Escapecharacter: ignored" );
582 parseMode = parseMode_before_ESC;
583 break;
585 break;
586 case MODE_WHITESPACE:
587 switch( *pos ) {
588 case '\"':
589 parseMode = MODE_DOUBLEQUOTE;
590 // ok... arg begins
591 current_arg++;
592 emit_pos = myargv[current_arg];
593 break;
594 case '\'':
595 parseMode = MODE_QUOTE;
596 // ok... arg begins
597 current_arg++;
598 emit_pos = myargv[current_arg];
599 break;
600 case '\\':
601 parseMode_before_ESC = MODE_NORMAL;
602 parseMode = MODE_ESCAPED;
603 // ok... arg begins
604 current_arg++;
605 emit_pos = myargv[current_arg];
606 break;
607 case ' ':
608 parseMode = MODE_WHITESPACE;
609 break;
610 case 0:
611 parseMode = MODE_EOL;
612 break;
613 default:
614 parseMode = MODE_NORMAL;
615 // ok... arg begins
616 current_arg++;
617 emit_pos = myargv[current_arg];
618 // Normal char;
619 *(emit_pos++) = *pos;
620 break;
622 break;
624 pos++;
627 strncpy( myargv[0], argv0, strlen(cmdline) );
629 *argc = myargc;
630 *argv = myargv;
633 /* Plugin "canDo" helper function to neaten up plugin feature detection calls */
634 int canDo(struct AEffect* plugin, char* feature)
636 return (plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)feature, 0.0f) > 0);
639 int WINAPI
640 WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow)
641 //int
642 //main( int argc, char **argv )
644 JackVST* jvst;
645 struct AEffect* plugin;
646 int i;
647 char* client_name = 0;
648 char* period;
649 int with_editor = 1;
650 int resume_not_rt = 1;
651 int load_state = 0;
652 char * state_file = 0;
653 char *plug;
654 int vst_version;
656 float sample_rate = 0;
657 long block_size = 0;
659 int argc;
660 char **argv;
662 create_argc_argv_from_cmdline( cmdline, "./fst", &argc, &argv );
664 #ifdef HAVE_LASH
666 lash_event_t *event;
667 lash_args_t *lash_args;
669 lash_args = lash_extract_args(&argc, &argv);
670 #endif
672 if (argc < 2) {
673 fprintf (stderr, "usage: %s <plugin>\n", argv[0]);
674 return 1;
677 printf( "yo... lets see...\n" );
678 //setpgrp();
680 gui_init (&argc, &argv);
682 for (i = 1; i < argc; ++i) {
683 if (argv[i][0] == '-') {
684 if (argv[i][1] == 'n') {
685 with_editor = 0;
687 if (argv[i][1] == 'r') {
688 resume_not_rt = 0;
690 if (argv[i][1] == 's') {
691 load_state = 1;
692 state_file = argv[i+1];
693 i++;
694 if (i + 2 >= argc) {
695 fprintf (stderr, "usage: %s <plugin>\n", argv[0]);
696 return 1;
699 if (argv[i][1] == 'c') {
700 client_name = argv[i+1];
701 i++;
702 if (i + 2 >= argc) {
703 fprintf (stderr, "usage: %s <plugin>\n", argv[0]);
704 return 1;
707 } else {
708 plug = argv[i];
709 break;
713 if (fst_init (hInst)) {
714 return 1;
717 jvst = (JackVST*) calloc (1, sizeof (JackVST));
718 for (i=0; i<128; i++ )
719 jvst->midi_map[i] = -1;
721 if (!client_name) {
722 client_name = g_path_get_basename(strdup (plug));
723 if ((period = strrchr (client_name, '.')) != NULL) {
724 *period = '\0';
729 if ((jvst->handle = fst_load (plug)) == NULL) {
730 fst_error ("can't load plugin %s", plug);
731 return 1;
733 if ((jvst->client = jack_client_open (client_name, JackNullOption, NULL )) == 0) {
734 fst_error ("can't connect to JACK");
735 return 1;
738 printf( "instantiate... \n" );
740 if ((jvst->fst = fst_instantiate (jvst->handle, jack_host_callback, jvst)) == NULL) {
741 fst_error ("can't instantiate plugin %s", plug);
742 return 1;
745 plugin = jvst->fst->plugin;
747 /* set rate and blocksize */
748 sample_rate = (float)jack_get_sample_rate(jvst->client);
749 block_size = jack_get_buffer_size(jvst->client);
751 printf("Sample Rate = %.2f\n", sample_rate);
752 printf("Block Size = %ld\n", block_size);
754 plugin->dispatcher (plugin, effSetSampleRate, 0, 0, NULL,
755 (float) jack_get_sample_rate (jvst->client));
756 plugin->dispatcher (plugin, effSetBlockSize, 0,
757 jack_get_buffer_size (jvst->client), NULL, 0.0f);
759 if( resume_not_rt ) {
760 jvst->resume_called = TRUE;
761 plugin->dispatcher (plugin, effMainsChanged, 0, 1, NULL, 0.0f);
764 // ok.... plugin is running... lets bind to lash...
766 #ifdef HAVE_LASH
767 int flags = LASH_Config_Data_Set;
769 lash_client =
770 lash_init(lash_args, client_name, flags, LASH_PROTOCOL(2, 0));
772 if (!lash_client) {
773 fprintf(stderr, "%s: could not initialise lash\n", __FUNCTION__);
774 fprintf(stderr, "%s: running fst without lash session-support\n", __FUNCTION__);
775 fprintf(stderr, "%s: to enable lash session-support launch the lash server prior fst\n", __FUNCTION__);
778 if (lash_enabled(lash_client)) {
779 event = lash_event_new_with_type(LASH_Client_Name);
780 lash_event_set_string(event, client_name);
781 lash_send_event(lash_client, event);
783 #endif
786 /* set program to zero */
787 /* i comment this out because it breaks dfx Geometer
788 * looks like we cant set programs for it
790 * TODO:
791 * this might have been because we were not a real wine thread, but i doubt
792 * it. need to check.
794 * plugin->dispatcher (plugin, effSetProgram, 0, 0, NULL, 0.0f);
798 jvst->midi_inport = jack_port_register(jvst->client,
799 "midi-in",
800 JACK_DEFAULT_MIDI_TYPE,
801 JackPortIsInput,
804 vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
805 if (vst_version >= 2) {
806 int isSynth = (plugin->flags & effFlagsIsSynth) > 0;
807 int canReceiveVstEvents = canDo(plugin, "receiveVstEvents");
808 int canReceiveVstMidiEvent = canDo(plugin, "receiveVstMidiEvent");
809 int canSendVstEvents = canDo(plugin, "sendVstEvents");
810 int canSendVstMidiEvent = canDo(plugin, "sendVstMidiEvent");
812 printf("Plugin isSynth = %d\n", isSynth);
813 printf("Plugin canDo receiveVstEvents = %d\n", canReceiveVstEvents);
814 printf("Plugin canDo receiveVstMidiEvent = %d\n", canReceiveVstMidiEvent);
815 printf("Plugin canDo sendVstEvents = %d\n", canSendVstEvents);
816 printf("Plugin canDo SendVstMidiEvent = %d\n", canSendVstMidiEvent);
818 /* should we send the plugin VST events (i.e. MIDI) */
819 if (isSynth || canReceiveVstEvents || canReceiveVstMidiEvent) {
820 int i;
821 jvst->want_midi_in = 1;
823 /* The VstEvents structure already contains an array of 2 */
824 /* pointers to VstEvent so I guess that this malloc actually */
825 /* gives enough space for MIDI_EVENT_MAX + 2 events.... */
826 jvst->events = (VstEvents*)malloc(sizeof(VstEvents) +
827 (MIDI_EVENT_MAX * sizeof(VstMidiEvent*)));
829 jvst->events->numEvents = 0;
830 jvst->events->reserved = 0;
832 /* Initialise dynamic array of MIDI_EVENT_MAX VstMidiEvents */
833 /* and point the VstEvents events array of pointers to it */
834 jvst->event_array = (VstMidiEvent*)calloc(MIDI_EVENT_MAX,
835 sizeof (VstMidiEvent));
836 for (i = 0; i < MIDI_EVENT_MAX; i++) {
837 jvst->events->events[i] = (VstEvent*)&(jvst->event_array[i]);
841 /* Can the plugin send VST events (i.e. MIDI) */
842 if (canSendVstEvents || canSendVstMidiEvent) {
843 jvst->ringbuffer = jack_ringbuffer_create(RINGBUFFER_SIZE);
844 if (jvst->ringbuffer == NULL) {
845 fst_error("Cannot create JACK ringbuffer.");
846 return 1;
849 jack_ringbuffer_mlock(jvst->ringbuffer);
851 jvst->midi_outport = jack_port_register(jvst->client,
852 "midi-out",
853 JACK_DEFAULT_MIDI_TYPE,
854 JackPortIsOutput,
859 printf("PortLayout: in: %d out: %d\n", plugin->numInputs, plugin->numOutputs);
861 jvst->inports = (jack_port_t**)malloc(sizeof(jack_port_t*) * plugin->numInputs);
862 jvst->ins = (float**)malloc(sizeof(float*) * plugin->numInputs);
864 for (i = 0; i < plugin->numInputs; ++i) {
865 char buf[64];
866 snprintf (buf, sizeof(buf), "in%d", i+1);
867 jvst->inports[i] = jack_port_register (jvst->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
870 jvst->outports = (jack_port_t **) malloc (sizeof(jack_port_t*) * plugin->numOutputs);
871 jvst->outs = (float **) malloc (sizeof (float *) * plugin->numOutputs);
873 for (i = 0; i < plugin->numOutputs; ++i) {
874 char buf[64];
875 snprintf (buf, sizeof(buf), "out%d", i+1);
876 jvst->outports[i] = jack_port_register (jvst->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
879 jack_set_thread_creator (wine_pthread_create);
881 jack_set_process_callback (jvst->client, (JackProcessCallback) process_callback, jvst);
883 printf( "Calling Jack activate\n" );
884 jack_activate (jvst->client);
886 if (with_editor) {
887 printf( "open Editor\n" );
889 if (fst_run_editor (jvst->fst)) {
890 fst_error ("cannot create editor");
891 return 1;
893 } else {
894 printf( "no Editor\n" );
897 #ifdef HAVE_LASH
898 if( lash_enabled( lash_client ) ) {
899 event = lash_event_new_with_type(LASH_Jack_Client_Name);
900 lash_event_set_string(event, client_name);
901 lash_send_event(lash_client, event);
903 #endif
905 /* load state if requested */
907 if (load_state) {
908 if (!fst_load_state (jvst->fst, state_file)) {
909 printf ("ERROR: Could not load state file %s\n", state_file);
910 jack_deactivate( jvst->client );
911 return 1;
916 printf( "Entering main loop\n" );
917 if (with_editor) {
918 printf( "ok.... RockNRoll\n" );
919 manage_vst_plugin (jvst);
920 } else {
921 while( 1 )
922 sleep (10);
925 jack_deactivate( jvst->client );
926 return 0;