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
29 #include <asoundlib.h>
31 #ifdef HAVE_VALGRIND_MEMCHECK_H
32 #include <valgrind/memcheck.h>
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
);
63 "sink_name=<name for the sink> "
64 "device=<ALSA device> "
65 "device_id=<ALSA card index> "
66 "format=<sample format> "
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
[] = {
90 "tsched_buffer_watermark",
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 */
106 pa_thread_mq thread_mq
;
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
;
122 pa_memchunk memchunk
;
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
;
136 uint64_t since_start
;
138 snd_pcm_sframes_t hwbuf_unused_frames
;
141 static void fix_tsched_watermark(struct userdata
*u
) {
143 size_t min_sleep
, min_wakeup
;
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
) {
171 pa_assert(sleep_usec
);
172 pa_assert(process_usec
);
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
);
186 *sleep_usec
= usec
- wm
;
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
) {
199 pa_log_debug("%s: %s", call
, snd_strerror(err
));
201 pa_assert(err
!= -EAGAIN
);
204 pa_log_debug("%s: Buffer underrun!", call
);
206 if ((err
= snd_pcm_recover(u
->pcm_handle
, err
, 1)) == 0) {
212 pa_log("%s: %s", call
, snd_strerror(err
));
216 static size_t check_left_to_play(struct userdata
*u
, snd_pcm_sframes_t n
) {
219 if ((size_t) n
*u
->frame_size
< u
->hwbuf_size
)
220 left_to_play
= u
->hwbuf_size
- ((size_t) n
*u
->frame_size
);
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!");
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
);
244 static int mmap_write(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
246 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
250 pa_sink_assert_ref(u
->sink
);
253 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
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
= pa_alsa_safe_avail_update(u
->pcm_handle
, u
->hwbuf_size
, &u
->sink
->sample_spec
)) < 0)) {
266 if ((r
= try_recover(u
, "snd_pcm_avail_update", (int) n
)) == 0)
272 left_to_play
= check_left_to_play(u
, n
);
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. */
283 pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) > process_usec
+max_sleep_usec
/2)
286 if (PA_UNLIKELY(n
<= u
->hwbuf_unused_frames
)) {
289 pa_log("ALSA woke us up to write new data to the device, but there was actually nothing to write! "
290 "Most likely this is an ALSA driver bug. Please report this issue to the ALSA developers. "
291 "We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail_update() returned 0.");
296 n
-= u
->hwbuf_unused_frames
;
300 /* pa_log_debug("Filling up"); */
306 const snd_pcm_channel_area_t
*areas
;
307 snd_pcm_uframes_t offset
, frames
= (snd_pcm_uframes_t
) n
;
308 snd_pcm_sframes_t sframes
;
310 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
312 if (PA_UNLIKELY((err
= pa_alsa_safe_mmap_begin(u
->pcm_handle
, &areas
, &offset
, &frames
, u
->hwbuf_size
, &u
->sink
->sample_spec
)) < 0)) {
314 if ((r
= try_recover(u
, "snd_pcm_mmap_begin", err
)) == 0)
320 /* Make sure that if these memblocks need to be copied they will fit into one slot */
321 if (frames
> pa_mempool_block_size_max(u
->sink
->core
->mempool
)/u
->frame_size
)
322 frames
= pa_mempool_block_size_max(u
->sink
->core
->mempool
)/u
->frame_size
;
324 /* Check these are multiples of 8 bit */
325 pa_assert((areas
[0].first
& 7) == 0);
326 pa_assert((areas
[0].step
& 7)== 0);
328 /* We assume a single interleaved memory buffer */
329 pa_assert((areas
[0].first
>> 3) == 0);
330 pa_assert((areas
[0].step
>> 3) == u
->frame_size
);
332 p
= (uint8_t*) areas
[0].addr
+ (offset
* u
->frame_size
);
334 chunk
.memblock
= pa_memblock_new_fixed(u
->core
->mempool
, p
, frames
* u
->frame_size
, TRUE
);
335 chunk
.length
= pa_memblock_get_length(chunk
.memblock
);
338 pa_sink_render_into_full(u
->sink
, &chunk
);
340 /* FIXME: Maybe we can do something to keep this memory block
341 * a little bit longer around? */
342 pa_memblock_unref_fixed(chunk
.memblock
);
344 if (PA_UNLIKELY((sframes
= snd_pcm_mmap_commit(u
->pcm_handle
, offset
, frames
)) < 0)) {
346 if ((r
= try_recover(u
, "snd_pcm_mmap_commit", (int) sframes
)) == 0)
354 u
->frame_index
+= (int64_t) frames
;
355 u
->since_start
+= frames
* u
->frame_size
;
357 /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
359 if (frames
>= (snd_pcm_uframes_t
) n
)
362 n
-= (snd_pcm_sframes_t
) frames
;
366 *sleep_usec
= pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) - process_usec
;
370 static int unix_write(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
372 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
376 pa_sink_assert_ref(u
->sink
);
379 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
385 snd_pcm_hwsync(u
->pcm_handle
);
387 if (PA_UNLIKELY((n
= pa_alsa_safe_avail_update(u
->pcm_handle
, u
->hwbuf_size
, &u
->sink
->sample_spec
)) < 0)) {
389 if ((r
= try_recover(u
, "snd_pcm_avail_update", (int) n
)) == 0)
395 left_to_play
= check_left_to_play(u
, n
);
399 /* We won't fill up the playback buffer before at least
400 * half the sleep time is over because otherwise we might
401 * ask for more data from the clients then they expect. We
402 * need to guarantee that clients only have to keep around
403 * a single hw buffer length. */
406 pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) > process_usec
+max_sleep_usec
/2)
409 if (PA_UNLIKELY(n
<= u
->hwbuf_unused_frames
)) {
412 pa_log("ALSA woke us up to write new data to the device, but there was actually nothing to write! "
413 "Most likely this is an ALSA driver bug. Please report this issue to the ALSA developers. "
414 "We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail_update() returned 0.");
419 n
-= u
->hwbuf_unused_frames
;
424 snd_pcm_sframes_t frames
;
427 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
429 if (u
->memchunk
.length
<= 0)
430 pa_sink_render(u
->sink
, (size_t) n
* u
->frame_size
, &u
->memchunk
);
432 pa_assert(u
->memchunk
.length
> 0);
434 frames
= (snd_pcm_sframes_t
) (u
->memchunk
.length
/ u
->frame_size
);
439 p
= pa_memblock_acquire(u
->memchunk
.memblock
);
440 frames
= snd_pcm_writei(u
->pcm_handle
, (const uint8_t*) p
+ u
->memchunk
.index
, (snd_pcm_uframes_t
) frames
);
441 pa_memblock_release(u
->memchunk
.memblock
);
443 pa_assert(frames
!= 0);
445 if (PA_UNLIKELY(frames
< 0)) {
447 if ((r
= try_recover(u
, "snd_pcm_writei", (int) frames
)) == 0)
453 u
->memchunk
.index
+= (size_t) frames
* u
->frame_size
;
454 u
->memchunk
.length
-= (size_t) frames
* u
->frame_size
;
456 if (u
->memchunk
.length
<= 0) {
457 pa_memblock_unref(u
->memchunk
.memblock
);
458 pa_memchunk_reset(&u
->memchunk
);
463 u
->frame_index
+= frames
;
464 u
->since_start
+= (size_t) frames
* u
->frame_size
;
466 /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
475 *sleep_usec
= pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) - process_usec
;
479 static void update_smoother(struct userdata
*u
) {
480 snd_pcm_sframes_t delay
= 0;
483 pa_usec_t now1
, now2
;
484 /* struct timeval timestamp; */
485 snd_pcm_status_t
*status
;
487 snd_pcm_status_alloca(&status
);
490 pa_assert(u
->pcm_handle
);
492 /* Let's update the time smoother */
494 snd_pcm_hwsync(u
->pcm_handle
);
495 snd_pcm_avail_update(u
->pcm_handle
);
497 /* if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) { */
498 /* pa_log("Failed to query DSP status data: %s", snd_strerror(err)); */
502 /* delay = snd_pcm_status_get_delay(status); */
504 if (PA_UNLIKELY((err
= snd_pcm_delay(u
->pcm_handle
, &delay
)) < 0)) {
505 pa_log("Failed to query DSP status data: %s", snd_strerror(err
));
509 frames
= u
->frame_index
- delay
;
511 /* pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames); */
513 /* snd_pcm_status_get_tstamp(status, ×tamp); */
514 /* pa_rtclock_from_wallclock(×tamp); */
515 /* now1 = pa_timeval_load(×tamp); */
517 now1
= pa_rtclock_usec();
518 now2
= pa_bytes_to_usec((uint64_t) frames
* u
->frame_size
, &u
->sink
->sample_spec
);
519 pa_smoother_put(u
->smoother
, now1
, now2
);
522 static pa_usec_t
sink_get_latency(struct userdata
*u
) {
525 pa_usec_t now1
, now2
;
529 now1
= pa_rtclock_usec();
530 now2
= pa_smoother_get(u
->smoother
, now1
);
532 delay
= (int64_t) pa_bytes_to_usec((uint64_t) u
->frame_index
* u
->frame_size
, &u
->sink
->sample_spec
) - (int64_t) now2
;
535 r
= (pa_usec_t
) delay
;
537 if (u
->memchunk
.memblock
)
538 r
+= pa_bytes_to_usec(u
->memchunk
.length
, &u
->sink
->sample_spec
);
543 static int build_pollfd(struct userdata
*u
) {
545 pa_assert(u
->pcm_handle
);
547 if (u
->alsa_rtpoll_item
)
548 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
550 if (!(u
->alsa_rtpoll_item
= pa_alsa_build_pollfd(u
->pcm_handle
, u
->rtpoll
)))
556 static int suspend(struct userdata
*u
) {
558 pa_assert(u
->pcm_handle
);
560 pa_smoother_pause(u
->smoother
, pa_rtclock_usec());
562 /* Let's suspend -- we don't call snd_pcm_drain() here since that might
563 * take awfully long with our long buffer sizes today. */
564 snd_pcm_close(u
->pcm_handle
);
565 u
->pcm_handle
= NULL
;
567 if (u
->alsa_rtpoll_item
) {
568 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
569 u
->alsa_rtpoll_item
= NULL
;
572 pa_log_info("Device suspended...");
577 static int update_sw_params(struct userdata
*u
) {
578 snd_pcm_uframes_t avail_min
;
583 /* Use the full buffer if noone asked us for anything specific */
584 u
->hwbuf_unused_frames
= 0;
589 if ((latency
= pa_sink_get_requested_latency_within_thread(u
->sink
)) != (pa_usec_t
) -1) {
592 pa_log_debug("latency set to %0.2fms", (double) latency
/ PA_USEC_PER_MSEC
);
594 b
= pa_usec_to_bytes(latency
, &u
->sink
->sample_spec
);
596 /* We need at least one sample in our buffer */
598 if (PA_UNLIKELY(b
< u
->frame_size
))
601 u
->hwbuf_unused_frames
= (snd_pcm_sframes_t
)
602 (PA_LIKELY(b
< u
->hwbuf_size
) ?
603 ((u
->hwbuf_size
- b
) / u
->frame_size
) : 0);
606 fix_tsched_watermark(u
);
609 pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u
->hwbuf_unused_frames
);
611 /* We need at last one frame in the used part of the buffer */
612 avail_min
= (snd_pcm_uframes_t
) u
->hwbuf_unused_frames
+ 1;
615 pa_usec_t sleep_usec
, process_usec
;
617 hw_sleep_time(u
, &sleep_usec
, &process_usec
);
618 avail_min
+= pa_usec_to_bytes(sleep_usec
, &u
->sink
->sample_spec
) / u
->frame_size
;
621 pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min
);
623 if ((err
= pa_alsa_set_sw_params(u
->pcm_handle
, avail_min
)) < 0) {
624 pa_log("Failed to set software parameters: %s", snd_strerror(err
));
628 pa_sink_set_max_request(u
->sink
, u
->hwbuf_size
- (size_t) u
->hwbuf_unused_frames
* u
->frame_size
);
633 static int unsuspend(struct userdata
*u
) {
638 snd_pcm_uframes_t period_size
;
641 pa_assert(!u
->pcm_handle
);
643 pa_log_info("Trying resume...");
645 snd_config_update_free_global();
646 if ((err
= snd_pcm_open(&u
->pcm_handle
, u
->device_name
, SND_PCM_STREAM_PLAYBACK
,
647 /*SND_PCM_NONBLOCK|*/
648 SND_PCM_NO_AUTO_RESAMPLE
|
649 SND_PCM_NO_AUTO_CHANNELS
|
650 SND_PCM_NO_AUTO_FORMAT
)) < 0) {
651 pa_log("Error opening PCM device %s: %s", u
->device_name
, snd_strerror(err
));
655 ss
= u
->sink
->sample_spec
;
656 nfrags
= u
->nfragments
;
657 period_size
= u
->fragment_size
/ u
->frame_size
;
661 if ((err
= pa_alsa_set_hw_params(u
->pcm_handle
, &ss
, &nfrags
, &period_size
, u
->hwbuf_size
/ u
->frame_size
, &b
, &d
, TRUE
)) < 0) {
662 pa_log("Failed to set hardware parameters: %s", snd_strerror(err
));
666 if (b
!= u
->use_mmap
|| d
!= u
->use_tsched
) {
667 pa_log_warn("Resume failed, couldn't get original access mode.");
671 if (!pa_sample_spec_equal(&ss
, &u
->sink
->sample_spec
)) {
672 pa_log_warn("Resume failed, couldn't restore original sample settings.");
676 if (nfrags
!= u
->nfragments
|| period_size
*u
->frame_size
!= u
->fragment_size
) {
677 pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
678 (unsigned long) u
->nfragments
, (unsigned long) u
->fragment_size
,
679 (unsigned long) nfrags
, period_size
* u
->frame_size
);
683 if (update_sw_params(u
) < 0)
686 if (build_pollfd(u
) < 0)
689 /* FIXME: We need to reload the volume somehow */
694 pa_log_info("Resumed successfully...");
700 snd_pcm_close(u
->pcm_handle
);
701 u
->pcm_handle
= NULL
;
707 static int sink_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
708 struct userdata
*u
= PA_SINK(o
)->userdata
;
712 case PA_SINK_MESSAGE_GET_LATENCY
: {
716 r
= sink_get_latency(u
);
718 *((pa_usec_t
*) data
) = r
;
723 case PA_SINK_MESSAGE_SET_STATE
:
725 switch ((pa_sink_state_t
) PA_PTR_TO_UINT(data
)) {
727 case PA_SINK_SUSPENDED
:
728 pa_assert(PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
));
736 case PA_SINK_RUNNING
:
738 if (u
->sink
->thread_info
.state
== PA_SINK_INIT
) {
739 if (build_pollfd(u
) < 0)
743 if (u
->sink
->thread_info
.state
== PA_SINK_SUSPENDED
) {
744 if (unsuspend(u
) < 0)
750 case PA_SINK_UNLINKED
:
758 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
761 static int mixer_callback(snd_mixer_elem_t
*elem
, unsigned int mask
) {
762 struct userdata
*u
= snd_mixer_elem_get_callback_private(elem
);
765 pa_assert(u
->mixer_handle
);
767 if (mask
== SND_CTL_EVENT_MASK_REMOVE
)
770 if (mask
& SND_CTL_EVENT_MASK_VALUE
) {
771 pa_sink_get_volume(u
->sink
, TRUE
);
772 pa_sink_get_mute(u
->sink
, TRUE
);
778 static pa_volume_t
from_alsa_volume(struct userdata
*u
, long alsa_vol
) {
780 return (pa_volume_t
) round(((double) (alsa_vol
- u
->hw_volume_min
) * PA_VOLUME_NORM
) /
781 (double) (u
->hw_volume_max
- u
->hw_volume_min
));
784 static long to_alsa_volume(struct userdata
*u
, pa_volume_t vol
) {
787 alsa_vol
= (long) round(((double) vol
* (double) (u
->hw_volume_max
- u
->hw_volume_min
))
788 / PA_VOLUME_NORM
) + u
->hw_volume_min
;
790 return PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_volume_min
, u
->hw_volume_max
);
793 static int sink_get_volume_cb(pa_sink
*s
) {
794 struct userdata
*u
= s
->userdata
;
798 char t
[PA_CVOLUME_SNPRINT_MAX
];
801 pa_assert(u
->mixer_elem
);
803 if (u
->mixer_seperate_channels
) {
805 r
.channels
= s
->sample_spec
.channels
;
807 for (i
= 0; i
< s
->sample_spec
.channels
; i
++) {
810 if (u
->hw_dB_supported
) {
812 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
815 #ifdef HAVE_VALGRIND_MEMCHECK_H
816 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol
, sizeof(alsa_vol
));
819 r
.values
[i
] = pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0);
822 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
825 r
.values
[i
] = from_alsa_volume(u
, alsa_vol
);
832 if (u
->hw_dB_supported
) {
834 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
837 #ifdef HAVE_VALGRIND_MEMCHECK_H
838 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol
, sizeof(alsa_vol
));
841 pa_cvolume_set(&r
, s
->sample_spec
.channels
, pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0));
845 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
848 pa_cvolume_set(&r
, s
->sample_spec
.channels
, from_alsa_volume(u
, alsa_vol
));
852 pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
854 if (!pa_cvolume_equal(&u
->hardware_volume
, &r
)) {
856 u
->hardware_volume
= s
->volume
= r
;
858 if (u
->hw_dB_supported
) {
861 /* Hmm, so the hardware volume changed, let's reset our software volume */
863 pa_cvolume_reset(&reset
, s
->sample_spec
.channels
);
864 pa_sink_set_soft_volume(s
, &reset
);
871 pa_log_error("Unable to read volume: %s", snd_strerror(err
));
876 static int sink_set_volume_cb(pa_sink
*s
) {
877 struct userdata
*u
= s
->userdata
;
883 pa_assert(u
->mixer_elem
);
885 if (u
->mixer_seperate_channels
) {
887 r
.channels
= s
->sample_spec
.channels
;
889 for (i
= 0; i
< s
->sample_spec
.channels
; i
++) {
893 vol
= s
->volume
.values
[i
];
895 if (u
->hw_dB_supported
) {
897 alsa_vol
= (long) (pa_sw_volume_to_dB(vol
) * 100);
898 alsa_vol
+= u
->hw_dB_max
;
899 alsa_vol
= PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_dB_min
, u
->hw_dB_max
);
901 if ((err
= snd_mixer_selem_set_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], alsa_vol
, 1)) < 0)
904 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
907 r
.values
[i
] = pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0);
910 alsa_vol
= to_alsa_volume(u
, vol
);
912 if ((err
= snd_mixer_selem_set_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], alsa_vol
)) < 0)
915 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
918 r
.values
[i
] = from_alsa_volume(u
, alsa_vol
);
926 vol
= pa_cvolume_max(&s
->volume
);
928 if (u
->hw_dB_supported
) {
929 alsa_vol
= (long) (pa_sw_volume_to_dB(vol
) * 100);
930 alsa_vol
+= u
->hw_dB_max
;
931 alsa_vol
= PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_dB_min
, u
->hw_dB_max
);
933 if ((err
= snd_mixer_selem_set_playback_dB_all(u
->mixer_elem
, alsa_vol
, 1)) < 0)
936 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
939 pa_cvolume_set(&r
, s
->volume
.channels
, pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0));
942 alsa_vol
= to_alsa_volume(u
, vol
);
944 if ((err
= snd_mixer_selem_set_playback_volume_all(u
->mixer_elem
, alsa_vol
)) < 0)
947 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
950 pa_cvolume_set(&r
, s
->sample_spec
.channels
, from_alsa_volume(u
, alsa_vol
));
954 u
->hardware_volume
= r
;
956 if (u
->hw_dB_supported
) {
957 char t
[PA_CVOLUME_SNPRINT_MAX
];
959 /* Match exactly what the user requested by software */
961 pa_sw_cvolume_divide(&r
, &s
->volume
, &r
);
962 pa_sink_set_soft_volume(s
, &r
);
964 pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->volume
));
965 pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &u
->hardware_volume
));
966 pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
970 /* We can't match exactly what the user requested, hence let's
971 * at least tell the user about it */
978 pa_log_error("Unable to set volume: %s", snd_strerror(err
));
983 static int sink_get_mute_cb(pa_sink
*s
) {
984 struct userdata
*u
= s
->userdata
;
988 pa_assert(u
->mixer_elem
);
990 if ((err
= snd_mixer_selem_get_playback_switch(u
->mixer_elem
, 0, &sw
)) < 0) {
991 pa_log_error("Unable to get switch: %s", snd_strerror(err
));
1000 static int sink_set_mute_cb(pa_sink
*s
) {
1001 struct userdata
*u
= s
->userdata
;
1005 pa_assert(u
->mixer_elem
);
1007 if ((err
= snd_mixer_selem_set_playback_switch_all(u
->mixer_elem
, !s
->muted
)) < 0) {
1008 pa_log_error("Unable to set switch: %s", snd_strerror(err
));
1015 static void sink_update_requested_latency_cb(pa_sink
*s
) {
1016 struct userdata
*u
= s
->userdata
;
1017 snd_pcm_sframes_t before
;
1023 before
= u
->hwbuf_unused_frames
;
1024 update_sw_params(u
);
1026 /* Let's check whether we now use only a smaller part of the
1027 buffer then before. If so, we need to make sure that subsequent
1028 rewinds are relative to the new maxium fill level and not to the
1029 current fill level. Thus, let's do a full rewind once, to clear
1032 if (u
->hwbuf_unused_frames
> before
) {
1033 pa_log_debug("Requesting rewind due to latency change.");
1034 pa_sink_request_rewind(s
, (size_t) -1);
1038 static int process_rewind(struct userdata
*u
) {
1039 snd_pcm_sframes_t unused
;
1040 size_t rewind_nbytes
, unused_nbytes
, limit_nbytes
;
1043 /* Figure out how much we shall rewind and reset the counter */
1044 rewind_nbytes
= u
->sink
->thread_info
.rewind_nbytes
;
1045 u
->sink
->thread_info
.rewind_nbytes
= 0;
1047 if (rewind_nbytes
<= 0)
1050 pa_assert(rewind_nbytes
> 0);
1051 pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes
);
1053 snd_pcm_hwsync(u
->pcm_handle
);
1054 if ((unused
= snd_pcm_avail_update(u
->pcm_handle
)) < 0) {
1055 pa_log("snd_pcm_avail_update() failed: %s", snd_strerror((int) unused
));
1059 unused_nbytes
= u
->tsched_watermark
+ (size_t) unused
* u
->frame_size
;
1061 if (u
->hwbuf_size
> unused_nbytes
)
1062 limit_nbytes
= u
->hwbuf_size
- unused_nbytes
;
1066 if (rewind_nbytes
> limit_nbytes
)
1067 rewind_nbytes
= limit_nbytes
;
1069 if (rewind_nbytes
> 0) {
1070 snd_pcm_sframes_t in_frames
, out_frames
;
1072 pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes
);
1074 in_frames
= (snd_pcm_sframes_t
) (rewind_nbytes
/ u
->frame_size
);
1075 pa_log_debug("before: %lu", (unsigned long) in_frames
);
1076 if ((out_frames
= snd_pcm_rewind(u
->pcm_handle
, (snd_pcm_uframes_t
) in_frames
)) < 0) {
1077 pa_log("snd_pcm_rewind() failed: %s", snd_strerror((int) out_frames
));
1080 pa_log_debug("after: %lu", (unsigned long) out_frames
);
1082 rewind_nbytes
= (size_t) out_frames
* u
->frame_size
;
1084 if (rewind_nbytes
<= 0)
1085 pa_log_info("Tried rewind, but was apparently not possible.");
1087 u
->frame_index
-= out_frames
;
1088 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes
);
1089 pa_sink_process_rewind(u
->sink
, rewind_nbytes
);
1091 u
->after_rewind
= TRUE
;
1095 pa_log_debug("Mhmm, actually there is nothing to rewind.");
1099 pa_sink_process_rewind(u
->sink
, 0);
1105 static void thread_func(void *userdata
) {
1106 struct userdata
*u
= userdata
;
1107 unsigned short revents
= 0;
1111 pa_log_debug("Thread starting up");
1113 if (u
->core
->realtime_scheduling
)
1114 pa_make_realtime(u
->core
->realtime_priority
);
1116 pa_thread_mq_install(&u
->thread_mq
);
1117 pa_rtpoll_install(u
->rtpoll
);
1122 /* pa_log_debug("loop"); */
1124 /* Render some data and write it to the dsp */
1125 if (PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
1127 pa_usec_t sleep_usec
= 0;
1129 if (u
->sink
->thread_info
.rewind_requested
)
1130 if (process_rewind(u
) < 0)
1134 work_done
= mmap_write(u
, &sleep_usec
, revents
& POLLOUT
);
1136 work_done
= unix_write(u
, &sleep_usec
, revents
& POLLOUT
);
1141 /* pa_log_debug("work_done = %i", work_done); */
1146 pa_log_info("Starting playback.");
1147 snd_pcm_start(u
->pcm_handle
);
1149 pa_smoother_resume(u
->smoother
, pa_rtclock_usec());
1155 if (u
->use_tsched
) {
1158 if (u
->since_start
<= u
->hwbuf_size
) {
1160 /* USB devices on ALSA seem to hit a buffer
1161 * underrun during the first iterations much
1162 * quicker then we calculate here, probably due to
1163 * the transport latency. To accomodate for that
1164 * we artificially decrease the sleep time until
1165 * we have filled the buffer at least once
1168 /*pa_log_debug("Cutting sleep time for the initial iterations by half.");*/
1172 /* OK, the playback buffer is now full, let's
1173 * calculate when to wake up next */
1174 /* pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
1176 /* Convert from the sound card time domain to the
1177 * system time domain */
1178 cusec
= pa_smoother_translate(u
->smoother
, pa_rtclock_usec(), sleep_usec
);
1180 /* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
1182 /* We don't trust the conversion, so we wake up whatever comes first */
1183 pa_rtpoll_set_timer_relative(u
->rtpoll
, PA_MIN(sleep_usec
, cusec
));
1187 u
->after_rewind
= FALSE
;
1189 } else if (u
->use_tsched
)
1191 /* OK, we're in an invalid state, let's disable our timers */
1192 pa_rtpoll_set_timer_disabled(u
->rtpoll
);
1194 /* Hmm, nothing to do. Let's sleep */
1195 if ((ret
= pa_rtpoll_run(u
->rtpoll
, TRUE
)) < 0)
1201 /* Tell ALSA about this and process its response */
1202 if (PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
1203 struct pollfd
*pollfd
;
1207 pollfd
= pa_rtpoll_item_get_pollfd(u
->alsa_rtpoll_item
, &n
);
1209 if ((err
= snd_pcm_poll_descriptors_revents(u
->pcm_handle
, pollfd
, n
, &revents
)) < 0) {
1210 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err
));
1214 if (revents
& (POLLIN
|POLLERR
|POLLNVAL
|POLLHUP
|POLLPRI
)) {
1215 if (pa_alsa_recover_from_poll(u
->pcm_handle
, revents
) < 0)
1222 if (revents
&& u
->use_tsched
)
1223 pa_log_debug("Wakeup from ALSA!%s%s", (revents
& POLLIN
) ? " INPUT" : "", (revents
& POLLOUT
) ? " OUTPUT" : "");
1229 /* If this was no regular exit from the loop we have to continue
1230 * processing messages until we received PA_MESSAGE_SHUTDOWN */
1231 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
1232 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
1235 pa_log_debug("Thread shutting down");
1238 int pa__init(pa_module
*m
) {
1240 pa_modargs
*ma
= NULL
;
1241 struct userdata
*u
= NULL
;
1245 uint32_t nfrags
, hwbuf_size
, frag_size
, tsched_size
, tsched_watermark
;
1246 snd_pcm_uframes_t period_frames
, tsched_frames
;
1248 snd_pcm_info_t
*pcm_info
= NULL
;
1251 char *name_buf
= NULL
;
1252 pa_bool_t namereg_fail
;
1253 pa_bool_t use_mmap
= TRUE
, b
, use_tsched
= TRUE
, d
;
1255 pa_sink_new_data data
;
1256 const pa_alsa_profile_info
*profile
= NULL
;
1258 snd_pcm_info_alloca(&pcm_info
);
1262 pa_alsa_redirect_errors_inc();
1264 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1265 pa_log("Failed to parse module arguments");
1269 ss
= m
->core
->default_sample_spec
;
1270 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_ALSA
) < 0) {
1271 pa_log("Failed to parse sample specification and channel map");
1275 frame_size
= pa_frame_size(&ss
);
1277 nfrags
= m
->core
->default_n_fragments
;
1278 frag_size
= (uint32_t) pa_usec_to_bytes(m
->core
->default_fragment_size_msec
*PA_USEC_PER_MSEC
, &ss
);
1280 frag_size
= (uint32_t) frame_size
;
1281 tsched_size
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC
, &ss
);
1282 tsched_watermark
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC
, &ss
);
1284 if (pa_modargs_get_value_u32(ma
, "fragments", &nfrags
) < 0 ||
1285 pa_modargs_get_value_u32(ma
, "fragment_size", &frag_size
) < 0 ||
1286 pa_modargs_get_value_u32(ma
, "tsched_buffer_size", &tsched_size
) < 0 ||
1287 pa_modargs_get_value_u32(ma
, "tsched_buffer_watermark", &tsched_watermark
) < 0) {
1288 pa_log("Failed to parse buffer metrics");
1292 hwbuf_size
= frag_size
* nfrags
;
1293 period_frames
= frag_size
/frame_size
;
1294 tsched_frames
= tsched_size
/frame_size
;
1296 if (pa_modargs_get_value_boolean(ma
, "mmap", &use_mmap
) < 0) {
1297 pa_log("Failed to parse mmap argument.");
1301 if (pa_modargs_get_value_boolean(ma
, "tsched", &use_tsched
) < 0) {
1302 pa_log("Failed to parse tsched argument.");
1306 if (use_tsched
&& !pa_rtclock_hrtimer()) {
1307 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1311 m
->userdata
= u
= pa_xnew0(struct userdata
, 1);
1314 u
->use_mmap
= use_mmap
;
1315 u
->use_tsched
= use_tsched
;
1318 u
->after_rewind
= FALSE
;
1319 u
->rtpoll
= pa_rtpoll_new();
1320 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
1321 u
->alsa_rtpoll_item
= NULL
;
1323 u
->smoother
= pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC
*2, DEFAULT_TSCHED_BUFFER_USEC
*2, TRUE
, 5);
1324 usec
= pa_rtclock_usec();
1325 pa_smoother_set_time_offset(u
->smoother
, usec
);
1326 pa_smoother_pause(u
->smoother
, usec
);
1328 snd_config_update_free_global();
1333 if ((dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1335 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id_auto(
1339 SND_PCM_STREAM_PLAYBACK
,
1340 &nfrags
, &period_frames
, tsched_frames
,
1347 if (!(u
->pcm_handle
= pa_alsa_open_by_device_string(
1348 pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
),
1351 SND_PCM_STREAM_PLAYBACK
,
1352 &nfrags
, &period_frames
, tsched_frames
,
1358 pa_assert(u
->device_name
);
1359 pa_log_info("Successfully opened device %s.", u
->device_name
);
1362 pa_log_info("Selected configuration '%s' (%s).", profile
->description
, profile
->name
);
1364 if (use_mmap
&& !b
) {
1365 pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
1366 u
->use_mmap
= use_mmap
= FALSE
;
1369 if (use_tsched
&& (!b
|| !d
)) {
1370 pa_log_info("Cannot enabled timer-based scheduling, falling back to sound IRQ scheduling.");
1371 u
->use_tsched
= use_tsched
= FALSE
;
1375 pa_log_info("Successfully enabled mmap() mode.");
1378 pa_log_info("Successfully enabled timer-based scheduling mode.");
1380 if ((err
= snd_pcm_info(u
->pcm_handle
, pcm_info
)) < 0) {
1381 pa_log("Error fetching PCM info: %s", snd_strerror(err
));
1385 /* ALSA might tweak the sample spec, so recalculate the frame size */
1386 frame_size
= pa_frame_size(&ss
);
1388 if ((err
= snd_mixer_open(&u
->mixer_handle
, 0)) < 0)
1389 pa_log_warn("Error opening mixer: %s", snd_strerror(err
));
1391 pa_bool_t found
= FALSE
;
1393 if (pa_alsa_prepare_mixer(u
->mixer_handle
, u
->device_name
) >= 0)
1396 snd_pcm_info_t
*info
;
1398 snd_pcm_info_alloca(&info
);
1400 if (snd_pcm_info(u
->pcm_handle
, info
) >= 0) {
1404 if ((card
= snd_pcm_info_get_card(info
)) >= 0) {
1406 md
= pa_sprintf_malloc("hw:%i", card
);
1408 if (strcmp(u
->device_name
, md
))
1409 if (pa_alsa_prepare_mixer(u
->mixer_handle
, md
) >= 0)
1417 if (!(u
->mixer_elem
= pa_alsa_find_elem(u
->mixer_handle
, "Master", "PCM", TRUE
)))
1421 snd_mixer_close(u
->mixer_handle
);
1422 u
->mixer_handle
= NULL
;
1426 if ((name
= pa_modargs_get_value(ma
, "sink_name", NULL
)))
1427 namereg_fail
= TRUE
;
1429 name
= name_buf
= pa_sprintf_malloc("alsa_output.%s", u
->device_name
);
1430 namereg_fail
= FALSE
;
1433 pa_sink_new_data_init(&data
);
1434 data
.driver
= __FILE__
;
1436 pa_sink_new_data_set_name(&data
, name
);
1437 data
.namereg_fail
= namereg_fail
;
1438 pa_sink_new_data_set_sample_spec(&data
, &ss
);
1439 pa_sink_new_data_set_channel_map(&data
, &map
);
1441 pa_alsa_init_proplist_pcm(data
.proplist
, pcm_info
);
1442 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
1443 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
* nfrags
));
1444 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
));
1445 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, u
->use_tsched
? "mmap+timer" : (u
->use_mmap
? "mmap" : "serial"));
1448 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_NAME
, profile
->name
);
1449 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
, profile
->description
);
1452 u
->sink
= pa_sink_new(m
->core
, &data
, PA_SINK_HARDWARE
|PA_SINK_LATENCY
);
1453 pa_sink_new_data_done(&data
);
1457 pa_log("Failed to create sink object");
1461 u
->sink
->parent
.process_msg
= sink_process_msg
;
1462 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1463 u
->sink
->userdata
= u
;
1465 pa_sink_set_asyncmsgq(u
->sink
, u
->thread_mq
.inq
);
1466 pa_sink_set_rtpoll(u
->sink
, u
->rtpoll
);
1468 u
->frame_size
= frame_size
;
1469 u
->fragment_size
= frag_size
= (uint32_t) (period_frames
* frame_size
);
1470 u
->nfragments
= nfrags
;
1471 u
->hwbuf_size
= u
->fragment_size
* nfrags
;
1472 u
->hwbuf_unused_frames
= 0;
1473 u
->tsched_watermark
= tsched_watermark
;
1475 u
->hw_dB_supported
= FALSE
;
1476 u
->hw_dB_min
= u
->hw_dB_max
= 0;
1477 u
->hw_volume_min
= u
->hw_volume_max
= 0;
1478 u
->mixer_seperate_channels
= FALSE
;
1479 pa_cvolume_mute(&u
->hardware_volume
, u
->sink
->sample_spec
.channels
);
1482 fix_tsched_watermark(u
);
1484 u
->sink
->thread_info
.max_rewind
= use_tsched
? u
->hwbuf_size
: 0;
1485 u
->sink
->thread_info
.max_request
= u
->hwbuf_size
;
1487 pa_sink_set_latency_range(u
->sink
,
1488 !use_tsched
? pa_bytes_to_usec(u
->hwbuf_size
, &ss
) : (pa_usec_t
) -1,
1489 pa_bytes_to_usec(u
->hwbuf_size
, &ss
));
1491 pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
1492 nfrags
, (long unsigned) u
->fragment_size
,
1493 (double) pa_bytes_to_usec(u
->hwbuf_size
, &ss
) / PA_USEC_PER_MSEC
);
1496 pa_log_info("Time scheduling watermark is %0.2fms",
1497 (double) pa_bytes_to_usec(u
->tsched_watermark
, &ss
) / PA_USEC_PER_MSEC
);
1499 if (update_sw_params(u
) < 0)
1502 pa_memchunk_reset(&u
->memchunk
);
1504 if (u
->mixer_handle
) {
1505 pa_assert(u
->mixer_elem
);
1507 if (snd_mixer_selem_has_playback_volume(u
->mixer_elem
)) {
1508 pa_bool_t suitable
= FALSE
;
1510 if (snd_mixer_selem_get_playback_volume_range(u
->mixer_elem
, &u
->hw_volume_min
, &u
->hw_volume_max
) < 0)
1511 pa_log_info("Failed to get volume range. Falling back to software volume control.");
1512 else if (u
->hw_volume_min
>= u
->hw_volume_max
)
1513 pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", u
->hw_volume_min
, u
->hw_volume_max
);
1515 pa_log_info("Volume ranges from %li to %li.", u
->hw_volume_min
, u
->hw_volume_max
);
1520 if (snd_mixer_selem_get_playback_dB_range(u
->mixer_elem
, &u
->hw_dB_min
, &u
->hw_dB_max
) < 0)
1521 pa_log_info("Mixer doesn't support dB information.");
1523 #ifdef HAVE_VALGRIND_MEMCHECK_H
1524 VALGRIND_MAKE_MEM_DEFINED(&u
->hw_dB_min
, sizeof(u
->hw_dB_min
));
1525 VALGRIND_MAKE_MEM_DEFINED(&u
->hw_dB_max
, sizeof(u
->hw_dB_max
));
1528 if (u
->hw_dB_min
>= u
->hw_dB_max
)
1529 pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u
->hw_dB_min
/100.0, (double) u
->hw_dB_max
/100.0);
1531 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);
1532 u
->hw_dB_supported
= TRUE
;
1534 if (u
->hw_dB_max
> 0) {
1535 u
->sink
->base_volume
= pa_sw_volume_from_dB(- (double) u
->hw_dB_max
/100.0);
1536 pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u
->sink
->base_volume
));
1538 pa_log_info("No particular base volume set, fixing to 0 dB");
1542 if (!u
->hw_dB_supported
&&
1543 u
->hw_volume_max
- u
->hw_volume_min
< 3) {
1545 pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
1551 u
->mixer_seperate_channels
= pa_alsa_calc_mixer_map(u
->mixer_elem
, &map
, u
->mixer_map
, TRUE
) >= 0;
1553 u
->sink
->get_volume
= sink_get_volume_cb
;
1554 u
->sink
->set_volume
= sink_set_volume_cb
;
1555 u
->sink
->flags
|= PA_SINK_HW_VOLUME_CTRL
| (u
->hw_dB_supported
? PA_SINK_DECIBEL_VOLUME
: 0);
1556 pa_log_info("Using hardware volume control. Hardware dB scale %s.", u
->hw_dB_supported
? "supported" : "not supported");
1559 pa_log_info("Using software volume control.");
1562 if (snd_mixer_selem_has_playback_switch(u
->mixer_elem
)) {
1563 u
->sink
->get_mute
= sink_get_mute_cb
;
1564 u
->sink
->set_mute
= sink_set_mute_cb
;
1565 u
->sink
->flags
|= PA_SINK_HW_MUTE_CTRL
;
1567 pa_log_info("Using software mute control.");
1569 u
->mixer_fdl
= pa_alsa_fdlist_new();
1571 if (pa_alsa_fdlist_set_mixer(u
->mixer_fdl
, u
->mixer_handle
, m
->core
->mainloop
) < 0) {
1572 pa_log("Failed to initialize file descriptor monitoring");
1576 snd_mixer_elem_set_callback(u
->mixer_elem
, mixer_callback
);
1577 snd_mixer_elem_set_callback_private(u
->mixer_elem
, u
);
1579 u
->mixer_fdl
= NULL
;
1581 pa_alsa_dump(u
->pcm_handle
);
1583 if (!(u
->thread
= pa_thread_new(thread_func
, u
))) {
1584 pa_log("Failed to create thread.");
1588 /* Get initial mixer settings */
1589 if (data
.volume_is_set
) {
1590 if (u
->sink
->set_volume
)
1591 u
->sink
->set_volume(u
->sink
);
1593 if (u
->sink
->get_volume
)
1594 u
->sink
->get_volume(u
->sink
);
1597 if (data
.muted_is_set
) {
1598 if (u
->sink
->set_mute
)
1599 u
->sink
->set_mute(u
->sink
);
1601 if (u
->sink
->get_mute
)
1602 u
->sink
->get_mute(u
->sink
);
1605 pa_sink_put(u
->sink
);
1607 pa_modargs_free(ma
);
1614 pa_modargs_free(ma
);
1621 int pa__get_n_used(pa_module
*m
) {
1625 pa_assert_se(u
= m
->userdata
);
1627 return pa_sink_linked_by(u
->sink
);
1630 void pa__done(pa_module
*m
) {
1635 if (!(u
= m
->userdata
))
1639 pa_sink_unlink(u
->sink
);
1642 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
1643 pa_thread_free(u
->thread
);
1646 pa_thread_mq_done(&u
->thread_mq
);
1649 pa_sink_unref(u
->sink
);
1651 if (u
->memchunk
.memblock
)
1652 pa_memblock_unref(u
->memchunk
.memblock
);
1654 if (u
->alsa_rtpoll_item
)
1655 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
1658 pa_rtpoll_free(u
->rtpoll
);
1661 pa_alsa_fdlist_free(u
->mixer_fdl
);
1663 if (u
->mixer_handle
)
1664 snd_mixer_close(u
->mixer_handle
);
1666 if (u
->pcm_handle
) {
1667 snd_pcm_drop(u
->pcm_handle
);
1668 snd_pcm_close(u
->pcm_handle
);
1672 pa_smoother_free(u
->smoother
);
1674 pa_xfree(u
->device_name
);
1679 snd_config_update_free_global();
1680 pa_alsa_redirect_errors_dec();