]> code.delx.au - pulseaudio/blob - src/utils/padsp.c
Merge remote branch 'origin/master-tx'
[pulseaudio] / src / utils / padsp.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2006 Lennart Poettering
5 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #ifdef _FILE_OFFSET_BITS
28 #undef _FILE_OFFSET_BITS
29 #endif
30
31 #ifndef _LARGEFILE64_SOURCE
32 #define _LARGEFILE64_SOURCE 1
33 #endif
34
35 #include <sys/soundcard.h>
36 #include <sys/ioctl.h>
37 #include <pthread.h>
38 #include <unistd.h>
39 #include <sys/socket.h>
40 #include <sys/stat.h>
41 #include <dlfcn.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <string.h>
45 #include <stdarg.h>
46 #include <stdio.h>
47 #include <signal.h>
48
49 #ifdef __linux__
50 #include <linux/sockios.h>
51 #endif
52
53 #include <pulse/pulseaudio.h>
54 #include <pulse/gccmacro.h>
55 #include <pulsecore/llist.h>
56 #include <pulsecore/core-util.h>
57
58 /* On some systems SIOCINQ isn't defined, but FIONREAD is just an alias */
59 #if !defined(SIOCINQ) && defined(FIONREAD)
60 # define SIOCINQ FIONREAD
61 #endif
62
63 /* make sure gcc doesn't redefine open and friends as macros */
64 #undef open
65 #undef open64
66
67 typedef enum {
68 FD_INFO_MIXER,
69 FD_INFO_STREAM,
70 } fd_info_type_t;
71
72 typedef struct fd_info fd_info;
73
74 struct fd_info {
75 pthread_mutex_t mutex;
76 int ref;
77 int unusable;
78
79 fd_info_type_t type;
80 int app_fd, thread_fd;
81
82 pa_sample_spec sample_spec;
83 size_t fragment_size;
84 unsigned n_fragments;
85
86 pa_threaded_mainloop *mainloop;
87 pa_context *context;
88 pa_stream *play_stream;
89 pa_stream *rec_stream;
90 int play_precork;
91 int rec_precork;
92
93 pa_io_event *io_event;
94 pa_io_event_flags_t io_flags;
95
96 void *buf;
97 size_t rec_offset;
98
99 int operation_success;
100
101 pa_cvolume sink_volume, source_volume;
102 uint32_t sink_index, source_index;
103 int volume_modify_count;
104
105 int optr_n_blocks;
106
107 PA_LLIST_FIELDS(fd_info);
108 };
109
110 static int dsp_drain(fd_info *i);
111 static void fd_info_remove_from_list(fd_info *i);
112
113 static pthread_mutex_t fd_infos_mutex = PTHREAD_MUTEX_INITIALIZER;
114 static pthread_mutex_t func_mutex = PTHREAD_MUTEX_INITIALIZER;
115
116 static PA_LLIST_HEAD(fd_info, fd_infos) = NULL;
117
118 static int (*_ioctl)(int, int, void*) = NULL;
119 static int (*_close)(int) = NULL;
120 static int (*_open)(const char *, int, mode_t) = NULL;
121 static FILE* (*_fopen)(const char *path, const char *mode) = NULL;
122 static int (*_stat)(const char *, struct stat *) = NULL;
123 #ifdef _STAT_VER
124 static int (*___xstat)(int, const char *, struct stat *) = NULL;
125 #endif
126 #ifdef HAVE_OPEN64
127 static int (*_open64)(const char *, int, mode_t) = NULL;
128 static FILE* (*_fopen64)(const char *path, const char *mode) = NULL;
129 static int (*_stat64)(const char *, struct stat64 *) = NULL;
130 #ifdef _STAT_VER
131 static int (*___xstat64)(int, const char *, struct stat64 *) = NULL;
132 #endif
133 #endif
134 static int (*_fclose)(FILE *f) = NULL;
135 static int (*_access)(const char *, int) = NULL;
136
137 /* dlsym() violates ISO C, so confide the breakage into this function to
138 * avoid warnings. */
139 typedef void (*fnptr)(void);
140 static inline fnptr dlsym_fn(void *handle, const char *symbol) {
141 return (fnptr) (long) dlsym(handle, symbol);
142 }
143
144 #define LOAD_IOCTL_FUNC() \
145 do { \
146 pthread_mutex_lock(&func_mutex); \
147 if (!_ioctl) \
148 _ioctl = (int (*)(int, int, void*)) dlsym_fn(RTLD_NEXT, "ioctl"); \
149 pthread_mutex_unlock(&func_mutex); \
150 } while(0)
151
152 #define LOAD_OPEN_FUNC() \
153 do { \
154 pthread_mutex_lock(&func_mutex); \
155 if (!_open) \
156 _open = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open"); \
157 pthread_mutex_unlock(&func_mutex); \
158 } while(0)
159
160 #define LOAD_OPEN64_FUNC() \
161 do { \
162 pthread_mutex_lock(&func_mutex); \
163 if (!_open64) \
164 _open64 = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open64"); \
165 pthread_mutex_unlock(&func_mutex); \
166 } while(0)
167
168 #define LOAD_CLOSE_FUNC() \
169 do { \
170 pthread_mutex_lock(&func_mutex); \
171 if (!_close) \
172 _close = (int (*)(int)) dlsym_fn(RTLD_NEXT, "close"); \
173 pthread_mutex_unlock(&func_mutex); \
174 } while(0)
175
176 #define LOAD_ACCESS_FUNC() \
177 do { \
178 pthread_mutex_lock(&func_mutex); \
179 if (!_access) \
180 _access = (int (*)(const char*, int)) dlsym_fn(RTLD_NEXT, "access"); \
181 pthread_mutex_unlock(&func_mutex); \
182 } while(0)
183
184 #define LOAD_STAT_FUNC() \
185 do { \
186 pthread_mutex_lock(&func_mutex); \
187 if (!_stat) \
188 _stat = (int (*)(const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "stat"); \
189 pthread_mutex_unlock(&func_mutex); \
190 } while(0)
191
192 #define LOAD_STAT64_FUNC() \
193 do { \
194 pthread_mutex_lock(&func_mutex); \
195 if (!_stat64) \
196 _stat64 = (int (*)(const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "stat64"); \
197 pthread_mutex_unlock(&func_mutex); \
198 } while(0)
199
200 #define LOAD_XSTAT_FUNC() \
201 do { \
202 pthread_mutex_lock(&func_mutex); \
203 if (!___xstat) \
204 ___xstat = (int (*)(int, const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "__xstat"); \
205 pthread_mutex_unlock(&func_mutex); \
206 } while(0)
207
208 #define LOAD_XSTAT64_FUNC() \
209 do { \
210 pthread_mutex_lock(&func_mutex); \
211 if (!___xstat64) \
212 ___xstat64 = (int (*)(int, const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "__xstat64"); \
213 pthread_mutex_unlock(&func_mutex); \
214 } while(0)
215
216 #define LOAD_FOPEN_FUNC() \
217 do { \
218 pthread_mutex_lock(&func_mutex); \
219 if (!_fopen) \
220 _fopen = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen"); \
221 pthread_mutex_unlock(&func_mutex); \
222 } while(0)
223
224 #define LOAD_FOPEN64_FUNC() \
225 do { \
226 pthread_mutex_lock(&func_mutex); \
227 if (!_fopen64) \
228 _fopen64 = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen64"); \
229 pthread_mutex_unlock(&func_mutex); \
230 } while(0)
231
232 #define LOAD_FCLOSE_FUNC() \
233 do { \
234 pthread_mutex_lock(&func_mutex); \
235 if (!_fclose) \
236 _fclose = (int (*)(FILE *)) dlsym_fn(RTLD_NEXT, "fclose"); \
237 pthread_mutex_unlock(&func_mutex); \
238 } while(0)
239
240 #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \
241 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \
242 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
243 goto label; \
244 } \
245 } while(0)
246
247 #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \
248 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
249 !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \
250 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
251 goto label; \
252 } \
253 } while(0)
254
255 #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \
256 if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
257 !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \
258 debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \
259 goto label; \
260 } \
261 } while(0)
262
263 static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
264
265 #define DEBUG_LEVEL_ALWAYS 0
266 #define DEBUG_LEVEL_NORMAL 1
267 #define DEBUG_LEVEL_VERBOSE 2
268
269 static void debug(int level, const char *format, ...) {
270 va_list ap;
271 const char *dlevel_s;
272 int dlevel;
273
274 dlevel_s = getenv("PADSP_DEBUG");
275 if (!dlevel_s)
276 return;
277
278 dlevel = atoi(dlevel_s);
279
280 if (dlevel < level)
281 return;
282
283 va_start(ap, format);
284 vfprintf(stderr, format, ap);
285 va_end(ap);
286 }
287
288 static int padsp_disabled(void) {
289 static int *sym;
290 static int sym_resolved = 0;
291
292 /* If the current process has a symbol __padsp_disabled__ we use
293 * it to detect whether we should enable our stuff or not. A
294 * program needs to be compiled with -rdynamic for this to work!
295 * The symbol must be an int containing a three bit bitmask: bit 1
296 * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat
297 * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value
298 * of 7 disables padsp entirely. */
299
300 pthread_mutex_lock(&func_mutex);
301 if (!sym_resolved) {
302 sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__");
303 sym_resolved = 1;
304 }
305 pthread_mutex_unlock(&func_mutex);
306
307 if (!sym)
308 return 0;
309
310 return *sym;
311 }
312
313 static int dsp_cloak_enable(void) {
314 if (padsp_disabled() & 1)
315 return 0;
316
317 if (getenv("PADSP_NO_DSP") || getenv("PULSE_INTERNAL"))
318 return 0;
319
320 return 1;
321 }
322
323 static int sndstat_cloak_enable(void) {
324 if (padsp_disabled() & 2)
325 return 0;
326
327 if (getenv("PADSP_NO_SNDSTAT") || getenv("PULSE_INTERNAL"))
328 return 0;
329
330 return 1;
331 }
332
333 static int mixer_cloak_enable(void) {
334 if (padsp_disabled() & 4)
335 return 0;
336
337 if (getenv("PADSP_NO_MIXER") || getenv("PULSE_INTERNAL"))
338 return 0;
339
340 return 1;
341 }
342 static pthread_key_t recursion_key;
343
344 static void recursion_key_alloc(void) {
345 pthread_key_create(&recursion_key, NULL);
346 }
347
348 static int function_enter(void) {
349 /* Avoid recursive calls */
350 static pthread_once_t recursion_key_once = PTHREAD_ONCE_INIT;
351 pthread_once(&recursion_key_once, recursion_key_alloc);
352
353 if (pthread_getspecific(recursion_key))
354 return 0;
355
356 pthread_setspecific(recursion_key, (void*) 1);
357 return 1;
358 }
359
360 static void function_exit(void) {
361 pthread_setspecific(recursion_key, NULL);
362 }
363
364 static void fd_info_free(fd_info *i) {
365 assert(i);
366
367 debug(DEBUG_LEVEL_NORMAL, __FILE__": freeing fd info (fd=%i)\n", i->app_fd);
368
369 dsp_drain(i);
370
371 if (i->mainloop)
372 pa_threaded_mainloop_stop(i->mainloop);
373
374 if (i->play_stream) {
375 pa_stream_disconnect(i->play_stream);
376 pa_stream_unref(i->play_stream);
377 }
378
379 if (i->rec_stream) {
380 pa_stream_disconnect(i->rec_stream);
381 pa_stream_unref(i->rec_stream);
382 }
383
384 if (i->context) {
385 pa_context_disconnect(i->context);
386 pa_context_unref(i->context);
387 }
388
389 if (i->mainloop)
390 pa_threaded_mainloop_free(i->mainloop);
391
392 if (i->app_fd >= 0) {
393 LOAD_CLOSE_FUNC();
394 _close(i->app_fd);
395 }
396
397 if (i->thread_fd >= 0) {
398 LOAD_CLOSE_FUNC();
399 _close(i->thread_fd);
400 }
401
402 free(i->buf);
403
404 pthread_mutex_destroy(&i->mutex);
405 free(i);
406 }
407
408 static fd_info *fd_info_ref(fd_info *i) {
409 assert(i);
410
411 pthread_mutex_lock(&i->mutex);
412 assert(i->ref >= 1);
413 i->ref++;
414
415 debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref++, now %i\n", i->ref);
416 pthread_mutex_unlock(&i->mutex);
417
418 return i;
419 }
420
421 static void fd_info_unref(fd_info *i) {
422 int r;
423 pthread_mutex_lock(&i->mutex);
424 assert(i->ref >= 1);
425 r = --i->ref;
426 debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref);
427 pthread_mutex_unlock(&i->mutex);
428
429 if (r <= 0)
430 fd_info_free(i);
431 }
432
433 static void context_state_cb(pa_context *c, void *userdata) {
434 fd_info *i = userdata;
435 assert(c);
436
437 switch (pa_context_get_state(c)) {
438 case PA_CONTEXT_READY:
439 case PA_CONTEXT_TERMINATED:
440 case PA_CONTEXT_FAILED:
441 pa_threaded_mainloop_signal(i->mainloop, 0);
442 break;
443
444 case PA_CONTEXT_UNCONNECTED:
445 case PA_CONTEXT_CONNECTING:
446 case PA_CONTEXT_AUTHORIZING:
447 case PA_CONTEXT_SETTING_NAME:
448 break;
449 }
450 }
451
452 static void reset_params(fd_info *i) {
453 assert(i);
454
455 i->sample_spec.format = PA_SAMPLE_U8;
456 i->sample_spec.channels = 1;
457 i->sample_spec.rate = 8000;
458 i->fragment_size = 0;
459 i->n_fragments = 0;
460 }
461
462 static const char *client_name(char *buf, size_t n) {
463 char *p;
464 const char *e;
465
466 if ((e = getenv("PADSP_CLIENT_NAME")))
467 return e;
468
469 if ((p = pa_get_binary_name_malloc())) {
470 snprintf(buf, n, "OSS Emulation[%s]", p);
471 pa_xfree(p);
472 } else
473 snprintf(buf, n, "OSS");
474
475 return buf;
476 }
477
478 static const char *stream_name(void) {
479 const char *e;
480
481 if ((e = getenv("PADSP_STREAM_NAME")))
482 return e;
483
484 return "Audio Stream";
485 }
486
487 static void atfork_prepare(void) {
488 fd_info *i;
489
490 debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() enter\n");
491
492 function_enter();
493
494 pthread_mutex_lock(&fd_infos_mutex);
495
496 for (i = fd_infos; i; i = i->next) {
497 pthread_mutex_lock(&i->mutex);
498 pa_threaded_mainloop_lock(i->mainloop);
499 }
500
501 pthread_mutex_lock(&func_mutex);
502
503 debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n");
504 }
505
506 static void atfork_parent(void) {
507 fd_info *i;
508
509 debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() enter\n");
510
511 pthread_mutex_unlock(&func_mutex);
512
513 for (i = fd_infos; i; i = i->next) {
514 pa_threaded_mainloop_unlock(i->mainloop);
515 pthread_mutex_unlock(&i->mutex);
516 }
517
518 pthread_mutex_unlock(&fd_infos_mutex);
519
520 function_exit();
521
522 debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() exit\n");
523 }
524
525 static void atfork_child(void) {
526 fd_info *i;
527
528 debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() enter\n");
529
530 /* We do only the bare minimum to get all fds closed */
531 pthread_mutex_init(&func_mutex, NULL);
532 pthread_mutex_init(&fd_infos_mutex, NULL);
533
534 for (i = fd_infos; i; i = i->next) {
535 pthread_mutex_init(&i->mutex, NULL);
536
537 if (i->context) {
538 pa_context_disconnect(i->context);
539 pa_context_unref(i->context);
540 i->context = NULL;
541 }
542
543 if (i->play_stream) {
544 pa_stream_unref(i->play_stream);
545 i->play_stream = NULL;
546 }
547
548 if (i->rec_stream) {
549 pa_stream_unref(i->rec_stream);
550 i->rec_stream = NULL;
551 }
552
553 if (i->app_fd >= 0) {
554 LOAD_CLOSE_FUNC();
555 _close(i->app_fd);
556 i->app_fd = -1;
557 }
558
559 if (i->thread_fd >= 0) {
560 LOAD_CLOSE_FUNC();
561 _close(i->thread_fd);
562 i->thread_fd = -1;
563 }
564
565 i->unusable = 1;
566 }
567
568 function_exit();
569
570 debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() exit\n");
571 }
572
573 static void install_atfork(void) {
574 pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
575 }
576
577 static void stream_success_cb(pa_stream *s, int success, void *userdata) {
578 fd_info *i = userdata;
579
580 assert(s);
581 assert(i);
582
583 i->operation_success = success;
584 pa_threaded_mainloop_signal(i->mainloop, 0);
585 }
586
587 static void context_success_cb(pa_context *c, int success, void *userdata) {
588 fd_info *i = userdata;
589
590 assert(c);
591 assert(i);
592
593 i->operation_success = success;
594 pa_threaded_mainloop_signal(i->mainloop, 0);
595 }
596
597 static fd_info* fd_info_new(fd_info_type_t type, int *_errno) {
598 fd_info *i;
599 int sfds[2] = { -1, -1 };
600 char name[64];
601 static pthread_once_t install_atfork_once = PTHREAD_ONCE_INIT;
602
603 debug(DEBUG_LEVEL_NORMAL, __FILE__": fd_info_new()\n");
604
605 signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */
606
607 pthread_once(&install_atfork_once, install_atfork);
608
609 if (!(i = malloc(sizeof(fd_info)))) {
610 *_errno = ENOMEM;
611 goto fail;
612 }
613
614 i->app_fd = i->thread_fd = -1;
615 i->type = type;
616
617 i->mainloop = NULL;
618 i->context = NULL;
619 i->play_stream = NULL;
620 i->rec_stream = NULL;
621 i->play_precork = 0;
622 i->rec_precork = 0;
623 i->io_event = NULL;
624 i->io_flags = 0;
625 pthread_mutex_init(&i->mutex, NULL);
626 i->ref = 1;
627 i->buf = NULL;
628 i->rec_offset = 0;
629 i->unusable = 0;
630 pa_cvolume_reset(&i->sink_volume, 2);
631 pa_cvolume_reset(&i->source_volume, 2);
632 i->volume_modify_count = 0;
633 i->sink_index = (uint32_t) -1;
634 i->source_index = (uint32_t) -1;
635 i->optr_n_blocks = 0;
636 PA_LLIST_INIT(fd_info, i);
637
638 reset_params(i);
639
640 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfds) < 0) {
641 *_errno = errno;
642 debug(DEBUG_LEVEL_NORMAL, __FILE__": socket() failed: %s\n", strerror(errno));
643 goto fail;
644 }
645
646 i->app_fd = sfds[0];
647 i->thread_fd = sfds[1];
648
649 if (!(i->mainloop = pa_threaded_mainloop_new())) {
650 *_errno = EIO;
651 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_new() failed\n");
652 goto fail;
653 }
654
655 if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), client_name(name, sizeof(name))))) {
656 *_errno = EIO;
657 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_new() failed\n");
658 goto fail;
659 }
660
661 pa_context_set_state_callback(i->context, context_state_cb, i);
662
663 if (pa_context_connect(i->context, NULL, 0, NULL) < 0) {
664 *_errno = ECONNREFUSED;
665 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
666 goto fail;
667 }
668
669 pa_threaded_mainloop_lock(i->mainloop);
670
671 if (pa_threaded_mainloop_start(i->mainloop) < 0) {
672 *_errno = EIO;
673 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_start() failed\n");
674 goto unlock_and_fail;
675 }
676
677 /* Wait until the context is ready */
678 pa_threaded_mainloop_wait(i->mainloop);
679
680 if (pa_context_get_state(i->context) != PA_CONTEXT_READY) {
681 *_errno = ECONNREFUSED;
682 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
683 goto unlock_and_fail;
684 }
685
686 pa_threaded_mainloop_unlock(i->mainloop);
687 return i;
688
689 unlock_and_fail:
690
691 pa_threaded_mainloop_unlock(i->mainloop);
692
693 fail:
694
695 if (i)
696 fd_info_unref(i);
697
698 return NULL;
699 }
700
701 static void fd_info_add_to_list(fd_info *i) {
702 assert(i);
703
704 pthread_mutex_lock(&fd_infos_mutex);
705 PA_LLIST_PREPEND(fd_info, fd_infos, i);
706 pthread_mutex_unlock(&fd_infos_mutex);
707
708 fd_info_ref(i);
709 }
710
711 static void fd_info_remove_from_list(fd_info *i) {
712 assert(i);
713
714 pthread_mutex_lock(&fd_infos_mutex);
715 PA_LLIST_REMOVE(fd_info, fd_infos, i);
716 pthread_mutex_unlock(&fd_infos_mutex);
717
718 fd_info_unref(i);
719 }
720
721 static fd_info* fd_info_find(int fd) {
722 fd_info *i;
723
724 pthread_mutex_lock(&fd_infos_mutex);
725
726 for (i = fd_infos; i; i = i->next)
727 if (i->app_fd == fd && !i->unusable) {
728 fd_info_ref(i);
729 break;
730 }
731
732 pthread_mutex_unlock(&fd_infos_mutex);
733
734 return i;
735 }
736
737 static void fix_metrics(fd_info *i) {
738 size_t fs;
739 char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
740
741 fs = pa_frame_size(&i->sample_spec);
742
743 /* Don't fix things more than necessary */
744 if ((i->fragment_size % fs) == 0 &&
745 i->n_fragments >= 2 &&
746 i->fragment_size > 0)
747 return;
748
749 i->fragment_size = (i->fragment_size/fs)*fs;
750
751 /* Number of fragments set? */
752 if (i->n_fragments < 2) {
753 if (i->fragment_size > 0) {
754 i->n_fragments = (unsigned) (pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size);
755 if (i->n_fragments < 2)
756 i->n_fragments = 2;
757 } else
758 i->n_fragments = 12;
759 }
760
761 /* Fragment size set? */
762 if (i->fragment_size <= 0) {
763 i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments;
764 if (i->fragment_size < 1024)
765 i->fragment_size = 1024;
766 }
767
768 debug(DEBUG_LEVEL_NORMAL, __FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec));
769 debug(DEBUG_LEVEL_NORMAL, __FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size);
770 }
771
772 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
773 fd_info *i = userdata;
774 assert(s);
775
776 if (i->io_event) {
777 pa_mainloop_api *api;
778 size_t n;
779
780 api = pa_threaded_mainloop_get_api(i->mainloop);
781
782 if (s == i->play_stream) {
783 n = pa_stream_writable_size(i->play_stream);
784 if (n == (size_t)-1) {
785 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n",
786 pa_strerror(pa_context_errno(i->context)));
787 }
788
789 if (n >= i->fragment_size)
790 i->io_flags |= PA_IO_EVENT_INPUT;
791 else
792 i->io_flags &= ~PA_IO_EVENT_INPUT;
793 }
794
795 if (s == i->rec_stream) {
796 n = pa_stream_readable_size(i->rec_stream);
797 if (n == (size_t)-1) {
798 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n",
799 pa_strerror(pa_context_errno(i->context)));
800 }
801
802 if (n >= i->fragment_size)
803 i->io_flags |= PA_IO_EVENT_OUTPUT;
804 else
805 i->io_flags &= ~PA_IO_EVENT_OUTPUT;
806 }
807
808 api->io_enable(i->io_event, i->io_flags);
809 }
810 }
811
812 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
813 fd_info *i = userdata;
814 assert(s);
815
816 pa_threaded_mainloop_signal(i->mainloop, 0);
817 }
818
819 static void fd_info_shutdown(fd_info *i) {
820 assert(i);
821
822 if (i->io_event) {
823 pa_mainloop_api *api;
824 api = pa_threaded_mainloop_get_api(i->mainloop);
825 api->io_free(i->io_event);
826 i->io_event = NULL;
827 i->io_flags = 0;
828 }
829
830 if (i->thread_fd >= 0) {
831 close(i->thread_fd);
832 i->thread_fd = -1;
833 }
834 }
835
836 static int fd_info_copy_data(fd_info *i, int force) {
837 size_t n;
838
839 if (!i->play_stream && !i->rec_stream)
840 return -1;
841
842 if ((i->play_stream) && (pa_stream_get_state(i->play_stream) == PA_STREAM_READY)) {
843 n = pa_stream_writable_size(i->play_stream);
844
845 if (n == (size_t)-1) {
846 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n",
847 pa_strerror(pa_context_errno(i->context)));
848 return -1;
849 }
850
851 while (n >= i->fragment_size || force) {
852 ssize_t r;
853
854 if (!i->buf) {
855 if (!(i->buf = malloc(i->fragment_size))) {
856 debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n");
857 return -1;
858 }
859 }
860
861 if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) {
862
863 if (errno == EAGAIN)
864 break;
865
866 debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno));
867 return -1;
868 }
869
870 if (pa_stream_write(i->play_stream, i->buf, (size_t) r, free, 0LL, PA_SEEK_RELATIVE) < 0) {
871 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context)));
872 return -1;
873 }
874
875 i->buf = NULL;
876
877 assert(n >= (size_t) r);
878 n -= (size_t) r;
879 }
880
881 if (n >= i->fragment_size)
882 i->io_flags |= PA_IO_EVENT_INPUT;
883 else
884 i->io_flags &= ~PA_IO_EVENT_INPUT;
885 }
886
887 if ((i->rec_stream) && (pa_stream_get_state(i->rec_stream) == PA_STREAM_READY)) {
888 n = pa_stream_readable_size(i->rec_stream);
889
890 if (n == (size_t)-1) {
891 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n",
892 pa_strerror(pa_context_errno(i->context)));
893 return -1;
894 }
895
896 while (n >= i->fragment_size || force) {
897 ssize_t r;
898 const void *data;
899 const char *buf;
900 size_t len;
901
902 if (pa_stream_peek(i->rec_stream, &data, &len) < 0) {
903 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_peek(): %s\n", pa_strerror(pa_context_errno(i->context)));
904 return -1;
905 }
906
907 if (!data)
908 break;
909
910 buf = (const char*)data + i->rec_offset;
911
912 if ((r = write(i->thread_fd, buf, len - i->rec_offset)) <= 0) {
913
914 if (errno == EAGAIN)
915 break;
916
917 debug(DEBUG_LEVEL_NORMAL, __FILE__": write(): %s\n", strerror(errno));
918 return -1;
919 }
920
921 assert((size_t)r <= len - i->rec_offset);
922 i->rec_offset += (size_t) r;
923
924 if (i->rec_offset == len) {
925 if (pa_stream_drop(i->rec_stream) < 0) {
926 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i->context)));
927 return -1;
928 }
929 i->rec_offset = 0;
930 }
931
932 assert(n >= (size_t) r);
933 n -= (size_t) r;
934 }
935
936 if (n >= i->fragment_size)
937 i->io_flags |= PA_IO_EVENT_OUTPUT;
938 else
939 i->io_flags &= ~PA_IO_EVENT_OUTPUT;
940 }
941
942 if (i->io_event) {
943 pa_mainloop_api *api;
944
945 api = pa_threaded_mainloop_get_api(i->mainloop);
946 api->io_enable(i->io_event, i->io_flags);
947 }
948
949 /* So, we emptied the socket now, let's tell dsp_empty_socket()
950 * about this */
951 pa_threaded_mainloop_signal(i->mainloop, 0);
952
953 return 0;
954 }
955
956 static void stream_state_cb(pa_stream *s, void * userdata) {
957 fd_info *i = userdata;
958 assert(s);
959
960 switch (pa_stream_get_state(s)) {
961
962 case PA_STREAM_READY:
963 debug(DEBUG_LEVEL_NORMAL, __FILE__": stream established.\n");
964 break;
965
966 case PA_STREAM_FAILED:
967 if (s == i->play_stream) {
968 debug(DEBUG_LEVEL_NORMAL,
969 __FILE__": pa_stream_connect_playback() failed: %s\n",
970 pa_strerror(pa_context_errno(i->context)));
971 pa_stream_unref(i->play_stream);
972 i->play_stream = NULL;
973 } else if (s == i->rec_stream) {
974 debug(DEBUG_LEVEL_NORMAL,
975 __FILE__": pa_stream_connect_record() failed: %s\n",
976 pa_strerror(pa_context_errno(i->context)));
977 pa_stream_unref(i->rec_stream);
978 i->rec_stream = NULL;
979 }
980 fd_info_shutdown(i);
981 break;
982
983 case PA_STREAM_TERMINATED:
984 case PA_STREAM_UNCONNECTED:
985 case PA_STREAM_CREATING:
986 break;
987 }
988 }
989
990 static int create_playback_stream(fd_info *i) {
991 pa_buffer_attr attr;
992 int n, flags;
993
994 assert(i);
995
996 fix_metrics(i);
997
998 if (!(i->play_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) {
999 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
1000 goto fail;
1001 }
1002
1003 pa_stream_set_state_callback(i->play_stream, stream_state_cb, i);
1004 pa_stream_set_write_callback(i->play_stream, stream_request_cb, i);
1005 pa_stream_set_latency_update_callback(i->play_stream, stream_latency_update_cb, i);
1006
1007 memset(&attr, 0, sizeof(attr));
1008 attr.maxlength = (uint32_t) (i->fragment_size * (i->n_fragments+1));
1009 attr.tlength = (uint32_t) (i->fragment_size * i->n_fragments);
1010 attr.prebuf = (uint32_t) i->fragment_size;
1011 attr.minreq = (uint32_t) i->fragment_size;
1012
1013 flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_EARLY_REQUESTS;
1014 if (i->play_precork) {
1015 flags |= PA_STREAM_START_CORKED;
1016 debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n");
1017 }
1018 if (pa_stream_connect_playback(i->play_stream, NULL, &attr, flags, NULL, NULL) < 0) {
1019 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
1020 goto fail;
1021 }
1022
1023 n = (int) i->fragment_size;
1024 setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
1025 n = (int) i->fragment_size;
1026 setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
1027
1028 return 0;
1029
1030 fail:
1031 return -1;
1032 }
1033
1034 static int create_record_stream(fd_info *i) {
1035 pa_buffer_attr attr;
1036 int n, flags;
1037
1038 assert(i);
1039
1040 fix_metrics(i);
1041
1042 if (!(i->rec_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) {
1043 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
1044 goto fail;
1045 }
1046
1047 pa_stream_set_state_callback(i->rec_stream, stream_state_cb, i);
1048 pa_stream_set_read_callback(i->rec_stream, stream_request_cb, i);
1049 pa_stream_set_latency_update_callback(i->rec_stream, stream_latency_update_cb, i);
1050
1051 memset(&attr, 0, sizeof(attr));
1052 attr.maxlength = (uint32_t) (i->fragment_size * (i->n_fragments+1));
1053 attr.fragsize = (uint32_t) i->fragment_size;
1054
1055 flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE;
1056 if (i->rec_precork) {
1057 flags |= PA_STREAM_START_CORKED;
1058 debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n");
1059 }
1060 if (pa_stream_connect_record(i->rec_stream, NULL, &attr, flags) < 0) {
1061 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
1062 goto fail;
1063 }
1064
1065 n = (int) i->fragment_size;
1066 setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
1067 n = (int) i->fragment_size;
1068 setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
1069
1070 return 0;
1071
1072 fail:
1073 return -1;
1074 }
1075
1076 static void free_streams(fd_info *i) {
1077 assert(i);
1078
1079 if (i->play_stream) {
1080 pa_stream_disconnect(i->play_stream);
1081 pa_stream_unref(i->play_stream);
1082 i->play_stream = NULL;
1083 i->io_flags |= PA_IO_EVENT_INPUT;
1084 }
1085
1086 if (i->rec_stream) {
1087 pa_stream_disconnect(i->rec_stream);
1088 pa_stream_unref(i->rec_stream);
1089 i->rec_stream = NULL;
1090 i->io_flags |= PA_IO_EVENT_OUTPUT;
1091 }
1092
1093 if (i->io_event) {
1094 pa_mainloop_api *api;
1095
1096 api = pa_threaded_mainloop_get_api(i->mainloop);
1097 api->io_enable(i->io_event, i->io_flags);
1098 }
1099 }
1100
1101 static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
1102 fd_info *i = userdata;
1103
1104 pa_threaded_mainloop_signal(i->mainloop, 0);
1105
1106 if (flags & PA_IO_EVENT_INPUT) {
1107
1108 if (!i->play_stream) {
1109 if (create_playback_stream(i) < 0)
1110 goto fail;
1111 } else {
1112 if (fd_info_copy_data(i, 0) < 0)
1113 goto fail;
1114 }
1115
1116 } else if (flags & PA_IO_EVENT_OUTPUT) {
1117
1118 if (!i->rec_stream) {
1119 if (create_record_stream(i) < 0)
1120 goto fail;
1121 } else {
1122 if (fd_info_copy_data(i, 0) < 0)
1123 goto fail;
1124 }
1125
1126 } else if (flags & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR))
1127 goto fail;
1128
1129 return;
1130
1131 fail:
1132 /* We can't do anything better than removing the event source */
1133 fd_info_shutdown(i);
1134 }
1135
1136 static int dsp_open(int flags, int *_errno) {
1137 fd_info *i;
1138 pa_mainloop_api *api;
1139 int ret;
1140 int f;
1141
1142 debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n");
1143
1144 if (!(i = fd_info_new(FD_INFO_STREAM, _errno)))
1145 return -1;
1146
1147 if ((flags & O_NONBLOCK) == O_NONBLOCK) {
1148 if ((f = fcntl(i->app_fd, F_GETFL)) >= 0)
1149 fcntl(i->app_fd, F_SETFL, f|O_NONBLOCK);
1150 }
1151 if ((f = fcntl(i->thread_fd, F_GETFL)) >= 0)
1152 fcntl(i->thread_fd, F_SETFL, f|O_NONBLOCK);
1153
1154 fcntl(i->app_fd, F_SETFD, FD_CLOEXEC);
1155 fcntl(i->thread_fd, F_SETFD, FD_CLOEXEC);
1156
1157 pa_threaded_mainloop_lock(i->mainloop);
1158 api = pa_threaded_mainloop_get_api(i->mainloop);
1159
1160 switch (flags & O_ACCMODE) {
1161 case O_RDONLY:
1162 i->io_flags = PA_IO_EVENT_OUTPUT;
1163 shutdown(i->thread_fd, SHUT_RD);
1164 shutdown(i->app_fd, SHUT_WR);
1165 break;
1166 case O_WRONLY:
1167 i->io_flags = PA_IO_EVENT_INPUT;
1168 shutdown(i->thread_fd, SHUT_WR);
1169 shutdown(i->app_fd, SHUT_RD);
1170 break;
1171 case O_RDWR:
1172 i->io_flags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT;
1173 break;
1174 default:
1175 return -1;
1176 }
1177
1178 if (!(i->io_event = api->io_new(api, i->thread_fd, i->io_flags, io_event_cb, i)))
1179 goto fail;
1180
1181 pa_threaded_mainloop_unlock(i->mainloop);
1182
1183 debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd);
1184
1185 fd_info_add_to_list(i);
1186 ret = i->app_fd;
1187 fd_info_unref(i);
1188
1189 return ret;
1190
1191 fail:
1192 pa_threaded_mainloop_unlock(i->mainloop);
1193
1194 if (i)
1195 fd_info_unref(i);
1196
1197 *_errno = EIO;
1198
1199 debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() failed\n");
1200
1201 return -1;
1202 }
1203
1204 static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, void *userdata) {
1205 fd_info *i = userdata;
1206
1207 if (!si || eol < 0) {
1208 i->operation_success = 0;
1209 pa_threaded_mainloop_signal(i->mainloop, 0);
1210 return;
1211 }
1212
1213 if (eol)
1214 return;
1215
1216 if (!pa_cvolume_equal(&i->sink_volume, &si->volume))
1217 i->volume_modify_count++;
1218
1219 i->sink_volume = si->volume;
1220 i->sink_index = si->index;
1221
1222 i->operation_success = 1;
1223 pa_threaded_mainloop_signal(i->mainloop, 0);
1224 }
1225
1226 static void source_info_cb(pa_context *context, const pa_source_info *si, int eol, void *userdata) {
1227 fd_info *i = userdata;
1228
1229 if (!si || eol < 0) {
1230 i->operation_success = 0;
1231 pa_threaded_mainloop_signal(i->mainloop, 0);
1232 return;
1233 }
1234
1235 if (eol)
1236 return;
1237
1238 if (!pa_cvolume_equal(&i->source_volume, &si->volume))
1239 i->volume_modify_count++;
1240
1241 i->source_volume = si->volume;
1242 i->source_index = si->index;
1243
1244 i->operation_success = 1;
1245 pa_threaded_mainloop_signal(i->mainloop, 0);
1246 }
1247
1248 static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1249 fd_info *i = userdata;
1250 pa_operation *o = NULL;
1251
1252 if (i->sink_index != idx)
1253 return;
1254
1255 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
1256 return;
1257
1258 if (!(o = pa_context_get_sink_info_by_index(i->context, i->sink_index, sink_info_cb, i))) {
1259 debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context)));
1260 return;
1261 }
1262
1263 pa_operation_unref(o);
1264 }
1265
1266 static int mixer_open(int flags, int *_errno) {
1267 fd_info *i;
1268 pa_operation *o = NULL;
1269 int ret;
1270
1271 debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n");
1272
1273 if (!(i = fd_info_new(FD_INFO_MIXER, _errno)))
1274 return -1;
1275
1276 pa_threaded_mainloop_lock(i->mainloop);
1277
1278 pa_context_set_subscribe_callback(i->context, subscribe_cb, i);
1279
1280 if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, context_success_cb, i))) {
1281 debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context)));
1282 *_errno = EIO;
1283 goto fail;
1284 }
1285
1286 i->operation_success = 0;
1287 while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1288 pa_threaded_mainloop_wait(i->mainloop);
1289 CONTEXT_CHECK_DEAD_GOTO(i, fail);
1290 }
1291
1292 pa_operation_unref(o);
1293 o = NULL;
1294
1295 if (!i->operation_success) {
1296 debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context)));
1297 *_errno = EIO;
1298 goto fail;
1299 }
1300
1301 /* Get sink info */
1302
1303 if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) {
1304 debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context)));
1305 *_errno = EIO;
1306 goto fail;
1307 }
1308
1309 i->operation_success = 0;
1310 while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1311 pa_threaded_mainloop_wait(i->mainloop);
1312 CONTEXT_CHECK_DEAD_GOTO(i, fail);
1313 }
1314
1315 pa_operation_unref(o);
1316 o = NULL;
1317
1318 if (!i->operation_success) {
1319 debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context)));
1320 *_errno = EIO;
1321 goto fail;
1322 }
1323
1324 /* Get source info */
1325
1326 if (!(o = pa_context_get_source_info_by_name(i->context, NULL, source_info_cb, i))) {
1327 debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context)));
1328 *_errno = EIO;
1329 goto fail;
1330 }
1331
1332 i->operation_success = 0;
1333 while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1334 pa_threaded_mainloop_wait(i->mainloop);
1335 CONTEXT_CHECK_DEAD_GOTO(i, fail);
1336 }
1337
1338 pa_operation_unref(o);
1339 o = NULL;
1340
1341 if (!i->operation_success) {
1342 debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context)));
1343 *_errno = EIO;
1344 goto fail;
1345 }
1346
1347 pa_threaded_mainloop_unlock(i->mainloop);
1348
1349 debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd);
1350
1351 fd_info_add_to_list(i);
1352 ret = i->app_fd;
1353 fd_info_unref(i);
1354
1355 return ret;
1356
1357 fail:
1358 if (o)
1359 pa_operation_unref(o);
1360
1361 pa_threaded_mainloop_unlock(i->mainloop);
1362
1363 if (i)
1364 fd_info_unref(i);
1365
1366 *_errno = EIO;
1367
1368 debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() failed\n");
1369
1370 return -1;
1371 }
1372
1373 static int sndstat_open(int flags, int *_errno) {
1374 static const char sndstat[] =
1375 "Sound Driver:3.8.1a-980706 (PulseAudio Virtual OSS)\n"
1376 "Kernel: POSIX\n"
1377 "Config options: 0\n"
1378 "\n"
1379 "Installed drivers:\n"
1380 "Type 255: PulseAudio Virtual OSS\n"
1381 "\n"
1382 "Card config:\n"
1383 "PulseAudio Virtual OSS\n"
1384 "\n"
1385 "Audio devices:\n"
1386 "0: PulseAudio Virtual OSS\n"
1387 "\n"
1388 "Synth devices: NOT ENABLED IN CONFIG\n"
1389 "\n"
1390 "Midi devices:\n"
1391 "\n"
1392 "Timers:\n"
1393 "\n"
1394 "Mixers:\n"
1395 "0: PulseAudio Virtual OSS\n";
1396
1397 char fn[] = "/tmp/padsp-sndstat-XXXXXX";
1398 mode_t u;
1399 int fd = -1;
1400 int e;
1401
1402 debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n");
1403
1404 if (flags != O_RDONLY
1405 #ifdef O_LARGEFILE
1406 && flags != (O_RDONLY|O_LARGEFILE)
1407 #endif
1408 ) {
1409 *_errno = EACCES;
1410 debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access!\n");
1411 goto fail;
1412 }
1413
1414 u = umask(0077);
1415 fd = mkstemp(fn);
1416 e = errno;
1417 umask(u);
1418
1419 if (fd < 0) {
1420 *_errno = e;
1421 debug(DEBUG_LEVEL_NORMAL, __FILE__": mkstemp() failed: %s\n", strerror(errno));
1422 goto fail;
1423 }
1424
1425 unlink(fn);
1426
1427 if (write(fd, sndstat, sizeof(sndstat) -1) != sizeof(sndstat)-1) {
1428 *_errno = errno;
1429 debug(DEBUG_LEVEL_NORMAL, __FILE__": write() failed: %s\n", strerror(errno));
1430 goto fail;
1431 }
1432
1433 if (lseek(fd, SEEK_SET, 0) < 0) {
1434 *_errno = errno;
1435 debug(DEBUG_LEVEL_NORMAL, __FILE__": lseek() failed: %s\n", strerror(errno));
1436 goto fail;
1437 }
1438
1439 return fd;
1440
1441 fail:
1442 if (fd >= 0)
1443 close(fd);
1444 return -1;
1445 }
1446
1447 static int real_open(const char *filename, int flags, mode_t mode) {
1448 int r, _errno = 0;
1449
1450 debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename?filename:"NULL");
1451
1452 if (!function_enter()) {
1453 LOAD_OPEN_FUNC();
1454 return _open(filename, flags, mode);
1455 }
1456
1457 if (filename && dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0))
1458 r = dsp_open(flags, &_errno);
1459 else if (filename && mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0)
1460 r = mixer_open(flags, &_errno);
1461 else if (filename && sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0)
1462 r = sndstat_open(flags, &_errno);
1463 else {
1464 function_exit();
1465 LOAD_OPEN_FUNC();
1466 return _open(filename, flags, mode);
1467 }
1468
1469 function_exit();
1470
1471 if (_errno)
1472 errno = _errno;
1473
1474 return r;
1475 }
1476
1477 int open(const char *filename, int flags, ...) {
1478 va_list args;
1479 mode_t mode = 0;
1480
1481 if (flags & O_CREAT) {
1482 va_start(args, flags);
1483 if (sizeof(mode_t) < sizeof(int))
1484 mode = (mode_t) va_arg(args, int);
1485 else
1486 mode = va_arg(args, mode_t);
1487 va_end(args);
1488 }
1489
1490 return real_open(filename, flags, mode);
1491 }
1492
1493 static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
1494 int ret = -1;
1495
1496 switch (request) {
1497 case SOUND_MIXER_READ_DEVMASK :
1498 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n");
1499
1500 *(int*) argp = SOUND_MASK_PCM | SOUND_MASK_IGAIN;
1501 break;
1502
1503 case SOUND_MIXER_READ_RECMASK :
1504 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECMASK\n");
1505
1506 *(int*) argp = SOUND_MASK_IGAIN;
1507 break;
1508
1509 case SOUND_MIXER_READ_STEREODEVS:
1510 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n");
1511
1512 pa_threaded_mainloop_lock(i->mainloop);
1513 *(int*) argp = 0;
1514 if (i->sink_volume.channels > 1)
1515 *(int*) argp |= SOUND_MASK_PCM;
1516 if (i->source_volume.channels > 1)
1517 *(int*) argp |= SOUND_MASK_IGAIN;
1518 pa_threaded_mainloop_unlock(i->mainloop);
1519
1520 break;
1521
1522 case SOUND_MIXER_READ_RECSRC:
1523 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECSRC\n");
1524
1525 *(int*) argp = SOUND_MASK_IGAIN;
1526 break;
1527
1528 case SOUND_MIXER_WRITE_RECSRC:
1529 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_RECSRC\n");
1530 break;
1531
1532 case SOUND_MIXER_READ_CAPS:
1533 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_CAPS\n");
1534
1535 *(int*) argp = 0;
1536 break;
1537
1538 case SOUND_MIXER_READ_PCM:
1539 case SOUND_MIXER_READ_IGAIN: {
1540 pa_cvolume *v;
1541
1542 if (request == SOUND_MIXER_READ_PCM)
1543 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n");
1544 else
1545 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_IGAIN\n");
1546
1547 pa_threaded_mainloop_lock(i->mainloop);
1548
1549 if (request == SOUND_MIXER_READ_PCM)
1550 v = &i->sink_volume;
1551 else
1552 v = &i->source_volume;
1553
1554 *(int*) argp =
1555 ((v->values[0]*100/PA_VOLUME_NORM)) |
1556 ((v->values[v->channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM) << 8);
1557
1558 pa_threaded_mainloop_unlock(i->mainloop);
1559
1560 break;
1561 }
1562
1563 case SOUND_MIXER_WRITE_PCM:
1564 case SOUND_MIXER_WRITE_IGAIN: {
1565 pa_cvolume v, *pv;
1566
1567 if (request == SOUND_MIXER_WRITE_PCM)
1568 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n");
1569 else
1570 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_IGAIN\n");
1571
1572 pa_threaded_mainloop_lock(i->mainloop);
1573
1574 if (request == SOUND_MIXER_WRITE_PCM) {
1575 v = i->sink_volume;
1576 pv = &i->sink_volume;
1577 } else {
1578 v = i->source_volume;
1579 pv = &i->source_volume;
1580 }
1581
1582 pv->values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100;
1583 pv->values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100;
1584
1585 if (!pa_cvolume_equal(pv, &v)) {
1586 pa_operation *o;
1587
1588 if (request == SOUND_MIXER_WRITE_PCM)
1589 o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, context_success_cb, i);
1590 else
1591 o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, context_success_cb, i);
1592
1593 if (!o)
1594 debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context)));
1595 else {
1596
1597 i->operation_success = 0;
1598 while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1599 CONTEXT_CHECK_DEAD_GOTO(i, exit_loop);
1600
1601 pa_threaded_mainloop_wait(i->mainloop);
1602 }
1603 exit_loop:
1604
1605 if (!i->operation_success)
1606 debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context)));
1607
1608 pa_operation_unref(o);
1609 }
1610
1611 /* We don't wait for completion here */
1612 i->volume_modify_count++;
1613 }
1614
1615 pa_threaded_mainloop_unlock(i->mainloop);
1616
1617 break;
1618 }
1619
1620 case SOUND_MIXER_INFO: {
1621 mixer_info *mi = argp;
1622
1623 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_INFO\n");
1624
1625 memset(mi, 0, sizeof(mixer_info));
1626 strncpy(mi->id, "PULSEAUDIO", sizeof(mi->id));
1627 strncpy(mi->name, "PulseAudio Virtual OSS", sizeof(mi->name));
1628 pa_threaded_mainloop_lock(i->mainloop);
1629 mi->modify_counter = i->volume_modify_count;
1630 pa_threaded_mainloop_unlock(i->mainloop);
1631 break;
1632 }
1633
1634 default:
1635 debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);
1636
1637 *_errno = EINVAL;
1638 goto fail;
1639 }
1640
1641 ret = 0;
1642
1643 fail:
1644
1645 return ret;
1646 }
1647
1648 static int map_format(int *fmt, pa_sample_spec *ss) {
1649
1650 switch (*fmt) {
1651 case AFMT_MU_LAW:
1652 ss->format = PA_SAMPLE_ULAW;
1653 break;
1654
1655 case AFMT_A_LAW:
1656 ss->format = PA_SAMPLE_ALAW;
1657 break;
1658
1659 case AFMT_S8:
1660 *fmt = AFMT_U8;
1661 /* fall through */
1662 case AFMT_U8:
1663 ss->format = PA_SAMPLE_U8;
1664 break;
1665
1666 case AFMT_U16_BE:
1667 *fmt = AFMT_S16_BE;
1668 /* fall through */
1669 case AFMT_S16_BE:
1670 ss->format = PA_SAMPLE_S16BE;
1671 break;
1672
1673 case AFMT_U16_LE:
1674 *fmt = AFMT_S16_LE;
1675 /* fall through */
1676 case AFMT_S16_LE:
1677 ss->format = PA_SAMPLE_S16LE;
1678 break;
1679
1680 default:
1681 ss->format = PA_SAMPLE_S16NE;
1682 *fmt = AFMT_S16_NE;
1683 break;
1684 }
1685
1686 return 0;
1687 }
1688
1689 static int map_format_back(pa_sample_format_t format) {
1690 switch (format) {
1691 case PA_SAMPLE_S16LE: return AFMT_S16_LE;
1692 case PA_SAMPLE_S16BE: return AFMT_S16_BE;
1693 case PA_SAMPLE_ULAW: return AFMT_MU_LAW;
1694 case PA_SAMPLE_ALAW: return AFMT_A_LAW;
1695 case PA_SAMPLE_U8: return AFMT_U8;
1696 default:
1697 abort();
1698 }
1699 }
1700
1701 static int dsp_flush_fd(int fd) {
1702 #ifdef SIOCINQ
1703 int l;
1704
1705 if (ioctl(fd, SIOCINQ, &l) < 0) {
1706 debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno));
1707 return -1;
1708 }
1709
1710 while (l > 0) {
1711 char buf[1024];
1712 size_t k;
1713
1714 k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l;
1715 if (read(fd, buf, k) < 0)
1716 debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", strerror(errno));
1717 l -= k;
1718 }
1719
1720 return 0;
1721 #else
1722 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1723 return 0;
1724 #endif
1725 }
1726
1727 static int dsp_flush_socket(fd_info *i) {
1728 int res = 0;
1729
1730 if ((i->thread_fd < 0) && (i->app_fd < 0))
1731 return -1;
1732
1733 if (i->thread_fd >= 0)
1734 res = dsp_flush_fd(i->thread_fd);
1735
1736 if (res < 0)
1737 return res;
1738
1739 if (i->app_fd >= 0)
1740 res = dsp_flush_fd(i->app_fd);
1741
1742 if (res < 0)
1743 return res;
1744
1745 return 0;
1746 }
1747
1748 static int dsp_empty_socket(fd_info *i) {
1749 #ifdef SIOCINQ
1750 int ret = -1;
1751
1752 /* Empty the socket */
1753 for (;;) {
1754 int l;
1755
1756 if (i->thread_fd < 0)
1757 break;
1758
1759 if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) {
1760 debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno));
1761 break;
1762 }
1763
1764 if (!l) {
1765 ret = 0;
1766 break;
1767 }
1768
1769 pa_threaded_mainloop_wait(i->mainloop);
1770 }
1771
1772 return ret;
1773 #else
1774 # warning "Your platform does not support SIOCINQ, something might not work as intended."
1775 return 0;
1776 #endif
1777 }
1778
1779 static int dsp_drain(fd_info *i) {
1780 pa_operation *o = NULL;
1781 int r = -1;
1782
1783 if (!i->mainloop)
1784 return 0;
1785
1786 debug(DEBUG_LEVEL_NORMAL, __FILE__": Draining.\n");
1787
1788 pa_threaded_mainloop_lock(i->mainloop);
1789
1790 if (dsp_empty_socket(i) < 0)
1791 goto fail;
1792
1793 if (!i->play_stream)
1794 goto fail;
1795
1796 debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n");
1797
1798 if (!(o = pa_stream_drain(i->play_stream, stream_success_cb, i))) {
1799 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context)));
1800 goto fail;
1801 }
1802
1803 i->operation_success = 0;
1804 while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
1805 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail);
1806
1807 pa_threaded_mainloop_wait(i->mainloop);
1808 }
1809
1810 if (!i->operation_success) {
1811 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context)));
1812 goto fail;
1813 }
1814
1815 r = 0;
1816
1817 fail:
1818
1819 if (o)
1820 pa_operation_unref(o);
1821
1822 pa_threaded_mainloop_unlock(i->mainloop);
1823
1824 return r;
1825 }
1826
1827 static int dsp_trigger(fd_info *i) {
1828 pa_operation *o = NULL;
1829 int r = -1;
1830
1831 if (!i->play_stream)
1832 return 0;
1833
1834 pa_threaded_mainloop_lock(i->mainloop);
1835
1836 if (dsp_empty_socket(i) < 0)
1837 goto fail;
1838
1839 debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n");
1840
1841 if (!(o = pa_stream_trigger(i->play_stream, stream_success_cb, i))) {
1842 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context)));
1843 goto fail;
1844 }
1845
1846 i->operation_success = 0;
1847 while (!pa_operation_get_state(o) != PA_OPERATION_DONE) {
1848 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail);
1849
1850 pa_threaded_mainloop_wait(i->mainloop);
1851 }
1852
1853 if (!i->operation_success) {
1854 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context)));
1855 goto fail;
1856 }
1857
1858 r = 0;
1859
1860 fail:
1861
1862 if (o)
1863 pa_operation_unref(o);
1864
1865 pa_threaded_mainloop_unlock(i->mainloop);
1866
1867 return r;
1868 }
1869
1870 static int dsp_cork(fd_info *i, pa_stream *s, int b) {
1871 pa_operation *o = NULL;
1872 int r = -1;
1873
1874 pa_threaded_mainloop_lock(i->mainloop);
1875
1876 if (!(o = pa_stream_cork(s, b, stream_success_cb, i))) {
1877 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i->context)));
1878 goto fail;
1879 }
1880
1881 i->operation_success = 0;
1882 while (!pa_operation_get_state(o) != PA_OPERATION_DONE) {
1883 if (s == i->play_stream)
1884 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail);
1885 else if (s == i->rec_stream)
1886 RECORD_STREAM_CHECK_DEAD_GOTO(i, fail);
1887
1888 pa_threaded_mainloop_wait(i->mainloop);
1889 }
1890
1891 if (!i->operation_success) {
1892 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i->context)));
1893 goto fail;
1894 }
1895
1896 r = 0;
1897
1898 fail:
1899
1900 if (o)
1901 pa_operation_unref(o);
1902
1903 pa_threaded_mainloop_unlock(i->mainloop);
1904
1905 return r;
1906 }
1907
1908 static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
1909 int ret = -1;
1910
1911 if (i->thread_fd == -1) {
1912 /*
1913 * We've encountered some fatal error and are just waiting
1914 * for a close.
1915 */
1916 debug(DEBUG_LEVEL_NORMAL, __FILE__": got ioctl 0x%08lx in fatal error state\n", request);
1917 *_errno = EIO;
1918 return -1;
1919 }
1920
1921 switch (request) {
1922 case SNDCTL_DSP_SETFMT: {
1923 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp);
1924
1925 pa_threaded_mainloop_lock(i->mainloop);
1926
1927 if (*(int*) argp == AFMT_QUERY)
1928 *(int*) argp = map_format_back(i->sample_spec.format);
1929 else {
1930 map_format((int*) argp, &i->sample_spec);
1931 free_streams(i);
1932 }
1933
1934 pa_threaded_mainloop_unlock(i->mainloop);
1935 break;
1936 }
1937
1938 case SNDCTL_DSP_SPEED: {
1939 pa_sample_spec ss;
1940 int valid;
1941 char t[256];
1942
1943 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp);
1944
1945 pa_threaded_mainloop_lock(i->mainloop);
1946
1947 ss = i->sample_spec;
1948 ss.rate = *(int*) argp;
1949
1950 if ((valid = pa_sample_spec_valid(&ss))) {
1951 i->sample_spec = ss;
1952 free_streams(i);
1953 }
1954
1955 debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec));
1956
1957 pa_threaded_mainloop_unlock(i->mainloop);
1958
1959 if (!valid) {
1960 *_errno = EINVAL;
1961 goto fail;
1962 }
1963
1964 break;
1965 }
1966
1967 case SNDCTL_DSP_STEREO:
1968 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp);
1969
1970 pa_threaded_mainloop_lock(i->mainloop);
1971
1972 i->sample_spec.channels = *(int*) argp ? 2 : 1;
1973 free_streams(i);
1974
1975 pa_threaded_mainloop_unlock(i->mainloop);
1976 return 0;
1977
1978 case SNDCTL_DSP_CHANNELS: {
1979 pa_sample_spec ss;
1980 int valid;
1981
1982 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp);
1983
1984 pa_threaded_mainloop_lock(i->mainloop);
1985
1986 ss = i->sample_spec;
1987 ss.channels = *(int*) argp;
1988
1989 if ((valid = pa_sample_spec_valid(&ss))) {
1990 i->sample_spec = ss;
1991 free_streams(i);
1992 }
1993
1994 pa_threaded_mainloop_unlock(i->mainloop);
1995
1996 if (!valid) {
1997 *_errno = EINVAL;
1998 goto fail;
1999 }
2000
2001 break;
2002 }
2003
2004 case SNDCTL_DSP_GETBLKSIZE:
2005 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETBLKSIZE\n");
2006
2007 pa_threaded_mainloop_lock(i->mainloop);
2008
2009 fix_metrics(i);
2010 *(int*) argp = i->fragment_size;
2011
2012 pa_threaded_mainloop_unlock(i->mainloop);
2013
2014 break;
2015
2016 case SNDCTL_DSP_SETFRAGMENT:
2017 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp);
2018
2019 pa_threaded_mainloop_lock(i->mainloop);
2020
2021 i->fragment_size = 1 << ((*(int*) argp) & 31);
2022 i->n_fragments = (*(int*) argp) >> 16;
2023
2024 /* 0x7FFF means that we can set whatever we like */
2025 if (i->n_fragments == 0x7FFF)
2026 i->n_fragments = 12;
2027
2028 free_streams(i);
2029
2030 pa_threaded_mainloop_unlock(i->mainloop);
2031
2032 break;
2033
2034 case SNDCTL_DSP_GETCAPS:
2035 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n");
2036
2037 *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER
2038 #ifdef DSP_CAP_MULTI
2039 | DSP_CAP_MULTI
2040 #endif
2041 ;
2042 break;
2043
2044 case SNDCTL_DSP_GETODELAY: {
2045 int l;
2046
2047 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n");
2048
2049 pa_threaded_mainloop_lock(i->mainloop);
2050
2051 *(int*) argp = 0;
2052
2053 for (;;) {
2054 pa_usec_t usec;
2055
2056 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop);
2057
2058 if (pa_stream_get_latency(i->play_stream, &usec, NULL) >= 0) {
2059 *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec);
2060 break;
2061 }
2062
2063 if (pa_context_errno(i->context) != PA_ERR_NODATA) {
2064 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context)));
2065 break;
2066 }
2067
2068 pa_threaded_mainloop_wait(i->mainloop);
2069 }
2070
2071 exit_loop:
2072
2073 #ifdef SIOCINQ
2074 if (ioctl(i->thread_fd, SIOCINQ, &l) < 0)
2075 debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno));
2076 else
2077 *(int*) argp += l;
2078 #else
2079 # warning "Your platform does not support SIOCINQ, something might not work as intended."
2080 #endif
2081
2082 pa_threaded_mainloop_unlock(i->mainloop);
2083
2084 debug(DEBUG_LEVEL_NORMAL, __FILE__": ODELAY: %i\n", *(int*) argp);
2085
2086 break;
2087 }
2088
2089 case SNDCTL_DSP_RESET: {
2090 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_RESET\n");
2091
2092 pa_threaded_mainloop_lock(i->mainloop);
2093
2094 free_streams(i);
2095 dsp_flush_socket(i);
2096
2097 i->optr_n_blocks = 0;
2098
2099 pa_threaded_mainloop_unlock(i->mainloop);
2100 break;
2101 }
2102
2103 case SNDCTL_DSP_GETFMTS: {
2104 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETFMTS\n");
2105
2106 *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE;
2107 break;
2108 }
2109
2110 case SNDCTL_DSP_POST:
2111 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_POST\n");
2112
2113 if (dsp_trigger(i) < 0)
2114 *_errno = EIO;
2115 break;
2116
2117 case SNDCTL_DSP_GETTRIGGER:
2118 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETTRIGGER\n");
2119
2120 *(int*) argp = 0;
2121 if (!i->play_precork)
2122 *(int*) argp |= PCM_ENABLE_OUTPUT;
2123 if (!i->rec_precork)
2124 *(int*) argp |= PCM_ENABLE_INPUT;
2125
2126 break;
2127
2128 case SNDCTL_DSP_SETTRIGGER:
2129 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp);
2130
2131 if (!i->io_event) {
2132 *_errno = EIO;
2133 break;
2134 }
2135
2136 i->play_precork = !((*(int*) argp) & PCM_ENABLE_OUTPUT);
2137
2138 if (i->play_stream) {
2139 if (dsp_cork(i, i->play_stream, !((*(int*) argp) & PCM_ENABLE_OUTPUT)) < 0)
2140 *_errno = EIO;
2141 if (dsp_trigger(i) < 0)
2142 *_errno = EIO;
2143 }
2144
2145 i->rec_precork = !((*(int*) argp) & PCM_ENABLE_INPUT);
2146
2147 if (i->rec_stream) {
2148 if (dsp_cork(i, i->rec_stream, !((*(int*) argp) & PCM_ENABLE_INPUT)) < 0)
2149 *_errno = EIO;
2150 }
2151
2152 break;
2153
2154 case SNDCTL_DSP_SYNC:
2155 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n");
2156
2157 if (dsp_drain(i) < 0)
2158 *_errno = EIO;
2159
2160 break;
2161
2162 case SNDCTL_DSP_GETOSPACE:
2163 case SNDCTL_DSP_GETISPACE: {
2164 audio_buf_info *bi = (audio_buf_info*) argp;
2165 int l = 0;
2166 size_t k = 0;
2167
2168 if (request == SNDCTL_DSP_GETOSPACE)
2169 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n");
2170 else
2171 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETISPACE\n");
2172
2173 pa_threaded_mainloop_lock(i->mainloop);
2174
2175 fix_metrics(i);
2176
2177 if (request == SNDCTL_DSP_GETOSPACE) {
2178 if (i->play_stream) {
2179 if ((k = pa_stream_writable_size(i->play_stream)) == (size_t) -1)
2180 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context)));
2181 } else
2182 k = i->fragment_size * i->n_fragments;
2183
2184 #ifdef SIOCINQ
2185 if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) {
2186 debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno));
2187 l = 0;
2188 }
2189 #else
2190 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2191 #endif
2192
2193 bi->bytes = k > (size_t) l ? k - l : 0;
2194 } else {
2195 if (i->rec_stream) {
2196 if ((k = pa_stream_readable_size(i->rec_stream)) == (size_t) -1)
2197 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i->context)));
2198 } else
2199 k = 0;
2200
2201 #ifdef SIOCINQ
2202 if (ioctl(i->app_fd, SIOCINQ, &l) < 0) {
2203 debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno));
2204 l = 0;
2205 }
2206 #else
2207 # warning "Your platform does not dsp_flush_fd, something might not work as intended."
2208 #endif
2209 bi->bytes = k + l;
2210 }
2211
2212 bi->fragsize = i->fragment_size;
2213 bi->fragstotal = i->n_fragments;
2214 bi->fragments = bi->bytes / bi->fragsize;
2215
2216 pa_threaded_mainloop_unlock(i->mainloop);
2217
2218 debug(DEBUG_LEVEL_NORMAL, __FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments);
2219
2220 break;
2221 }
2222
2223 case SOUND_PCM_READ_RATE:
2224 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_RATE\n");
2225
2226 pa_threaded_mainloop_lock(i->mainloop);
2227 *(int*) argp = i->sample_spec.rate;
2228 pa_threaded_mainloop_unlock(i->mainloop);
2229 break;
2230
2231 case SOUND_PCM_READ_CHANNELS:
2232 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_CHANNELS\n");
2233
2234 pa_threaded_mainloop_lock(i->mainloop);
2235 *(int*) argp = i->sample_spec.channels;
2236 pa_threaded_mainloop_unlock(i->mainloop);
2237 break;
2238
2239 case SOUND_PCM_READ_BITS:
2240 debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_BITS\n");
2241
2242 pa_threaded_mainloop_lock(i->mainloop);
2243 *(int*) argp = pa_sample_size(&i->sample_spec)*8;
2244 pa_threaded_mainloop_unlock(i->mainloop);
2245 break;
2246
2247 case SNDCTL_DSP_GETOPTR: {
2248 count_info *info;
2249
2250 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOPTR\n");
2251
2252 info = (count_info*) argp;
2253 memset(info, 0, sizeof(*info));
2254
2255 pa_threaded_mainloop_lock(i->mainloop);
2256
2257 for (;;) {
2258 pa_usec_t usec;
2259
2260 PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop2);
2261
2262 if (pa_stream_get_time(i->play_stream, &usec) >= 0) {
2263 size_t k = pa_usec_to_bytes(usec, &i->sample_spec);
2264 int m;
2265
2266 info->bytes = (int) k;
2267 m = k / i->fragment_size;
2268 info->blocks = m - i->optr_n_blocks;
2269 i->optr_n_blocks = m;
2270
2271 break;
2272 }
2273
2274 if (pa_context_errno(i->context) != PA_ERR_NODATA) {
2275 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context)));
2276 break;
2277 }
2278
2279 pa_threaded_mainloop_wait(i->mainloop);
2280 }
2281
2282 exit_loop2:
2283
2284 pa_threaded_mainloop_unlock(i->mainloop);
2285
2286 debug(DEBUG_LEVEL_NORMAL, __FILE__": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info->bytes, info->blocks, info->ptr);
2287
2288 break;
2289 }
2290
2291 case SNDCTL_DSP_GETIPTR:
2292 debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n");
2293 goto inval;
2294
2295 case SNDCTL_DSP_SETDUPLEX:
2296 debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n");
2297 /* this is a no-op */
2298 break;
2299
2300 default:
2301 /* Mixer ioctls are valid on /dev/dsp aswell */
2302 return mixer_ioctl(i, request, argp, _errno);
2303
2304 inval:
2305 *_errno = EINVAL;
2306 goto fail;
2307 }
2308
2309 ret = 0;
2310
2311 fail:
2312
2313 return ret;
2314 }
2315
2316 #ifdef sun
2317 int ioctl(int fd, int request, ...) {
2318 #else
2319 int ioctl(int fd, unsigned long request, ...) {
2320 #endif
2321 fd_info *i;
2322 va_list args;
2323 void *argp;
2324 int r, _errno = 0;
2325
2326 debug(DEBUG_LEVEL_VERBOSE, __FILE__": ioctl()\n");
2327
2328 va_start(args, request);
2329 argp = va_arg(args, void *);
2330 va_end(args);
2331
2332 if (!function_enter()) {
2333 LOAD_IOCTL_FUNC();
2334 return _ioctl(fd, request, argp);
2335 }
2336
2337 if (!(i = fd_info_find(fd))) {
2338 function_exit();
2339 LOAD_IOCTL_FUNC();
2340 return _ioctl(fd, request, argp);
2341 }
2342
2343 if (i->type == FD_INFO_MIXER)
2344 r = mixer_ioctl(i, request, argp, &_errno);
2345 else
2346 r = dsp_ioctl(i, request, argp, &_errno);
2347
2348 fd_info_unref(i);
2349
2350 if (_errno)
2351 errno = _errno;
2352
2353 function_exit();
2354
2355 return r;
2356 }
2357
2358 int close(int fd) {
2359 fd_info *i;
2360
2361 debug(DEBUG_LEVEL_VERBOSE, __FILE__": close()\n");
2362
2363 if (!function_enter()) {
2364 LOAD_CLOSE_FUNC();
2365 return _close(fd);
2366 }
2367
2368 if (!(i = fd_info_find(fd))) {
2369 function_exit();
2370 LOAD_CLOSE_FUNC();
2371 return _close(fd);
2372 }
2373
2374 fd_info_remove_from_list(i);
2375 fd_info_unref(i);
2376
2377 function_exit();
2378
2379 return 0;
2380 }
2381
2382 int access(const char *pathname, int mode) {
2383
2384 debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname?pathname:"NULL");
2385
2386 if (!pathname ||
2387 (strcmp(pathname, "/dev/dsp") != 0 &&
2388 strcmp(pathname, "/dev/adsp") != 0 &&
2389 strcmp(pathname, "/dev/sndstat") != 0 &&
2390 strcmp(pathname, "/dev/mixer") != 0 )) {
2391 LOAD_ACCESS_FUNC();
2392 return _access(pathname, mode);
2393 }
2394
2395 if (mode & X_OK) {
2396 debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = EACCESS\n", pathname, mode);
2397 errno = EACCES;
2398 return -1;
2399 }
2400
2401 debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = OK\n", pathname, mode);
2402
2403 return 0;
2404 }
2405
2406 int stat(const char *pathname, struct stat *buf) {
2407 #ifdef HAVE_OPEN64
2408 struct stat64 parent;
2409 #else
2410 struct stat parent;
2411 #endif
2412 int ret;
2413
2414 if (!pathname ||
2415 !buf ||
2416 ( strcmp(pathname, "/dev/dsp") != 0 &&
2417 strcmp(pathname, "/dev/adsp") != 0 &&
2418 strcmp(pathname, "/dev/sndstat") != 0 &&
2419 strcmp(pathname, "/dev/mixer") != 0 )) {
2420 debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname?pathname:"NULL");
2421 LOAD_STAT_FUNC();
2422 return _stat(pathname, buf);
2423 }
2424
2425 debug(DEBUG_LEVEL_NORMAL, __FILE__": stat(%s)\n", pathname);
2426
2427 #ifdef _STAT_VER
2428 #ifdef HAVE_OPEN64
2429 ret = __xstat64(_STAT_VER, "/dev", &parent);
2430 #else
2431 ret = __xstat(_STAT_VER, "/dev", &parent);
2432 #endif
2433 #else
2434 #ifdef HAVE_OPEN64
2435 ret = stat64("/dev", &parent);
2436 #else
2437 ret = stat("/dev", &parent);
2438 #endif
2439 #endif
2440
2441 if (ret) {
2442 debug(DEBUG_LEVEL_NORMAL, __FILE__": unable to stat \"/dev\"\n");
2443 return -1;
2444 }
2445
2446 buf->st_dev = parent.st_dev;
2447 buf->st_ino = 0xDEADBEEF; /* FIXME: Can we do this in a safe way? */
2448 buf->st_mode = S_IFCHR | S_IRUSR | S_IWUSR;
2449 buf->st_nlink = 1;
2450 buf->st_uid = getuid();
2451 buf->st_gid = getgid();
2452 buf->st_rdev = 0x0E03; /* FIXME: Linux specific */
2453 buf->st_size = 0;
2454 buf->st_atime = 1181557705;
2455 buf->st_mtime = 1181557705;
2456 buf->st_ctime = 1181557705;
2457 buf->st_blksize = 1;
2458 buf->st_blocks = 0;
2459
2460 return 0;
2461 }
2462
2463 #ifdef HAVE_OPEN64
2464
2465 int stat64(const char *pathname, struct stat64 *buf) {
2466 struct stat oldbuf;
2467 int ret;
2468
2469 debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname?pathname:"NULL");
2470
2471 if (!pathname ||
2472 !buf ||
2473 ( strcmp(pathname, "/dev/dsp") != 0 &&
2474 strcmp(pathname, "/dev/adsp") != 0 &&
2475 strcmp(pathname, "/dev/sndstat") != 0 &&
2476 strcmp(pathname, "/dev/mixer") != 0 )) {
2477 LOAD_STAT64_FUNC();
2478 return _stat64(pathname, buf);
2479 }
2480
2481 ret = stat(pathname, &oldbuf);
2482 if (ret)
2483 return ret;
2484
2485 buf->st_dev = oldbuf.st_dev;
2486 buf->st_ino = oldbuf.st_ino;
2487 buf->st_mode = oldbuf.st_mode;
2488 buf->st_nlink = oldbuf.st_nlink;
2489 buf->st_uid = oldbuf.st_uid;
2490 buf->st_gid = oldbuf.st_gid;
2491 buf->st_rdev = oldbuf.st_rdev;
2492 buf->st_size = oldbuf.st_size;
2493 buf->st_atime = oldbuf.st_atime;
2494 buf->st_mtime = oldbuf.st_mtime;
2495 buf->st_ctime = oldbuf.st_ctime;
2496 buf->st_blksize = oldbuf.st_blksize;
2497 buf->st_blocks = oldbuf.st_blocks;
2498
2499 return 0;
2500 }
2501
2502 int open64(const char *filename, int flags, ...) {
2503 va_list args;
2504 mode_t mode = 0;
2505
2506 debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename?filename:"NULL");
2507
2508 if (flags & O_CREAT) {
2509 va_start(args, flags);
2510 if (sizeof(mode_t) < sizeof(int))
2511 mode = va_arg(args, int);
2512 else
2513 mode = va_arg(args, mode_t);
2514 va_end(args);
2515 }
2516
2517 if (!filename ||
2518 ( strcmp(filename, "/dev/dsp") != 0 &&
2519 strcmp(filename, "/dev/adsp") != 0 &&
2520 strcmp(filename, "/dev/sndstat") != 0 &&
2521 strcmp(filename, "/dev/mixer") != 0 )) {
2522 LOAD_OPEN64_FUNC();
2523 return _open64(filename, flags, mode);
2524 }
2525
2526 return real_open(filename, flags, mode);
2527 }
2528
2529 #endif
2530
2531 #ifdef _STAT_VER
2532
2533 int __xstat(int ver, const char *pathname, struct stat *buf) {
2534 debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname?pathname:"NULL");
2535
2536 if (!pathname ||
2537 !buf ||
2538 ( strcmp(pathname, "/dev/dsp") != 0 &&
2539 strcmp(pathname, "/dev/adsp") != 0 &&
2540 strcmp(pathname, "/dev/sndstat") != 0 &&
2541 strcmp(pathname, "/dev/mixer") != 0 )) {
2542 LOAD_XSTAT_FUNC();
2543 return ___xstat(ver, pathname, buf);
2544 }
2545
2546 if (ver != _STAT_VER) {
2547 errno = EINVAL;
2548 return -1;
2549 }
2550
2551 return stat(pathname, buf);
2552 }
2553
2554 #ifdef HAVE_OPEN64
2555
2556 int __xstat64(int ver, const char *pathname, struct stat64 *buf) {
2557 debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname?pathname:"NULL");
2558
2559 if (!pathname ||
2560 !buf ||
2561 ( strcmp(pathname, "/dev/dsp") != 0 &&
2562 strcmp(pathname, "/dev/adsp") != 0 &&
2563 strcmp(pathname, "/dev/sndstat") != 0 &&
2564 strcmp(pathname, "/dev/mixer") != 0 )) {
2565 LOAD_XSTAT64_FUNC();
2566 return ___xstat64(ver, pathname, buf);
2567 }
2568
2569 if (ver != _STAT_VER) {
2570 errno = EINVAL;
2571 return -1;
2572 }
2573
2574 return stat64(pathname, buf);
2575 }
2576
2577 #endif
2578
2579 #endif
2580
2581 FILE* fopen(const char *filename, const char *mode) {
2582 FILE *f = NULL;
2583 int fd;
2584 mode_t m;
2585
2586 debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename?filename:"NULL");
2587
2588 if (!filename ||
2589 !mode ||
2590 ( strcmp(filename, "/dev/dsp") != 0 &&
2591 strcmp(filename, "/dev/adsp") != 0 &&
2592 strcmp(filename, "/dev/sndstat") != 0 &&
2593 strcmp(filename, "/dev/mixer") != 0 )) {
2594 LOAD_FOPEN_FUNC();
2595 return _fopen(filename, mode);
2596 }
2597
2598 switch (mode[0]) {
2599 case 'r':
2600 m = O_RDONLY;
2601 break;
2602 case 'w':
2603 case 'a':
2604 m = O_WRONLY;
2605 break;
2606 default:
2607 errno = EINVAL;
2608 return NULL;
2609 }
2610
2611 if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+'))
2612 m = O_RDWR;
2613
2614 if ((fd = real_open(filename, m, 0)) < 0)
2615 return NULL;
2616
2617 if (!(f = fdopen(fd, mode))) {
2618 close(fd);
2619 return NULL;
2620 }
2621
2622 return f;
2623 }
2624
2625 #ifdef HAVE_OPEN64
2626
2627 FILE *fopen64(const char *filename, const char *mode) {
2628
2629 debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename?filename:"NULL");
2630
2631 if (!filename ||
2632 !mode ||
2633 ( strcmp(filename, "/dev/dsp") != 0 &&
2634 strcmp(filename, "/dev/adsp") != 0 &&
2635 strcmp(filename, "/dev/sndstat") != 0 &&
2636 strcmp(filename, "/dev/mixer") != 0 )) {
2637 LOAD_FOPEN64_FUNC();
2638 return _fopen64(filename, mode);
2639 }
2640
2641 return fopen(filename, mode);
2642 }
2643
2644 #endif
2645
2646 int fclose(FILE *f) {
2647 fd_info *i;
2648
2649 debug(DEBUG_LEVEL_VERBOSE, __FILE__": fclose()\n");
2650
2651 if (!function_enter()) {
2652 LOAD_FCLOSE_FUNC();
2653 return _fclose(f);
2654 }
2655
2656 if (!(i = fd_info_find(fileno(f)))) {
2657 function_exit();
2658 LOAD_FCLOSE_FUNC();
2659 return _fclose(f);
2660 }
2661
2662 fd_info_remove_from_list(i);
2663
2664 /* Dirty trick to avoid that the fd is not freed twice, once by us
2665 * and once by the real fclose() */
2666 i->app_fd = -1;
2667
2668 fd_info_unref(i);
2669
2670 function_exit();
2671
2672 LOAD_FCLOSE_FUNC();
2673 return _fclose(f);
2674 }