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