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 #include <pulse/xmalloc.h>
32 #include <pulse/util.h>
33 #include <pulse/timeval.h>
35 #include <pulsecore/core.h>
36 #include <pulsecore/module.h>
37 #include <pulsecore/memchunk.h>
38 #include <pulsecore/sink.h>
39 #include <pulsecore/modargs.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/sample-util.h>
42 #include <pulsecore/log.h>
43 #include <pulsecore/macro.h>
44 #include <pulsecore/thread.h>
45 #include <pulsecore/core-error.h>
46 #include <pulsecore/thread-mq.h>
47 #include <pulsecore/rtpoll.h>
48 #include <pulsecore/rtclock.h>
49 #include <pulsecore/time-smoother.h>
51 #include "alsa-util.h"
52 #include "module-alsa-sink-symdef.h"
54 PA_MODULE_AUTHOR("Lennart Poettering");
55 PA_MODULE_DESCRIPTION("ALSA Sink");
56 PA_MODULE_VERSION(PACKAGE_VERSION
);
57 PA_MODULE_LOAD_ONCE(FALSE
);
59 "sink_name=<name for the sink> "
60 "device=<ALSA device> "
61 "device_id=<ALSA card index> "
62 "format=<sample format> "
64 "channels=<number of channels> "
65 "channel_map=<channel map> "
66 "fragments=<number of fragments> "
67 "fragment_size=<fragment size> "
68 "mmap=<enable memory mapping?> "
69 "tsched=<enable system timer based scheduling mode?> "
70 "tsched_buffer_size=<buffer size when using timer based scheduling> "
71 "tsched_buffer_watermark=<lower fill watermark>");
73 static const char* const valid_modargs
[] = {
86 "tsched_buffer_watermark",
90 #define DEFAULT_DEVICE "default"
91 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC) /* 2s */
92 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms */
93 #define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC) /* 3ms */
94 #define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC) /* 3ms */
102 pa_thread_mq thread_mq
;
105 snd_pcm_t
*pcm_handle
;
107 pa_alsa_fdlist
*mixer_fdl
;
108 snd_mixer_t
*mixer_handle
;
109 snd_mixer_elem_t
*mixer_elem
;
110 long hw_volume_max
, hw_volume_min
;
111 long hw_dB_max
, hw_dB_min
;
112 pa_bool_t hw_dB_supported
;
113 pa_bool_t mixer_seperate_channels
;
114 pa_cvolume hardware_volume
;
116 size_t frame_size
, fragment_size
, hwbuf_size
, tsched_watermark
;
118 pa_memchunk memchunk
;
122 pa_bool_t use_mmap
, use_tsched
;
124 pa_bool_t first
, after_rewind
;
126 pa_rtpoll_item
*alsa_rtpoll_item
;
128 snd_mixer_selem_channel_id_t mixer_map
[SND_MIXER_SCHN_LAST
];
130 pa_smoother
*smoother
;
132 uint64_t since_start
;
134 snd_pcm_sframes_t hwbuf_unused_frames
;
137 static void fix_tsched_watermark(struct userdata
*u
) {
139 size_t min_sleep
, min_wakeup
;
142 max_use
= u
->hwbuf_size
- u
->hwbuf_unused_frames
* u
->frame_size
;
144 min_sleep
= pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC
, &u
->sink
->sample_spec
);
145 min_wakeup
= pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC
, &u
->sink
->sample_spec
);
147 if (min_sleep
> max_use
/2)
148 min_sleep
= pa_frame_align(max_use
/2, &u
->sink
->sample_spec
);
149 if (min_sleep
< u
->frame_size
)
150 min_sleep
= u
->frame_size
;
152 if (min_wakeup
> max_use
/2)
153 min_wakeup
= pa_frame_align(max_use
/2, &u
->sink
->sample_spec
);
154 if (min_wakeup
< u
->frame_size
)
155 min_wakeup
= u
->frame_size
;
157 if (u
->tsched_watermark
> max_use
-min_sleep
)
158 u
->tsched_watermark
= max_use
-min_sleep
;
160 if (u
->tsched_watermark
< min_wakeup
)
161 u
->tsched_watermark
= min_wakeup
;
164 static void hw_sleep_time(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_usec_t
*process_usec
) {
167 pa_assert(sleep_usec
);
168 pa_assert(process_usec
);
172 usec
= pa_sink_get_requested_latency_within_thread(u
->sink
);
174 if (usec
== (pa_usec_t
) -1)
175 usec
= pa_bytes_to_usec(u
->hwbuf_size
, &u
->sink
->sample_spec
);
177 /* pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
179 wm
= pa_bytes_to_usec(u
->tsched_watermark
, &u
->sink
->sample_spec
);
182 *sleep_usec
= usec
- wm
;
185 *process_usec
= *sleep_usec
= usec
/ 2;
187 /* pa_log_debug("after watermark: %u ms", (unsigned) (*sleep_usec / PA_USEC_PER_MSEC)); */
190 static int try_recover(struct userdata
*u
, const char *call
, int err
) {
195 pa_log_debug("%s: %s", call
, snd_strerror(err
));
197 pa_assert(err
!= -EAGAIN
);
200 pa_log_debug("%s: Buffer underrun!", call
);
202 if ((err
= snd_pcm_recover(u
->pcm_handle
, err
, 1)) == 0) {
208 pa_log("%s: %s", call
, snd_strerror(err
));
212 static size_t check_left_to_play(struct userdata
*u
, snd_pcm_sframes_t n
) {
215 if (n
*u
->frame_size
< u
->hwbuf_size
)
216 left_to_play
= u
->hwbuf_size
- (n
*u
->frame_size
);
220 if (left_to_play
> 0) {
221 /* 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); */
222 } else if (!u
->first
&& !u
->after_rewind
) {
223 pa_log_info("Underrun!");
226 size_t old_watermark
= u
->tsched_watermark
;
228 u
->tsched_watermark
*= 2;
229 fix_tsched_watermark(u
);
231 if (old_watermark
!= u
->tsched_watermark
)
232 pa_log_notice("Increasing wakeup watermark to %0.2f ms",
233 (double) pa_bytes_to_usec(u
->tsched_watermark
, &u
->sink
->sample_spec
) / PA_USEC_PER_MSEC
);
240 static int mmap_write(struct userdata
*u
, pa_usec_t
*sleep_usec
) {
242 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
246 pa_sink_assert_ref(u
->sink
);
249 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
255 snd_pcm_hwsync(u
->pcm_handle
);
257 /* First we determine how many samples are missing to fill the
258 * buffer up to 100% */
260 if (PA_UNLIKELY((n
= snd_pcm_avail_update(u
->pcm_handle
)) < 0)) {
262 if ((r
= try_recover(u
, "snd_pcm_avail_update", n
)) == 0)
268 left_to_play
= check_left_to_play(u
, n
);
272 /* We won't fill up the playback buffer before at least
273 * half the sleep time is over because otherwise we might
274 * ask for more data from the clients then they expect. We
275 * need to guarantee that clients only have to keep around
276 * a single hw buffer length. */
278 if (pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) > process_usec
+max_sleep_usec
/2)
281 if (PA_UNLIKELY(n
<= u
->hwbuf_unused_frames
))
284 n
-= u
->hwbuf_unused_frames
;
286 /* pa_log_debug("Filling up"); */
292 const snd_pcm_channel_area_t
*areas
;
293 snd_pcm_uframes_t offset
, frames
= (snd_pcm_uframes_t
) n
;
295 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
297 if (PA_UNLIKELY((err
= snd_pcm_mmap_begin(u
->pcm_handle
, &areas
, &offset
, &frames
)) < 0)) {
299 if ((r
= try_recover(u
, "snd_pcm_mmap_begin", err
)) == 0)
305 /* Make sure that if these memblocks need to be copied they will fit into one slot */
306 if (frames
> pa_mempool_block_size_max(u
->sink
->core
->mempool
)/u
->frame_size
)
307 frames
= pa_mempool_block_size_max(u
->sink
->core
->mempool
)/u
->frame_size
;
309 /* Check these are multiples of 8 bit */
310 pa_assert((areas
[0].first
& 7) == 0);
311 pa_assert((areas
[0].step
& 7)== 0);
313 /* We assume a single interleaved memory buffer */
314 pa_assert((areas
[0].first
>> 3) == 0);
315 pa_assert((areas
[0].step
>> 3) == u
->frame_size
);
317 p
= (uint8_t*) areas
[0].addr
+ (offset
* u
->frame_size
);
319 chunk
.memblock
= pa_memblock_new_fixed(u
->core
->mempool
, p
, frames
* u
->frame_size
, TRUE
);
320 chunk
.length
= pa_memblock_get_length(chunk
.memblock
);
323 pa_sink_render_into_full(u
->sink
, &chunk
);
325 /* FIXME: Maybe we can do something to keep this memory block
326 * a little bit longer around? */
327 pa_memblock_unref_fixed(chunk
.memblock
);
329 if (PA_UNLIKELY((err
= snd_pcm_mmap_commit(u
->pcm_handle
, offset
, frames
)) < 0)) {
331 if ((r
= try_recover(u
, "snd_pcm_mmap_commit", err
)) == 0)
339 u
->frame_index
+= frames
;
340 u
->since_start
+= frames
* u
->frame_size
;
342 /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
344 if (frames
>= (snd_pcm_uframes_t
) n
)
351 *sleep_usec
= pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) - process_usec
;
355 static int unix_write(struct userdata
*u
, pa_usec_t
*sleep_usec
) {
357 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
361 pa_sink_assert_ref(u
->sink
);
364 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
370 snd_pcm_hwsync(u
->pcm_handle
);
372 if (PA_UNLIKELY((n
= snd_pcm_avail_update(u
->pcm_handle
)) < 0)) {
374 if ((r
= try_recover(u
, "snd_pcm_avail_update", n
)) == 0)
380 left_to_play
= check_left_to_play(u
, n
);
384 /* We won't fill up the playback buffer before at least
385 * half the sleep time is over because otherwise we might
386 * ask for more data from the clients then they expect. We
387 * need to guarantee that clients only have to keep around
388 * a single hw buffer length. */
390 if (pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) > process_usec
+max_sleep_usec
/2)
393 if (PA_UNLIKELY(n
<= u
->hwbuf_unused_frames
))
396 n
-= u
->hwbuf_unused_frames
;
399 snd_pcm_sframes_t frames
;
402 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
404 if (u
->memchunk
.length
<= 0)
405 pa_sink_render(u
->sink
, n
* u
->frame_size
, &u
->memchunk
);
407 pa_assert(u
->memchunk
.length
> 0);
409 frames
= u
->memchunk
.length
/ u
->frame_size
;
414 p
= pa_memblock_acquire(u
->memchunk
.memblock
);
415 frames
= snd_pcm_writei(u
->pcm_handle
, (const uint8_t*) p
+ u
->memchunk
.index
, frames
);
416 pa_memblock_release(u
->memchunk
.memblock
);
418 pa_assert(frames
!= 0);
420 if (PA_UNLIKELY(frames
< 0)) {
422 if ((r
= try_recover(u
, "snd_pcm_writei", n
)) == 0)
428 u
->memchunk
.index
+= frames
* u
->frame_size
;
429 u
->memchunk
.length
-= frames
* u
->frame_size
;
431 if (u
->memchunk
.length
<= 0) {
432 pa_memblock_unref(u
->memchunk
.memblock
);
433 pa_memchunk_reset(&u
->memchunk
);
438 u
->frame_index
+= frames
;
439 u
->since_start
+= frames
* u
->frame_size
;
441 /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
450 *sleep_usec
= pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) - process_usec
;
454 static void update_smoother(struct userdata
*u
) {
455 snd_pcm_sframes_t delay
= 0;
458 pa_usec_t now1
, now2
;
459 /* struct timeval timestamp; */
460 snd_pcm_status_t
*status
;
462 snd_pcm_status_alloca(&status
);
465 pa_assert(u
->pcm_handle
);
467 /* Let's update the time smoother */
469 snd_pcm_hwsync(u
->pcm_handle
);
470 snd_pcm_avail_update(u
->pcm_handle
);
472 /* if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) { */
473 /* pa_log("Failed to query DSP status data: %s", snd_strerror(err)); */
477 /* delay = snd_pcm_status_get_delay(status); */
479 if (PA_UNLIKELY((err
= snd_pcm_delay(u
->pcm_handle
, &delay
)) < 0)) {
480 pa_log("Failed to query DSP status data: %s", snd_strerror(err
));
484 frames
= u
->frame_index
- delay
;
486 /* pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames); */
488 /* snd_pcm_status_get_tstamp(status, ×tamp); */
489 /* pa_rtclock_from_wallclock(×tamp); */
490 /* now1 = pa_timeval_load(×tamp); */
492 now1
= pa_rtclock_usec();
493 now2
= pa_bytes_to_usec(frames
* u
->frame_size
, &u
->sink
->sample_spec
);
494 pa_smoother_put(u
->smoother
, now1
, now2
);
497 static pa_usec_t
sink_get_latency(struct userdata
*u
) {
500 pa_usec_t now1
, now2
;
504 now1
= pa_rtclock_usec();
505 now2
= pa_smoother_get(u
->smoother
, now1
);
507 delay
= (int64_t) pa_bytes_to_usec(u
->frame_index
* u
->frame_size
, &u
->sink
->sample_spec
) - (int64_t) now2
;
510 r
= (pa_usec_t
) delay
;
512 if (u
->memchunk
.memblock
)
513 r
+= pa_bytes_to_usec(u
->memchunk
.length
, &u
->sink
->sample_spec
);
518 static int build_pollfd(struct userdata
*u
) {
520 pa_assert(u
->pcm_handle
);
522 if (u
->alsa_rtpoll_item
)
523 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
525 if (!(u
->alsa_rtpoll_item
= pa_alsa_build_pollfd(u
->pcm_handle
, u
->rtpoll
)))
531 static int suspend(struct userdata
*u
) {
533 pa_assert(u
->pcm_handle
);
535 pa_smoother_pause(u
->smoother
, pa_rtclock_usec());
538 snd_pcm_drain(u
->pcm_handle
);
539 snd_pcm_close(u
->pcm_handle
);
540 u
->pcm_handle
= NULL
;
542 if (u
->alsa_rtpoll_item
) {
543 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
544 u
->alsa_rtpoll_item
= NULL
;
547 pa_log_info("Device suspended...");
552 static int update_sw_params(struct userdata
*u
) {
553 snd_pcm_uframes_t avail_min
;
558 /* Use the full buffer if noone asked us for anything specific */
559 u
->hwbuf_unused_frames
= 0;
564 if ((latency
= pa_sink_get_requested_latency_within_thread(u
->sink
)) != (pa_usec_t
) -1) {
567 pa_log_debug("latency set to %0.2f", (double) latency
/ PA_USEC_PER_MSEC
);
569 b
= pa_usec_to_bytes(latency
, &u
->sink
->sample_spec
);
571 /* We need at least one sample in our buffer */
573 if (PA_UNLIKELY(b
< u
->frame_size
))
576 u
->hwbuf_unused_frames
=
577 PA_LIKELY(b
< u
->hwbuf_size
) ?
578 ((u
->hwbuf_size
- b
) / u
->frame_size
) : 0;
580 fix_tsched_watermark(u
);
584 pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u
->hwbuf_unused_frames
);
586 /* We need at last one frame in the used part of the buffer */
587 avail_min
= u
->hwbuf_unused_frames
+ 1;
590 pa_usec_t sleep_usec
, process_usec
;
592 hw_sleep_time(u
, &sleep_usec
, &process_usec
);
593 avail_min
+= pa_usec_to_bytes(sleep_usec
, &u
->sink
->sample_spec
);
596 pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min
);
598 if ((err
= pa_alsa_set_sw_params(u
->pcm_handle
, avail_min
)) < 0) {
599 pa_log("Failed to set software parameters: %s", snd_strerror(err
));
603 pa_sink_set_max_request(u
->sink
, u
->hwbuf_size
- u
->hwbuf_unused_frames
* u
->frame_size
);
608 static int unsuspend(struct userdata
*u
) {
613 snd_pcm_uframes_t period_size
;
616 pa_assert(!u
->pcm_handle
);
618 pa_log_info("Trying resume...");
620 snd_config_update_free_global();
621 if ((err
= snd_pcm_open(&u
->pcm_handle
, u
->device_name
, SND_PCM_STREAM_PLAYBACK
, SND_PCM_NONBLOCK
)) < 0) {
622 pa_log("Error opening PCM device %s: %s", u
->device_name
, snd_strerror(err
));
626 ss
= u
->sink
->sample_spec
;
627 nfrags
= u
->nfragments
;
628 period_size
= u
->fragment_size
/ u
->frame_size
;
632 if ((err
= pa_alsa_set_hw_params(u
->pcm_handle
, &ss
, &nfrags
, &period_size
, u
->hwbuf_size
/ u
->frame_size
, &b
, &d
, TRUE
)) < 0) {
633 pa_log("Failed to set hardware parameters: %s", snd_strerror(err
));
637 if (b
!= u
->use_mmap
|| d
!= u
->use_tsched
) {
638 pa_log_warn("Resume failed, couldn't get original access mode.");
642 if (!pa_sample_spec_equal(&ss
, &u
->sink
->sample_spec
)) {
643 pa_log_warn("Resume failed, couldn't restore original sample settings.");
647 if (nfrags
!= u
->nfragments
|| period_size
*u
->frame_size
!= u
->fragment_size
) {
648 pa_log_warn("Resume failed, couldn't restore original fragment settings.");
652 if (update_sw_params(u
) < 0)
655 if (build_pollfd(u
) < 0)
658 /* FIXME: We need to reload the volume somehow */
663 pa_log_info("Resumed successfully...");
669 snd_pcm_close(u
->pcm_handle
);
670 u
->pcm_handle
= NULL
;
676 static int sink_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
677 struct userdata
*u
= PA_SINK(o
)->userdata
;
681 case PA_SINK_MESSAGE_GET_LATENCY
: {
685 r
= sink_get_latency(u
);
687 *((pa_usec_t
*) data
) = r
;
692 case PA_SINK_MESSAGE_SET_STATE
:
694 switch ((pa_sink_state_t
) PA_PTR_TO_UINT(data
)) {
696 case PA_SINK_SUSPENDED
:
697 pa_assert(PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
));
705 case PA_SINK_RUNNING
:
707 if (u
->sink
->thread_info
.state
== PA_SINK_INIT
) {
708 if (build_pollfd(u
) < 0)
712 if (u
->sink
->thread_info
.state
== PA_SINK_SUSPENDED
) {
713 if (unsuspend(u
) < 0)
719 case PA_SINK_UNLINKED
:
727 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
730 static int mixer_callback(snd_mixer_elem_t
*elem
, unsigned int mask
) {
731 struct userdata
*u
= snd_mixer_elem_get_callback_private(elem
);
734 pa_assert(u
->mixer_handle
);
736 if (mask
== SND_CTL_EVENT_MASK_REMOVE
)
739 if (mask
& SND_CTL_EVENT_MASK_VALUE
) {
740 pa_sink_get_volume(u
->sink
, TRUE
);
741 pa_sink_get_mute(u
->sink
, TRUE
);
747 static int sink_get_volume_cb(pa_sink
*s
) {
748 struct userdata
*u
= s
->userdata
;
752 char t
[PA_CVOLUME_SNPRINT_MAX
];
755 pa_assert(u
->mixer_elem
);
757 if (u
->mixer_seperate_channels
) {
759 r
.channels
= s
->sample_spec
.channels
;
761 for (i
= 0; i
< s
->sample_spec
.channels
; i
++) {
764 if (u
->hw_dB_supported
) {
766 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
769 r
.values
[i
] = pa_sw_volume_from_dB((double) alsa_vol
/ 100.0);
772 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
775 r
.values
[i
] = (pa_volume_t
) round(((double) (alsa_vol
- u
->hw_volume_min
) * PA_VOLUME_NORM
) / (u
->hw_volume_max
- u
->hw_volume_min
));
782 pa_assert(u
->hw_dB_supported
);
784 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
787 pa_cvolume_set(&r
, s
->sample_spec
.channels
, pa_sw_volume_from_dB((double) alsa_vol
/ 100.0));
790 pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
792 if (!pa_cvolume_equal(&u
->hardware_volume
, &r
)) {
794 u
->hardware_volume
= s
->volume
= r
;
796 if (u
->hw_dB_supported
) {
799 /* Hmm, so the hardware volume changed, let's reset our software volume */
801 pa_cvolume_reset(&reset
, s
->sample_spec
.channels
);
802 pa_sink_set_soft_volume(s
, &reset
);
809 pa_log_error("Unable to read volume: %s", snd_strerror(err
));
814 static int sink_set_volume_cb(pa_sink
*s
) {
815 struct userdata
*u
= s
->userdata
;
821 pa_assert(u
->mixer_elem
);
823 if (u
->mixer_seperate_channels
) {
825 r
.channels
= s
->sample_spec
.channels
;
827 for (i
= 0; i
< s
->sample_spec
.channels
; i
++) {
831 vol
= s
->volume
.values
[i
];
833 if (u
->hw_dB_supported
) {
835 alsa_vol
= (long) (pa_sw_volume_to_dB(vol
) * 100);
836 alsa_vol
= PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_dB_min
, u
->hw_dB_max
);
838 if ((err
= snd_mixer_selem_set_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], alsa_vol
, 1)) < 0)
841 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
844 r
.values
[i
] = pa_sw_volume_from_dB((double) alsa_vol
/ 100.0);
847 alsa_vol
= (long) round(((double) vol
* (u
->hw_volume_max
- u
->hw_volume_min
)) / PA_VOLUME_NORM
) + u
->hw_volume_min
;
848 alsa_vol
= PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_volume_min
, u
->hw_volume_max
);
850 if ((err
= snd_mixer_selem_set_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], alsa_vol
)) < 0)
853 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
856 r
.values
[i
] = (pa_volume_t
) round(((double) (alsa_vol
- u
->hw_volume_min
) * PA_VOLUME_NORM
) / (u
->hw_volume_max
- u
->hw_volume_min
));
864 pa_assert(u
->hw_dB_supported
);
866 vol
= pa_cvolume_max(&s
->volume
);
868 alsa_vol
= (long) (pa_sw_volume_to_dB(vol
) * 100);
869 alsa_vol
= PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_dB_min
, u
->hw_dB_max
);
871 if ((err
= snd_mixer_selem_set_playback_dB_all(u
->mixer_elem
, alsa_vol
, 1)) < 0)
874 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
877 pa_cvolume_set(&r
, s
->volume
.channels
, pa_sw_volume_from_dB((double) alsa_vol
/ 100.0));
880 u
->hardware_volume
= r
;
882 if (u
->hw_dB_supported
) {
883 char t
[PA_CVOLUME_SNPRINT_MAX
];
885 /* Match exactly what the user requested by software */
887 pa_alsa_volume_divide(&r
, &s
->volume
);
888 pa_sink_set_soft_volume(s
, &r
);
890 pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->volume
));
891 pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &u
->hardware_volume
));
892 pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
896 /* We can't match exactly what the user requested, hence let's
897 * at least tell the user about it */
904 pa_log_error("Unable to set volume: %s", snd_strerror(err
));
909 static int sink_get_mute_cb(pa_sink
*s
) {
910 struct userdata
*u
= s
->userdata
;
914 pa_assert(u
->mixer_elem
);
916 if ((err
= snd_mixer_selem_get_playback_switch(u
->mixer_elem
, 0, &sw
)) < 0) {
917 pa_log_error("Unable to get switch: %s", snd_strerror(err
));
926 static int sink_set_mute_cb(pa_sink
*s
) {
927 struct userdata
*u
= s
->userdata
;
931 pa_assert(u
->mixer_elem
);
933 if ((err
= snd_mixer_selem_set_playback_switch_all(u
->mixer_elem
, !s
->muted
)) < 0) {
934 pa_log_error("Unable to set switch: %s", snd_strerror(err
));
941 static void sink_update_requested_latency_cb(pa_sink
*s
) {
942 struct userdata
*u
= s
->userdata
;
943 snd_pcm_sframes_t before
;
949 before
= u
->hwbuf_unused_frames
;
952 /* Let's check whether we now use only a smaller part of the
953 buffer then before. If so, we need to make sure that subsequent
954 rewinds are relative to the new maxium fill level and not to the
955 current fill level. Thus, let's do a full rewind once, to clear
958 if (u
->hwbuf_unused_frames
> before
) {
959 pa_log_debug("Requesting rewind due to latency change.");
960 pa_sink_request_rewind(s
, (size_t) -1);
964 static int process_rewind(struct userdata
*u
) {
965 snd_pcm_sframes_t unused
;
966 size_t rewind_nbytes
, unused_nbytes
, limit_nbytes
;
969 /* Figure out how much we shall rewind and reset the counter */
970 rewind_nbytes
= u
->sink
->thread_info
.rewind_nbytes
;
971 u
->sink
->thread_info
.rewind_nbytes
= 0;
973 if (rewind_nbytes
<= 0)
976 pa_assert(rewind_nbytes
> 0);
977 pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes
);
979 snd_pcm_hwsync(u
->pcm_handle
);
980 if ((unused
= snd_pcm_avail_update(u
->pcm_handle
)) < 0) {
981 pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused
));
985 unused_nbytes
= u
->tsched_watermark
+ (size_t) unused
* u
->frame_size
;
987 if (u
->hwbuf_size
> unused_nbytes
)
988 limit_nbytes
= u
->hwbuf_size
- unused_nbytes
;
992 if (rewind_nbytes
> limit_nbytes
)
993 rewind_nbytes
= limit_nbytes
;
995 if (rewind_nbytes
> 0) {
996 snd_pcm_sframes_t in_frames
, out_frames
;
998 pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes
);
1000 in_frames
= (snd_pcm_sframes_t
) rewind_nbytes
/ u
->frame_size
;
1001 pa_log_debug("before: %lu", (unsigned long) in_frames
);
1002 if ((out_frames
= snd_pcm_rewind(u
->pcm_handle
, in_frames
)) < 0) {
1003 pa_log("snd_pcm_rewind() failed: %s", snd_strerror(out_frames
));
1006 pa_log_debug("after: %lu", (unsigned long) out_frames
);
1008 rewind_nbytes
= out_frames
* u
->frame_size
;
1010 if (rewind_nbytes
<= 0)
1011 pa_log_info("Tried rewind, but was apparently not possible.");
1013 u
->frame_index
-= out_frames
;
1014 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes
);
1015 pa_sink_process_rewind(u
->sink
, rewind_nbytes
);
1017 u
->after_rewind
= TRUE
;
1021 pa_log_debug("Mhmm, actually there is nothing to rewind.");
1025 pa_sink_process_rewind(u
->sink
, 0);
1031 static void thread_func(void *userdata
) {
1032 struct userdata
*u
= userdata
;
1036 pa_log_debug("Thread starting up");
1038 if (u
->core
->realtime_scheduling
)
1039 pa_make_realtime(u
->core
->realtime_priority
);
1041 pa_thread_mq_install(&u
->thread_mq
);
1042 pa_rtpoll_install(u
->rtpoll
);
1047 /* pa_log_debug("loop"); */
1049 /* Render some data and write it to the dsp */
1050 if (PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
1052 pa_usec_t sleep_usec
= 0;
1054 if (u
->sink
->thread_info
.rewind_requested
)
1055 if (process_rewind(u
) < 0)
1059 work_done
= mmap_write(u
, &sleep_usec
);
1061 work_done
= unix_write(u
, &sleep_usec
);
1066 /* pa_log_debug("work_done = %i", work_done); */
1071 pa_log_info("Starting playback.");
1072 snd_pcm_start(u
->pcm_handle
);
1074 pa_smoother_resume(u
->smoother
, pa_rtclock_usec());
1080 if (u
->use_tsched
) {
1083 if (u
->since_start
<= u
->hwbuf_size
) {
1085 /* USB devices on ALSA seem to hit a buffer
1086 * underrun during the first iterations much
1087 * quicker then we calculate here, probably due to
1088 * the transport latency. To accomodate for that
1089 * we artificially decrease the sleep time until
1090 * we have filled the buffer at least once
1093 /*pa_log_debug("Cutting sleep time for the initial iterations by half.");*/
1097 /* OK, the playback buffer is now full, let's
1098 * calculate when to wake up next */
1099 /* pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
1101 /* Convert from the sound card time domain to the
1102 * system time domain */
1103 cusec
= pa_smoother_translate(u
->smoother
, pa_rtclock_usec(), sleep_usec
);
1105 /* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
1107 /* We don't trust the conversion, so we wake up whatever comes first */
1108 pa_rtpoll_set_timer_relative(u
->rtpoll
, PA_MIN(sleep_usec
, cusec
));
1112 u
->after_rewind
= FALSE
;
1114 } else if (u
->use_tsched
)
1116 /* OK, we're in an invalid state, let's disable our timers */
1117 pa_rtpoll_set_timer_disabled(u
->rtpoll
);
1119 /* Hmm, nothing to do. Let's sleep */
1120 if ((ret
= pa_rtpoll_run(u
->rtpoll
, 1)) < 0)
1126 /* Tell ALSA about this and process its response */
1127 if (PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
1128 struct pollfd
*pollfd
;
1129 unsigned short revents
= 0;
1133 pollfd
= pa_rtpoll_item_get_pollfd(u
->alsa_rtpoll_item
, &n
);
1135 if ((err
= snd_pcm_poll_descriptors_revents(u
->pcm_handle
, pollfd
, n
, &revents
)) < 0) {
1136 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err
));
1140 if (revents
& (POLLERR
|POLLNVAL
|POLLHUP
)) {
1141 if (pa_alsa_recover_from_poll(u
->pcm_handle
, revents
) < 0)
1148 if (revents
&& u
->use_tsched
)
1149 pa_log_debug("Wakeup from ALSA! (%i)", revents
);
1154 /* If this was no regular exit from the loop we have to continue
1155 * processing messages until we received PA_MESSAGE_SHUTDOWN */
1156 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
1157 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
1160 pa_log_debug("Thread shutting down");
1163 int pa__init(pa_module
*m
) {
1165 pa_modargs
*ma
= NULL
;
1166 struct userdata
*u
= NULL
;
1170 uint32_t nfrags
, hwbuf_size
, frag_size
, tsched_size
, tsched_watermark
;
1171 snd_pcm_uframes_t period_frames
, tsched_frames
;
1173 snd_pcm_info_t
*pcm_info
= NULL
;
1176 char *name_buf
= NULL
;
1177 pa_bool_t namereg_fail
;
1178 pa_bool_t use_mmap
= TRUE
, b
, use_tsched
= TRUE
, d
;
1180 pa_sink_new_data data
;
1182 snd_pcm_info_alloca(&pcm_info
);
1186 pa_alsa_redirect_errors_inc();
1188 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1189 pa_log("Failed to parse module arguments");
1193 ss
= m
->core
->default_sample_spec
;
1194 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_ALSA
) < 0) {
1195 pa_log("Failed to parse sample specification and channel map");
1199 frame_size
= pa_frame_size(&ss
);
1201 nfrags
= m
->core
->default_n_fragments
;
1202 frag_size
= pa_usec_to_bytes(m
->core
->default_fragment_size_msec
*PA_USEC_PER_MSEC
, &ss
);
1204 frag_size
= frame_size
;
1205 tsched_size
= pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC
, &ss
);
1206 tsched_watermark
= pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC
, &ss
);
1208 if (pa_modargs_get_value_u32(ma
, "fragments", &nfrags
) < 0 ||
1209 pa_modargs_get_value_u32(ma
, "fragment_size", &frag_size
) < 0 ||
1210 pa_modargs_get_value_u32(ma
, "tsched_buffer_size", &tsched_size
) < 0 ||
1211 pa_modargs_get_value_u32(ma
, "tsched_buffer_watermark", &tsched_watermark
) < 0) {
1212 pa_log("Failed to parse buffer metrics");
1216 hwbuf_size
= frag_size
* nfrags
;
1217 period_frames
= frag_size
/frame_size
;
1218 tsched_frames
= tsched_size
/frame_size
;
1220 if (pa_modargs_get_value_boolean(ma
, "mmap", &use_mmap
) < 0) {
1221 pa_log("Failed to parse mmap argument.");
1225 if (pa_modargs_get_value_boolean(ma
, "tsched", &use_tsched
) < 0) {
1226 pa_log("Failed to parse tsched argument.");
1230 if (use_tsched
&& !pa_rtclock_hrtimer()) {
1231 pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1235 u
= pa_xnew0(struct userdata
, 1);
1239 u
->use_mmap
= use_mmap
;
1240 u
->use_tsched
= use_tsched
;
1243 u
->after_rewind
= FALSE
;
1244 u
->rtpoll
= pa_rtpoll_new();
1245 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
1246 u
->alsa_rtpoll_item
= NULL
;
1248 u
->smoother
= pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC
*2, DEFAULT_TSCHED_BUFFER_USEC
*2, TRUE
, 5);
1249 usec
= pa_rtclock_usec();
1250 pa_smoother_set_time_offset(u
->smoother
, usec
);
1251 pa_smoother_pause(u
->smoother
, usec
);
1253 snd_config_update_free_global();
1258 if ((dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1260 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id(
1264 SND_PCM_STREAM_PLAYBACK
,
1265 &nfrags
, &period_frames
, tsched_frames
,
1272 if (!(u
->pcm_handle
= pa_alsa_open_by_device_string(
1273 pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
),
1276 SND_PCM_STREAM_PLAYBACK
,
1277 &nfrags
, &period_frames
, tsched_frames
,
1283 pa_assert(u
->device_name
);
1284 pa_log_info("Successfully opened device %s.", u
->device_name
);
1286 if (use_mmap
&& !b
) {
1287 pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
1288 u
->use_mmap
= use_mmap
= FALSE
;
1291 if (use_tsched
&& (!b
|| !d
)) {
1292 pa_log_info("Cannot enabled timer-based scheduling, falling back to sound IRQ scheduling.");
1293 u
->use_tsched
= use_tsched
= FALSE
;
1297 pa_log_info("Successfully enabled mmap() mode.");
1300 pa_log_info("Successfully enabled timer-based scheduling mode.");
1302 if ((err
= snd_pcm_info(u
->pcm_handle
, pcm_info
)) < 0) {
1303 pa_log("Error fetching PCM info: %s", snd_strerror(err
));
1307 /* ALSA might tweak the sample spec, so recalculate the frame size */
1308 frame_size
= pa_frame_size(&ss
);
1310 if ((err
= snd_mixer_open(&u
->mixer_handle
, 0)) < 0)
1311 pa_log_warn("Error opening mixer: %s", snd_strerror(err
));
1313 pa_bool_t found
= FALSE
;
1315 if (pa_alsa_prepare_mixer(u
->mixer_handle
, u
->device_name
) >= 0)
1318 snd_pcm_info_t
*info
;
1320 snd_pcm_info_alloca(&info
);
1322 if (snd_pcm_info(u
->pcm_handle
, info
) >= 0) {
1326 if ((card
= snd_pcm_info_get_card(info
)) >= 0) {
1328 md
= pa_sprintf_malloc("hw:%i", card
);
1330 if (strcmp(u
->device_name
, md
))
1331 if (pa_alsa_prepare_mixer(u
->mixer_handle
, md
) >= 0)
1339 if (!(u
->mixer_elem
= pa_alsa_find_elem(u
->mixer_handle
, "Master", "PCM")))
1343 snd_mixer_close(u
->mixer_handle
);
1344 u
->mixer_handle
= NULL
;
1348 if ((name
= pa_modargs_get_value(ma
, "sink_name", NULL
)))
1349 namereg_fail
= TRUE
;
1351 name
= name_buf
= pa_sprintf_malloc("alsa_output.%s", u
->device_name
);
1352 namereg_fail
= FALSE
;
1355 pa_sink_new_data_init(&data
);
1356 data
.driver
= __FILE__
;
1358 pa_sink_new_data_set_name(&data
, name
);
1359 data
.namereg_fail
= namereg_fail
;
1360 pa_sink_new_data_set_sample_spec(&data
, &ss
);
1361 pa_sink_new_data_set_channel_map(&data
, &map
);
1363 pa_alsa_init_proplist(data
.proplist
, pcm_info
);
1364 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
1365 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
* nfrags
));
1366 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
));
1367 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, u
->use_tsched
? "mmap+timer" : (u
->use_mmap
? "mmap" : "serial"));
1369 u
->sink
= pa_sink_new(m
->core
, &data
, PA_SINK_HARDWARE
|PA_SINK_LATENCY
);
1370 pa_sink_new_data_done(&data
);
1374 pa_log("Failed to create sink object");
1378 u
->sink
->parent
.process_msg
= sink_process_msg
;
1379 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1380 u
->sink
->userdata
= u
;
1382 pa_sink_set_asyncmsgq(u
->sink
, u
->thread_mq
.inq
);
1383 pa_sink_set_rtpoll(u
->sink
, u
->rtpoll
);
1385 u
->frame_size
= frame_size
;
1386 u
->fragment_size
= frag_size
= period_frames
* frame_size
;
1387 u
->nfragments
= nfrags
;
1388 u
->hwbuf_size
= u
->fragment_size
* nfrags
;
1389 u
->hwbuf_unused_frames
= 0;
1390 u
->tsched_watermark
= tsched_watermark
;
1392 u
->hw_dB_supported
= FALSE
;
1393 u
->hw_dB_min
= u
->hw_dB_max
= 0;
1394 u
->hw_volume_min
= u
->hw_volume_max
= 0;
1395 u
->mixer_seperate_channels
= FALSE
;
1396 pa_cvolume_mute(&u
->hardware_volume
, u
->sink
->sample_spec
.channels
);
1399 fix_tsched_watermark(u
);
1401 u
->sink
->thread_info
.max_rewind
= use_tsched
? u
->hwbuf_size
: 0;
1402 u
->sink
->thread_info
.max_request
= u
->hwbuf_size
;
1404 pa_sink_set_latency_range(u
->sink
,
1405 !use_tsched
? pa_bytes_to_usec(u
->hwbuf_size
, &ss
) : (pa_usec_t
) -1,
1406 pa_bytes_to_usec(u
->hwbuf_size
, &ss
));
1408 pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
1409 nfrags
, (long unsigned) u
->fragment_size
,
1410 (double) pa_bytes_to_usec(u
->hwbuf_size
, &ss
) / PA_USEC_PER_MSEC
);
1413 pa_log_info("Time scheduling watermark is %0.2fms",
1414 (double) pa_bytes_to_usec(u
->tsched_watermark
, &ss
) / PA_USEC_PER_MSEC
);
1416 if (update_sw_params(u
) < 0)
1419 pa_memchunk_reset(&u
->memchunk
);
1421 if (u
->mixer_handle
) {
1422 pa_assert(u
->mixer_elem
);
1424 if (snd_mixer_selem_has_playback_volume(u
->mixer_elem
)) {
1425 pa_bool_t suitable
= TRUE
;
1427 if (snd_mixer_selem_get_playback_volume_range(u
->mixer_elem
, &u
->hw_volume_min
, &u
->hw_volume_max
) < 0) {
1428 pa_log_info("Failed to get volume range. Falling back to software volume control.");
1431 pa_log_info("Volume ranges from %li to %li.", u
->hw_volume_min
, u
->hw_volume_max
);
1432 pa_assert(u
->hw_volume_min
< u
->hw_volume_max
);
1435 if (snd_mixer_selem_get_playback_dB_range(u
->mixer_elem
, &u
->hw_dB_min
, &u
->hw_dB_max
) < 0)
1436 pa_log_info("Mixer doesn't support dB information.");
1438 pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u
->hw_dB_min
/100.0, u
->hw_dB_max
/100.0);
1439 pa_assert(u
->hw_dB_min
< u
->hw_dB_max
);
1440 u
->hw_dB_supported
= TRUE
;
1444 !u
->hw_dB_supported
&&
1445 u
->hw_volume_max
- u
->hw_volume_min
< 3) {
1447 pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
1452 u
->mixer_seperate_channels
= pa_alsa_calc_mixer_map(u
->mixer_elem
, &map
, u
->mixer_map
, TRUE
) >= 0;
1454 u
->sink
->get_volume
= sink_get_volume_cb
;
1455 u
->sink
->set_volume
= sink_set_volume_cb
;
1456 u
->sink
->flags
|= PA_SINK_HW_VOLUME_CTRL
| (u
->hw_dB_supported
? PA_SINK_DECIBEL_VOLUME
: 0);
1457 pa_log_info("Using hardware volume control. Hardware dB scale %s.", u
->hw_dB_supported
? "supported" : "not supported");
1460 pa_log_info("Using software volume control.");
1463 if (snd_mixer_selem_has_playback_switch(u
->mixer_elem
)) {
1464 u
->sink
->get_mute
= sink_get_mute_cb
;
1465 u
->sink
->set_mute
= sink_set_mute_cb
;
1466 u
->sink
->flags
|= PA_SINK_HW_MUTE_CTRL
;
1468 pa_log_info("Using software mute control.");
1470 u
->mixer_fdl
= pa_alsa_fdlist_new();
1472 if (pa_alsa_fdlist_set_mixer(u
->mixer_fdl
, u
->mixer_handle
, m
->core
->mainloop
) < 0) {
1473 pa_log("Failed to initialize file descriptor monitoring");
1477 snd_mixer_elem_set_callback(u
->mixer_elem
, mixer_callback
);
1478 snd_mixer_elem_set_callback_private(u
->mixer_elem
, u
);
1480 u
->mixer_fdl
= NULL
;
1482 pa_alsa_dump(u
->pcm_handle
);
1484 if (!(u
->thread
= pa_thread_new(thread_func
, u
))) {
1485 pa_log("Failed to create thread.");
1489 /* Get initial mixer settings */
1490 if (data
.volume_is_set
) {
1491 if (u
->sink
->set_volume
)
1492 u
->sink
->set_volume(u
->sink
);
1494 if (u
->sink
->get_volume
)
1495 u
->sink
->get_volume(u
->sink
);
1498 if (data
.muted_is_set
) {
1499 if (u
->sink
->set_mute
)
1500 u
->sink
->set_mute(u
->sink
);
1502 if (u
->sink
->get_mute
)
1503 u
->sink
->get_mute(u
->sink
);
1506 pa_sink_put(u
->sink
);
1508 pa_modargs_free(ma
);
1515 pa_modargs_free(ma
);
1522 void pa__done(pa_module
*m
) {
1527 if (!(u
= m
->userdata
)) {
1528 pa_alsa_redirect_errors_dec();
1533 pa_sink_unlink(u
->sink
);
1536 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
1537 pa_thread_free(u
->thread
);
1540 pa_thread_mq_done(&u
->thread_mq
);
1543 pa_sink_unref(u
->sink
);
1545 if (u
->memchunk
.memblock
)
1546 pa_memblock_unref(u
->memchunk
.memblock
);
1548 if (u
->alsa_rtpoll_item
)
1549 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
1552 pa_rtpoll_free(u
->rtpoll
);
1555 pa_alsa_fdlist_free(u
->mixer_fdl
);
1557 if (u
->mixer_handle
)
1558 snd_mixer_close(u
->mixer_handle
);
1560 if (u
->pcm_handle
) {
1561 snd_pcm_drop(u
->pcm_handle
);
1562 snd_pcm_close(u
->pcm_handle
);
1566 pa_smoother_free(u
->smoother
);
1568 pa_xfree(u
->device_name
);
1571 snd_config_update_free_global();
1573 pa_alsa_redirect_errors_dec();