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
)));
928 buf
= (const char*)data
+ i
->rec_offset
;
930 if ((r
= write(i
->thread_fd
, buf
, len
- i
->rec_offset
)) <= 0) {
935 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write(): %s\n", strerror(errno
));
939 assert((size_t)r
<= len
- i
->rec_offset
);
940 i
->rec_offset
+= (size_t) r
;
942 if (i
->rec_offset
== len
) {
943 if (pa_stream_drop(i
->rec_stream
) < 0) {
944 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
950 assert(n
>= (size_t) r
);
954 if (n
>= i
->fragment_size
)
955 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
957 i
->io_flags
&= ~PA_IO_EVENT_OUTPUT
;
961 pa_mainloop_api
*api
;
963 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
964 api
->io_enable(i
->io_event
, i
->io_flags
);
967 /* So, we emptied the socket now, let's tell dsp_empty_socket()
969 pa_threaded_mainloop_signal(i
->mainloop
, 0);
974 static void stream_state_cb(pa_stream
*s
, void * userdata
) {
975 fd_info
*i
= userdata
;
978 switch (pa_stream_get_state(s
)) {
980 case PA_STREAM_READY
:
981 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stream established.\n");
984 case PA_STREAM_FAILED
:
985 if (s
== i
->play_stream
) {
986 debug(DEBUG_LEVEL_NORMAL
,
987 __FILE__
": pa_stream_connect_playback() failed: %s\n",
988 pa_strerror(pa_context_errno(i
->context
)));
989 pa_stream_unref(i
->play_stream
);
990 i
->play_stream
= NULL
;
991 } else if (s
== i
->rec_stream
) {
992 debug(DEBUG_LEVEL_NORMAL
,
993 __FILE__
": pa_stream_connect_record() failed: %s\n",
994 pa_strerror(pa_context_errno(i
->context
)));
995 pa_stream_unref(i
->rec_stream
);
996 i
->rec_stream
= NULL
;
1001 case PA_STREAM_TERMINATED
:
1002 case PA_STREAM_UNCONNECTED
:
1003 case PA_STREAM_CREATING
:
1008 static int create_playback_stream(fd_info
*i
) {
1009 pa_buffer_attr attr
;
1016 if (!(i
->play_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
1017 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1021 pa_stream_set_state_callback(i
->play_stream
, stream_state_cb
, i
);
1022 pa_stream_set_write_callback(i
->play_stream
, stream_request_cb
, i
);
1023 pa_stream_set_latency_update_callback(i
->play_stream
, stream_latency_update_cb
, i
);
1025 memset(&attr
, 0, sizeof(attr
));
1026 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1027 attr
.tlength
= (uint32_t) (i
->fragment_size
* i
->n_fragments
);
1028 attr
.prebuf
= (uint32_t) i
->fragment_size
;
1029 attr
.minreq
= (uint32_t) i
->fragment_size
;
1031 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
|PA_STREAM_EARLY_REQUESTS
;
1032 if (i
->play_precork
) {
1033 flags
|= PA_STREAM_START_CORKED
;
1034 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1036 if (pa_stream_connect_playback(i
->play_stream
, NULL
, &attr
, flags
, NULL
, NULL
) < 0) {
1037 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1041 n
= (int) i
->fragment_size
;
1042 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1043 n
= (int) i
->fragment_size
;
1044 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1052 static int create_record_stream(fd_info
*i
) {
1053 pa_buffer_attr attr
;
1060 if (!(i
->rec_stream
= pa_stream_new(i
->context
, stream_name(), &i
->sample_spec
, NULL
))) {
1061 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1065 pa_stream_set_state_callback(i
->rec_stream
, stream_state_cb
, i
);
1066 pa_stream_set_read_callback(i
->rec_stream
, stream_request_cb
, i
);
1067 pa_stream_set_latency_update_callback(i
->rec_stream
, stream_latency_update_cb
, i
);
1069 memset(&attr
, 0, sizeof(attr
));
1070 attr
.maxlength
= (uint32_t) (i
->fragment_size
* (i
->n_fragments
+1));
1071 attr
.fragsize
= (uint32_t) i
->fragment_size
;
1073 flags
= PA_STREAM_INTERPOLATE_TIMING
|PA_STREAM_AUTO_TIMING_UPDATE
;
1074 if (i
->rec_precork
) {
1075 flags
|= PA_STREAM_START_CORKED
;
1076 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": creating stream corked\n");
1078 if (pa_stream_connect_record(i
->rec_stream
, NULL
, &attr
, flags
) < 0) {
1079 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1083 n
= (int) i
->fragment_size
;
1084 setsockopt(i
->app_fd
, SOL_SOCKET
, SO_RCVBUF
, &n
, sizeof(n
));
1085 n
= (int) i
->fragment_size
;
1086 setsockopt(i
->thread_fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
));
1094 static void free_streams(fd_info
*i
) {
1097 if (i
->play_stream
) {
1098 pa_stream_disconnect(i
->play_stream
);
1099 pa_stream_unref(i
->play_stream
);
1100 i
->play_stream
= NULL
;
1101 i
->io_flags
|= PA_IO_EVENT_INPUT
;
1104 if (i
->rec_stream
) {
1105 pa_stream_disconnect(i
->rec_stream
);
1106 pa_stream_unref(i
->rec_stream
);
1107 i
->rec_stream
= NULL
;
1108 i
->io_flags
|= PA_IO_EVENT_OUTPUT
;
1112 pa_mainloop_api
*api
;
1114 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1115 api
->io_enable(i
->io_event
, i
->io_flags
);
1119 static void io_event_cb(pa_mainloop_api
*api
, pa_io_event
*e
, int fd
, pa_io_event_flags_t flags
, void *userdata
) {
1120 fd_info
*i
= userdata
;
1122 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1124 if (flags
& PA_IO_EVENT_INPUT
) {
1126 if (!i
->play_stream
) {
1127 if (create_playback_stream(i
) < 0)
1130 if (fd_info_copy_data(i
, 0) < 0)
1134 } else if (flags
& PA_IO_EVENT_OUTPUT
) {
1136 if (!i
->rec_stream
) {
1137 if (create_record_stream(i
) < 0)
1140 if (fd_info_copy_data(i
, 0) < 0)
1144 } else if (flags
& (PA_IO_EVENT_HANGUP
|PA_IO_EVENT_ERROR
))
1150 /* We can't do anything better than removing the event source */
1151 fd_info_shutdown(i
);
1154 static int dsp_open(int flags
, int *_errno
) {
1156 pa_mainloop_api
*api
;
1160 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open()\n");
1162 if (!(i
= fd_info_new(FD_INFO_STREAM
, _errno
)))
1165 if ((flags
& O_NONBLOCK
) == O_NONBLOCK
) {
1166 if ((f
= fcntl(i
->app_fd
, F_GETFL
)) >= 0)
1167 fcntl(i
->app_fd
, F_SETFL
, f
|O_NONBLOCK
);
1169 if ((f
= fcntl(i
->thread_fd
, F_GETFL
)) >= 0)
1170 fcntl(i
->thread_fd
, F_SETFL
, f
|O_NONBLOCK
);
1172 fcntl(i
->app_fd
, F_SETFD
, FD_CLOEXEC
);
1173 fcntl(i
->thread_fd
, F_SETFD
, FD_CLOEXEC
);
1175 pa_threaded_mainloop_lock(i
->mainloop
);
1176 api
= pa_threaded_mainloop_get_api(i
->mainloop
);
1178 switch (flags
& O_ACCMODE
) {
1180 i
->io_flags
= PA_IO_EVENT_OUTPUT
;
1181 shutdown(i
->thread_fd
, SHUT_RD
);
1182 shutdown(i
->app_fd
, SHUT_WR
);
1185 i
->io_flags
= PA_IO_EVENT_INPUT
;
1186 shutdown(i
->thread_fd
, SHUT_WR
);
1187 shutdown(i
->app_fd
, SHUT_RD
);
1190 i
->io_flags
= PA_IO_EVENT_INPUT
| PA_IO_EVENT_OUTPUT
;
1196 if (!(i
->io_event
= api
->io_new(api
, i
->thread_fd
, i
->io_flags
, io_event_cb
, i
)))
1199 pa_threaded_mainloop_unlock(i
->mainloop
);
1201 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() succeeded, fd=%i\n", i
->app_fd
);
1203 fd_info_add_to_list(i
);
1210 pa_threaded_mainloop_unlock(i
->mainloop
);
1217 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": dsp_open() failed\n");
1222 static void sink_info_cb(pa_context
*context
, const pa_sink_info
*si
, int eol
, void *userdata
) {
1223 fd_info
*i
= userdata
;
1226 i
->operation_success
= 0;
1227 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1234 if (!pa_cvolume_equal(&i
->sink_volume
, &si
->volume
))
1235 i
->volume_modify_count
++;
1237 i
->sink_volume
= si
->volume
;
1238 i
->sink_index
= si
->index
;
1240 i
->operation_success
= 1;
1241 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1244 static void source_info_cb(pa_context
*context
, const pa_source_info
*si
, int eol
, void *userdata
) {
1245 fd_info
*i
= userdata
;
1248 i
->operation_success
= 0;
1249 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1256 if (!pa_cvolume_equal(&i
->source_volume
, &si
->volume
))
1257 i
->volume_modify_count
++;
1259 i
->source_volume
= si
->volume
;
1260 i
->source_index
= si
->index
;
1262 i
->operation_success
= 1;
1263 pa_threaded_mainloop_signal(i
->mainloop
, 0);
1266 static void subscribe_cb(pa_context
*context
, pa_subscription_event_type_t t
, uint32_t idx
, void *userdata
) {
1267 fd_info
*i
= userdata
;
1268 pa_operation
*o
= NULL
;
1270 if (i
->sink_index
!= idx
)
1273 if ((t
& PA_SUBSCRIPTION_EVENT_TYPE_MASK
) != PA_SUBSCRIPTION_EVENT_CHANGE
)
1276 if (!(o
= pa_context_get_sink_info_by_index(i
->context
, i
->sink_index
, sink_info_cb
, i
))) {
1277 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1281 pa_operation_unref(o
);
1284 static int mixer_open(int flags
, int *_errno
) {
1286 pa_operation
*o
= NULL
;
1289 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open()\n");
1291 if (!(i
= fd_info_new(FD_INFO_MIXER
, _errno
)))
1294 pa_threaded_mainloop_lock(i
->mainloop
);
1296 pa_context_set_subscribe_callback(i
->context
, subscribe_cb
, i
);
1298 if (!(o
= pa_context_subscribe(i
->context
, PA_SUBSCRIPTION_MASK_SINK
| PA_SUBSCRIPTION_MASK_SOURCE
, context_success_cb
, i
))) {
1299 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1304 i
->operation_success
= 0;
1305 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1306 pa_threaded_mainloop_wait(i
->mainloop
);
1307 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1310 pa_operation_unref(o
);
1313 if (!i
->operation_success
) {
1314 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i
->context
)));
1321 if (!(o
= pa_context_get_sink_info_by_name(i
->context
, NULL
, sink_info_cb
, i
))) {
1322 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1327 i
->operation_success
= 0;
1328 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1329 pa_threaded_mainloop_wait(i
->mainloop
);
1330 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1333 pa_operation_unref(o
);
1336 if (!i
->operation_success
) {
1337 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get sink info: %s", pa_strerror(pa_context_errno(i
->context
)));
1342 /* Get source info */
1344 if (!(o
= pa_context_get_source_info_by_name(i
->context
, NULL
, source_info_cb
, i
))) {
1345 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1350 i
->operation_success
= 0;
1351 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1352 pa_threaded_mainloop_wait(i
->mainloop
);
1353 CONTEXT_CHECK_DEAD_GOTO(i
, fail
);
1356 pa_operation_unref(o
);
1359 if (!i
->operation_success
) {
1360 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to get source info: %s", pa_strerror(pa_context_errno(i
->context
)));
1365 pa_threaded_mainloop_unlock(i
->mainloop
);
1367 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() succeeded, fd=%i\n", i
->app_fd
);
1369 fd_info_add_to_list(i
);
1377 pa_operation_unref(o
);
1379 pa_threaded_mainloop_unlock(i
->mainloop
);
1386 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mixer_open() failed\n");
1391 static int sndstat_open(int flags
, int *_errno
) {
1392 static const char sndstat
[] =
1393 "Sound Driver:3.8.1a-980706 (PulseAudio Virtual OSS)\n"
1395 "Config options: 0\n"
1397 "Installed drivers:\n"
1398 "Type 255: PulseAudio Virtual OSS\n"
1401 "PulseAudio Virtual OSS\n"
1404 "0: PulseAudio Virtual OSS\n"
1406 "Synth devices: NOT ENABLED IN CONFIG\n"
1413 "0: PulseAudio Virtual OSS\n";
1420 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"padsp-sndstat-XXXXXX", pa_get_temp_dir());
1422 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": sndstat_open()\n");
1424 if (flags
!= O_RDONLY
1426 && flags
!= (O_RDONLY
|O_LARGEFILE
)
1430 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": bad access!\n");
1441 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": mkstemp() failed: %s\n", strerror(errno
));
1448 if (write(fd
, sndstat
, sizeof(sndstat
) -1) != sizeof(sndstat
)-1) {
1450 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": write() failed: %s\n", strerror(errno
));
1454 if (lseek(fd
, SEEK_SET
, 0) < 0) {
1456 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": lseek() failed: %s\n", strerror(errno
));
1469 static int real_open(const char *filename
, int flags
, mode_t mode
) {
1472 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open(%s)\n", filename
?filename
:"NULL");
1474 if (!function_enter()) {
1476 return _open(filename
, flags
, mode
);
1479 if (filename
&& dsp_cloak_enable() && (pa_streq(filename
, "/dev/dsp") || pa_streq(filename
, "/dev/adsp") || pa_streq(filename
, "/dev/audio")))
1480 r
= dsp_open(flags
, &_errno
);
1481 else if (filename
&& mixer_cloak_enable() && pa_streq(filename
, "/dev/mixer"))
1482 r
= mixer_open(flags
, &_errno
);
1483 else if (filename
&& sndstat_cloak_enable() && pa_streq(filename
, "/dev/sndstat"))
1484 r
= sndstat_open(flags
, &_errno
);
1488 return _open(filename
, flags
, mode
);
1499 int open(const char *filename
, int flags
, ...) {
1503 if (flags
& O_CREAT
) {
1504 va_start(args
, flags
);
1505 if (sizeof(mode_t
) < sizeof(int))
1506 mode
= (mode_t
) va_arg(args
, int);
1508 mode
= va_arg(args
, mode_t
);
1512 return real_open(filename
, flags
, mode
);
1515 static pa_bool_t
is_audio_device_node(const char *path
) {
1517 pa_streq(path
, "/dev/dsp") ||
1518 pa_streq(path
, "/dev/adsp") ||
1519 pa_streq(path
, "/dev/audio") ||
1520 pa_streq(path
, "/dev/sndstat") ||
1521 pa_streq(path
, "/dev/mixer");
1524 int __open_2(const char *filename
, int flags
) {
1525 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __open_2(%s)\n", filename
?filename
:"NULL");
1527 if ((flags
& O_CREAT
) ||
1529 !is_audio_device_node(filename
)) {
1530 LOAD___OPEN_2_FUNC();
1531 return ___open_2(filename
, flags
);
1533 return real_open(filename
, flags
, 0);
1536 static int mixer_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1540 case SOUND_MIXER_READ_DEVMASK
:
1541 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_DEVMASK\n");
1543 *(int*) argp
= SOUND_MASK_PCM
| SOUND_MASK_IGAIN
;
1546 case SOUND_MIXER_READ_RECMASK
:
1547 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECMASK\n");
1549 *(int*) argp
= SOUND_MASK_IGAIN
;
1552 case SOUND_MIXER_READ_STEREODEVS
:
1553 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_STEREODEVS\n");
1555 pa_threaded_mainloop_lock(i
->mainloop
);
1557 if (i
->sink_volume
.channels
> 1)
1558 *(int*) argp
|= SOUND_MASK_PCM
;
1559 if (i
->source_volume
.channels
> 1)
1560 *(int*) argp
|= SOUND_MASK_IGAIN
;
1561 pa_threaded_mainloop_unlock(i
->mainloop
);
1565 case SOUND_MIXER_READ_RECSRC
:
1566 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_RECSRC\n");
1568 *(int*) argp
= SOUND_MASK_IGAIN
;
1571 case SOUND_MIXER_WRITE_RECSRC
:
1572 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_RECSRC\n");
1575 case SOUND_MIXER_READ_CAPS
:
1576 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_CAPS\n");
1581 case SOUND_MIXER_READ_PCM
:
1582 case SOUND_MIXER_READ_IGAIN
: {
1585 if (request
== SOUND_MIXER_READ_PCM
)
1586 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_PCM\n");
1588 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_READ_IGAIN\n");
1590 pa_threaded_mainloop_lock(i
->mainloop
);
1592 if (request
== SOUND_MIXER_READ_PCM
)
1593 v
= &i
->sink_volume
;
1595 v
= &i
->source_volume
;
1598 ((v
->values
[0]*100/PA_VOLUME_NORM
)) |
1599 ((v
->values
[v
->channels
> 1 ? 1 : 0]*100/PA_VOLUME_NORM
) << 8);
1601 pa_threaded_mainloop_unlock(i
->mainloop
);
1606 case SOUND_MIXER_WRITE_PCM
:
1607 case SOUND_MIXER_WRITE_IGAIN
: {
1610 if (request
== SOUND_MIXER_WRITE_PCM
)
1611 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_PCM\n");
1613 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_WRITE_IGAIN\n");
1615 pa_threaded_mainloop_lock(i
->mainloop
);
1617 if (request
== SOUND_MIXER_WRITE_PCM
) {
1619 pv
= &i
->sink_volume
;
1621 v
= i
->source_volume
;
1622 pv
= &i
->source_volume
;
1625 pv
->values
[0] = ((*(int*) argp
& 0xFF)*PA_VOLUME_NORM
)/100;
1626 pv
->values
[1] = ((*(int*) argp
>> 8)*PA_VOLUME_NORM
)/100;
1628 if (!pa_cvolume_equal(pv
, &v
)) {
1631 if (request
== SOUND_MIXER_WRITE_PCM
)
1632 o
= pa_context_set_sink_volume_by_index(i
->context
, i
->sink_index
, pv
, context_success_cb
, i
);
1634 o
= pa_context_set_source_volume_by_index(i
->context
, i
->source_index
, pv
, context_success_cb
, i
);
1637 debug(DEBUG_LEVEL_NORMAL
, __FILE__
":Failed set volume: %s", pa_strerror(pa_context_errno(i
->context
)));
1640 i
->operation_success
= 0;
1641 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1642 CONTEXT_CHECK_DEAD_GOTO(i
, exit_loop
);
1644 pa_threaded_mainloop_wait(i
->mainloop
);
1648 if (!i
->operation_success
)
1649 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1651 pa_operation_unref(o
);
1654 /* We don't wait for completion here */
1655 i
->volume_modify_count
++;
1658 pa_threaded_mainloop_unlock(i
->mainloop
);
1663 case SOUND_MIXER_INFO
: {
1664 mixer_info
*mi
= argp
;
1666 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_MIXER_INFO\n");
1668 memset(mi
, 0, sizeof(mixer_info
));
1669 strncpy(mi
->id
, "PULSEAUDIO", sizeof(mi
->id
));
1670 strncpy(mi
->name
, "PulseAudio Virtual OSS", sizeof(mi
->name
));
1671 pa_threaded_mainloop_lock(i
->mainloop
);
1672 mi
->modify_counter
= i
->volume_modify_count
;
1673 pa_threaded_mainloop_unlock(i
->mainloop
);
1678 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unknown ioctl 0x%08lx\n", request
);
1691 static int map_format(int *fmt
, pa_sample_spec
*ss
) {
1695 ss
->format
= PA_SAMPLE_ULAW
;
1699 ss
->format
= PA_SAMPLE_ALAW
;
1706 ss
->format
= PA_SAMPLE_U8
;
1713 ss
->format
= PA_SAMPLE_S16BE
;
1720 ss
->format
= PA_SAMPLE_S16LE
;
1724 ss
->format
= PA_SAMPLE_S16NE
;
1732 static int map_format_back(pa_sample_format_t format
) {
1734 case PA_SAMPLE_S16LE
: return AFMT_S16_LE
;
1735 case PA_SAMPLE_S16BE
: return AFMT_S16_BE
;
1736 case PA_SAMPLE_ULAW
: return AFMT_MU_LAW
;
1737 case PA_SAMPLE_ALAW
: return AFMT_A_LAW
;
1738 case PA_SAMPLE_U8
: return AFMT_U8
;
1744 static int dsp_flush_fd(int fd
) {
1748 if (ioctl(fd
, SIOCINQ
, &l
) < 0) {
1749 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1757 k
= (size_t) l
> sizeof(buf
) ? sizeof(buf
) : (size_t) l
;
1758 if (read(fd
, buf
, k
) < 0)
1759 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": read(): %s\n", strerror(errno
));
1765 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1770 static int dsp_flush_socket(fd_info
*i
) {
1773 if ((i
->thread_fd
< 0) && (i
->app_fd
< 0))
1776 if (i
->thread_fd
>= 0)
1777 res
= dsp_flush_fd(i
->thread_fd
);
1783 res
= dsp_flush_fd(i
->app_fd
);
1791 static int dsp_empty_socket(fd_info
*i
) {
1795 /* Empty the socket */
1799 if (i
->thread_fd
< 0)
1802 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
1803 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ: %s\n", strerror(errno
));
1812 pa_threaded_mainloop_wait(i
->mainloop
);
1817 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1822 static int dsp_drain(fd_info
*i
) {
1823 pa_operation
*o
= NULL
;
1829 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Draining.\n");
1831 pa_threaded_mainloop_lock(i
->mainloop
);
1833 if (dsp_empty_socket(i
) < 0)
1836 if (!i
->play_stream
)
1839 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Really draining.\n");
1841 if (!(o
= pa_stream_drain(i
->play_stream
, stream_success_cb
, i
))) {
1842 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1846 i
->operation_success
= 0;
1847 while (pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1848 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1850 pa_threaded_mainloop_wait(i
->mainloop
);
1853 if (!i
->operation_success
) {
1854 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i
->context
)));
1863 pa_operation_unref(o
);
1865 pa_threaded_mainloop_unlock(i
->mainloop
);
1870 static int dsp_trigger(fd_info
*i
) {
1871 pa_operation
*o
= NULL
;
1874 if (!i
->play_stream
)
1877 pa_threaded_mainloop_lock(i
->mainloop
);
1879 if (dsp_empty_socket(i
) < 0)
1882 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": Triggering.\n");
1884 if (!(o
= pa_stream_trigger(i
->play_stream
, stream_success_cb
, i
))) {
1885 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1889 i
->operation_success
= 0;
1890 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1891 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1893 pa_threaded_mainloop_wait(i
->mainloop
);
1896 if (!i
->operation_success
) {
1897 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1906 pa_operation_unref(o
);
1908 pa_threaded_mainloop_unlock(i
->mainloop
);
1913 static int dsp_cork(fd_info
*i
, pa_stream
*s
, int b
) {
1914 pa_operation
*o
= NULL
;
1917 pa_threaded_mainloop_lock(i
->mainloop
);
1919 if (!(o
= pa_stream_cork(s
, b
, stream_success_cb
, i
))) {
1920 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1924 i
->operation_success
= 0;
1925 while (!pa_operation_get_state(o
) != PA_OPERATION_DONE
) {
1926 if (s
== i
->play_stream
)
1927 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1928 else if (s
== i
->rec_stream
)
1929 RECORD_STREAM_CHECK_DEAD_GOTO(i
, fail
);
1931 pa_threaded_mainloop_wait(i
->mainloop
);
1934 if (!i
->operation_success
) {
1935 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
1944 pa_operation_unref(o
);
1946 pa_threaded_mainloop_unlock(i
->mainloop
);
1951 static int dsp_ioctl(fd_info
*i
, unsigned long request
, void*argp
, int *_errno
) {
1954 if (i
->thread_fd
== -1) {
1956 * We've encountered some fatal error and are just waiting
1959 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": got ioctl 0x%08lx in fatal error state\n", request
);
1965 case SNDCTL_DSP_SETFMT
: {
1966 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp
);
1968 pa_threaded_mainloop_lock(i
->mainloop
);
1970 if (*(int*) argp
== AFMT_QUERY
)
1971 *(int*) argp
= map_format_back(i
->sample_spec
.format
);
1973 map_format((int*) argp
, &i
->sample_spec
);
1977 pa_threaded_mainloop_unlock(i
->mainloop
);
1981 case SNDCTL_DSP_SPEED
: {
1986 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SPEED: %i\n", *(int*) argp
);
1988 pa_threaded_mainloop_lock(i
->mainloop
);
1990 ss
= i
->sample_spec
;
1991 ss
.rate
= *(int*) argp
;
1993 if ((valid
= pa_sample_spec_valid(&ss
))) {
1994 i
->sample_spec
= ss
;
1998 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ss: %s\n", pa_sample_spec_snprint(t
, sizeof(t
), &i
->sample_spec
));
2000 pa_threaded_mainloop_unlock(i
->mainloop
);
2010 case SNDCTL_DSP_STEREO
:
2011 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_STEREO: %i\n", *(int*) argp
);
2013 pa_threaded_mainloop_lock(i
->mainloop
);
2015 i
->sample_spec
.channels
= *(int*) argp
? 2 : 1;
2018 pa_threaded_mainloop_unlock(i
->mainloop
);
2021 case SNDCTL_DSP_CHANNELS
: {
2025 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp
);
2027 pa_threaded_mainloop_lock(i
->mainloop
);
2029 ss
= i
->sample_spec
;
2030 ss
.channels
= *(int*) argp
;
2032 if ((valid
= pa_sample_spec_valid(&ss
))) {
2033 i
->sample_spec
= ss
;
2037 pa_threaded_mainloop_unlock(i
->mainloop
);
2047 case SNDCTL_DSP_GETBLKSIZE
:
2048 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETBLKSIZE\n");
2050 pa_threaded_mainloop_lock(i
->mainloop
);
2053 *(int*) argp
= i
->fragment_size
;
2055 pa_threaded_mainloop_unlock(i
->mainloop
);
2059 case SNDCTL_DSP_SETFRAGMENT
:
2060 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp
);
2062 pa_threaded_mainloop_lock(i
->mainloop
);
2064 i
->fragment_size
= 1 << ((*(int*) argp
) & 31);
2065 i
->n_fragments
= (*(int*) argp
) >> 16;
2067 /* 0x7FFF means that we can set whatever we like */
2068 if (i
->n_fragments
== 0x7FFF)
2069 i
->n_fragments
= 12;
2073 pa_threaded_mainloop_unlock(i
->mainloop
);
2077 case SNDCTL_DSP_GETCAPS
:
2078 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_CAPS\n");
2080 *(int*) argp
= DSP_CAP_DUPLEX
| DSP_CAP_TRIGGER
2081 #ifdef DSP_CAP_MULTI
2087 case SNDCTL_DSP_GETODELAY
: {
2090 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETODELAY\n");
2092 pa_threaded_mainloop_lock(i
->mainloop
);
2099 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop
);
2101 if (pa_stream_get_latency(i
->play_stream
, &usec
, NULL
) >= 0) {
2102 *(int*) argp
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2106 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2107 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2111 pa_threaded_mainloop_wait(i
->mainloop
);
2117 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0)
2118 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2122 # warning "Your platform does not support SIOCINQ, something might not work as intended."
2125 pa_threaded_mainloop_unlock(i
->mainloop
);
2127 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": ODELAY: %i\n", *(int*) argp
);
2132 case SNDCTL_DSP_RESET
: {
2133 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_RESET\n");
2135 pa_threaded_mainloop_lock(i
->mainloop
);
2138 dsp_flush_socket(i
);
2140 i
->optr_n_blocks
= 0;
2142 pa_threaded_mainloop_unlock(i
->mainloop
);
2146 case SNDCTL_DSP_GETFMTS
: {
2147 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETFMTS\n");
2149 *(int*) argp
= AFMT_MU_LAW
|AFMT_A_LAW
|AFMT_U8
|AFMT_S16_LE
|AFMT_S16_BE
;
2153 case SNDCTL_DSP_POST
:
2154 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_POST\n");
2156 if (dsp_trigger(i
) < 0)
2160 case SNDCTL_DSP_GETTRIGGER
:
2161 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETTRIGGER\n");
2164 if (!i
->play_precork
)
2165 *(int*) argp
|= PCM_ENABLE_OUTPUT
;
2166 if (!i
->rec_precork
)
2167 *(int*) argp
|= PCM_ENABLE_INPUT
;
2171 case SNDCTL_DSP_SETTRIGGER
:
2172 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp
);
2179 i
->play_precork
= !((*(int*) argp
) & PCM_ENABLE_OUTPUT
);
2181 if (i
->play_stream
) {
2182 if (dsp_cork(i
, i
->play_stream
, !((*(int*) argp
) & PCM_ENABLE_OUTPUT
)) < 0)
2184 if (dsp_trigger(i
) < 0)
2188 i
->rec_precork
= !((*(int*) argp
) & PCM_ENABLE_INPUT
);
2190 if (i
->rec_stream
) {
2191 if (dsp_cork(i
, i
->rec_stream
, !((*(int*) argp
) & PCM_ENABLE_INPUT
)) < 0)
2197 case SNDCTL_DSP_SYNC
:
2198 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SYNC\n");
2200 if (dsp_drain(i
) < 0)
2205 case SNDCTL_DSP_GETOSPACE
:
2206 case SNDCTL_DSP_GETISPACE
: {
2207 audio_buf_info
*bi
= (audio_buf_info
*) argp
;
2211 if (request
== SNDCTL_DSP_GETOSPACE
)
2212 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOSPACE\n");
2214 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETISPACE\n");
2216 pa_threaded_mainloop_lock(i
->mainloop
);
2220 if (request
== SNDCTL_DSP_GETOSPACE
) {
2221 if (i
->play_stream
) {
2222 if ((k
= pa_stream_writable_size(i
->play_stream
)) == (size_t) -1)
2223 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2225 k
= i
->fragment_size
* i
->n_fragments
;
2228 if (ioctl(i
->thread_fd
, SIOCINQ
, &l
) < 0) {
2229 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2233 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2236 bi
->bytes
= k
> (size_t) l
? k
- l
: 0;
2238 if (i
->rec_stream
) {
2239 if ((k
= pa_stream_readable_size(i
->rec_stream
)) == (size_t) -1)
2240 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2245 if (ioctl(i
->app_fd
, SIOCINQ
, &l
) < 0) {
2246 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SIOCINQ failed: %s\n", strerror(errno
));
2250 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2255 bi
->fragsize
= i
->fragment_size
;
2256 bi
->fragstotal
= i
->n_fragments
;
2257 bi
->fragments
= bi
->bytes
/ bi
->fragsize
;
2259 pa_threaded_mainloop_unlock(i
->mainloop
);
2261 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi
->fragsize
, bi
->fragstotal
, bi
->bytes
, bi
->fragments
);
2266 case SOUND_PCM_READ_RATE
:
2267 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_RATE\n");
2269 pa_threaded_mainloop_lock(i
->mainloop
);
2270 *(int*) argp
= i
->sample_spec
.rate
;
2271 pa_threaded_mainloop_unlock(i
->mainloop
);
2274 case SOUND_PCM_READ_CHANNELS
:
2275 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_CHANNELS\n");
2277 pa_threaded_mainloop_lock(i
->mainloop
);
2278 *(int*) argp
= i
->sample_spec
.channels
;
2279 pa_threaded_mainloop_unlock(i
->mainloop
);
2282 case SOUND_PCM_READ_BITS
:
2283 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SOUND_PCM_READ_BITS\n");
2285 pa_threaded_mainloop_lock(i
->mainloop
);
2286 *(int*) argp
= pa_sample_size(&i
->sample_spec
)*8;
2287 pa_threaded_mainloop_unlock(i
->mainloop
);
2290 case SNDCTL_DSP_GETOPTR
: {
2293 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_GETOPTR\n");
2295 info
= (count_info
*) argp
;
2296 memset(info
, 0, sizeof(*info
));
2298 pa_threaded_mainloop_lock(i
->mainloop
);
2303 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i
, exit_loop2
);
2305 if (pa_stream_get_time(i
->play_stream
, &usec
) >= 0) {
2306 size_t k
= pa_usec_to_bytes(usec
, &i
->sample_spec
);
2309 info
->bytes
= (int) k
;
2310 m
= k
/ i
->fragment_size
;
2311 info
->blocks
= m
- i
->optr_n_blocks
;
2312 i
->optr_n_blocks
= m
;
2317 if (pa_context_errno(i
->context
) != PA_ERR_NODATA
) {
2318 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i
->context
)));
2322 pa_threaded_mainloop_wait(i
->mainloop
);
2327 pa_threaded_mainloop_unlock(i
->mainloop
);
2329 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info
->bytes
, info
->blocks
, info
->ptr
);
2334 case SNDCTL_DSP_GETIPTR
:
2335 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": invalid ioctl SNDCTL_DSP_GETIPTR\n");
2338 case SNDCTL_DSP_SETDUPLEX
:
2339 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": SNDCTL_DSP_SETDUPLEX\n");
2340 /* this is a no-op */
2344 /* Mixer ioctls are valid on /dev/dsp as well */
2345 return mixer_ioctl(i
, request
, argp
, _errno
);
2360 int ioctl(int fd
, int request
, ...) {
2362 int ioctl(int fd
, unsigned long request
, ...) {
2369 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": ioctl()\n");
2371 va_start(args
, request
);
2372 argp
= va_arg(args
, void *);
2375 if (!function_enter()) {
2377 return _ioctl(fd
, request
, argp
);
2380 if (!(i
= fd_info_find(fd
))) {
2383 return _ioctl(fd
, request
, argp
);
2386 if (i
->type
== FD_INFO_MIXER
)
2387 r
= mixer_ioctl(i
, request
, argp
, &_errno
);
2389 r
= dsp_ioctl(i
, request
, argp
, &_errno
);
2404 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": close()\n");
2406 if (!function_enter()) {
2411 if (!(i
= fd_info_find(fd
))) {
2417 fd_info_remove_from_list(i
);
2425 int access(const char *pathname
, int mode
) {
2427 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": access(%s)\n", pathname
?pathname
:"NULL");
2430 !is_audio_device_node(pathname
)) {
2432 return _access(pathname
, mode
);
2436 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = EACCESS\n", pathname
, mode
);
2441 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": access(%s, %x) = OK\n", pathname
, mode
);
2446 int stat(const char *pathname
, struct stat
*buf
) {
2448 struct stat64 parent
;
2456 !is_audio_device_node(pathname
)) {
2457 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat(%s)\n", pathname
?pathname
:"NULL");
2459 return _stat(pathname
, buf
);
2462 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": stat(%s)\n", pathname
);
2466 ret
= __xstat64(_STAT_VER
, "/dev", &parent
);
2468 ret
= __xstat(_STAT_VER
, "/dev", &parent
);
2472 ret
= stat64("/dev", &parent
);
2474 ret
= stat("/dev", &parent
);
2479 debug(DEBUG_LEVEL_NORMAL
, __FILE__
": unable to stat \"/dev\"\n");
2483 buf
->st_dev
= parent
.st_dev
;
2484 buf
->st_ino
= 0xDEADBEEF; /* FIXME: Can we do this in a safe way? */
2485 buf
->st_mode
= S_IFCHR
| S_IRUSR
| S_IWUSR
;
2487 buf
->st_uid
= getuid();
2488 buf
->st_gid
= getgid();
2489 buf
->st_rdev
= 0x0E03; /* FIXME: Linux specific */
2491 buf
->st_atime
= 1181557705;
2492 buf
->st_mtime
= 1181557705;
2493 buf
->st_ctime
= 1181557705;
2494 buf
->st_blksize
= 1;
2502 int stat64(const char *pathname
, struct stat64
*buf
) {
2506 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": stat64(%s)\n", pathname
?pathname
:"NULL");
2510 !is_audio_device_node(pathname
)) {
2512 return _stat64(pathname
, buf
);
2515 ret
= stat(pathname
, &oldbuf
);
2519 buf
->st_dev
= oldbuf
.st_dev
;
2520 buf
->st_ino
= oldbuf
.st_ino
;
2521 buf
->st_mode
= oldbuf
.st_mode
;
2522 buf
->st_nlink
= oldbuf
.st_nlink
;
2523 buf
->st_uid
= oldbuf
.st_uid
;
2524 buf
->st_gid
= oldbuf
.st_gid
;
2525 buf
->st_rdev
= oldbuf
.st_rdev
;
2526 buf
->st_size
= oldbuf
.st_size
;
2527 buf
->st_atime
= oldbuf
.st_atime
;
2528 buf
->st_mtime
= oldbuf
.st_mtime
;
2529 buf
->st_ctime
= oldbuf
.st_ctime
;
2530 buf
->st_blksize
= oldbuf
.st_blksize
;
2531 buf
->st_blocks
= oldbuf
.st_blocks
;
2536 int open64(const char *filename
, int flags
, ...) {
2540 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": open64(%s)\n", filename
?filename
:"NULL");
2542 if (flags
& O_CREAT
) {
2543 va_start(args
, flags
);
2544 if (sizeof(mode_t
) < sizeof(int))
2545 mode
= va_arg(args
, int);
2547 mode
= va_arg(args
, mode_t
);
2552 !is_audio_device_node(filename
)) {
2554 return _open64(filename
, flags
, mode
);
2557 return real_open(filename
, flags
, mode
);
2560 int __open64_2(const char *filename
, int flags
) {
2561 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __open64_2(%s)\n", filename
?filename
:"NULL");
2563 if ((flags
& O_CREAT
) ||
2565 !is_audio_device_node(filename
)) {
2566 LOAD___OPEN64_2_FUNC();
2567 return ___open64_2(filename
, flags
);
2570 return real_open(filename
, flags
, 0);
2577 int __xstat(int ver
, const char *pathname
, struct stat
*buf
) {
2578 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat(%s)\n", pathname
?pathname
:"NULL");
2582 !is_audio_device_node(pathname
)) {
2584 return ___xstat(ver
, pathname
, buf
);
2587 if (ver
!= _STAT_VER
) {
2592 return stat(pathname
, buf
);
2597 int __xstat64(int ver
, const char *pathname
, struct stat64
*buf
) {
2598 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": __xstat64(%s)\n", pathname
?pathname
:"NULL");
2602 !is_audio_device_node(pathname
)) {
2603 LOAD_XSTAT64_FUNC();
2604 return ___xstat64(ver
, pathname
, buf
);
2607 if (ver
!= _STAT_VER
) {
2612 return stat64(pathname
, buf
);
2619 FILE* fopen(const char *filename
, const char *mode
) {
2624 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen(%s)\n", filename
?filename
:"NULL");
2628 !is_audio_device_node(filename
)) {
2630 return _fopen(filename
, mode
);
2646 if ((((mode
[1] == 'b') || (mode
[1] == 't')) && (mode
[2] == '+')) || (mode
[1] == '+'))
2649 if ((fd
= real_open(filename
, m
, 0)) < 0)
2652 if (!(f
= fdopen(fd
, mode
))) {
2662 FILE *fopen64(const char *filename
, const char *mode
) {
2664 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fopen64(%s)\n", filename
?filename
:"NULL");
2668 !is_audio_device_node(filename
)) {
2669 LOAD_FOPEN64_FUNC();
2670 return _fopen64(filename
, mode
);
2673 return fopen(filename
, mode
);
2678 int fclose(FILE *f
) {
2681 debug(DEBUG_LEVEL_VERBOSE
, __FILE__
": fclose()\n");
2683 if (!function_enter()) {
2688 if (!(i
= fd_info_find(fileno(f
)))) {
2694 fd_info_remove_from_list(i
);
2696 /* Dirty trick to avoid that the fd is not freed twice, once by us
2697 * and once by the real fclose() */