Remove prints, now that signals work properly
[klaudia.git] / fst / jfst.c
blob25aa8dc7b83555ec39ad5d82bbe0b0347fd76fe6
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 #include <windows.h>
33 /* audiomaster.c */
35 extern long jack_host_callback (struct AEffect*, long, long, long, void*, float);
37 /* gtk.c */
39 extern void gui_init (int* argc, char** argv[]);
40 extern int manage_vst_plugin (JackVST*);
42 /* Ladish support */
43 extern int ladish_save_now;
44 extern char* ladish_state_filename;
46 /* Prototype for plugin "canDo" helper function*/
47 int canDo(struct AEffect* plugin, char* feature);
49 /* Structures & Prototypes for midi output and associated queue */
50 typedef struct _MidiMessage MidiMessage;
52 struct _MidiMessage {
53 jack_nframes_t time;
54 int len; /* Length of MIDI message, in bytes. */
55 unsigned char data[3];
57 #define RINGBUFFER_SIZE 1024*sizeof(MidiMessage)
58 void process_midi_output(JackVST* jvst, jack_nframes_t nframes);
59 void queue_midi_message(JackVST* jvst, int status, int d1, int d2, jack_nframes_t delta);
62 // Until i get Jack to call me when he wants to create a thread,
63 // i need to go through this.
65 volatile int with_winaudio = 1;
67 static HANDLE audioThreadHandle = 0;
68 static jack_nframes_t winaudio_nframes;
69 static void *winaudio_data;
70 sem_t winaudio_activate, winaudio_done;
72 static pthread_t audio_thread = 0;
74 int winaudio_process_callback( jack_nframes_t nframes, void *data )
76 winaudio_nframes = nframes;
77 winaudio_data = data;
79 sem_post( &winaudio_activate );
80 sem_wait( &winaudio_done );
82 return 0;
85 DWORD WINAPI
86 WinAudioThreadMain(LPVOID parameter)
89 struct sched_param param;
90 param.sched_priority = 10;
91 pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
93 sem_post( &winaudio_done );
95 while( with_winaudio ) {
96 sem_wait( &winaudio_activate );
97 process_callback( winaudio_nframes, winaudio_data );
98 sem_post( &winaudio_done );
100 return 0;
103 void process_midi_output(JackVST* jvst, jack_nframes_t nframes)
105 /* This jack ringbuffer consume code was largely taken from jack-keyboard */
106 /* written by Edward Tomasz Napierala <trasz@FreeBSD.org> */
107 int read, t;
108 unsigned char *buffer;
109 void *port_buffer;
110 jack_nframes_t last_frame_time;
111 jack_ringbuffer_t* ringbuffer;
112 MidiMessage ev;
114 last_frame_time = jack_last_frame_time(jvst->client);
116 port_buffer = jack_port_get_buffer(jvst->midi_outport, nframes);
117 if (port_buffer == NULL) {
118 fst_error("jack_port_get_buffer failed, cannot send anything.");
119 return;
122 ringbuffer = jvst->ringbuffer;
123 while (jack_ringbuffer_read_space(ringbuffer)) {
124 read = jack_ringbuffer_peek(ringbuffer, (char*)&ev, sizeof(ev));
125 if (read != sizeof(ev)) {
126 fst_error("Short read from the ringbuffer, possible note loss.");
127 jack_ringbuffer_read_advance(ringbuffer, read);
128 continue;
131 t = ev.time + nframes - last_frame_time;
133 /* If computed time is too much into the future, we'll send it later. */
134 if (t >= (int)nframes) break;
136 /* If computed time is < 0, we missed a cycle because of xrun. */
137 if (t < 0) t = 0;
139 jack_ringbuffer_read_advance(ringbuffer, sizeof(ev));
141 buffer = jack_midi_event_reserve(port_buffer, t, ev.len);
142 if (buffer == NULL) {
143 fst_error("queue: jack_midi_event_reserve failed, NOTE LOST.");
144 break;
147 memcpy(buffer, ev.data, ev.len);
151 void queue_midi_message(JackVST* jvst, int status, int d1, int d2, jack_nframes_t delta )
153 jack_ringbuffer_t* ringbuffer;
154 int written;
155 int statusHi = (status >> 4) & 0xF;
156 int statusLo = status & 0xF;
157 MidiMessage ev;
159 /*fst_error("queue_new_message = 0x%hhX, %d, %d\n", status, d1, d2);*/
160 /* fst_error("statusHi = %d, statusLo = %d\n", statusHi, statusLo);*/
162 ev.data[0] = status;
163 if (statusHi == 0xC || statusHi == 0xD) {
164 ev.len = 2;
165 ev.data[1] = d1;
166 } else if (statusHi == 0xF) {
167 if (statusLo == 0 || statusLo == 2) {
168 ev.len = 3;
169 ev.data[1] = d1;
170 ev.data[2] = d2;
171 } else if (statusLo == 1 || statusLo == 3) {
172 ev.len = 2;
173 ev.data[1] = d1;
174 } else ev.len = 1;
175 } else {
176 ev.len = 3;
177 ev.data[1] = d1;
178 ev.data[2] = d2;
181 if( pthread_self() == audio_thread ) {
182 unsigned char *buffer;
183 void *port_buffer;
184 port_buffer = jack_port_get_buffer(jvst->midi_outport, jack_get_buffer_size( jvst->client ) );
185 if (port_buffer == NULL) {
186 fst_error("jack_port_get_buffer failed, cannot send anything.");
187 return;
190 buffer = jack_midi_event_reserve(port_buffer, delta, ev.len);
191 if (buffer == NULL) {
192 fst_error("jack_midi_event_reserve failed, NOTE LOST.");
193 return;
195 memcpy(buffer, ev.data, ev.len);
197 return;
200 ev.time = jack_frame_time(jvst->client) + delta;
202 ringbuffer = jvst->ringbuffer;
203 if (jack_ringbuffer_write_space(ringbuffer) < sizeof(ev)) {
204 fst_error("Not enough space in the ringbuffer, NOTE LOST.");
205 return;
208 written = jack_ringbuffer_write(ringbuffer, (char*)&ev, sizeof(ev));
209 if (written != sizeof(ev)) {
210 fst_error("jack_ringbuffer_write failed, NOTE LOST.");
214 int process_callback( jack_nframes_t nframes, void* data)
216 int i, o;
217 int current_program;
218 JackVST* jvst = (JackVST*) data;
219 struct AEffect* plugin = jvst->fst->plugin;
221 audio_thread = pthread_self();
223 if( !jvst->resume_called ) {
224 jvst->resume_called = TRUE;
225 plugin->dispatcher (plugin, effMainsChanged, 0, 1, NULL, 0.0f);
227 for (i = 0; i < plugin->numInputs; ++i) {
228 jvst->ins[i] = (float *) jack_port_get_buffer (jvst->inports[i], nframes);
231 for (i = 0; i < plugin->numOutputs; ++i) {
232 jvst->outs[i] = (float *) jack_port_get_buffer (jvst->outports[i], nframes);
235 if (jvst->bypassed) {
237 if (plugin->numInputs) {
238 for (o = 0, i = 0; o < plugin->numOutputs; ++o) {
239 memcpy (jvst->outs[o], jvst->ins[i], sizeof (float) * nframes);
241 if (i < plugin->numOutputs - 1) {
242 ++i;
245 } else {
246 for (o = 0, i = 0; o < plugin->numOutputs; ++o) {
247 if (jvst->outs[o]) {
248 memset (jvst->outs[o], 0, sizeof (float) * nframes);
253 } else if (jvst->muted) {
255 for (o = 0, i = 0; o < plugin->numOutputs; ++o) {
256 if (jvst->outs[o]) {
257 memset (jvst->outs[o], 0, sizeof (float) * nframes);
261 } else {
263 if (jvst->midi_outport) {
264 void *port_buffer = jack_port_get_buffer(jvst->midi_outport, nframes);
265 if (port_buffer == NULL) {
266 fst_error("jack_port_get_buffer failed, cannot send anything.");
267 return;
269 jack_midi_clear_buffer(port_buffer);
272 if (jvst->midi_inport) {
273 void *port_buffer = jack_port_get_buffer( jvst->midi_inport, nframes );
274 jack_nframes_t num_jackevents = jack_midi_get_event_count( port_buffer );
275 jack_midi_event_t jackevent;
276 int j,stuffed_events = 0;
278 if( num_jackevents >= MIDI_EVENT_MAX )
279 num_jackevents = MIDI_EVENT_MAX;
281 for( i=0; i<num_jackevents; i++ ) {
282 if( jack_midi_event_get( &jackevent, port_buffer, i ) != 0 )
283 break;
285 if( (jackevent.buffer[0] & 0xf0) == 0xb0 && jvst->midi_learn ) {
286 jvst->midi_learn_CC = jackevent.buffer[1];
287 } else if( (jackevent.buffer[0] & 0xf0) == 0xb0 && jvst->midi_map[jackevent.buffer[1]] != -1 ) {
288 // midi mapped.
289 int parameter = jvst->midi_map[jackevent.buffer[1]];
290 float value = 1.0/127.0 * (float) jackevent.buffer[2];
291 plugin->setParameter( plugin, parameter, value );
293 } else if( jvst->want_midi_in ) {
294 jvst->event_array[stuffed_events].type = kVstMidiType;
295 jvst->event_array[stuffed_events].byteSize = 24;
296 jvst->event_array[stuffed_events].deltaFrames = jackevent.time;
298 for( j=0; (j<4); j++ ) {
299 jvst->event_array[stuffed_events].midiData[j] =
300 (j<jackevent.size) ? jackevent.buffer[j] : 0;
302 stuffed_events += 1;
306 if( stuffed_events > 0 ) {
307 jvst->events->numEvents = stuffed_events;
308 plugin->dispatcher (plugin, effProcessEvents, 0, 0, jvst->events, 0.0f);
312 current_program = plugin->dispatcher( plugin, effGetProgram, 0, 0, NULL, 0.0f );
313 if( current_program >= 0 )
314 jvst->current_program = current_program;
316 if (plugin->flags & effFlagsCanReplacing) {
318 for (i = 0; i < plugin->numOutputs; ++i) {
319 memset (jvst->outs[i], 0, sizeof (float) * nframes);
321 plugin->processReplacing (plugin, jvst->ins, jvst->outs, nframes);
323 } else {
325 for (i = 0; i < plugin->numOutputs; ++i) {
326 memset (jvst->outs[i], 0, sizeof (float) * nframes);
328 plugin->process (plugin, jvst->ins, jvst->outs, nframes);
330 if (jvst->midi_outport) {
331 process_midi_output(jvst, nframes);
335 if (ladish_save_now)
337 printf("got ladish save here\n");
338 fst_save_state (jvst->fst, ladish_state_filename);
339 ladish_save_now = 0;
342 return 0;
345 enum ParseMode {
346 MODE_NORMAL,
347 MODE_QUOTE,
348 MODE_DOUBLEQUOTE,
349 MODE_ESCAPED,
350 MODE_WHITESPACE,
351 MODE_EOL
354 void create_argc_argv_from_cmdline( char *cmdline, char *argv0, int *argc, char ***argv ) {
355 // first count argc
356 char *pos = cmdline;
357 enum ParseMode parseMode = MODE_WHITESPACE;
358 enum ParseMode parseMode_before_ESC = MODE_NORMAL;
359 int i;
361 int myargc = 1;
362 char **myargv;
364 while( parseMode != MODE_EOL ) {
365 switch( parseMode ) {
366 case MODE_NORMAL:
367 switch( *pos ) {
368 case '\"':
369 parseMode = MODE_DOUBLEQUOTE;
370 break;
371 case '\'':
372 parseMode = MODE_QUOTE;
373 break;
374 case '\\':
375 parseMode_before_ESC = parseMode;
376 parseMode = MODE_ESCAPED;
377 break;
378 case ' ': // First Space after an arg;
379 parseMode = MODE_WHITESPACE;
380 myargc++;
381 break;
382 case 0: // EOL after arg.
383 parseMode = MODE_EOL;
384 break;
385 default:
386 // Normal char;
387 break;
389 break;
390 case MODE_QUOTE:
391 switch( *pos ) {
392 case '\'':
393 parseMode = MODE_NORMAL;
394 break;
395 case '\\':
396 parseMode_before_ESC = parseMode;
397 parseMode = MODE_ESCAPED;
398 break;
399 case 0:
400 fst_error( "parse Error on cmdline" );
401 parseMode = MODE_EOL;
402 break;
403 default:
404 // Normal char;
405 break;
407 break;
408 case MODE_DOUBLEQUOTE:
409 switch( *pos ) {
410 case '\"':
411 parseMode = MODE_NORMAL;
412 break;
413 case '\\':
414 parseMode_before_ESC = parseMode;
415 parseMode = MODE_ESCAPED;
416 break;
417 case 0:
418 fst_error( "parse Error on cmdline" );
419 parseMode = MODE_EOL;
420 break;
421 default:
422 // Normal char;
423 break;
425 break;
426 case MODE_ESCAPED:
427 switch( *pos ) {
428 case '\"':
429 // emit escaped char;
430 parseMode = parseMode_before_ESC;
431 break;
432 case '\'':
433 // emit escaped char;
434 parseMode = parseMode_before_ESC;
435 break;
436 case '\\':
437 // emit escaped char;
438 parseMode = parseMode_before_ESC;
439 break;
440 case 0:
441 fst_error( "EOL after escape: ignored" );
442 parseMode = MODE_EOL;
443 break;
444 default:
445 fst_error( "Unknown Escapecharacter: ignored" );
446 parseMode = parseMode_before_ESC;
447 // Normal char;
448 break;
450 break;
451 case MODE_WHITESPACE:
452 switch( *pos ) {
453 case '\"':
454 parseMode = MODE_DOUBLEQUOTE;
455 myargc++;
456 break;
457 case '\'':
458 parseMode = MODE_QUOTE;
459 myargc++;
460 break;
461 case '\\':
462 parseMode_before_ESC = MODE_NORMAL;
463 parseMode = MODE_ESCAPED;
464 myargc++;
465 break;
466 case ' ':
467 parseMode = MODE_WHITESPACE;
468 break;
469 case 0:
470 parseMode = MODE_EOL;
471 break;
472 default:
474 parseMode = MODE_NORMAL;
475 // Normal char;
476 myargc++;
477 break;
479 break;
481 pos++;
484 myargv = malloc( myargc * sizeof( char * ) );
485 if( !myargv ) {
486 fst_error( "cant alloc memory" );
487 exit( 10 );
490 // alloc strlen(cmdline) + 1 for each argv.
491 // this avoids another parsing pass.
492 for( i=0; i<myargc; i++ ) {
493 myargv[i] = malloc( strlen(cmdline) + 1 );
494 if( !myargv[i] ) {
495 fst_error( "cant alloc memory" );
496 exit( 10 );
498 myargv[i][0] = 0;
501 // Now rerun theparser and actually emit chars.
502 pos = cmdline;
503 parseMode = MODE_WHITESPACE;
504 parseMode_before_ESC = MODE_NORMAL;
505 int current_arg = 0;
506 char *emit_pos = myargv[0];
508 while( parseMode != MODE_EOL ) {
509 switch( parseMode ) {
510 case MODE_NORMAL:
511 switch( *pos ) {
512 case '\"':
513 parseMode = MODE_DOUBLEQUOTE;
514 break;
515 case '\'':
516 parseMode = MODE_QUOTE;
517 break;
518 case '\\':
519 parseMode_before_ESC = parseMode;
520 parseMode = MODE_ESCAPED;
521 break;
522 case ' ': // First Space after an arg;
523 parseMode = MODE_WHITESPACE;
524 *emit_pos = 0;
526 break;
527 case 0: // EOL after arg.
528 parseMode = MODE_EOL;
529 *emit_pos = 0;
530 break;
531 default:
533 *(emit_pos++) = *pos;
534 break;
536 break;
537 case MODE_QUOTE:
538 switch( *pos ) {
539 case '\'':
540 parseMode = MODE_NORMAL;
541 break;
542 case '\\':
543 parseMode_before_ESC = parseMode;
544 parseMode = MODE_ESCAPED;
545 break;
546 case 0:
547 fst_error( "parse Error on cmdline" );
548 parseMode = MODE_EOL;
549 *emit_pos = 0;
550 break;
551 default:
552 // Normal char;
553 *(emit_pos++) = *pos;
554 break;
556 break;
557 case MODE_DOUBLEQUOTE:
558 switch( *pos ) {
559 case '"':
560 parseMode = MODE_NORMAL;
561 break;
562 case '\\':
563 parseMode_before_ESC = parseMode;
564 parseMode = MODE_ESCAPED;
565 break;
566 case 0:
567 fst_error( "parse Error on cmdline" );
568 parseMode = MODE_EOL;
569 *emit_pos = 0;
570 break;
571 default:
572 // Normal char;
573 *(emit_pos++) = *pos;
574 break;
576 break;
577 case MODE_ESCAPED:
578 switch( *pos ) {
579 case '\"':
580 // emit escaped char;
581 parseMode = parseMode_before_ESC;
582 *(emit_pos++) = *pos;
583 break;
584 case '\'':
585 // emit escaped char;
586 parseMode = parseMode_before_ESC;
587 *(emit_pos++) = *pos;
588 break;
589 case '\\':
590 // emit escaped char;
591 parseMode = parseMode_before_ESC;
592 *(emit_pos++) = *pos;
593 break;
594 case 0:
595 fst_error( "EOL after escape: ignored" );
596 parseMode = MODE_EOL;
597 *emit_pos = 0;
598 break;
599 default:
600 fst_error( "Unknown Escapecharacter: ignored" );
601 parseMode = parseMode_before_ESC;
602 break;
604 break;
605 case MODE_WHITESPACE:
606 switch( *pos ) {
607 case '\"':
608 parseMode = MODE_DOUBLEQUOTE;
609 // ok... arg begins
610 current_arg++;
611 emit_pos = myargv[current_arg];
612 break;
613 case '\'':
614 parseMode = MODE_QUOTE;
615 // ok... arg begins
616 current_arg++;
617 emit_pos = myargv[current_arg];
618 break;
619 case '\\':
620 parseMode_before_ESC = MODE_NORMAL;
621 parseMode = MODE_ESCAPED;
622 // ok... arg begins
623 current_arg++;
624 emit_pos = myargv[current_arg];
625 break;
626 case ' ':
627 parseMode = MODE_WHITESPACE;
628 break;
629 case 0:
630 parseMode = MODE_EOL;
631 break;
632 default:
633 parseMode = MODE_NORMAL;
634 // ok... arg begins
635 current_arg++;
636 emit_pos = myargv[current_arg];
637 // Normal char;
638 *(emit_pos++) = *pos;
639 break;
641 break;
643 pos++;
646 strncpy( myargv[0], argv0, strlen(cmdline) );
648 *argc = myargc;
649 *argv = myargv;
652 /* Plugin "canDo" helper function to neaten up plugin feature detection calls */
653 int canDo(struct AEffect* plugin, char* feature)
655 return (plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)feature, 0.0f) > 0);
658 //Ladish SIGUSR1
659 static void sig_ladish(int sig)
661 printf("got SIGUSR1, saving state now...\n");
662 ladish_save_now = 1;
665 int WINAPI
666 WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow)
667 //int
668 //main( int argc, char **argv )
670 JackVST* jvst;
671 struct AEffect* plugin;
672 int i;
673 char* client_name = 0;
674 char* period;
675 int with_editor = 1;
676 int resume_not_rt = 1;
677 int load_state = 0;
678 char * state_file = 0;
679 char *plug;
680 int vst_version;
682 float sample_rate = 0;
683 long block_size = 0;
685 int argc;
686 char **argv;
688 //Ladish SIGUSR1
689 struct sigaction sa;
690 memset(&sa, 0, sizeof(sa));
691 sa.sa_handler = sig_ladish;
692 sigaction(SIGUSR1, &sa, NULL);
693 ladish_save_now = 0;
695 create_argc_argv_from_cmdline( cmdline, "./fst", &argc, &argv );
697 if (argc < 3) {
698 fprintf (stderr, "usage: %s <ladish-state-filename> <plugin>\n", argv[0]);
699 return 1;
702 printf( "yo... lets see...\n" );
703 //setpgrp();
705 gui_init (&argc, &argv);
707 ladish_state_filename = argv[1];
709 if (open(ladish_state_filename, O_RDONLY) > 0) {
710 load_state = 1;
711 state_file = ladish_state_filename;
714 plug = argv[2];
716 if (fst_init (hInst)) {
717 return 1;
720 jvst = (JackVST*) calloc (1, sizeof (JackVST));
721 for (i=0; i<128; i++ )
722 jvst->midi_map[i] = -1;
724 client_name = g_path_get_basename(strdup (plug));
725 if ((period = strrchr (client_name, '.')) != NULL) {
726 *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);
760 /* set program to zero */
761 /* i comment this out because it breaks dfx Geometer
762 * looks like we cant set programs for it
764 * TODO:
765 * this might have been because we were not a real wine thread, but i doubt
766 * it. need to check.
768 * plugin->dispatcher (plugin, effSetProgram, 0, 0, NULL, 0.0f);
772 jvst->midi_inport = jack_port_register(jvst->client,
773 "midi-in",
774 JACK_DEFAULT_MIDI_TYPE,
775 JackPortIsInput,
778 vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
779 if (vst_version >= 2) {
780 int isSynth = (plugin->flags & effFlagsIsSynth) > 0;
781 int canReceiveVstEvents = canDo(plugin, "receiveVstEvents");
782 int canReceiveVstMidiEvent = canDo(plugin, "receiveVstMidiEvent");
783 int canSendVstEvents = canDo(plugin, "sendVstEvents");
784 int canSendVstMidiEvent = canDo(plugin, "sendVstMidiEvent");
786 printf("Plugin isSynth = %d\n", isSynth);
787 printf("Plugin canDo receiveVstEvents = %d\n", canReceiveVstEvents);
788 printf("Plugin canDo receiveVstMidiEvent = %d\n", canReceiveVstMidiEvent);
789 printf("Plugin canDo sendVstEvents = %d\n", canSendVstEvents);
790 printf("Plugin canDo SendVstMidiEvent = %d\n", canSendVstMidiEvent);
792 /* should we send the plugin VST events (i.e. MIDI) */
793 if (isSynth || canReceiveVstEvents || canReceiveVstMidiEvent) {
794 int i;
795 jvst->want_midi_in = 1;
797 /* The VstEvents structure already contains an array of 2 */
798 /* pointers to VstEvent so I guess that this malloc actually */
799 /* gives enough space for MIDI_EVENT_MAX + 2 events.... */
800 jvst->events = (VstEvents*)malloc(sizeof(VstEvents) +
801 (MIDI_EVENT_MAX * sizeof(VstMidiEvent*)));
803 jvst->events->numEvents = 0;
804 jvst->events->reserved = 0;
806 /* Initialise dynamic array of MIDI_EVENT_MAX VstMidiEvents */
807 /* and point the VstEvents events array of pointers to it */
808 jvst->event_array = (VstMidiEvent*)calloc(MIDI_EVENT_MAX,
809 sizeof (VstMidiEvent));
810 for (i = 0; i < MIDI_EVENT_MAX; i++) {
811 jvst->events->events[i] = (VstEvent*)&(jvst->event_array[i]);
815 /* Can the plugin send VST events (i.e. MIDI) */
816 if (canSendVstEvents || canSendVstMidiEvent) {
817 jvst->ringbuffer = jack_ringbuffer_create(RINGBUFFER_SIZE);
818 if (jvst->ringbuffer == NULL) {
819 fst_error("Cannot create JACK ringbuffer.");
820 return 1;
823 jack_ringbuffer_mlock(jvst->ringbuffer);
825 jvst->midi_outport = jack_port_register(jvst->client,
826 "midi-out",
827 JACK_DEFAULT_MIDI_TYPE,
828 JackPortIsOutput,
833 printf("PortLayout: in: %d out: %d\n", plugin->numInputs, plugin->numOutputs);
835 jvst->inports = (jack_port_t**)malloc(sizeof(jack_port_t*) * plugin->numInputs);
836 jvst->ins = (float**)malloc(sizeof(float*) * plugin->numInputs);
838 for (i = 0; i < plugin->numInputs; ++i) {
839 char buf[64];
840 snprintf (buf, sizeof(buf), "in%d", i+1);
841 jvst->inports[i] = jack_port_register (jvst->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
844 jvst->outports = (jack_port_t **) malloc (sizeof(jack_port_t*) * plugin->numOutputs);
845 jvst->outs = (float **) malloc (sizeof (float *) * plugin->numOutputs);
847 for (i = 0; i < plugin->numOutputs; ++i) {
848 char buf[64];
849 snprintf (buf, sizeof(buf), "out%d", i+1);
850 jvst->outports[i] = jack_port_register (jvst->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
853 if( with_winaudio ) {
854 DWORD threadId = 0;
856 sem_init( &winaudio_activate, 0, 0 );
857 sem_init( &winaudio_done, 0, 0 );
859 audioThreadHandle = CreateThread(0, 0, WinAudioThreadMain, 0, 0, &threadId);
860 if (!audioThreadHandle) {
861 fst_error( "Failed to create audio thread!" );
862 return 1;
864 // ok... this waits for the windows thread to get up in the first place.
865 sem_wait( &winaudio_done );
866 printf( "created audio thread\n" );
867 jack_set_process_callback (jvst->client, (JackProcessCallback) winaudio_process_callback, jvst);
868 } else {
870 jack_set_process_callback (jvst->client, (JackProcessCallback) process_callback, jvst);
872 printf( "Calling Jack activate\n" );
873 jack_activate (jvst->client);
875 if (with_editor) {
876 printf( "open Editor\n" );
878 if (fst_run_editor (jvst->fst)) {
879 fst_error ("cannot create editor");
880 return 1;
882 } else {
883 printf( "no Editor\n" );
886 /* load state if requested */
888 if (load_state) {
889 if (!fst_load_state (jvst->fst, state_file)) {
890 printf ("ERROR: Could not load state file %s\n", state_file);
891 jack_deactivate( jvst->client );
892 if( with_winaudio ) {
893 printf( "Waiting for WinAudioThread to exit\n" );
894 with_winaudio = 0;
895 CloseHandle( audioThreadHandle );
897 return 1;
902 printf( "Entering main loop\n" );
903 if (with_editor) {
904 printf( "ok.... RockNRoll\n" );
905 manage_vst_plugin (jvst);
906 } else {
907 while( 1 )
908 sleep (10);
911 jack_deactivate( jvst->client );
912 if( with_winaudio ) {
913 printf( "Waiting for WinAudioThread to exit\n" );
914 with_winaudio = 0;
915 CloseHandle( audioThreadHandle );
917 return 0;