2 This file is part of PulseAudio.
4 Copyright 2006 Lennart Poettering
5 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #ifdef _FILE_OFFSET_BITS
28 #undef _FILE_OFFSET_BITS
31 #ifndef _LARGEFILE64_SOURCE
32 #define _LARGEFILE64_SOURCE 1
35 #include <sys/soundcard.h>
36 #include <sys/ioctl.h>
39 #include <sys/socket.h>
50 #include <linux/sockios.h>
53 #include <pulse/pulseaudio.h>
54 #include <pulse/gccmacro.h>
55 #include <pulsecore/llist.h>
56 #include <pulsecore/core-util.h>
58 /* On some systems SIOCINQ isn't defined, but FIONREAD is just an alias */
59 #if !defined(SIOCINQ) && defined(FIONREAD)
60 # define SIOCINQ FIONREAD
63 /* make sure gcc doesn't redefine open and friends as macros */
72 typedef struct fd_info fd_info
;
75 pthread_mutex_t mutex
;
80 int app_fd
, thread_fd
;
82 pa_sample_spec sample_spec
;
86 pa_threaded_mainloop
*mainloop
;
88 pa_stream
*play_stream
;
89 pa_stream
*rec_stream
;
93 pa_io_event
*io_event
;
94 pa_io_event_flags_t io_flags
;
99 int operation_success
;
101 pa_cvolume sink_volume
, source_volume
;
102 uint32_t sink_index
, source_index
;
103 int volume_modify_count
;
107 PA_LLIST_FIELDS(fd_info
);
110 static int dsp_drain(fd_info
*i
);
111 static void fd_info_remove_from_list(fd_info
*i
);
113 static pthread_mutex_t fd_infos_mutex
= PTHREAD_MUTEX_INITIALIZER
;
114 static pthread_mutex_t func_mutex
= PTHREAD_MUTEX_INITIALIZER
;
116 static PA_LLIST_HEAD(fd_info
, fd_infos
) = NULL
;
118 static int (*_ioctl
)(int, int, void*) = NULL
;
119 static int (*_close
)(int) = NULL
;
120 static int (*_open
)(const char *, int, mode_t
) = NULL
;
121 static FILE* (*_fopen
)(const char *path
, const char *mode
) = NULL
;
122 static int (*_stat
)(const char *, struct stat
*) = NULL
;
124 static int (*___xstat
)(int, const char *, struct stat
*) = NULL
;
127 static int (*_open64
)(const char *, int, mode_t
) = NULL
;
128 static FILE* (*_fopen64
)(const char *path
, const char *mode
) = NULL
;
129 static int (*_stat64
)(const char *, struct stat64
*) = NULL
;
131 static int (*___xstat64
)(int, const char *, struct stat64
*) = NULL
;
134 static int (*_fclose
)(FILE *f
) = NULL
;
135 static int (*_access
)(const char *, int) = NULL
;
137 /* dlsym() violates ISO C, so confide the breakage into this function to
139 typedef void (*fnptr
)(void);
140 static inline fnptr
dlsym_fn(void *handle
, const char *symbol
) {
141 return (fnptr
) (long) dlsym(handle
, symbol
);
144 #define LOAD_IOCTL_FUNC() \
146 pthread_mutex_lock(&func_mutex); \
148 _ioctl = (int (*)(int, int, void*)) dlsym_fn(RTLD_NEXT, "ioctl"); \
149 pthread_mutex_unlock(&func_mutex); \
152 #define LOAD_OPEN_FUNC() \
154 pthread_mutex_lock(&func_mutex); \
156 _open = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open"); \
157 pthread_mutex_unlock(&func_mutex); \
160 #define LOAD_OPEN64_FUNC() \
162 pthread_mutex_lock(&func_mutex); \
164 _open64 = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open64"); \
165 pthread_mutex_unlock(&func_mutex); \
168 #define LOAD_CLOSE_FUNC() \
170 pthread_mutex_lock(&func_mutex); \
172 _close = (int (*)(int)) dlsym_fn(RTLD_NEXT, "close"); \
173 pthread_mutex_unlock(&func_mutex); \
176 #define LOAD_ACCESS_FUNC() \
178 pthread_mutex_lock(&func_mutex); \
180 _access = (int (*)(const char*, int)) dlsym_fn(RTLD_NEXT, "access"); \
181 pthread_mutex_unlock(&func_mutex); \
184 #define LOAD_STAT_FUNC() \
186 pthread_mutex_lock(&func_mutex); \
188 _stat = (int (*)(const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "stat"); \
189 pthread_mutex_unlock(&func_mutex); \
192 #define LOAD_STAT64_FUNC() \
194 pthread_mutex_lock(&func_mutex); \
196 _stat64 = (int (*)(const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "stat64"); \
197 pthread_mutex_unlock(&func_mutex); \
200 #define LOAD_XSTAT_FUNC() \
202 pthread_mutex_lock(&func_mutex); \
204 ___xstat = (int (*)(int, const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "__xstat"); \
205 pthread_mutex_unlock(&func_mutex); \
208 #define LOAD_XSTAT64_FUNC() \
210 pthread_mutex_lock(&func_mutex); \
212 ___xstat64 = (int (*)(int, const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "__xstat64"); \
213 pthread_mutex_unlock(&func_mutex); \
216 #define LOAD_FOPEN_FUNC() \
218 pthread_mutex_lock(&func_mutex); \
220 _fopen = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen"); \
221 pthread_mutex_unlock(&func_mutex); \
224 #define LOAD_FOPEN64_FUNC() \
226 pthread_mutex_lock(&func_mutex); \
228 _fopen64 = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen64"); \
229 pthread_mutex_unlock(&func_mutex); \
232 #define LOAD_FCLOSE_FUNC() \
234 pthread_mutex_lock(&func_mutex); \
236 _fclose = (int (*)(FILE *)) dlsym_fn(RTLD_NEXT, "fclose"); \
237 pthread_mutex_unlock(&func_mutex); \
240 #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \
241 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \
242 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
247 #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \
248 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
249 !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \
250 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
255 #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \
256 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
257 !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \
258 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
263 static void debug(int level
, const char *format
, ...) PA_GCC_PRINTF_ATTR(2,3);
265 #define DEBUG_LEVEL_ALWAYS 0
266 #define DEBUG_LEVEL_NORMAL 1
267 #define DEBUG_LEVEL_VERBOSE 2
269 static void debug(int level
, const char *format
, ...) {
271 const char *dlevel_s
;
274 dlevel_s
= getenv("PADSP_DEBUG");
278 dlevel
= atoi(dlevel_s
);
283 va_start(ap
, format
);
284 vfprintf(stderr
, format
, ap
);
288 static int padsp_disabled(void) {
290 static int sym_resolved
= 0;
292 /* If the current process has a symbol __padsp_disabled__ we use
293 * it to detect whether we should enable our stuff or not. A
294 * program needs to be compiled with -rdynamic for this to work!
295 * The symbol must be an int containing a three bit bitmask: bit 1
296 * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat
297 * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value
298 * of 7 disables padsp entirely. */
300 pthread_mutex_lock(&func_mutex
);
302 sym
= (int*) dlsym(RTLD_DEFAULT
, "__padsp_disabled__");
305 pthread_mutex_unlock(&func_mutex
);
313 static int dsp_cloak_enable(void) {
314 if (padsp_disabled() & 1)
317 if (getenv("PADSP_NO_DSP") || getenv("PULSE_INTERNAL"))
323 static int sndstat_cloak_enable(void) {
324 if (padsp_disabled() & 2)
327 if (getenv("PADSP_NO_SNDSTAT") || getenv("PULSE_INTERNAL"))
333 static int mixer_cloak_enable(void) {
334 if (padsp_disabled() & 4)
337 if (getenv("PADSP_NO_MIXER") || getenv("PULSE_INTERNAL"))
342 static pthread_key_t recursion_key
;
344 static void recursion_key_alloc(void) {
345 pthread_key_create(&recursion_key
, NULL
);
348 static int function_enter(void) {
349 /* Avoid recursive calls */
350 static pthread_once_t recursion_key_once
= PTHREAD_ONCE_INIT
;
351 pthread_once(&recursion_key_once
, recursion_key_alloc
);
353 if (pthread_getspecific(recursion_key
))
356 pthread_setspecific(recursion_key
, (void*) 1);
360 static void function_exit(void) {
361 pthread_setspecific(recursion_key
, NULL
);
364 static void fd_info_free(fd_info
*i
) {
367 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": freeing fd info (fd=%i)\n", i
->app_fd
);
372 pa_threaded_mainloop_stop(i
->mainloop
);
374 if (i
->play_stream
) {
375 pa_stream_disconnect(i
->play_stream
);
376 pa_stream_unref(i
->play_stream
);
380 pa_stream_disconnect(i
->rec_stream
);
381 pa_stream_unref(i
->rec_stream
);
385 pa_context_disconnect(i
->context
);
386 pa_context_unref(i
->context
);
390 pa_threaded_mainloop_free(i
->mainloop
);
392 if (i
->app_fd
>= 0) {
397 if (i
->thread_fd
>= 0) {
399 _close(i
->thread_fd
);
404 pthread_mutex_destroy(&i
->mutex
);
408 static fd_info
*fd_info_ref(fd_info
*i
) {
411 pthread_mutex_lock(&i
->mutex
);
415 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ref++, now %i\n", i
->ref
);
416 pthread_mutex_unlock(&i
->mutex
);
421 static void fd_info_unref(fd_info
*i
) {
423 pthread_mutex_lock(&i
->mutex
);
426 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ref--, now %i\n", i
->ref
);
427 pthread_mutex_unlock(&i
->mutex
);
433 static void context_state_cb(pa_context
*c
, void *userdata
) {
434 fd_info
*i
= userdata
;
437 switch (pa_context_get_state(c
)) {
438 case PA_CONTEXT_READY
:
439 case PA_CONTEXT_TERMINATED
:
440 case PA_CONTEXT_FAILED
:
441 pa_threaded_mainloop_signal(i
->mainloop
, 0);
444 case PA_CONTEXT_UNCONNECTED
:
445 case PA_CONTEXT_CONNECTING
:
446 case PA_CONTEXT_AUTHORIZING
:
447 case PA_CONTEXT_SETTING_NAME
:
452 static void reset_params(fd_info
*i
) {
455 i
->sample_spec
.format
= PA_SAMPLE_U8
;
456 i
->sample_spec
.channels
= 1;
457 i
->sample_spec
.rate
= 8000;
458 i
->fragment_size
= 0;
462 static const char *client_name(char *buf
, size_t n
) {
466 if ((e
= getenv("PADSP_CLIENT_NAME")))
469 if ((p
= pa_get_binary_name_malloc())) {
470 snprintf(buf
, n
, "OSS Emulation[%s]", p
);
473 snprintf(buf
, n
, "OSS");
478 static const char *stream_name(void) {
481 if ((e
= getenv("PADSP_STREAM_NAME")))
484 return "Audio Stream";
487 static void atfork_prepare(void) {
490 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_prepare() enter\n");
494 pthread_mutex_lock(&fd_infos_mutex
);
496 for (i
= fd_infos
; i
; i
= i
->next
) {
497 pthread_mutex_lock(&i
->mutex
);
498 pa_threaded_mainloop_lock(i
->mainloop
);
501 pthread_mutex_lock(&func_mutex
);
503 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_prepare() exit\n");
506 static void atfork_parent(void) {
509 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_parent() enter\n");
511 pthread_mutex_unlock(&func_mutex
);
513 for (i
= fd_infos
; i
; i
= i
->next
) {
514 pa_threaded_mainloop_unlock(i
->mainloop
);
515 pthread_mutex_unlock(&i
->mutex
);
518 pthread_mutex_unlock(&fd_infos_mutex
);
522 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_parent() exit\n");
525 static void atfork_child(void) {
528 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_child() enter\n");
530 /* We do only the bare minimum to get all fds closed */
531 pthread_mutex_init(&func_mutex
, NULL
);
532 pthread_mutex_init(&fd_infos_mutex
, NULL
);
534 for (i
= fd_infos
; i
; i
= i
->next
) {
535 pthread_mutex_init(&i
->mutex
, NULL
);
538 pa_context_disconnect(i
->context
);
539 pa_context_unref(i
->context
);
543 if (i
->play_stream
) {
544 pa_stream_unref(i
->play_stream
);
545 i
->play_stream
= NULL
;
549 pa_stream_unref(i
->rec_stream
);
550 i
->rec_stream
= NULL
;
553 if (i
->app_fd
>= 0) {
559 if (i
->thread_fd
>= 0) {
561 _close(i
->thread_fd
);
570 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_child() exit\n");
573 static void install_atfork(void) {
574 pthread_atfork(atfork_prepare
, atfork_parent
, atfork_child
);
577 static void stream_success_cb(pa_stream
*s
, int success
, void *userdata
) {
578 fd_info
*i
= userdata
;
583 i
->operation_success
= success
;
584 pa_threaded_mainloop_signal(i
->mainloop
, 0);
587 static void context_success_cb(pa_context
*c
, int success
, void *userdata
) {
588 fd_info
*i
= userdata
;
593 i
->operation_success
= success
;
594 pa_threaded_mainloop_signal(i
->mainloop
, 0);
597 static fd_info
* fd_info_new(fd_info_type_t type
, int *_errno
) {
599 int sfds
[2] = { -1, -1 };
601 static pthread_once_t install_atfork_once
= PTHREAD_ONCE_INIT
;
603 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fd_info_new()\n");
605 signal(SIGPIPE
, SIG_IGN
); /* Yes, ugly as hell */
607 pthread_once(&install_atfork_once
, install_atfork
);
609 if (!(i
= malloc(sizeof(fd_info
)))) {
614 i
->app_fd
= i
->thread_fd
= -1;
619 i
->play_stream
= NULL
;
620 i
->rec_stream
= NULL
;
625 pthread_mutex_init(&i
->mutex
, NULL
);
630 pa_cvolume_reset(&i
->sink_volume
, 2);
631 pa_cvolume_reset(&i
->source_volume
, 2);
632 i
->volume_modify_count
= 0;
633 i
->sink_index
= (uint32_t) -1;
634 i
->source_index
= (uint32_t) -1;
635 i
->optr_n_blocks
= 0;
636 PA_LLIST_INIT(fd_info
, i
);
640 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sfds
) < 0) {
642 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": socket() failed: %s\n", strerror(errno
));
647 i
->thread_fd
= sfds
[1];
649 if (!(i
->mainloop
= pa_threaded_mainloop_new())) {
651 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_threaded_mainloop_new() failed\n");
655 if (!(i
->context
= pa_context_new(pa_threaded_mainloop_get_api(i
->mainloop
), client_name(name
, sizeof(name
))))) {
657 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_new() failed\n");
661 pa_context_set_state_callback(i
->context
, context_state_cb
, i
);
663 if (pa_context_connect(i
->context
, NULL
, 0, NULL
) < 0) {
664 *_errno
= ECONNREFUSED
;
665 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
669 pa_threaded_mainloop_lock(i
->mainloop
);
671 if (pa_threaded_mainloop_start(i
->mainloop
) < 0) {
673 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_threaded_mainloop_start() failed\n");
674 goto unlock_and_fail
;
677 /* Wait until the context is ready */
678 pa_threaded_mainloop_wait(i
->mainloop
);
680 if (pa_context_get_state(i
->context
) != PA_CONTEXT_READY
) {
681 *_errno
= ECONNREFUSED
;
682 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
683 goto unlock_and_fail
;
686 pa_threaded_mainloop_unlock(i
->mainloop
);
691 pa_threaded_mainloop_unlock(i
->mainloop
);
701 static void fd_info_add_to_list(fd_info
*i
) {
704 pthread_mutex_lock(&fd_infos_mutex
);
705 PA_LLIST_PREPEND(fd_info
, fd_infos
, i
);
706 pthread_mutex_unlock(&fd_infos_mutex
);
711 static void fd_info_remove_from_list(fd_info
*i
) {
714 pthread_mutex_lock(&fd_infos_mutex
);
715 PA_LLIST_REMOVE(fd_info
, fd_infos
, i
);
716 pthread_mutex_unlock(&fd_infos_mutex
);
721 static fd_info
* fd_info_find(int fd
) {
724 pthread_mutex_lock(&fd_infos_mutex
);
726 for (i
= fd_infos
; i
; i
= i
->next
)
727 if (i
->app_fd
== fd
&& !i
->unusable
) {
732 pthread_mutex_unlock(&fd_infos_mutex
);
737 static void fix_metrics(fd_info
*i
) {
739 char t
[PA_SAMPLE_SPEC_SNPRINT_MAX
];
741 fs
= pa_frame_size(&i
->sample_spec
);
743 /* Don't fix things more than necessary */
744 if ((i
->fragment_size
% fs
) == 0 &&
745 i
->n_fragments
>= 2 &&
746 i
->fragment_size
> 0)
749 i
->fragment_size
= (i
->fragment_size
/fs
)*fs
;
751 /* Number of fragments set? */
752 if (i
->n_fragments
< 2) {
753 if (i
->fragment_size
> 0) {
754 i
->n_fragments
= (unsigned) (pa_bytes_per_second(&i
->sample_spec
) / 2 / i
->fragment_size
);
755 if (i
->n_fragments
< 2)
761 /* Fragment size set? */
762 if (i
->fragment_size
<= 0) {
763 i
->fragment_size
= pa_bytes_per_second(&i
->sample_spec
) / 2 / i
->n_fragments
;
764 if (i
->fragment_size
< 1024)
765 i
->fragment_size
= 1024;
768 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": sample spec: %s\n", pa_sample_spec_snprint(t
, sizeof(t
), &i
->sample_spec
));
769 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fixated metrics to %i fragments, %li bytes each.\n", i
->n_fragments
, (long)i
->fragment_size
);
772 static void stream_request_cb(pa_stream
*s
, size_t length
, void *userdata
) {
773 fd_info
*i
= userdata
;
777 pa_mainloop_api
*api
;
780 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
782 if (s
== i
->play_stream
) {
783 n
= pa_stream_writable_size(i
->play_stream
);
784 if (n
== (size_t)-1) {
785 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n",
786 pa_strerror(pa_context_errno(i
->context
)));
789 if (n
>= i
->fragment_size
)
790 i
->io_flags
|= PA_IO_EVENT_INPUT
;
792 i
->io_flags
&= ~PA_IO_EVENT_INPUT
;
795 if (s
== i
->rec_stream
) {
796 n
= pa_stream_readable_size(i
->rec_stream
);
797 if (n
== (size_t)-1) {
798 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n",
799 pa_strerror(pa_context_errno(i
->context
)));
802 if (n
>= i
->fragment_size
)
803 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
805 i
->io_flags
&= ~PA_IO_EVENT_OUTPUT
;
808 api
->io_enable(i
->io_event
, i
->io_flags
);
812 static void stream_latency_update_cb(pa_stream
*s
, void *userdata
) {
813 fd_info
*i
= userdata
;
816 pa_threaded_mainloop_signal(i
->mainloop
, 0);
819 static void fd_info_shutdown(fd_info
*i
) {
823 pa_mainloop_api
*api
;
824 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
825 api
->io_free(i
->io_event
);
830 if (i
->thread_fd
>= 0) {
836 static int fd_info_copy_data(fd_info
*i
, int force
) {
839 if (!i
->play_stream
&& !i
->rec_stream
)
842 if ((i
->play_stream
) && (pa_stream_get_state(i
->play_stream
) == PA_STREAM_READY
)) {
843 n
= pa_stream_writable_size(i
->play_stream
);
845 if (n
== (size_t)-1) {
846 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n",
847 pa_strerror(pa_context_errno(i
->context
)));
851 while (n
>= i
->fragment_size
|| force
) {
855 if (!(i
->buf
= malloc(i
->fragment_size
))) {
856 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": malloc() failed.\n");
861 if ((r
= read(i
->thread_fd
, i
->buf
, i
->fragment_size
)) <= 0) {
866 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": read(): %s\n", r
== 0 ? "EOF" : strerror(errno
));
870 if (pa_stream_write(i
->play_stream
, i
->buf
, (size_t) r
, free
, 0LL, PA_SEEK_RELATIVE
) < 0) {
871 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
877 assert(n
>= (size_t) r
);
881 if (n
>= i
->fragment_size
)
882 i
->io_flags
|= PA_IO_EVENT_INPUT
;
884 i
->io_flags
&= ~PA_IO_EVENT_INPUT
;
887 if ((i
->rec_stream
) && (pa_stream_get_state(i
->rec_stream
) == PA_STREAM_READY
)) {
888 n
= pa_stream_readable_size(i
->rec_stream
);
890 if (n
== (size_t)-1) {
891 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n",
892 pa_strerror(pa_context_errno(i
->context
)));
896 while (n
>= i
->fragment_size
|| force
) {
902 if (pa_stream_peek(i
->rec_stream
, &data
, &len
) < 0) {
903 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_peek(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
910 buf
= (const char*)data
+ i
->rec_offset
;
912 if ((r
= write(i
->thread_fd
, buf
, len
- i
->rec_offset
)) <= 0) {
917 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write(): %s\n", strerror(errno
));
921 assert((size_t)r
<= len
- i
->rec_offset
);
922 i
->rec_offset
+= (size_t) r
;
924 if (i
->rec_offset
== len
) {
925 if (pa_stream_drop(i
->rec_stream
) < 0) {
926 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
932 assert(n
>= (size_t) r
);
936 if (n
>= i
->fragment_size
)
937 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
939 i
->io_flags
&= ~PA_IO_EVENT_OUTPUT
;
943 pa_mainloop_api
*api
;
945 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
946 api
->io_enable(i
->io_event
, i
->io_flags
);
949 /* So, we emptied the socket now, let's tell dsp_empty_socket()
951 pa_threaded_mainloop_signal(i
->mainloop
, 0);
956 static void stream_state_cb(pa_stream
*s
, void * userdata
) {
957 fd_info
*i
= userdata
;
960 switch (pa_stream_get_state(s
)) {
962 case PA_STREAM_READY
:
963 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stream established.\n");
966 case PA_STREAM_FAILED
:
967 if (s
== i
->play_stream
) {
968 debug(DEBUG_LEVEL_NORMAL
,
969 __FILE__
": pa_stream_connect_playback() failed: %s\n",
970 pa_strerror(pa_context_errno(i
->context
)));
971 pa_stream_unref(i
->play_stream
);
972 i
->play_stream
= NULL
;
973 } else if (s
== i
->rec_stream
) {
974 debug(DEBUG_LEVEL_NORMAL
,
975 __FILE__
": pa_stream_connect_record() failed: %s\n",
976 pa_strerror(pa_context_errno(i
->context
)));
977 pa_stream_unref(i
->rec_stream
);
978 i
->rec_stream
= NULL
;
983 case PA_STREAM_TERMINATED
:
984 case PA_STREAM_UNCONNECTED
:
985 case PA_STREAM_CREATING
:
990 static int create_playback_stream(fd_info
*i
) {
998 if (!(i
->play_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
999 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1003 pa_stream_set_state_callback(i
->play_stream
, stream_state_cb
, i
);
1004 pa_stream_set_write_callback(i
->play_stream
, stream_request_cb
, i
);
1005 pa_stream_set_latency_update_callback(i
->play_stream
, stream_latency_update_cb
, i
);
1007 memset(&attr
, 0, sizeof(attr
));
1008 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1009 attr
.tlength
= (uint32_t) (i
->fragment_size
* i
->n_fragments
);
1010 attr
.prebuf
= (uint32_t) i
->fragment_size
;
1011 attr
.minreq
= (uint32_t) i
->fragment_size
;
1013 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
|PA_STREAM_EARLY_REQUESTS
;
1014 if (i
->play_precork
) {
1015 flags
|= PA_STREAM_START_CORKED
;
1016 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1018 if (pa_stream_connect_playback(i
->play_stream
, NULL
, &attr
, flags
, NULL
, NULL
) < 0) {
1019 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1023 n
= (int) i
->fragment_size
;
1024 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1025 n
= (int) i
->fragment_size
;
1026 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1034 static int create_record_stream(fd_info
*i
) {
1035 pa_buffer_attr attr
;
1042 if (!(i
->rec_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
1043 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1047 pa_stream_set_state_callback(i
->rec_stream
, stream_state_cb
, i
);
1048 pa_stream_set_read_callback(i
->rec_stream
, stream_request_cb
, i
);
1049 pa_stream_set_latency_update_callback(i
->rec_stream
, stream_latency_update_cb
, i
);
1051 memset(&attr
, 0, sizeof(attr
));
1052 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1053 attr
.fragsize
= (uint32_t) i
->fragment_size
;
1055 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
;
1056 if (i
->rec_precork
) {
1057 flags
|= PA_STREAM_START_CORKED
;
1058 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1060 if (pa_stream_connect_record(i
->rec_stream
, NULL
, &attr
, flags
) < 0) {
1061 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1065 n
= (int) i
->fragment_size
;
1066 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1067 n
= (int) i
->fragment_size
;
1068 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1076 static void free_streams(fd_info
*i
) {
1079 if (i
->play_stream
) {
1080 pa_stream_disconnect(i
->play_stream
);
1081 pa_stream_unref(i
->play_stream
);
1082 i
->play_stream
= NULL
;
1083 i
->io_flags
|= PA_IO_EVENT_INPUT
;
1086 if (i
->rec_stream
) {
1087 pa_stream_disconnect(i
->rec_stream
);
1088 pa_stream_unref(i
->rec_stream
);
1089 i
->rec_stream
= NULL
;
1090 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
1094 pa_mainloop_api
*api
;
1096 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1097 api
->io_enable(i
->io_event
, i
->io_flags
);
1101 static void io_event_cb(pa_mainloop_api
*api
, pa_io_event
*e
, int fd
, pa_io_event_flags_t flags
, void *userdata
) {
1102 fd_info
*i
= userdata
;
1104 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1106 if (flags
& PA_IO_EVENT_INPUT
) {
1108 if (!i
->play_stream
) {
1109 if (create_playback_stream(i
) < 0)
1112 if (fd_info_copy_data(i
, 0) < 0)
1116 } else if (flags
& PA_IO_EVENT_OUTPUT
) {
1118 if (!i
->rec_stream
) {
1119 if (create_record_stream(i
) < 0)
1122 if (fd_info_copy_data(i
, 0) < 0)
1126 } else if (flags
& (PA_IO_EVENT_HANGUP
|PA_IO_EVENT_ERROR
))
1132 /* We can't do anything better than removing the event source */
1133 fd_info_shutdown(i
);
1136 static int dsp_open(int flags
, int *_errno
) {
1138 pa_mainloop_api
*api
;
1142 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open()\n");
1144 if (!(i
= fd_info_new(FD_INFO_STREAM
, _errno
)))
1147 if ((flags
& O_NONBLOCK
) == O_NONBLOCK
) {
1148 if ((f
= fcntl(i
->app_fd
, F_GETFL
)) >= 0)
1149 fcntl(i
->app_fd
, F_SETFL
, f
|O_NONBLOCK
);
1151 if ((f
= fcntl(i
->thread_fd
, F_GETFL
)) >= 0)
1152 fcntl(i
->thread_fd
, F_SETFL
, f
|O_NONBLOCK
);
1154 fcntl(i
->app_fd
, F_SETFD
, FD_CLOEXEC
);
1155 fcntl(i
->thread_fd
, F_SETFD
, FD_CLOEXEC
);
1157 pa_threaded_mainloop_lock(i
->mainloop
);
1158 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1160 switch (flags
& O_ACCMODE
) {
1162 i
->io_flags
= PA_IO_EVENT_OUTPUT
;
1163 shutdown(i
->thread_fd
, SHUT_RD
);
1164 shutdown(i
->app_fd
, SHUT_WR
);
1167 i
->io_flags
= PA_IO_EVENT_INPUT
;
1168 shutdown(i
->thread_fd
, SHUT_WR
);
1169 shutdown(i
->app_fd
, SHUT_RD
);
1172 i
->io_flags
= PA_IO_EVENT_INPUT
| PA_IO_EVENT_OUTPUT
;
1178 if (!(i
->io_event
= api
->io_new(api
, i
->thread_fd
, i
->io_flags
, io_event_cb
, i
)))
1181 pa_threaded_mainloop_unlock(i
->mainloop
);
1183 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() succeeded, fd=%i\n", i
->app_fd
);
1185 fd_info_add_to_list(i
);
1192 pa_threaded_mainloop_unlock(i
->mainloop
);
1199 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() failed\n");
1204 static void sink_info_cb(pa_context
*context
, const pa_sink_info
*si
, int eol
, void *userdata
) {
1205 fd_info
*i
= userdata
;
1207 if (!si
|| eol
< 0) {
1208 i
->operation_success
= 0;
1209 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1216 if (!pa_cvolume_equal(&i
->sink_volume
, &si
->volume
))
1217 i
->volume_modify_count
++;
1219 i
->sink_volume
= si
->volume
;
1220 i
->sink_index
= si
->index
;
1222 i
->operation_success
= 1;
1223 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1226 static void source_info_cb(pa_context
*context
, const pa_source_info
*si
, int eol
, void *userdata
) {
1227 fd_info
*i
= userdata
;
1229 if (!si
|| eol
< 0) {
1230 i
->operation_success
= 0;
1231 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1238 if (!pa_cvolume_equal(&i
->source_volume
, &si
->volume
))
1239 i
->volume_modify_count
++;
1241 i
->source_volume
= si
->volume
;
1242 i
->source_index
= si
->index
;
1244 i
->operation_success
= 1;
1245 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1248 static void subscribe_cb(pa_context
*context
, pa_subscription_event_type_t t
, uint32_t idx
, void *userdata
) {
1249 fd_info
*i
= userdata
;
1250 pa_operation
*o
= NULL
;
1252 if (i
->sink_index
!= idx
)
1255 if ((t
& PA_SUBSCRIPTION_EVENT_TYPE_MASK
) != PA_SUBSCRIPTION_EVENT_CHANGE
)
1258 if (!(o
= pa_context_get_sink_info_by_index(i
->context
, i
->sink_index
, sink_info_cb
, i
))) {
1259 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1263 pa_operation_unref(o
);
1266 static int mixer_open(int flags
, int *_errno
) {
1268 pa_operation
*o
= NULL
;
1271 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open()\n");
1273 if (!(i
= fd_info_new(FD_INFO_MIXER
, _errno
)))
1276 pa_threaded_mainloop_lock(i
->mainloop
);
1278 pa_context_set_subscribe_callback(i
->context
, subscribe_cb
, i
);
1280 if (!(o
= pa_context_subscribe(i
->context
, PA_SUBSCRIPTION_MASK_SINK
| PA_SUBSCRIPTION_MASK_SOURCE
, context_success_cb
, i
))) {
1281 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1286 i
->operation_success
= 0;
1287 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1288 pa_threaded_mainloop_wait(i
->mainloop
);
1289 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1292 pa_operation_unref(o
);
1295 if (!i
->operation_success
) {
1296 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1303 if (!(o
= pa_context_get_sink_info_by_name(i
->context
, NULL
, sink_info_cb
, i
))) {
1304 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1309 i
->operation_success
= 0;
1310 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1311 pa_threaded_mainloop_wait(i
->mainloop
);
1312 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1315 pa_operation_unref(o
);
1318 if (!i
->operation_success
) {
1319 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1324 /* Get source info */
1326 if (!(o
= pa_context_get_source_info_by_name(i
->context
, NULL
, source_info_cb
, i
))) {
1327 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1332 i
->operation_success
= 0;
1333 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1334 pa_threaded_mainloop_wait(i
->mainloop
);
1335 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1338 pa_operation_unref(o
);
1341 if (!i
->operation_success
) {
1342 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1347 pa_threaded_mainloop_unlock(i
->mainloop
);
1349 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() succeeded, fd=%i\n", i
->app_fd
);
1351 fd_info_add_to_list(i
);
1359 pa_operation_unref(o
);
1361 pa_threaded_mainloop_unlock(i
->mainloop
);
1368 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() failed\n");
1373 static int sndstat_open(int flags
, int *_errno
) {
1374 static const char sndstat
[] =
1375 "Sound Driver:3.8.1a-980706 (PulseAudio Virtual OSS)\n"
1377 "Config options: 0\n"
1379 "Installed drivers:\n"
1380 "Type 255: PulseAudio Virtual OSS\n"
1383 "PulseAudio Virtual OSS\n"
1386 "0: PulseAudio Virtual OSS\n"
1388 "Synth devices: NOT ENABLED IN CONFIG\n"
1395 "0: PulseAudio Virtual OSS\n";
1397 char fn
[] = "/tmp/padsp-sndstat-XXXXXX";
1402 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": sndstat_open()\n");
1404 if (flags
!= O_RDONLY
1406 && flags
!= (O_RDONLY
|O_LARGEFILE
)
1410 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": bad access!\n");
1421 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mkstemp() failed: %s\n", strerror(errno
));
1427 if (write(fd
, sndstat
, sizeof(sndstat
) -1) != sizeof(sndstat
)-1) {
1429 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write() failed: %s\n", strerror(errno
));
1433 if (lseek(fd
, SEEK_SET
, 0) < 0) {
1435 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": lseek() failed: %s\n", strerror(errno
));
1447 static int real_open(const char *filename
, int flags
, mode_t mode
) {
1450 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open(%s)\n", filename
?filename
:"NULL");
1452 if (!function_enter()) {
1454 return _open(filename
, flags
, mode
);
1457 if (filename
&& dsp_cloak_enable() && (strcmp(filename
, "/dev/dsp") == 0 || strcmp(filename
, "/dev/adsp") == 0))
1458 r
= dsp_open(flags
, &_errno
);
1459 else if (filename
&& mixer_cloak_enable() && strcmp(filename
, "/dev/mixer") == 0)
1460 r
= mixer_open(flags
, &_errno
);
1461 else if (filename
&& sndstat_cloak_enable() && strcmp(filename
, "/dev/sndstat") == 0)
1462 r
= sndstat_open(flags
, &_errno
);
1466 return _open(filename
, flags
, mode
);
1477 int open(const char *filename
, int flags
, ...) {
1481 if (flags
& O_CREAT
) {
1482 va_start(args
, flags
);
1483 if (sizeof(mode_t
) < sizeof(int))
1484 mode
= (mode_t
) va_arg(args
, int);
1486 mode
= va_arg(args
, mode_t
);
1490 return real_open(filename
, flags
, mode
);
1493 static int mixer_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1497 case SOUND_MIXER_READ_DEVMASK
:
1498 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_DEVMASK\n");
1500 *(int*) argp
= SOUND_MASK_PCM
| SOUND_MASK_IGAIN
;
1503 case SOUND_MIXER_READ_RECMASK
:
1504 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECMASK\n");
1506 *(int*) argp
= SOUND_MASK_IGAIN
;
1509 case SOUND_MIXER_READ_STEREODEVS
:
1510 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_STEREODEVS\n");
1512 pa_threaded_mainloop_lock(i
->mainloop
);
1514 if (i
->sink_volume
.channels
> 1)
1515 *(int*) argp
|= SOUND_MASK_PCM
;
1516 if (i
->source_volume
.channels
> 1)
1517 *(int*) argp
|= SOUND_MASK_IGAIN
;
1518 pa_threaded_mainloop_unlock(i
->mainloop
);
1522 case SOUND_MIXER_READ_RECSRC
:
1523 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECSRC\n");
1525 *(int*) argp
= SOUND_MASK_IGAIN
;
1528 case SOUND_MIXER_WRITE_RECSRC
:
1529 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_RECSRC\n");
1532 case SOUND_MIXER_READ_CAPS
:
1533 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_CAPS\n");
1538 case SOUND_MIXER_READ_PCM
:
1539 case SOUND_MIXER_READ_IGAIN
: {
1542 if (request
== SOUND_MIXER_READ_PCM
)
1543 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_PCM\n");
1545 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_IGAIN\n");
1547 pa_threaded_mainloop_lock(i
->mainloop
);
1549 if (request
== SOUND_MIXER_READ_PCM
)
1550 v
= &i
->sink_volume
;
1552 v
= &i
->source_volume
;
1555 ((v
->values
[0]*100/PA_VOLUME_NORM
)) |
1556 ((v
->values
[v
->channels
> 1 ? 1 : 0]*100/PA_VOLUME_NORM
) << 8);
1558 pa_threaded_mainloop_unlock(i
->mainloop
);
1563 case SOUND_MIXER_WRITE_PCM
:
1564 case SOUND_MIXER_WRITE_IGAIN
: {
1567 if (request
== SOUND_MIXER_WRITE_PCM
)
1568 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_PCM\n");
1570 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_IGAIN\n");
1572 pa_threaded_mainloop_lock(i
->mainloop
);
1574 if (request
== SOUND_MIXER_WRITE_PCM
) {
1576 pv
= &i
->sink_volume
;
1578 v
= i
->source_volume
;
1579 pv
= &i
->source_volume
;
1582 pv
->values
[0] = ((*(int*) argp
& 0xFF)*PA_VOLUME_NORM
)/100;
1583 pv
->values
[1] = ((*(int*) argp
>> 8)*PA_VOLUME_NORM
)/100;
1585 if (!pa_cvolume_equal(pv
, &v
)) {
1588 if (request
== SOUND_MIXER_WRITE_PCM
)
1589 o
= pa_context_set_sink_volume_by_index(i
->context
, i
->sink_index
, pv
, context_success_cb
, i
);
1591 o
= pa_context_set_source_volume_by_index(i
->context
, i
->source_index
, pv
, context_success_cb
, i
);
1594 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed set volume: %s", pa_strerror(pa_context_errno(i
->context
)));
1597 i
->operation_success
= 0;
1598 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1599 CONTEXT_CHECK_DEAD_GOTO(i
, exit_loop
);
1601 pa_threaded_mainloop_wait(i
->mainloop
);
1605 if (!i
->operation_success
)
1606 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1608 pa_operation_unref(o
);
1611 /* We don't wait for completion here */
1612 i
->volume_modify_count
++;
1615 pa_threaded_mainloop_unlock(i
->mainloop
);
1620 case SOUND_MIXER_INFO
: {
1621 mixer_info
*mi
= argp
;
1623 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_INFO\n");
1625 memset(mi
, 0, sizeof(mixer_info
));
1626 strncpy(mi
->id
, "PULSEAUDIO", sizeof(mi
->id
));
1627 strncpy(mi
->name
, "PulseAudio Virtual OSS", sizeof(mi
->name
));
1628 pa_threaded_mainloop_lock(i
->mainloop
);
1629 mi
->modify_counter
= i
->volume_modify_count
;
1630 pa_threaded_mainloop_unlock(i
->mainloop
);
1635 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unknown ioctl 0x%08lx\n", request
);
1648 static int map_format(int *fmt
, pa_sample_spec
*ss
) {
1652 ss
->format
= PA_SAMPLE_ULAW
;
1656 ss
->format
= PA_SAMPLE_ALAW
;
1663 ss
->format
= PA_SAMPLE_U8
;
1670 ss
->format
= PA_SAMPLE_S16BE
;
1677 ss
->format
= PA_SAMPLE_S16LE
;
1681 ss
->format
= PA_SAMPLE_S16NE
;
1689 static int map_format_back(pa_sample_format_t format
) {
1691 case PA_SAMPLE_S16LE
: return AFMT_S16_LE
;
1692 case PA_SAMPLE_S16BE
: return AFMT_S16_BE
;
1693 case PA_SAMPLE_ULAW
: return AFMT_MU_LAW
;
1694 case PA_SAMPLE_ALAW
: return AFMT_A_LAW
;
1695 case PA_SAMPLE_U8
: return AFMT_U8
;
1701 static int dsp_flush_fd(int fd
) {
1705 if (ioctl(fd
, SIOCINQ
, &l
) < 0) {
1706 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1714 k
= (size_t) l
> sizeof(buf
) ? sizeof(buf
) : (size_t) l
;
1715 if (read(fd
, buf
, k
) < 0)
1716 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": read(): %s\n", strerror(errno
));
1722 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1727 static int dsp_flush_socket(fd_info
*i
) {
1730 if ((i
->thread_fd
< 0) && (i
->app_fd
< 0))
1733 if (i
->thread_fd
>= 0)
1734 res
= dsp_flush_fd(i
->thread_fd
);
1740 res
= dsp_flush_fd(i
->app_fd
);
1748 static int dsp_empty_socket(fd_info
*i
) {
1752 /* Empty the socket */
1756 if (i
->thread_fd
< 0)
1759 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
1760 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1769 pa_threaded_mainloop_wait(i
->mainloop
);
1774 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1779 static int dsp_drain(fd_info
*i
) {
1780 pa_operation
*o
= NULL
;
1786 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Draining.\n");
1788 pa_threaded_mainloop_lock(i
->mainloop
);
1790 if (dsp_empty_socket(i
) < 0)
1793 if (!i
->play_stream
)
1796 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Really draining.\n");
1798 if (!(o
= pa_stream_drain(i
->play_stream
, stream_success_cb
, i
))) {
1799 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1803 i
->operation_success
= 0;
1804 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1805 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1807 pa_threaded_mainloop_wait(i
->mainloop
);
1810 if (!i
->operation_success
) {
1811 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1820 pa_operation_unref(o
);
1822 pa_threaded_mainloop_unlock(i
->mainloop
);
1827 static int dsp_trigger(fd_info
*i
) {
1828 pa_operation
*o
= NULL
;
1831 if (!i
->play_stream
)
1834 pa_threaded_mainloop_lock(i
->mainloop
);
1836 if (dsp_empty_socket(i
) < 0)
1839 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Triggering.\n");
1841 if (!(o
= pa_stream_trigger(i
->play_stream
, stream_success_cb
, i
))) {
1842 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1846 i
->operation_success
= 0;
1847 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1848 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1850 pa_threaded_mainloop_wait(i
->mainloop
);
1853 if (!i
->operation_success
) {
1854 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1863 pa_operation_unref(o
);
1865 pa_threaded_mainloop_unlock(i
->mainloop
);
1870 static int dsp_cork(fd_info
*i
, pa_stream
*s
, int b
) {
1871 pa_operation
*o
= NULL
;
1874 pa_threaded_mainloop_lock(i
->mainloop
);
1876 if (!(o
= pa_stream_cork(s
, b
, stream_success_cb
, i
))) {
1877 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1881 i
->operation_success
= 0;
1882 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1883 if (s
== i
->play_stream
)
1884 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1885 else if (s
== i
->rec_stream
)
1886 RECORD_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1888 pa_threaded_mainloop_wait(i
->mainloop
);
1891 if (!i
->operation_success
) {
1892 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1901 pa_operation_unref(o
);
1903 pa_threaded_mainloop_unlock(i
->mainloop
);
1908 static int dsp_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1911 if (i
->thread_fd
== -1) {
1913 * We've encountered some fatal error and are just waiting
1916 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": got ioctl 0x%08lx in fatal error state\n", request
);
1922 case SNDCTL_DSP_SETFMT
: {
1923 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp
);
1925 pa_threaded_mainloop_lock(i
->mainloop
);
1927 if (*(int*) argp
== AFMT_QUERY
)
1928 *(int*) argp
= map_format_back(i
->sample_spec
.format
);
1930 map_format((int*) argp
, &i
->sample_spec
);
1934 pa_threaded_mainloop_unlock(i
->mainloop
);
1938 case SNDCTL_DSP_SPEED
: {
1943 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SPEED: %i\n", *(int*) argp
);
1945 pa_threaded_mainloop_lock(i
->mainloop
);
1947 ss
= i
->sample_spec
;
1948 ss
.rate
= *(int*) argp
;
1950 if ((valid
= pa_sample_spec_valid(&ss
))) {
1951 i
->sample_spec
= ss
;
1955 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ss: %s\n", pa_sample_spec_snprint(t
, sizeof(t
), &i
->sample_spec
));
1957 pa_threaded_mainloop_unlock(i
->mainloop
);
1967 case SNDCTL_DSP_STEREO
:
1968 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_STEREO: %i\n", *(int*) argp
);
1970 pa_threaded_mainloop_lock(i
->mainloop
);
1972 i
->sample_spec
.channels
= *(int*) argp
? 2 : 1;
1975 pa_threaded_mainloop_unlock(i
->mainloop
);
1978 case SNDCTL_DSP_CHANNELS
: {
1982 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp
);
1984 pa_threaded_mainloop_lock(i
->mainloop
);
1986 ss
= i
->sample_spec
;
1987 ss
.channels
= *(int*) argp
;
1989 if ((valid
= pa_sample_spec_valid(&ss
))) {
1990 i
->sample_spec
= ss
;
1994 pa_threaded_mainloop_unlock(i
->mainloop
);
2004 case SNDCTL_DSP_GETBLKSIZE
:
2005 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETBLKSIZE\n");
2007 pa_threaded_mainloop_lock(i
->mainloop
);
2010 *(int*) argp
= i
->fragment_size
;
2012 pa_threaded_mainloop_unlock(i
->mainloop
);
2016 case SNDCTL_DSP_SETFRAGMENT
:
2017 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp
);
2019 pa_threaded_mainloop_lock(i
->mainloop
);
2021 i
->fragment_size
= 1 << ((*(int*) argp
) & 31);
2022 i
->n_fragments
= (*(int*) argp
) >> 16;
2024 /* 0x7FFF means that we can set whatever we like */
2025 if (i
->n_fragments
== 0x7FFF)
2026 i
->n_fragments
= 12;
2030 pa_threaded_mainloop_unlock(i
->mainloop
);
2034 case SNDCTL_DSP_GETCAPS
:
2035 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CAPS\n");
2037 *(int*) argp
= DSP_CAP_DUPLEX
| DSP_CAP_TRIGGER
2038 #ifdef DSP_CAP_MULTI
2044 case SNDCTL_DSP_GETODELAY
: {
2047 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETODELAY\n");
2049 pa_threaded_mainloop_lock(i
->mainloop
);
2056 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop
);
2058 if (pa_stream_get_latency(i
->play_stream
, &usec
, NULL
) >= 0) {
2059 *(int*) argp
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2063 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2064 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2068 pa_threaded_mainloop_wait(i
->mainloop
);
2074 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0)
2075 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2079 # warning "Your platform does not support SIOCINQ, something might not work as intended."
2082 pa_threaded_mainloop_unlock(i
->mainloop
);
2084 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ODELAY: %i\n", *(int*) argp
);
2089 case SNDCTL_DSP_RESET
: {
2090 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_RESET\n");
2092 pa_threaded_mainloop_lock(i
->mainloop
);
2095 dsp_flush_socket(i
);
2097 i
->optr_n_blocks
= 0;
2099 pa_threaded_mainloop_unlock(i
->mainloop
);
2103 case SNDCTL_DSP_GETFMTS
: {
2104 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETFMTS\n");
2106 *(int*) argp
= AFMT_MU_LAW
|AFMT_A_LAW
|AFMT_U8
|AFMT_S16_LE
|AFMT_S16_BE
;
2110 case SNDCTL_DSP_POST
:
2111 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_POST\n");
2113 if (dsp_trigger(i
) < 0)
2117 case SNDCTL_DSP_GETTRIGGER
:
2118 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETTRIGGER\n");
2121 if (!i
->play_precork
)
2122 *(int*) argp
|= PCM_ENABLE_OUTPUT
;
2123 if (!i
->rec_precork
)
2124 *(int*) argp
|= PCM_ENABLE_INPUT
;
2128 case SNDCTL_DSP_SETTRIGGER
:
2129 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp
);
2136 i
->play_precork
= !((*(int*) argp
) & PCM_ENABLE_OUTPUT
);
2138 if (i
->play_stream
) {
2139 if (dsp_cork(i
, i
->play_stream
, !((*(int*) argp
) & PCM_ENABLE_OUTPUT
)) < 0)
2141 if (dsp_trigger(i
) < 0)
2145 i
->rec_precork
= !((*(int*) argp
) & PCM_ENABLE_INPUT
);
2147 if (i
->rec_stream
) {
2148 if (dsp_cork(i
, i
->rec_stream
, !((*(int*) argp
) & PCM_ENABLE_INPUT
)) < 0)
2154 case SNDCTL_DSP_SYNC
:
2155 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SYNC\n");
2157 if (dsp_drain(i
) < 0)
2162 case SNDCTL_DSP_GETOSPACE
:
2163 case SNDCTL_DSP_GETISPACE
: {
2164 audio_buf_info
*bi
= (audio_buf_info
*) argp
;
2168 if (request
== SNDCTL_DSP_GETOSPACE
)
2169 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOSPACE\n");
2171 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETISPACE\n");
2173 pa_threaded_mainloop_lock(i
->mainloop
);
2177 if (request
== SNDCTL_DSP_GETOSPACE
) {
2178 if (i
->play_stream
) {
2179 if ((k
= pa_stream_writable_size(i
->play_stream
)) == (size_t) -1)
2180 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2182 k
= i
->fragment_size
* i
->n_fragments
;
2185 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
2186 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2190 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2193 bi
->bytes
= k
> (size_t) l
? k
- l
: 0;
2195 if (i
->rec_stream
) {
2196 if ((k
= pa_stream_readable_size(i
->rec_stream
)) == (size_t) -1)
2197 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2202 if (ioctl(i
->app_fd
, SIOCINQ
, &l
) < 0) {
2203 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2207 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2212 bi
->fragsize
= i
->fragment_size
;
2213 bi
->fragstotal
= i
->n_fragments
;
2214 bi
->fragments
= bi
->bytes
/ bi
->fragsize
;
2216 pa_threaded_mainloop_unlock(i
->mainloop
);
2218 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi
->fragsize
, bi
->fragstotal
, bi
->bytes
, bi
->fragments
);
2223 case SOUND_PCM_READ_RATE
:
2224 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_RATE\n");
2226 pa_threaded_mainloop_lock(i
->mainloop
);
2227 *(int*) argp
= i
->sample_spec
.rate
;
2228 pa_threaded_mainloop_unlock(i
->mainloop
);
2231 case SOUND_PCM_READ_CHANNELS
:
2232 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_CHANNELS\n");
2234 pa_threaded_mainloop_lock(i
->mainloop
);
2235 *(int*) argp
= i
->sample_spec
.channels
;
2236 pa_threaded_mainloop_unlock(i
->mainloop
);
2239 case SOUND_PCM_READ_BITS
:
2240 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_BITS\n");
2242 pa_threaded_mainloop_lock(i
->mainloop
);
2243 *(int*) argp
= pa_sample_size(&i
->sample_spec
)*8;
2244 pa_threaded_mainloop_unlock(i
->mainloop
);
2247 case SNDCTL_DSP_GETOPTR
: {
2250 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOPTR\n");
2252 info
= (count_info
*) argp
;
2253 memset(info
, 0, sizeof(*info
));
2255 pa_threaded_mainloop_lock(i
->mainloop
);
2260 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop2
);
2262 if (pa_stream_get_time(i
->play_stream
, &usec
) >= 0) {
2263 size_t k
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2266 info
->bytes
= (int) k
;
2267 m
= k
/ i
->fragment_size
;
2268 info
->blocks
= m
- i
->optr_n_blocks
;
2269 i
->optr_n_blocks
= m
;
2274 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2275 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2279 pa_threaded_mainloop_wait(i
->mainloop
);
2284 pa_threaded_mainloop_unlock(i
->mainloop
);
2286 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info
->bytes
, info
->blocks
, info
->ptr
);
2291 case SNDCTL_DSP_GETIPTR
:
2292 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": invalid ioctl SNDCTL_DSP_GETIPTR\n");
2295 case SNDCTL_DSP_SETDUPLEX
:
2296 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETDUPLEX\n");
2297 /* this is a no-op */
2301 /* Mixer ioctls are valid on /dev/dsp aswell */
2302 return mixer_ioctl(i
, request
, argp
, _errno
);
2317 int ioctl(int fd
, int request
, ...) {
2319 int ioctl(int fd
, unsigned long request
, ...) {
2326 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ioctl()\n");
2328 va_start(args
, request
);
2329 argp
= va_arg(args
, void *);
2332 if (!function_enter()) {
2334 return _ioctl(fd
, request
, argp
);
2337 if (!(i
= fd_info_find(fd
))) {
2340 return _ioctl(fd
, request
, argp
);
2343 if (i
->type
== FD_INFO_MIXER
)
2344 r
= mixer_ioctl(i
, request
, argp
, &_errno
);
2346 r
= dsp_ioctl(i
, request
, argp
, &_errno
);
2361 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": close()\n");
2363 if (!function_enter()) {
2368 if (!(i
= fd_info_find(fd
))) {
2374 fd_info_remove_from_list(i
);
2382 int access(const char *pathname
, int mode
) {
2384 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": access(%s)\n", pathname
?pathname
:"NULL");
2387 (strcmp(pathname
, "/dev/dsp") != 0 &&
2388 strcmp(pathname
, "/dev/adsp") != 0 &&
2389 strcmp(pathname
, "/dev/sndstat") != 0 &&
2390 strcmp(pathname
, "/dev/mixer") != 0 )) {
2392 return _access(pathname
, mode
);
2396 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = EACCESS\n", pathname
, mode
);
2401 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = OK\n", pathname
, mode
);
2406 int stat(const char *pathname
, struct stat
*buf
) {
2408 struct stat64 parent
;
2416 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2417 strcmp(pathname
, "/dev/adsp") != 0 &&
2418 strcmp(pathname
, "/dev/sndstat") != 0 &&
2419 strcmp(pathname
, "/dev/mixer") != 0 )) {
2420 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat(%s)\n", pathname
?pathname
:"NULL");
2422 return _stat(pathname
, buf
);
2425 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stat(%s)\n", pathname
);
2429 ret
= __xstat64(_STAT_VER
, "/dev", &parent
);
2431 ret
= __xstat(_STAT_VER
, "/dev", &parent
);
2435 ret
= stat64("/dev", &parent
);
2437 ret
= stat("/dev", &parent
);
2442 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unable to stat \"/dev\"\n");
2446 buf
->st_dev
= parent
.st_dev
;
2447 buf
->st_ino
= 0xDEADBEEF; /* FIXME: Can we do this in a safe way? */
2448 buf
->st_mode
= S_IFCHR
| S_IRUSR
| S_IWUSR
;
2450 buf
->st_uid
= getuid();
2451 buf
->st_gid
= getgid();
2452 buf
->st_rdev
= 0x0E03; /* FIXME: Linux specific */
2454 buf
->st_atime
= 1181557705;
2455 buf
->st_mtime
= 1181557705;
2456 buf
->st_ctime
= 1181557705;
2457 buf
->st_blksize
= 1;
2465 int stat64(const char *pathname
, struct stat64
*buf
) {
2469 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat64(%s)\n", pathname
?pathname
:"NULL");
2473 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2474 strcmp(pathname
, "/dev/adsp") != 0 &&
2475 strcmp(pathname
, "/dev/sndstat") != 0 &&
2476 strcmp(pathname
, "/dev/mixer") != 0 )) {
2478 return _stat64(pathname
, buf
);
2481 ret
= stat(pathname
, &oldbuf
);
2485 buf
->st_dev
= oldbuf
.st_dev
;
2486 buf
->st_ino
= oldbuf
.st_ino
;
2487 buf
->st_mode
= oldbuf
.st_mode
;
2488 buf
->st_nlink
= oldbuf
.st_nlink
;
2489 buf
->st_uid
= oldbuf
.st_uid
;
2490 buf
->st_gid
= oldbuf
.st_gid
;
2491 buf
->st_rdev
= oldbuf
.st_rdev
;
2492 buf
->st_size
= oldbuf
.st_size
;
2493 buf
->st_atime
= oldbuf
.st_atime
;
2494 buf
->st_mtime
= oldbuf
.st_mtime
;
2495 buf
->st_ctime
= oldbuf
.st_ctime
;
2496 buf
->st_blksize
= oldbuf
.st_blksize
;
2497 buf
->st_blocks
= oldbuf
.st_blocks
;
2502 int open64(const char *filename
, int flags
, ...) {
2506 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open64(%s)\n", filename
?filename
:"NULL");
2508 if (flags
& O_CREAT
) {
2509 va_start(args
, flags
);
2510 if (sizeof(mode_t
) < sizeof(int))
2511 mode
= va_arg(args
, int);
2513 mode
= va_arg(args
, mode_t
);
2518 ( strcmp(filename
, "/dev/dsp") != 0 &&
2519 strcmp(filename
, "/dev/adsp") != 0 &&
2520 strcmp(filename
, "/dev/sndstat") != 0 &&
2521 strcmp(filename
, "/dev/mixer") != 0 )) {
2523 return _open64(filename
, flags
, mode
);
2526 return real_open(filename
, flags
, mode
);
2533 int __xstat(int ver
, const char *pathname
, struct stat
*buf
) {
2534 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat(%s)\n", pathname
?pathname
:"NULL");
2538 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2539 strcmp(pathname
, "/dev/adsp") != 0 &&
2540 strcmp(pathname
, "/dev/sndstat") != 0 &&
2541 strcmp(pathname
, "/dev/mixer") != 0 )) {
2543 return ___xstat(ver
, pathname
, buf
);
2546 if (ver
!= _STAT_VER
) {
2551 return stat(pathname
, buf
);
2556 int __xstat64(int ver
, const char *pathname
, struct stat64
*buf
) {
2557 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat64(%s)\n", pathname
?pathname
:"NULL");
2561 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2562 strcmp(pathname
, "/dev/adsp") != 0 &&
2563 strcmp(pathname
, "/dev/sndstat") != 0 &&
2564 strcmp(pathname
, "/dev/mixer") != 0 )) {
2565 LOAD_XSTAT64_FUNC();
2566 return ___xstat64(ver
, pathname
, buf
);
2569 if (ver
!= _STAT_VER
) {
2574 return stat64(pathname
, buf
);
2581 FILE* fopen(const char *filename
, const char *mode
) {
2586 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen(%s)\n", filename
?filename
:"NULL");
2590 ( strcmp(filename
, "/dev/dsp") != 0 &&
2591 strcmp(filename
, "/dev/adsp") != 0 &&
2592 strcmp(filename
, "/dev/sndstat") != 0 &&
2593 strcmp(filename
, "/dev/mixer") != 0 )) {
2595 return _fopen(filename
, mode
);
2611 if ((((mode
[1] == 'b') || (mode
[1] == 't')) && (mode
[2] == '+')) || (mode
[1] == '+'))
2614 if ((fd
= real_open(filename
, m
, 0)) < 0)
2617 if (!(f
= fdopen(fd
, mode
))) {
2627 FILE *fopen64(const char *filename
, const char *mode
) {
2629 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen64(%s)\n", filename
?filename
:"NULL");
2633 ( strcmp(filename
, "/dev/dsp") != 0 &&
2634 strcmp(filename
, "/dev/adsp") != 0 &&
2635 strcmp(filename
, "/dev/sndstat") != 0 &&
2636 strcmp(filename
, "/dev/mixer") != 0 )) {
2637 LOAD_FOPEN64_FUNC();
2638 return _fopen64(filename
, mode
);
2641 return fopen(filename
, mode
);
2646 int fclose(FILE *f
) {
2649 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fclose()\n");
2651 if (!function_enter()) {
2656 if (!(i
= fd_info_find(fileno(f
)))) {
2662 fd_info_remove_from_list(i
);
2664 /* Dirty trick to avoid that the fd is not freed twice, once by us
2665 * and once by the real fclose() */