source: roaraudio/libroar/vio_pipe.c @ 1304:4c024e764410

Last change on this file since 1304:4c024e764410 was 1304:4c024e764410, checked in by phi, 15 years ago

added pipe impl. working for sockets at least and a simple test prog

File size: 5.9 KB
Line 
1//vio_pipe.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37int roar_vio_open_pipe (struct roar_vio_calls * s0, struct roar_vio_calls * s1, int type, int flags) {
38 struct roar_vio_pipe * self;
39 int                    rw = flags & (O_RDONLY|O_WRONLY|O_RDWR);
40
41 if ( s0 == NULL || s1 == NULL )
42  return -1;
43
44 if ( (self = malloc(sizeof(struct roar_vio_pipe))) == NULL )
45  return -1;
46
47 memset(self, 0, sizeof(struct roar_vio_pipe));
48
49 self->refcount = 2;
50 self->flags    = flags;
51
52 if ( type == ROAR_VIO_PIPE_TYPE_AUTO ) {
53#ifdef ROAR_TARGET_WIN32
54  type = ROAR_VIO_PIPE_TYPE_BUFFER;
55#else
56  type = ROAR_VIO_PIPE_TYPE_SOCKET;
57#endif
58 }
59
60 self->type     = type;
61
62 switch (type) {
63  case ROAR_VIO_PIPE_TYPE_BUFFER:
64    // no buffers need to be set up here,
65    // we handle the NULL pointer in the reader and writer func
66    free(self);
67    return -1;
68   break;
69  case ROAR_VIO_PIPE_TYPE_PIPE:
70    if ( rw == O_RDWR || rw == O_RDONLY )
71     if ( pipe(self->b.p) == -1 ) {
72      free(self);
73      return -1;
74     }
75    if ( rw == O_RDWR || rw == O_WRONLY )
76     if ( pipe((self->b.p) + 2) == -1 ) {
77      close(self->b.p[0]);
78      close(self->b.p[1]);
79      free(self);
80      return -1;
81     }
82   break;
83  case ROAR_VIO_PIPE_TYPE_SOCKET:
84    if ( socketpair(AF_UNIX, SOCK_STREAM, 0, self->b.p) == -1 ) {
85     free(self);
86     return -1;
87    }
88
89    if ( rw == O_RDONLY ) {
90     shutdown(self->b.p[0], SHUT_WR);
91     shutdown(self->b.p[1], SHUT_RD);
92    } else if ( rw == O_WRONLY ) {
93     shutdown(self->b.p[0], SHUT_RD);
94     shutdown(self->b.p[1], SHUT_WR);
95    }
96   break;
97  default:
98    free(self);
99    return -1;
100 }
101
102 roar_vio_pipe_init(s0, self, flags);
103 roar_vio_pipe_init(s1, self, flags);
104
105 self->s0 = s0;
106
107 return 0;
108}
109
110int roar_vio_pipe_init (struct roar_vio_calls * s,  struct roar_vio_pipe * self, int flags) {
111 if ( s == NULL || self == NULL )
112  return -1;
113
114 memset(s, 0, sizeof(struct roar_vio_calls));
115
116 s->close    = roar_vio_pipe_close;
117 s->read     = roar_vio_pipe_read;
118 s->write    = roar_vio_pipe_write;
119 s->nonblock = roar_vio_pipe_nonblock;
120 s->sync     = roar_vio_pipe_sync;
121
122 s->inst = (void*) self;
123
124 if ( flags & O_NONBLOCK ) {
125  roar_vio_pipe_nonblock(s, ROAR_SOCKET_NONBLOCK);
126 }
127
128 return 0;
129}
130
131int     roar_vio_pipe_close   (struct roar_vio_calls * vio) {
132 struct roar_vio_pipe * self;
133 int                    idx;
134
135 if ( vio == NULL )
136  return -1;
137
138 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
139  return -1;
140
141 self->refcount--;
142
143 switch (self->type) {
144  case ROAR_VIO_PIPE_TYPE_BUFFER:
145    // this will be a bit more complex as we need to change the flags, too.
146   break;
147  case ROAR_VIO_PIPE_TYPE_PIPE:
148   switch (ROAR_VIO_PIPE_S(self, vio)) {
149    case 0:
150      close(self->b.p[0]);
151      close(self->b.p[1]);
152      self->b.p[0] = -1;
153      self->b.p[1] = -1;
154     break;
155    case 1:
156      close(self->b.p[2]);
157      close(self->b.p[3]);
158      self->b.p[2] = -1;
159      self->b.p[3] = -1;
160     break;
161   }
162   break;
163  case ROAR_VIO_PIPE_TYPE_SOCKET:
164    close(self->b.p[idx = ROAR_VIO_PIPE_S(self, vio)]);
165    self->b.p[idx] = -1;
166   break;
167 }
168
169 if ( ! self->refcount ) {
170  free(self);
171 }
172
173 vio->inst = NULL;
174 return 0;
175}
176
177int     roar_vio_pipe_nonblock(struct roar_vio_calls * vio, int state) {
178 return -1;
179}
180
181int     roar_vio_pipe_sync    (struct roar_vio_calls * vio) {
182 // we may add fdatasync() calls here depending on the type
183 // but in general they should not be needed on pipes.
184 return 0;
185}
186
187ssize_t roar_vio_pipe_read    (struct roar_vio_calls * vio, void *buf, size_t count) {
188 struct roar_vio_pipe * self;
189
190 if ( vio == NULL )
191  return -1;
192
193 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
194  return -1;
195
196 switch (self->type) {
197  case ROAR_VIO_PIPE_TYPE_BUFFER:
198    // this will be a bit more complex as we need to check the flags, too.
199   break;
200  case ROAR_VIO_PIPE_TYPE_PIPE:
201    return read(self->b.p[ROAR_VIO_PIPE_S(self,vio)*2], buf, count);
202   break;
203  case ROAR_VIO_PIPE_TYPE_SOCKET:
204    return read(self->b.p[ROAR_VIO_PIPE_S(self,vio)], buf, count);
205   break;
206 }
207
208 return -1;
209}
210
211ssize_t roar_vio_pipe_write   (struct roar_vio_calls * vio, void *buf, size_t count) {
212 struct roar_vio_pipe * self;
213
214 if ( vio == NULL )
215  return -1;
216
217 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
218  return -1;
219
220 switch (self->type) {
221  case ROAR_VIO_PIPE_TYPE_BUFFER:
222    // this will be a bit more complex as we need to check the flags, too.
223   break;
224  case ROAR_VIO_PIPE_TYPE_PIPE:
225    return write(self->b.p[(ROAR_VIO_PIPE_S(self,vio)*2)+1], buf, count);
226   break;
227  case ROAR_VIO_PIPE_TYPE_SOCKET:
228    return write(self->b.p[ROAR_VIO_PIPE_S(self,vio)], buf, count);
229   break;
230 }
231
232 return -1;
233}
234
235//ll
Note: See TracBrowser for help on using the repository browser.