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.1 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/i18n.h>
32 #include <pulse/rtclock.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35 #include <pulse/xmalloc.h>
37 #include <pulsecore/core-error.h>
38 #include <pulsecore/core.h>
39 #include <pulsecore/module.h>
40 #include <pulsecore/memchunk.h>
41 #include <pulsecore/sink.h>
42 #include <pulsecore/modargs.h>
43 #include <pulsecore/core-rtclock.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/time-smoother.h>
54 #include <modules/reserve-wrap.h>
56 #include "alsa-util.h"
57 #include "alsa-source.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_WATERMARK_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
65 #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
66 #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms */
74 pa_thread_mq thread_mq
;
77 snd_pcm_t
*pcm_handle
;
79 pa_alsa_fdlist
*mixer_fdl
;
80 snd_mixer_t
*mixer_handle
;
81 pa_alsa_path_set
*mixer_path_set
;
82 pa_alsa_path
*mixer_path
;
84 pa_cvolume hardware_volume
;
101 pa_bool_t use_mmap
:1, use_tsched
:1;
103 pa_rtpoll_item
*alsa_rtpoll_item
;
105 snd_mixer_selem_channel_id_t mixer_map
[SND_MIXER_SCHN_LAST
];
107 pa_smoother
*smoother
;
110 pa_reserve_wrapper
*reserve
;
111 pa_hook_slot
*reserve_slot
;
112 pa_reserve_monitor_wrapper
*monitor
;
113 pa_hook_slot
*monitor_slot
;
116 static void userdata_free(struct userdata
*u
);
118 static pa_hook_result_t
reserve_cb(pa_reserve_wrapper
*r
, void *forced
, struct userdata
*u
) {
122 if (pa_source_suspend(u
->source
, TRUE
, PA_SUSPEND_APPLICATION
) < 0)
123 return PA_HOOK_CANCEL
;
128 static void reserve_done(struct userdata
*u
) {
131 if (u
->reserve_slot
) {
132 pa_hook_slot_free(u
->reserve_slot
);
133 u
->reserve_slot
= NULL
;
137 pa_reserve_wrapper_unref(u
->reserve
);
142 static void reserve_update(struct userdata
*u
) {
143 const char *description
;
146 if (!u
->source
|| !u
->reserve
)
149 if ((description
= pa_proplist_gets(u
->source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)))
150 pa_reserve_wrapper_set_application_device_name(u
->reserve
, description
);
153 static int reserve_init(struct userdata
*u
, const char *dname
) {
162 if (pa_in_system_mode())
165 /* We are resuming, try to lock the device */
166 if (!(rname
= pa_alsa_get_reserve_name(dname
)))
169 u
->reserve
= pa_reserve_wrapper_get(u
->core
, rname
);
177 pa_assert(!u
->reserve_slot
);
178 u
->reserve_slot
= pa_hook_connect(pa_reserve_wrapper_hook(u
->reserve
), PA_HOOK_NORMAL
, (pa_hook_cb_t
) reserve_cb
, u
);
183 static pa_hook_result_t
monitor_cb(pa_reserve_monitor_wrapper
*w
, void* busy
, struct userdata
*u
) {
189 b
= PA_PTR_TO_UINT(busy
) && !u
->reserve
;
191 pa_source_suspend(u
->source
, b
, PA_SUSPEND_APPLICATION
);
195 static void monitor_done(struct userdata
*u
) {
198 if (u
->monitor_slot
) {
199 pa_hook_slot_free(u
->monitor_slot
);
200 u
->monitor_slot
= NULL
;
204 pa_reserve_monitor_wrapper_unref(u
->monitor
);
209 static int reserve_monitor_init(struct userdata
*u
, const char *dname
) {
215 if (pa_in_system_mode())
218 /* We are resuming, try to lock the device */
219 if (!(rname
= pa_alsa_get_reserve_name(dname
)))
222 u
->monitor
= pa_reserve_monitor_wrapper_get(u
->core
, rname
);
228 pa_assert(!u
->monitor_slot
);
229 u
->monitor_slot
= pa_hook_connect(pa_reserve_monitor_wrapper_hook(u
->monitor
), PA_HOOK_NORMAL
, (pa_hook_cb_t
) monitor_cb
, u
);
234 static void fix_min_sleep_wakeup(struct userdata
*u
) {
235 size_t max_use
, max_use_2
;
238 max_use
= u
->hwbuf_size
- u
->hwbuf_unused
;
239 max_use_2
= pa_frame_align(max_use
/2, &u
->source
->sample_spec
);
241 u
->min_sleep
= pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC
, &u
->source
->sample_spec
);
242 u
->min_sleep
= PA_CLAMP(u
->min_sleep
, u
->frame_size
, max_use_2
);
244 u
->min_wakeup
= pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC
, &u
->source
->sample_spec
);
245 u
->min_wakeup
= PA_CLAMP(u
->min_wakeup
, u
->frame_size
, max_use_2
);
248 static void fix_tsched_watermark(struct userdata
*u
) {
252 max_use
= u
->hwbuf_size
- u
->hwbuf_unused
;
254 if (u
->tsched_watermark
> max_use
- u
->min_sleep
)
255 u
->tsched_watermark
= max_use
- u
->min_sleep
;
257 if (u
->tsched_watermark
< u
->min_wakeup
)
258 u
->tsched_watermark
= u
->min_wakeup
;
261 static void adjust_after_overrun(struct userdata
*u
) {
262 size_t old_watermark
;
263 pa_usec_t old_min_latency
, new_min_latency
;
266 pa_assert(u
->use_tsched
);
268 /* First, just try to increase the watermark */
269 old_watermark
= u
->tsched_watermark
;
270 u
->tsched_watermark
= PA_MIN(u
->tsched_watermark
* 2, u
->tsched_watermark
+ u
->watermark_step
);
272 fix_tsched_watermark(u
);
274 if (old_watermark
!= u
->tsched_watermark
) {
275 pa_log_notice("Increasing wakeup watermark to %0.2f ms",
276 (double) pa_bytes_to_usec(u
->tsched_watermark
, &u
->source
->sample_spec
) / PA_USEC_PER_MSEC
);
280 /* Hmm, we cannot increase the watermark any further, hence let's raise the latency */
281 old_min_latency
= u
->source
->thread_info
.min_latency
;
282 new_min_latency
= PA_MIN(old_min_latency
* 2, old_min_latency
+ TSCHED_WATERMARK_STEP_USEC
);
283 new_min_latency
= PA_MIN(new_min_latency
, u
->source
->thread_info
.max_latency
);
285 if (old_min_latency
!= new_min_latency
) {
286 pa_log_notice("Increasing minimal latency to %0.2f ms",
287 (double) new_min_latency
/ PA_USEC_PER_MSEC
);
289 pa_source_set_latency_range_within_thread(u
->source
, new_min_latency
, u
->source
->thread_info
.max_latency
);
293 /* When we reach this we're officialy fucked! */
296 static pa_usec_t
hw_sleep_time(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_usec_t
*process_usec
) {
301 usec
= pa_source_get_requested_latency_within_thread(u
->source
);
303 if (usec
== (pa_usec_t
) -1)
304 usec
= pa_bytes_to_usec(u
->hwbuf_size
, &u
->source
->sample_spec
);
306 wm
= pa_bytes_to_usec(u
->tsched_watermark
, &u
->source
->sample_spec
);
311 *sleep_usec
= usec
- wm
;
315 pa_log_debug("Buffer time: %lu ms; Sleep time: %lu ms; Process time: %lu ms",
316 (unsigned long) (usec
/ PA_USEC_PER_MSEC
),
317 (unsigned long) (*sleep_usec
/ PA_USEC_PER_MSEC
),
318 (unsigned long) (*process_usec
/ PA_USEC_PER_MSEC
));
324 static int try_recover(struct userdata
*u
, const char *call
, int err
) {
329 pa_log_debug("%s: %s", call
, pa_alsa_strerror(err
));
331 pa_assert(err
!= -EAGAIN
);
334 pa_log_debug("%s: Buffer overrun!", call
);
336 if ((err
= snd_pcm_recover(u
->pcm_handle
, err
, 1)) < 0) {
337 pa_log("%s: %s", call
, pa_alsa_strerror(err
));
341 snd_pcm_start(u
->pcm_handle
);
345 static size_t check_left_to_record(struct userdata
*u
, size_t n_bytes
) {
346 size_t left_to_record
;
347 size_t rec_space
= u
->hwbuf_size
- u
->hwbuf_unused
;
349 /* We use <= instead of < for this check here because an overrun
350 * only happens after the last sample was processed, not already when
351 * it is removed from the buffer. This is particularly important
352 * when block transfer is used. */
354 if (n_bytes
<= rec_space
) {
355 left_to_record
= rec_space
- n_bytes
;
358 pa_log_debug("%0.2f ms left to record", (double) pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
) / PA_USEC_PER_MSEC
);
368 if (pa_log_ratelimit())
369 pa_log_info("Overrun!");
372 adjust_after_overrun(u
);
375 return left_to_record
;
378 static int mmap_read(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
379 pa_bool_t work_done
= FALSE
;
380 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
381 size_t left_to_record
;
385 pa_source_assert_ref(u
->source
);
388 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
395 if (PA_UNLIKELY((n
= pa_alsa_safe_avail(u
->pcm_handle
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
397 if ((r
= try_recover(u
, "snd_pcm_avail", (int) n
)) == 0)
403 n_bytes
= (size_t) n
* u
->frame_size
;
406 pa_log_debug("avail: %lu", (unsigned long) n_bytes
);
409 left_to_record
= check_left_to_record(u
, n_bytes
);
413 pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
) > process_usec
+max_sleep_usec
/2) {
415 pa_log_debug("Not reading, because too early.");
420 if (PA_UNLIKELY(n_bytes
<= 0)) {
424 char *dn
= pa_alsa_get_driver_name_by_pcm(u
->pcm_handle
);
425 pa_log(_("ALSA woke us up to read new data from the device, but there was actually nothing to read!\n"
426 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n"
427 "We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail."),
433 pa_log_debug("Not reading, because not necessary.");
440 pa_log_debug("Not filling up, because already too many iterations.");
449 pa_log_debug("Reading");
454 const snd_pcm_channel_area_t
*areas
;
455 snd_pcm_uframes_t offset
, frames
;
458 snd_pcm_sframes_t sframes
;
460 frames
= (snd_pcm_uframes_t
) (n_bytes
/ u
->frame_size
);
462 /* pa_log_debug("%lu frames to read", (unsigned long) frames); */
464 if (PA_UNLIKELY((err
= pa_alsa_safe_mmap_begin(u
->pcm_handle
, &areas
, &offset
, &frames
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
466 if ((r
= try_recover(u
, "snd_pcm_mmap_begin", err
)) == 0)
472 /* Make sure that if these memblocks need to be copied they will fit into one slot */
473 if (frames
> pa_mempool_block_size_max(u
->source
->core
->mempool
)/u
->frame_size
)
474 frames
= pa_mempool_block_size_max(u
->source
->core
->mempool
)/u
->frame_size
;
476 /* Check these are multiples of 8 bit */
477 pa_assert((areas
[0].first
& 7) == 0);
478 pa_assert((areas
[0].step
& 7)== 0);
480 /* We assume a single interleaved memory buffer */
481 pa_assert((areas
[0].first
>> 3) == 0);
482 pa_assert((areas
[0].step
>> 3) == u
->frame_size
);
484 p
= (uint8_t*) areas
[0].addr
+ (offset
* u
->frame_size
);
486 chunk
.memblock
= pa_memblock_new_fixed(u
->core
->mempool
, p
, frames
* u
->frame_size
, TRUE
);
487 chunk
.length
= pa_memblock_get_length(chunk
.memblock
);
490 pa_source_post(u
->source
, &chunk
);
491 pa_memblock_unref_fixed(chunk
.memblock
);
493 if (PA_UNLIKELY((sframes
= snd_pcm_mmap_commit(u
->pcm_handle
, offset
, frames
)) < 0)) {
495 if ((r
= try_recover(u
, "snd_pcm_mmap_commit", (int) sframes
)) == 0)
503 u
->read_count
+= frames
* u
->frame_size
;
506 pa_log_debug("Read %lu bytes (of possible %lu bytes)", (unsigned long) (frames
* u
->frame_size
), (unsigned long) n_bytes
);
509 if ((size_t) frames
* u
->frame_size
>= n_bytes
)
512 n_bytes
-= (size_t) frames
* u
->frame_size
;
516 *sleep_usec
= pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
);
518 if (*sleep_usec
> process_usec
)
519 *sleep_usec
-= process_usec
;
523 return work_done
? 1 : 0;
526 static int unix_read(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
527 int work_done
= FALSE
;
528 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
529 size_t left_to_record
;
533 pa_source_assert_ref(u
->source
);
536 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
543 if (PA_UNLIKELY((n
= pa_alsa_safe_avail(u
->pcm_handle
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
545 if ((r
= try_recover(u
, "snd_pcm_avail", (int) n
)) == 0)
551 n_bytes
= (size_t) n
* u
->frame_size
;
552 left_to_record
= check_left_to_record(u
, n_bytes
);
556 pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
) > process_usec
+max_sleep_usec
/2)
559 if (PA_UNLIKELY(n_bytes
<= 0)) {
563 char *dn
= pa_alsa_get_driver_name_by_pcm(u
->pcm_handle
);
564 pa_log(_("ALSA woke us up to read new data from the device, but there was actually nothing to read!\n"
565 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n"
566 "We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail."),
576 pa_log_debug("Not filling up, because already too many iterations.");
586 snd_pcm_sframes_t frames
;
589 chunk
.memblock
= pa_memblock_new(u
->core
->mempool
, (size_t) -1);
591 frames
= (snd_pcm_sframes_t
) (pa_memblock_get_length(chunk
.memblock
) / u
->frame_size
);
593 if (frames
> (snd_pcm_sframes_t
) (n_bytes
/u
->frame_size
))
594 frames
= (snd_pcm_sframes_t
) (n_bytes
/u
->frame_size
);
596 /* pa_log_debug("%lu frames to read", (unsigned long) n); */
598 p
= pa_memblock_acquire(chunk
.memblock
);
599 frames
= snd_pcm_readi(u
->pcm_handle
, (uint8_t*) p
, (snd_pcm_uframes_t
) frames
);
600 pa_memblock_release(chunk
.memblock
);
602 pa_assert(frames
!= 0);
604 if (PA_UNLIKELY(frames
< 0)) {
605 pa_memblock_unref(chunk
.memblock
);
607 if ((r
= try_recover(u
, "snd_pcm_readi", (int) (frames
))) == 0)
614 chunk
.length
= (size_t) frames
* u
->frame_size
;
616 pa_source_post(u
->source
, &chunk
);
617 pa_memblock_unref(chunk
.memblock
);
621 u
->read_count
+= frames
* u
->frame_size
;
623 /* pa_log_debug("read %lu frames", (unsigned long) frames); */
625 if ((size_t) frames
* u
->frame_size
>= n_bytes
)
628 n_bytes
-= (size_t) frames
* u
->frame_size
;
632 *sleep_usec
= pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
);
634 if (*sleep_usec
> process_usec
)
635 *sleep_usec
-= process_usec
;
639 return work_done
? 1 : 0;
642 static void update_smoother(struct userdata
*u
) {
643 snd_pcm_sframes_t delay
= 0;
646 pa_usec_t now1
= 0, now2
;
647 snd_pcm_status_t
*status
;
649 snd_pcm_status_alloca(&status
);
652 pa_assert(u
->pcm_handle
);
654 /* Let's update the time smoother */
656 if (PA_UNLIKELY((err
= pa_alsa_safe_delay(u
->pcm_handle
, &delay
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
657 pa_log_warn("Failed to get delay: %s", pa_alsa_strerror(err
));
661 if (PA_UNLIKELY((err
= snd_pcm_status(u
->pcm_handle
, status
)) < 0))
662 pa_log_warn("Failed to get timestamp: %s", pa_alsa_strerror(err
));
664 snd_htimestamp_t htstamp
= { 0, 0 };
665 snd_pcm_status_get_htstamp(status
, &htstamp
);
666 now1
= pa_timespec_load(&htstamp
);
669 position
= u
->read_count
+ ((uint64_t) delay
* (uint64_t) u
->frame_size
);
671 /* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
673 now1
= pa_rtclock_now();
675 now2
= pa_bytes_to_usec(position
, &u
->source
->sample_spec
);
677 pa_smoother_put(u
->smoother
, now1
, now2
);
680 static pa_usec_t
source_get_latency(struct userdata
*u
) {
682 pa_usec_t now1
, now2
;
686 now1
= pa_rtclock_now();
687 now2
= pa_smoother_get(u
->smoother
, now1
);
689 delay
= (int64_t) now2
- (int64_t) pa_bytes_to_usec(u
->read_count
, &u
->source
->sample_spec
);
691 return delay
>= 0 ? (pa_usec_t
) delay
: 0;
694 static int build_pollfd(struct userdata
*u
) {
696 pa_assert(u
->pcm_handle
);
698 if (u
->alsa_rtpoll_item
)
699 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
701 if (!(u
->alsa_rtpoll_item
= pa_alsa_build_pollfd(u
->pcm_handle
, u
->rtpoll
)))
707 static int suspend(struct userdata
*u
) {
709 pa_assert(u
->pcm_handle
);
711 pa_smoother_pause(u
->smoother
, pa_rtclock_now());
714 snd_pcm_close(u
->pcm_handle
);
715 u
->pcm_handle
= NULL
;
717 if (u
->alsa_rtpoll_item
) {
718 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
719 u
->alsa_rtpoll_item
= NULL
;
722 pa_log_info("Device suspended...");
727 static int update_sw_params(struct userdata
*u
) {
728 snd_pcm_uframes_t avail_min
;
733 /* Use the full buffer if noone asked us for anything specific */
739 if ((latency
= pa_source_get_requested_latency_within_thread(u
->source
)) != (pa_usec_t
) -1) {
742 pa_log_debug("latency set to %0.2fms", (double) latency
/ PA_USEC_PER_MSEC
);
744 b
= pa_usec_to_bytes(latency
, &u
->source
->sample_spec
);
746 /* We need at least one sample in our buffer */
748 if (PA_UNLIKELY(b
< u
->frame_size
))
751 u
->hwbuf_unused
= PA_LIKELY(b
< u
->hwbuf_size
) ? (u
->hwbuf_size
- b
) : 0;
754 fix_min_sleep_wakeup(u
);
755 fix_tsched_watermark(u
);
758 pa_log_debug("hwbuf_unused=%lu", (unsigned long) u
->hwbuf_unused
);
763 pa_usec_t sleep_usec
, process_usec
;
765 hw_sleep_time(u
, &sleep_usec
, &process_usec
);
766 avail_min
+= pa_usec_to_bytes(sleep_usec
, &u
->source
->sample_spec
) / u
->frame_size
;
769 pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min
);
771 if ((err
= pa_alsa_set_sw_params(u
->pcm_handle
, avail_min
)) < 0) {
772 pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err
));
779 static int unsuspend(struct userdata
*u
) {
784 snd_pcm_uframes_t period_size
;
787 pa_assert(!u
->pcm_handle
);
789 pa_log_info("Trying resume...");
791 if ((err
= snd_pcm_open(&u
->pcm_handle
, u
->device_name
, SND_PCM_STREAM_CAPTURE
,
792 /*SND_PCM_NONBLOCK|*/
793 SND_PCM_NO_AUTO_RESAMPLE
|
794 SND_PCM_NO_AUTO_CHANNELS
|
795 SND_PCM_NO_AUTO_FORMAT
)) < 0) {
796 pa_log("Error opening PCM device %s: %s", u
->device_name
, pa_alsa_strerror(err
));
800 ss
= u
->source
->sample_spec
;
801 nfrags
= u
->nfragments
;
802 period_size
= u
->fragment_size
/ u
->frame_size
;
806 if ((err
= pa_alsa_set_hw_params(u
->pcm_handle
, &ss
, &nfrags
, &period_size
, u
->hwbuf_size
/ u
->frame_size
, &b
, &d
, TRUE
)) < 0) {
807 pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err
));
811 if (b
!= u
->use_mmap
|| d
!= u
->use_tsched
) {
812 pa_log_warn("Resume failed, couldn't get original access mode.");
816 if (!pa_sample_spec_equal(&ss
, &u
->source
->sample_spec
)) {
817 pa_log_warn("Resume failed, couldn't restore original sample settings.");
821 if (nfrags
!= u
->nfragments
|| period_size
*u
->frame_size
!= u
->fragment_size
) {
822 pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
823 (unsigned long) u
->nfragments
, (unsigned long) u
->fragment_size
,
824 (unsigned long) nfrags
, period_size
* u
->frame_size
);
828 if (update_sw_params(u
) < 0)
831 if (build_pollfd(u
) < 0)
834 /* FIXME: We need to reload the volume somehow */
836 snd_pcm_start(u
->pcm_handle
);
837 pa_smoother_resume(u
->smoother
, pa_rtclock_now(), TRUE
);
839 pa_log_info("Resumed successfully...");
845 snd_pcm_close(u
->pcm_handle
);
846 u
->pcm_handle
= NULL
;
852 static int source_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
853 struct userdata
*u
= PA_SOURCE(o
)->userdata
;
857 case PA_SOURCE_MESSAGE_GET_LATENCY
: {
861 r
= source_get_latency(u
);
863 *((pa_usec_t
*) data
) = r
;
868 case PA_SOURCE_MESSAGE_SET_STATE
:
870 switch ((pa_source_state_t
) PA_PTR_TO_UINT(data
)) {
872 case PA_SOURCE_SUSPENDED
:
873 pa_assert(PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
));
881 case PA_SOURCE_RUNNING
:
883 if (u
->source
->thread_info
.state
== PA_SOURCE_INIT
) {
884 if (build_pollfd(u
) < 0)
887 snd_pcm_start(u
->pcm_handle
);
890 if (u
->source
->thread_info
.state
== PA_SOURCE_SUSPENDED
) {
891 if (unsuspend(u
) < 0)
897 case PA_SOURCE_UNLINKED
:
899 case PA_SOURCE_INVALID_STATE
:
906 return pa_source_process_msg(o
, code
, data
, offset
, chunk
);
909 /* Called from main context */
910 static int source_set_state_cb(pa_source
*s
, pa_source_state_t new_state
) {
911 pa_source_state_t old_state
;
914 pa_source_assert_ref(s
);
915 pa_assert_se(u
= s
->userdata
);
917 old_state
= pa_source_get_state(u
->source
);
919 if (PA_SINK_IS_OPENED(old_state
) && new_state
== PA_SINK_SUSPENDED
)
921 else if (old_state
== PA_SINK_SUSPENDED
&& PA_SINK_IS_OPENED(new_state
))
922 if (reserve_init(u
, u
->device_name
) < 0)
928 static int mixer_callback(snd_mixer_elem_t
*elem
, unsigned int mask
) {
929 struct userdata
*u
= snd_mixer_elem_get_callback_private(elem
);
932 pa_assert(u
->mixer_handle
);
934 if (mask
== SND_CTL_EVENT_MASK_REMOVE
)
937 if (mask
& SND_CTL_EVENT_MASK_VALUE
) {
938 pa_source_get_volume(u
->source
, TRUE
);
939 pa_source_get_mute(u
->source
, TRUE
);
945 static void source_get_volume_cb(pa_source
*s
) {
946 struct userdata
*u
= s
->userdata
;
948 char t
[PA_CVOLUME_SNPRINT_MAX
];
951 pa_assert(u
->mixer_path
);
952 pa_assert(u
->mixer_handle
);
954 if (pa_alsa_path_get_volume(u
->mixer_path
, u
->mixer_handle
, &s
->channel_map
, &r
) < 0)
957 /* Shift down by the base volume, so that 0dB becomes maximum volume */
958 pa_sw_cvolume_multiply_scalar(&r
, &r
, s
->base_volume
);
960 pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
962 if (pa_cvolume_equal(&u
->hardware_volume
, &r
))
965 s
->virtual_volume
= u
->hardware_volume
= r
;
967 if (u
->mixer_path
->has_dB
) {
970 /* Hmm, so the hardware volume changed, let's reset our software volume */
971 pa_cvolume_reset(&reset
, s
->sample_spec
.channels
);
972 pa_source_set_soft_volume(s
, &reset
);
976 static void source_set_volume_cb(pa_source
*s
) {
977 struct userdata
*u
= s
->userdata
;
979 char t
[PA_CVOLUME_SNPRINT_MAX
];
982 pa_assert(u
->mixer_path
);
983 pa_assert(u
->mixer_handle
);
985 /* Shift up by the base volume */
986 pa_sw_cvolume_divide_scalar(&r
, &s
->virtual_volume
, s
->base_volume
);
988 if (pa_alsa_path_set_volume(u
->mixer_path
, u
->mixer_handle
, &s
->channel_map
, &r
) < 0)
991 /* Shift down by the base volume, so that 0dB becomes maximum volume */
992 pa_sw_cvolume_multiply_scalar(&r
, &r
, s
->base_volume
);
994 u
->hardware_volume
= r
;
996 if (u
->mixer_path
->has_dB
) {
998 /* Match exactly what the user requested by software */
999 pa_sw_cvolume_divide(&s
->soft_volume
, &s
->virtual_volume
, &u
->hardware_volume
);
1001 pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->virtual_volume
));
1002 pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &u
->hardware_volume
));
1003 pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->soft_volume
));
1006 pa_log_debug("Wrote hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
1008 /* We can't match exactly what the user requested, hence let's
1009 * at least tell the user about it */
1011 s
->virtual_volume
= r
;
1015 static void source_get_mute_cb(pa_source
*s
) {
1016 struct userdata
*u
= s
->userdata
;
1020 pa_assert(u
->mixer_path
);
1021 pa_assert(u
->mixer_handle
);
1023 if (pa_alsa_path_get_mute(u
->mixer_path
, u
->mixer_handle
, &b
) < 0)
1029 static void source_set_mute_cb(pa_source
*s
) {
1030 struct userdata
*u
= s
->userdata
;
1033 pa_assert(u
->mixer_path
);
1034 pa_assert(u
->mixer_handle
);
1036 pa_alsa_path_set_mute(u
->mixer_path
, u
->mixer_handle
, s
->muted
);
1039 static int source_set_port_cb(pa_source
*s
, pa_device_port
*p
) {
1040 struct userdata
*u
= s
->userdata
;
1041 pa_alsa_port_data
*data
;
1045 pa_assert(u
->mixer_handle
);
1047 data
= PA_DEVICE_PORT_DATA(p
);
1049 pa_assert_se(u
->mixer_path
= data
->path
);
1050 pa_alsa_path_select(u
->mixer_path
, u
->mixer_handle
);
1052 if (u
->mixer_path
->has_volume
&& u
->mixer_path
->has_dB
) {
1053 s
->base_volume
= pa_sw_volume_from_dB(-u
->mixer_path
->max_dB
);
1054 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
1056 if (u
->mixer_path
->max_dB
> 0.0)
1057 pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(s
->base_volume
));
1059 pa_log_info("No particular base volume set, fixing to 0 dB");
1061 s
->base_volume
= PA_VOLUME_NORM
;
1062 s
->n_volume_steps
= u
->mixer_path
->max_volume
- u
->mixer_path
->min_volume
+ 1;
1066 pa_alsa_setting_select(data
->setting
, u
->mixer_handle
);
1076 static void source_update_requested_latency_cb(pa_source
*s
) {
1077 struct userdata
*u
= s
->userdata
;
1083 update_sw_params(u
);
1086 static void thread_func(void *userdata
) {
1087 struct userdata
*u
= userdata
;
1088 unsigned short revents
= 0;
1092 pa_log_debug("Thread starting up");
1094 if (u
->core
->realtime_scheduling
)
1095 pa_make_realtime(u
->core
->realtime_priority
);
1097 pa_thread_mq_install(&u
->thread_mq
);
1103 pa_log_debug("Loop");
1106 /* Read some data and pass it to the sources */
1107 if (PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
)) {
1109 pa_usec_t sleep_usec
= 0;
1112 work_done
= mmap_read(u
, &sleep_usec
, revents
& POLLIN
);
1114 work_done
= unix_read(u
, &sleep_usec
, revents
& POLLIN
);
1119 /* pa_log_debug("work_done = %i", work_done); */
1124 if (u
->use_tsched
) {
1127 /* OK, the capture buffer is now empty, let's
1128 * calculate when to wake up next */
1130 /* pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
1132 /* Convert from the sound card time domain to the
1133 * system time domain */
1134 cusec
= pa_smoother_translate(u
->smoother
, pa_rtclock_now(), sleep_usec
);
1136 /* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
1138 /* We don't trust the conversion, so we wake up whatever comes first */
1139 pa_rtpoll_set_timer_relative(u
->rtpoll
, PA_MIN(sleep_usec
, cusec
));
1141 } else if (u
->use_tsched
)
1143 /* OK, we're in an invalid state, let's disable our timers */
1144 pa_rtpoll_set_timer_disabled(u
->rtpoll
);
1146 /* Hmm, nothing to do. Let's sleep */
1147 if ((ret
= pa_rtpoll_run(u
->rtpoll
, TRUE
)) < 0)
1153 /* Tell ALSA about this and process its response */
1154 if (PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
)) {
1155 struct pollfd
*pollfd
;
1159 pollfd
= pa_rtpoll_item_get_pollfd(u
->alsa_rtpoll_item
, &n
);
1161 if ((err
= snd_pcm_poll_descriptors_revents(u
->pcm_handle
, pollfd
, n
, &revents
)) < 0) {
1162 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", pa_alsa_strerror(err
));
1166 if (revents
& ~POLLIN
) {
1167 if (pa_alsa_recover_from_poll(u
->pcm_handle
, revents
) < 0)
1170 snd_pcm_start(u
->pcm_handle
);
1171 } else if (revents
&& u
->use_tsched
&& pa_log_ratelimit())
1172 pa_log_debug("Wakeup from ALSA!");
1179 /* If this was no regular exit from the loop we have to continue
1180 * processing messages until we received PA_MESSAGE_SHUTDOWN */
1181 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
1182 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
1185 pa_log_debug("Thread shutting down");
1188 static void set_source_name(pa_source_new_data
*data
, pa_modargs
*ma
, const char *device_id
, const char *device_name
, pa_alsa_mapping
*mapping
) {
1194 pa_assert(device_name
);
1196 if ((n
= pa_modargs_get_value(ma
, "source_name", NULL
))) {
1197 pa_source_new_data_set_name(data
, n
);
1198 data
->namereg_fail
= TRUE
;
1202 if ((n
= pa_modargs_get_value(ma
, "name", NULL
)))
1203 data
->namereg_fail
= TRUE
;
1205 n
= device_id
? device_id
: device_name
;
1206 data
->namereg_fail
= FALSE
;
1210 t
= pa_sprintf_malloc("alsa_input.%s.%s", n
, mapping
->name
);
1212 t
= pa_sprintf_malloc("alsa_input.%s", n
);
1214 pa_source_new_data_set_name(data
, t
);
1218 static void find_mixer(struct userdata
*u
, pa_alsa_mapping
*mapping
, const char *element
, pa_bool_t ignore_dB
) {
1220 if (!mapping
&& !element
)
1223 if (!(u
->mixer_handle
= pa_alsa_open_mixer_for_pcm(u
->pcm_handle
, &u
->control_device
))) {
1224 pa_log_info("Failed to find a working mixer device.");
1230 if (!(u
->mixer_path
= pa_alsa_path_synthesize(element
, PA_ALSA_DIRECTION_INPUT
)))
1233 if (pa_alsa_path_probe(u
->mixer_path
, u
->mixer_handle
, ignore_dB
) < 0)
1236 pa_log_debug("Probed mixer path %s:", u
->mixer_path
->name
);
1237 pa_alsa_path_dump(u
->mixer_path
);
1240 if (!(u
->mixer_path_set
= pa_alsa_path_set_new(mapping
, PA_ALSA_DIRECTION_INPUT
)))
1243 pa_alsa_path_set_probe(u
->mixer_path_set
, u
->mixer_handle
, ignore_dB
);
1245 pa_log_debug("Probed mixer paths:");
1246 pa_alsa_path_set_dump(u
->mixer_path_set
);
1253 if (u
->mixer_path_set
) {
1254 pa_alsa_path_set_free(u
->mixer_path_set
);
1255 u
->mixer_path_set
= NULL
;
1256 } else if (u
->mixer_path
) {
1257 pa_alsa_path_free(u
->mixer_path
);
1258 u
->mixer_path
= NULL
;
1261 if (u
->mixer_handle
) {
1262 snd_mixer_close(u
->mixer_handle
);
1263 u
->mixer_handle
= NULL
;
1267 static int setup_mixer(struct userdata
*u
, pa_bool_t ignore_dB
) {
1270 if (!u
->mixer_handle
)
1273 if (u
->source
->active_port
) {
1274 pa_alsa_port_data
*data
;
1276 /* We have a list of supported paths, so let's activate the
1277 * one that has been chosen as active */
1279 data
= PA_DEVICE_PORT_DATA(u
->source
->active_port
);
1280 u
->mixer_path
= data
->path
;
1282 pa_alsa_path_select(data
->path
, u
->mixer_handle
);
1285 pa_alsa_setting_select(data
->setting
, u
->mixer_handle
);
1289 if (!u
->mixer_path
&& u
->mixer_path_set
)
1290 u
->mixer_path
= u
->mixer_path_set
->paths
;
1292 if (u
->mixer_path
) {
1293 /* Hmm, we have only a single path, then let's activate it */
1295 pa_alsa_path_select(u
->mixer_path
, u
->mixer_handle
);
1297 if (u
->mixer_path
->settings
)
1298 pa_alsa_setting_select(u
->mixer_path
->settings
, u
->mixer_handle
);
1303 if (!u
->mixer_path
->has_volume
)
1304 pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
1307 if (u
->mixer_path
->has_dB
) {
1308 pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u
->mixer_path
->min_dB
, u
->mixer_path
->max_dB
);
1310 u
->source
->base_volume
= pa_sw_volume_from_dB(-u
->mixer_path
->max_dB
);
1311 u
->source
->n_volume_steps
= PA_VOLUME_NORM
+1;
1313 if (u
->mixer_path
->max_dB
> 0.0)
1314 pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u
->source
->base_volume
));
1316 pa_log_info("No particular base volume set, fixing to 0 dB");
1319 pa_log_info("Hardware volume ranges from %li to %li.", u
->mixer_path
->min_volume
, u
->mixer_path
->max_volume
);
1320 u
->source
->base_volume
= PA_VOLUME_NORM
;
1321 u
->source
->n_volume_steps
= u
->mixer_path
->max_volume
- u
->mixer_path
->min_volume
+ 1;
1324 u
->source
->get_volume
= source_get_volume_cb
;
1325 u
->source
->set_volume
= source_set_volume_cb
;
1327 u
->source
->flags
|= PA_SOURCE_HW_VOLUME_CTRL
| (u
->mixer_path
->has_dB
? PA_SOURCE_DECIBEL_VOLUME
: 0);
1328 pa_log_info("Using hardware volume control. Hardware dB scale %s.", u
->mixer_path
->has_dB
? "supported" : "not supported");
1331 if (!u
->mixer_path
->has_mute
) {
1332 pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
1334 u
->source
->get_mute
= source_get_mute_cb
;
1335 u
->source
->set_mute
= source_set_mute_cb
;
1336 u
->source
->flags
|= PA_SOURCE_HW_MUTE_CTRL
;
1337 pa_log_info("Using hardware mute control.");
1340 u
->mixer_fdl
= pa_alsa_fdlist_new();
1342 if (pa_alsa_fdlist_set_mixer(u
->mixer_fdl
, u
->mixer_handle
, u
->core
->mainloop
) < 0) {
1343 pa_log("Failed to initialize file descriptor monitoring");
1347 if (u
->mixer_path_set
)
1348 pa_alsa_path_set_set_callback(u
->mixer_path_set
, u
->mixer_handle
, mixer_callback
, u
);
1350 pa_alsa_path_set_callback(u
->mixer_path
, u
->mixer_handle
, mixer_callback
, u
);
1355 pa_source
*pa_alsa_source_new(pa_module
*m
, pa_modargs
*ma
, const char*driver
, pa_card
*card
, pa_alsa_mapping
*mapping
) {
1357 struct userdata
*u
= NULL
;
1358 const char *dev_id
= NULL
;
1359 pa_sample_spec ss
, requested_ss
;
1361 uint32_t nfrags
, hwbuf_size
, frag_size
, tsched_size
, tsched_watermark
;
1362 snd_pcm_uframes_t period_frames
, tsched_frames
;
1364 pa_bool_t use_mmap
= TRUE
, b
, use_tsched
= TRUE
, d
, ignore_dB
= FALSE
;
1365 pa_source_new_data data
;
1366 pa_alsa_profile_set
*profile_set
= NULL
;
1371 ss
= m
->core
->default_sample_spec
;
1372 map
= m
->core
->default_channel_map
;
1373 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_ALSA
) < 0) {
1374 pa_log("Failed to parse sample specification");
1379 frame_size
= pa_frame_size(&ss
);
1381 nfrags
= m
->core
->default_n_fragments
;
1382 frag_size
= (uint32_t) pa_usec_to_bytes(m
->core
->default_fragment_size_msec
*PA_USEC_PER_MSEC
, &ss
);
1384 frag_size
= (uint32_t) frame_size
;
1385 tsched_size
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC
, &ss
);
1386 tsched_watermark
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC
, &ss
);
1388 if (pa_modargs_get_value_u32(ma
, "fragments", &nfrags
) < 0 ||
1389 pa_modargs_get_value_u32(ma
, "fragment_size", &frag_size
) < 0 ||
1390 pa_modargs_get_value_u32(ma
, "tsched_buffer_size", &tsched_size
) < 0 ||
1391 pa_modargs_get_value_u32(ma
, "tsched_buffer_watermark", &tsched_watermark
) < 0) {
1392 pa_log("Failed to parse buffer metrics");
1396 hwbuf_size
= frag_size
* nfrags
;
1397 period_frames
= frag_size
/frame_size
;
1398 tsched_frames
= tsched_size
/frame_size
;
1400 if (pa_modargs_get_value_boolean(ma
, "mmap", &use_mmap
) < 0) {
1401 pa_log("Failed to parse mmap argument.");
1405 if (pa_modargs_get_value_boolean(ma
, "tsched", &use_tsched
) < 0) {
1406 pa_log("Failed to parse timer_scheduling argument.");
1410 if (pa_modargs_get_value_boolean(ma
, "ignore_dB", &ignore_dB
) < 0) {
1411 pa_log("Failed to parse ignore_dB argument.");
1415 if (use_tsched
&& !pa_rtclock_hrtimer()) {
1416 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1420 u
= pa_xnew0(struct userdata
, 1);
1423 u
->use_mmap
= use_mmap
;
1424 u
->use_tsched
= use_tsched
;
1425 u
->rtpoll
= pa_rtpoll_new();
1426 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
1428 u
->smoother
= pa_smoother_new(
1429 DEFAULT_TSCHED_WATERMARK_USEC
*2,
1430 DEFAULT_TSCHED_WATERMARK_USEC
*2,
1437 dev_id
= pa_modargs_get_value(
1439 pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
));
1441 if (reserve_init(u
, dev_id
) < 0)
1444 if (reserve_monitor_init(u
, dev_id
) < 0)
1452 if (!(dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1453 pa_log("device_id= not set");
1457 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id_mapping(
1461 SND_PCM_STREAM_CAPTURE
,
1462 &nfrags
, &period_frames
, tsched_frames
,
1466 } else if ((dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1468 if (!(profile_set
= pa_alsa_profile_set_new(NULL
, &map
)))
1471 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id_auto(
1475 SND_PCM_STREAM_CAPTURE
,
1476 &nfrags
, &period_frames
, tsched_frames
,
1477 &b
, &d
, profile_set
, &mapping
)))
1482 if (!(u
->pcm_handle
= pa_alsa_open_by_device_string(
1483 pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
),
1486 SND_PCM_STREAM_CAPTURE
,
1487 &nfrags
, &period_frames
, tsched_frames
,
1492 pa_assert(u
->device_name
);
1493 pa_log_info("Successfully opened device %s.", u
->device_name
);
1495 if (pa_alsa_pcm_is_modem(u
->pcm_handle
)) {
1496 pa_log_notice("Device %s is modem, refusing further initialization.", u
->device_name
);
1501 pa_log_info("Selected mapping '%s' (%s).", mapping
->description
, mapping
->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
;
1513 if (use_tsched
&& !pa_alsa_pcm_is_hw(u
->pcm_handle
)) {
1514 pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
1515 u
->use_tsched
= use_tsched
= FALSE
;
1519 pa_log_info("Successfully enabled mmap() mode.");
1522 pa_log_info("Successfully enabled timer-based scheduling mode.");
1524 /* ALSA might tweak the sample spec, so recalculate the frame size */
1525 frame_size
= pa_frame_size(&ss
);
1527 find_mixer(u
, mapping
, pa_modargs_get_value(ma
, "control", NULL
), ignore_dB
);
1529 pa_source_new_data_init(&data
);
1530 data
.driver
= driver
;
1533 set_source_name(&data
, ma
, dev_id
, u
->device_name
, mapping
);
1534 pa_source_new_data_set_sample_spec(&data
, &ss
);
1535 pa_source_new_data_set_channel_map(&data
, &map
);
1537 pa_alsa_init_proplist_pcm(m
->core
, data
.proplist
, u
->pcm_handle
);
1538 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
1539 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
* nfrags
));
1540 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
));
1541 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, u
->use_tsched
? "mmap+timer" : (u
->use_mmap
? "mmap" : "serial"));
1544 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_NAME
, mapping
->name
);
1545 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
, mapping
->description
);
1548 pa_alsa_init_description(data
.proplist
);
1550 if (u
->control_device
)
1551 pa_alsa_init_proplist_ctl(data
.proplist
, u
->control_device
);
1553 if (pa_modargs_get_proplist(ma
, "source_properties", data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1554 pa_log("Invalid properties");
1555 pa_source_new_data_done(&data
);
1559 if (u
->mixer_path_set
)
1560 pa_alsa_add_ports(&data
.ports
, u
->mixer_path_set
);
1562 u
->source
= pa_source_new(m
->core
, &data
, PA_SOURCE_HARDWARE
|PA_SOURCE_LATENCY
|(u
->use_tsched
? PA_SOURCE_DYNAMIC_LATENCY
: 0));
1563 pa_source_new_data_done(&data
);
1566 pa_log("Failed to create source object");
1570 u
->source
->parent
.process_msg
= source_process_msg
;
1571 u
->source
->update_requested_latency
= source_update_requested_latency_cb
;
1572 u
->source
->set_state
= source_set_state_cb
;
1573 u
->source
->set_port
= source_set_port_cb
;
1574 u
->source
->userdata
= u
;
1576 pa_source_set_asyncmsgq(u
->source
, u
->thread_mq
.inq
);
1577 pa_source_set_rtpoll(u
->source
, u
->rtpoll
);
1579 u
->frame_size
= frame_size
;
1580 u
->fragment_size
= frag_size
= (uint32_t) (period_frames
* frame_size
);
1581 u
->nfragments
= nfrags
;
1582 u
->hwbuf_size
= u
->fragment_size
* nfrags
;
1583 u
->tsched_watermark
= pa_usec_to_bytes_round_up(pa_bytes_to_usec_round_up(tsched_watermark
, &requested_ss
), &u
->source
->sample_spec
);
1584 pa_cvolume_mute(&u
->hardware_volume
, u
->source
->sample_spec
.channels
);
1586 pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
1587 nfrags
, (long unsigned) u
->fragment_size
,
1588 (double) pa_bytes_to_usec(u
->hwbuf_size
, &ss
) / PA_USEC_PER_MSEC
);
1590 if (u
->use_tsched
) {
1591 u
->watermark_step
= pa_usec_to_bytes(TSCHED_WATERMARK_STEP_USEC
, &u
->source
->sample_spec
);
1593 fix_min_sleep_wakeup(u
);
1594 fix_tsched_watermark(u
);
1596 pa_source_set_latency_range(u
->source
,
1598 pa_bytes_to_usec(u
->hwbuf_size
, &ss
));
1600 pa_log_info("Time scheduling watermark is %0.2fms",
1601 (double) pa_bytes_to_usec(u
->tsched_watermark
, &ss
) / PA_USEC_PER_MSEC
);
1603 pa_source_set_fixed_latency(u
->source
, pa_bytes_to_usec(u
->hwbuf_size
, &ss
));
1607 if (update_sw_params(u
) < 0)
1610 if (setup_mixer(u
, ignore_dB
) < 0)
1613 pa_alsa_dump(PA_LOG_DEBUG
, u
->pcm_handle
);
1615 if (!(u
->thread
= pa_thread_new(thread_func
, u
))) {
1616 pa_log("Failed to create thread.");
1619 /* Get initial mixer settings */
1620 if (data
.volume_is_set
) {
1621 if (u
->source
->set_volume
)
1622 u
->source
->set_volume(u
->source
);
1624 if (u
->source
->get_volume
)
1625 u
->source
->get_volume(u
->source
);
1628 if (data
.muted_is_set
) {
1629 if (u
->source
->set_mute
)
1630 u
->source
->set_mute(u
->source
);
1632 if (u
->source
->get_mute
)
1633 u
->source
->get_mute(u
->source
);
1636 pa_source_put(u
->source
);
1639 pa_alsa_profile_set_free(profile_set
);
1649 pa_alsa_profile_set_free(profile_set
);
1654 static void userdata_free(struct userdata
*u
) {
1658 pa_source_unlink(u
->source
);
1661 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
1662 pa_thread_free(u
->thread
);
1665 pa_thread_mq_done(&u
->thread_mq
);
1668 pa_source_unref(u
->source
);
1670 if (u
->alsa_rtpoll_item
)
1671 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
1674 pa_rtpoll_free(u
->rtpoll
);
1676 if (u
->pcm_handle
) {
1677 snd_pcm_drop(u
->pcm_handle
);
1678 snd_pcm_close(u
->pcm_handle
);
1682 pa_alsa_fdlist_free(u
->mixer_fdl
);
1684 if (u
->mixer_path_set
)
1685 pa_alsa_path_set_free(u
->mixer_path_set
);
1686 else if (u
->mixer_path
)
1687 pa_alsa_path_free(u
->mixer_path
);
1689 if (u
->mixer_handle
)
1690 snd_mixer_close(u
->mixer_handle
);
1693 pa_smoother_free(u
->smoother
);
1698 pa_xfree(u
->device_name
);
1699 pa_xfree(u
->control_device
);
1703 void pa_alsa_source_free(pa_source
*s
) {
1706 pa_source_assert_ref(s
);
1707 pa_assert_se(u
= s
->userdata
);