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