Lines Matching defs:*
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
23 #include <fcntl.h>
24 #include <sys/ioctl.h>
25 #include "seq_local.h"
27 #ifndef PIC
28 /* entry for static linking */
29 const char *_snd_module_seq_hw = "";
30 #endif
32 #ifndef DOC_HIDDEN
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)
37 typedef struct {
38 int fd;
39 } snd_seq_hw_t;
40 #endif /* DOC_HIDDEN */
42 static int snd_seq_hw_close(snd_seq_t *seq)
44 snd_seq_hw_t *hw = seq->private_data;
45 int err = 0;
47 if (close(hw->fd)) {
48 err = -errno;
49 SYSERR("close failed\n");
51 free(hw);
52 return err;
55 static int snd_seq_hw_nonblock(snd_seq_t *seq, int nonblock)
57 snd_seq_hw_t *hw = seq->private_data;
58 long flags;
60 if ((flags = fcntl(hw->fd, F_GETFL)) < 0) {
61 SYSERR("F_GETFL failed");
62 return -errno;
64 if (nonblock)
65 flags |= O_NONBLOCK;
66 else
67 flags &= ~O_NONBLOCK;
68 if (fcntl(hw->fd, F_SETFL, flags) < 0) {
69 SYSERR("F_SETFL for O_NONBLOCK failed");
70 return -errno;
72 return 0;
75 static int snd_seq_hw_client_id(snd_seq_t *seq)
77 snd_seq_hw_t *hw = seq->private_data;
78 int client;
79 if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_CLIENT_ID, &client) < 0) {
80 SYSERR("SNDRV_SEQ_IOCTL_CLIENT_ID failed");
81 return -errno;
83 return client;
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");
91 return -errno;
93 return 0;
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");*/
101 return -errno;
103 return 0;
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");*/
111 return -errno;
113 return 0;
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");*/
121 return -errno;
123 return 0;
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");*/
131 return -errno;
133 return 0;
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");*/
141 return -errno;
143 return 0;
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");*/
151 return -errno;
153 return 0;
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");*/
161 return -errno;
163 return 0;
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");*/
171 return -errno;
173 return 0;
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");*/
181 return -errno;
183 return 0;
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");*/
191 return -errno;
193 return 0;
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");*/
201 return -errno;
203 return 0;
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");*/
211 return -errno;
213 return 0;
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");*/
221 return -errno;
223 return 0;
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");*/
231 return -errno;
233 return 0;
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");*/
241 return -errno;
243 return 0;
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");*/
251 return -errno;
253 return 0;
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");*/
261 return -errno;
263 return 0;
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");*/
271 return -errno;
273 return 0;
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");*/
281 return -errno;
283 return 0;
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");*/
291 return -errno;
293 return 0;
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");*/
301 return -errno;
303 return 0;
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");*/
311 return -errno;
313 return 0;
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);
320 if (result < 0)
321 return -errno;
322 return result;
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);
329 if (result < 0)
330 return -errno;
331 return result;
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");*/
339 return -errno;
341 return 0;
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");*/
349 return -errno;
351 return 0;
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");*/
359 return -errno;
361 return 0;
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");*/
369 return -errno;
371 return 0;
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");*/
379 return -errno;
381 return 0;
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;
423 snd_seq_t *seq;
424 snd_seq_hw_t *hw;
426 *handle = NULL;
428 switch (streams) {
429 case SND_SEQ_OPEN_OUTPUT:
430 fmode = O_WRONLY;
431 break;
432 case SND_SEQ_OPEN_INPUT:
433 fmode = O_RDONLY;
434 break;
435 case SND_SEQ_OPEN_DUPLEX:
436 fmode = O_RDWR;
437 break;
438 default:
439 assert(0);
440 return -EINVAL;
443 if (mode & SND_SEQ_NONBLOCK)
444 fmode |= O_NONBLOCK;
446 filename = SNDRV_FILE_SEQ;
447 fd = snd_open_device(filename, fmode);
448 #ifdef SUPPORT_ALOAD
449 if (fd < 0) {
450 fd = snd_open_device(SNDRV_FILE_ALOADSEQ, fmode);
451 if (fd >= 0)
452 close(fd);
453 fd = snd_open_device(filename, fmode);
455 #endif
456 if (fd < 0) {
457 SYSERR("open %s failed", filename);
458 return -errno;
460 if (ioctl(fd, SNDRV_SEQ_IOCTL_PVERSION, &ver) < 0) {
461 SYSERR("SNDRV_SEQ_IOCTL_PVERSION failed");
462 ret = -errno;
463 close(fd);
464 return ret;
466 if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_SEQ_VERSION_MAX)) {
467 close(fd);
468 return -SND_ERROR_INCOMPATIBLE_VERSION;
470 hw = calloc(1, sizeof(snd_seq_hw_t));
471 if (hw == NULL) {
472 close(fd);
473 return -ENOMEM;
476 seq = calloc(1, sizeof(snd_seq_t));
477 if (seq == NULL) {
478 free(hw);
479 close(fd);
480 return -ENOMEM;
482 hw->fd = fd;
483 if (streams & SND_SEQ_OPEN_OUTPUT) {
484 seq->obuf = (char *) malloc(seq->obufsize = SND_SEQ_OBUF_SIZE);
485 if (!seq->obuf) {
486 free(hw);
487 free(seq);
488 close(fd);
489 return -ENOMEM;
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);
494 if (!seq->ibuf) {
495 free(seq->obuf);
496 free(hw);
497 free(seq);
498 close(fd);
499 return -ENOMEM;
502 if (name)
503 seq->name = strdup(name);
504 seq->type = SND_SEQ_TYPE_HW;
505 seq->streams = streams;
506 seq->mode = mode;
507 seq->tmpbuf = NULL;
508 seq->tmpbufsize = 0;
509 seq->poll_fd = fd;
510 seq->ops = &snd_seq_hw_ops;
511 seq->private_data = hw;
512 client = snd_seq_hw_client_id(seq);
513 if (client < 0) {
514 snd_seq_close(seq);
515 return client;
516 } else
517 seq->client = client;
519 #ifdef SNDRV_SEQ_IOCTL_RUNNING_MODE
521 struct sndrv_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;
527 #else
528 run_mode.big_endian = 0;
529 #endif
530 run_mode.cpu_mode = sizeof(long);
531 ioctl(fd, SNDRV_SEQ_IOCTL_RUNNING_MODE, &run_mode);
533 #endif
535 *handle = seq;
536 return 0;
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);
546 const char *id;
547 if (snd_config_get_id(n, &id) < 0)
548 continue;
549 if (strcmp(id, "comment") == 0)
550 continue;
551 if (strcmp(id, "type") == 0)
552 continue;
553 return -EINVAL;
555 return snd_seq_hw_open(handlep, name, streams, mode);
557 SND_DLSYM_BUILD_VERSION(_snd_seq_hw_open, SND_SEQ_DLSYM_VERSION);