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>
38 #include <pulse/i18n.h>
40 #include <pulsecore/core.h>
41 #include <pulsecore/module.h>
42 #include <pulsecore/memchunk.h>
43 #include <pulsecore/sink.h>
44 #include <pulsecore/modargs.h>
45 #include <pulsecore/core-util.h>
46 #include <pulsecore/sample-util.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/macro.h>
49 #include <pulsecore/thread.h>
50 #include <pulsecore/core-error.h>
51 #include <pulsecore/thread-mq.h>
52 #include <pulsecore/rtpoll.h>
53 #include <pulsecore/rtclock.h>
54 #include <pulsecore/time-smoother.h>
56 #include "alsa-util.h"
57 #include "alsa-sink.h"
59 /* #define DEBUG_TIMING */
61 #define DEFAULT_DEVICE "default"
62 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC) /* 2s */
63 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms */
64 #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
65 #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms */
73 pa_thread_mq thread_mq
;
76 snd_pcm_t
*pcm_handle
;
78 pa_alsa_fdlist
*mixer_fdl
;
79 snd_mixer_t
*mixer_handle
;
80 snd_mixer_elem_t
*mixer_elem
;
81 long hw_volume_max
, hw_volume_min
;
82 long hw_dB_max
, hw_dB_min
;
83 pa_bool_t hw_dB_supported
:1;
84 pa_bool_t mixer_seperate_channels
:1;
85 pa_cvolume hardware_volume
;
87 size_t frame_size
, fragment_size
, hwbuf_size
, tsched_watermark
, hwbuf_unused
, min_sleep
, min_wakeup
;
93 pa_bool_t use_mmap
:1, use_tsched
:1;
95 pa_bool_t first
, after_rewind
;
97 pa_rtpoll_item
*alsa_rtpoll_item
;
99 snd_mixer_selem_channel_id_t mixer_map
[SND_MIXER_SCHN_LAST
];
101 pa_smoother
*smoother
;
102 uint64_t write_count
;
103 uint64_t since_start
;
106 static void userdata_free(struct userdata
*u
);
108 static void fix_min_sleep_wakeup(struct userdata
*u
) {
109 size_t max_use
, max_use_2
;
113 max_use
= u
->hwbuf_size
- u
->hwbuf_unused
;
114 max_use_2
= pa_frame_align(max_use
/2, &u
->sink
->sample_spec
);
116 u
->min_sleep
= pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC
, &u
->sink
->sample_spec
);
117 u
->min_sleep
= PA_CLAMP(u
->min_sleep
, u
->frame_size
, max_use_2
);
119 u
->min_wakeup
= pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC
, &u
->sink
->sample_spec
);
120 u
->min_wakeup
= PA_CLAMP(u
->min_wakeup
, u
->frame_size
, max_use_2
);
123 static void fix_tsched_watermark(struct userdata
*u
) {
127 max_use
= u
->hwbuf_size
- u
->hwbuf_unused
;
129 if (u
->tsched_watermark
> max_use
- u
->min_sleep
)
130 u
->tsched_watermark
= max_use
- u
->min_sleep
;
132 if (u
->tsched_watermark
< u
->min_wakeup
)
133 u
->tsched_watermark
= u
->min_wakeup
;
136 static void adjust_after_underrun(struct userdata
*u
) {
137 size_t old_watermark
;
138 pa_usec_t old_min_latency
, new_min_latency
;
142 /* First, just try to increase the watermark */
143 old_watermark
= u
->tsched_watermark
;
144 u
->tsched_watermark
*= 2;
145 fix_tsched_watermark(u
);
147 if (old_watermark
!= u
->tsched_watermark
) {
148 pa_log_notice("Increasing wakeup watermark to %0.2f ms",
149 (double) pa_bytes_to_usec(u
->tsched_watermark
, &u
->sink
->sample_spec
) / PA_USEC_PER_MSEC
);
153 /* Hmm, we cannot increase the watermark any further, hence let's raise the latency */
154 old_min_latency
= u
->sink
->thread_info
.min_latency
;
155 new_min_latency
= PA_MIN(old_min_latency
* 2, u
->sink
->thread_info
.max_latency
);
157 if (old_min_latency
!= new_min_latency
) {
158 pa_log_notice("Increasing minimal latency to %0.2f ms",
159 (double) new_min_latency
/ PA_USEC_PER_MSEC
);
161 pa_sink_update_latency_range(u
->sink
, new_min_latency
, u
->sink
->thread_info
.max_latency
);
165 /* When we reach this we're officialy fucked! */
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 wm
= pa_bytes_to_usec(u
->tsched_watermark
, &u
->sink
->sample_spec
);
186 *sleep_usec
= usec
- wm
;
190 pa_log_debug("Buffer time: %lu ms; Sleep time: %lu ms; Process time: %lu ms",
191 (unsigned long) (usec
/ PA_USEC_PER_MSEC
),
192 (unsigned long) (*sleep_usec
/ PA_USEC_PER_MSEC
),
193 (unsigned long) (*process_usec
/ PA_USEC_PER_MSEC
));
197 static int try_recover(struct userdata
*u
, const char *call
, int err
) {
202 pa_log_debug("%s: %s", call
, snd_strerror(err
));
204 pa_assert(err
!= -EAGAIN
);
207 pa_log_debug("%s: Buffer underrun!", call
);
209 if ((err
= snd_pcm_recover(u
->pcm_handle
, err
, 1)) < 0) {
210 pa_log("%s: %s", call
, snd_strerror(err
));
219 static size_t check_left_to_play(struct userdata
*u
, size_t n_bytes
) {
222 /* We use <= instead of < for this check here because an underrun
223 * only happens after the last sample was processed, not already when
224 * it is removed from the buffer. This is particularly important
225 * when block transfer is used. */
227 if (n_bytes
<= u
->hwbuf_size
) {
228 left_to_play
= u
->hwbuf_size
- n_bytes
;
231 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
);
241 if (!u
->first
&& !u
->after_rewind
) {
243 if (pa_log_ratelimit())
244 pa_log_info("Underrun!");
247 adjust_after_underrun(u
);
254 static int mmap_write(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
255 pa_bool_t work_done
= TRUE
;
256 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
260 pa_sink_assert_ref(u
->sink
);
263 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
270 /* First we determine how many samples are missing to fill the
271 * buffer up to 100% */
273 if (PA_UNLIKELY((n
= pa_alsa_safe_avail(u
->pcm_handle
, u
->hwbuf_size
, &u
->sink
->sample_spec
)) < 0)) {
275 if ((r
= try_recover(u
, "snd_pcm_avail", (int) n
)) == 0)
281 n_bytes
= (size_t) n
* u
->frame_size
;
284 pa_log_debug("avail: %lu", (unsigned long) n_bytes
);
287 left_to_play
= check_left_to_play(u
, n_bytes
);
291 /* We won't fill up the playback buffer before at least
292 * half the sleep time is over because otherwise we might
293 * ask for more data from the clients then they expect. We
294 * need to guarantee that clients only have to keep around
295 * a single hw buffer length. */
298 pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) > process_usec
+max_sleep_usec
/2) {
300 pa_log_debug("Not filling up, because too early.");
305 if (PA_UNLIKELY(n_bytes
<= u
->hwbuf_unused
)) {
309 char *dn
= pa_alsa_get_driver_name_by_pcm(u
->pcm_handle
);
310 pa_log(_("ALSA woke us up to write new data to the device, but there was actually nothing to write!\n"
311 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n"
312 "We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail."),
318 pa_log_debug("Not filling up, because not necessary.");
323 n_bytes
-= u
->hwbuf_unused
;
327 pa_log_debug("Filling up");
334 const snd_pcm_channel_area_t
*areas
;
335 snd_pcm_uframes_t offset
, frames
;
336 snd_pcm_sframes_t sframes
;
338 frames
= (snd_pcm_uframes_t
) (n_bytes
/ u
->frame_size
);
339 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
341 if (PA_UNLIKELY((err
= pa_alsa_safe_mmap_begin(u
->pcm_handle
, &areas
, &offset
, &frames
, u
->hwbuf_size
, &u
->sink
->sample_spec
)) < 0)) {
343 if ((r
= try_recover(u
, "snd_pcm_mmap_begin", err
)) == 0)
349 /* Make sure that if these memblocks need to be copied they will fit into one slot */
350 if (frames
> pa_mempool_block_size_max(u
->sink
->core
->mempool
)/u
->frame_size
)
351 frames
= pa_mempool_block_size_max(u
->sink
->core
->mempool
)/u
->frame_size
;
353 /* Check these are multiples of 8 bit */
354 pa_assert((areas
[0].first
& 7) == 0);
355 pa_assert((areas
[0].step
& 7)== 0);
357 /* We assume a single interleaved memory buffer */
358 pa_assert((areas
[0].first
>> 3) == 0);
359 pa_assert((areas
[0].step
>> 3) == u
->frame_size
);
361 p
= (uint8_t*) areas
[0].addr
+ (offset
* u
->frame_size
);
363 chunk
.memblock
= pa_memblock_new_fixed(u
->core
->mempool
, p
, frames
* u
->frame_size
, TRUE
);
364 chunk
.length
= pa_memblock_get_length(chunk
.memblock
);
367 pa_sink_render_into_full(u
->sink
, &chunk
);
368 pa_memblock_unref_fixed(chunk
.memblock
);
370 if (PA_UNLIKELY((sframes
= snd_pcm_mmap_commit(u
->pcm_handle
, offset
, frames
)) < 0)) {
372 if ((r
= try_recover(u
, "snd_pcm_mmap_commit", (int) sframes
)) == 0)
380 u
->write_count
+= frames
* u
->frame_size
;
381 u
->since_start
+= frames
* u
->frame_size
;
384 pa_log_debug("Wrote %lu bytes", (unsigned long) (frames
* u
->frame_size
));
387 if ((size_t) frames
* u
->frame_size
>= n_bytes
)
390 n_bytes
-= (size_t) frames
* u
->frame_size
;
394 *sleep_usec
= pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) - process_usec
;
395 return work_done
? 1 : 0;
398 static int unix_write(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
399 pa_bool_t work_done
= FALSE
;
400 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
404 pa_sink_assert_ref(u
->sink
);
407 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
414 if (PA_UNLIKELY((n
= pa_alsa_safe_avail(u
->pcm_handle
, u
->hwbuf_size
, &u
->sink
->sample_spec
)) < 0)) {
416 if ((r
= try_recover(u
, "snd_pcm_avail", (int) n
)) == 0)
422 n_bytes
= (size_t) n
* u
->frame_size
;
423 left_to_play
= check_left_to_play(u
, n_bytes
);
427 /* We won't fill up the playback buffer before at least
428 * half the sleep time is over because otherwise we might
429 * ask for more data from the clients then they expect. We
430 * need to guarantee that clients only have to keep around
431 * a single hw buffer length. */
434 pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) > process_usec
+max_sleep_usec
/2)
437 if (PA_UNLIKELY(n_bytes
<= u
->hwbuf_unused
)) {
441 char *dn
= pa_alsa_get_driver_name_by_pcm(u
->pcm_handle
);
442 pa_log(_("ALSA woke us up to write new data to the device, but there was actually nothing to write!\n"
443 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n"
444 "We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail."),
452 n_bytes
-= u
->hwbuf_unused
;
456 snd_pcm_sframes_t frames
;
459 /* pa_log_debug("%lu frames to write", (unsigned long) frames); */
461 if (u
->memchunk
.length
<= 0)
462 pa_sink_render(u
->sink
, n_bytes
, &u
->memchunk
);
464 pa_assert(u
->memchunk
.length
> 0);
466 frames
= (snd_pcm_sframes_t
) (u
->memchunk
.length
/ u
->frame_size
);
468 if (frames
> (snd_pcm_sframes_t
) (n_bytes
/u
->frame_size
))
469 frames
= (snd_pcm_sframes_t
) (n_bytes
/u
->frame_size
);
471 p
= pa_memblock_acquire(u
->memchunk
.memblock
);
472 frames
= snd_pcm_writei(u
->pcm_handle
, (const uint8_t*) p
+ u
->memchunk
.index
, (snd_pcm_uframes_t
) frames
);
473 pa_memblock_release(u
->memchunk
.memblock
);
475 pa_assert(frames
!= 0);
477 if (PA_UNLIKELY(frames
< 0)) {
479 if ((r
= try_recover(u
, "snd_pcm_writei", (int) frames
)) == 0)
485 u
->memchunk
.index
+= (size_t) frames
* u
->frame_size
;
486 u
->memchunk
.length
-= (size_t) frames
* u
->frame_size
;
488 if (u
->memchunk
.length
<= 0) {
489 pa_memblock_unref(u
->memchunk
.memblock
);
490 pa_memchunk_reset(&u
->memchunk
);
495 u
->write_count
+= frames
* u
->frame_size
;
496 u
->since_start
+= frames
* u
->frame_size
;
498 /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
500 if ((size_t) frames
* u
->frame_size
>= n_bytes
)
503 n_bytes
-= (size_t) frames
* u
->frame_size
;
507 *sleep_usec
= pa_bytes_to_usec(left_to_play
, &u
->sink
->sample_spec
) - process_usec
;
508 return work_done
? 1 : 0;
511 static void update_smoother(struct userdata
*u
) {
512 snd_pcm_sframes_t delay
= 0;
515 pa_usec_t now1
= 0, now2
;
516 snd_pcm_status_t
*status
;
518 snd_pcm_status_alloca(&status
);
521 pa_assert(u
->pcm_handle
);
523 /* Let's update the time smoother */
525 if (PA_UNLIKELY((err
= snd_pcm_delay(u
->pcm_handle
, &delay
)) < 0)) {
526 pa_log_warn("Failed to query DSP status data: %s", snd_strerror(err
));
530 if (PA_UNLIKELY((err
= snd_pcm_status(u
->pcm_handle
, status
)) < 0))
531 pa_log_warn("Failed to get timestamp: %s", snd_strerror(err
));
533 snd_htimestamp_t htstamp
= { 0, 0 };
534 snd_pcm_status_get_htstamp(status
, &htstamp
);
535 now1
= pa_timespec_load(&htstamp
);
538 position
= (int64_t) u
->write_count
- ((int64_t) delay
* (int64_t) u
->frame_size
);
540 if (PA_UNLIKELY(position
< 0))
543 /* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
545 now1
= pa_rtclock_usec();
547 now2
= pa_bytes_to_usec((uint64_t) position
, &u
->sink
->sample_spec
);
549 pa_smoother_put(u
->smoother
, now1
, now2
);
552 static pa_usec_t
sink_get_latency(struct userdata
*u
) {
555 pa_usec_t now1
, now2
;
559 now1
= pa_rtclock_usec();
560 now2
= pa_smoother_get(u
->smoother
, now1
);
562 delay
= (int64_t) pa_bytes_to_usec(u
->write_count
, &u
->sink
->sample_spec
) - (int64_t) now2
;
564 r
= delay
>= 0 ? (pa_usec_t
) delay
: 0;
566 if (u
->memchunk
.memblock
)
567 r
+= pa_bytes_to_usec(u
->memchunk
.length
, &u
->sink
->sample_spec
);
572 static int build_pollfd(struct userdata
*u
) {
574 pa_assert(u
->pcm_handle
);
576 if (u
->alsa_rtpoll_item
)
577 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
579 if (!(u
->alsa_rtpoll_item
= pa_alsa_build_pollfd(u
->pcm_handle
, u
->rtpoll
)))
585 static int suspend(struct userdata
*u
) {
587 pa_assert(u
->pcm_handle
);
589 pa_smoother_pause(u
->smoother
, pa_rtclock_usec());
591 /* Let's suspend -- we don't call snd_pcm_drain() here since that might
592 * take awfully long with our long buffer sizes today. */
593 snd_pcm_close(u
->pcm_handle
);
594 u
->pcm_handle
= NULL
;
596 if (u
->alsa_rtpoll_item
) {
597 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
598 u
->alsa_rtpoll_item
= NULL
;
601 pa_log_info("Device suspended...");
606 static int update_sw_params(struct userdata
*u
) {
607 snd_pcm_uframes_t avail_min
;
612 /* Use the full buffer if noone asked us for anything specific */
618 if ((latency
= pa_sink_get_requested_latency_within_thread(u
->sink
)) != (pa_usec_t
) -1) {
621 pa_log_debug("Latency set to %0.2fms", (double) latency
/ PA_USEC_PER_MSEC
);
623 b
= pa_usec_to_bytes(latency
, &u
->sink
->sample_spec
);
625 /* We need at least one sample in our buffer */
627 if (PA_UNLIKELY(b
< u
->frame_size
))
630 u
->hwbuf_unused
= PA_LIKELY(b
< u
->hwbuf_size
) ? (u
->hwbuf_size
- b
) : 0;
633 fix_min_sleep_wakeup(u
);
634 fix_tsched_watermark(u
);
637 pa_log_debug("hwbuf_unused=%lu", (unsigned long) u
->hwbuf_unused
);
639 /* We need at last one frame in the used part of the buffer */
640 avail_min
= (snd_pcm_uframes_t
) u
->hwbuf_unused
/ u
->frame_size
+ 1;
643 pa_usec_t sleep_usec
, process_usec
;
645 hw_sleep_time(u
, &sleep_usec
, &process_usec
);
646 avail_min
+= pa_usec_to_bytes(sleep_usec
, &u
->sink
->sample_spec
) / u
->frame_size
;
649 pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min
);
651 if ((err
= pa_alsa_set_sw_params(u
->pcm_handle
, avail_min
)) < 0) {
652 pa_log("Failed to set software parameters: %s", snd_strerror(err
));
656 pa_sink_set_max_request(u
->sink
, u
->hwbuf_size
- u
->hwbuf_unused
);
661 static int unsuspend(struct userdata
*u
) {
666 snd_pcm_uframes_t period_size
;
669 pa_assert(!u
->pcm_handle
);
671 pa_log_info("Trying resume...");
673 snd_config_update_free_global();
674 if ((err
= snd_pcm_open(&u
->pcm_handle
, u
->device_name
, SND_PCM_STREAM_PLAYBACK
,
675 /*SND_PCM_NONBLOCK|*/
676 SND_PCM_NO_AUTO_RESAMPLE
|
677 SND_PCM_NO_AUTO_CHANNELS
|
678 SND_PCM_NO_AUTO_FORMAT
)) < 0) {
679 pa_log("Error opening PCM device %s: %s", u
->device_name
, snd_strerror(err
));
683 ss
= u
->sink
->sample_spec
;
684 nfrags
= u
->nfragments
;
685 period_size
= u
->fragment_size
/ u
->frame_size
;
689 if ((err
= pa_alsa_set_hw_params(u
->pcm_handle
, &ss
, &nfrags
, &period_size
, u
->hwbuf_size
/ u
->frame_size
, &b
, &d
, TRUE
)) < 0) {
690 pa_log("Failed to set hardware parameters: %s", snd_strerror(err
));
694 if (b
!= u
->use_mmap
|| d
!= u
->use_tsched
) {
695 pa_log_warn("Resume failed, couldn't get original access mode.");
699 if (!pa_sample_spec_equal(&ss
, &u
->sink
->sample_spec
)) {
700 pa_log_warn("Resume failed, couldn't restore original sample settings.");
704 if (nfrags
!= u
->nfragments
|| period_size
*u
->frame_size
!= u
->fragment_size
) {
705 pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
706 (unsigned long) u
->nfragments
, (unsigned long) u
->fragment_size
,
707 (unsigned long) nfrags
, period_size
* u
->frame_size
);
711 if (update_sw_params(u
) < 0)
714 if (build_pollfd(u
) < 0)
720 pa_log_info("Resumed successfully...");
726 snd_pcm_close(u
->pcm_handle
);
727 u
->pcm_handle
= NULL
;
733 static int sink_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
734 struct userdata
*u
= PA_SINK(o
)->userdata
;
738 case PA_SINK_MESSAGE_GET_LATENCY
: {
742 r
= sink_get_latency(u
);
744 *((pa_usec_t
*) data
) = r
;
749 case PA_SINK_MESSAGE_SET_STATE
:
751 switch ((pa_sink_state_t
) PA_PTR_TO_UINT(data
)) {
753 case PA_SINK_SUSPENDED
:
754 pa_assert(PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
));
762 case PA_SINK_RUNNING
:
764 if (u
->sink
->thread_info
.state
== PA_SINK_INIT
) {
765 if (build_pollfd(u
) < 0)
769 if (u
->sink
->thread_info
.state
== PA_SINK_SUSPENDED
) {
770 if (unsuspend(u
) < 0)
776 case PA_SINK_UNLINKED
:
778 case PA_SINK_INVALID_STATE
:
785 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
788 static int mixer_callback(snd_mixer_elem_t
*elem
, unsigned int mask
) {
789 struct userdata
*u
= snd_mixer_elem_get_callback_private(elem
);
792 pa_assert(u
->mixer_handle
);
794 if (mask
== SND_CTL_EVENT_MASK_REMOVE
)
797 if (mask
& SND_CTL_EVENT_MASK_VALUE
) {
798 pa_sink_get_volume(u
->sink
, TRUE
);
799 pa_sink_get_mute(u
->sink
, TRUE
);
805 static pa_volume_t
from_alsa_volume(struct userdata
*u
, long alsa_vol
) {
807 return (pa_volume_t
) round(((double) (alsa_vol
- u
->hw_volume_min
) * PA_VOLUME_NORM
) /
808 (double) (u
->hw_volume_max
- u
->hw_volume_min
));
811 static long to_alsa_volume(struct userdata
*u
, pa_volume_t vol
) {
814 alsa_vol
= (long) round(((double) vol
* (double) (u
->hw_volume_max
- u
->hw_volume_min
))
815 / PA_VOLUME_NORM
) + u
->hw_volume_min
;
817 return PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_volume_min
, u
->hw_volume_max
);
820 static void sink_get_volume_cb(pa_sink
*s
) {
821 struct userdata
*u
= s
->userdata
;
825 char t
[PA_CVOLUME_SNPRINT_MAX
];
828 pa_assert(u
->mixer_elem
);
830 if (u
->mixer_seperate_channels
) {
832 r
.channels
= s
->sample_spec
.channels
;
834 for (i
= 0; i
< s
->sample_spec
.channels
; i
++) {
837 if (u
->hw_dB_supported
) {
839 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
842 #ifdef HAVE_VALGRIND_MEMCHECK_H
843 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol
, sizeof(alsa_vol
));
846 r
.values
[i
] = pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0);
849 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
852 r
.values
[i
] = from_alsa_volume(u
, alsa_vol
);
859 if (u
->hw_dB_supported
) {
861 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
864 #ifdef HAVE_VALGRIND_MEMCHECK_H
865 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol
, sizeof(alsa_vol
));
868 pa_cvolume_set(&r
, s
->sample_spec
.channels
, pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0));
872 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
875 pa_cvolume_set(&r
, s
->sample_spec
.channels
, from_alsa_volume(u
, alsa_vol
));
879 pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
881 if (!pa_cvolume_equal(&u
->hardware_volume
, &r
)) {
883 s
->virtual_volume
= u
->hardware_volume
= r
;
885 if (u
->hw_dB_supported
) {
888 /* Hmm, so the hardware volume changed, let's reset our software volume */
889 pa_cvolume_reset(&reset
, s
->sample_spec
.channels
);
890 pa_sink_set_soft_volume(s
, &reset
);
897 pa_log_error("Unable to read volume: %s", snd_strerror(err
));
900 static void sink_set_volume_cb(pa_sink
*s
) {
901 struct userdata
*u
= s
->userdata
;
907 pa_assert(u
->mixer_elem
);
909 if (u
->mixer_seperate_channels
) {
911 r
.channels
= s
->sample_spec
.channels
;
913 for (i
= 0; i
< s
->sample_spec
.channels
; i
++) {
917 vol
= s
->virtual_volume
.values
[i
];
919 if (u
->hw_dB_supported
) {
921 alsa_vol
= (long) (pa_sw_volume_to_dB(vol
) * 100);
922 alsa_vol
+= u
->hw_dB_max
;
923 alsa_vol
= PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_dB_min
, u
->hw_dB_max
);
925 if ((err
= snd_mixer_selem_set_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], alsa_vol
, 1)) < 0)
928 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
931 #ifdef HAVE_VALGRIND_MEMCHECK_H
932 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol
, sizeof(alsa_vol
));
935 r
.values
[i
] = pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0);
938 alsa_vol
= to_alsa_volume(u
, vol
);
940 if ((err
= snd_mixer_selem_set_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], alsa_vol
)) < 0)
943 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, u
->mixer_map
[i
], &alsa_vol
)) < 0)
946 r
.values
[i
] = from_alsa_volume(u
, alsa_vol
);
954 vol
= pa_cvolume_max(&s
->virtual_volume
);
956 if (u
->hw_dB_supported
) {
957 alsa_vol
= (long) (pa_sw_volume_to_dB(vol
) * 100);
958 alsa_vol
+= u
->hw_dB_max
;
959 alsa_vol
= PA_CLAMP_UNLIKELY(alsa_vol
, u
->hw_dB_min
, u
->hw_dB_max
);
961 if ((err
= snd_mixer_selem_set_playback_dB_all(u
->mixer_elem
, alsa_vol
, 1)) < 0)
964 if ((err
= snd_mixer_selem_get_playback_dB(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
967 #ifdef HAVE_VALGRIND_MEMCHECK_H
968 VALGRIND_MAKE_MEM_DEFINED(&alsa_vol
, sizeof(alsa_vol
));
971 pa_cvolume_set(&r
, s
->sample_spec
.channels
, pa_sw_volume_from_dB((double) (alsa_vol
- u
->hw_dB_max
) / 100.0));
974 alsa_vol
= to_alsa_volume(u
, vol
);
976 if ((err
= snd_mixer_selem_set_playback_volume_all(u
->mixer_elem
, alsa_vol
)) < 0)
979 if ((err
= snd_mixer_selem_get_playback_volume(u
->mixer_elem
, SND_MIXER_SCHN_MONO
, &alsa_vol
)) < 0)
982 pa_cvolume_set(&r
, s
->sample_spec
.channels
, from_alsa_volume(u
, alsa_vol
));
986 u
->hardware_volume
= r
;
988 if (u
->hw_dB_supported
) {
989 char t
[PA_CVOLUME_SNPRINT_MAX
];
991 /* Match exactly what the user requested by software */
992 pa_sw_cvolume_divide(&s
->soft_volume
, &s
->virtual_volume
, &u
->hardware_volume
);
994 pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->virtual_volume
));
995 pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &u
->hardware_volume
));
996 pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->soft_volume
));
1000 /* We can't match exactly what the user requested, hence let's
1001 * at least tell the user about it */
1003 s
->virtual_volume
= r
;
1008 pa_log_error("Unable to set volume: %s", snd_strerror(err
));
1011 static void sink_get_mute_cb(pa_sink
*s
) {
1012 struct userdata
*u
= s
->userdata
;
1016 pa_assert(u
->mixer_elem
);
1018 if ((err
= snd_mixer_selem_get_playback_switch(u
->mixer_elem
, 0, &sw
)) < 0) {
1019 pa_log_error("Unable to get switch: %s", snd_strerror(err
));
1026 static void sink_set_mute_cb(pa_sink
*s
) {
1027 struct userdata
*u
= s
->userdata
;
1031 pa_assert(u
->mixer_elem
);
1033 if ((err
= snd_mixer_selem_set_playback_switch_all(u
->mixer_elem
, !s
->muted
)) < 0) {
1034 pa_log_error("Unable to set switch: %s", snd_strerror(err
));
1039 static void sink_update_requested_latency_cb(pa_sink
*s
) {
1040 struct userdata
*u
= s
->userdata
;
1047 before
= u
->hwbuf_unused
;
1048 update_sw_params(u
);
1050 /* Let's check whether we now use only a smaller part of the
1051 buffer then before. If so, we need to make sure that subsequent
1052 rewinds are relative to the new maxium fill level and not to the
1053 current fill level. Thus, let's do a full rewind once, to clear
1056 if (u
->hwbuf_unused
> before
) {
1057 pa_log_debug("Requesting rewind due to latency change.");
1058 pa_sink_request_rewind(s
, (size_t) -1);
1062 static int process_rewind(struct userdata
*u
) {
1063 snd_pcm_sframes_t unused
;
1064 size_t rewind_nbytes
, unused_nbytes
, limit_nbytes
;
1067 /* Figure out how much we shall rewind and reset the counter */
1068 rewind_nbytes
= u
->sink
->thread_info
.rewind_nbytes
;
1069 u
->sink
->thread_info
.rewind_nbytes
= 0;
1071 if (rewind_nbytes
<= 0)
1074 pa_assert(rewind_nbytes
> 0);
1075 pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes
);
1077 snd_pcm_hwsync(u
->pcm_handle
);
1078 if ((unused
= snd_pcm_avail_update(u
->pcm_handle
)) < 0) {
1079 pa_log("snd_pcm_avail_update() failed: %s", snd_strerror((int) unused
));
1083 unused_nbytes
= u
->tsched_watermark
+ (size_t) unused
* u
->frame_size
;
1085 if (u
->hwbuf_size
> unused_nbytes
)
1086 limit_nbytes
= u
->hwbuf_size
- unused_nbytes
;
1090 if (rewind_nbytes
> limit_nbytes
)
1091 rewind_nbytes
= limit_nbytes
;
1093 if (rewind_nbytes
> 0) {
1094 snd_pcm_sframes_t in_frames
, out_frames
;
1096 pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes
);
1098 in_frames
= (snd_pcm_sframes_t
) (rewind_nbytes
/ u
->frame_size
);
1099 pa_log_debug("before: %lu", (unsigned long) in_frames
);
1100 if ((out_frames
= snd_pcm_rewind(u
->pcm_handle
, (snd_pcm_uframes_t
) in_frames
)) < 0) {
1101 pa_log("snd_pcm_rewind() failed: %s", snd_strerror((int) out_frames
));
1104 pa_log_debug("after: %lu", (unsigned long) out_frames
);
1106 rewind_nbytes
= (size_t) out_frames
* u
->frame_size
;
1108 if (rewind_nbytes
<= 0)
1109 pa_log_info("Tried rewind, but was apparently not possible.");
1111 u
->write_count
-= out_frames
* u
->frame_size
;
1112 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes
);
1113 pa_sink_process_rewind(u
->sink
, rewind_nbytes
);
1115 u
->after_rewind
= TRUE
;
1119 pa_log_debug("Mhmm, actually there is nothing to rewind.");
1123 pa_sink_process_rewind(u
->sink
, 0);
1129 static void thread_func(void *userdata
) {
1130 struct userdata
*u
= userdata
;
1131 unsigned short revents
= 0;
1135 pa_log_debug("Thread starting up");
1137 if (u
->core
->realtime_scheduling
)
1138 pa_make_realtime(u
->core
->realtime_priority
);
1140 pa_thread_mq_install(&u
->thread_mq
);
1141 pa_rtpoll_install(u
->rtpoll
);
1147 pa_log_debug("Loop");
1150 /* Render some data and write it to the dsp */
1151 if (PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
1153 pa_usec_t sleep_usec
= 0;
1155 if (u
->sink
->thread_info
.rewind_requested
)
1156 if (process_rewind(u
) < 0)
1160 work_done
= mmap_write(u
, &sleep_usec
, revents
& POLLOUT
);
1162 work_done
= unix_write(u
, &sleep_usec
, revents
& POLLOUT
);
1167 /* pa_log_debug("work_done = %i", work_done); */
1172 pa_log_info("Starting playback.");
1173 snd_pcm_start(u
->pcm_handle
);
1175 pa_smoother_resume(u
->smoother
, pa_rtclock_usec());
1181 if (u
->use_tsched
) {
1184 if (u
->since_start
<= u
->hwbuf_size
) {
1186 /* USB devices on ALSA seem to hit a buffer
1187 * underrun during the first iterations much
1188 * quicker then we calculate here, probably due to
1189 * the transport latency. To accomodate for that
1190 * we artificially decrease the sleep time until
1191 * we have filled the buffer at least once
1194 pa_log_debug("Cutting sleep time for the initial iterations by half.");
1198 /* OK, the playback buffer is now full, let's
1199 * calculate when to wake up next */
1200 /* pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
1202 /* Convert from the sound card time domain to the
1203 * system time domain */
1204 cusec
= pa_smoother_translate(u
->smoother
, pa_rtclock_usec(), sleep_usec
);
1206 /* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
1208 /* We don't trust the conversion, so we wake up whatever comes first */
1209 pa_rtpoll_set_timer_relative(u
->rtpoll
, PA_MIN(sleep_usec
, cusec
));
1213 u
->after_rewind
= FALSE
;
1215 } else if (u
->use_tsched
)
1217 /* OK, we're in an invalid state, let's disable our timers */
1218 pa_rtpoll_set_timer_disabled(u
->rtpoll
);
1220 /* Hmm, nothing to do. Let's sleep */
1221 if ((ret
= pa_rtpoll_run(u
->rtpoll
, TRUE
)) < 0)
1227 /* Tell ALSA about this and process its response */
1228 if (PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
1229 struct pollfd
*pollfd
;
1233 pollfd
= pa_rtpoll_item_get_pollfd(u
->alsa_rtpoll_item
, &n
);
1235 if ((err
= snd_pcm_poll_descriptors_revents(u
->pcm_handle
, pollfd
, n
, &revents
)) < 0) {
1236 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err
));
1240 if (revents
& ~POLLOUT
) {
1241 if (pa_alsa_recover_from_poll(u
->pcm_handle
, revents
) < 0)
1246 } else if (revents
&& u
->use_tsched
&& pa_log_ratelimit())
1247 pa_log_debug("Wakeup from ALSA!");
1254 /* If this was no regular exit from the loop we have to continue
1255 * processing messages until we received PA_MESSAGE_SHUTDOWN */
1256 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
1257 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
1260 pa_log_debug("Thread shutting down");
1263 static void set_sink_name(pa_sink_new_data
*data
, pa_modargs
*ma
, const char *device_id
, const char *device_name
) {
1269 pa_assert(device_name
);
1271 if ((n
= pa_modargs_get_value(ma
, "sink_name", NULL
))) {
1272 pa_sink_new_data_set_name(data
, n
);
1273 data
->namereg_fail
= TRUE
;
1277 if ((n
= pa_modargs_get_value(ma
, "name", NULL
)))
1278 data
->namereg_fail
= TRUE
;
1280 n
= device_id
? device_id
: device_name
;
1281 data
->namereg_fail
= FALSE
;
1284 t
= pa_sprintf_malloc("alsa_output.%s", n
);
1285 pa_sink_new_data_set_name(data
, t
);
1289 static int setup_mixer(struct userdata
*u
, pa_bool_t ignore_dB
) {
1292 if (!u
->mixer_handle
)
1295 pa_assert(u
->mixer_elem
);
1297 if (snd_mixer_selem_has_playback_volume(u
->mixer_elem
)) {
1298 pa_bool_t suitable
= FALSE
;
1300 if (snd_mixer_selem_get_playback_volume_range(u
->mixer_elem
, &u
->hw_volume_min
, &u
->hw_volume_max
) < 0)
1301 pa_log_info("Failed to get volume range. Falling back to software volume control.");
1302 else if (u
->hw_volume_min
>= u
->hw_volume_max
)
1303 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
);
1305 pa_log_info("Volume ranges from %li to %li.", u
->hw_volume_min
, u
->hw_volume_max
);
1310 if (ignore_dB
|| snd_mixer_selem_get_playback_dB_range(u
->mixer_elem
, &u
->hw_dB_min
, &u
->hw_dB_max
) < 0)
1311 pa_log_info("Mixer doesn't support dB information or data is ignored.");
1313 #ifdef HAVE_VALGRIND_MEMCHECK_H
1314 VALGRIND_MAKE_MEM_DEFINED(&u
->hw_dB_min
, sizeof(u
->hw_dB_min
));
1315 VALGRIND_MAKE_MEM_DEFINED(&u
->hw_dB_max
, sizeof(u
->hw_dB_max
));
1318 if (u
->hw_dB_min
>= u
->hw_dB_max
)
1319 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);
1321 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);
1322 u
->hw_dB_supported
= TRUE
;
1324 if (u
->hw_dB_max
> 0) {
1325 u
->sink
->base_volume
= pa_sw_volume_from_dB(- (double) u
->hw_dB_max
/100.0);
1326 pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u
->sink
->base_volume
));
1328 pa_log_info("No particular base volume set, fixing to 0 dB");
1332 if (!u
->hw_dB_supported
&&
1333 u
->hw_volume_max
- u
->hw_volume_min
< 3) {
1335 pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
1341 u
->mixer_seperate_channels
= pa_alsa_calc_mixer_map(u
->mixer_elem
, &u
->sink
->channel_map
, u
->mixer_map
, TRUE
) >= 0;
1343 u
->sink
->get_volume
= sink_get_volume_cb
;
1344 u
->sink
->set_volume
= sink_set_volume_cb
;
1345 u
->sink
->flags
|= PA_SINK_HW_VOLUME_CTRL
| (u
->hw_dB_supported
? PA_SINK_DECIBEL_VOLUME
: 0);
1346 pa_log_info("Using hardware volume control. Hardware dB scale %s.", u
->hw_dB_supported
? "supported" : "not supported");
1348 if (!u
->hw_dB_supported
)
1349 u
->sink
->n_volume_steps
= u
->hw_volume_max
- u
->hw_volume_min
+ 1;
1351 pa_log_info("Using software volume control.");
1354 if (snd_mixer_selem_has_playback_switch(u
->mixer_elem
)) {
1355 u
->sink
->get_mute
= sink_get_mute_cb
;
1356 u
->sink
->set_mute
= sink_set_mute_cb
;
1357 u
->sink
->flags
|= PA_SINK_HW_MUTE_CTRL
;
1359 pa_log_info("Using software mute control.");
1361 u
->mixer_fdl
= pa_alsa_fdlist_new();
1363 if (pa_alsa_fdlist_set_mixer(u
->mixer_fdl
, u
->mixer_handle
, u
->core
->mainloop
) < 0) {
1364 pa_log("Failed to initialize file descriptor monitoring");
1368 snd_mixer_elem_set_callback(u
->mixer_elem
, mixer_callback
);
1369 snd_mixer_elem_set_callback_private(u
->mixer_elem
, u
);
1374 pa_sink
*pa_alsa_sink_new(pa_module
*m
, pa_modargs
*ma
, const char*driver
, pa_card
*card
, const pa_alsa_profile_info
*profile
) {
1376 struct userdata
*u
= NULL
;
1377 const char *dev_id
= NULL
;
1380 uint32_t nfrags
, hwbuf_size
, frag_size
, tsched_size
, tsched_watermark
;
1381 snd_pcm_uframes_t period_frames
, tsched_frames
;
1383 pa_bool_t use_mmap
= TRUE
, b
, use_tsched
= TRUE
, d
, ignore_dB
= FALSE
;
1385 pa_sink_new_data data
;
1390 ss
= m
->core
->default_sample_spec
;
1391 map
= m
->core
->default_channel_map
;
1392 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_ALSA
) < 0) {
1393 pa_log("Failed to parse sample specification and channel map");
1397 frame_size
= pa_frame_size(&ss
);
1399 nfrags
= m
->core
->default_n_fragments
;
1400 frag_size
= (uint32_t) pa_usec_to_bytes(m
->core
->default_fragment_size_msec
*PA_USEC_PER_MSEC
, &ss
);
1402 frag_size
= (uint32_t) frame_size
;
1403 tsched_size
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC
, &ss
);
1404 tsched_watermark
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC
, &ss
);
1406 if (pa_modargs_get_value_u32(ma
, "fragments", &nfrags
) < 0 ||
1407 pa_modargs_get_value_u32(ma
, "fragment_size", &frag_size
) < 0 ||
1408 pa_modargs_get_value_u32(ma
, "tsched_buffer_size", &tsched_size
) < 0 ||
1409 pa_modargs_get_value_u32(ma
, "tsched_buffer_watermark", &tsched_watermark
) < 0) {
1410 pa_log("Failed to parse buffer metrics");
1414 hwbuf_size
= frag_size
* nfrags
;
1415 period_frames
= frag_size
/frame_size
;
1416 tsched_frames
= tsched_size
/frame_size
;
1418 if (pa_modargs_get_value_boolean(ma
, "mmap", &use_mmap
) < 0) {
1419 pa_log("Failed to parse mmap argument.");
1423 if (pa_modargs_get_value_boolean(ma
, "tsched", &use_tsched
) < 0) {
1424 pa_log("Failed to parse tsched argument.");
1428 if (pa_modargs_get_value_boolean(ma
, "ignore_dB", &ignore_dB
) < 0) {
1429 pa_log("Failed to parse ignore_dB argument.");
1433 if (use_tsched
&& !pa_rtclock_hrtimer()) {
1434 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1438 u
= pa_xnew0(struct userdata
, 1);
1441 u
->use_mmap
= use_mmap
;
1442 u
->use_tsched
= use_tsched
;
1444 u
->rtpoll
= pa_rtpoll_new();
1445 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
1447 u
->smoother
= pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC
*2, DEFAULT_TSCHED_BUFFER_USEC
*2, TRUE
, 5);
1448 usec
= pa_rtclock_usec();
1449 pa_smoother_set_time_offset(u
->smoother
, usec
);
1450 pa_smoother_pause(u
->smoother
, usec
);
1457 if (!(dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1458 pa_log("device_id= not set");
1462 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id_profile(
1466 SND_PCM_STREAM_PLAYBACK
,
1467 &nfrags
, &period_frames
, tsched_frames
,
1472 } else if ((dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1474 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id_auto(
1478 SND_PCM_STREAM_PLAYBACK
,
1479 &nfrags
, &period_frames
, tsched_frames
,
1486 if (!(u
->pcm_handle
= pa_alsa_open_by_device_string(
1487 pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
),
1490 SND_PCM_STREAM_PLAYBACK
,
1491 &nfrags
, &period_frames
, tsched_frames
,
1497 pa_assert(u
->device_name
);
1498 pa_log_info("Successfully opened device %s.", u
->device_name
);
1501 pa_log_info("Selected configuration '%s' (%s).", profile
->description
, profile
->name
);
1503 if (use_mmap
&& !b
) {
1504 pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
1505 u
->use_mmap
= use_mmap
= FALSE
;
1508 if (use_tsched
&& (!b
|| !d
)) {
1509 pa_log_info("Cannot enable timer-based scheduling, falling back to sound IRQ scheduling.");
1510 u
->use_tsched
= use_tsched
= FALSE
;
1514 pa_log_info("Successfully enabled mmap() mode.");
1517 pa_log_info("Successfully enabled timer-based scheduling mode.");
1519 /* ALSA might tweak the sample spec, so recalculate the frame size */
1520 frame_size
= pa_frame_size(&ss
);
1522 pa_alsa_find_mixer_and_elem(u
->pcm_handle
, &u
->mixer_handle
, &u
->mixer_elem
);
1524 pa_sink_new_data_init(&data
);
1525 data
.driver
= driver
;
1528 set_sink_name(&data
, ma
, dev_id
, u
->device_name
);
1529 pa_sink_new_data_set_sample_spec(&data
, &ss
);
1530 pa_sink_new_data_set_channel_map(&data
, &map
);
1532 pa_alsa_init_proplist_pcm(m
->core
, data
.proplist
, u
->pcm_handle
);
1533 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
1534 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
* nfrags
));
1535 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
));
1536 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, u
->use_tsched
? "mmap+timer" : (u
->use_mmap
? "mmap" : "serial"));
1539 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_NAME
, profile
->name
);
1540 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
, profile
->description
);
1543 u
->sink
= pa_sink_new(m
->core
, &data
, PA_SINK_HARDWARE
|PA_SINK_LATENCY
);
1544 pa_sink_new_data_done(&data
);
1547 pa_log("Failed to create sink object");
1551 u
->sink
->parent
.process_msg
= sink_process_msg
;
1552 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1553 u
->sink
->userdata
= u
;
1555 pa_sink_set_asyncmsgq(u
->sink
, u
->thread_mq
.inq
);
1556 pa_sink_set_rtpoll(u
->sink
, u
->rtpoll
);
1558 u
->frame_size
= frame_size
;
1559 u
->fragment_size
= frag_size
= (uint32_t) (period_frames
* frame_size
);
1560 u
->nfragments
= nfrags
;
1561 u
->hwbuf_size
= u
->fragment_size
* nfrags
;
1562 u
->tsched_watermark
= tsched_watermark
;
1563 pa_cvolume_mute(&u
->hardware_volume
, u
->sink
->sample_spec
.channels
);
1566 fix_min_sleep_wakeup(u
);
1567 fix_tsched_watermark(u
);
1570 u
->sink
->thread_info
.max_rewind
= use_tsched
? u
->hwbuf_size
: 0;
1571 u
->sink
->thread_info
.max_request
= u
->hwbuf_size
;
1573 pa_sink_set_latency_range(u
->sink
,
1574 !use_tsched
? pa_bytes_to_usec(u
->hwbuf_size
, &ss
) : (pa_usec_t
) -1,
1575 pa_bytes_to_usec(u
->hwbuf_size
, &ss
));
1577 pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
1578 nfrags
, (long unsigned) u
->fragment_size
,
1579 (double) pa_bytes_to_usec(u
->hwbuf_size
, &ss
) / PA_USEC_PER_MSEC
);
1582 pa_log_info("Time scheduling watermark is %0.2fms",
1583 (double) pa_bytes_to_usec(u
->tsched_watermark
, &ss
) / PA_USEC_PER_MSEC
);
1585 if (update_sw_params(u
) < 0)
1588 if (setup_mixer(u
, ignore_dB
) < 0)
1591 pa_alsa_dump(u
->pcm_handle
);
1593 if (!(u
->thread
= pa_thread_new(thread_func
, u
))) {
1594 pa_log("Failed to create thread.");
1598 /* Get initial mixer settings */
1599 if (data
.volume_is_set
) {
1600 if (u
->sink
->set_volume
)
1601 u
->sink
->set_volume(u
->sink
);
1603 if (u
->sink
->get_volume
)
1604 u
->sink
->get_volume(u
->sink
);
1607 if (data
.muted_is_set
) {
1608 if (u
->sink
->set_mute
)
1609 u
->sink
->set_mute(u
->sink
);
1611 if (u
->sink
->get_mute
)
1612 u
->sink
->get_mute(u
->sink
);
1615 pa_sink_put(u
->sink
);
1626 static void userdata_free(struct userdata
*u
) {
1630 pa_sink_unlink(u
->sink
);
1633 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
1634 pa_thread_free(u
->thread
);
1637 pa_thread_mq_done(&u
->thread_mq
);
1640 pa_sink_unref(u
->sink
);
1642 if (u
->memchunk
.memblock
)
1643 pa_memblock_unref(u
->memchunk
.memblock
);
1645 if (u
->alsa_rtpoll_item
)
1646 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
1649 pa_rtpoll_free(u
->rtpoll
);
1652 pa_alsa_fdlist_free(u
->mixer_fdl
);
1654 if (u
->mixer_handle
)
1655 snd_mixer_close(u
->mixer_handle
);
1657 if (u
->pcm_handle
) {
1658 snd_pcm_drop(u
->pcm_handle
);
1659 snd_pcm_close(u
->pcm_handle
);
1663 pa_smoother_free(u
->smoother
);
1665 pa_xfree(u
->device_name
);
1669 void pa_alsa_sink_free(pa_sink
*s
) {
1672 pa_sink_assert_ref(s
);
1673 pa_assert_se(u
= s
->userdata
);