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>
57 /* On some systems SIOCINQ isn't defined, but FIONREAD is just an alias */
58 #if !defined(SIOCINQ) && defined(FIONREAD)
59 # define SIOCINQ FIONREAD
62 /* make sure gcc doesn't redefine open and friends as macros */
71 typedef struct fd_info fd_info
;
74 pthread_mutex_t mutex
;
79 int app_fd
, thread_fd
;
81 pa_sample_spec sample_spec
;
85 pa_threaded_mainloop
*mainloop
;
87 pa_stream
*play_stream
;
88 pa_stream
*rec_stream
;
92 pa_io_event
*io_event
;
93 pa_io_event_flags_t io_flags
;
98 int operation_success
;
100 pa_cvolume sink_volume
, source_volume
;
101 uint32_t sink_index
, source_index
;
102 int volume_modify_count
;
106 PA_LLIST_FIELDS(fd_info
);
109 static int dsp_drain(fd_info
*i
);
110 static void fd_info_remove_from_list(fd_info
*i
);
112 static pthread_mutex_t fd_infos_mutex
= PTHREAD_MUTEX_INITIALIZER
;
113 static pthread_mutex_t func_mutex
= PTHREAD_MUTEX_INITIALIZER
;
115 static PA_LLIST_HEAD(fd_info
, fd_infos
) = NULL
;
117 static int (*_ioctl
)(int, int, void*) = NULL
;
118 static int (*_close
)(int) = NULL
;
119 static int (*_open
)(const char *, int, mode_t
) = NULL
;
120 static FILE* (*_fopen
)(const char *path
, const char *mode
) = NULL
;
121 static int (*_stat
)(const char *, struct stat
*) = NULL
;
123 static int (*___xstat
)(int, const char *, struct stat
*) = NULL
;
126 static int (*_open64
)(const char *, int, mode_t
) = NULL
;
127 static FILE* (*_fopen64
)(const char *path
, const char *mode
) = NULL
;
128 static int (*_stat64
)(const char *, struct stat64
*) = NULL
;
130 static int (*___xstat64
)(int, const char *, struct stat64
*) = NULL
;
133 static int (*_fclose
)(FILE *f
) = NULL
;
134 static int (*_access
)(const char *, int) = NULL
;
136 /* dlsym() violates ISO C, so confide the breakage into this function to
138 typedef void (*fnptr
)(void);
139 static inline fnptr
dlsym_fn(void *handle
, const char *symbol
) {
140 return (fnptr
) (long) dlsym(handle
, symbol
);
143 #define LOAD_IOCTL_FUNC() \
145 pthread_mutex_lock(&func_mutex); \
147 _ioctl = (int (*)(int, int, void*)) dlsym_fn(RTLD_NEXT, "ioctl"); \
148 pthread_mutex_unlock(&func_mutex); \
151 #define LOAD_OPEN_FUNC() \
153 pthread_mutex_lock(&func_mutex); \
155 _open = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open"); \
156 pthread_mutex_unlock(&func_mutex); \
159 #define LOAD_OPEN64_FUNC() \
161 pthread_mutex_lock(&func_mutex); \
163 _open64 = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open64"); \
164 pthread_mutex_unlock(&func_mutex); \
167 #define LOAD_CLOSE_FUNC() \
169 pthread_mutex_lock(&func_mutex); \
171 _close = (int (*)(int)) dlsym_fn(RTLD_NEXT, "close"); \
172 pthread_mutex_unlock(&func_mutex); \
175 #define LOAD_ACCESS_FUNC() \
177 pthread_mutex_lock(&func_mutex); \
179 _access = (int (*)(const char*, int)) dlsym_fn(RTLD_NEXT, "access"); \
180 pthread_mutex_unlock(&func_mutex); \
183 #define LOAD_STAT_FUNC() \
185 pthread_mutex_lock(&func_mutex); \
187 _stat = (int (*)(const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "stat"); \
188 pthread_mutex_unlock(&func_mutex); \
191 #define LOAD_STAT64_FUNC() \
193 pthread_mutex_lock(&func_mutex); \
195 _stat64 = (int (*)(const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "stat64"); \
196 pthread_mutex_unlock(&func_mutex); \
199 #define LOAD_XSTAT_FUNC() \
201 pthread_mutex_lock(&func_mutex); \
203 ___xstat = (int (*)(int, const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "__xstat"); \
204 pthread_mutex_unlock(&func_mutex); \
207 #define LOAD_XSTAT64_FUNC() \
209 pthread_mutex_lock(&func_mutex); \
211 ___xstat64 = (int (*)(int, const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "__xstat64"); \
212 pthread_mutex_unlock(&func_mutex); \
215 #define LOAD_FOPEN_FUNC() \
217 pthread_mutex_lock(&func_mutex); \
219 _fopen = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen"); \
220 pthread_mutex_unlock(&func_mutex); \
223 #define LOAD_FOPEN64_FUNC() \
225 pthread_mutex_lock(&func_mutex); \
227 _fopen64 = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen64"); \
228 pthread_mutex_unlock(&func_mutex); \
231 #define LOAD_FCLOSE_FUNC() \
233 pthread_mutex_lock(&func_mutex); \
235 _fclose = (int (*)(FILE *)) dlsym_fn(RTLD_NEXT, "fclose"); \
236 pthread_mutex_unlock(&func_mutex); \
239 #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \
240 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \
241 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
246 #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \
247 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
248 !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \
249 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
254 #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \
255 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
256 !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \
257 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
262 static void debug(int level
, const char *format
, ...) PA_GCC_PRINTF_ATTR(2,3);
264 #define DEBUG_LEVEL_ALWAYS 0
265 #define DEBUG_LEVEL_NORMAL 1
266 #define DEBUG_LEVEL_VERBOSE 2
268 static void debug(int level
, const char *format
, ...) {
270 const char *dlevel_s
;
273 dlevel_s
= getenv("PADSP_DEBUG");
277 dlevel
= atoi(dlevel_s
);
282 va_start(ap
, format
);
283 vfprintf(stderr
, format
, ap
);
287 static int padsp_disabled(void) {
289 static int sym_resolved
= 0;
291 /* If the current process has a symbol __padsp_disabled__ we use
292 * it to detect whether we should enable our stuff or not. A
293 * program needs to be compiled with -rdynamic for this to work!
294 * The symbol must be an int containing a three bit bitmask: bit 1
295 * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat
296 * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value
297 * of 7 disables padsp entirely. */
299 pthread_mutex_lock(&func_mutex
);
301 sym
= (int*) dlsym(RTLD_DEFAULT
, "__padsp_disabled__");
304 pthread_mutex_unlock(&func_mutex
);
312 static int dsp_cloak_enable(void) {
313 if (padsp_disabled() & 1)
316 if (getenv("PADSP_NO_DSP") || getenv("PULSE_INTERNAL"))
322 static int sndstat_cloak_enable(void) {
323 if (padsp_disabled() & 2)
326 if (getenv("PADSP_NO_SNDSTAT") || getenv("PULSE_INTERNAL"))
332 static int mixer_cloak_enable(void) {
333 if (padsp_disabled() & 4)
336 if (getenv("PADSP_NO_MIXER") || getenv("PULSE_INTERNAL"))
341 static pthread_key_t recursion_key
;
343 static void recursion_key_alloc(void) {
344 pthread_key_create(&recursion_key
, NULL
);
347 static int function_enter(void) {
348 /* Avoid recursive calls */
349 static pthread_once_t recursion_key_once
= PTHREAD_ONCE_INIT
;
350 pthread_once(&recursion_key_once
, recursion_key_alloc
);
352 if (pthread_getspecific(recursion_key
))
355 pthread_setspecific(recursion_key
, (void*) 1);
359 static void function_exit(void) {
360 pthread_setspecific(recursion_key
, NULL
);
363 static void fd_info_free(fd_info
*i
) {
366 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": freeing fd info (fd=%i)\n", i
->app_fd
);
371 pa_threaded_mainloop_stop(i
->mainloop
);
373 if (i
->play_stream
) {
374 pa_stream_disconnect(i
->play_stream
);
375 pa_stream_unref(i
->play_stream
);
379 pa_stream_disconnect(i
->rec_stream
);
380 pa_stream_unref(i
->rec_stream
);
384 pa_context_disconnect(i
->context
);
385 pa_context_unref(i
->context
);
389 pa_threaded_mainloop_free(i
->mainloop
);
391 if (i
->app_fd
>= 0) {
396 if (i
->thread_fd
>= 0) {
398 _close(i
->thread_fd
);
403 pthread_mutex_destroy(&i
->mutex
);
407 static fd_info
*fd_info_ref(fd_info
*i
) {
410 pthread_mutex_lock(&i
->mutex
);
414 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ref++, now %i\n", i
->ref
);
415 pthread_mutex_unlock(&i
->mutex
);
420 static void fd_info_unref(fd_info
*i
) {
422 pthread_mutex_lock(&i
->mutex
);
425 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ref--, now %i\n", i
->ref
);
426 pthread_mutex_unlock(&i
->mutex
);
432 static void context_state_cb(pa_context
*c
, void *userdata
) {
433 fd_info
*i
= userdata
;
436 switch (pa_context_get_state(c
)) {
437 case PA_CONTEXT_READY
:
438 case PA_CONTEXT_TERMINATED
:
439 case PA_CONTEXT_FAILED
:
440 pa_threaded_mainloop_signal(i
->mainloop
, 0);
443 case PA_CONTEXT_UNCONNECTED
:
444 case PA_CONTEXT_CONNECTING
:
445 case PA_CONTEXT_AUTHORIZING
:
446 case PA_CONTEXT_SETTING_NAME
:
451 static void reset_params(fd_info
*i
) {
454 i
->sample_spec
.format
= PA_SAMPLE_U8
;
455 i
->sample_spec
.channels
= 1;
456 i
->sample_spec
.rate
= 8000;
457 i
->fragment_size
= 0;
461 static const char *client_name(char *buf
, size_t n
) {
465 if ((e
= getenv("PADSP_CLIENT_NAME")))
468 if (pa_get_binary_name(p
, sizeof(p
)))
469 snprintf(buf
, n
, "OSS Emulation[%s]", p
);
471 snprintf(buf
, n
, "OSS");
476 static const char *stream_name(void) {
479 if ((e
= getenv("PADSP_STREAM_NAME")))
482 return "Audio Stream";
485 static void atfork_prepare(void) {
488 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_prepare() enter\n");
492 pthread_mutex_lock(&fd_infos_mutex
);
494 for (i
= fd_infos
; i
; i
= i
->next
) {
495 pthread_mutex_lock(&i
->mutex
);
496 pa_threaded_mainloop_lock(i
->mainloop
);
499 pthread_mutex_lock(&func_mutex
);
501 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_prepare() exit\n");
504 static void atfork_parent(void) {
507 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_parent() enter\n");
509 pthread_mutex_unlock(&func_mutex
);
511 for (i
= fd_infos
; i
; i
= i
->next
) {
512 pa_threaded_mainloop_unlock(i
->mainloop
);
513 pthread_mutex_unlock(&i
->mutex
);
516 pthread_mutex_unlock(&fd_infos_mutex
);
520 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_parent() exit\n");
523 static void atfork_child(void) {
526 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_child() enter\n");
528 /* We do only the bare minimum to get all fds closed */
529 pthread_mutex_init(&func_mutex
, NULL
);
530 pthread_mutex_init(&fd_infos_mutex
, NULL
);
532 for (i
= fd_infos
; i
; i
= i
->next
) {
533 pthread_mutex_init(&i
->mutex
, NULL
);
536 pa_context_disconnect(i
->context
);
537 pa_context_unref(i
->context
);
541 if (i
->play_stream
) {
542 pa_stream_unref(i
->play_stream
);
543 i
->play_stream
= NULL
;
547 pa_stream_unref(i
->rec_stream
);
548 i
->rec_stream
= NULL
;
551 if (i
->app_fd
>= 0) {
557 if (i
->thread_fd
>= 0) {
559 _close(i
->thread_fd
);
568 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_child() exit\n");
571 static void install_atfork(void) {
572 pthread_atfork(atfork_prepare
, atfork_parent
, atfork_child
);
575 static void stream_success_cb(pa_stream
*s
, int success
, void *userdata
) {
576 fd_info
*i
= userdata
;
581 i
->operation_success
= success
;
582 pa_threaded_mainloop_signal(i
->mainloop
, 0);
585 static void context_success_cb(pa_context
*c
, int success
, void *userdata
) {
586 fd_info
*i
= userdata
;
591 i
->operation_success
= success
;
592 pa_threaded_mainloop_signal(i
->mainloop
, 0);
595 static fd_info
* fd_info_new(fd_info_type_t type
, int *_errno
) {
597 int sfds
[2] = { -1, -1 };
599 static pthread_once_t install_atfork_once
= PTHREAD_ONCE_INIT
;
601 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fd_info_new()\n");
603 signal(SIGPIPE
, SIG_IGN
); /* Yes, ugly as hell */
605 pthread_once(&install_atfork_once
, install_atfork
);
607 if (!(i
= malloc(sizeof(fd_info
)))) {
612 i
->app_fd
= i
->thread_fd
= -1;
617 i
->play_stream
= NULL
;
618 i
->rec_stream
= NULL
;
623 pthread_mutex_init(&i
->mutex
, NULL
);
628 pa_cvolume_reset(&i
->sink_volume
, 2);
629 pa_cvolume_reset(&i
->source_volume
, 2);
630 i
->volume_modify_count
= 0;
631 i
->sink_index
= (uint32_t) -1;
632 i
->source_index
= (uint32_t) -1;
633 i
->optr_n_blocks
= 0;
634 PA_LLIST_INIT(fd_info
, i
);
638 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sfds
) < 0) {
640 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": socket() failed: %s\n", strerror(errno
));
645 i
->thread_fd
= sfds
[1];
647 if (!(i
->mainloop
= pa_threaded_mainloop_new())) {
649 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_threaded_mainloop_new() failed\n");
653 if (!(i
->context
= pa_context_new(pa_threaded_mainloop_get_api(i
->mainloop
), client_name(name
, sizeof(name
))))) {
655 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_new() failed\n");
659 pa_context_set_state_callback(i
->context
, context_state_cb
, i
);
661 if (pa_context_connect(i
->context
, NULL
, 0, NULL
) < 0) {
662 *_errno
= ECONNREFUSED
;
663 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
667 pa_threaded_mainloop_lock(i
->mainloop
);
669 if (pa_threaded_mainloop_start(i
->mainloop
) < 0) {
671 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_threaded_mainloop_start() failed\n");
672 goto unlock_and_fail
;
675 /* Wait until the context is ready */
676 pa_threaded_mainloop_wait(i
->mainloop
);
678 if (pa_context_get_state(i
->context
) != PA_CONTEXT_READY
) {
679 *_errno
= ECONNREFUSED
;
680 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
681 goto unlock_and_fail
;
684 pa_threaded_mainloop_unlock(i
->mainloop
);
689 pa_threaded_mainloop_unlock(i
->mainloop
);
699 static void fd_info_add_to_list(fd_info
*i
) {
702 pthread_mutex_lock(&fd_infos_mutex
);
703 PA_LLIST_PREPEND(fd_info
, fd_infos
, i
);
704 pthread_mutex_unlock(&fd_infos_mutex
);
709 static void fd_info_remove_from_list(fd_info
*i
) {
712 pthread_mutex_lock(&fd_infos_mutex
);
713 PA_LLIST_REMOVE(fd_info
, fd_infos
, i
);
714 pthread_mutex_unlock(&fd_infos_mutex
);
719 static fd_info
* fd_info_find(int fd
) {
722 pthread_mutex_lock(&fd_infos_mutex
);
724 for (i
= fd_infos
; i
; i
= i
->next
)
725 if (i
->app_fd
== fd
&& !i
->unusable
) {
730 pthread_mutex_unlock(&fd_infos_mutex
);
735 static void fix_metrics(fd_info
*i
) {
737 char t
[PA_SAMPLE_SPEC_SNPRINT_MAX
];
739 fs
= pa_frame_size(&i
->sample_spec
);
741 /* Don't fix things more than necessary */
742 if ((i
->fragment_size
% fs
) == 0 &&
743 i
->n_fragments
>= 2 &&
744 i
->fragment_size
> 0)
747 i
->fragment_size
= (i
->fragment_size
/fs
)*fs
;
749 /* Number of fragments set? */
750 if (i
->n_fragments
< 2) {
751 if (i
->fragment_size
> 0) {
752 i
->n_fragments
= (unsigned) (pa_bytes_per_second(&i
->sample_spec
) / 2 / i
->fragment_size
);
753 if (i
->n_fragments
< 2)
759 /* Fragment size set? */
760 if (i
->fragment_size
<= 0) {
761 i
->fragment_size
= pa_bytes_per_second(&i
->sample_spec
) / 2 / i
->n_fragments
;
762 if (i
->fragment_size
< 1024)
763 i
->fragment_size
= 1024;
766 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": sample spec: %s\n", pa_sample_spec_snprint(t
, sizeof(t
), &i
->sample_spec
));
767 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fixated metrics to %i fragments, %li bytes each.\n", i
->n_fragments
, (long)i
->fragment_size
);
770 static void stream_request_cb(pa_stream
*s
, size_t length
, void *userdata
) {
771 fd_info
*i
= userdata
;
775 pa_mainloop_api
*api
;
778 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
780 if (s
== i
->play_stream
) {
781 n
= pa_stream_writable_size(i
->play_stream
);
782 if (n
== (size_t)-1) {
783 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n",
784 pa_strerror(pa_context_errno(i
->context
)));
787 if (n
>= i
->fragment_size
)
788 i
->io_flags
|= PA_IO_EVENT_INPUT
;
790 i
->io_flags
&= ~PA_IO_EVENT_INPUT
;
793 if (s
== i
->rec_stream
) {
794 n
= pa_stream_readable_size(i
->rec_stream
);
795 if (n
== (size_t)-1) {
796 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n",
797 pa_strerror(pa_context_errno(i
->context
)));
800 if (n
>= i
->fragment_size
)
801 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
803 i
->io_flags
&= ~PA_IO_EVENT_OUTPUT
;
806 api
->io_enable(i
->io_event
, i
->io_flags
);
810 static void stream_latency_update_cb(pa_stream
*s
, void *userdata
) {
811 fd_info
*i
= userdata
;
814 pa_threaded_mainloop_signal(i
->mainloop
, 0);
817 static void fd_info_shutdown(fd_info
*i
) {
821 pa_mainloop_api
*api
;
822 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
823 api
->io_free(i
->io_event
);
828 if (i
->thread_fd
>= 0) {
834 static int fd_info_copy_data(fd_info
*i
, int force
) {
837 if (!i
->play_stream
&& !i
->rec_stream
)
840 if ((i
->play_stream
) && (pa_stream_get_state(i
->play_stream
) == PA_STREAM_READY
)) {
841 n
= pa_stream_writable_size(i
->play_stream
);
843 if (n
== (size_t)-1) {
844 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n",
845 pa_strerror(pa_context_errno(i
->context
)));
849 while (n
>= i
->fragment_size
|| force
) {
853 if (!(i
->buf
= malloc(i
->fragment_size
))) {
854 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": malloc() failed.\n");
859 if ((r
= read(i
->thread_fd
, i
->buf
, i
->fragment_size
)) <= 0) {
864 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": read(): %s\n", r
== 0 ? "EOF" : strerror(errno
));
868 if (pa_stream_write(i
->play_stream
, i
->buf
, (size_t) r
, free
, 0LL, PA_SEEK_RELATIVE
) < 0) {
869 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
875 assert(n
>= (size_t) r
);
879 if (n
>= i
->fragment_size
)
880 i
->io_flags
|= PA_IO_EVENT_INPUT
;
882 i
->io_flags
&= ~PA_IO_EVENT_INPUT
;
885 if ((i
->rec_stream
) && (pa_stream_get_state(i
->rec_stream
) == PA_STREAM_READY
)) {
886 n
= pa_stream_readable_size(i
->rec_stream
);
888 if (n
== (size_t)-1) {
889 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n",
890 pa_strerror(pa_context_errno(i
->context
)));
894 while (n
>= i
->fragment_size
|| force
) {
900 if (pa_stream_peek(i
->rec_stream
, &data
, &len
) < 0) {
901 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_peek(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
908 buf
= (const char*)data
+ i
->rec_offset
;
910 if ((r
= write(i
->thread_fd
, buf
, len
- i
->rec_offset
)) <= 0) {
915 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write(): %s\n", strerror(errno
));
919 assert((size_t)r
<= len
- i
->rec_offset
);
920 i
->rec_offset
+= (size_t) r
;
922 if (i
->rec_offset
== len
) {
923 if (pa_stream_drop(i
->rec_stream
) < 0) {
924 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
930 assert(n
>= (size_t) r
);
934 if (n
>= i
->fragment_size
)
935 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
937 i
->io_flags
&= ~PA_IO_EVENT_OUTPUT
;
941 pa_mainloop_api
*api
;
943 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
944 api
->io_enable(i
->io_event
, i
->io_flags
);
947 /* So, we emptied the socket now, let's tell dsp_empty_socket()
949 pa_threaded_mainloop_signal(i
->mainloop
, 0);
954 static void stream_state_cb(pa_stream
*s
, void * userdata
) {
955 fd_info
*i
= userdata
;
958 switch (pa_stream_get_state(s
)) {
960 case PA_STREAM_READY
:
961 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stream established.\n");
964 case PA_STREAM_FAILED
:
965 if (s
== i
->play_stream
) {
966 debug(DEBUG_LEVEL_NORMAL
,
967 __FILE__
": pa_stream_connect_playback() failed: %s\n",
968 pa_strerror(pa_context_errno(i
->context
)));
969 pa_stream_unref(i
->play_stream
);
970 i
->play_stream
= NULL
;
971 } else if (s
== i
->rec_stream
) {
972 debug(DEBUG_LEVEL_NORMAL
,
973 __FILE__
": pa_stream_connect_record() failed: %s\n",
974 pa_strerror(pa_context_errno(i
->context
)));
975 pa_stream_unref(i
->rec_stream
);
976 i
->rec_stream
= NULL
;
981 case PA_STREAM_TERMINATED
:
982 case PA_STREAM_UNCONNECTED
:
983 case PA_STREAM_CREATING
:
988 static int create_playback_stream(fd_info
*i
) {
996 if (!(i
->play_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
997 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1001 pa_stream_set_state_callback(i
->play_stream
, stream_state_cb
, i
);
1002 pa_stream_set_write_callback(i
->play_stream
, stream_request_cb
, i
);
1003 pa_stream_set_latency_update_callback(i
->play_stream
, stream_latency_update_cb
, i
);
1005 memset(&attr
, 0, sizeof(attr
));
1006 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1007 attr
.tlength
= (uint32_t) (i
->fragment_size
* i
->n_fragments
);
1008 attr
.prebuf
= (uint32_t) i
->fragment_size
;
1009 attr
.minreq
= (uint32_t) i
->fragment_size
;
1011 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
|PA_STREAM_EARLY_REQUESTS
;
1012 if (i
->play_precork
) {
1013 flags
|= PA_STREAM_START_CORKED
;
1014 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1016 if (pa_stream_connect_playback(i
->play_stream
, NULL
, &attr
, flags
, NULL
, NULL
) < 0) {
1017 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1021 n
= (int) i
->fragment_size
;
1022 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1023 n
= (int) i
->fragment_size
;
1024 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1032 static int create_record_stream(fd_info
*i
) {
1033 pa_buffer_attr attr
;
1040 if (!(i
->rec_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
1041 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1045 pa_stream_set_state_callback(i
->rec_stream
, stream_state_cb
, i
);
1046 pa_stream_set_read_callback(i
->rec_stream
, stream_request_cb
, i
);
1047 pa_stream_set_latency_update_callback(i
->rec_stream
, stream_latency_update_cb
, i
);
1049 memset(&attr
, 0, sizeof(attr
));
1050 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1051 attr
.fragsize
= (uint32_t) i
->fragment_size
;
1053 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
;
1054 if (i
->rec_precork
) {
1055 flags
|= PA_STREAM_START_CORKED
;
1056 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1058 if (pa_stream_connect_record(i
->rec_stream
, NULL
, &attr
, flags
) < 0) {
1059 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1063 n
= (int) i
->fragment_size
;
1064 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1065 n
= (int) i
->fragment_size
;
1066 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1074 static void free_streams(fd_info
*i
) {
1077 if (i
->play_stream
) {
1078 pa_stream_disconnect(i
->play_stream
);
1079 pa_stream_unref(i
->play_stream
);
1080 i
->play_stream
= NULL
;
1081 i
->io_flags
|= PA_IO_EVENT_INPUT
;
1084 if (i
->rec_stream
) {
1085 pa_stream_disconnect(i
->rec_stream
);
1086 pa_stream_unref(i
->rec_stream
);
1087 i
->rec_stream
= NULL
;
1088 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
1092 pa_mainloop_api
*api
;
1094 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1095 api
->io_enable(i
->io_event
, i
->io_flags
);
1099 static void io_event_cb(pa_mainloop_api
*api
, pa_io_event
*e
, int fd
, pa_io_event_flags_t flags
, void *userdata
) {
1100 fd_info
*i
= userdata
;
1102 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1104 if (flags
& PA_IO_EVENT_INPUT
) {
1106 if (!i
->play_stream
) {
1107 if (create_playback_stream(i
) < 0)
1110 if (fd_info_copy_data(i
, 0) < 0)
1114 } else if (flags
& PA_IO_EVENT_OUTPUT
) {
1116 if (!i
->rec_stream
) {
1117 if (create_record_stream(i
) < 0)
1120 if (fd_info_copy_data(i
, 0) < 0)
1124 } else if (flags
& (PA_IO_EVENT_HANGUP
|PA_IO_EVENT_ERROR
))
1130 /* We can't do anything better than removing the event source */
1131 fd_info_shutdown(i
);
1134 static int dsp_open(int flags
, int *_errno
) {
1136 pa_mainloop_api
*api
;
1140 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open()\n");
1142 if (!(i
= fd_info_new(FD_INFO_STREAM
, _errno
)))
1145 if ((flags
& O_NONBLOCK
) == O_NONBLOCK
) {
1146 if ((f
= fcntl(i
->app_fd
, F_GETFL
)) >= 0)
1147 fcntl(i
->app_fd
, F_SETFL
, f
|O_NONBLOCK
);
1149 if ((f
= fcntl(i
->thread_fd
, F_GETFL
)) >= 0)
1150 fcntl(i
->thread_fd
, F_SETFL
, f
|O_NONBLOCK
);
1152 fcntl(i
->app_fd
, F_SETFD
, FD_CLOEXEC
);
1153 fcntl(i
->thread_fd
, F_SETFD
, FD_CLOEXEC
);
1155 pa_threaded_mainloop_lock(i
->mainloop
);
1156 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1158 switch (flags
& O_ACCMODE
) {
1160 i
->io_flags
= PA_IO_EVENT_OUTPUT
;
1161 shutdown(i
->thread_fd
, SHUT_RD
);
1162 shutdown(i
->app_fd
, SHUT_WR
);
1165 i
->io_flags
= PA_IO_EVENT_INPUT
;
1166 shutdown(i
->thread_fd
, SHUT_WR
);
1167 shutdown(i
->app_fd
, SHUT_RD
);
1170 i
->io_flags
= PA_IO_EVENT_INPUT
| PA_IO_EVENT_OUTPUT
;
1176 if (!(i
->io_event
= api
->io_new(api
, i
->thread_fd
, i
->io_flags
, io_event_cb
, i
)))
1179 pa_threaded_mainloop_unlock(i
->mainloop
);
1181 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() succeeded, fd=%i\n", i
->app_fd
);
1183 fd_info_add_to_list(i
);
1190 pa_threaded_mainloop_unlock(i
->mainloop
);
1197 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() failed\n");
1202 static void sink_info_cb(pa_context
*context
, const pa_sink_info
*si
, int eol
, void *userdata
) {
1203 fd_info
*i
= userdata
;
1205 if (!si
|| eol
< 0) {
1206 i
->operation_success
= 0;
1207 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1214 if (!pa_cvolume_equal(&i
->sink_volume
, &si
->volume
))
1215 i
->volume_modify_count
++;
1217 i
->sink_volume
= si
->volume
;
1218 i
->sink_index
= si
->index
;
1220 i
->operation_success
= 1;
1221 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1224 static void source_info_cb(pa_context
*context
, const pa_source_info
*si
, int eol
, void *userdata
) {
1225 fd_info
*i
= userdata
;
1227 if (!si
|| eol
< 0) {
1228 i
->operation_success
= 0;
1229 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1236 if (!pa_cvolume_equal(&i
->source_volume
, &si
->volume
))
1237 i
->volume_modify_count
++;
1239 i
->source_volume
= si
->volume
;
1240 i
->source_index
= si
->index
;
1242 i
->operation_success
= 1;
1243 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1246 static void subscribe_cb(pa_context
*context
, pa_subscription_event_type_t t
, uint32_t idx
, void *userdata
) {
1247 fd_info
*i
= userdata
;
1248 pa_operation
*o
= NULL
;
1250 if (i
->sink_index
!= idx
)
1253 if ((t
& PA_SUBSCRIPTION_EVENT_TYPE_MASK
) != PA_SUBSCRIPTION_EVENT_CHANGE
)
1256 if (!(o
= pa_context_get_sink_info_by_index(i
->context
, i
->sink_index
, sink_info_cb
, i
))) {
1257 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1261 pa_operation_unref(o
);
1264 static int mixer_open(int flags
, int *_errno
) {
1266 pa_operation
*o
= NULL
;
1269 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open()\n");
1271 if (!(i
= fd_info_new(FD_INFO_MIXER
, _errno
)))
1274 pa_threaded_mainloop_lock(i
->mainloop
);
1276 pa_context_set_subscribe_callback(i
->context
, subscribe_cb
, i
);
1278 if (!(o
= pa_context_subscribe(i
->context
, PA_SUBSCRIPTION_MASK_SINK
| PA_SUBSCRIPTION_MASK_SOURCE
, context_success_cb
, i
))) {
1279 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1284 i
->operation_success
= 0;
1285 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1286 pa_threaded_mainloop_wait(i
->mainloop
);
1287 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1290 pa_operation_unref(o
);
1293 if (!i
->operation_success
) {
1294 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1301 if (!(o
= pa_context_get_sink_info_by_name(i
->context
, NULL
, sink_info_cb
, i
))) {
1302 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1307 i
->operation_success
= 0;
1308 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1309 pa_threaded_mainloop_wait(i
->mainloop
);
1310 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1313 pa_operation_unref(o
);
1316 if (!i
->operation_success
) {
1317 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1322 /* Get source info */
1324 if (!(o
= pa_context_get_source_info_by_name(i
->context
, NULL
, source_info_cb
, i
))) {
1325 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1330 i
->operation_success
= 0;
1331 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1332 pa_threaded_mainloop_wait(i
->mainloop
);
1333 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1336 pa_operation_unref(o
);
1339 if (!i
->operation_success
) {
1340 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1345 pa_threaded_mainloop_unlock(i
->mainloop
);
1347 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() succeeded, fd=%i\n", i
->app_fd
);
1349 fd_info_add_to_list(i
);
1357 pa_operation_unref(o
);
1359 pa_threaded_mainloop_unlock(i
->mainloop
);
1366 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() failed\n");
1371 static int sndstat_open(int flags
, int *_errno
) {
1372 static const char sndstat
[] =
1373 "Sound Driver:3.8.1a-980706 (PulseAudio Virtual OSS)\n"
1375 "Config options: 0\n"
1377 "Installed drivers:\n"
1378 "Type 255: PulseAudio Virtual OSS\n"
1381 "PulseAudio Virtual OSS\n"
1384 "0: PulseAudio Virtual OSS\n"
1386 "Synth devices: NOT ENABLED IN CONFIG\n"
1393 "0: PulseAudio Virtual OSS\n";
1395 char fn
[] = "/tmp/padsp-sndstat-XXXXXX";
1400 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": sndstat_open()\n");
1402 if (flags
!= O_RDONLY
1404 && flags
!= (O_RDONLY
|O_LARGEFILE
)
1408 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": bad access!\n");
1419 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mkstemp() failed: %s\n", strerror(errno
));
1425 if (write(fd
, sndstat
, sizeof(sndstat
) -1) != sizeof(sndstat
)-1) {
1427 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write() failed: %s\n", strerror(errno
));
1431 if (lseek(fd
, SEEK_SET
, 0) < 0) {
1433 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": lseek() failed: %s\n", strerror(errno
));
1445 static int real_open(const char *filename
, int flags
, mode_t mode
) {
1448 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open(%s)\n", filename
?filename
:"NULL");
1450 if (!function_enter()) {
1452 return _open(filename
, flags
, mode
);
1455 if (filename
&& dsp_cloak_enable() && (strcmp(filename
, "/dev/dsp") == 0 || strcmp(filename
, "/dev/adsp") == 0))
1456 r
= dsp_open(flags
, &_errno
);
1457 else if (filename
&& mixer_cloak_enable() && strcmp(filename
, "/dev/mixer") == 0)
1458 r
= mixer_open(flags
, &_errno
);
1459 else if (filename
&& sndstat_cloak_enable() && strcmp(filename
, "/dev/sndstat") == 0)
1460 r
= sndstat_open(flags
, &_errno
);
1464 return _open(filename
, flags
, mode
);
1475 int open(const char *filename
, int flags
, ...) {
1479 if (flags
& O_CREAT
) {
1480 va_start(args
, flags
);
1481 if (sizeof(mode_t
) < sizeof(int))
1482 mode
= (mode_t
) va_arg(args
, int);
1484 mode
= va_arg(args
, mode_t
);
1488 return real_open(filename
, flags
, mode
);
1491 static int mixer_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1495 case SOUND_MIXER_READ_DEVMASK
:
1496 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_DEVMASK\n");
1498 *(int*) argp
= SOUND_MASK_PCM
| SOUND_MASK_IGAIN
;
1501 case SOUND_MIXER_READ_RECMASK
:
1502 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECMASK\n");
1504 *(int*) argp
= SOUND_MASK_IGAIN
;
1507 case SOUND_MIXER_READ_STEREODEVS
:
1508 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_STEREODEVS\n");
1510 pa_threaded_mainloop_lock(i
->mainloop
);
1512 if (i
->sink_volume
.channels
> 1)
1513 *(int*) argp
|= SOUND_MASK_PCM
;
1514 if (i
->source_volume
.channels
> 1)
1515 *(int*) argp
|= SOUND_MASK_IGAIN
;
1516 pa_threaded_mainloop_unlock(i
->mainloop
);
1520 case SOUND_MIXER_READ_RECSRC
:
1521 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECSRC\n");
1523 *(int*) argp
= SOUND_MASK_IGAIN
;
1526 case SOUND_MIXER_WRITE_RECSRC
:
1527 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_RECSRC\n");
1530 case SOUND_MIXER_READ_CAPS
:
1531 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_CAPS\n");
1536 case SOUND_MIXER_READ_PCM
:
1537 case SOUND_MIXER_READ_IGAIN
: {
1540 if (request
== SOUND_MIXER_READ_PCM
)
1541 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_PCM\n");
1543 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_IGAIN\n");
1545 pa_threaded_mainloop_lock(i
->mainloop
);
1547 if (request
== SOUND_MIXER_READ_PCM
)
1548 v
= &i
->sink_volume
;
1550 v
= &i
->source_volume
;
1553 ((v
->values
[0]*100/PA_VOLUME_NORM
)) |
1554 ((v
->values
[v
->channels
> 1 ? 1 : 0]*100/PA_VOLUME_NORM
) << 8);
1556 pa_threaded_mainloop_unlock(i
->mainloop
);
1561 case SOUND_MIXER_WRITE_PCM
:
1562 case SOUND_MIXER_WRITE_IGAIN
: {
1565 if (request
== SOUND_MIXER_WRITE_PCM
)
1566 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_PCM\n");
1568 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_IGAIN\n");
1570 pa_threaded_mainloop_lock(i
->mainloop
);
1572 if (request
== SOUND_MIXER_WRITE_PCM
) {
1574 pv
= &i
->sink_volume
;
1576 v
= i
->source_volume
;
1577 pv
= &i
->source_volume
;
1580 pv
->values
[0] = ((*(int*) argp
& 0xFF)*PA_VOLUME_NORM
)/100;
1581 pv
->values
[1] = ((*(int*) argp
>> 8)*PA_VOLUME_NORM
)/100;
1583 if (!pa_cvolume_equal(pv
, &v
)) {
1586 if (request
== SOUND_MIXER_WRITE_PCM
)
1587 o
= pa_context_set_sink_volume_by_index(i
->context
, i
->sink_index
, pv
, context_success_cb
, i
);
1589 o
= pa_context_set_source_volume_by_index(i
->context
, i
->source_index
, pv
, context_success_cb
, i
);
1592 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed set volume: %s", pa_strerror(pa_context_errno(i
->context
)));
1595 i
->operation_success
= 0;
1596 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1597 CONTEXT_CHECK_DEAD_GOTO(i
, exit_loop
);
1599 pa_threaded_mainloop_wait(i
->mainloop
);
1603 if (!i
->operation_success
)
1604 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1606 pa_operation_unref(o
);
1609 /* We don't wait for completion here */
1610 i
->volume_modify_count
++;
1613 pa_threaded_mainloop_unlock(i
->mainloop
);
1618 case SOUND_MIXER_INFO
: {
1619 mixer_info
*mi
= argp
;
1621 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_INFO\n");
1623 memset(mi
, 0, sizeof(mixer_info
));
1624 strncpy(mi
->id
, "PULSEAUDIO", sizeof(mi
->id
));
1625 strncpy(mi
->name
, "PulseAudio Virtual OSS", sizeof(mi
->name
));
1626 pa_threaded_mainloop_lock(i
->mainloop
);
1627 mi
->modify_counter
= i
->volume_modify_count
;
1628 pa_threaded_mainloop_unlock(i
->mainloop
);
1633 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unknown ioctl 0x%08lx\n", request
);
1646 static int map_format(int *fmt
, pa_sample_spec
*ss
) {
1650 ss
->format
= PA_SAMPLE_ULAW
;
1654 ss
->format
= PA_SAMPLE_ALAW
;
1661 ss
->format
= PA_SAMPLE_U8
;
1668 ss
->format
= PA_SAMPLE_S16BE
;
1675 ss
->format
= PA_SAMPLE_S16LE
;
1679 ss
->format
= PA_SAMPLE_S16NE
;
1687 static int map_format_back(pa_sample_format_t format
) {
1689 case PA_SAMPLE_S16LE
: return AFMT_S16_LE
;
1690 case PA_SAMPLE_S16BE
: return AFMT_S16_BE
;
1691 case PA_SAMPLE_ULAW
: return AFMT_MU_LAW
;
1692 case PA_SAMPLE_ALAW
: return AFMT_A_LAW
;
1693 case PA_SAMPLE_U8
: return AFMT_U8
;
1699 static int dsp_flush_fd(int fd
) {
1703 if (ioctl(fd
, SIOCINQ
, &l
) < 0) {
1704 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1712 k
= (size_t) l
> sizeof(buf
) ? sizeof(buf
) : (size_t) l
;
1713 if (read(fd
, buf
, k
) < 0)
1714 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": read(): %s\n", strerror(errno
));
1720 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1725 static int dsp_flush_socket(fd_info
*i
) {
1728 if ((i
->thread_fd
< 0) && (i
->app_fd
< 0))
1731 if (i
->thread_fd
>= 0)
1732 res
= dsp_flush_fd(i
->thread_fd
);
1738 res
= dsp_flush_fd(i
->app_fd
);
1746 static int dsp_empty_socket(fd_info
*i
) {
1750 /* Empty the socket */
1754 if (i
->thread_fd
< 0)
1757 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
1758 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1767 pa_threaded_mainloop_wait(i
->mainloop
);
1772 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1777 static int dsp_drain(fd_info
*i
) {
1778 pa_operation
*o
= NULL
;
1784 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Draining.\n");
1786 pa_threaded_mainloop_lock(i
->mainloop
);
1788 if (dsp_empty_socket(i
) < 0)
1791 if (!i
->play_stream
)
1794 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Really draining.\n");
1796 if (!(o
= pa_stream_drain(i
->play_stream
, stream_success_cb
, i
))) {
1797 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1801 i
->operation_success
= 0;
1802 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1803 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1805 pa_threaded_mainloop_wait(i
->mainloop
);
1808 if (!i
->operation_success
) {
1809 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1818 pa_operation_unref(o
);
1820 pa_threaded_mainloop_unlock(i
->mainloop
);
1825 static int dsp_trigger(fd_info
*i
) {
1826 pa_operation
*o
= NULL
;
1829 if (!i
->play_stream
)
1832 pa_threaded_mainloop_lock(i
->mainloop
);
1834 if (dsp_empty_socket(i
) < 0)
1837 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Triggering.\n");
1839 if (!(o
= pa_stream_trigger(i
->play_stream
, stream_success_cb
, i
))) {
1840 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1844 i
->operation_success
= 0;
1845 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1846 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1848 pa_threaded_mainloop_wait(i
->mainloop
);
1851 if (!i
->operation_success
) {
1852 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1861 pa_operation_unref(o
);
1863 pa_threaded_mainloop_unlock(i
->mainloop
);
1868 static int dsp_cork(fd_info
*i
, pa_stream
*s
, int b
) {
1869 pa_operation
*o
= NULL
;
1872 pa_threaded_mainloop_lock(i
->mainloop
);
1874 if (!(o
= pa_stream_cork(s
, b
, stream_success_cb
, i
))) {
1875 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1879 i
->operation_success
= 0;
1880 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1881 if (s
== i
->play_stream
)
1882 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1883 else if (s
== i
->rec_stream
)
1884 RECORD_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1886 pa_threaded_mainloop_wait(i
->mainloop
);
1889 if (!i
->operation_success
) {
1890 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1899 pa_operation_unref(o
);
1901 pa_threaded_mainloop_unlock(i
->mainloop
);
1906 static int dsp_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1909 if (i
->thread_fd
== -1) {
1911 * We've encountered some fatal error and are just waiting
1914 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": got ioctl 0x%08lx in fatal error state\n", request
);
1920 case SNDCTL_DSP_SETFMT
: {
1921 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp
);
1923 pa_threaded_mainloop_lock(i
->mainloop
);
1925 if (*(int*) argp
== AFMT_QUERY
)
1926 *(int*) argp
= map_format_back(i
->sample_spec
.format
);
1928 map_format((int*) argp
, &i
->sample_spec
);
1932 pa_threaded_mainloop_unlock(i
->mainloop
);
1936 case SNDCTL_DSP_SPEED
: {
1941 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SPEED: %i\n", *(int*) argp
);
1943 pa_threaded_mainloop_lock(i
->mainloop
);
1945 ss
= i
->sample_spec
;
1946 ss
.rate
= *(int*) argp
;
1948 if ((valid
= pa_sample_spec_valid(&ss
))) {
1949 i
->sample_spec
= ss
;
1953 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ss: %s\n", pa_sample_spec_snprint(t
, sizeof(t
), &i
->sample_spec
));
1955 pa_threaded_mainloop_unlock(i
->mainloop
);
1965 case SNDCTL_DSP_STEREO
:
1966 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_STEREO: %i\n", *(int*) argp
);
1968 pa_threaded_mainloop_lock(i
->mainloop
);
1970 i
->sample_spec
.channels
= *(int*) argp
? 2 : 1;
1973 pa_threaded_mainloop_unlock(i
->mainloop
);
1976 case SNDCTL_DSP_CHANNELS
: {
1980 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp
);
1982 pa_threaded_mainloop_lock(i
->mainloop
);
1984 ss
= i
->sample_spec
;
1985 ss
.channels
= *(int*) argp
;
1987 if ((valid
= pa_sample_spec_valid(&ss
))) {
1988 i
->sample_spec
= ss
;
1992 pa_threaded_mainloop_unlock(i
->mainloop
);
2002 case SNDCTL_DSP_GETBLKSIZE
:
2003 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETBLKSIZE\n");
2005 pa_threaded_mainloop_lock(i
->mainloop
);
2008 *(int*) argp
= i
->fragment_size
;
2010 pa_threaded_mainloop_unlock(i
->mainloop
);
2014 case SNDCTL_DSP_SETFRAGMENT
:
2015 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp
);
2017 pa_threaded_mainloop_lock(i
->mainloop
);
2019 i
->fragment_size
= 1 << ((*(int*) argp
) & 31);
2020 i
->n_fragments
= (*(int*) argp
) >> 16;
2022 /* 0x7FFF means that we can set whatever we like */
2023 if (i
->n_fragments
== 0x7FFF)
2024 i
->n_fragments
= 12;
2028 pa_threaded_mainloop_unlock(i
->mainloop
);
2032 case SNDCTL_DSP_GETCAPS
:
2033 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CAPS\n");
2035 *(int*) argp
= DSP_CAP_DUPLEX
| DSP_CAP_TRIGGER
2036 #ifdef DSP_CAP_MULTI
2042 case SNDCTL_DSP_GETODELAY
: {
2045 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETODELAY\n");
2047 pa_threaded_mainloop_lock(i
->mainloop
);
2054 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop
);
2056 if (pa_stream_get_latency(i
->play_stream
, &usec
, NULL
) >= 0) {
2057 *(int*) argp
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2061 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2062 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2066 pa_threaded_mainloop_wait(i
->mainloop
);
2072 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0)
2073 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2077 # warning "Your platform does not support SIOCINQ, something might not work as intended."
2080 pa_threaded_mainloop_unlock(i
->mainloop
);
2082 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ODELAY: %i\n", *(int*) argp
);
2087 case SNDCTL_DSP_RESET
: {
2088 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_RESET\n");
2090 pa_threaded_mainloop_lock(i
->mainloop
);
2093 dsp_flush_socket(i
);
2095 i
->optr_n_blocks
= 0;
2097 pa_threaded_mainloop_unlock(i
->mainloop
);
2101 case SNDCTL_DSP_GETFMTS
: {
2102 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETFMTS\n");
2104 *(int*) argp
= AFMT_MU_LAW
|AFMT_A_LAW
|AFMT_U8
|AFMT_S16_LE
|AFMT_S16_BE
;
2108 case SNDCTL_DSP_POST
:
2109 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_POST\n");
2111 if (dsp_trigger(i
) < 0)
2115 case SNDCTL_DSP_GETTRIGGER
:
2116 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETTRIGGER\n");
2119 if (!i
->play_precork
)
2120 *(int*) argp
|= PCM_ENABLE_OUTPUT
;
2121 if (!i
->rec_precork
)
2122 *(int*) argp
|= PCM_ENABLE_INPUT
;
2126 case SNDCTL_DSP_SETTRIGGER
:
2127 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp
);
2134 i
->play_precork
= !((*(int*) argp
) & PCM_ENABLE_OUTPUT
);
2136 if (i
->play_stream
) {
2137 if (dsp_cork(i
, i
->play_stream
, !((*(int*) argp
) & PCM_ENABLE_OUTPUT
)) < 0)
2139 if (dsp_trigger(i
) < 0)
2143 i
->rec_precork
= !((*(int*) argp
) & PCM_ENABLE_INPUT
);
2145 if (i
->rec_stream
) {
2146 if (dsp_cork(i
, i
->rec_stream
, !((*(int*) argp
) & PCM_ENABLE_INPUT
)) < 0)
2152 case SNDCTL_DSP_SYNC
:
2153 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SYNC\n");
2155 if (dsp_drain(i
) < 0)
2160 case SNDCTL_DSP_GETOSPACE
:
2161 case SNDCTL_DSP_GETISPACE
: {
2162 audio_buf_info
*bi
= (audio_buf_info
*) argp
;
2166 if (request
== SNDCTL_DSP_GETOSPACE
)
2167 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOSPACE\n");
2169 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETISPACE\n");
2171 pa_threaded_mainloop_lock(i
->mainloop
);
2175 if (request
== SNDCTL_DSP_GETOSPACE
) {
2176 if (i
->play_stream
) {
2177 if ((k
= pa_stream_writable_size(i
->play_stream
)) == (size_t) -1)
2178 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2180 k
= i
->fragment_size
* i
->n_fragments
;
2183 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
2184 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2188 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2191 bi
->bytes
= k
> (size_t) l
? k
- l
: 0;
2193 if (i
->rec_stream
) {
2194 if ((k
= pa_stream_readable_size(i
->rec_stream
)) == (size_t) -1)
2195 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2200 if (ioctl(i
->app_fd
, SIOCINQ
, &l
) < 0) {
2201 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2205 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2210 bi
->fragsize
= i
->fragment_size
;
2211 bi
->fragstotal
= i
->n_fragments
;
2212 bi
->fragments
= bi
->bytes
/ bi
->fragsize
;
2214 pa_threaded_mainloop_unlock(i
->mainloop
);
2216 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi
->fragsize
, bi
->fragstotal
, bi
->bytes
, bi
->fragments
);
2221 case SOUND_PCM_READ_RATE
:
2222 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_RATE\n");
2224 pa_threaded_mainloop_lock(i
->mainloop
);
2225 *(int*) argp
= i
->sample_spec
.rate
;
2226 pa_threaded_mainloop_unlock(i
->mainloop
);
2229 case SOUND_PCM_READ_CHANNELS
:
2230 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_CHANNELS\n");
2232 pa_threaded_mainloop_lock(i
->mainloop
);
2233 *(int*) argp
= i
->sample_spec
.channels
;
2234 pa_threaded_mainloop_unlock(i
->mainloop
);
2237 case SOUND_PCM_READ_BITS
:
2238 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_BITS\n");
2240 pa_threaded_mainloop_lock(i
->mainloop
);
2241 *(int*) argp
= pa_sample_size(&i
->sample_spec
)*8;
2242 pa_threaded_mainloop_unlock(i
->mainloop
);
2245 case SNDCTL_DSP_GETOPTR
: {
2248 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOPTR\n");
2250 info
= (count_info
*) argp
;
2251 memset(info
, 0, sizeof(*info
));
2253 pa_threaded_mainloop_lock(i
->mainloop
);
2258 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop2
);
2260 if (pa_stream_get_time(i
->play_stream
, &usec
) >= 0) {
2261 size_t k
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2264 info
->bytes
= (int) k
;
2265 m
= k
/ i
->fragment_size
;
2266 info
->blocks
= m
- i
->optr_n_blocks
;
2267 i
->optr_n_blocks
= m
;
2272 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2273 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2277 pa_threaded_mainloop_wait(i
->mainloop
);
2282 pa_threaded_mainloop_unlock(i
->mainloop
);
2284 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info
->bytes
, info
->blocks
, info
->ptr
);
2289 case SNDCTL_DSP_GETIPTR
:
2290 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": invalid ioctl SNDCTL_DSP_GETIPTR\n");
2293 case SNDCTL_DSP_SETDUPLEX
:
2294 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETDUPLEX\n");
2295 /* this is a no-op */
2299 /* Mixer ioctls are valid on /dev/dsp aswell */
2300 return mixer_ioctl(i
, request
, argp
, _errno
);
2315 int ioctl(int fd
, int request
, ...) {
2317 int ioctl(int fd
, unsigned long request
, ...) {
2324 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ioctl()\n");
2326 va_start(args
, request
);
2327 argp
= va_arg(args
, void *);
2330 if (!function_enter()) {
2332 return _ioctl(fd
, request
, argp
);
2335 if (!(i
= fd_info_find(fd
))) {
2338 return _ioctl(fd
, request
, argp
);
2341 if (i
->type
== FD_INFO_MIXER
)
2342 r
= mixer_ioctl(i
, request
, argp
, &_errno
);
2344 r
= dsp_ioctl(i
, request
, argp
, &_errno
);
2359 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": close()\n");
2361 if (!function_enter()) {
2366 if (!(i
= fd_info_find(fd
))) {
2372 fd_info_remove_from_list(i
);
2380 int access(const char *pathname
, int mode
) {
2382 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": access(%s)\n", pathname
?pathname
:"NULL");
2385 (strcmp(pathname
, "/dev/dsp") != 0 &&
2386 strcmp(pathname
, "/dev/adsp") != 0 &&
2387 strcmp(pathname
, "/dev/sndstat") != 0 &&
2388 strcmp(pathname
, "/dev/mixer") != 0 )) {
2390 return _access(pathname
, mode
);
2394 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = EACCESS\n", pathname
, mode
);
2399 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = OK\n", pathname
, mode
);
2404 int stat(const char *pathname
, struct stat
*buf
) {
2406 struct stat64 parent
;
2414 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2415 strcmp(pathname
, "/dev/adsp") != 0 &&
2416 strcmp(pathname
, "/dev/sndstat") != 0 &&
2417 strcmp(pathname
, "/dev/mixer") != 0 )) {
2418 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat(%s)\n", pathname
?pathname
:"NULL");
2420 return _stat(pathname
, buf
);
2423 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stat(%s)\n", pathname
);
2427 ret
= __xstat64(_STAT_VER
, "/dev", &parent
);
2429 ret
= __xstat(_STAT_VER
, "/dev", &parent
);
2433 ret
= stat64("/dev", &parent
);
2435 ret
= stat("/dev", &parent
);
2440 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unable to stat \"/dev\"\n");
2444 buf
->st_dev
= parent
.st_dev
;
2445 buf
->st_ino
= 0xDEADBEEF; /* FIXME: Can we do this in a safe way? */
2446 buf
->st_mode
= S_IFCHR
| S_IRUSR
| S_IWUSR
;
2448 buf
->st_uid
= getuid();
2449 buf
->st_gid
= getgid();
2450 buf
->st_rdev
= 0x0E03; /* FIXME: Linux specific */
2452 buf
->st_atime
= 1181557705;
2453 buf
->st_mtime
= 1181557705;
2454 buf
->st_ctime
= 1181557705;
2455 buf
->st_blksize
= 1;
2463 int stat64(const char *pathname
, struct stat64
*buf
) {
2467 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat64(%s)\n", pathname
?pathname
:"NULL");
2471 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2472 strcmp(pathname
, "/dev/adsp") != 0 &&
2473 strcmp(pathname
, "/dev/sndstat") != 0 &&
2474 strcmp(pathname
, "/dev/mixer") != 0 )) {
2476 return _stat64(pathname
, buf
);
2479 ret
= stat(pathname
, &oldbuf
);
2483 buf
->st_dev
= oldbuf
.st_dev
;
2484 buf
->st_ino
= oldbuf
.st_ino
;
2485 buf
->st_mode
= oldbuf
.st_mode
;
2486 buf
->st_nlink
= oldbuf
.st_nlink
;
2487 buf
->st_uid
= oldbuf
.st_uid
;
2488 buf
->st_gid
= oldbuf
.st_gid
;
2489 buf
->st_rdev
= oldbuf
.st_rdev
;
2490 buf
->st_size
= oldbuf
.st_size
;
2491 buf
->st_atime
= oldbuf
.st_atime
;
2492 buf
->st_mtime
= oldbuf
.st_mtime
;
2493 buf
->st_ctime
= oldbuf
.st_ctime
;
2494 buf
->st_blksize
= oldbuf
.st_blksize
;
2495 buf
->st_blocks
= oldbuf
.st_blocks
;
2500 int open64(const char *filename
, int flags
, ...) {
2504 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open64(%s)\n", filename
?filename
:"NULL");
2506 if (flags
& O_CREAT
) {
2507 va_start(args
, flags
);
2508 if (sizeof(mode_t
) < sizeof(int))
2509 mode
= va_arg(args
, int);
2511 mode
= va_arg(args
, mode_t
);
2516 ( strcmp(filename
, "/dev/dsp") != 0 &&
2517 strcmp(filename
, "/dev/adsp") != 0 &&
2518 strcmp(filename
, "/dev/sndstat") != 0 &&
2519 strcmp(filename
, "/dev/mixer") != 0 )) {
2521 return _open64(filename
, flags
, mode
);
2524 return real_open(filename
, flags
, mode
);
2531 int __xstat(int ver
, const char *pathname
, struct stat
*buf
) {
2532 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat(%s)\n", pathname
?pathname
:"NULL");
2536 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2537 strcmp(pathname
, "/dev/adsp") != 0 &&
2538 strcmp(pathname
, "/dev/sndstat") != 0 &&
2539 strcmp(pathname
, "/dev/mixer") != 0 )) {
2541 return ___xstat(ver
, pathname
, buf
);
2544 if (ver
!= _STAT_VER
) {
2549 return stat(pathname
, buf
);
2554 int __xstat64(int ver
, const char *pathname
, struct stat64
*buf
) {
2555 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat64(%s)\n", pathname
?pathname
:"NULL");
2559 ( strcmp(pathname
, "/dev/dsp") != 0 &&
2560 strcmp(pathname
, "/dev/adsp") != 0 &&
2561 strcmp(pathname
, "/dev/sndstat") != 0 &&
2562 strcmp(pathname
, "/dev/mixer") != 0 )) {
2563 LOAD_XSTAT64_FUNC();
2564 return ___xstat64(ver
, pathname
, buf
);
2567 if (ver
!= _STAT_VER
) {
2572 return stat64(pathname
, buf
);
2579 FILE* fopen(const char *filename
, const char *mode
) {
2584 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen(%s)\n", filename
?filename
:"NULL");
2588 ( strcmp(filename
, "/dev/dsp") != 0 &&
2589 strcmp(filename
, "/dev/adsp") != 0 &&
2590 strcmp(filename
, "/dev/sndstat") != 0 &&
2591 strcmp(filename
, "/dev/mixer") != 0 )) {
2593 return _fopen(filename
, mode
);
2609 if ((((mode
[1] == 'b') || (mode
[1] == 't')) && (mode
[2] == '+')) || (mode
[1] == '+'))
2612 if ((fd
= real_open(filename
, m
, 0)) < 0)
2615 if (!(f
= fdopen(fd
, mode
))) {
2625 FILE *fopen64(const char *filename
, const char *mode
) {
2627 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen64(%s)\n", filename
?filename
:"NULL");
2631 ( strcmp(filename
, "/dev/dsp") != 0 &&
2632 strcmp(filename
, "/dev/adsp") != 0 &&
2633 strcmp(filename
, "/dev/sndstat") != 0 &&
2634 strcmp(filename
, "/dev/mixer") != 0 )) {
2635 LOAD_FOPEN64_FUNC();
2636 return _fopen64(filename
, mode
);
2639 return fopen(filename
, mode
);
2644 int fclose(FILE *f
) {
2647 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fclose()\n");
2649 if (!function_enter()) {
2654 if (!(i
= fd_info_find(fileno(f
)))) {
2660 fd_info_remove_from_list(i
);
2662 /* Dirty trick to avoid that the fd is not freed twice, once by us
2663 * and once by the real fclose() */