xref: /openbsd/usr.bin/sndiod/miofile.c (revision 898184e3)
1 /*	$OpenBSD: miofile.c,v 1.3 2012/11/30 22:26:34 ratchov Exp $	*/
2 /*
3  * Copyright (c) 2008-2012 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/types.h>
19 #include <sys/time.h>
20 
21 #include <poll.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sndio.h>
26 #include "defs.h"
27 #include "file.h"
28 #include "midi.h"
29 #include "miofile.h"
30 #include "utils.h"
31 
32 int  port_mio_pollfd(void *, struct pollfd *);
33 int  port_mio_revents(void *, struct pollfd *);
34 void port_mio_in(void *);
35 void port_mio_out(void *);
36 void port_mio_hup(void *);
37 
38 struct fileops port_mio_ops = {
39 	"mio",
40 	port_mio_pollfd,
41 	port_mio_revents,
42 	port_mio_in,
43 	port_mio_out,
44 	port_mio_hup
45 };
46 
47 int
48 port_mio_open(struct port *p)
49 {
50 	p->mio.hdl = mio_open(p->path, p->midi->mode, 1);
51 	if (p->mio.hdl == NULL)
52 		return 0;
53 	p->mio.file = file_new(&port_mio_ops, p, p->path, mio_nfds(p->mio.hdl));
54 	return 1;
55 }
56 
57 void
58 port_mio_close(struct port *p)
59 {
60 	file_del(p->mio.file);
61 	mio_close(p->mio.hdl);
62 }
63 
64 int
65 port_mio_pollfd(void *addr, struct pollfd *pfd)
66 {
67 	struct port *p = addr;
68 	struct midi *ep = p->midi;
69 	int events = 0;
70 
71 	if (ep->mode & MODE_MIDIIN)
72 		events |= POLLIN;
73 	if ((ep->mode & MODE_MIDIOUT) && ep->obuf.used > 0)
74 		events |= POLLOUT;
75 	return mio_pollfd(p->mio.hdl, pfd, events);
76 }
77 
78 int
79 port_mio_revents(void *addr, struct pollfd *pfd)
80 {
81 	struct port *p = addr;
82 
83 	return mio_revents(p->mio.hdl, pfd);
84 }
85 
86 void
87 port_mio_in(void *arg)
88 {
89 	unsigned char data[MIDI_BUFSZ];
90 	struct port *p = arg;
91 	struct midi *ep = p->midi;
92 	int n;
93 
94 	for (;;) {
95 		n = mio_read(p->mio.hdl, data, MIDI_BUFSZ);
96 		if (n == 0)
97 			break;
98 		midi_in(ep, data, n);
99 	}
100 }
101 
102 void
103 port_mio_out(void *arg)
104 {
105 	struct port *p = arg;
106 	struct midi *ep = p->midi;
107 	unsigned char *data;
108 	int n, count;
109 
110 	for (;;) {
111 		data = abuf_rgetblk(&ep->obuf, &count);
112 		if (count == 0)
113 			break;
114 		n = mio_write(p->mio.hdl, data, count);
115 		if (n == 0)
116 			break;
117 		abuf_rdiscard(&ep->obuf, n);
118 		if (n < count)
119 			break;
120 	}
121 	if (p->state == PORT_DRAIN && ep->obuf.used == 0)
122 		port_close(p);
123 	midi_fill(ep);
124 }
125 
126 void
127 port_mio_hup(void *arg)
128 {
129 	struct port *p = arg;
130 
131 	port_close(p);
132 }
133