Record support.
[profile/ivi/pulseaudio.git] / src / utils / padsp.c
1 /* $Id$ */
2
3 /***
4   This file is part of polypaudio.
5  
6   polypaudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2 of the License,
9   or (at your option) any later version.
10  
11   polypaudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public License
17   along with polypaudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #ifdef _FILE_OFFSET_BITS
27 #undef _FILE_OFFSET_BITS
28 #endif
29
30 #ifndef _LARGEFILE64_SOURCE
31 #define _LARGEFILE64_SOURCE 1
32 #endif
33
34 #include <sys/soundcard.h>
35 #include <sys/ioctl.h>
36 #include <pthread.h>
37 #include <unistd.h>
38 #include <sys/socket.h>
39 #include <dlfcn.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <string.h>
43 #include <stdarg.h>
44 #include <stdio.h>
45 #include <signal.h>
46
47 #include <linux/sockios.h>
48
49 #include <polyp/polypaudio.h>
50 #include <polypcore/llist.h>
51 #include <polypcore/gccmacro.h>
52
53 typedef enum {
54     FD_INFO_MIXER,
55     FD_INFO_STREAM,
56 } fd_info_type_t;
57
58 typedef struct fd_info fd_info;
59
60 struct fd_info {
61     pthread_mutex_t mutex;
62     int ref;
63     int unusable;
64     
65     fd_info_type_t type;
66     int app_fd, thread_fd;
67
68     pa_sample_spec sample_spec;
69     size_t fragment_size;
70     unsigned n_fragments;
71
72     pa_threaded_mainloop *mainloop;
73     pa_context *context;
74     pa_stream *play_stream;
75     pa_stream *rec_stream;
76
77     pa_io_event *io_event;
78
79     void *buf;
80     size_t rec_offset;
81
82     int operation_success;
83
84     pa_cvolume sink_volume, source_volume;
85     uint32_t sink_index, source_index;
86     int volume_modify_count;
87     
88     PA_LLIST_FIELDS(fd_info);
89 };
90
91 static int dsp_drain(fd_info *i);
92 static void fd_info_remove_from_list(fd_info *i);
93
94 static pthread_mutex_t fd_infos_mutex = PTHREAD_MUTEX_INITIALIZER;
95 static pthread_mutex_t func_mutex = PTHREAD_MUTEX_INITIALIZER;
96
97 static PA_LLIST_HEAD(fd_info, fd_infos) = NULL;
98
99 static int (*_ioctl)(int, int, void*) = NULL;
100 static int (*_close)(int) = NULL;
101 static int (*_open)(const char *, int, mode_t) = NULL;
102 static FILE* (*_fopen)(const char *path, const char *mode) = NULL;
103 static int (*_open64)(const char *, int, mode_t) = NULL;
104 static FILE* (*_fopen64)(const char *path, const char *mode) = NULL;
105 static int (*_fclose)(FILE *f) = NULL;
106 static int (*_access)(const char *, int) = NULL;
107
108 /* dlsym() violates ISO C, so confide the breakage into this function to
109  * avoid warnings. */
110 typedef void (*fnptr)(void);
111 static inline fnptr dlsym_fn(void *handle, const char *symbol) {
112     return (fnptr) (long) dlsym(handle, symbol);
113 }
114
115 #define LOAD_IOCTL_FUNC() \
116 do { \
117     pthread_mutex_lock(&func_mutex); \
118     if (!_ioctl)  \
119         _ioctl = (int (*)(int, int, void*)) dlsym_fn(RTLD_NEXT, "ioctl"); \
120     pthread_mutex_unlock(&func_mutex); \
121 } while(0)
122
123 #define LOAD_OPEN_FUNC() \
124 do { \
125     pthread_mutex_lock(&func_mutex); \
126     if (!_open) \
127         _open = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open"); \
128     pthread_mutex_unlock(&func_mutex); \
129 } while(0)
130
131 #define LOAD_OPEN64_FUNC() \
132 do { \
133     pthread_mutex_lock(&func_mutex); \
134     if (!_open64) \
135         _open64 = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open64"); \
136     pthread_mutex_unlock(&func_mutex); \
137 } while(0)
138
139 #define LOAD_CLOSE_FUNC() \
140 do { \
141     pthread_mutex_lock(&func_mutex); \
142     if (!_close) \
143         _close = (int (*)(int)) dlsym_fn(RTLD_NEXT, "close"); \
144     pthread_mutex_unlock(&func_mutex); \
145 } while(0)
146
147 #define LOAD_ACCESS_FUNC() \
148 do { \
149     pthread_mutex_lock(&func_mutex); \
150     if (!_access) \
151         _access = (int (*)(const char*, int)) dlsym_fn(RTLD_NEXT, "access"); \
152     pthread_mutex_unlock(&func_mutex); \
153 } while(0)
154
155 #define LOAD_FOPEN_FUNC() \
156 do { \
157     pthread_mutex_lock(&func_mutex); \
158     if (!_fopen) \
159         _fopen = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen"); \
160     pthread_mutex_unlock(&func_mutex); \
161 } while(0)
162
163 #define LOAD_FOPEN64_FUNC() \
164 do { \
165     pthread_mutex_lock(&func_mutex); \
166     if (!_fopen64) \
167         _fopen64 = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen64"); \
168     pthread_mutex_unlock(&func_mutex); \
169 } while(0)
170
171 #define LOAD_FCLOSE_FUNC() \
172 do { \
173     pthread_mutex_lock(&func_mutex); \
174     if (!_fclose) \
175         _fclose = (int (*)(FILE *)) dlsym_fn(RTLD_NEXT, "fclose"); \
176     pthread_mutex_unlock(&func_mutex); \
177 } while(0)
178
179 #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \
180 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \
181     debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
182     goto label; \
183 } \
184 } while(0);
185
186 #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \
187 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
188     !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \
189     debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
190     goto label; \
191 } \
192 } while(0);
193
194 #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \
195 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
196     !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \
197     debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
198     goto label; \
199 } \
200 } while(0);
201
202 static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
203
204 #define DEBUG_LEVEL_ALWAYS              0
205 #define DEBUG_LEVEL_NORMAL              1
206 #define DEBUG_LEVEL_VERBOSE             2
207
208 static void debug(int level, const char *format, ...) {
209     va_list ap;
210     const char *dlevel_s;
211     int dlevel;
212
213     dlevel_s = getenv("PADSP_DEBUG");
214     if (!dlevel_s)
215         return;
216
217     dlevel = atoi(dlevel_s);
218
219     if (dlevel < level)
220         return;
221
222     va_start(ap, format);
223     vfprintf(stderr, format, ap);
224     va_end(ap);
225 }
226
227 static int padsp_disabled(void) {
228     static int *sym;
229     static int sym_resolved = 0;
230
231     /* If the current process has a symbol __padsp_disabled__ we use
232      * it to detect whether we should enable our stuff or not. A
233      * program needs to be compiled with -rdynamic for this to work!
234      * The symbol must be an int containing a three bit bitmask: bit 1
235      * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat
236      * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value
237      * of 7 disables padsp entirely. */
238     
239     pthread_mutex_lock(&func_mutex);
240     if (!sym_resolved) {
241         sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__");
242         sym_resolved = 1;
243
244     }
245     pthread_mutex_unlock(&func_mutex);
246
247     if (!sym)
248         return 0;
249     
250     return *sym;
251 }
252
253 static int dsp_cloak_enable(void) {
254     if (padsp_disabled() & 1)
255         return 0;
256     
257     if (getenv("PADSP_NO_DSP"))
258         return 0;
259
260     return 1;
261 }
262
263 static int sndstat_cloak_enable(void) {
264     if (padsp_disabled() & 2)
265         return 0;
266
267     if (getenv("PADSP_NO_SNDSTAT"))
268         return 0;
269
270     return 1;
271 }
272
273 static int mixer_cloak_enable(void) {
274     if (padsp_disabled() & 4)
275         return 0;
276
277     if (getenv("PADSP_NO_MIXER"))
278         return 0;
279
280     return 1;
281 }
282 static pthread_key_t recursion_key;
283
284 static void recursion_key_alloc(void) {
285     pthread_key_create(&recursion_key, NULL);
286 }
287
288 static int function_enter(void) {
289     /* Avoid recursive calls */
290     static pthread_once_t recursion_key_once = PTHREAD_ONCE_INIT;
291     pthread_once(&recursion_key_once, recursion_key_alloc);
292     
293     if (pthread_getspecific(recursion_key))
294         return 0;
295
296     pthread_setspecific(recursion_key, (void*) 1);
297     return 1;
298 }
299
300 static void function_exit(void) {
301     pthread_setspecific(recursion_key, NULL);
302 }
303
304 static void fd_info_free(fd_info *i) {
305     assert(i);
306
307     debug(DEBUG_LEVEL_NORMAL, __FILE__": freeing fd info (fd=%i)\n", i->app_fd);
308
309     dsp_drain(i);
310     
311     if (i->mainloop)
312         pa_threaded_mainloop_stop(i->mainloop);
313     
314     if (i->play_stream) {
315         pa_stream_disconnect(i->play_stream);
316         pa_stream_unref(i->play_stream);
317     }
318
319     if (i->rec_stream) {
320         pa_stream_disconnect(i->rec_stream);
321         pa_stream_unref(i->rec_stream);
322     }
323
324     if (i->context) {
325         pa_context_disconnect(i->context);
326         pa_context_unref(i->context);
327     }
328     
329     if (i->mainloop)
330         pa_threaded_mainloop_free(i->mainloop);
331
332     if (i->app_fd >= 0) {
333         LOAD_CLOSE_FUNC();
334         _close(i->app_fd);
335     }
336
337     if (i->thread_fd >= 0) {
338         LOAD_CLOSE_FUNC();
339         _close(i->thread_fd);
340     }
341
342     free(i->buf);
343
344     pthread_mutex_destroy(&i->mutex);
345     free(i);
346 }
347
348 static fd_info *fd_info_ref(fd_info *i) {
349     assert(i);
350     
351     pthread_mutex_lock(&i->mutex);
352     assert(i->ref >= 1);
353     i->ref++;
354
355     debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref++, now %i\n", i->ref);
356     pthread_mutex_unlock(&i->mutex);
357
358     return i;
359 }
360
361 static void fd_info_unref(fd_info *i) {
362     int r;
363     pthread_mutex_lock(&i->mutex);
364     assert(i->ref >= 1);
365     r = --i->ref;
366         debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref);
367     pthread_mutex_unlock(&i->mutex);
368
369     if (r <= 0)
370         fd_info_free(i);
371 }
372
373 static void context_state_cb(pa_context *c, void *userdata) {
374     fd_info *i = userdata;
375     assert(c);
376
377     switch (pa_context_get_state(c)) {
378         case PA_CONTEXT_READY:
379         case PA_CONTEXT_TERMINATED:
380         case PA_CONTEXT_FAILED:
381             pa_threaded_mainloop_signal(i->mainloop, 0);
382             break;
383
384         case PA_CONTEXT_UNCONNECTED:
385         case PA_CONTEXT_CONNECTING:
386         case PA_CONTEXT_AUTHORIZING:
387         case PA_CONTEXT_SETTING_NAME:
388             break;
389     }
390 }
391
392 static void reset_params(fd_info *i) {
393     assert(i);
394     
395     i->sample_spec.format = PA_SAMPLE_ULAW;
396     i->sample_spec.channels = 1;
397     i->sample_spec.rate = 8000;
398     i->fragment_size = 0;
399     i->n_fragments = 0;
400 }
401
402 static const char *client_name(char *buf, size_t n) {
403     char p[PATH_MAX];
404     const char *e;
405
406     if ((e = getenv("PADSP_CLIENT_NAME")))
407         return e;
408     
409     if (pa_get_binary_name(p, sizeof(p)))
410         snprintf(buf, n, "OSS Emulation[%s]", pa_path_get_filename(p));
411     else
412         snprintf(buf, n, "OSS");
413
414     return buf;
415 }
416
417 static const char *stream_name(void) {
418     const char *e;
419
420     if ((e = getenv("PADSP_STREAM_NAME")))
421         return e;
422
423     return "Audio Stream";
424 }
425
426 static void atfork_prepare(void) {
427     fd_info *i;
428
429     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() enter\n");
430     
431     function_enter();
432
433     pthread_mutex_lock(&fd_infos_mutex);
434
435     for (i = fd_infos; i; i = i->next) {
436         pthread_mutex_lock(&i->mutex);
437         pa_threaded_mainloop_lock(i->mainloop);
438     }
439
440     pthread_mutex_lock(&func_mutex);
441
442     
443     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n");
444 }
445
446 static void atfork_parent(void) {
447     fd_info *i;
448     
449     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() enter\n");
450
451     pthread_mutex_unlock(&func_mutex);
452
453     for (i = fd_infos; i; i = i->next) {
454         pa_threaded_mainloop_unlock(i->mainloop);
455         pthread_mutex_unlock(&i->mutex);
456     }
457
458     pthread_mutex_unlock(&fd_infos_mutex);
459
460     function_exit();
461     
462     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() exit\n");
463 }
464
465 static void atfork_child(void) {
466     fd_info *i;
467     
468     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() enter\n");
469
470     /* We do only the bare minimum to get all fds closed */
471     pthread_mutex_init(&func_mutex, NULL);
472     pthread_mutex_init(&fd_infos_mutex, NULL);
473     
474     for (i = fd_infos; i; i = i->next) {
475         pthread_mutex_init(&i->mutex, NULL);
476
477         if (i->context) {
478             pa_context_disconnect(i->context);
479             pa_context_unref(i->context);
480             i->context = NULL;
481         }
482
483         if (i->play_stream) {
484             pa_stream_unref(i->play_stream);
485             i->play_stream = NULL;
486         }
487
488         if (i->rec_stream) {
489             pa_stream_unref(i->rec_stream);
490             i->rec_stream = NULL;
491         }
492
493         if (i->app_fd >= 0) {
494             close(i->app_fd);
495             i->app_fd = -1;
496         }
497
498         if (i->thread_fd >= 0) {
499             close(i->thread_fd);
500             i->thread_fd = -1;
501         }
502
503         i->unusable = 1;
504     }
505
506     function_exit();
507
508     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() exit\n");
509 }
510
511 static void install_atfork(void) {
512     pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
513 }
514
515 static void stream_success_cb(pa_stream *s, int success, void *userdata) {
516     fd_info *i = userdata;
517
518     assert(s);
519     assert(i);
520
521     i->operation_success = success;
522     pa_threaded_mainloop_signal(i->mainloop, 0);
523 }
524
525 static void context_success_cb(pa_context *c, int success, void *userdata) {
526     fd_info *i = userdata;
527
528     assert(c);
529     assert(i);
530
531     i->operation_success = success;
532     pa_threaded_mainloop_signal(i->mainloop, 0);
533 }
534
535 static fd_info* fd_info_new(fd_info_type_t type, int *_errno) {
536     fd_info *i;
537     int sfds[2] = { -1, -1 };
538     char name[64];
539     static pthread_once_t install_atfork_once = PTHREAD_ONCE_INIT;
540
541     debug(DEBUG_LEVEL_NORMAL, __FILE__": fd_info_new()\n");
542
543     signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */
544
545     pthread_once(&install_atfork_once, install_atfork);
546     
547     if (!(i = malloc(sizeof(fd_info)))) {
548         *_errno = ENOMEM;
549         goto fail;
550     }
551
552     i->app_fd = i->thread_fd = -1;
553     i->type = type;
554
555     i->mainloop = NULL;
556     i->context = NULL;
557     i->play_stream = NULL;
558     i->rec_stream = NULL;
559     i->io_event = NULL;
560     pthread_mutex_init(&i->mutex, NULL);
561     i->ref = 1;
562     i->buf = NULL;
563     i->rec_offset = 0;
564     i->unusable = 0;
565     pa_cvolume_reset(&i->sink_volume, 2);
566     pa_cvolume_reset(&i->source_volume, 2);
567     i->volume_modify_count = 0;
568     i->sink_index = (uint32_t) -1;
569     i->source_index = (uint32_t) -1;
570     PA_LLIST_INIT(fd_info, i);
571
572     reset_params(i);
573
574     if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfds) < 0) {
575         *_errno = errno;
576         debug(DEBUG_LEVEL_NORMAL, __FILE__": socket() failed: %s\n", strerror(errno));
577         goto fail;
578     }
579
580     i->app_fd = sfds[0];
581     i->thread_fd = sfds[1];
582
583     if (!(i->mainloop = pa_threaded_mainloop_new())) {
584         *_errno = EIO;
585         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_new() failed\n");
586         goto fail;
587     }
588
589     if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), client_name(name, sizeof(name))))) {
590         *_errno = EIO;
591         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_new() failed\n");
592         goto fail;
593     }
594
595     pa_context_set_state_callback(i->context, context_state_cb, i);
596
597     if (pa_context_connect(i->context, NULL, 0, NULL) < 0) {
598         *_errno = ECONNREFUSED;
599         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
600         goto fail;
601     }
602
603     pa_threaded_mainloop_lock(i->mainloop);
604
605     if (pa_threaded_mainloop_start(i->mainloop) < 0) {
606         *_errno = EIO;
607         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_start() failed\n");
608         goto unlock_and_fail;
609     }
610
611     /* Wait until the context is ready */
612     pa_threaded_mainloop_wait(i->mainloop);
613
614     if (pa_context_get_state(i->context) != PA_CONTEXT_READY) {
615         *_errno = ECONNREFUSED;
616         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
617         goto unlock_and_fail;
618     }
619
620     pa_threaded_mainloop_unlock(i->mainloop);
621     return i;
622
623 unlock_and_fail:
624
625     pa_threaded_mainloop_unlock(i->mainloop);
626     
627 fail:
628
629     if (i)
630         fd_info_unref(i);
631     
632     return NULL;
633 }
634
635 static void fd_info_add_to_list(fd_info *i) {
636     assert(i);
637
638     pthread_mutex_lock(&fd_infos_mutex);
639     PA_LLIST_PREPEND(fd_info, fd_infos, i);
640     pthread_mutex_unlock(&fd_infos_mutex);
641
642     fd_info_ref(i);
643 }
644
645 static void fd_info_remove_from_list(fd_info *i) {
646     assert(i);
647
648     pthread_mutex_lock(&fd_infos_mutex);
649     PA_LLIST_REMOVE(fd_info, fd_infos, i);
650     pthread_mutex_unlock(&fd_infos_mutex);
651
652     fd_info_unref(i);
653 }
654
655 static fd_info* fd_info_find(int fd) {
656     fd_info *i;
657
658     pthread_mutex_lock(&fd_infos_mutex);
659     
660     for (i = fd_infos; i; i = i->next)
661         if (i->app_fd == fd && !i->unusable) {
662             fd_info_ref(i);
663             break;
664         }
665
666     pthread_mutex_unlock(&fd_infos_mutex);
667     
668     return i;
669 }
670
671 static void fix_metrics(fd_info *i) {
672     size_t fs;
673     char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
674
675     fs = pa_frame_size(&i->sample_spec);
676     i->fragment_size = (i->fragment_size/fs)*fs;
677
678     /* Number of fragments set? */
679     if (i->n_fragments < 2) {
680         if (i->fragment_size > 0) {
681             i->n_fragments = pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size;
682             if (i->n_fragments < 2)
683                 i->n_fragments = 2;
684         } else
685             i->n_fragments = 12;
686     }
687
688     /* Fragment size set? */
689     if (i->fragment_size <= 0) {
690         i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments;
691         if (i->fragment_size < 1024)
692             i->fragment_size = 1024;
693     }
694
695     debug(DEBUG_LEVEL_NORMAL, __FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec));
696     debug(DEBUG_LEVEL_NORMAL, __FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size);
697 }
698
699 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
700     fd_info *i = userdata;
701     assert(s);
702
703     if (i->io_event) {
704         pa_mainloop_api *api;
705         pa_io_event_flags_t flags;
706         size_t n;
707
708         api = pa_threaded_mainloop_get_api(i->mainloop);
709
710         flags = 0;
711
712         if (s == i->play_stream) {
713             n = pa_stream_writable_size(i->play_stream);
714             if (n == (size_t)-1) {
715                 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n",
716                     pa_strerror(pa_context_errno(i->context)));
717             }
718
719             if (n >= i->fragment_size)
720                 flags |= PA_IO_EVENT_INPUT;
721         }
722
723         if (s == i->rec_stream) {
724             n = pa_stream_readable_size(i->rec_stream);
725             if (n == (size_t)-1) {
726                 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n",
727                     pa_strerror(pa_context_errno(i->context)));
728             }
729
730             if (n >= i->fragment_size)
731                 flags |= PA_IO_EVENT_OUTPUT;
732         }
733
734         api->io_enable(i->io_event, flags);
735     }
736 }
737
738 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
739     fd_info *i = userdata;
740     assert(s);
741
742     pa_threaded_mainloop_signal(i->mainloop, 0);
743 }
744
745 static void fd_info_shutdown(fd_info *i) {
746     assert(i);
747
748     if (i->io_event) {
749         pa_mainloop_api *api;
750         api = pa_threaded_mainloop_get_api(i->mainloop);
751         api->io_free(i->io_event);
752         i->io_event = NULL;
753     }
754
755     if (i->thread_fd >= 0) {
756         close(i->thread_fd);
757         i->thread_fd = -1;
758     }
759 }
760
761 static int fd_info_copy_data(fd_info *i, int force) {
762     size_t n;
763     pa_io_event_flags_t flags;
764
765     if (!i->play_stream && !i->rec_stream)
766         return -1;
767
768     flags = 0;
769
770     if (i->play_stream) {
771         n = pa_stream_writable_size(i->play_stream);
772
773         if (n == (size_t)-1) {
774             debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n",
775                 pa_strerror(pa_context_errno(i->context)));
776             return -1;
777         }
778
779         while (n >= i->fragment_size || force) {
780             ssize_t r;
781
782             if (!i->buf) {
783                 if (!(i->buf = malloc(i->fragment_size))) {
784                     debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n");
785                     return -1;
786                 }
787             }
788
789             if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) {
790
791                 if (errno == EAGAIN)
792                     break;
793
794                 debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno));
795                 return -1;
796             }
797
798             if (pa_stream_write(i->play_stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) {
799                 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context)));
800                 return -1;
801             }
802
803             i->buf = NULL;
804
805             assert(n >= (size_t) r);
806             n -= r;
807         }
808
809         if (n >= i->fragment_size)
810             flags |= PA_IO_EVENT_INPUT;
811     }
812
813     if (i->rec_stream) {
814         n = pa_stream_readable_size(i->rec_stream);
815
816         if (n == (size_t)-1) {
817             debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n",
818                 pa_strerror(pa_context_errno(i->context)));
819             return -1;
820         }
821
822         while (n >= i->fragment_size || force) {
823             ssize_t r;
824             const void *data;
825             const char *buf;
826             size_t len;
827
828             if (pa_stream_peek(i->rec_stream, &data, &len) < 0) {
829                 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_peek(): %s\n", pa_strerror(pa_context_errno(i->context)));
830                 return -1;
831             }
832
833             if (!data)
834                 break;
835
836             buf = (const char*)data + i->rec_offset;
837
838             if ((r = write(i->thread_fd, buf, len - i->rec_offset)) <= 0) {
839
840                 if (errno == EAGAIN)
841                     break;
842
843                 debug(DEBUG_LEVEL_NORMAL, __FILE__": write(): %s\n", strerror(errno));
844                 return -1;
845             }
846
847             assert((size_t)r <= len - i->rec_offset);
848             i->rec_offset += r;
849
850             if (i->rec_offset == len) {
851                 if (pa_stream_drop(i->rec_stream) < 0) {
852                     debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i->context)));
853                     return -1;
854                 }
855                 i->rec_offset = 0;
856             }
857
858             assert(n >= (size_t) r);
859             n -= r;
860         }
861
862         if (n >= i->fragment_size)
863             flags |= PA_IO_EVENT_OUTPUT;
864     }
865
866     if (i->io_event) {
867         pa_mainloop_api *api;
868
869         api = pa_threaded_mainloop_get_api(i->mainloop);
870         api->io_enable(i->io_event, flags);
871     }
872
873     return 0;
874 }
875
876 static void stream_state_cb(pa_stream *s, void * userdata) {
877     fd_info *i = userdata;
878     assert(s);
879
880     switch (pa_stream_get_state(s)) {
881
882         case PA_STREAM_READY:
883             debug(DEBUG_LEVEL_NORMAL, __FILE__": stream established.\n");
884             break;
885             
886         case PA_STREAM_FAILED:
887             debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
888             fd_info_shutdown(i);
889             break;
890
891         case PA_STREAM_TERMINATED:
892         case PA_STREAM_UNCONNECTED:
893         case PA_STREAM_CREATING:
894             break;
895     }
896 }
897
898 static int create_playback_stream(fd_info *i) {
899     pa_buffer_attr attr;
900     int n;
901     
902     assert(i);
903
904     fix_metrics(i);
905
906     if (!(i->play_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) {
907         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
908         goto fail;
909     }
910
911     pa_stream_set_state_callback(i->play_stream, stream_state_cb, i);
912     pa_stream_set_write_callback(i->play_stream, stream_request_cb, i);
913     pa_stream_set_latency_update_callback(i->play_stream, stream_latency_update_cb, i);
914
915     memset(&attr, 0, sizeof(attr));
916     attr.maxlength = i->fragment_size * (i->n_fragments+1);
917     attr.tlength = i->fragment_size * i->n_fragments;
918     attr.prebuf = i->fragment_size;
919     attr.minreq = i->fragment_size;
920     
921     if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) {
922         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
923         goto fail;
924     }
925
926     n = i->fragment_size;
927     setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
928     n = i->fragment_size;
929     setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
930     
931     return 0;
932
933 fail:
934     return -1;
935 }
936
937 static int create_record_stream(fd_info *i) {
938     pa_buffer_attr attr;
939     int n;
940     
941     assert(i);
942
943     fix_metrics(i);
944
945     if (!(i->rec_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) {
946         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
947         goto fail;
948     }
949
950     pa_stream_set_state_callback(i->rec_stream, stream_state_cb, i);
951     pa_stream_set_read_callback(i->rec_stream, stream_request_cb, i);
952     pa_stream_set_latency_update_callback(i->rec_stream, stream_latency_update_cb, i);
953
954     memset(&attr, 0, sizeof(attr));
955     attr.maxlength = i->fragment_size * (i->n_fragments+1);
956     attr.fragsize = i->fragment_size;
957     
958     if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) {
959         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
960         goto fail;
961     }
962
963     n = i->fragment_size;
964     setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
965     n = i->fragment_size;
966     setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
967     
968     return 0;
969
970 fail:
971     return -1;
972 }
973
974 static void free_streams(fd_info *i) {
975     assert(i);
976
977     if (i->play_stream) {
978         pa_stream_disconnect(i->play_stream);
979         pa_stream_unref(i->play_stream);
980         i->play_stream = NULL;
981     }
982
983     if (i->rec_stream) {
984         pa_stream_disconnect(i->rec_stream);
985         pa_stream_unref(i->rec_stream);
986         i->rec_stream = NULL;
987     }
988 }
989
990 static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
991     fd_info *i = userdata;
992
993     pa_threaded_mainloop_signal(i->mainloop, 0);
994     
995     if (flags & PA_IO_EVENT_INPUT) {
996
997         if (!i->play_stream) {
998             if (create_playback_stream(i) < 0)
999                 goto fail;
1000         } else {
1001             if (fd_info_copy_data(i, 0) < 0)
1002                 goto fail;
1003         }
1004         
1005     } else if (flags & PA_IO_EVENT_OUTPUT) {
1006
1007         if (!i->rec_stream) {
1008             if (create_record_stream(i) < 0)
1009                 goto fail;
1010         } else {
1011             if (fd_info_copy_data(i, 0) < 0)
1012                 goto fail;
1013         }
1014
1015     } else if (flags & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR))
1016         goto fail;
1017
1018     return;
1019     
1020 fail:
1021     /* We can't do anything better than removing the event source */
1022     fd_info_shutdown(i);
1023 }
1024
1025 static int dsp_open(int flags, int *_errno) {
1026     fd_info *i;
1027     pa_mainloop_api *api;
1028     int ret;
1029     int f;
1030     pa_io_event_flags_t ioflags;
1031
1032     debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n");
1033
1034     if (!(i = fd_info_new(FD_INFO_STREAM, _errno)))
1035         return -1;
1036
1037     if ((flags & O_NONBLOCK) == O_NONBLOCK) {
1038         if ((f = fcntl(i->app_fd, F_GETFL)) >= 0)
1039             fcntl(i->app_fd, F_SETFL, f|O_NONBLOCK);
1040     }
1041     if ((f = fcntl(i->thread_fd, F_GETFL)) >= 0)
1042         fcntl(i->thread_fd, F_SETFL, f|O_NONBLOCK);
1043
1044     fcntl(i->app_fd, F_SETFD, FD_CLOEXEC);
1045     fcntl(i->thread_fd, F_SETFD, FD_CLOEXEC);
1046
1047     pa_threaded_mainloop_lock(i->mainloop);
1048     api = pa_threaded_mainloop_get_api(i->mainloop);
1049
1050     switch (flags & O_ACCMODE) {
1051     case O_RDONLY:
1052         ioflags = PA_IO_EVENT_OUTPUT;
1053         shutdown(i->thread_fd, SHUT_RD);
1054         shutdown(i->app_fd, SHUT_WR);
1055         break;
1056     case O_WRONLY:
1057         ioflags = PA_IO_EVENT_INPUT;
1058         shutdown(i->thread_fd, SHUT_WR);
1059         shutdown(i->app_fd, SHUT_RD);
1060         break;
1061     case O_RDWR:
1062         ioflags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT;
1063         break;
1064     default:
1065         return -1;
1066     }
1067
1068     if (!(i->io_event = api->io_new(api, i->thread_fd, ioflags, io_event_cb, i)))
1069         goto fail;
1070     
1071     pa_threaded_mainloop_unlock(i->mainloop);
1072
1073     debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd);
1074
1075     fd_info_add_to_list(i);
1076     ret = i->app_fd;
1077     fd_info_unref(i);
1078     
1079     return ret;
1080
1081 fail:
1082     pa_threaded_mainloop_unlock(i->mainloop);
1083
1084     if (i)
1085         fd_info_unref(i);
1086     
1087     *_errno = EIO;
1088
1089     debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() failed\n");
1090
1091     return -1;
1092 }
1093
1094 static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, void *userdata) {
1095     fd_info *i = userdata;
1096
1097     if (!si && eol < 0) {
1098         i->operation_success = 0;
1099         pa_threaded_mainloop_signal(i->mainloop, 0);
1100         return;
1101     }
1102
1103     if (eol)
1104         return;
1105
1106     if (!pa_cvolume_equal(&i->sink_volume, &si->volume))
1107         i->volume_modify_count++;
1108     
1109     i->sink_volume = si->volume;
1110     i->sink_index = si->index;
1111
1112     i->operation_success = 1;
1113     pa_threaded_mainloop_signal(i->mainloop, 0);
1114 }
1115
1116 static void source_info_cb(pa_context *context, const pa_source_info *si, int eol, void *userdata) {
1117     fd_info *i = userdata;
1118
1119     if (!si && eol < 0) {
1120         i->operation_success = 0;
1121         pa_threaded_mainloop_signal(i->mainloop, 0);
1122         return;
1123     }
1124
1125     if (eol)
1126         return;
1127
1128     if (!pa_cvolume_equal(&i->source_volume, &si->volume))
1129         i->volume_modify_count++;
1130     
1131     i->source_volume = si->volume;
1132     i->source_index = si->index;
1133
1134     i->operation_success = 1;
1135     pa_threaded_mainloop_signal(i->mainloop, 0);
1136 }
1137
1138 static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1139     fd_info *i = userdata;
1140     pa_operation *o = NULL;
1141
1142     if (i->sink_index != idx)
1143         return;
1144
1145     if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
1146         return;
1147
1148     if (!(o = pa_context_get_sink_info_by_index(i->context, i->sink_index, sink_info_cb, i))) {
1149         debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context)));
1150         return;
1151     }
1152
1153     pa_operation_unref(o);
1154 }
1155
1156 static int mixer_open(int flags, int *_errno) {
1157     fd_info *i;
1158     pa_operation *o = NULL;
1159     int ret;
1160
1161     debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n");
1162
1163     if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) 
1164         return -1;
1165     
1166     pa_threaded_mainloop_lock(i->mainloop);
1167
1168     pa_context_set_subscribe_callback(i->context, subscribe_cb, i);
1169     
1170     if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, context_success_cb, i))) {
1171         debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context)));
1172         *_errno = EIO;
1173         goto fail;
1174     }
1175
1176     i->operation_success = 0;
1177     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1178         pa_threaded_mainloop_wait(i->mainloop);
1179         CONTEXT_CHECK_DEAD_GOTO(i, fail);
1180     }
1181
1182     pa_operation_unref(o);
1183     o = NULL;
1184
1185     if (!i->operation_success) {
1186         debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context)));
1187         *_errno = EIO;
1188         goto fail;
1189     }
1190
1191     /* Get sink info */
1192
1193     if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) {
1194         debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context)));
1195         *_errno = EIO;
1196         goto fail;
1197     }
1198
1199     i->operation_success = 0;
1200     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1201         pa_threaded_mainloop_wait(i->mainloop);
1202         CONTEXT_CHECK_DEAD_GOTO(i, fail);
1203     }
1204
1205     pa_operation_unref(o);
1206     o = NULL;
1207
1208     if (!i->operation_success) {
1209         debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context)));
1210         *_errno = EIO;
1211         goto fail;
1212     }
1213
1214     /* Get source info */
1215
1216     if (!(o = pa_context_get_source_info_by_name(i->context, NULL, source_info_cb, i))) {
1217         debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context)));
1218         *_errno = EIO;
1219         goto fail;
1220     }
1221
1222     i->operation_success = 0;
1223     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1224         pa_threaded_mainloop_wait(i->mainloop);
1225         CONTEXT_CHECK_DEAD_GOTO(i, fail);
1226     }
1227
1228     pa_operation_unref(o);
1229     o = NULL;
1230
1231     if (!i->operation_success) {
1232         debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context)));
1233         *_errno = EIO;
1234         goto fail;
1235     }
1236
1237     pa_threaded_mainloop_unlock(i->mainloop);
1238
1239     debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd);
1240
1241     fd_info_add_to_list(i);
1242     ret = i->app_fd;
1243     fd_info_unref(i);
1244     
1245     return ret;
1246
1247 fail:
1248     if (o)
1249         pa_operation_unref(o);
1250
1251     pa_threaded_mainloop_unlock(i->mainloop);
1252
1253     if (i)
1254         fd_info_unref(i);
1255     
1256     *_errno = EIO;
1257
1258     debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() failed\n");
1259
1260     return -1;
1261 }
1262
1263 static int sndstat_open(int flags, int *_errno) {
1264     static const char sndstat[] =
1265         "Sound Driver:3.8.1a-980706 (Polypaudio Virtual OSS)\n"
1266         "Kernel: POSIX\n"
1267         "Config options: 0\n"
1268         "\n"
1269         "Installed drivers:\n"
1270         "Type 255: Polypaudio Virtual OSS\n"
1271         "\n"
1272         "Card config:\n"
1273         "Polypaudio Virtual OSS\n"
1274         "\n"
1275         "Audio devices:\n"
1276         "0: Polypaudio Virtual OSS\n"
1277         "\n"
1278         "Synth devices: NOT ENABLED IN CONFIG\n"
1279         "\n"
1280         "Midi devices:\n"
1281         "\n"
1282         "Timers:\n"
1283         "\n"
1284         "Mixers:\n"
1285         "0: Polypaudio Virtual OSS\n";
1286
1287     char fn[] = "/tmp/padsp-sndstat-XXXXXX";
1288     mode_t u;
1289     int fd = -1;
1290     int e;
1291
1292     debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n");
1293     
1294     if (flags != O_RDONLY && flags != (O_RDONLY|O_LARGEFILE)) {
1295         *_errno = EACCES;
1296         debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access!\n");
1297         goto fail;
1298     }
1299
1300     u = umask(0077);
1301     fd = mkstemp(fn);
1302     e = errno;
1303     umask(u);
1304
1305     if (fd < 0) {
1306         *_errno = e;
1307         debug(DEBUG_LEVEL_NORMAL, __FILE__": mkstemp() failed: %s\n", strerror(errno));
1308         goto fail;
1309     }
1310
1311     unlink(fn);
1312
1313     if (write(fd, sndstat, sizeof(sndstat) -1) != sizeof(sndstat)-1) {
1314         *_errno = errno;
1315         debug(DEBUG_LEVEL_NORMAL, __FILE__": write() failed: %s\n", strerror(errno));
1316         goto fail;
1317     }
1318
1319     if (lseek(fd, SEEK_SET, 0) < 0) {
1320         *_errno = errno;
1321         debug(DEBUG_LEVEL_NORMAL, __FILE__": lseek() failed: %s\n", strerror(errno));
1322         goto fail;
1323     }
1324
1325     return fd;
1326
1327 fail:
1328     if (fd >= 0)
1329         close(fd);
1330     return -1;
1331 }
1332
1333 int open(const char *filename, int flags, ...) {
1334     va_list args;
1335     mode_t mode = 0;
1336     int r, _errno = 0;
1337
1338     debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename);
1339
1340     va_start(args, flags);
1341     if (flags & O_CREAT)
1342         mode = va_arg(args, mode_t);
1343     va_end(args);
1344
1345     if (!function_enter()) {
1346         LOAD_OPEN_FUNC();
1347         return _open(filename, flags, mode);
1348     }
1349
1350     if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) {
1351         r = dsp_open(flags, &_errno);
1352     } else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) {
1353         r = mixer_open(flags, &_errno);
1354     } else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) {
1355         r = sndstat_open(flags, &_errno);
1356     } else {
1357         function_exit();
1358         LOAD_OPEN_FUNC();
1359         return _open(filename, flags, mode);
1360     }
1361
1362     function_exit();
1363     
1364     if (_errno)
1365         errno = _errno;
1366     
1367     return r;
1368 }
1369
1370 static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
1371     int ret = -1;
1372     
1373     switch (request) {
1374         case SOUND_MIXER_READ_DEVMASK :
1375             debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n");
1376
1377             *(int*) argp = SOUND_MASK_PCM | SOUND_MASK_IGAIN;
1378             break;
1379
1380         case SOUND_MIXER_READ_RECMASK :
1381             debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECMASK\n");
1382
1383             *(int*) argp = SOUND_MASK_IGAIN;
1384             break;
1385             
1386         case SOUND_MIXER_READ_STEREODEVS:
1387             debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n");
1388
1389             pa_threaded_mainloop_lock(i->mainloop);
1390             *(int*) argp = 0;
1391             if (i->sink_volume.channels > 1)
1392                 *(int*) argp |= SOUND_MASK_PCM;
1393             if (i->source_volume.channels > 1)
1394                 *(int*) argp |= SOUND_MASK_IGAIN;
1395             pa_threaded_mainloop_unlock(i->mainloop);
1396             
1397             break;
1398
1399         case SOUND_MIXER_READ_RECSRC:
1400             debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECSRC\n");
1401
1402             *(int*) argp = SOUND_MASK_IGAIN;
1403             break;
1404
1405         case SOUND_MIXER_WRITE_RECSRC:
1406             debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_RECSRC\n");
1407             break;
1408
1409         case SOUND_MIXER_READ_CAPS:
1410             debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_CAPS\n");
1411
1412             *(int*) argp = 0;
1413             break;
1414     
1415         case SOUND_MIXER_READ_PCM:
1416         case SOUND_MIXER_READ_IGAIN: {
1417             pa_cvolume *v;
1418
1419             if (request == SOUND_MIXER_READ_PCM)
1420                 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n");
1421             else
1422                 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_IGAIN\n");
1423
1424             pa_threaded_mainloop_lock(i->mainloop);
1425
1426             if (request == SOUND_MIXER_READ_PCM)
1427                 v = &i->sink_volume;
1428             else
1429                 v = &i->source_volume;
1430
1431             *(int*) argp =
1432                 ((v->values[0]*100/PA_VOLUME_NORM)) |
1433                 ((v->values[v->channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM)  << 8);
1434
1435             pa_threaded_mainloop_unlock(i->mainloop);
1436
1437             break;
1438         }
1439
1440         case SOUND_MIXER_WRITE_PCM:
1441         case SOUND_MIXER_WRITE_IGAIN: {
1442             pa_cvolume v, *pv;
1443
1444             if (request == SOUND_MIXER_READ_PCM)
1445                 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n");
1446             else
1447                 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_IGAIN\n");
1448
1449             pa_threaded_mainloop_lock(i->mainloop);
1450
1451             if (request == SOUND_MIXER_READ_PCM) {
1452                 v = i->sink_volume;
1453                 pv = &i->sink_volume;
1454             } else {
1455                 v = i->source_volume;
1456                 pv = &i->source_volume;
1457             }
1458
1459             pv->values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100;
1460             pv->values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100;
1461
1462             if (!pa_cvolume_equal(pv, &v)) {
1463                 pa_operation *o;
1464
1465                 if (request == SOUND_MIXER_READ_PCM)
1466                     o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, NULL, NULL);
1467                 else
1468                     o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, NULL, NULL);
1469
1470                 if (!o)
1471                     debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context)));
1472                 else {
1473
1474                     i->operation_success = 0;
1475                     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1476                         CONTEXT_CHECK_DEAD_GOTO(i, exit_loop);
1477                         
1478                         pa_threaded_mainloop_wait(i->mainloop);
1479                     }
1480                 exit_loop:
1481                     
1482                     if (!i->operation_success)
1483                         debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context)));
1484
1485                     pa_operation_unref(o);
1486                 }
1487                 
1488                 /* We don't wait for completion here */
1489                 i->volume_modify_count++;
1490             }
1491             
1492             pa_threaded_mainloop_unlock(i->mainloop);
1493             
1494             break;
1495         }
1496
1497         case SOUND_MIXER_INFO: {
1498             mixer_info *mi = argp;
1499
1500             debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_INFO\n");
1501
1502             memset(mi, 0, sizeof(mixer_info));
1503             strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id));
1504             strncpy(mi->name, "Polypaudio Virtual OSS", sizeof(mi->name));
1505             pa_threaded_mainloop_lock(i->mainloop);
1506             mi->modify_counter = i->volume_modify_count;
1507             pa_threaded_mainloop_unlock(i->mainloop);
1508             break;
1509         }
1510             
1511         default:
1512             debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);
1513
1514             *_errno = EINVAL;
1515             goto fail;
1516     }
1517
1518     ret = 0;
1519     
1520 fail:
1521     
1522     return ret;
1523 }
1524
1525 static int map_format(int *fmt, pa_sample_spec *ss) {
1526     
1527     switch (*fmt) {
1528         case AFMT_MU_LAW:
1529             ss->format = PA_SAMPLE_ULAW;
1530             break;
1531             
1532         case AFMT_A_LAW:
1533             ss->format = PA_SAMPLE_ALAW;
1534             break;
1535             
1536         case AFMT_S8:
1537             *fmt = AFMT_U8;
1538             /* fall through */
1539         case AFMT_U8:
1540             ss->format = PA_SAMPLE_U8;
1541             break;
1542             
1543         case AFMT_U16_BE:
1544             *fmt = AFMT_S16_BE;
1545             /* fall through */
1546         case AFMT_S16_BE:
1547             ss->format = PA_SAMPLE_S16BE;
1548             break;
1549             
1550         case AFMT_U16_LE:
1551             *fmt = AFMT_S16_LE;
1552             /* fall through */
1553         case AFMT_S16_LE:
1554             ss->format = PA_SAMPLE_S16LE;
1555             break;
1556             
1557         default:
1558             ss->format = PA_SAMPLE_S16NE;
1559             *fmt = AFMT_S16_NE;
1560             break;
1561     }
1562
1563     return 0;
1564 }
1565
1566 static int map_format_back(pa_sample_format_t format) {
1567     switch (format) {
1568         case PA_SAMPLE_S16LE: return AFMT_S16_LE;
1569         case PA_SAMPLE_S16BE: return AFMT_S16_BE;
1570         case PA_SAMPLE_ULAW: return AFMT_MU_LAW;
1571         case PA_SAMPLE_ALAW: return AFMT_A_LAW;
1572         case PA_SAMPLE_U8: return AFMT_U8;
1573         default:
1574             abort();
1575     }
1576 }
1577
1578 static int dsp_flush_fd(int fd) {
1579     int l;
1580
1581     if (ioctl(fd, SIOCINQ, &l) < 0) {
1582         debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno));
1583         return -1;
1584     }
1585
1586     while (l > 0) {
1587         char buf[1024];
1588         size_t k;
1589
1590         k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l;
1591         if (read(fd, buf, k) < 0)
1592             debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", strerror(errno));
1593         l -= k;
1594     }
1595
1596     return 0;
1597 }
1598
1599 static int dsp_flush_socket(fd_info *i) {
1600     int res = 0;
1601
1602     if ((i->thread_fd < 0) && (i->app_fd < 0))
1603         return -1;
1604
1605     if (i->thread_fd >= 0)
1606         res = dsp_flush_fd(i->thread_fd);
1607
1608     if (res < 0)
1609         return res;
1610
1611     if (i->app_fd >= 0)
1612         res = dsp_flush_fd(i->app_fd);
1613
1614     if (res < 0)
1615         return res;
1616
1617     return 0;
1618 }
1619
1620 static int dsp_empty_socket(fd_info *i) {
1621     int ret = -1;
1622     
1623     /* Empty the socket */
1624     for (;;) {
1625         int l;
1626         
1627         if (i->thread_fd < 0)
1628             break;
1629         
1630         if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) {
1631             debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno));
1632             break;
1633         }
1634
1635         if (!l) {
1636             ret = 0;
1637             break;
1638         }
1639         
1640         pa_threaded_mainloop_wait(i->mainloop);
1641     }
1642
1643     return ret;
1644 }
1645
1646 static int dsp_drain(fd_info *i) {
1647     pa_operation *o = NULL;
1648     int r = -1;
1649
1650     if (!i->mainloop)
1651         return 0;
1652     
1653     debug(DEBUG_LEVEL_NORMAL, __FILE__": Draining.\n");
1654
1655     pa_threaded_mainloop_lock(i->mainloop);
1656
1657     if (dsp_empty_socket(i) < 0)
1658         goto fail;
1659     
1660     if (!i->play_stream)
1661         goto fail;
1662
1663     debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n");
1664         
1665     if (!(o = pa_stream_drain(i->play_stream, stream_success_cb, i))) {
1666         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context)));
1667         goto fail;
1668     }
1669
1670     i->operation_success = 0;
1671     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1672         PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail);
1673             
1674         pa_threaded_mainloop_wait(i->mainloop);
1675     }
1676
1677     if (!i->operation_success) {
1678         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context)));
1679         goto fail;
1680     }
1681
1682     r = 0;
1683     
1684 fail:
1685     
1686     if (o)
1687         pa_operation_unref(o);
1688
1689     pa_threaded_mainloop_unlock(i->mainloop);
1690
1691     return 0;
1692 }
1693
1694 static int dsp_trigger(fd_info *i) {
1695     pa_operation *o = NULL;
1696     int r = -1;
1697
1698     if (!i->play_stream)
1699         return 0;
1700
1701     pa_threaded_mainloop_lock(i->mainloop);
1702
1703     if (dsp_empty_socket(i) < 0)
1704         goto fail;
1705
1706     debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n");
1707         
1708     if (!(o = pa_stream_trigger(i->play_stream, stream_success_cb, i))) {
1709         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context)));
1710         goto fail;
1711     }
1712
1713     i->operation_success = 0;
1714     while (!pa_operation_get_state(o) != PA_OPERATION_DONE) {
1715         PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail);
1716             
1717         pa_threaded_mainloop_wait(i->mainloop);
1718     }
1719
1720     if (!i->operation_success) {
1721         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context)));
1722         goto fail;
1723     }
1724
1725     r = 0;
1726     
1727 fail:
1728     
1729     if (o)
1730         pa_operation_unref(o);
1731
1732     pa_threaded_mainloop_unlock(i->mainloop);
1733
1734     return 0;
1735 }
1736
1737 static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
1738     int ret = -1;
1739     
1740     switch (request) {
1741         case SNDCTL_DSP_SETFMT: {
1742             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp);
1743             
1744             pa_threaded_mainloop_lock(i->mainloop);
1745
1746             if (*(int*) argp == AFMT_QUERY)
1747                 *(int*) argp = map_format_back(i->sample_spec.format);
1748             else {
1749                 map_format((int*) argp, &i->sample_spec);
1750                 free_streams(i);
1751             }
1752
1753             pa_threaded_mainloop_unlock(i->mainloop);
1754             break;
1755         }
1756             
1757         case SNDCTL_DSP_SPEED: {
1758             pa_sample_spec ss;
1759             int valid;
1760             char t[256];
1761             
1762             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp);
1763
1764             pa_threaded_mainloop_lock(i->mainloop);
1765
1766             ss = i->sample_spec;
1767             ss.rate = *(int*) argp;
1768
1769             if ((valid = pa_sample_spec_valid(&ss))) {
1770                 i->sample_spec = ss;
1771                 free_streams(i);
1772             }
1773             
1774             debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec));
1775
1776             pa_threaded_mainloop_unlock(i->mainloop);
1777
1778             if (!valid) {
1779                 *_errno = EINVAL;
1780                 goto fail;
1781             }
1782
1783             break;
1784         }
1785             
1786         case SNDCTL_DSP_STEREO:
1787             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp);
1788             
1789             pa_threaded_mainloop_lock(i->mainloop);
1790             
1791             i->sample_spec.channels = *(int*) argp ? 2 : 1;
1792             free_streams(i);
1793             
1794             pa_threaded_mainloop_unlock(i->mainloop);
1795             return 0;
1796
1797         case SNDCTL_DSP_CHANNELS: {
1798             pa_sample_spec ss;
1799             int valid;
1800             
1801             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp);
1802             
1803             pa_threaded_mainloop_lock(i->mainloop);
1804
1805             ss = i->sample_spec;
1806             ss.channels = *(int*) argp;
1807
1808             if ((valid = pa_sample_spec_valid(&ss))) {
1809                 i->sample_spec = ss;
1810                 free_streams(i);
1811             }
1812             
1813             pa_threaded_mainloop_unlock(i->mainloop);
1814
1815             if (!valid) {
1816                 *_errno = EINVAL;
1817                 goto fail;
1818             }
1819
1820             break;
1821         }
1822
1823         case SNDCTL_DSP_GETBLKSIZE:
1824             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETBLKSIZE\n");
1825
1826             pa_threaded_mainloop_lock(i->mainloop);
1827
1828             fix_metrics(i);
1829             *(int*) argp = i->fragment_size;
1830             
1831             pa_threaded_mainloop_unlock(i->mainloop);
1832             
1833             break;
1834
1835         case SNDCTL_DSP_SETFRAGMENT:
1836             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp);
1837             
1838             pa_threaded_mainloop_lock(i->mainloop);
1839             
1840             i->fragment_size = 1 << (*(int*) argp);
1841             i->n_fragments = (*(int*) argp) >> 16;
1842             
1843             free_streams(i);
1844             
1845             pa_threaded_mainloop_unlock(i->mainloop);
1846             
1847             break;
1848             
1849         case SNDCTL_DSP_GETCAPS:
1850             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n");
1851             
1852             *(int*)  argp = DSP_CAP_DUPLEX | DSP_CAP_MULTI;
1853             break;
1854
1855         case SNDCTL_DSP_GETODELAY: {
1856             int l;
1857             
1858             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n");
1859             
1860             pa_threaded_mainloop_lock(i->mainloop);
1861
1862             *(int*) argp = 0;
1863             
1864             for (;;) {
1865                 pa_usec_t usec;
1866
1867                 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop);
1868
1869                 if (pa_stream_get_latency(i->play_stream, &usec, NULL) >= 0) {
1870                     *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec);
1871                     break;
1872                 }
1873
1874                 if (pa_context_errno(i->context) != PA_ERR_NODATA) {
1875                     debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context)));
1876                     break;
1877                 }
1878
1879                 pa_threaded_mainloop_wait(i->mainloop);
1880             }
1881             
1882         exit_loop:
1883             
1884             if (ioctl(i->thread_fd, SIOCINQ, &l) < 0)
1885                 debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno));
1886             else
1887                 *(int*) argp += l;
1888
1889             pa_threaded_mainloop_unlock(i->mainloop);
1890
1891             debug(DEBUG_LEVEL_NORMAL, __FILE__": ODELAY: %i\n", *(int*) argp);
1892
1893             break;
1894         }
1895             
1896         case SNDCTL_DSP_RESET: {
1897             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_RESET\n");
1898             
1899             pa_threaded_mainloop_lock(i->mainloop);
1900
1901             free_streams(i);
1902             dsp_flush_socket(i);
1903             reset_params(i);
1904             
1905             pa_threaded_mainloop_unlock(i->mainloop);
1906             break;
1907         }
1908             
1909         case SNDCTL_DSP_GETFMTS: {
1910             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETFMTS\n");
1911             
1912             *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE;
1913             break;
1914         }
1915
1916         case SNDCTL_DSP_POST:
1917             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_POST\n");
1918             
1919             if (dsp_trigger(i) < 0) 
1920                 *_errno = EIO;
1921             break;
1922
1923         case SNDCTL_DSP_SYNC: 
1924             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n");
1925             
1926             if (dsp_drain(i) < 0) 
1927                 *_errno = EIO;
1928
1929             break;
1930
1931         case SNDCTL_DSP_GETOSPACE:
1932         case SNDCTL_DSP_GETISPACE: {
1933             audio_buf_info *bi = (audio_buf_info*) argp;
1934             int l;
1935             size_t k = 0;
1936
1937             if (request == SNDCTL_DSP_GETOSPACE)
1938                 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n");
1939             else
1940                 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETISPACE\n");
1941
1942             pa_threaded_mainloop_lock(i->mainloop);
1943
1944             fix_metrics(i);
1945
1946             if (request == SNDCTL_DSP_GETOSPACE) {
1947                 if (i->play_stream) {
1948                     if ((k = pa_stream_writable_size(i->play_stream)) == (size_t) -1)
1949                         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context)));
1950                 } else
1951                     k = i->fragment_size * i->n_fragments;
1952
1953                 if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) {
1954                     debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno));
1955                     l = 0;
1956                 }
1957
1958                 bi->bytes = k > (size_t) l ? k - l : 0;
1959             } else {
1960                 if (i->rec_stream) {
1961                     if ((k = pa_stream_readable_size(i->rec_stream)) == (size_t) -1)
1962                         debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i->context)));
1963                 } else
1964                     k = 0;
1965
1966                 if (ioctl(i->app_fd, SIOCINQ, &l) < 0) {
1967                     debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno));
1968                     l = 0;
1969                 }
1970
1971                 bi->bytes = k + l;
1972             }
1973
1974             bi->fragsize = i->fragment_size;
1975             bi->fragstotal = i->n_fragments;
1976             bi->fragments = bi->bytes / bi->fragsize;
1977
1978             pa_threaded_mainloop_unlock(i->mainloop);
1979
1980             debug(DEBUG_LEVEL_NORMAL, __FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments);
1981
1982             break;
1983         }
1984             
1985         default:
1986             debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);
1987
1988             *_errno = EINVAL;
1989             goto fail;
1990     }
1991
1992     ret = 0;
1993     
1994 fail:
1995     
1996     return ret;
1997 }
1998
1999 int ioctl(int fd, unsigned long request, ...) {
2000     fd_info *i;
2001     va_list args;
2002     void *argp;
2003     int r, _errno = 0;
2004
2005     debug(DEBUG_LEVEL_VERBOSE, __FILE__": ioctl()\n");
2006
2007     va_start(args, request);
2008     argp = va_arg(args, void *);
2009     va_end(args);
2010
2011     if (!function_enter()) {
2012         LOAD_IOCTL_FUNC();
2013         return _ioctl(fd, request, argp);
2014     }
2015
2016     if (!(i = fd_info_find(fd))) {
2017         function_exit();
2018         LOAD_IOCTL_FUNC();
2019         return _ioctl(fd, request, argp);
2020     }
2021
2022     if (i->type == FD_INFO_MIXER)
2023         r = mixer_ioctl(i, request, argp, &_errno);
2024     else
2025         r = dsp_ioctl(i, request, argp, &_errno);
2026     
2027     fd_info_unref(i);
2028
2029     if (_errno)
2030         errno = _errno;
2031
2032     function_exit();
2033     
2034     return r;
2035 }
2036
2037 int close(int fd) {
2038     fd_info *i;
2039
2040     debug(DEBUG_LEVEL_VERBOSE, __FILE__": close()\n");
2041
2042     if (!function_enter()) {
2043         LOAD_CLOSE_FUNC();
2044         return _close(fd);
2045     }
2046
2047     if (!(i = fd_info_find(fd))) {
2048         function_exit();
2049         LOAD_CLOSE_FUNC();
2050         return _close(fd);
2051     }
2052
2053     fd_info_remove_from_list(i);
2054     fd_info_unref(i);
2055     
2056     function_exit();
2057
2058     return 0;
2059 }
2060
2061 int access(const char *pathname, int mode) {
2062     debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname);
2063
2064     if (strcmp(pathname, "/dev/dsp") != 0 &&
2065         strcmp(pathname, "/dev/adsp") != 0 &&
2066         strcmp(pathname, "/dev/sndstat") != 0 &&
2067         strcmp(pathname, "/dev/mixer") != 0) {
2068         LOAD_ACCESS_FUNC();
2069         return _access(pathname, mode);
2070     }
2071
2072     if (mode & (W_OK | X_OK)) {
2073         debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = EACCESS\n", pathname, mode);
2074         errno = EACCES;
2075         return -1;
2076     }
2077
2078     debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = OK\n", pathname, mode);
2079
2080     return 0;
2081 }
2082
2083 int open64(const char *filename, int flags, ...) {
2084     va_list args;
2085     mode_t mode = 0;
2086
2087     debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename);
2088     
2089     va_start(args, flags);
2090     if (flags & O_CREAT)
2091         mode = va_arg(args, mode_t);
2092     va_end(args);
2093
2094     if (strcmp(filename, "/dev/dsp") != 0 &&
2095         strcmp(filename, "/dev/adsp") != 0 &&
2096         strcmp(filename, "/dev/sndstat") != 0 &&
2097         strcmp(filename, "/dev/mixer") != 0) {
2098         LOAD_OPEN64_FUNC();
2099         return _open64(filename, flags, mode);
2100     }
2101
2102     return open(filename, flags, mode);
2103 }
2104
2105 FILE* fopen(const char *filename, const char *mode) {
2106     FILE *f = NULL;
2107     int fd;
2108     mode_t m;
2109     
2110     debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename);
2111
2112     if (strcmp(filename, "/dev/dsp") != 0 &&
2113         strcmp(filename, "/dev/adsp") != 0 &&
2114         strcmp(filename, "/dev/sndstat") != 0 &&
2115         strcmp(filename, "/dev/mixer") != 0) {
2116         LOAD_FOPEN_FUNC();
2117         return _fopen(filename, mode);
2118     }
2119
2120     switch (mode[0]) {
2121     case 'r':
2122         m = O_RDONLY;
2123         break;
2124     case 'w':
2125     case 'a':
2126         m = O_WRONLY;
2127         break;
2128     default:
2129         errno = EINVAL;
2130         return NULL;
2131     }
2132
2133     if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+'))
2134         m = O_RDWR;
2135
2136     if ((fd = open(filename, m)) < 0)
2137         return NULL;
2138
2139     if (!(f = fdopen(fd, mode))) {
2140         close(fd);
2141         return NULL;
2142     }
2143     
2144     return f;
2145 }
2146
2147 FILE *fopen64(const char *filename, const char *mode) {
2148
2149     debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename);
2150
2151     if (strcmp(filename, "/dev/dsp") != 0 &&
2152         strcmp(filename, "/dev/adsp") != 0 &&
2153         strcmp(filename, "/dev/sndstat") != 0 &&
2154         strcmp(filename, "/dev/mixer") != 0) {
2155         LOAD_FOPEN64_FUNC();
2156         return _fopen64(filename, mode);
2157     }
2158
2159     return fopen(filename, mode);
2160 }
2161
2162 int fclose(FILE *f) {
2163     fd_info *i;
2164
2165     debug(DEBUG_LEVEL_VERBOSE, __FILE__": fclose()\n");
2166
2167     if (!function_enter()) {
2168         LOAD_FCLOSE_FUNC();
2169         return _fclose(f);
2170     }
2171
2172     if (!(i = fd_info_find(fileno(f)))) {
2173         function_exit();
2174         LOAD_FCLOSE_FUNC();
2175         return _fclose(f);
2176     }
2177
2178     fd_info_remove_from_list(i);
2179
2180     /* Dirty trick to avoid that the fd is not freed twice, once by us
2181      * and once by the real fclose() */
2182     i->app_fd = -1;
2183     
2184     fd_info_unref(i);
2185     
2186     function_exit();
2187
2188     LOAD_FCLOSE_FUNC();
2189     return _fclose(f);
2190 }