Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Midi Sequencer interface routines. | |
3 | * | |
4 | * Copyright (C) 1999 Steve Ratcliffe | |
5 | * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
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. | |
16 | * | |
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 | |
20 | */ | |
21 | ||
22 | #include "emux_voice.h" | |
23 | #include <linux/slab.h> | |
da155d5b | 24 | #include <linux/module.h> |
1da177e4 LT |
25 | |
26 | /* Prototypes for static functions */ | |
27 | static void free_port(void *private); | |
03da312a TI |
28 | static void snd_emux_init_port(struct snd_emux_port *p); |
29 | static int snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info); | |
30 | static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info); | |
1da177e4 LT |
31 | |
32 | /* | |
33 | * MIDI emulation operators | |
34 | */ | |
03da312a | 35 | static struct snd_midi_op emux_ops = { |
f93a1c9e KC |
36 | .note_on = snd_emux_note_on, |
37 | .note_off = snd_emux_note_off, | |
38 | .key_press = snd_emux_key_press, | |
39 | .note_terminate = snd_emux_terminate_note, | |
40 | .control = snd_emux_control, | |
41 | .nrpn = snd_emux_nrpn, | |
42 | .sysex = snd_emux_sysex, | |
1da177e4 LT |
43 | }; |
44 | ||
45 | ||
46 | /* | |
47 | * number of MIDI channels | |
48 | */ | |
49 | #define MIDI_CHANNELS 16 | |
50 | ||
51 | /* | |
52 | * type flags for MIDI sequencer port | |
53 | */ | |
54 | #define DEFAULT_MIDI_TYPE (SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |\ | |
55 | SNDRV_SEQ_PORT_TYPE_MIDI_GM |\ | |
56 | SNDRV_SEQ_PORT_TYPE_MIDI_GS |\ | |
450047a7 CL |
57 | SNDRV_SEQ_PORT_TYPE_MIDI_XG |\ |
58 | SNDRV_SEQ_PORT_TYPE_HARDWARE |\ | |
59 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) | |
1da177e4 LT |
60 | |
61 | /* | |
62 | * Initialise the EMUX Synth by creating a client and registering | |
63 | * a series of ports. | |
64 | * Each of the ports will contain the 16 midi channels. Applications | |
65 | * can connect to these ports to play midi data. | |
66 | */ | |
67 | int | |
03da312a | 68 | snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) |
1da177e4 LT |
69 | { |
70 | int i; | |
03da312a | 71 | struct snd_seq_port_callback pinfo; |
1da177e4 LT |
72 | char tmpname[64]; |
73 | ||
7b6d9245 CL |
74 | emu->client = snd_seq_create_kernel_client(card, index, |
75 | "%s WaveTable", emu->name); | |
1da177e4 | 76 | if (emu->client < 0) { |
42b0158b | 77 | snd_printk(KERN_ERR "can't create client\n"); |
1da177e4 LT |
78 | return -ENODEV; |
79 | } | |
80 | ||
81 | if (emu->num_ports < 0) { | |
42b0158b | 82 | snd_printk(KERN_WARNING "seqports must be greater than zero\n"); |
1da177e4 LT |
83 | emu->num_ports = 1; |
84 | } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) { | |
42b0158b | 85 | snd_printk(KERN_WARNING "too many ports." |
1da177e4 LT |
86 | "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS); |
87 | emu->num_ports = SNDRV_EMUX_MAX_PORTS; | |
88 | } | |
89 | ||
90 | memset(&pinfo, 0, sizeof(pinfo)); | |
91 | pinfo.owner = THIS_MODULE; | |
92 | pinfo.use = snd_emux_use; | |
93 | pinfo.unuse = snd_emux_unuse; | |
94 | pinfo.event_input = snd_emux_event_input; | |
95 | ||
96 | for (i = 0; i < emu->num_ports; i++) { | |
03da312a | 97 | struct snd_emux_port *p; |
1da177e4 LT |
98 | |
99 | sprintf(tmpname, "%s Port %d", emu->name, i); | |
100 | p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS, | |
101 | 0, &pinfo); | |
fbc020b4 | 102 | if (!p) { |
42b0158b | 103 | snd_printk(KERN_ERR "can't create port\n"); |
1da177e4 LT |
104 | return -ENOMEM; |
105 | } | |
106 | ||
107 | p->port_mode = SNDRV_EMUX_PORT_MODE_MIDI; | |
108 | snd_emux_init_port(p); | |
109 | emu->ports[i] = p->chset.port; | |
110 | emu->portptrs[i] = p; | |
111 | } | |
112 | ||
113 | return 0; | |
114 | } | |
115 | ||
116 | ||
117 | /* | |
118 | * Detach from the ports that were set up for this synthesizer and | |
119 | * destroy the kernel client. | |
120 | */ | |
121 | void | |
03da312a | 122 | snd_emux_detach_seq(struct snd_emux *emu) |
1da177e4 LT |
123 | { |
124 | if (emu->voices) | |
125 | snd_emux_terminate_all(emu); | |
126 | ||
1da177e4 LT |
127 | if (emu->client >= 0) { |
128 | snd_seq_delete_kernel_client(emu->client); | |
129 | emu->client = -1; | |
130 | } | |
1da177e4 LT |
131 | } |
132 | ||
133 | ||
134 | /* | |
135 | * create a sequencer port and channel_set | |
136 | */ | |
137 | ||
03da312a TI |
138 | struct snd_emux_port * |
139 | snd_emux_create_port(struct snd_emux *emu, char *name, | |
140 | int max_channels, int oss_port, | |
141 | struct snd_seq_port_callback *callback) | |
1da177e4 | 142 | { |
03da312a | 143 | struct snd_emux_port *p; |
1da177e4 LT |
144 | int i, type, cap; |
145 | ||
146 | /* Allocate structures for this channel */ | |
c997aabb | 147 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
64a591e6 | 148 | if (!p) |
1da177e4 | 149 | return NULL; |
64a591e6 | 150 | |
949a0c23 ME |
151 | p->chset.channels = kcalloc(max_channels, sizeof(*p->chset.channels), |
152 | GFP_KERNEL); | |
fbc020b4 | 153 | if (!p->chset.channels) { |
1da177e4 LT |
154 | kfree(p); |
155 | return NULL; | |
156 | } | |
157 | for (i = 0; i < max_channels; i++) | |
158 | p->chset.channels[i].number = i; | |
159 | p->chset.private_data = p; | |
160 | p->chset.max_channels = max_channels; | |
161 | p->emu = emu; | |
162 | p->chset.client = emu->client; | |
163 | #ifdef SNDRV_EMUX_USE_RAW_EFFECT | |
164 | snd_emux_create_effect(p); | |
165 | #endif | |
166 | callback->private_free = free_port; | |
167 | callback->private_data = p; | |
168 | ||
169 | cap = SNDRV_SEQ_PORT_CAP_WRITE; | |
170 | if (oss_port) { | |
171 | type = SNDRV_SEQ_PORT_TYPE_SPECIFIC; | |
172 | } else { | |
173 | type = DEFAULT_MIDI_TYPE; | |
174 | cap |= SNDRV_SEQ_PORT_CAP_SUBS_WRITE; | |
175 | } | |
176 | ||
177 | p->chset.port = snd_seq_event_port_attach(emu->client, callback, | |
178 | cap, type, max_channels, | |
179 | emu->max_voices, name); | |
180 | ||
181 | return p; | |
182 | } | |
183 | ||
184 | ||
185 | /* | |
186 | * release memory block for port | |
187 | */ | |
188 | static void | |
189 | free_port(void *private_data) | |
190 | { | |
03da312a | 191 | struct snd_emux_port *p; |
1da177e4 LT |
192 | |
193 | p = private_data; | |
194 | if (p) { | |
195 | #ifdef SNDRV_EMUX_USE_RAW_EFFECT | |
196 | snd_emux_delete_effect(p); | |
197 | #endif | |
198 | kfree(p->chset.channels); | |
199 | kfree(p); | |
200 | } | |
201 | } | |
202 | ||
203 | ||
204 | #define DEFAULT_DRUM_FLAGS (1<<9) | |
205 | ||
206 | /* | |
207 | * initialize the port specific parameters | |
208 | */ | |
209 | static void | |
03da312a | 210 | snd_emux_init_port(struct snd_emux_port *p) |
1da177e4 LT |
211 | { |
212 | p->drum_flags = DEFAULT_DRUM_FLAGS; | |
213 | p->volume_atten = 0; | |
214 | ||
215 | snd_emux_reset_port(p); | |
216 | } | |
217 | ||
218 | ||
219 | /* | |
220 | * reset port | |
221 | */ | |
222 | void | |
03da312a | 223 | snd_emux_reset_port(struct snd_emux_port *port) |
1da177e4 LT |
224 | { |
225 | int i; | |
226 | ||
227 | /* stop all sounds */ | |
228 | snd_emux_sounds_off_all(port); | |
229 | ||
230 | snd_midi_channel_set_clear(&port->chset); | |
231 | ||
232 | #ifdef SNDRV_EMUX_USE_RAW_EFFECT | |
233 | snd_emux_clear_effect(port); | |
234 | #endif | |
235 | ||
236 | /* set port specific control parameters */ | |
237 | port->ctrls[EMUX_MD_DEF_BANK] = 0; | |
238 | port->ctrls[EMUX_MD_DEF_DRUM] = 0; | |
239 | port->ctrls[EMUX_MD_REALTIME_PAN] = 1; | |
240 | ||
241 | for (i = 0; i < port->chset.max_channels; i++) { | |
03da312a | 242 | struct snd_midi_channel *chan = port->chset.channels + i; |
1da177e4 LT |
243 | chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0; |
244 | } | |
245 | } | |
246 | ||
247 | ||
248 | /* | |
249 | * input sequencer event | |
250 | */ | |
251 | int | |
03da312a | 252 | snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data, |
1da177e4 LT |
253 | int atomic, int hop) |
254 | { | |
03da312a | 255 | struct snd_emux_port *port; |
1da177e4 LT |
256 | |
257 | port = private_data; | |
5e246b85 TI |
258 | if (snd_BUG_ON(!port || !ev)) |
259 | return -EINVAL; | |
1da177e4 LT |
260 | |
261 | snd_midi_process_event(&emux_ops, ev, &port->chset); | |
262 | ||
263 | return 0; | |
264 | } | |
265 | ||
266 | ||
267 | /* | |
268 | * increment usage count | |
269 | */ | |
1c94e65c TI |
270 | static int |
271 | __snd_emux_inc_count(struct snd_emux *emu) | |
1da177e4 LT |
272 | { |
273 | emu->used++; | |
274 | if (!try_module_get(emu->ops.owner)) | |
275 | goto __error; | |
276 | if (!try_module_get(emu->card->module)) { | |
277 | module_put(emu->ops.owner); | |
278 | __error: | |
279 | emu->used--; | |
280 | return 0; | |
281 | } | |
282 | return 1; | |
283 | } | |
284 | ||
1c94e65c TI |
285 | int snd_emux_inc_count(struct snd_emux *emu) |
286 | { | |
287 | int ret; | |
288 | ||
289 | mutex_lock(&emu->register_mutex); | |
290 | ret = __snd_emux_inc_count(emu); | |
291 | mutex_unlock(&emu->register_mutex); | |
292 | return ret; | |
293 | } | |
1da177e4 LT |
294 | |
295 | /* | |
296 | * decrease usage count | |
297 | */ | |
1c94e65c TI |
298 | static void |
299 | __snd_emux_dec_count(struct snd_emux *emu) | |
1da177e4 LT |
300 | { |
301 | module_put(emu->card->module); | |
302 | emu->used--; | |
303 | if (emu->used <= 0) | |
304 | snd_emux_terminate_all(emu); | |
305 | module_put(emu->ops.owner); | |
306 | } | |
307 | ||
1c94e65c TI |
308 | void snd_emux_dec_count(struct snd_emux *emu) |
309 | { | |
310 | mutex_lock(&emu->register_mutex); | |
311 | __snd_emux_dec_count(emu); | |
312 | mutex_unlock(&emu->register_mutex); | |
313 | } | |
1da177e4 LT |
314 | |
315 | /* | |
316 | * Routine that is called upon a first use of a particular port | |
317 | */ | |
318 | static int | |
03da312a | 319 | snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) |
1da177e4 | 320 | { |
03da312a TI |
321 | struct snd_emux_port *p; |
322 | struct snd_emux *emu; | |
1da177e4 LT |
323 | |
324 | p = private_data; | |
5e246b85 TI |
325 | if (snd_BUG_ON(!p)) |
326 | return -EINVAL; | |
1da177e4 | 327 | emu = p->emu; |
5e246b85 TI |
328 | if (snd_BUG_ON(!emu)) |
329 | return -EINVAL; | |
1da177e4 | 330 | |
ef9f0a42 | 331 | mutex_lock(&emu->register_mutex); |
1da177e4 | 332 | snd_emux_init_port(p); |
1c94e65c | 333 | __snd_emux_inc_count(emu); |
ef9f0a42 | 334 | mutex_unlock(&emu->register_mutex); |
1da177e4 LT |
335 | return 0; |
336 | } | |
337 | ||
338 | /* | |
339 | * Routine that is called upon the last unuse() of a particular port. | |
340 | */ | |
341 | static int | |
03da312a | 342 | snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) |
1da177e4 | 343 | { |
03da312a TI |
344 | struct snd_emux_port *p; |
345 | struct snd_emux *emu; | |
1da177e4 LT |
346 | |
347 | p = private_data; | |
5e246b85 TI |
348 | if (snd_BUG_ON(!p)) |
349 | return -EINVAL; | |
1da177e4 | 350 | emu = p->emu; |
5e246b85 TI |
351 | if (snd_BUG_ON(!emu)) |
352 | return -EINVAL; | |
1da177e4 | 353 | |
ef9f0a42 | 354 | mutex_lock(&emu->register_mutex); |
1da177e4 | 355 | snd_emux_sounds_off_all(p); |
1c94e65c | 356 | __snd_emux_dec_count(emu); |
ef9f0a42 | 357 | mutex_unlock(&emu->register_mutex); |
1da177e4 LT |
358 | return 0; |
359 | } | |
360 | ||
361 | ||
1da177e4 LT |
362 | /* |
363 | * attach virtual rawmidi devices | |
364 | */ | |
03da312a | 365 | int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card) |
1da177e4 LT |
366 | { |
367 | int i; | |
368 | ||
369 | emu->vmidi = NULL; | |
370 | if (emu->midi_ports <= 0) | |
371 | return 0; | |
372 | ||
949a0c23 | 373 | emu->vmidi = kcalloc(emu->midi_ports, sizeof(*emu->vmidi), GFP_KERNEL); |
fbc020b4 | 374 | if (!emu->vmidi) |
1da177e4 LT |
375 | return -ENOMEM; |
376 | ||
377 | for (i = 0; i < emu->midi_ports; i++) { | |
03da312a TI |
378 | struct snd_rawmidi *rmidi; |
379 | struct snd_virmidi_dev *rdev; | |
1da177e4 LT |
380 | if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0) |
381 | goto __error; | |
382 | rdev = rmidi->private_data; | |
383 | sprintf(rmidi->name, "%s Synth MIDI", emu->name); | |
384 | rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH; | |
385 | rdev->client = emu->client; | |
386 | rdev->port = emu->ports[i]; | |
387 | if (snd_device_register(card, rmidi) < 0) { | |
388 | snd_device_free(card, rmidi); | |
389 | goto __error; | |
390 | } | |
391 | emu->vmidi[i] = rmidi; | |
42b0158b | 392 | /* snd_printk(KERN_DEBUG "virmidi %d ok\n", i); */ |
1da177e4 LT |
393 | } |
394 | return 0; | |
395 | ||
396 | __error: | |
42b0158b | 397 | /* snd_printk(KERN_DEBUG "error init..\n"); */ |
1da177e4 LT |
398 | snd_emux_delete_virmidi(emu); |
399 | return -ENOMEM; | |
400 | } | |
401 | ||
03da312a | 402 | int snd_emux_delete_virmidi(struct snd_emux *emu) |
1da177e4 LT |
403 | { |
404 | int i; | |
405 | ||
fbc020b4 | 406 | if (!emu->vmidi) |
1da177e4 LT |
407 | return 0; |
408 | ||
409 | for (i = 0; i < emu->midi_ports; i++) { | |
410 | if (emu->vmidi[i]) | |
411 | snd_device_free(emu->card, emu->vmidi[i]); | |
412 | } | |
413 | kfree(emu->vmidi); | |
414 | emu->vmidi = NULL; | |
415 | return 0; | |
416 | } |