ignore unpaired noteoff's when writing part of a MidiModel to a new source. in realit...
[ardour2.git] / libs / fst / vsti.c
blob6a64f9c5e4810d934f4d3cdd2444bdba45b95ead
1 /*
2 * VST instrument support
4 * Derived from code that was marked:
5 * Copyright (C) Kjetil S. Matheussen 2004 (k.s.matheussen@notam02.no)
6 * Alsa-seq midi-code made by looking at the jack-rack source made by Bob Ham.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * $Id: vsti.c,v 1.2 2004/04/07 01:56:23 pauld Exp $
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <memory.h>
30 #include <fcntl.h>
31 #include <stdbool.h>
32 #include <jackvst.h>
33 #include <vestige/aeffectx.h>
34 #include <pthread.h>
35 #include <sched.h>
37 snd_seq_t *
38 create_sequencer (const char* client_name, bool isinput)
40 snd_seq_t * seq;
41 int err;
43 if ((err = snd_seq_open (&seq, "default", SND_SEQ_OPEN_DUPLEX, 0)) != 0) {
44 fst_error ("Could not open ALSA sequencer, aborting\n\n%s\n\n"
45 "Make sure you have configure ALSA properly and that\n"
46 "/proc/asound/seq/clients exists and contains relevant\n"
47 "devices (%s).",
48 snd_strerror (err));
49 return NULL;
52 snd_seq_set_client_name (seq, client_name);
54 if ((err = snd_seq_create_simple_port (seq, isinput? "Input" : "Output",
55 (isinput? SND_SEQ_PORT_CAP_WRITE: SND_SEQ_PORT_CAP_READ)| SND_SEQ_PORT_CAP_DUPLEX |
56 SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE,
57 SND_SEQ_PORT_TYPE_APPLICATION|SND_SEQ_PORT_TYPE_SPECIFIC)) != 0) {
58 fst_error ("Could not create ALSA port: %s", snd_strerror (err));
59 snd_seq_close(seq);
60 return NULL;
63 return seq;
66 static void
67 queue_midi (JackVST *jvst, int val1, int val2, int val3)
69 struct VstMidiEvent *pevent;
70 jack_ringbuffer_data_t vec[2];
72 jack_ringbuffer_get_write_vector (jvst->event_queue, vec);
74 if (vec[0].len < sizeof (struct VstMidiEvent)) {
75 fst_error ("event queue has no write space");
76 return;
79 pevent = (struct VstMidiEvent *) vec[0].buf;
81 // printf("note: %d\n",note);
83 pevent->type = kVstMidiType;
84 pevent->byteSize = 24;
85 pevent->deltaFrames = 0;
86 pevent->flags = 0;
87 pevent->detune = 0;
88 pevent->noteLength = 0;
89 pevent->noteOffset = 0;
90 pevent->reserved1 = 0;
91 pevent->reserved2 = 0;
92 pevent->noteOffVelocity = 0;
93 pevent->midiData[0] = val1;
94 pevent->midiData[1] = val2;
95 pevent->midiData[2] = val3;
96 pevent->midiData[3] = 0;
98 //printf("Sending: %x %x %x\n",val1,val2,val3);
100 jack_ringbuffer_write_advance (jvst->event_queue, sizeof (struct VstMidiEvent));
103 void *midireceiver(void *arg)
105 snd_seq_event_t *event;
106 JackVST *jvst = (JackVST* )arg;
107 int val;
109 struct sched_param scp;
110 scp.sched_priority = 50;
112 // Try to set fifo priority...
113 // this works, if we are root or newe sched-cap manegment is used...
114 pthread_setschedparam( pthread_self(), SCHED_FIFO, &scp );
116 while (1) {
118 snd_seq_event_input (jvst->seq, &event);
120 if (jvst->midiquit) {
121 break;
124 switch(event->type){
125 case SND_SEQ_EVENT_NOTEON:
126 queue_midi(jvst,0x90+event->data.note.channel,event->data.note.note,event->data.note.velocity);
127 //printf("Noteon, channel: %d note: %d vol: %d\n",event->data.note.channel,event->data.note.note,event->data.note.velocity);
128 break;
129 case SND_SEQ_EVENT_NOTEOFF:
130 queue_midi(jvst,0x80+event->data.note.channel,event->data.note.note,0);
131 //printf("Noteoff, channel: %d note: %d vol: %d\n",event->data.note.channel,event->data.note.note,event->data.note.velocity);
132 break;
133 case SND_SEQ_EVENT_KEYPRESS:
134 //printf("Keypress, channel: %d note: %d vol: %d\n",event->data.note.channel,event->data.note.note,event->data.note.velocity);
135 queue_midi(jvst,0xa0+event->data.note.channel,event->data.note.note,event->data.note.velocity);
136 break;
137 case SND_SEQ_EVENT_CONTROLLER:
138 queue_midi(jvst,0xb0+event->data.control.channel,event->data.control.param,event->data.control.value);
139 //printf("Control: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
140 break;
141 case SND_SEQ_EVENT_PITCHBEND:
142 val=event->data.control.value + 0x2000;
143 queue_midi(jvst,0xe0+event->data.control.channel,val&127,val>>7);
144 //printf("Pitch: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
145 break;
146 case SND_SEQ_EVENT_CHANPRESS:
147 //printf("chanpress: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
148 queue_midi(jvst,0xd0+event->data.control.channel,event->data.control.value,0);
149 break;
150 case SND_SEQ_EVENT_PGMCHANGE:
151 //printf("pgmchange: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
152 queue_midi(jvst,0xc0+event->data.control.channel,event->data.control.value,0);
153 break;
154 default:
155 //printf("Unknown type: %d\n",event->type);
156 break;
160 return NULL;
163 void stop_midireceiver (JackVST *jvst)
165 int err;
166 snd_seq_event_t event;
167 snd_seq_t *seq2 = create_sequencer ("jfstquit", true);
169 jvst->midiquit = 1;
171 snd_seq_connect_to (seq2, 0, snd_seq_client_id (jvst->seq),0);
172 snd_seq_ev_clear (&event);
173 snd_seq_ev_set_direct (&event);
174 snd_seq_ev_set_subs (&event);
175 snd_seq_ev_set_source (&event, 0);
176 snd_seq_ev_set_controller (&event,1,0x80,50);
178 if ((err = snd_seq_event_output (seq2, &event)) < 0) {
179 fst_error ("cannot send stop event to midi thread: %s\n",
180 snd_strerror (err));
183 snd_seq_drain_output (seq2);
184 snd_seq_close (seq2);
185 pthread_join (jvst->midi_thread,NULL);
186 snd_seq_close (jvst->seq);