2 * Sequencer Interface - main file
3 * Copyright (c) 2000 by Jaroslav Kysela <perex@perex.cz>
4 * Abramo Bagnara <abramo@alsa-project.org>
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
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 Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/ioctl.h>
25 #include "seq_local.h"
28 /* entry for static linking */
29 const char *_snd_module_seq_hw = "";
33 #define SNDRV_FILE_SEQ ALSA_DEVICE_DIRECTORY "seq"
34 #define SNDRV_FILE_ALOADSEQ ALOAD_DEVICE_DIRECTORY "aloadSEQ"
35 #define SNDRV_SEQ_VERSION_MAX SNDRV_PROTOCOL_VERSION(1, 0, 1)
40 #endif /* DOC_HIDDEN */
42 static int snd_seq_hw_close(snd_seq_t *seq)
44 snd_seq_hw_t *hw = seq->private_data;
49 SYSERR("close failed\n");
55 static int snd_seq_hw_nonblock(snd_seq_t *seq, int nonblock)
57 snd_seq_hw_t *hw = seq->private_data;
60 if ((flags = fcntl(hw->fd, F_GETFL)) < 0) {
61 SYSERR("F_GETFL failed");
68 if (fcntl(hw->fd, F_SETFL, flags) < 0) {
69 SYSERR("F_SETFL for O_NONBLOCK failed");
75 static int snd_seq_hw_client_id(snd_seq_t *seq)
77 snd_seq_hw_t *hw = seq->private_data;
79 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_CLIENT_ID, &client) < 0) {
80 SYSERR("SNDRV_SEQ_IOCTL_CLIENT_ID failed");
86 static int snd_seq_hw_system_info(snd_seq_t *seq, snd_seq_system_info_t * info)
88 snd_seq_hw_t *hw = seq->private_data;
89 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SYSTEM_INFO, info) < 0) {
90 SYSERR("SNDRV_SEQ_IOCTL_SYSTEM_INFO failed");
96 static int snd_seq_hw_get_client_info(snd_seq_t *seq, snd_seq_client_info_t * info)
98 snd_seq_hw_t *hw = seq->private_data;
99 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, info) < 0) {
100 /*SYSERR("SNDRV_SEQ_IOCTL_GET_CLIENT_INFO failed");*/
106 static int snd_seq_hw_set_client_info(snd_seq_t *seq, snd_seq_client_info_t * info)
108 snd_seq_hw_t *hw = seq->private_data;
109 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info) < 0) {
110 /*SYSERR("SNDRV_SEQ_IOCTL_SET_CLIENT_INFO failed");*/
116 static int snd_seq_hw_create_port(snd_seq_t *seq, snd_seq_port_info_t * port)
118 snd_seq_hw_t *hw = seq->private_data;
119 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_CREATE_PORT, port) < 0) {
120 /*SYSERR("SNDRV_SEQ_IOCTL_CREATE_PORT failed");*/
126 static int snd_seq_hw_delete_port(snd_seq_t *seq, snd_seq_port_info_t * port)
128 snd_seq_hw_t *hw = seq->private_data;
129 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_DELETE_PORT, port) < 0) {
130 /*SYSERR("SNDRV_SEQ_IOCTL_DELETE_PORT failed");*/
136 static int snd_seq_hw_get_port_info(snd_seq_t *seq, snd_seq_port_info_t * info)
138 snd_seq_hw_t *hw = seq->private_data;
139 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_PORT_INFO, info) < 0) {
140 /*SYSERR("SNDRV_SEQ_IOCTL_GET_PORT_INFO failed");*/
146 static int snd_seq_hw_set_port_info(snd_seq_t *seq, snd_seq_port_info_t * info)
148 snd_seq_hw_t *hw = seq->private_data;
149 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_PORT_INFO, info) < 0) {
150 /*SYSERR("SNDRV_SEQ_IOCTL_SET_PORT_INFO failed");*/
156 static int snd_seq_hw_get_port_subscription(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
158 snd_seq_hw_t *hw = seq->private_data;
159 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION, sub) < 0) {
160 /*SYSERR("SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION failed");*/
166 static int snd_seq_hw_subscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
168 snd_seq_hw_t *hw = seq->private_data;
169 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, sub) < 0) {
170 /*SYSERR("SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT failed");*/
176 static int snd_seq_hw_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
178 snd_seq_hw_t *hw = seq->private_data;
179 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, sub) < 0) {
180 /*SYSERR("SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT failed");*/
186 static int snd_seq_hw_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subscribe_t * subs)
188 snd_seq_hw_t *hw = seq->private_data;
189 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_QUERY_SUBS, subs) < 0) {
190 /*SYSERR("SNDRV_SEQ_IOCTL_QUERY_SUBS failed");*/
196 static int snd_seq_hw_get_queue_status(snd_seq_t *seq, snd_seq_queue_status_t * status)
198 snd_seq_hw_t *hw = seq->private_data;
199 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS, status) < 0) {
200 /*SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS failed");*/
206 static int snd_seq_hw_get_queue_tempo(snd_seq_t *seq, snd_seq_queue_tempo_t * tempo)
208 snd_seq_hw_t *hw = seq->private_data;
209 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO, tempo) < 0) {
210 /*SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO failed");*/
216 static int snd_seq_hw_set_queue_tempo(snd_seq_t *seq, snd_seq_queue_tempo_t * tempo)
218 snd_seq_hw_t *hw = seq->private_data;
219 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, tempo) < 0) {
220 /*SYSERR("SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO failed");*/
226 static int snd_seq_hw_get_queue_timer(snd_seq_t *seq, snd_seq_queue_timer_t * timer)
228 snd_seq_hw_t *hw = seq->private_data;
229 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER, timer) < 0) {
230 /*SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER failed");*/
236 static int snd_seq_hw_set_queue_timer(snd_seq_t *seq, snd_seq_queue_timer_t * timer)
238 snd_seq_hw_t *hw = seq->private_data;
239 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER, timer) < 0) {
240 /*SYSERR("SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER failed");*/
246 static int snd_seq_hw_get_queue_client(snd_seq_t *seq, snd_seq_queue_client_t * info)
248 snd_seq_hw_t *hw = seq->private_data;
249 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT, info) < 0) {
250 /*SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT failed");*/
256 static int snd_seq_hw_set_queue_client(snd_seq_t *seq, snd_seq_queue_client_t * info)
258 snd_seq_hw_t *hw = seq->private_data;
259 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT, info) < 0) {
260 /*SYSERR("SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT failed");*/
266 static int snd_seq_hw_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info)
268 snd_seq_hw_t *hw = seq->private_data;
269 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_CREATE_QUEUE, info) < 0) {
270 /*SYSERR("SNDRV_SEQ_IOCTL_CREATE_QUEUE failed");*/
276 static int snd_seq_hw_delete_queue(snd_seq_t *seq, snd_seq_queue_info_t *info)
278 snd_seq_hw_t *hw = seq->private_data;
279 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_DELETE_QUEUE, info) < 0) {
280 /*SYSERR("SNDRV_SEQ_IOCTL_DELETE_QUEUE failed");*/
286 static int snd_seq_hw_get_queue_info(snd_seq_t *seq, snd_seq_queue_info_t *info)
288 snd_seq_hw_t *hw = seq->private_data;
289 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_QUEUE_INFO, info) < 0) {
290 /*SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_INFO failed");*/
296 static int snd_seq_hw_set_queue_info(snd_seq_t *seq, snd_seq_queue_info_t *info)
298 snd_seq_hw_t *hw = seq->private_data;
299 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_QUEUE_INFO, info) < 0) {
300 /*SYSERR("SNDRV_SEQ_IOCTL_SET_QUEUE_INFO failed");*/
306 static int snd_seq_hw_get_named_queue(snd_seq_t *seq, snd_seq_queue_info_t *info)
308 snd_seq_hw_t *hw = seq->private_data;
309 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE, info) < 0) {
310 /*SYSERR("SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE failed");*/
316 static ssize_t snd_seq_hw_write(snd_seq_t *seq, void *buf, size_t len)
318 snd_seq_hw_t *hw = seq->private_data;
319 ssize_t result = write(hw->fd, buf, len);
325 static ssize_t snd_seq_hw_read(snd_seq_t *seq, void *buf, size_t len)
327 snd_seq_hw_t *hw = seq->private_data;
328 ssize_t result = read(hw->fd, buf, len);
334 static int snd_seq_hw_remove_events(snd_seq_t *seq, snd_seq_remove_events_t *rmp)
336 snd_seq_hw_t *hw = seq->private_data;
337 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_REMOVE_EVENTS, rmp) < 0) {
338 /*SYSERR("SNDRV_SEQ_IOCTL_REMOVE_EVENTS failed");*/
344 static int snd_seq_hw_get_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
346 snd_seq_hw_t *hw = seq->private_data;
347 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, info) < 0) {
348 /*SYSERR("SNDRV_SEQ_IOCTL_GET_CLIENT_POOL failed");*/
354 static int snd_seq_hw_set_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
356 snd_seq_hw_t *hw = seq->private_data;
357 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, info) < 0) {
358 /*SYSERR("SNDRV_SEQ_IOCTL_SET_CLIENT_POOL failed");*/
364 static int snd_seq_hw_query_next_client(snd_seq_t *seq, snd_seq_client_info_t *info)
366 snd_seq_hw_t *hw = seq->private_data;
367 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, info) < 0) {
368 /*SYSERR("SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT failed");*/
374 static int snd_seq_hw_query_next_port(snd_seq_t *seq, snd_seq_port_info_t *info)
376 snd_seq_hw_t *hw = seq->private_data;
377 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, info) < 0) {
378 /*SYSERR("SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT failed");*/
384 static const snd_seq_ops_t snd_seq_hw_ops = {
385 .close = snd_seq_hw_close,
386 .nonblock = snd_seq_hw_nonblock,
387 .system_info = snd_seq_hw_system_info,
388 .get_client_info = snd_seq_hw_get_client_info,
389 .set_client_info = snd_seq_hw_set_client_info,
390 .create_port = snd_seq_hw_create_port,
391 .delete_port = snd_seq_hw_delete_port,
392 .get_port_info = snd_seq_hw_get_port_info,
393 .set_port_info = snd_seq_hw_set_port_info,
394 .get_port_subscription = snd_seq_hw_get_port_subscription,
395 .subscribe_port = snd_seq_hw_subscribe_port,
396 .unsubscribe_port = snd_seq_hw_unsubscribe_port,
397 .query_port_subscribers = snd_seq_hw_query_port_subscribers,
398 .get_queue_status = snd_seq_hw_get_queue_status,
399 .get_queue_tempo = snd_seq_hw_get_queue_tempo,
400 .set_queue_tempo = snd_seq_hw_set_queue_tempo,
401 .get_queue_timer = snd_seq_hw_get_queue_timer,
402 .set_queue_timer = snd_seq_hw_set_queue_timer,
403 .get_queue_client = snd_seq_hw_get_queue_client,
404 .set_queue_client = snd_seq_hw_set_queue_client,
405 .create_queue = snd_seq_hw_create_queue,
406 .delete_queue = snd_seq_hw_delete_queue,
407 .get_queue_info = snd_seq_hw_get_queue_info,
408 .set_queue_info = snd_seq_hw_set_queue_info,
409 .get_named_queue = snd_seq_hw_get_named_queue,
410 .write = snd_seq_hw_write,
411 .read = snd_seq_hw_read,
412 .remove_events = snd_seq_hw_remove_events,
413 .get_client_pool = snd_seq_hw_get_client_pool,
414 .set_client_pool = snd_seq_hw_set_client_pool,
415 .query_next_client = snd_seq_hw_query_next_client,
416 .query_next_port = snd_seq_hw_query_next_port,
419 int snd_seq_hw_open(snd_seq_t **handle, const char *name, int streams, int mode)
421 int fd, ver, client, fmode, ret;
422 const char *filename;
429 case SND_SEQ_OPEN_OUTPUT:
432 case SND_SEQ_OPEN_INPUT:
435 case SND_SEQ_OPEN_DUPLEX:
443 if (mode & SND_SEQ_NONBLOCK)
446 filename = SNDRV_FILE_SEQ;
447 fd = snd_open_device(filename, fmode);
450 fd = snd_open_device(SNDRV_FILE_ALOADSEQ, fmode);
453 fd = snd_open_device(filename, fmode);
457 SYSERR("open %s failed", filename);
460 if (ioctl(fd, SNDRV_SEQ_IOCTL_PVERSION, &ver) < 0) {
461 SYSERR("SNDRV_SEQ_IOCTL_PVERSION failed");
466 if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_SEQ_VERSION_MAX)) {
468 return -SND_ERROR_INCOMPATIBLE_VERSION;
470 hw = calloc(1, sizeof(snd_seq_hw_t));
476 seq = calloc(1, sizeof(snd_seq_t));
483 if (streams & SND_SEQ_OPEN_OUTPUT) {
484 seq->obuf = (char *) malloc(seq->obufsize = SND_SEQ_OBUF_SIZE);
492 if (streams & SND_SEQ_OPEN_INPUT) {
493 seq->ibuf = (snd_seq_event_t *) calloc(sizeof(snd_seq_event_t), seq->ibufsize = SND_SEQ_IBUF_SIZE);
503 seq->name = strdup(name);
504 seq->type = SND_SEQ_TYPE_HW;
505 seq->streams = streams;
510 seq->ops = &snd_seq_hw_ops;
511 seq->private_data = hw;
512 client = snd_seq_hw_client_id(seq);
517 seq->client = client;
519 #ifdef SNDRV_SEQ_IOCTL_RUNNING_MODE
521 struct snd_seq_running_info run_mode;
522 /* check running mode */
523 memset(&run_mode, 0, sizeof(run_mode));
524 run_mode.client = client;
525 #ifdef SNDRV_BIG_ENDIAN
526 run_mode.big_endian = 1;
528 run_mode.big_endian = 0;
530 run_mode.cpu_mode = sizeof(long);
531 ioctl(fd, SNDRV_SEQ_IOCTL_RUNNING_MODE, &run_mode);
539 int _snd_seq_hw_open(snd_seq_t **handlep, char *name,
540 snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf,
541 int streams, int mode)
543 snd_config_iterator_t i, next;
544 snd_config_for_each(i, next, conf) {
545 snd_config_t *n = snd_config_iterator_entry(i);
547 if (snd_config_get_id(n, &id) < 0)
549 if (strcmp(id, "comment") == 0)
551 if (strcmp(id, "type") == 0)
555 return snd_seq_hw_open(handlep, name, streams, mode);
557 SND_DLSYM_BUILD_VERSION(_snd_seq_hw_open, SND_SEQ_DLSYM_VERSION);