]> code.delx.au - pulseaudio/blob - src/iochannel.c
add resampler
[pulseaudio] / src / iochannel.c
1 #include <stdlib.h>
2 #include <assert.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5
6 #include "iochannel.h"
7 #include "util.h"
8
9 struct iochannel {
10 int ifd, ofd;
11 struct pa_mainloop_api* mainloop;
12
13 void (*callback)(struct iochannel*io, void *userdata);
14 void*userdata;
15
16 int readable;
17 int writable;
18
19 int no_close;
20
21 void* input_source, *output_source;
22 };
23
24 static void enable_mainloop_sources(struct iochannel *io) {
25 assert(io);
26
27 if (io->input_source == io->output_source) {
28 enum pa_mainloop_api_io_events e = PA_MAINLOOP_API_IO_EVENT_NULL;
29 assert(io->input_source);
30
31 if (!io->readable)
32 e |= PA_MAINLOOP_API_IO_EVENT_INPUT;
33 if (!io->writable)
34 e |= PA_MAINLOOP_API_IO_EVENT_OUTPUT;
35
36 io->mainloop->enable_io(io->mainloop, io->input_source, e);
37 } else {
38 if (io->input_source)
39 io->mainloop->enable_io(io->mainloop, io->input_source, io->readable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_INPUT);
40 if (io->output_source)
41 io->mainloop->enable_io(io->mainloop, io->output_source, io->writable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_OUTPUT);
42 }
43 }
44
45 static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
46 struct iochannel *io = userdata;
47 int changed = 0;
48 assert(m && fd >= 0 && events && userdata);
49
50 if ((events & PA_MAINLOOP_API_IO_EVENT_INPUT) && !io->readable) {
51 io->readable = 1;
52 changed = 1;
53 assert(id == io->input_source);
54 }
55
56 if ((events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) && !io->writable) {
57 io->writable = 1;
58 changed = 1;
59 assert(id == io->output_source);
60 }
61
62 if (changed) {
63 enable_mainloop_sources(io);
64
65 if (io->callback)
66 io->callback(io, io->userdata);
67 }
68 }
69
70 struct iochannel* iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd) {
71 struct iochannel *io;
72 assert(m && (ifd >= 0 || ofd >= 0));
73
74 io = malloc(sizeof(struct iochannel));
75 io->ifd = ifd;
76 io->ofd = ofd;
77 io->mainloop = m;
78
79 io->userdata = NULL;
80 io->callback = NULL;
81 io->readable = 0;
82 io->writable = 0;
83 io->no_close = 0;
84
85 if (ifd == ofd) {
86 assert(ifd >= 0);
87 make_nonblock_fd(io->ifd);
88 io->input_source = io->output_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_BOTH, callback, io);
89 } else {
90
91 if (ifd >= 0) {
92 make_nonblock_fd(io->ifd);
93 io->input_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, io);
94 } else
95 io->input_source = NULL;
96
97 if (ofd >= 0) {
98 make_nonblock_fd(io->ofd);
99 io->output_source = m->source_io(m, ofd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, callback, io);
100 } else
101 io->output_source = NULL;
102 }
103
104 return io;
105 }
106
107 void iochannel_free(struct iochannel*io) {
108 assert(io);
109
110 if (!io->no_close) {
111 if (io->ifd >= 0)
112 close(io->ifd);
113 if (io->ofd >= 0 && io->ofd != io->ifd)
114 close(io->ofd);
115 }
116
117 if (io->input_source)
118 io->mainloop->cancel_io(io->mainloop, io->input_source);
119 if (io->output_source && (io->output_source != io->input_source))
120 io->mainloop->cancel_io(io->mainloop, io->output_source);
121
122 free(io);
123 }
124
125 int iochannel_is_readable(struct iochannel*io) {
126 assert(io);
127 return io->readable;
128 }
129
130 int iochannel_is_writable(struct iochannel*io) {
131 assert(io);
132 return io->writable;
133 }
134
135 ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l) {
136 ssize_t r;
137 assert(io && data && l && io->ofd >= 0);
138
139 if ((r = write(io->ofd, data, l)) >= 0) {
140 io->writable = 0;
141 enable_mainloop_sources(io);
142 }
143
144 return r;
145 }
146
147 ssize_t iochannel_read(struct iochannel*io, void*data, size_t l) {
148 ssize_t r;
149
150 assert(io && data && l && io->ifd >= 0);
151
152 if ((r = read(io->ifd, data, l)) >= 0) {
153 io->readable = 0;
154 enable_mainloop_sources(io);
155 }
156
157 return r;
158 }
159
160 void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochannel*io, void *userdata), void *userdata) {
161 assert(io);
162 io->callback = callback;
163 io->userdata = userdata;
164 }
165
166 void iochannel_set_noclose(struct iochannel*io, int b) {
167 assert(io);
168 io->no_close = b;
169 }
170
171 void iochannel_peer_to_string(struct iochannel*io, char*s, size_t l) {
172 assert(io && s && l);
173 peer_to_string(s, l, io->ifd);
174 }