1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * ALSA SEQ < - > JACK MIDI bridge
5 * Copyright (c) 2006,2007 Dmitry S. Baikov <c0ff@konstruktiv.org>
6 * Copyright (c) 2007,2008,2009 Nedko Arnaudov <nedko@arnaudov.name>
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; version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <semaphore.h>
24 #include <alsa/asoundlib.h>
25 #include <jack/jack.h>
26 #include <jack/ringbuffer.h>
31 #include "port_hash.h"
33 #include "port_thread.h"
37 a2j_find_port_by_addr(
38 struct a2j_stream
* stream_ptr
,
41 struct list_head
* node_ptr
;
42 struct a2j_port
* port_ptr
;
44 list_for_each(node_ptr
, &stream_ptr
->list
)
46 port_ptr
= list_entry(node_ptr
, struct a2j_port
, siblings
);
47 if (port_ptr
->remote
.client
== addr
.client
&& port_ptr
->remote
.port
== addr
.port
)
57 a2j_find_port_by_jack_port_name(
58 struct a2j_stream
* stream_ptr
,
59 const char * jack_port
)
61 struct list_head
* node_ptr
;
62 struct a2j_port
* port_ptr
;
64 list_for_each(node_ptr
, &stream_ptr
->list
)
66 port_ptr
= list_entry(node_ptr
, struct a2j_port
, siblings
);
67 if (strcmp(port_ptr
->name
, jack_port
) == 0)
77 * ==================== Port add/del handling thread ==============================
86 const snd_seq_port_info_t
* info
)
88 struct a2j_stream
* stream_ptr
;
90 struct a2j_port
* port_ptr
;
92 a2j_debug("update_port_type(%d:%d)", addr
.client
, addr
.port
);
94 stream_ptr
= &self
->stream
[type
];
95 port_ptr
= a2j_find_port_by_addr(stream_ptr
, addr
);
97 if (type
== A2J_PORT_CAPTURE
)
99 alsa_mask
= SND_SEQ_PORT_CAP_SUBS_READ
;
103 alsa_mask
= SND_SEQ_PORT_CAP_SUBS_WRITE
;
106 if (port_ptr
!= NULL
&& (caps
& alsa_mask
) != alsa_mask
)
108 a2j_debug("setdead: %s", port_ptr
->name
);
109 port_ptr
->is_dead
= true;
112 if (port_ptr
== NULL
&& (caps
& alsa_mask
) == alsa_mask
)
114 if(jack_ringbuffer_write_space(stream_ptr
->new_ports
) >= sizeof(port_ptr
)) {
115 port_ptr
= a2j_port_create(self
, type
, addr
, info
);
116 if (port_ptr
!= NULL
)
118 jack_ringbuffer_write(stream_ptr
->new_ports
, (char *)&port_ptr
, sizeof(port_ptr
));
121 a2j_error( "dropping new port event... increase MAX_PORTS" );
130 const snd_seq_port_info_t
* info
)
132 unsigned int port_caps
= snd_seq_port_info_get_capability(info
);
133 unsigned int port_type
= snd_seq_port_info_get_type(info
);
135 a2j_debug("port %u:%u", addr
.client
, addr
.port
);
136 a2j_debug("port type: 0x%08X", port_type
);
137 a2j_debug("port caps: 0x%08X", port_caps
);
139 if (port_type
& SND_SEQ_PORT_TYPE_SPECIFIC
)
141 a2j_debug("SPECIFIC");
144 if (port_type
& SND_SEQ_PORT_TYPE_MIDI_GENERIC
)
146 a2j_debug("MIDI_GENERIC");
149 if (port_type
& SND_SEQ_PORT_TYPE_MIDI_GM
)
151 a2j_debug("MIDI_GM");
154 if (port_type
& SND_SEQ_PORT_TYPE_MIDI_GS
)
156 a2j_debug("MIDI_GS");
159 if (port_type
& SND_SEQ_PORT_TYPE_MIDI_XG
)
161 a2j_debug("MIDI_XG");
164 if (port_type
& SND_SEQ_PORT_TYPE_MIDI_MT32
)
166 a2j_debug("MIDI_MT32");
169 if (port_type
& SND_SEQ_PORT_TYPE_MIDI_GM2
)
171 a2j_debug("MIDI_GM2");
174 if (port_type
& SND_SEQ_PORT_TYPE_SYNTH
)
179 if (port_type
& SND_SEQ_PORT_TYPE_DIRECT_SAMPLE
)
181 a2j_debug("DIRECT_SAMPLE");
184 if (port_type
& SND_SEQ_PORT_TYPE_SAMPLE
)
189 if (port_type
& SND_SEQ_PORT_TYPE_HARDWARE
)
191 a2j_debug("HARDWARE");
194 if (port_type
& SND_SEQ_PORT_TYPE_SOFTWARE
)
196 a2j_debug("SOFTWARE");
199 if (port_type
& SND_SEQ_PORT_TYPE_SYNTHESIZER
)
201 a2j_debug("SYNTHESIZER");
204 if (port_type
& SND_SEQ_PORT_TYPE_PORT
)
209 if (port_type
& SND_SEQ_PORT_TYPE_APPLICATION
)
211 a2j_debug("APPLICATION");
216 a2j_debug("Ignoring port of type 0");
220 if ((port_type
& SND_SEQ_PORT_TYPE_HARDWARE
) && !g_a2j_export_hw_ports
)
222 a2j_debug("Ignoring hardware port");
226 if (port_caps
& SND_SEQ_PORT_CAP_NO_EXPORT
)
228 a2j_debug("Ignoring no-export port");
232 a2j_update_port_type(self
, A2J_PORT_CAPTURE
, addr
, port_caps
, info
);
233 a2j_update_port_type(self
, A2J_PORT_PLAYBACK
, addr
, port_caps
, info
);
238 jack_ringbuffer_t
* ports
)
240 struct a2j_port
*port
;
242 while ((sz
= jack_ringbuffer_read(ports
, (char*)&port
, sizeof(port
)))) {
243 assert (sz
== sizeof(port
));
244 a2j_info("port deleted: %s", port
->name
);
245 list_del(&port
->siblings
);
257 while ((size
= jack_ringbuffer_read(self
->port_add
, (char *)&addr
, sizeof(addr
))) != 0)
259 snd_seq_port_info_t
* info
;
262 snd_seq_port_info_alloca(&info
);
263 assert(size
== sizeof(addr
));
264 assert(addr
.client
!= self
->client_id
);
265 if ((err
= snd_seq_get_any_port_info(self
->seq
, addr
.client
, addr
.port
, info
)) >= 0)
267 a2j_update_port(self
, addr
, info
);
271 //a2j_port_setdead(self->stream[A2J_PORT_CAPTURE].ports, addr);
272 //a2j_port_setdead(self->stream[A2J_PORT_PLAYBACK].ports, addr);