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.
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 $
33 #include <vestige/aeffectx.h>
38 create_sequencer (const char* client_name
, bool isinput
)
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"
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
));
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");
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;
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
;
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
);
118 snd_seq_event_input (jvst
->seq
, &event
);
120 if (jvst
->midiquit
) {
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);
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);
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
);
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);
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);
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);
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);
155 //printf("Unknown type: %d\n",event->type);
163 void stop_midireceiver (JackVST
*jvst
)
166 snd_seq_event_t event
;
167 snd_seq_t
*seq2
= create_sequencer ("jfstquit", true);
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",
183 snd_seq_drain_output (seq2
);
184 snd_seq_close (seq2
);
185 pthread_join (jvst
->midi_thread
,NULL
);
186 snd_seq_close (jvst
->seq
);