Add some more device properties to the sink properties list
[pulseaudio-mirror.git] / src / modules / module-alsa-sink.c
blobb8bef935f9bc34ac25c7eb4b8485ceb1ca902911
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2008 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdio.h>
29 #include <asoundlib.h>
31 #ifdef HAVE_VALGRIND_MEMCHECK_H
32 #include <valgrind/memcheck.h>
33 #endif
35 #include <pulse/xmalloc.h>
36 #include <pulse/util.h>
37 #include <pulse/timeval.h>
39 #include <pulsecore/core.h>
40 #include <pulsecore/module.h>
41 #include <pulsecore/memchunk.h>
42 #include <pulsecore/sink.h>
43 #include <pulsecore/modargs.h>
44 #include <pulsecore/core-util.h>
45 #include <pulsecore/sample-util.h>
46 #include <pulsecore/log.h>
47 #include <pulsecore/macro.h>
48 #include <pulsecore/thread.h>
49 #include <pulsecore/core-error.h>
50 #include <pulsecore/thread-mq.h>
51 #include <pulsecore/rtpoll.h>
52 #include <pulsecore/rtclock.h>
53 #include <pulsecore/time-smoother.h>
55 #include "alsa-util.h"
56 #include "module-alsa-sink-symdef.h"
58 PA_MODULE_AUTHOR("Lennart Poettering");
59 PA_MODULE_DESCRIPTION("ALSA Sink");
60 PA_MODULE_VERSION(PACKAGE_VERSION);
61 PA_MODULE_LOAD_ONCE(FALSE);
62 PA_MODULE_USAGE(
63 "sink_name=<name for the sink> "
64 "device=<ALSA device> "
65 "device_id=<ALSA card index> "
66 "format=<sample format> "
67 "rate=<sample rate> "
68 "channels=<number of channels> "
69 "channel_map=<channel map> "
70 "fragments=<number of fragments> "
71 "fragment_size=<fragment size> "
72 "mmap=<enable memory mapping?> "
73 "tsched=<enable system timer based scheduling mode?> "
74 "tsched_buffer_size=<buffer size when using timer based scheduling> "
75 "tsched_buffer_watermark=<lower fill watermark>");
77 static const char* const valid_modargs[] = {
78 "sink_name",
79 "device",
80 "device_id",
81 "format",
82 "rate",
83 "channels",
84 "channel_map",
85 "fragments",
86 "fragment_size",
87 "mmap",
88 "tsched",
89 "tsched_buffer_size",
90 "tsched_buffer_watermark",
91 NULL
94 #define DEFAULT_DEVICE "default"
95 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC) /* 2s */
96 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms */
97 #define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC) /* 3ms */
98 #define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC) /* 3ms */
100 struct userdata {
101 pa_core *core;
102 pa_module *module;
103 pa_sink *sink;
105 pa_thread *thread;
106 pa_thread_mq thread_mq;
107 pa_rtpoll *rtpoll;
109 snd_pcm_t *pcm_handle;
111 pa_alsa_fdlist *mixer_fdl;
112 snd_mixer_t *mixer_handle;
113 snd_mixer_elem_t *mixer_elem;
114 long hw_volume_max, hw_volume_min;
115 long hw_dB_max, hw_dB_min;
116 pa_bool_t hw_dB_supported;
117 pa_bool_t mixer_seperate_channels;
118 pa_cvolume hardware_volume;
120 size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
121 unsigned nfragments;
122 pa_memchunk memchunk;
124 char *device_name;
126 pa_bool_t use_mmap, use_tsched;
128 pa_bool_t first, after_rewind;
130 pa_rtpoll_item *alsa_rtpoll_item;
132 snd_mixer_selem_channel_id_t mixer_map[SND_MIXER_SCHN_LAST];
134 pa_smoother *smoother;
135 int64_t frame_index;
136 uint64_t since_start;
138 snd_pcm_sframes_t hwbuf_unused_frames;
141 static void fix_tsched_watermark(struct userdata *u) {
142 size_t max_use;
143 size_t min_sleep, min_wakeup;
144 pa_assert(u);
146 max_use = u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size;
148 min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->sink->sample_spec);
149 min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->sink->sample_spec);
151 if (min_sleep > max_use/2)
152 min_sleep = pa_frame_align(max_use/2, &u->sink->sample_spec);
153 if (min_sleep < u->frame_size)
154 min_sleep = u->frame_size;
156 if (min_wakeup > max_use/2)
157 min_wakeup = pa_frame_align(max_use/2, &u->sink->sample_spec);
158 if (min_wakeup < u->frame_size)
159 min_wakeup = u->frame_size;
161 if (u->tsched_watermark > max_use-min_sleep)
162 u->tsched_watermark = max_use-min_sleep;
164 if (u->tsched_watermark < min_wakeup)
165 u->tsched_watermark = min_wakeup;
168 static void hw_sleep_time(struct userdata *u, pa_usec_t *sleep_usec, pa_usec_t*process_usec) {
169 pa_usec_t usec, wm;
171 pa_assert(sleep_usec);
172 pa_assert(process_usec);
174 pa_assert(u);
176 usec = pa_sink_get_requested_latency_within_thread(u->sink);
178 if (usec == (pa_usec_t) -1)
179 usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
181 /* pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
183 wm = pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec);
185 if (usec >= wm) {
186 *sleep_usec = usec - wm;
187 *process_usec = wm;
188 } else
189 *process_usec = *sleep_usec = usec / 2;
191 /* pa_log_debug("after watermark: %u ms", (unsigned) (*sleep_usec / PA_USEC_PER_MSEC)); */
194 static int try_recover(struct userdata *u, const char *call, int err) {
195 pa_assert(u);
196 pa_assert(call);
197 pa_assert(err < 0);
199 pa_log_debug("%s: %s", call, snd_strerror(err));
201 pa_assert(err != -EAGAIN);
203 if (err == -EPIPE)
204 pa_log_debug("%s: Buffer underrun!", call);
206 if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
207 u->first = TRUE;
208 u->since_start = 0;
209 return 0;
212 pa_log("%s: %s", call, snd_strerror(err));
213 return -1;
216 static size_t check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
217 size_t left_to_play;
219 if ((size_t) n*u->frame_size < u->hwbuf_size)
220 left_to_play = u->hwbuf_size - ((size_t) n*u->frame_size);
221 else
222 left_to_play = 0;
224 if (left_to_play > 0) {
225 /* pa_log_debug("%0.2f ms left to play", (double) pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) / PA_USEC_PER_MSEC); */
226 } else if (!u->first && !u->after_rewind) {
227 pa_log_info("Underrun!");
229 if (u->use_tsched) {
230 size_t old_watermark = u->tsched_watermark;
232 u->tsched_watermark *= 2;
233 fix_tsched_watermark(u);
235 if (old_watermark != u->tsched_watermark)
236 pa_log_notice("Increasing wakeup watermark to %0.2f ms",
237 (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
241 return left_to_play;
244 static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
245 int work_done = 0;
246 pa_usec_t max_sleep_usec = 0, process_usec = 0;
247 size_t left_to_play;
249 pa_assert(u);
250 pa_sink_assert_ref(u->sink);
252 if (u->use_tsched)
253 hw_sleep_time(u, &max_sleep_usec, &process_usec);
255 for (;;) {
256 snd_pcm_sframes_t n;
257 int r;
259 snd_pcm_hwsync(u->pcm_handle);
261 /* First we determine how many samples are missing to fill the
262 * buffer up to 100% */
264 if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
266 if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0)
267 continue;
269 return r;
272 left_to_play = check_left_to_play(u, n);
274 if (u->use_tsched)
276 /* We won't fill up the playback buffer before at least
277 * half the sleep time is over because otherwise we might
278 * ask for more data from the clients then they expect. We
279 * need to guarantee that clients only have to keep around
280 * a single hw buffer length. */
282 if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2)
283 break;
285 if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
286 break;
288 n -= u->hwbuf_unused_frames;
290 /* pa_log_debug("Filling up"); */
292 for (;;) {
293 pa_memchunk chunk;
294 void *p;
295 int err;
296 const snd_pcm_channel_area_t *areas;
297 snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n;
298 snd_pcm_sframes_t sframes;
300 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
302 if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
304 if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
305 continue;
307 return r;
310 /* Make sure that if these memblocks need to be copied they will fit into one slot */
311 if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size)
312 frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size;
314 /* Check these are multiples of 8 bit */
315 pa_assert((areas[0].first & 7) == 0);
316 pa_assert((areas[0].step & 7)== 0);
318 /* We assume a single interleaved memory buffer */
319 pa_assert((areas[0].first >> 3) == 0);
320 pa_assert((areas[0].step >> 3) == u->frame_size);
322 p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
324 chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
325 chunk.length = pa_memblock_get_length(chunk.memblock);
326 chunk.index = 0;
328 pa_sink_render_into_full(u->sink, &chunk);
330 /* FIXME: Maybe we can do something to keep this memory block
331 * a little bit longer around? */
332 pa_memblock_unref_fixed(chunk.memblock);
334 if (PA_UNLIKELY((sframes = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
336 if ((r = try_recover(u, "snd_pcm_mmap_commit", (int) sframes)) == 0)
337 continue;
339 return r;
342 work_done = 1;
344 u->frame_index += (int64_t) frames;
345 u->since_start += frames * u->frame_size;
347 /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
349 if (frames >= (snd_pcm_uframes_t) n)
350 break;
352 n -= (snd_pcm_sframes_t) frames;
356 *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) - process_usec;
357 return work_done;
360 static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) {
361 int work_done = 0;
362 pa_usec_t max_sleep_usec = 0, process_usec = 0;
363 size_t left_to_play;
365 pa_assert(u);
366 pa_sink_assert_ref(u->sink);
368 if (u->use_tsched)
369 hw_sleep_time(u, &max_sleep_usec, &process_usec);
371 for (;;) {
372 snd_pcm_sframes_t n;
373 int r;
375 snd_pcm_hwsync(u->pcm_handle);
377 if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
379 if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0)
380 continue;
382 return r;
385 left_to_play = check_left_to_play(u, n);
387 if (u->use_tsched)
389 /* We won't fill up the playback buffer before at least
390 * half the sleep time is over because otherwise we might
391 * ask for more data from the clients then they expect. We
392 * need to guarantee that clients only have to keep around
393 * a single hw buffer length. */
395 if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2)
396 break;
398 if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
399 break;
401 n -= u->hwbuf_unused_frames;
403 for (;;) {
404 snd_pcm_sframes_t frames;
405 void *p;
407 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
409 if (u->memchunk.length <= 0)
410 pa_sink_render(u->sink, (size_t) n * u->frame_size, &u->memchunk);
412 pa_assert(u->memchunk.length > 0);
414 frames = (snd_pcm_sframes_t) (u->memchunk.length / u->frame_size);
416 if (frames > n)
417 frames = n;
419 p = pa_memblock_acquire(u->memchunk.memblock);
420 frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, (snd_pcm_uframes_t) frames);
421 pa_memblock_release(u->memchunk.memblock);
423 pa_assert(frames != 0);
425 if (PA_UNLIKELY(frames < 0)) {
427 if ((r = try_recover(u, "snd_pcm_writei", (int) frames)) == 0)
428 continue;
430 return r;
433 u->memchunk.index += (size_t) frames * u->frame_size;
434 u->memchunk.length -= (size_t) frames * u->frame_size;
436 if (u->memchunk.length <= 0) {
437 pa_memblock_unref(u->memchunk.memblock);
438 pa_memchunk_reset(&u->memchunk);
441 work_done = 1;
443 u->frame_index += frames;
444 u->since_start += (size_t) frames * u->frame_size;
446 /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
448 if (frames >= n)
449 break;
451 n -= frames;
455 *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) - process_usec;
456 return work_done;
459 static void update_smoother(struct userdata *u) {
460 snd_pcm_sframes_t delay = 0;
461 int64_t frames;
462 int err;
463 pa_usec_t now1, now2;
464 /* struct timeval timestamp; */
465 snd_pcm_status_t *status;
467 snd_pcm_status_alloca(&status);
469 pa_assert(u);
470 pa_assert(u->pcm_handle);
472 /* Let's update the time smoother */
474 snd_pcm_hwsync(u->pcm_handle);
475 snd_pcm_avail_update(u->pcm_handle);
477 /* if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) { */
478 /* pa_log("Failed to query DSP status data: %s", snd_strerror(err)); */
479 /* return; */
480 /* } */
482 /* delay = snd_pcm_status_get_delay(status); */
484 if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
485 pa_log("Failed to query DSP status data: %s", snd_strerror(err));
486 return;
489 frames = u->frame_index - delay;
491 /* pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames); */
493 /* snd_pcm_status_get_tstamp(status, &timestamp); */
494 /* pa_rtclock_from_wallclock(&timestamp); */
495 /* now1 = pa_timeval_load(&timestamp); */
497 now1 = pa_rtclock_usec();
498 now2 = pa_bytes_to_usec((uint64_t) frames * u->frame_size, &u->sink->sample_spec);
499 pa_smoother_put(u->smoother, now1, now2);
502 static pa_usec_t sink_get_latency(struct userdata *u) {
503 pa_usec_t r = 0;
504 int64_t delay;
505 pa_usec_t now1, now2;
507 pa_assert(u);
509 now1 = pa_rtclock_usec();
510 now2 = pa_smoother_get(u->smoother, now1);
512 delay = (int64_t) pa_bytes_to_usec((uint64_t) u->frame_index * u->frame_size, &u->sink->sample_spec) - (int64_t) now2;
514 if (delay > 0)
515 r = (pa_usec_t) delay;
517 if (u->memchunk.memblock)
518 r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
520 return r;
523 static int build_pollfd(struct userdata *u) {
524 pa_assert(u);
525 pa_assert(u->pcm_handle);
527 if (u->alsa_rtpoll_item)
528 pa_rtpoll_item_free(u->alsa_rtpoll_item);
530 if (!(u->alsa_rtpoll_item = pa_alsa_build_pollfd(u->pcm_handle, u->rtpoll)))
531 return -1;
533 return 0;
536 static int suspend(struct userdata *u) {
537 pa_assert(u);
538 pa_assert(u->pcm_handle);
540 pa_smoother_pause(u->smoother, pa_rtclock_usec());
542 /* Let's suspend */
543 snd_pcm_drain(u->pcm_handle);
544 snd_pcm_close(u->pcm_handle);
545 u->pcm_handle = NULL;
547 if (u->alsa_rtpoll_item) {
548 pa_rtpoll_item_free(u->alsa_rtpoll_item);
549 u->alsa_rtpoll_item = NULL;
552 pa_log_info("Device suspended...");
554 return 0;
557 static int update_sw_params(struct userdata *u) {
558 snd_pcm_uframes_t avail_min;
559 int err;
561 pa_assert(u);
563 /* Use the full buffer if noone asked us for anything specific */
564 u->hwbuf_unused_frames = 0;
566 if (u->use_tsched) {
567 pa_usec_t latency;
569 if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) != (pa_usec_t) -1) {
570 size_t b;
572 pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC);
574 b = pa_usec_to_bytes(latency, &u->sink->sample_spec);
576 /* We need at least one sample in our buffer */
578 if (PA_UNLIKELY(b < u->frame_size))
579 b = u->frame_size;
581 u->hwbuf_unused_frames = (snd_pcm_sframes_t)
582 (PA_LIKELY(b < u->hwbuf_size) ?
583 ((u->hwbuf_size - b) / u->frame_size) : 0);
585 fix_tsched_watermark(u);
589 pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
591 /* We need at last one frame in the used part of the buffer */
592 avail_min = (snd_pcm_uframes_t) u->hwbuf_unused_frames + 1;
594 if (u->use_tsched) {
595 pa_usec_t sleep_usec, process_usec;
597 hw_sleep_time(u, &sleep_usec, &process_usec);
598 avail_min += pa_usec_to_bytes(sleep_usec, &u->sink->sample_spec);
601 pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
603 if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
604 pa_log("Failed to set software parameters: %s", snd_strerror(err));
605 return err;
608 pa_sink_set_max_request(u->sink, u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size);
610 return 0;
613 static int unsuspend(struct userdata *u) {
614 pa_sample_spec ss;
615 int err;
616 pa_bool_t b, d;
617 unsigned nfrags;
618 snd_pcm_uframes_t period_size;
620 pa_assert(u);
621 pa_assert(!u->pcm_handle);
623 pa_log_info("Trying resume...");
625 snd_config_update_free_global();
626 if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK,
627 /*SND_PCM_NONBLOCK|*/
628 SND_PCM_NO_AUTO_RESAMPLE|
629 SND_PCM_NO_AUTO_CHANNELS|
630 SND_PCM_NO_AUTO_FORMAT)) < 0) {
631 pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err));
632 goto fail;
635 ss = u->sink->sample_spec;
636 nfrags = u->nfragments;
637 period_size = u->fragment_size / u->frame_size;
638 b = u->use_mmap;
639 d = u->use_tsched;
641 if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
642 pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
643 goto fail;
646 if (b != u->use_mmap || d != u->use_tsched) {
647 pa_log_warn("Resume failed, couldn't get original access mode.");
648 goto fail;
651 if (!pa_sample_spec_equal(&ss, &u->sink->sample_spec)) {
652 pa_log_warn("Resume failed, couldn't restore original sample settings.");
653 goto fail;
656 if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
657 pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
658 (unsigned long) u->nfragments, (unsigned long) u->fragment_size,
659 (unsigned long) nfrags, period_size * u->frame_size);
660 goto fail;
663 if (update_sw_params(u) < 0)
664 goto fail;
666 if (build_pollfd(u) < 0)
667 goto fail;
669 /* FIXME: We need to reload the volume somehow */
671 u->first = TRUE;
672 u->since_start = 0;
674 pa_log_info("Resumed successfully...");
676 return 0;
678 fail:
679 if (u->pcm_handle) {
680 snd_pcm_close(u->pcm_handle);
681 u->pcm_handle = NULL;
684 return -1;
687 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
688 struct userdata *u = PA_SINK(o)->userdata;
690 switch (code) {
692 case PA_SINK_MESSAGE_GET_LATENCY: {
693 pa_usec_t r = 0;
695 if (u->pcm_handle)
696 r = sink_get_latency(u);
698 *((pa_usec_t*) data) = r;
700 return 0;
703 case PA_SINK_MESSAGE_SET_STATE:
705 switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
707 case PA_SINK_SUSPENDED:
708 pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
710 if (suspend(u) < 0)
711 return -1;
713 break;
715 case PA_SINK_IDLE:
716 case PA_SINK_RUNNING:
718 if (u->sink->thread_info.state == PA_SINK_INIT) {
719 if (build_pollfd(u) < 0)
720 return -1;
723 if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
724 if (unsuspend(u) < 0)
725 return -1;
728 break;
730 case PA_SINK_UNLINKED:
731 case PA_SINK_INIT:
735 break;
738 return pa_sink_process_msg(o, code, data, offset, chunk);
741 static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
742 struct userdata *u = snd_mixer_elem_get_callback_private(elem);
744 pa_assert(u);
745 pa_assert(u->mixer_handle);
747 if (mask == SND_CTL_EVENT_MASK_REMOVE)
748 return 0;
750 if (mask & SND_CTL_EVENT_MASK_VALUE) {
751 pa_sink_get_volume(u->sink, TRUE);
752 pa_sink_get_mute(u->sink, TRUE);
755 return 0;
758 static int sink_get_volume_cb(pa_sink *s) {
759 struct userdata *u = s->userdata;
760 int err;
761 unsigned i;
762 pa_cvolume r;
763 char t[PA_CVOLUME_SNPRINT_MAX];
765 pa_assert(u);
766 pa_assert(u->mixer_elem);
768 if (u->mixer_seperate_channels) {
770 r.channels = s->sample_spec.channels;
772 for (i = 0; i < s->sample_spec.channels; i++) {
773 long alsa_vol;
775 if (u->hw_dB_supported) {
777 if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
778 goto fail;
780 #ifdef HAVE_VALGRIND_MEMCHECK_H
781 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
782 #endif
784 r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
785 } else {
787 if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
788 goto fail;
790 r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
794 } else {
795 long alsa_vol;
797 pa_assert(u->hw_dB_supported);
799 if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
800 goto fail;
802 #ifdef HAVE_VALGRIND_MEMCHECK_H
803 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
804 #endif
806 pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
809 pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
811 if (!pa_cvolume_equal(&u->hardware_volume, &r)) {
813 u->hardware_volume = s->volume = r;
815 if (u->hw_dB_supported) {
816 pa_cvolume reset;
818 /* Hmm, so the hardware volume changed, let's reset our software volume */
820 pa_cvolume_reset(&reset, s->sample_spec.channels);
821 pa_sink_set_soft_volume(s, &reset);
825 return 0;
827 fail:
828 pa_log_error("Unable to read volume: %s", snd_strerror(err));
830 return -1;
833 static int sink_set_volume_cb(pa_sink *s) {
834 struct userdata *u = s->userdata;
835 int err;
836 unsigned i;
837 pa_cvolume r;
839 pa_assert(u);
840 pa_assert(u->mixer_elem);
842 if (u->mixer_seperate_channels) {
844 r.channels = s->sample_spec.channels;
846 for (i = 0; i < s->sample_spec.channels; i++) {
847 long alsa_vol;
848 pa_volume_t vol;
850 vol = s->volume.values[i];
852 if (u->hw_dB_supported) {
854 alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
855 alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
857 if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, 1)) < 0)
858 goto fail;
860 if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
861 goto fail;
863 r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
864 } else {
866 alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
867 alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
869 if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
870 goto fail;
872 if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
873 goto fail;
875 r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
879 } else {
880 pa_volume_t vol;
881 long alsa_vol;
883 pa_assert(u->hw_dB_supported);
885 vol = pa_cvolume_max(&s->volume);
887 alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
888 alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
890 if ((err = snd_mixer_selem_set_playback_dB_all(u->mixer_elem, alsa_vol, 1)) < 0)
891 goto fail;
893 if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
894 goto fail;
896 pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
899 u->hardware_volume = r;
901 if (u->hw_dB_supported) {
902 char t[PA_CVOLUME_SNPRINT_MAX];
904 /* Match exactly what the user requested by software */
906 pa_alsa_volume_divide(&r, &s->volume);
907 pa_sink_set_soft_volume(s, &r);
909 pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->volume));
910 pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &u->hardware_volume));
911 pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
913 } else
915 /* We can't match exactly what the user requested, hence let's
916 * at least tell the user about it */
918 s->volume = r;
920 return 0;
922 fail:
923 pa_log_error("Unable to set volume: %s", snd_strerror(err));
925 return -1;
928 static int sink_get_mute_cb(pa_sink *s) {
929 struct userdata *u = s->userdata;
930 int err, sw;
932 pa_assert(u);
933 pa_assert(u->mixer_elem);
935 if ((err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw)) < 0) {
936 pa_log_error("Unable to get switch: %s", snd_strerror(err));
937 return -1;
940 s->muted = !sw;
942 return 0;
945 static int sink_set_mute_cb(pa_sink *s) {
946 struct userdata *u = s->userdata;
947 int err;
949 pa_assert(u);
950 pa_assert(u->mixer_elem);
952 if ((err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->muted)) < 0) {
953 pa_log_error("Unable to set switch: %s", snd_strerror(err));
954 return -1;
957 return 0;
960 static void sink_update_requested_latency_cb(pa_sink *s) {
961 struct userdata *u = s->userdata;
962 snd_pcm_sframes_t before;
963 pa_assert(u);
965 if (!u->pcm_handle)
966 return;
968 before = u->hwbuf_unused_frames;
969 update_sw_params(u);
971 /* Let's check whether we now use only a smaller part of the
972 buffer then before. If so, we need to make sure that subsequent
973 rewinds are relative to the new maxium fill level and not to the
974 current fill level. Thus, let's do a full rewind once, to clear
975 things up. */
977 if (u->hwbuf_unused_frames > before) {
978 pa_log_debug("Requesting rewind due to latency change.");
979 pa_sink_request_rewind(s, (size_t) -1);
983 static int process_rewind(struct userdata *u) {
984 snd_pcm_sframes_t unused;
985 size_t rewind_nbytes, unused_nbytes, limit_nbytes;
986 pa_assert(u);
988 /* Figure out how much we shall rewind and reset the counter */
989 rewind_nbytes = u->sink->thread_info.rewind_nbytes;
990 u->sink->thread_info.rewind_nbytes = 0;
992 if (rewind_nbytes <= 0)
993 goto finish;
995 pa_assert(rewind_nbytes > 0);
996 pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
998 snd_pcm_hwsync(u->pcm_handle);
999 if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
1000 pa_log("snd_pcm_avail_update() failed: %s", snd_strerror((int) unused));
1001 return -1;
1004 unused_nbytes = u->tsched_watermark + (size_t) unused * u->frame_size;
1006 if (u->hwbuf_size > unused_nbytes)
1007 limit_nbytes = u->hwbuf_size - unused_nbytes;
1008 else
1009 limit_nbytes = 0;
1011 if (rewind_nbytes > limit_nbytes)
1012 rewind_nbytes = limit_nbytes;
1014 if (rewind_nbytes > 0) {
1015 snd_pcm_sframes_t in_frames, out_frames;
1017 pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes);
1019 in_frames = (snd_pcm_sframes_t) (rewind_nbytes / u->frame_size);
1020 pa_log_debug("before: %lu", (unsigned long) in_frames);
1021 if ((out_frames = snd_pcm_rewind(u->pcm_handle, (snd_pcm_uframes_t) in_frames)) < 0) {
1022 pa_log("snd_pcm_rewind() failed: %s", snd_strerror((int) out_frames));
1023 return -1;
1025 pa_log_debug("after: %lu", (unsigned long) out_frames);
1027 rewind_nbytes = (size_t) out_frames * u->frame_size;
1029 if (rewind_nbytes <= 0)
1030 pa_log_info("Tried rewind, but was apparently not possible.");
1031 else {
1032 u->frame_index -= out_frames;
1033 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
1034 pa_sink_process_rewind(u->sink, rewind_nbytes);
1036 u->after_rewind = TRUE;
1037 return 0;
1039 } else
1040 pa_log_debug("Mhmm, actually there is nothing to rewind.");
1042 finish:
1044 pa_sink_process_rewind(u->sink, 0);
1046 return 0;
1050 static void thread_func(void *userdata) {
1051 struct userdata *u = userdata;
1053 pa_assert(u);
1055 pa_log_debug("Thread starting up");
1057 if (u->core->realtime_scheduling)
1058 pa_make_realtime(u->core->realtime_priority);
1060 pa_thread_mq_install(&u->thread_mq);
1061 pa_rtpoll_install(u->rtpoll);
1063 for (;;) {
1064 int ret;
1066 /* pa_log_debug("loop"); */
1068 /* Render some data and write it to the dsp */
1069 if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
1070 int work_done;
1071 pa_usec_t sleep_usec = 0;
1073 if (u->sink->thread_info.rewind_requested)
1074 if (process_rewind(u) < 0)
1075 goto fail;
1077 if (u->use_mmap)
1078 work_done = mmap_write(u, &sleep_usec);
1079 else
1080 work_done = unix_write(u, &sleep_usec);
1082 if (work_done < 0)
1083 goto fail;
1085 /* pa_log_debug("work_done = %i", work_done); */
1087 if (work_done) {
1089 if (u->first) {
1090 pa_log_info("Starting playback.");
1091 snd_pcm_start(u->pcm_handle);
1093 pa_smoother_resume(u->smoother, pa_rtclock_usec());
1096 update_smoother(u);
1099 if (u->use_tsched) {
1100 pa_usec_t cusec;
1102 if (u->since_start <= u->hwbuf_size) {
1104 /* USB devices on ALSA seem to hit a buffer
1105 * underrun during the first iterations much
1106 * quicker then we calculate here, probably due to
1107 * the transport latency. To accomodate for that
1108 * we artificially decrease the sleep time until
1109 * we have filled the buffer at least once
1110 * completely.*/
1112 /*pa_log_debug("Cutting sleep time for the initial iterations by half.");*/
1113 sleep_usec /= 2;
1116 /* OK, the playback buffer is now full, let's
1117 * calculate when to wake up next */
1118 /* pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
1120 /* Convert from the sound card time domain to the
1121 * system time domain */
1122 cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), sleep_usec);
1124 /* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
1126 /* We don't trust the conversion, so we wake up whatever comes first */
1127 pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(sleep_usec, cusec));
1130 u->first = FALSE;
1131 u->after_rewind = FALSE;
1133 } else if (u->use_tsched)
1135 /* OK, we're in an invalid state, let's disable our timers */
1136 pa_rtpoll_set_timer_disabled(u->rtpoll);
1138 /* Hmm, nothing to do. Let's sleep */
1139 if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
1140 goto fail;
1142 if (ret == 0)
1143 goto finish;
1145 /* Tell ALSA about this and process its response */
1146 if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
1147 struct pollfd *pollfd;
1148 unsigned short revents = 0;
1149 int err;
1150 unsigned n;
1152 pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, &n);
1154 if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd, n, &revents)) < 0) {
1155 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
1156 goto fail;
1159 if (revents & (POLLERR|POLLNVAL|POLLHUP|POLLPRI)) {
1160 if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
1161 goto fail;
1163 u->first = TRUE;
1164 u->since_start = 0;
1167 if (revents && u->use_tsched)
1168 pa_log_debug("Wakeup from ALSA!%s%s", (revents & POLLIN) ? " INPUT" : "", (revents & POLLOUT) ? " OUTPUT" : "");
1172 fail:
1173 /* If this was no regular exit from the loop we have to continue
1174 * processing messages until we received PA_MESSAGE_SHUTDOWN */
1175 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
1176 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
1178 finish:
1179 pa_log_debug("Thread shutting down");
1182 int pa__init(pa_module*m) {
1184 pa_modargs *ma = NULL;
1185 struct userdata *u = NULL;
1186 const char *dev_id;
1187 pa_sample_spec ss;
1188 pa_channel_map map;
1189 uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
1190 snd_pcm_uframes_t period_frames, tsched_frames;
1191 size_t frame_size;
1192 snd_pcm_info_t *pcm_info = NULL;
1193 int err;
1194 const char *name;
1195 char *name_buf = NULL;
1196 pa_bool_t namereg_fail;
1197 pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
1198 pa_usec_t usec;
1199 pa_sink_new_data data;
1201 snd_pcm_info_alloca(&pcm_info);
1203 pa_assert(m);
1205 pa_alsa_redirect_errors_inc();
1207 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1208 pa_log("Failed to parse module arguments");
1209 goto fail;
1212 ss = m->core->default_sample_spec;
1213 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) {
1214 pa_log("Failed to parse sample specification and channel map");
1215 goto fail;
1218 frame_size = pa_frame_size(&ss);
1220 nfrags = m->core->default_n_fragments;
1221 frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
1222 if (frag_size <= 0)
1223 frag_size = (uint32_t) frame_size;
1224 tsched_size = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
1225 tsched_watermark = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
1227 if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 ||
1228 pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 ||
1229 pa_modargs_get_value_u32(ma, "tsched_buffer_size", &tsched_size) < 0 ||
1230 pa_modargs_get_value_u32(ma, "tsched_buffer_watermark", &tsched_watermark) < 0) {
1231 pa_log("Failed to parse buffer metrics");
1232 goto fail;
1235 hwbuf_size = frag_size * nfrags;
1236 period_frames = frag_size/frame_size;
1237 tsched_frames = tsched_size/frame_size;
1239 if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
1240 pa_log("Failed to parse mmap argument.");
1241 goto fail;
1244 if (pa_modargs_get_value_boolean(ma, "tsched", &use_tsched) < 0) {
1245 pa_log("Failed to parse tsched argument.");
1246 goto fail;
1249 if (use_tsched && !pa_rtclock_hrtimer()) {
1250 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1251 use_tsched = FALSE;
1254 u = pa_xnew0(struct userdata, 1);
1255 u->core = m->core;
1256 u->module = m;
1257 m->userdata = u;
1258 u->use_mmap = use_mmap;
1259 u->use_tsched = use_tsched;
1260 u->first = TRUE;
1261 u->since_start = 0;
1262 u->after_rewind = FALSE;
1263 u->rtpoll = pa_rtpoll_new();
1264 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
1265 u->alsa_rtpoll_item = NULL;
1267 u->smoother = pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC*2, DEFAULT_TSCHED_BUFFER_USEC*2, TRUE, 5);
1268 usec = pa_rtclock_usec();
1269 pa_smoother_set_time_offset(u->smoother, usec);
1270 pa_smoother_pause(u->smoother, usec);
1272 snd_config_update_free_global();
1274 b = use_mmap;
1275 d = use_tsched;
1277 if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
1279 if (!(u->pcm_handle = pa_alsa_open_by_device_id(
1280 dev_id,
1281 &u->device_name,
1282 &ss, &map,
1283 SND_PCM_STREAM_PLAYBACK,
1284 &nfrags, &period_frames, tsched_frames,
1285 &b, &d)))
1287 goto fail;
1289 } else {
1291 if (!(u->pcm_handle = pa_alsa_open_by_device_string(
1292 pa_modargs_get_value(ma, "device", DEFAULT_DEVICE),
1293 &u->device_name,
1294 &ss, &map,
1295 SND_PCM_STREAM_PLAYBACK,
1296 &nfrags, &period_frames, tsched_frames,
1297 &b, &d)))
1298 goto fail;
1302 pa_assert(u->device_name);
1303 pa_log_info("Successfully opened device %s.", u->device_name);
1305 if (use_mmap && !b) {
1306 pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
1307 u->use_mmap = use_mmap = FALSE;
1310 if (use_tsched && (!b || !d)) {
1311 pa_log_info("Cannot enabled timer-based scheduling, falling back to sound IRQ scheduling.");
1312 u->use_tsched = use_tsched = FALSE;
1315 if (u->use_mmap)
1316 pa_log_info("Successfully enabled mmap() mode.");
1318 if (u->use_tsched)
1319 pa_log_info("Successfully enabled timer-based scheduling mode.");
1321 if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
1322 pa_log("Error fetching PCM info: %s", snd_strerror(err));
1323 goto fail;
1326 /* ALSA might tweak the sample spec, so recalculate the frame size */
1327 frame_size = pa_frame_size(&ss);
1329 if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
1330 pa_log_warn("Error opening mixer: %s", snd_strerror(err));
1331 else {
1332 pa_bool_t found = FALSE;
1334 if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
1335 found = TRUE;
1336 else {
1337 snd_pcm_info_t *info;
1339 snd_pcm_info_alloca(&info);
1341 if (snd_pcm_info(u->pcm_handle, info) >= 0) {
1342 char *md;
1343 int card;
1345 if ((card = snd_pcm_info_get_card(info)) >= 0) {
1347 md = pa_sprintf_malloc("hw:%i", card);
1349 if (strcmp(u->device_name, md))
1350 if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
1351 found = TRUE;
1352 pa_xfree(md);
1357 if (found)
1358 if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM")))
1359 found = FALSE;
1361 if (!found) {
1362 snd_mixer_close(u->mixer_handle);
1363 u->mixer_handle = NULL;
1367 if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
1368 namereg_fail = TRUE;
1369 else {
1370 name = name_buf = pa_sprintf_malloc("alsa_output.%s", u->device_name);
1371 namereg_fail = FALSE;
1374 pa_sink_new_data_init(&data);
1375 data.driver = __FILE__;
1376 data.module = m;
1377 pa_sink_new_data_set_name(&data, name);
1378 data.namereg_fail = namereg_fail;
1379 pa_sink_new_data_set_sample_spec(&data, &ss);
1380 pa_sink_new_data_set_channel_map(&data, &map);
1382 pa_alsa_init_proplist(data.proplist, pcm_info);
1383 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
1384 pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
1385 pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
1386 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
1388 u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
1389 pa_sink_new_data_done(&data);
1390 pa_xfree(name_buf);
1392 if (!u->sink) {
1393 pa_log("Failed to create sink object");
1394 goto fail;
1397 u->sink->parent.process_msg = sink_process_msg;
1398 u->sink->update_requested_latency = sink_update_requested_latency_cb;
1399 u->sink->userdata = u;
1401 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
1402 pa_sink_set_rtpoll(u->sink, u->rtpoll);
1404 u->frame_size = frame_size;
1405 u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
1406 u->nfragments = nfrags;
1407 u->hwbuf_size = u->fragment_size * nfrags;
1408 u->hwbuf_unused_frames = 0;
1409 u->tsched_watermark = tsched_watermark;
1410 u->frame_index = 0;
1411 u->hw_dB_supported = FALSE;
1412 u->hw_dB_min = u->hw_dB_max = 0;
1413 u->hw_volume_min = u->hw_volume_max = 0;
1414 u->mixer_seperate_channels = FALSE;
1415 pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels);
1417 if (use_tsched)
1418 fix_tsched_watermark(u);
1420 u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
1421 u->sink->thread_info.max_request = u->hwbuf_size;
1423 pa_sink_set_latency_range(u->sink,
1424 !use_tsched ? pa_bytes_to_usec(u->hwbuf_size, &ss) : (pa_usec_t) -1,
1425 pa_bytes_to_usec(u->hwbuf_size, &ss));
1427 pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
1428 nfrags, (long unsigned) u->fragment_size,
1429 (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
1431 if (use_tsched)
1432 pa_log_info("Time scheduling watermark is %0.2fms",
1433 (double) pa_bytes_to_usec(u->tsched_watermark, &ss) / PA_USEC_PER_MSEC);
1435 if (update_sw_params(u) < 0)
1436 goto fail;
1438 pa_memchunk_reset(&u->memchunk);
1440 if (u->mixer_handle) {
1441 pa_assert(u->mixer_elem);
1443 if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
1444 pa_bool_t suitable = TRUE;
1446 if (snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0) {
1447 pa_log_info("Failed to get volume range. Falling back to software volume control.");
1448 suitable = FALSE;
1449 } else {
1450 pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
1451 pa_assert(u->hw_volume_min < u->hw_volume_max);
1454 if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
1455 pa_log_info("Mixer doesn't support dB information.");
1456 else {
1457 #ifdef HAVE_VALGRIND_MEMCHECK_H
1458 VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
1459 VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
1460 #endif
1462 pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
1463 pa_assert(u->hw_dB_min < u->hw_dB_max);
1464 u->hw_dB_supported = TRUE;
1467 if (suitable &&
1468 !u->hw_dB_supported &&
1469 u->hw_volume_max - u->hw_volume_min < 3) {
1471 pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
1472 suitable = FALSE;
1475 if (suitable) {
1476 u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0;
1478 u->sink->get_volume = sink_get_volume_cb;
1479 u->sink->set_volume = sink_set_volume_cb;
1480 u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
1481 pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
1483 } else
1484 pa_log_info("Using software volume control.");
1487 if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
1488 u->sink->get_mute = sink_get_mute_cb;
1489 u->sink->set_mute = sink_set_mute_cb;
1490 u->sink->flags |= PA_SINK_HW_MUTE_CTRL;
1491 } else
1492 pa_log_info("Using software mute control.");
1494 u->mixer_fdl = pa_alsa_fdlist_new();
1496 if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) {
1497 pa_log("Failed to initialize file descriptor monitoring");
1498 goto fail;
1501 snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback);
1502 snd_mixer_elem_set_callback_private(u->mixer_elem, u);
1503 } else
1504 u->mixer_fdl = NULL;
1506 pa_alsa_dump(u->pcm_handle);
1508 if (!(u->thread = pa_thread_new(thread_func, u))) {
1509 pa_log("Failed to create thread.");
1510 goto fail;
1513 /* Get initial mixer settings */
1514 if (data.volume_is_set) {
1515 if (u->sink->set_volume)
1516 u->sink->set_volume(u->sink);
1517 } else {
1518 if (u->sink->get_volume)
1519 u->sink->get_volume(u->sink);
1522 if (data.muted_is_set) {
1523 if (u->sink->set_mute)
1524 u->sink->set_mute(u->sink);
1525 } else {
1526 if (u->sink->get_mute)
1527 u->sink->get_mute(u->sink);
1530 pa_sink_put(u->sink);
1532 pa_modargs_free(ma);
1534 return 0;
1536 fail:
1538 if (ma)
1539 pa_modargs_free(ma);
1541 pa__done(m);
1543 return -1;
1546 void pa__done(pa_module*m) {
1547 struct userdata *u;
1549 pa_assert(m);
1551 if (!(u = m->userdata)) {
1552 pa_alsa_redirect_errors_dec();
1553 return;
1556 if (u->sink)
1557 pa_sink_unlink(u->sink);
1559 if (u->thread) {
1560 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
1561 pa_thread_free(u->thread);
1564 pa_thread_mq_done(&u->thread_mq);
1566 if (u->sink)
1567 pa_sink_unref(u->sink);
1569 if (u->memchunk.memblock)
1570 pa_memblock_unref(u->memchunk.memblock);
1572 if (u->alsa_rtpoll_item)
1573 pa_rtpoll_item_free(u->alsa_rtpoll_item);
1575 if (u->rtpoll)
1576 pa_rtpoll_free(u->rtpoll);
1578 if (u->mixer_fdl)
1579 pa_alsa_fdlist_free(u->mixer_fdl);
1581 if (u->mixer_handle)
1582 snd_mixer_close(u->mixer_handle);
1584 if (u->pcm_handle) {
1585 snd_pcm_drop(u->pcm_handle);
1586 snd_pcm_close(u->pcm_handle);
1589 if (u->smoother)
1590 pa_smoother_free(u->smoother);
1592 pa_xfree(u->device_name);
1593 pa_xfree(u);
1595 snd_config_update_free_global();
1597 pa_alsa_redirect_errors_dec();