source: roaraudio/libroaross/libroaross.c @ 3143:5a5427b1a757

Last change on this file since 3143:5a5427b1a757 was 3143:5a5427b1a757, checked in by phi, 14 years ago

wrote _open_file(), fixed _open_session()

File size: 7.5 KB
Line 
1//libroaross.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
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 "roaraudio.h"
36
37#if defined(ROAR_HAVE_OSS_BSD) || defined(ROAR_HAVE_OSS)
38#if defined(__OpenBSD__) || defined(__NetBSD__)
39#include <soundcard.h>
40#else
41#include <sys/soundcard.h>
42#endif
43#include <sys/ioctl.h>
44
45#ifdef ROAR_HAVE_H_SYS_TYPES
46#include <sys/types.h>
47#endif
48
49#ifdef ROAR_HAVE_H_FCNTL
50#include <fcntl.h>
51#endif
52
53#ifdef ROAR_HAVE_H_UNISTD
54#include <unistd.h>
55#endif
56
57#include <sys/stat.h>
58#include <dlfcn.h>
59
60#if defined(RTLD_NEXT)
61#define REAL_LIBC RTLD_NEXT
62#else
63#define REAL_LIBC ((void *) -1L)
64#endif
65
66#define _MAX_POINTER  8
67
68// handle type:
69#define HT_NONE       0
70#define HT_STREAM     1
71#define HT_MIXER      2
72
73struct session {
74 int refc;
75 struct roar_connection con;
76};
77
78static struct session _session = {.refc = 0};
79
80struct handle {
81 int refc; // refrence counter
82 struct session * session;
83 int type;
84 struct roar_stream    stream;
85 struct roar_vio_calls stream_vio;
86 int                   stream_opened;
87};
88
89static struct {
90 int     (*open)(const char *pathname, int flags, mode_t mode);
91 int     (*close)(int fd);
92 ssize_t (*write)(int fd, const void *buf, size_t count);
93 ssize_t (*read)(int fd, void *buf, size_t count);
94} _os;
95
96static struct pointer {
97 int fh;
98 struct handle * handle;
99} _ptr[_MAX_POINTER];
100
101static void _init_os (void) {
102 memset(&_os, 0, sizeof(_os));
103
104 _os.open  = dlsym(REAL_LIBC, "open");
105 _os.close = dlsym(REAL_LIBC, "close");
106 _os.write = dlsym(REAL_LIBC, "write");
107 _os.read  = dlsym(REAL_LIBC, "read");
108}
109
110static void _init_ptr (void) {
111 int i;
112
113 for (i = 0; i < _MAX_POINTER; i++) {
114  _ptr[i].fh = -1;
115 }
116}
117
118static void _init (void) {
119 static int inited = 0;
120
121 if ( !inited ) {
122  _init_os();
123  _init_ptr();
124  inited++;
125 }
126}
127
128static int _open_dummy (void) {
129 int p[2];
130
131 if ( pipe(p) == -1 )
132  return -1;
133
134 close(p[1]);
135
136 return p[0];
137}
138
139static struct session * _open_session (char * server, char * name) {
140 if ( _session.refc == 0 ) {
141
142  if ( name == NULL )
143   name = "libroaross client";
144
145  if ( roar_simple_connect(&(_session.con), server, name) == -1 )
146   return NULL;
147 }
148
149 _session.refc++;
150 return &_session;
151}
152
153static void _close_session(struct session * session) {
154 if ( session == NULL )
155  return;
156
157 session->refc--;
158
159 if ( session->refc == 0 ) {
160  roar_disconnect(&(session->con));
161 }
162}
163
164static struct handle * _open_handle(struct session * session) {
165 struct handle * handle;
166
167 if ( (handle = roar_mm_malloc(sizeof(struct handle))) == NULL )
168  return NULL;
169
170 memset(handle, 0, sizeof(struct handle));
171
172 handle->refc = 1;
173 handle->session = session;
174 session->refc++; // TODO: better warp this
175 handle->type = HT_NONE;
176 roar_stream_new_empty(&(handle->stream));
177
178 return handle;
179}
180
181static void _close_handle(struct handle * handle) {
182 if (handle == NULL)
183  return;
184
185 handle->refc--;
186
187 if ( handle->refc == 0 ) {
188  _close_session(handle->session);
189
190  if ( handle->stream_opened )
191   roar_vio_close(&(handle->stream_vio));
192
193  roar_mm_free(handle);
194 }
195}
196
197static int _open_stream (struct handle * handle) {
198  return -1;
199}
200
201static struct pointer * _get_pointer_by_fh (int fh) {
202 int i;
203
204 for (i = 0; i < _MAX_POINTER; i++) {
205  if ( _ptr[i].fh == fh )
206   return &(_ptr[i]);
207 }
208
209 return NULL;
210}
211
212static struct pointer * _open_pointer(struct handle * handle) {
213 struct pointer * ret = _get_pointer_by_fh(-1);
214
215 if ( ret == NULL )
216  return NULL;
217
218 if ( (ret->fh = _open_dummy()) == -1 )
219  return NULL;
220
221 ret->handle = handle;
222
223 return ret;
224}
225
226static void _close_pointer(struct pointer * pointer) {
227 if ( pointer == NULL )
228  return;
229
230 _os.close(pointer->fh);
231
232 pointer->fh = -1;
233
234 _close_handle(pointer->handle);
235}
236
237// -------------------------------------
238// central open function:
239// -------------------------------------
240
241static int _open_file (const char *pathname, int flags) {
242 struct session * session;
243 struct handle  * handle;
244 struct pointer * pointer;
245 struct {
246  char * prefix;
247  int type;
248 } * ptr = NULL, p[] = {
249  {"/dev/dsp", HT_STREAM},
250  {NULL, HT_NONE},
251 };
252 int i;
253
254 for (i = 0; p[i].prefix != NULL; i++) {
255  if ( !strcmp(pathname, p[i].prefix) ) {
256   ptr = &(p[i]);
257  }
258 }
259
260 if ( ptr == NULL )
261  return -2;
262
263 _os.write(1, "DOOF!\n", 6);
264
265 if ( (session = _open_session(NULL, NULL)) == NULL ) {
266  return -1;
267 }
268
269 if ( (handle = _open_handle(session)) == NULL ) {
270  _close_session(session);
271  return -1;
272 }
273
274 handle->type = ptr->type;
275
276 if ( (pointer = _open_pointer(handle)) == NULL ) {
277  _close_handle(handle);
278  return -1;
279 }
280
281 return pointer->fh;
282}
283
284// -------------------------------------
285// emulated functions follow:
286// -------------------------------------
287
288int     open(const char *pathname, int flags, ...) {
289 int     ret;
290 mode_t  mode = 0;
291 va_list args;
292
293 _init();
294
295 ret = _open_file(pathname, flags);
296
297 switch (ret) {
298  case -2:       // continue as normal, use _op.open()
299   break;
300  case -1:       // pass error to caller
301    return -1;
302   break;
303  default:       // return successfully opened pointer to caller
304    return ret;
305   break;
306 }
307
308 if (flags & O_CREAT) {
309  va_start(args, flags);
310  mode = va_arg(args, mode_t);
311  va_end(args);
312 }
313
314 return _os.open(pathname, flags, mode);
315}
316
317int     close(int fd) {
318 struct pointer * pointer;
319 _init();
320
321 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
322  _close_pointer(pointer);
323  return 0;
324 }
325
326 return _os.close(fd);
327}
328
329ssize_t write(int fd, const void *buf, size_t count) {
330 struct pointer * pointer;
331
332 _init();
333
334 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
335  if ( pointer->handle->type == HT_STREAM ) {
336   if ( pointer->handle->stream_opened == 0 ) {
337    if ( _open_stream(pointer->handle) == -1 ) {
338     errno = EIO;
339     return -1;
340    }
341   }
342   return roar_vio_write(&(pointer->handle->stream_vio), (char*)buf, count);
343  } else {
344   errno = EINVAL;
345   return -1;
346  }
347 }
348
349 return _os.write(fd, buf, count);
350}
351
352ssize_t read(int fd, void *buf, size_t count) {
353 struct pointer * pointer;
354
355 _init();
356
357 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
358  if ( pointer->handle->type == HT_STREAM ) {
359   if ( pointer->handle->stream_opened == 0 ) {
360    if ( _open_stream(pointer->handle) == -1 ) {
361     errno = EIO;
362     return -1;
363    }
364   }
365   return roar_vio_read(&(pointer->handle->stream_vio), buf, count);
366  } else {
367   errno = EINVAL;
368   return -1;
369  }
370 }
371
372 return _os.read(fd, buf, count);
373}
374
375#endif
376
377//ll
Note: See TracBrowser for help on using the repository browser.