xref: /openbsd/lib/libsndio/mio.c (revision 7207b069)
1 /*	$OpenBSD: mio.c,v 1.14 2012/04/11 06:05:43 ratchov Exp $	*/
2 /*
3  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/types.h>
20 #include <sys/time.h>
21 #include <sys/stat.h>
22 
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <poll.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 
31 #include "debug.h"
32 #include "mio_priv.h"
33 
34 struct mio_hdl *
35 mio_open(const char *str, unsigned int mode, int nbio)
36 {
37 	struct mio_hdl *hdl;
38 	const char *p;
39 
40 #ifdef DEBUG
41 	sndio_debug_init();
42 #endif
43 	if ((mode & (MIO_OUT | MIO_IN)) == 0)
44 		return NULL;
45 	if (str == NULL && !issetugid())
46 		str = getenv("MIDIDEVICE");
47 	if (str == NULL) {
48 		hdl = mio_aucat_open("/0", mode, nbio, 1);
49 		if (hdl != NULL)
50 			return hdl;
51 		return mio_rmidi_open("/0", mode, nbio);
52 	}
53 	if ((p = sndio_parsetype(str, "snd")) != NULL ||
54 	    (p = sndio_parsetype(str, "aucat")) != NULL)
55 		return mio_aucat_open(p, mode, nbio, 0);
56 	if ((p = sndio_parsetype(str, "midithru")) != NULL)
57 		return mio_aucat_open(p, mode, nbio, 1);
58 	if ((p = sndio_parsetype(str, "rmidi")) != NULL)
59 		return mio_rmidi_open(p, mode, nbio);
60 	DPRINTF("mio_open: %s: unknown device type\n", str);
61 	return NULL;
62 }
63 
64 void
65 mio_create(struct mio_hdl *hdl, struct mio_ops *ops,
66     unsigned int mode, int nbio)
67 {
68 	hdl->ops = ops;
69 	hdl->mode = mode;
70 	hdl->nbio = nbio;
71 	hdl->eof = 0;
72 }
73 
74 void
75 mio_close(struct mio_hdl *hdl)
76 {
77 	hdl->ops->close(hdl);
78 }
79 
80 size_t
81 mio_read(struct mio_hdl *hdl, void *buf, size_t len)
82 {
83 	if (hdl->eof) {
84 		DPRINTF("mio_read: eof\n");
85 		return 0;
86 	}
87 	if (!(hdl->mode & MIO_IN)) {
88 		DPRINTF("mio_read: not input device\n");
89 		hdl->eof = 1;
90 		return 0;
91 	}
92 	if (len == 0) {
93 		DPRINTF("mio_read: zero length read ignored\n");
94 		return 0;
95 	}
96 	return hdl->ops->read(hdl, buf, len);
97 }
98 
99 size_t
100 mio_write(struct mio_hdl *hdl, const void *buf, size_t len)
101 {
102 	if (hdl->eof) {
103 		DPRINTF("mio_write: eof\n");
104 		return 0;
105 	}
106 	if (!(hdl->mode & MIO_OUT)) {
107 		DPRINTF("mio_write: not output device\n");
108 		hdl->eof = 1;
109 		return 0;
110 	}
111 	if (len == 0) {
112 		DPRINTF("mio_write: zero length write ignored\n");
113 		return 0;
114 	}
115 	return hdl->ops->write(hdl, buf, len);
116 }
117 
118 int
119 mio_nfds(struct mio_hdl *hdl)
120 {
121 	return 1;
122 }
123 
124 int
125 mio_pollfd(struct mio_hdl *hdl, struct pollfd *pfd, int events)
126 {
127 	if (hdl->eof)
128 		return 0;
129 	return hdl->ops->pollfd(hdl, pfd, events);
130 }
131 
132 int
133 mio_revents(struct mio_hdl *hdl, struct pollfd *pfd)
134 {
135 	if (hdl->eof)
136 		return POLLHUP;
137 	return hdl->ops->revents(hdl, pfd);
138 }
139 
140 int
141 mio_eof(struct mio_hdl *hdl)
142 {
143 	return hdl->eof;
144 }
145