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 int (*___open_2
)(const char *, int) = NULL
;
122 static FILE* (*_fopen
)(const char *path
, const char *mode
) = NULL
;
123 static int (*_stat
)(const char *, struct stat
*) = NULL
;
125 static int (*___xstat
)(int, const char *, struct stat
*) = NULL
;
128 static int (*_open64
)(const char *, int, mode_t
) = NULL
;
129 static int (*___open64_2
)(const char *, int) = NULL
;
130 static FILE* (*_fopen64
)(const char *path
, const char *mode
) = NULL
;
131 static int (*_stat64
)(const char *, struct stat64
*) = NULL
;
133 static int (*___xstat64
)(int, const char *, struct stat64
*) = NULL
;
136 static int (*_fclose
)(FILE *f
) = NULL
;
137 static int (*_access
)(const char *, int) = NULL
;
139 /* dlsym() violates ISO C, so confide the breakage into this function to
141 typedef void (*fnptr
)(void);
142 static inline fnptr
dlsym_fn(void *handle
, const char *symbol
) {
143 return (fnptr
) (long) dlsym(handle
, symbol
);
146 #define LOAD_IOCTL_FUNC() \
148 pthread_mutex_lock(&func_mutex); \
150 _ioctl = (int (*)(int, int, void*)) dlsym_fn(RTLD_NEXT, "ioctl"); \
151 pthread_mutex_unlock(&func_mutex); \
154 #define LOAD_OPEN_FUNC() \
156 pthread_mutex_lock(&func_mutex); \
158 _open = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open"); \
159 pthread_mutex_unlock(&func_mutex); \
162 #define LOAD___OPEN_2_FUNC() \
164 pthread_mutex_lock(&func_mutex); \
166 ___open_2 = (int (*)(const char *, int)) dlsym_fn(RTLD_NEXT, "__open_2"); \
167 pthread_mutex_unlock(&func_mutex); \
170 #define LOAD_OPEN64_FUNC() \
172 pthread_mutex_lock(&func_mutex); \
174 _open64 = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open64"); \
175 pthread_mutex_unlock(&func_mutex); \
178 #define LOAD___OPEN64_2_FUNC() \
180 pthread_mutex_lock(&func_mutex); \
182 ___open64_2 = (int (*)(const char *, int)) dlsym_fn(RTLD_NEXT, "__open64_2"); \
183 pthread_mutex_unlock(&func_mutex); \
186 #define LOAD_CLOSE_FUNC() \
188 pthread_mutex_lock(&func_mutex); \
190 _close = (int (*)(int)) dlsym_fn(RTLD_NEXT, "close"); \
191 pthread_mutex_unlock(&func_mutex); \
194 #define LOAD_ACCESS_FUNC() \
196 pthread_mutex_lock(&func_mutex); \
198 _access = (int (*)(const char*, int)) dlsym_fn(RTLD_NEXT, "access"); \
199 pthread_mutex_unlock(&func_mutex); \
202 #define LOAD_STAT_FUNC() \
204 pthread_mutex_lock(&func_mutex); \
206 _stat = (int (*)(const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "stat"); \
207 pthread_mutex_unlock(&func_mutex); \
210 #define LOAD_STAT64_FUNC() \
212 pthread_mutex_lock(&func_mutex); \
214 _stat64 = (int (*)(const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "stat64"); \
215 pthread_mutex_unlock(&func_mutex); \
218 #define LOAD_XSTAT_FUNC() \
220 pthread_mutex_lock(&func_mutex); \
222 ___xstat = (int (*)(int, const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "__xstat"); \
223 pthread_mutex_unlock(&func_mutex); \
226 #define LOAD_XSTAT64_FUNC() \
228 pthread_mutex_lock(&func_mutex); \
230 ___xstat64 = (int (*)(int, const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "__xstat64"); \
231 pthread_mutex_unlock(&func_mutex); \
234 #define LOAD_FOPEN_FUNC() \
236 pthread_mutex_lock(&func_mutex); \
238 _fopen = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen"); \
239 pthread_mutex_unlock(&func_mutex); \
242 #define LOAD_FOPEN64_FUNC() \
244 pthread_mutex_lock(&func_mutex); \
246 _fopen64 = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen64"); \
247 pthread_mutex_unlock(&func_mutex); \
250 #define LOAD_FCLOSE_FUNC() \
252 pthread_mutex_lock(&func_mutex); \
254 _fclose = (int (*)(FILE *)) dlsym_fn(RTLD_NEXT, "fclose"); \
255 pthread_mutex_unlock(&func_mutex); \
258 #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \
259 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \
260 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
265 #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \
266 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
267 !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \
268 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
273 #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \
274 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
275 !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \
276 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
281 static void debug(int level
, const char *format
, ...) PA_GCC_PRINTF_ATTR(2,3);
283 #define DEBUG_LEVEL_ALWAYS 0
284 #define DEBUG_LEVEL_NORMAL 1
285 #define DEBUG_LEVEL_VERBOSE 2
287 static void debug(int level
, const char *format
, ...) {
289 const char *dlevel_s
;
292 dlevel_s
= getenv("PADSP_DEBUG");
296 dlevel
= atoi(dlevel_s
);
301 va_start(ap
, format
);
302 vfprintf(stderr
, format
, ap
);
306 static int padsp_disabled(void) {
308 static int sym_resolved
= 0;
310 /* If the current process has a symbol __padsp_disabled__ we use
311 * it to detect whether we should enable our stuff or not. A
312 * program needs to be compiled with -rdynamic for this to work!
313 * The symbol must be an int containing a three bit bitmask: bit 1
314 * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat
315 * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value
316 * of 7 disables padsp entirely. */
318 pthread_mutex_lock(&func_mutex
);
320 sym
= (int*) dlsym(RTLD_DEFAULT
, "__padsp_disabled__");
323 pthread_mutex_unlock(&func_mutex
);
331 static int dsp_cloak_enable(void) {
332 if (padsp_disabled() & 1)
335 if (getenv("PADSP_NO_DSP") || getenv("PULSE_INTERNAL"))
341 static int sndstat_cloak_enable(void) {
342 if (padsp_disabled() & 2)
345 if (getenv("PADSP_NO_SNDSTAT") || getenv("PULSE_INTERNAL"))
351 static int mixer_cloak_enable(void) {
352 if (padsp_disabled() & 4)
355 if (getenv("PADSP_NO_MIXER") || getenv("PULSE_INTERNAL"))
360 static pthread_key_t recursion_key
;
362 static void recursion_key_alloc(void) {
363 pthread_key_create(&recursion_key
, NULL
);
366 static int function_enter(void) {
367 /* Avoid recursive calls */
368 static pthread_once_t recursion_key_once
= PTHREAD_ONCE_INIT
;
369 pthread_once(&recursion_key_once
, recursion_key_alloc
);
371 if (pthread_getspecific(recursion_key
))
374 pthread_setspecific(recursion_key
, (void*) 1);
378 static void function_exit(void) {
379 pthread_setspecific(recursion_key
, NULL
);
382 static void fd_info_free(fd_info
*i
) {
385 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": freeing fd info (fd=%i)\n", i
->app_fd
);
390 pa_threaded_mainloop_stop(i
->mainloop
);
392 if (i
->play_stream
) {
393 pa_stream_disconnect(i
->play_stream
);
394 pa_stream_unref(i
->play_stream
);
398 pa_stream_disconnect(i
->rec_stream
);
399 pa_stream_unref(i
->rec_stream
);
403 pa_context_disconnect(i
->context
);
404 pa_context_unref(i
->context
);
408 pa_threaded_mainloop_free(i
->mainloop
);
410 if (i
->app_fd
>= 0) {
415 if (i
->thread_fd
>= 0) {
417 _close(i
->thread_fd
);
422 pthread_mutex_destroy(&i
->mutex
);
426 static fd_info
*fd_info_ref(fd_info
*i
) {
429 pthread_mutex_lock(&i
->mutex
);
433 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ref++, now %i\n", i
->ref
);
434 pthread_mutex_unlock(&i
->mutex
);
439 static void fd_info_unref(fd_info
*i
) {
441 pthread_mutex_lock(&i
->mutex
);
444 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ref--, now %i\n", i
->ref
);
445 pthread_mutex_unlock(&i
->mutex
);
451 static void context_state_cb(pa_context
*c
, void *userdata
) {
452 fd_info
*i
= userdata
;
455 switch (pa_context_get_state(c
)) {
456 case PA_CONTEXT_READY
:
457 case PA_CONTEXT_TERMINATED
:
458 case PA_CONTEXT_FAILED
:
459 pa_threaded_mainloop_signal(i
->mainloop
, 0);
462 case PA_CONTEXT_UNCONNECTED
:
463 case PA_CONTEXT_CONNECTING
:
464 case PA_CONTEXT_AUTHORIZING
:
465 case PA_CONTEXT_SETTING_NAME
:
470 static void reset_params(fd_info
*i
) {
473 i
->sample_spec
.format
= PA_SAMPLE_U8
;
474 i
->sample_spec
.channels
= 1;
475 i
->sample_spec
.rate
= 8000;
476 i
->fragment_size
= 0;
480 static const char *client_name(char *buf
, size_t n
) {
484 if ((e
= getenv("PADSP_CLIENT_NAME")))
487 if ((p
= pa_get_binary_name_malloc())) {
488 snprintf(buf
, n
, "OSS Emulation[%s]", p
);
491 snprintf(buf
, n
, "OSS");
496 static const char *stream_name(void) {
499 if ((e
= getenv("PADSP_STREAM_NAME")))
502 return "Audio Stream";
505 static void atfork_prepare(void) {
508 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_prepare() enter\n");
512 pthread_mutex_lock(&fd_infos_mutex
);
514 for (i
= fd_infos
; i
; i
= i
->next
) {
515 pthread_mutex_lock(&i
->mutex
);
516 pa_threaded_mainloop_lock(i
->mainloop
);
519 pthread_mutex_lock(&func_mutex
);
521 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_prepare() exit\n");
524 static void atfork_parent(void) {
527 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_parent() enter\n");
529 pthread_mutex_unlock(&func_mutex
);
531 for (i
= fd_infos
; i
; i
= i
->next
) {
532 pa_threaded_mainloop_unlock(i
->mainloop
);
533 pthread_mutex_unlock(&i
->mutex
);
536 pthread_mutex_unlock(&fd_infos_mutex
);
540 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_parent() exit\n");
543 static void atfork_child(void) {
546 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_child() enter\n");
548 /* We do only the bare minimum to get all fds closed */
549 pthread_mutex_init(&func_mutex
, NULL
);
550 pthread_mutex_init(&fd_infos_mutex
, NULL
);
552 for (i
= fd_infos
; i
; i
= i
->next
) {
553 pthread_mutex_init(&i
->mutex
, NULL
);
556 pa_context_disconnect(i
->context
);
557 pa_context_unref(i
->context
);
561 if (i
->play_stream
) {
562 pa_stream_unref(i
->play_stream
);
563 i
->play_stream
= NULL
;
567 pa_stream_unref(i
->rec_stream
);
568 i
->rec_stream
= NULL
;
571 if (i
->app_fd
>= 0) {
577 if (i
->thread_fd
>= 0) {
579 _close(i
->thread_fd
);
588 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": atfork_child() exit\n");
591 static void install_atfork(void) {
592 pthread_atfork(atfork_prepare
, atfork_parent
, atfork_child
);
595 static void stream_success_cb(pa_stream
*s
, int success
, void *userdata
) {
596 fd_info
*i
= userdata
;
601 i
->operation_success
= success
;
602 pa_threaded_mainloop_signal(i
->mainloop
, 0);
605 static void context_success_cb(pa_context
*c
, int success
, void *userdata
) {
606 fd_info
*i
= userdata
;
611 i
->operation_success
= success
;
612 pa_threaded_mainloop_signal(i
->mainloop
, 0);
615 static fd_info
* fd_info_new(fd_info_type_t type
, int *_errno
) {
617 int sfds
[2] = { -1, -1 };
619 static pthread_once_t install_atfork_once
= PTHREAD_ONCE_INIT
;
621 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fd_info_new()\n");
623 signal(SIGPIPE
, SIG_IGN
); /* Yes, ugly as hell */
625 pthread_once(&install_atfork_once
, install_atfork
);
627 if (!(i
= malloc(sizeof(fd_info
)))) {
632 i
->app_fd
= i
->thread_fd
= -1;
637 i
->play_stream
= NULL
;
638 i
->rec_stream
= NULL
;
643 pthread_mutex_init(&i
->mutex
, NULL
);
648 pa_cvolume_reset(&i
->sink_volume
, 2);
649 pa_cvolume_reset(&i
->source_volume
, 2);
650 i
->volume_modify_count
= 0;
651 i
->sink_index
= (uint32_t) -1;
652 i
->source_index
= (uint32_t) -1;
653 i
->optr_n_blocks
= 0;
654 PA_LLIST_INIT(fd_info
, i
);
658 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sfds
) < 0) {
660 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": socket() failed: %s\n", strerror(errno
));
665 i
->thread_fd
= sfds
[1];
667 if (!(i
->mainloop
= pa_threaded_mainloop_new())) {
669 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_threaded_mainloop_new() failed\n");
673 if (!(i
->context
= pa_context_new(pa_threaded_mainloop_get_api(i
->mainloop
), client_name(name
, sizeof(name
))))) {
675 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_new() failed\n");
679 pa_context_set_state_callback(i
->context
, context_state_cb
, i
);
681 if (pa_context_connect(i
->context
, NULL
, 0, NULL
) < 0) {
682 *_errno
= ECONNREFUSED
;
683 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
687 pa_threaded_mainloop_lock(i
->mainloop
);
689 if (pa_threaded_mainloop_start(i
->mainloop
) < 0) {
691 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_threaded_mainloop_start() failed\n");
692 goto unlock_and_fail
;
695 /* Wait until the context is ready */
696 pa_threaded_mainloop_wait(i
->mainloop
);
698 if (pa_context_get_state(i
->context
) != PA_CONTEXT_READY
) {
699 *_errno
= ECONNREFUSED
;
700 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
701 goto unlock_and_fail
;
704 pa_threaded_mainloop_unlock(i
->mainloop
);
709 pa_threaded_mainloop_unlock(i
->mainloop
);
719 static void fd_info_add_to_list(fd_info
*i
) {
722 pthread_mutex_lock(&fd_infos_mutex
);
723 PA_LLIST_PREPEND(fd_info
, fd_infos
, i
);
724 pthread_mutex_unlock(&fd_infos_mutex
);
729 static void fd_info_remove_from_list(fd_info
*i
) {
732 pthread_mutex_lock(&fd_infos_mutex
);
733 PA_LLIST_REMOVE(fd_info
, fd_infos
, i
);
734 pthread_mutex_unlock(&fd_infos_mutex
);
739 static fd_info
* fd_info_find(int fd
) {
742 pthread_mutex_lock(&fd_infos_mutex
);
744 for (i
= fd_infos
; i
; i
= i
->next
)
745 if (i
->app_fd
== fd
&& !i
->unusable
) {
750 pthread_mutex_unlock(&fd_infos_mutex
);
755 static void fix_metrics(fd_info
*i
) {
757 char t
[PA_SAMPLE_SPEC_SNPRINT_MAX
];
759 fs
= pa_frame_size(&i
->sample_spec
);
761 /* Don't fix things more than necessary */
762 if ((i
->fragment_size
% fs
) == 0 &&
763 i
->n_fragments
>= 2 &&
764 i
->fragment_size
> 0)
767 i
->fragment_size
= (i
->fragment_size
/fs
)*fs
;
769 /* Number of fragments set? */
770 if (i
->n_fragments
< 2) {
771 if (i
->fragment_size
> 0) {
772 i
->n_fragments
= (unsigned) (pa_bytes_per_second(&i
->sample_spec
) / 2 / i
->fragment_size
);
773 if (i
->n_fragments
< 2)
779 /* Fragment size set? */
780 if (i
->fragment_size
<= 0) {
781 i
->fragment_size
= pa_bytes_per_second(&i
->sample_spec
) / 2 / i
->n_fragments
;
782 if (i
->fragment_size
< 1024)
783 i
->fragment_size
= 1024;
786 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": sample spec: %s\n", pa_sample_spec_snprint(t
, sizeof(t
), &i
->sample_spec
));
787 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fixated metrics to %i fragments, %li bytes each.\n", i
->n_fragments
, (long)i
->fragment_size
);
790 static void stream_request_cb(pa_stream
*s
, size_t length
, void *userdata
) {
791 fd_info
*i
= userdata
;
795 pa_mainloop_api
*api
;
798 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
800 if (s
== i
->play_stream
) {
801 n
= pa_stream_writable_size(i
->play_stream
);
802 if (n
== (size_t)-1) {
803 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n",
804 pa_strerror(pa_context_errno(i
->context
)));
807 if (n
>= i
->fragment_size
)
808 i
->io_flags
|= PA_IO_EVENT_INPUT
;
810 i
->io_flags
&= ~PA_IO_EVENT_INPUT
;
813 if (s
== i
->rec_stream
) {
814 n
= pa_stream_readable_size(i
->rec_stream
);
815 if (n
== (size_t)-1) {
816 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n",
817 pa_strerror(pa_context_errno(i
->context
)));
820 if (n
>= i
->fragment_size
)
821 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
823 i
->io_flags
&= ~PA_IO_EVENT_OUTPUT
;
826 api
->io_enable(i
->io_event
, i
->io_flags
);
830 static void stream_latency_update_cb(pa_stream
*s
, void *userdata
) {
831 fd_info
*i
= userdata
;
834 pa_threaded_mainloop_signal(i
->mainloop
, 0);
837 static void fd_info_shutdown(fd_info
*i
) {
841 pa_mainloop_api
*api
;
842 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
843 api
->io_free(i
->io_event
);
848 if (i
->thread_fd
>= 0) {
854 static int fd_info_copy_data(fd_info
*i
, int force
) {
857 if (!i
->play_stream
&& !i
->rec_stream
)
860 if ((i
->play_stream
) && (pa_stream_get_state(i
->play_stream
) == PA_STREAM_READY
)) {
861 n
= pa_stream_writable_size(i
->play_stream
);
863 if (n
== (size_t)-1) {
864 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n",
865 pa_strerror(pa_context_errno(i
->context
)));
869 while (n
>= i
->fragment_size
|| force
) {
873 if (!(i
->buf
= malloc(i
->fragment_size
))) {
874 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": malloc() failed.\n");
879 if ((r
= read(i
->thread_fd
, i
->buf
, i
->fragment_size
)) <= 0) {
884 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": read(): %s\n", r
== 0 ? "EOF" : strerror(errno
));
888 if (pa_stream_write(i
->play_stream
, i
->buf
, (size_t) r
, free
, 0LL, PA_SEEK_RELATIVE
) < 0) {
889 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
895 assert(n
>= (size_t) r
);
899 if (n
>= i
->fragment_size
)
900 i
->io_flags
|= PA_IO_EVENT_INPUT
;
902 i
->io_flags
&= ~PA_IO_EVENT_INPUT
;
905 if ((i
->rec_stream
) && (pa_stream_get_state(i
->rec_stream
) == PA_STREAM_READY
)) {
906 n
= pa_stream_readable_size(i
->rec_stream
);
908 if (n
== (size_t)-1) {
909 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n",
910 pa_strerror(pa_context_errno(i
->context
)));
914 while (n
>= i
->fragment_size
|| force
) {
920 if (pa_stream_peek(i
->rec_stream
, &data
, &len
) < 0) {
921 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_peek(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
929 /* Maybe we should generate silence here, but I'm lazy and
930 * I'll just skip any holes in the stream. */
931 if (pa_stream_drop(i
->rec_stream
) < 0) {
932 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
941 buf
= (const char*)data
+ i
->rec_offset
;
943 if ((r
= write(i
->thread_fd
, buf
, len
- i
->rec_offset
)) <= 0) {
948 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write(): %s\n", strerror(errno
));
952 assert((size_t)r
<= len
- i
->rec_offset
);
953 i
->rec_offset
+= (size_t) r
;
955 if (i
->rec_offset
== len
) {
956 if (pa_stream_drop(i
->rec_stream
) < 0) {
957 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
963 assert(n
>= (size_t) r
);
967 if (n
>= i
->fragment_size
)
968 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
970 i
->io_flags
&= ~PA_IO_EVENT_OUTPUT
;
974 pa_mainloop_api
*api
;
976 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
977 api
->io_enable(i
->io_event
, i
->io_flags
);
980 /* So, we emptied the socket now, let's tell dsp_empty_socket()
982 pa_threaded_mainloop_signal(i
->mainloop
, 0);
987 static void stream_state_cb(pa_stream
*s
, void * userdata
) {
988 fd_info
*i
= userdata
;
991 switch (pa_stream_get_state(s
)) {
993 case PA_STREAM_READY
:
994 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stream established.\n");
997 case PA_STREAM_FAILED
:
998 if (s
== i
->play_stream
) {
999 debug(DEBUG_LEVEL_NORMAL
,
1000 __FILE__
": pa_stream_connect_playback() failed: %s\n",
1001 pa_strerror(pa_context_errno(i
->context
)));
1002 pa_stream_unref(i
->play_stream
);
1003 i
->play_stream
= NULL
;
1004 } else if (s
== i
->rec_stream
) {
1005 debug(DEBUG_LEVEL_NORMAL
,
1006 __FILE__
": pa_stream_connect_record() failed: %s\n",
1007 pa_strerror(pa_context_errno(i
->context
)));
1008 pa_stream_unref(i
->rec_stream
);
1009 i
->rec_stream
= NULL
;
1011 fd_info_shutdown(i
);
1014 case PA_STREAM_TERMINATED
:
1015 case PA_STREAM_UNCONNECTED
:
1016 case PA_STREAM_CREATING
:
1021 static int create_playback_stream(fd_info
*i
) {
1022 pa_buffer_attr attr
;
1029 if (!(i
->play_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
1030 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1034 pa_stream_set_state_callback(i
->play_stream
, stream_state_cb
, i
);
1035 pa_stream_set_write_callback(i
->play_stream
, stream_request_cb
, i
);
1036 pa_stream_set_latency_update_callback(i
->play_stream
, stream_latency_update_cb
, i
);
1038 memset(&attr
, 0, sizeof(attr
));
1039 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1040 attr
.tlength
= (uint32_t) (i
->fragment_size
* i
->n_fragments
);
1041 attr
.prebuf
= (uint32_t) i
->fragment_size
;
1042 attr
.minreq
= (uint32_t) i
->fragment_size
;
1044 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
|PA_STREAM_EARLY_REQUESTS
;
1045 if (i
->play_precork
) {
1046 flags
|= PA_STREAM_START_CORKED
;
1047 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1049 if (pa_stream_connect_playback(i
->play_stream
, NULL
, &attr
, flags
, NULL
, NULL
) < 0) {
1050 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1054 n
= (int) i
->fragment_size
;
1055 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1056 n
= (int) i
->fragment_size
;
1057 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1065 static int create_record_stream(fd_info
*i
) {
1066 pa_buffer_attr attr
;
1073 if (!(i
->rec_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
1074 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1078 pa_stream_set_state_callback(i
->rec_stream
, stream_state_cb
, i
);
1079 pa_stream_set_read_callback(i
->rec_stream
, stream_request_cb
, i
);
1080 pa_stream_set_latency_update_callback(i
->rec_stream
, stream_latency_update_cb
, i
);
1082 memset(&attr
, 0, sizeof(attr
));
1083 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1084 attr
.fragsize
= (uint32_t) i
->fragment_size
;
1086 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
;
1087 if (i
->rec_precork
) {
1088 flags
|= PA_STREAM_START_CORKED
;
1089 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1091 if (pa_stream_connect_record(i
->rec_stream
, NULL
, &attr
, flags
) < 0) {
1092 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1096 n
= (int) i
->fragment_size
;
1097 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1098 n
= (int) i
->fragment_size
;
1099 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1107 static void free_streams(fd_info
*i
) {
1110 if (i
->play_stream
) {
1111 pa_stream_disconnect(i
->play_stream
);
1112 pa_stream_unref(i
->play_stream
);
1113 i
->play_stream
= NULL
;
1114 i
->io_flags
|= PA_IO_EVENT_INPUT
;
1117 if (i
->rec_stream
) {
1118 pa_stream_disconnect(i
->rec_stream
);
1119 pa_stream_unref(i
->rec_stream
);
1120 i
->rec_stream
= NULL
;
1121 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
1125 pa_mainloop_api
*api
;
1127 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1128 api
->io_enable(i
->io_event
, i
->io_flags
);
1132 static void io_event_cb(pa_mainloop_api
*api
, pa_io_event
*e
, int fd
, pa_io_event_flags_t flags
, void *userdata
) {
1133 fd_info
*i
= userdata
;
1135 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1137 if (flags
& PA_IO_EVENT_INPUT
) {
1139 if (!i
->play_stream
) {
1140 if (create_playback_stream(i
) < 0)
1143 if (fd_info_copy_data(i
, 0) < 0)
1147 } else if (flags
& PA_IO_EVENT_OUTPUT
) {
1149 if (!i
->rec_stream
) {
1150 if (create_record_stream(i
) < 0)
1153 if (fd_info_copy_data(i
, 0) < 0)
1157 } else if (flags
& (PA_IO_EVENT_HANGUP
|PA_IO_EVENT_ERROR
))
1163 /* We can't do anything better than removing the event source */
1164 fd_info_shutdown(i
);
1167 static int dsp_open(int flags
, int *_errno
) {
1169 pa_mainloop_api
*api
;
1173 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open()\n");
1175 if (!(i
= fd_info_new(FD_INFO_STREAM
, _errno
)))
1178 if ((flags
& O_NONBLOCK
) == O_NONBLOCK
) {
1179 if ((f
= fcntl(i
->app_fd
, F_GETFL
)) >= 0)
1180 fcntl(i
->app_fd
, F_SETFL
, f
|O_NONBLOCK
);
1182 if ((f
= fcntl(i
->thread_fd
, F_GETFL
)) >= 0)
1183 fcntl(i
->thread_fd
, F_SETFL
, f
|O_NONBLOCK
);
1185 fcntl(i
->app_fd
, F_SETFD
, FD_CLOEXEC
);
1186 fcntl(i
->thread_fd
, F_SETFD
, FD_CLOEXEC
);
1188 pa_threaded_mainloop_lock(i
->mainloop
);
1189 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1191 switch (flags
& O_ACCMODE
) {
1193 i
->io_flags
= PA_IO_EVENT_OUTPUT
;
1194 shutdown(i
->thread_fd
, SHUT_RD
);
1195 shutdown(i
->app_fd
, SHUT_WR
);
1198 i
->io_flags
= PA_IO_EVENT_INPUT
;
1199 shutdown(i
->thread_fd
, SHUT_WR
);
1200 shutdown(i
->app_fd
, SHUT_RD
);
1203 i
->io_flags
= PA_IO_EVENT_INPUT
| PA_IO_EVENT_OUTPUT
;
1209 if (!(i
->io_event
= api
->io_new(api
, i
->thread_fd
, i
->io_flags
, io_event_cb
, i
)))
1212 pa_threaded_mainloop_unlock(i
->mainloop
);
1214 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() succeeded, fd=%i\n", i
->app_fd
);
1216 fd_info_add_to_list(i
);
1223 pa_threaded_mainloop_unlock(i
->mainloop
);
1230 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() failed\n");
1235 static void sink_info_cb(pa_context
*context
, const pa_sink_info
*si
, int eol
, void *userdata
) {
1236 fd_info
*i
= userdata
;
1239 i
->operation_success
= 0;
1240 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1247 if (!pa_cvolume_equal(&i
->sink_volume
, &si
->volume
))
1248 i
->volume_modify_count
++;
1250 i
->sink_volume
= si
->volume
;
1251 i
->sink_index
= si
->index
;
1253 i
->operation_success
= 1;
1254 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1257 static void source_info_cb(pa_context
*context
, const pa_source_info
*si
, int eol
, void *userdata
) {
1258 fd_info
*i
= userdata
;
1261 i
->operation_success
= 0;
1262 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1269 if (!pa_cvolume_equal(&i
->source_volume
, &si
->volume
))
1270 i
->volume_modify_count
++;
1272 i
->source_volume
= si
->volume
;
1273 i
->source_index
= si
->index
;
1275 i
->operation_success
= 1;
1276 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1279 static void subscribe_cb(pa_context
*context
, pa_subscription_event_type_t t
, uint32_t idx
, void *userdata
) {
1280 fd_info
*i
= userdata
;
1281 pa_operation
*o
= NULL
;
1283 if (i
->sink_index
!= idx
)
1286 if ((t
& PA_SUBSCRIPTION_EVENT_TYPE_MASK
) != PA_SUBSCRIPTION_EVENT_CHANGE
)
1289 if (!(o
= pa_context_get_sink_info_by_index(i
->context
, i
->sink_index
, sink_info_cb
, i
))) {
1290 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1294 pa_operation_unref(o
);
1297 static int mixer_open(int flags
, int *_errno
) {
1299 pa_operation
*o
= NULL
;
1302 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open()\n");
1304 if (!(i
= fd_info_new(FD_INFO_MIXER
, _errno
)))
1307 pa_threaded_mainloop_lock(i
->mainloop
);
1309 pa_context_set_subscribe_callback(i
->context
, subscribe_cb
, i
);
1311 if (!(o
= pa_context_subscribe(i
->context
, PA_SUBSCRIPTION_MASK_SINK
| PA_SUBSCRIPTION_MASK_SOURCE
, context_success_cb
, i
))) {
1312 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1317 i
->operation_success
= 0;
1318 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1319 pa_threaded_mainloop_wait(i
->mainloop
);
1320 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1323 pa_operation_unref(o
);
1326 if (!i
->operation_success
) {
1327 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1334 if (!(o
= pa_context_get_sink_info_by_name(i
->context
, NULL
, sink_info_cb
, i
))) {
1335 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1340 i
->operation_success
= 0;
1341 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1342 pa_threaded_mainloop_wait(i
->mainloop
);
1343 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1346 pa_operation_unref(o
);
1349 if (!i
->operation_success
) {
1350 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1355 /* Get source info */
1357 if (!(o
= pa_context_get_source_info_by_name(i
->context
, NULL
, source_info_cb
, i
))) {
1358 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1363 i
->operation_success
= 0;
1364 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1365 pa_threaded_mainloop_wait(i
->mainloop
);
1366 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1369 pa_operation_unref(o
);
1372 if (!i
->operation_success
) {
1373 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1378 pa_threaded_mainloop_unlock(i
->mainloop
);
1380 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() succeeded, fd=%i\n", i
->app_fd
);
1382 fd_info_add_to_list(i
);
1390 pa_operation_unref(o
);
1392 pa_threaded_mainloop_unlock(i
->mainloop
);
1399 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() failed\n");
1404 static int sndstat_open(int flags
, int *_errno
) {
1405 static const char sndstat
[] =
1406 "Sound Driver:3.8.1a-980706 (PulseAudio Virtual OSS)\n"
1408 "Config options: 0\n"
1410 "Installed drivers:\n"
1411 "Type 255: PulseAudio Virtual OSS\n"
1414 "PulseAudio Virtual OSS\n"
1417 "0: PulseAudio Virtual OSS\n"
1419 "Synth devices: NOT ENABLED IN CONFIG\n"
1426 "0: PulseAudio Virtual OSS\n";
1433 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"padsp-sndstat-XXXXXX", pa_get_temp_dir());
1435 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": sndstat_open()\n");
1437 if (flags
!= O_RDONLY
1439 && flags
!= (O_RDONLY
|O_LARGEFILE
)
1443 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": bad access!\n");
1454 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mkstemp() failed: %s\n", strerror(errno
));
1462 if (write(fd
, sndstat
, sizeof(sndstat
) -1) != sizeof(sndstat
)-1) {
1464 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write() failed: %s\n", strerror(errno
));
1468 if (lseek(fd
, SEEK_SET
, 0) < 0) {
1470 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": lseek() failed: %s\n", strerror(errno
));
1483 static int real_open(const char *filename
, int flags
, mode_t mode
) {
1486 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open(%s)\n", filename
?filename
:"NULL");
1488 if (!function_enter()) {
1490 return _open(filename
, flags
, mode
);
1493 if (filename
&& dsp_cloak_enable() && (pa_streq(filename
, "/dev/dsp") || pa_streq(filename
, "/dev/adsp") || pa_streq(filename
, "/dev/audio")))
1494 r
= dsp_open(flags
, &_errno
);
1495 else if (filename
&& mixer_cloak_enable() && pa_streq(filename
, "/dev/mixer"))
1496 r
= mixer_open(flags
, &_errno
);
1497 else if (filename
&& sndstat_cloak_enable() && pa_streq(filename
, "/dev/sndstat"))
1498 r
= sndstat_open(flags
, &_errno
);
1502 return _open(filename
, flags
, mode
);
1513 int open(const char *filename
, int flags
, ...) {
1517 if (flags
& O_CREAT
) {
1518 va_start(args
, flags
);
1519 if (sizeof(mode_t
) < sizeof(int))
1520 mode
= (mode_t
) va_arg(args
, int);
1522 mode
= va_arg(args
, mode_t
);
1526 return real_open(filename
, flags
, mode
);
1529 static bool is_audio_device_node(const char *path
) {
1531 pa_streq(path
, "/dev/dsp") ||
1532 pa_streq(path
, "/dev/adsp") ||
1533 pa_streq(path
, "/dev/audio") ||
1534 pa_streq(path
, "/dev/sndstat") ||
1535 pa_streq(path
, "/dev/mixer");
1538 int __open_2(const char *filename
, int flags
) {
1539 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __open_2(%s)\n", filename
?filename
:"NULL");
1541 if ((flags
& O_CREAT
) ||
1543 !is_audio_device_node(filename
)) {
1544 LOAD___OPEN_2_FUNC();
1545 return ___open_2(filename
, flags
);
1547 return real_open(filename
, flags
, 0);
1550 static int mixer_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1554 case SOUND_MIXER_READ_DEVMASK
:
1555 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_DEVMASK\n");
1557 *(int*) argp
= SOUND_MASK_PCM
| SOUND_MASK_IGAIN
;
1560 case SOUND_MIXER_READ_RECMASK
:
1561 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECMASK\n");
1563 *(int*) argp
= SOUND_MASK_IGAIN
;
1566 case SOUND_MIXER_READ_STEREODEVS
:
1567 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_STEREODEVS\n");
1569 pa_threaded_mainloop_lock(i
->mainloop
);
1571 if (i
->sink_volume
.channels
> 1)
1572 *(int*) argp
|= SOUND_MASK_PCM
;
1573 if (i
->source_volume
.channels
> 1)
1574 *(int*) argp
|= SOUND_MASK_IGAIN
;
1575 pa_threaded_mainloop_unlock(i
->mainloop
);
1579 case SOUND_MIXER_READ_RECSRC
:
1580 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECSRC\n");
1582 *(int*) argp
= SOUND_MASK_IGAIN
;
1585 case SOUND_MIXER_WRITE_RECSRC
:
1586 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_RECSRC\n");
1589 case SOUND_MIXER_READ_CAPS
:
1590 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_CAPS\n");
1595 case SOUND_MIXER_READ_PCM
:
1596 case SOUND_MIXER_READ_IGAIN
: {
1599 if (request
== SOUND_MIXER_READ_PCM
)
1600 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_PCM\n");
1602 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_IGAIN\n");
1604 pa_threaded_mainloop_lock(i
->mainloop
);
1606 if (request
== SOUND_MIXER_READ_PCM
)
1607 v
= &i
->sink_volume
;
1609 v
= &i
->source_volume
;
1612 ((v
->values
[0]*100/PA_VOLUME_NORM
)) |
1613 ((v
->values
[v
->channels
> 1 ? 1 : 0]*100/PA_VOLUME_NORM
) << 8);
1615 pa_threaded_mainloop_unlock(i
->mainloop
);
1620 case SOUND_MIXER_WRITE_PCM
:
1621 case SOUND_MIXER_WRITE_IGAIN
: {
1624 if (request
== SOUND_MIXER_WRITE_PCM
)
1625 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_PCM\n");
1627 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_IGAIN\n");
1629 pa_threaded_mainloop_lock(i
->mainloop
);
1631 if (request
== SOUND_MIXER_WRITE_PCM
) {
1633 pv
= &i
->sink_volume
;
1635 v
= i
->source_volume
;
1636 pv
= &i
->source_volume
;
1639 pv
->values
[0] = ((*(int*) argp
& 0xFF)*PA_VOLUME_NORM
)/100;
1640 pv
->values
[1] = ((*(int*) argp
>> 8)*PA_VOLUME_NORM
)/100;
1642 if (!pa_cvolume_equal(pv
, &v
)) {
1645 if (request
== SOUND_MIXER_WRITE_PCM
)
1646 o
= pa_context_set_sink_volume_by_index(i
->context
, i
->sink_index
, pv
, context_success_cb
, i
);
1648 o
= pa_context_set_source_volume_by_index(i
->context
, i
->source_index
, pv
, context_success_cb
, i
);
1651 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed set volume: %s", pa_strerror(pa_context_errno(i
->context
)));
1654 i
->operation_success
= 0;
1655 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1656 CONTEXT_CHECK_DEAD_GOTO(i
, exit_loop
);
1658 pa_threaded_mainloop_wait(i
->mainloop
);
1662 if (!i
->operation_success
)
1663 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1665 pa_operation_unref(o
);
1668 /* We don't wait for completion here */
1669 i
->volume_modify_count
++;
1672 pa_threaded_mainloop_unlock(i
->mainloop
);
1677 case SOUND_MIXER_INFO
: {
1678 mixer_info
*mi
= argp
;
1680 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_INFO\n");
1682 memset(mi
, 0, sizeof(mixer_info
));
1683 strncpy(mi
->id
, "PULSEAUDIO", sizeof(mi
->id
));
1684 strncpy(mi
->name
, "PulseAudio Virtual OSS", sizeof(mi
->name
));
1685 pa_threaded_mainloop_lock(i
->mainloop
);
1686 mi
->modify_counter
= i
->volume_modify_count
;
1687 pa_threaded_mainloop_unlock(i
->mainloop
);
1692 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unknown ioctl 0x%08lx\n", request
);
1705 static int map_format(int *fmt
, pa_sample_spec
*ss
) {
1709 ss
->format
= PA_SAMPLE_ULAW
;
1713 ss
->format
= PA_SAMPLE_ALAW
;
1720 ss
->format
= PA_SAMPLE_U8
;
1727 ss
->format
= PA_SAMPLE_S16BE
;
1734 ss
->format
= PA_SAMPLE_S16LE
;
1738 ss
->format
= PA_SAMPLE_S16NE
;
1746 static int map_format_back(pa_sample_format_t format
) {
1748 case PA_SAMPLE_S16LE
: return AFMT_S16_LE
;
1749 case PA_SAMPLE_S16BE
: return AFMT_S16_BE
;
1750 case PA_SAMPLE_ULAW
: return AFMT_MU_LAW
;
1751 case PA_SAMPLE_ALAW
: return AFMT_A_LAW
;
1752 case PA_SAMPLE_U8
: return AFMT_U8
;
1758 static int dsp_flush_fd(int fd
) {
1762 if (ioctl(fd
, SIOCINQ
, &l
) < 0) {
1763 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1771 k
= (size_t) l
> sizeof(buf
) ? sizeof(buf
) : (size_t) l
;
1772 if (read(fd
, buf
, k
) < 0)
1773 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": read(): %s\n", strerror(errno
));
1779 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1784 static int dsp_flush_socket(fd_info
*i
) {
1787 if ((i
->thread_fd
< 0) && (i
->app_fd
< 0))
1790 if (i
->thread_fd
>= 0)
1791 res
= dsp_flush_fd(i
->thread_fd
);
1797 res
= dsp_flush_fd(i
->app_fd
);
1805 static int dsp_empty_socket(fd_info
*i
) {
1809 /* Empty the socket */
1813 if (i
->thread_fd
< 0)
1816 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
1817 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1826 pa_threaded_mainloop_wait(i
->mainloop
);
1831 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1836 static int dsp_drain(fd_info
*i
) {
1837 pa_operation
*o
= NULL
;
1843 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Draining.\n");
1845 pa_threaded_mainloop_lock(i
->mainloop
);
1847 if (dsp_empty_socket(i
) < 0)
1850 if (!i
->play_stream
)
1853 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Really draining.\n");
1855 if (!(o
= pa_stream_drain(i
->play_stream
, stream_success_cb
, i
))) {
1856 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1860 i
->operation_success
= 0;
1861 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1862 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1864 pa_threaded_mainloop_wait(i
->mainloop
);
1867 if (!i
->operation_success
) {
1868 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1877 pa_operation_unref(o
);
1879 pa_threaded_mainloop_unlock(i
->mainloop
);
1884 static int dsp_trigger(fd_info
*i
) {
1885 pa_operation
*o
= NULL
;
1888 if (!i
->play_stream
)
1891 pa_threaded_mainloop_lock(i
->mainloop
);
1893 if (dsp_empty_socket(i
) < 0)
1896 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Triggering.\n");
1898 if (!(o
= pa_stream_trigger(i
->play_stream
, stream_success_cb
, i
))) {
1899 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1903 i
->operation_success
= 0;
1904 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1905 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1907 pa_threaded_mainloop_wait(i
->mainloop
);
1910 if (!i
->operation_success
) {
1911 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1920 pa_operation_unref(o
);
1922 pa_threaded_mainloop_unlock(i
->mainloop
);
1927 static int dsp_cork(fd_info
*i
, pa_stream
*s
, int b
) {
1928 pa_operation
*o
= NULL
;
1931 pa_threaded_mainloop_lock(i
->mainloop
);
1933 if (!(o
= pa_stream_cork(s
, b
, stream_success_cb
, i
))) {
1934 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1938 i
->operation_success
= 0;
1939 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1940 if (s
== i
->play_stream
)
1941 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1942 else if (s
== i
->rec_stream
)
1943 RECORD_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1945 pa_threaded_mainloop_wait(i
->mainloop
);
1948 if (!i
->operation_success
) {
1949 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1958 pa_operation_unref(o
);
1960 pa_threaded_mainloop_unlock(i
->mainloop
);
1965 static int dsp_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1968 if (i
->thread_fd
== -1) {
1970 * We've encountered some fatal error and are just waiting
1973 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": got ioctl 0x%08lx in fatal error state\n", request
);
1979 case SNDCTL_DSP_SETFMT
: {
1980 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp
);
1982 pa_threaded_mainloop_lock(i
->mainloop
);
1984 if (*(int*) argp
== AFMT_QUERY
)
1985 *(int*) argp
= map_format_back(i
->sample_spec
.format
);
1987 map_format((int*) argp
, &i
->sample_spec
);
1991 pa_threaded_mainloop_unlock(i
->mainloop
);
1995 case SNDCTL_DSP_SPEED
: {
2000 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SPEED: %i\n", *(int*) argp
);
2002 pa_threaded_mainloop_lock(i
->mainloop
);
2004 ss
= i
->sample_spec
;
2005 ss
.rate
= *(int*) argp
;
2007 if ((valid
= pa_sample_spec_valid(&ss
))) {
2008 i
->sample_spec
= ss
;
2012 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ss: %s\n", pa_sample_spec_snprint(t
, sizeof(t
), &i
->sample_spec
));
2014 pa_threaded_mainloop_unlock(i
->mainloop
);
2024 case SNDCTL_DSP_STEREO
:
2025 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_STEREO: %i\n", *(int*) argp
);
2027 pa_threaded_mainloop_lock(i
->mainloop
);
2029 i
->sample_spec
.channels
= *(int*) argp
? 2 : 1;
2032 pa_threaded_mainloop_unlock(i
->mainloop
);
2035 case SNDCTL_DSP_CHANNELS
: {
2039 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp
);
2041 pa_threaded_mainloop_lock(i
->mainloop
);
2043 ss
= i
->sample_spec
;
2044 ss
.channels
= *(int*) argp
;
2046 if ((valid
= pa_sample_spec_valid(&ss
))) {
2047 i
->sample_spec
= ss
;
2051 pa_threaded_mainloop_unlock(i
->mainloop
);
2061 case SNDCTL_DSP_GETBLKSIZE
:
2062 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETBLKSIZE\n");
2064 pa_threaded_mainloop_lock(i
->mainloop
);
2067 *(int*) argp
= i
->fragment_size
;
2069 pa_threaded_mainloop_unlock(i
->mainloop
);
2073 case SNDCTL_DSP_SETFRAGMENT
:
2074 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp
);
2076 pa_threaded_mainloop_lock(i
->mainloop
);
2078 i
->fragment_size
= 1 << ((*(int*) argp
) & 31);
2079 i
->n_fragments
= (*(int*) argp
) >> 16;
2081 /* 0x7FFF means that we can set whatever we like */
2082 if (i
->n_fragments
== 0x7FFF)
2083 i
->n_fragments
= 12;
2087 pa_threaded_mainloop_unlock(i
->mainloop
);
2091 case SNDCTL_DSP_GETCAPS
:
2092 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CAPS\n");
2094 *(int*) argp
= DSP_CAP_DUPLEX
| DSP_CAP_TRIGGER
2095 #ifdef DSP_CAP_MULTI
2101 case SNDCTL_DSP_GETODELAY
: {
2104 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETODELAY\n");
2106 pa_threaded_mainloop_lock(i
->mainloop
);
2113 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop
);
2115 if (pa_stream_get_latency(i
->play_stream
, &usec
, NULL
) >= 0) {
2116 *(int*) argp
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2120 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2121 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2125 pa_threaded_mainloop_wait(i
->mainloop
);
2131 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0)
2132 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2136 # warning "Your platform does not support SIOCINQ, something might not work as intended."
2139 pa_threaded_mainloop_unlock(i
->mainloop
);
2141 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ODELAY: %i\n", *(int*) argp
);
2146 case SNDCTL_DSP_RESET
: {
2147 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_RESET\n");
2149 pa_threaded_mainloop_lock(i
->mainloop
);
2152 dsp_flush_socket(i
);
2154 i
->optr_n_blocks
= 0;
2156 pa_threaded_mainloop_unlock(i
->mainloop
);
2160 case SNDCTL_DSP_GETFMTS
: {
2161 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETFMTS\n");
2163 *(int*) argp
= AFMT_MU_LAW
|AFMT_A_LAW
|AFMT_U8
|AFMT_S16_LE
|AFMT_S16_BE
;
2167 case SNDCTL_DSP_POST
:
2168 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_POST\n");
2170 if (dsp_trigger(i
) < 0)
2174 case SNDCTL_DSP_GETTRIGGER
:
2175 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETTRIGGER\n");
2178 if (!i
->play_precork
)
2179 *(int*) argp
|= PCM_ENABLE_OUTPUT
;
2180 if (!i
->rec_precork
)
2181 *(int*) argp
|= PCM_ENABLE_INPUT
;
2185 case SNDCTL_DSP_SETTRIGGER
:
2186 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp
);
2193 i
->play_precork
= !((*(int*) argp
) & PCM_ENABLE_OUTPUT
);
2195 if (i
->play_stream
) {
2196 if (dsp_cork(i
, i
->play_stream
, !((*(int*) argp
) & PCM_ENABLE_OUTPUT
)) < 0)
2198 if (dsp_trigger(i
) < 0)
2202 i
->rec_precork
= !((*(int*) argp
) & PCM_ENABLE_INPUT
);
2204 if (i
->rec_stream
) {
2205 if (dsp_cork(i
, i
->rec_stream
, !((*(int*) argp
) & PCM_ENABLE_INPUT
)) < 0)
2211 case SNDCTL_DSP_SYNC
:
2212 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SYNC\n");
2214 if (dsp_drain(i
) < 0)
2219 case SNDCTL_DSP_GETOSPACE
:
2220 case SNDCTL_DSP_GETISPACE
: {
2221 audio_buf_info
*bi
= (audio_buf_info
*) argp
;
2225 if (request
== SNDCTL_DSP_GETOSPACE
)
2226 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOSPACE\n");
2228 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETISPACE\n");
2230 pa_threaded_mainloop_lock(i
->mainloop
);
2234 if (request
== SNDCTL_DSP_GETOSPACE
) {
2235 if (i
->play_stream
) {
2236 if ((k
= pa_stream_writable_size(i
->play_stream
)) == (size_t) -1)
2237 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2239 k
= i
->fragment_size
* i
->n_fragments
;
2242 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
2243 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2247 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2250 bi
->bytes
= k
> (size_t) l
? k
- l
: 0;
2252 if (i
->rec_stream
) {
2253 if ((k
= pa_stream_readable_size(i
->rec_stream
)) == (size_t) -1)
2254 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2259 if (ioctl(i
->app_fd
, SIOCINQ
, &l
) < 0) {
2260 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2264 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2269 bi
->fragsize
= i
->fragment_size
;
2270 bi
->fragstotal
= i
->n_fragments
;
2271 bi
->fragments
= bi
->bytes
/ bi
->fragsize
;
2273 pa_threaded_mainloop_unlock(i
->mainloop
);
2275 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi
->fragsize
, bi
->fragstotal
, bi
->bytes
, bi
->fragments
);
2280 case SOUND_PCM_READ_RATE
:
2281 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_RATE\n");
2283 pa_threaded_mainloop_lock(i
->mainloop
);
2284 *(int*) argp
= i
->sample_spec
.rate
;
2285 pa_threaded_mainloop_unlock(i
->mainloop
);
2288 case SOUND_PCM_READ_CHANNELS
:
2289 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_CHANNELS\n");
2291 pa_threaded_mainloop_lock(i
->mainloop
);
2292 *(int*) argp
= i
->sample_spec
.channels
;
2293 pa_threaded_mainloop_unlock(i
->mainloop
);
2296 case SOUND_PCM_READ_BITS
:
2297 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_BITS\n");
2299 pa_threaded_mainloop_lock(i
->mainloop
);
2300 *(int*) argp
= pa_sample_size(&i
->sample_spec
)*8;
2301 pa_threaded_mainloop_unlock(i
->mainloop
);
2304 case SNDCTL_DSP_GETOPTR
: {
2307 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOPTR\n");
2309 info
= (count_info
*) argp
;
2310 memset(info
, 0, sizeof(*info
));
2312 pa_threaded_mainloop_lock(i
->mainloop
);
2317 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop2
);
2319 if (pa_stream_get_time(i
->play_stream
, &usec
) >= 0) {
2320 size_t k
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2323 info
->bytes
= (int) k
;
2324 m
= k
/ i
->fragment_size
;
2325 info
->blocks
= m
- i
->optr_n_blocks
;
2326 i
->optr_n_blocks
= m
;
2331 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2332 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2336 pa_threaded_mainloop_wait(i
->mainloop
);
2341 pa_threaded_mainloop_unlock(i
->mainloop
);
2343 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info
->bytes
, info
->blocks
, info
->ptr
);
2348 case SNDCTL_DSP_GETIPTR
:
2349 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": invalid ioctl SNDCTL_DSP_GETIPTR\n");
2352 case SNDCTL_DSP_SETDUPLEX
:
2353 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETDUPLEX\n");
2354 /* this is a no-op */
2358 /* Mixer ioctls are valid on /dev/dsp as well */
2359 return mixer_ioctl(i
, request
, argp
, _errno
);
2374 int ioctl(int fd
, int request
, ...) {
2376 int ioctl(int fd
, unsigned long request
, ...) {
2383 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ioctl()\n");
2385 va_start(args
, request
);
2386 argp
= va_arg(args
, void *);
2389 if (!function_enter()) {
2391 return _ioctl(fd
, request
, argp
);
2394 if (!(i
= fd_info_find(fd
))) {
2397 return _ioctl(fd
, request
, argp
);
2400 if (i
->type
== FD_INFO_MIXER
)
2401 r
= mixer_ioctl(i
, request
, argp
, &_errno
);
2403 r
= dsp_ioctl(i
, request
, argp
, &_errno
);
2418 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": close()\n");
2420 if (!function_enter()) {
2425 if (!(i
= fd_info_find(fd
))) {
2431 fd_info_remove_from_list(i
);
2439 int access(const char *pathname
, int mode
) {
2441 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": access(%s)\n", pathname
?pathname
:"NULL");
2444 !is_audio_device_node(pathname
)) {
2446 return _access(pathname
, mode
);
2450 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = EACCESS\n", pathname
, mode
);
2455 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = OK\n", pathname
, mode
);
2460 int stat(const char *pathname
, struct stat
*buf
) {
2462 struct stat64 parent
;
2470 !is_audio_device_node(pathname
)) {
2471 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat(%s)\n", pathname
?pathname
:"NULL");
2473 return _stat(pathname
, buf
);
2476 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stat(%s)\n", pathname
);
2480 ret
= __xstat64(_STAT_VER
, "/dev", &parent
);
2482 ret
= __xstat(_STAT_VER
, "/dev", &parent
);
2486 ret
= stat64("/dev", &parent
);
2488 ret
= stat("/dev", &parent
);
2493 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unable to stat \"/dev\"\n");
2497 buf
->st_dev
= parent
.st_dev
;
2498 buf
->st_ino
= 0xDEADBEEF; /* FIXME: Can we do this in a safe way? */
2499 buf
->st_mode
= S_IFCHR
| S_IRUSR
| S_IWUSR
;
2501 buf
->st_uid
= getuid();
2502 buf
->st_gid
= getgid();
2503 buf
->st_rdev
= 0x0E03; /* FIXME: Linux specific */
2505 buf
->st_atime
= 1181557705;
2506 buf
->st_mtime
= 1181557705;
2507 buf
->st_ctime
= 1181557705;
2508 buf
->st_blksize
= 1;
2516 int stat64(const char *pathname
, struct stat64
*buf
) {
2520 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat64(%s)\n", pathname
?pathname
:"NULL");
2524 !is_audio_device_node(pathname
)) {
2526 return _stat64(pathname
, buf
);
2529 ret
= stat(pathname
, &oldbuf
);
2533 buf
->st_dev
= oldbuf
.st_dev
;
2534 buf
->st_ino
= oldbuf
.st_ino
;
2535 buf
->st_mode
= oldbuf
.st_mode
;
2536 buf
->st_nlink
= oldbuf
.st_nlink
;
2537 buf
->st_uid
= oldbuf
.st_uid
;
2538 buf
->st_gid
= oldbuf
.st_gid
;
2539 buf
->st_rdev
= oldbuf
.st_rdev
;
2540 buf
->st_size
= oldbuf
.st_size
;
2541 buf
->st_atime
= oldbuf
.st_atime
;
2542 buf
->st_mtime
= oldbuf
.st_mtime
;
2543 buf
->st_ctime
= oldbuf
.st_ctime
;
2544 buf
->st_blksize
= oldbuf
.st_blksize
;
2545 buf
->st_blocks
= oldbuf
.st_blocks
;
2550 int open64(const char *filename
, int flags
, ...) {
2554 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open64(%s)\n", filename
?filename
:"NULL");
2556 if (flags
& O_CREAT
) {
2557 va_start(args
, flags
);
2558 if (sizeof(mode_t
) < sizeof(int))
2559 mode
= va_arg(args
, int);
2561 mode
= va_arg(args
, mode_t
);
2566 !is_audio_device_node(filename
)) {
2568 return _open64(filename
, flags
, mode
);
2571 return real_open(filename
, flags
, mode
);
2574 int __open64_2(const char *filename
, int flags
) {
2575 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __open64_2(%s)\n", filename
?filename
:"NULL");
2577 if ((flags
& O_CREAT
) ||
2579 !is_audio_device_node(filename
)) {
2580 LOAD___OPEN64_2_FUNC();
2581 return ___open64_2(filename
, flags
);
2584 return real_open(filename
, flags
, 0);
2591 int __xstat(int ver
, const char *pathname
, struct stat
*buf
) {
2592 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat(%s)\n", pathname
?pathname
:"NULL");
2596 !is_audio_device_node(pathname
)) {
2598 return ___xstat(ver
, pathname
, buf
);
2601 if (ver
!= _STAT_VER
) {
2606 return stat(pathname
, buf
);
2611 int __xstat64(int ver
, const char *pathname
, struct stat64
*buf
) {
2612 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat64(%s)\n", pathname
?pathname
:"NULL");
2616 !is_audio_device_node(pathname
)) {
2617 LOAD_XSTAT64_FUNC();
2618 return ___xstat64(ver
, pathname
, buf
);
2621 if (ver
!= _STAT_VER
) {
2626 return stat64(pathname
, buf
);
2633 FILE* fopen(const char *filename
, const char *mode
) {
2638 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen(%s)\n", filename
?filename
:"NULL");
2642 !is_audio_device_node(filename
)) {
2644 return _fopen(filename
, mode
);
2660 if ((((mode
[1] == 'b') || (mode
[1] == 't')) && (mode
[2] == '+')) || (mode
[1] == '+'))
2663 if ((fd
= real_open(filename
, m
, 0)) < 0)
2666 if (!(f
= fdopen(fd
, mode
))) {
2676 FILE *fopen64(const char *filename
, const char *mode
) {
2678 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen64(%s)\n", filename
?filename
:"NULL");
2682 !is_audio_device_node(filename
)) {
2683 LOAD_FOPEN64_FUNC();
2684 return _fopen64(filename
, mode
);
2687 return fopen(filename
, mode
);
2692 int fclose(FILE *f
) {
2695 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fclose()\n");
2697 if (!function_enter()) {
2702 if (!(i
= fd_info_find(fileno(f
)))) {
2708 fd_info_remove_from_list(i
);
2710 /* Dirty trick to avoid that the fd is not freed twice, once by us
2711 * and once by the real fclose() */