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/xmalloc.h>
32 #include <pulse/util.h>
33 #include <pulse/timeval.h>
34 #include <pulse/i18n.h>
36 #include <pulsecore/core-error.h>
37 #include <pulsecore/core.h>
38 #include <pulsecore/module.h>
39 #include <pulsecore/memchunk.h>
40 #include <pulsecore/sink.h>
41 #include <pulsecore/modargs.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/sample-util.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/macro.h>
46 #include <pulsecore/thread.h>
47 #include <pulsecore/core-error.h>
48 #include <pulsecore/thread-mq.h>
49 #include <pulsecore/rtpoll.h>
50 #include <pulsecore/time-smoother.h>
51 #include <pulsecore/rtclock.h>
53 #include <modules/reserve-wrap.h>
55 #include "alsa-util.h"
56 #include "alsa-source.h"
58 /* #define DEBUG_TIMING */
60 #define DEFAULT_DEVICE "default"
61 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC) /* 2s */
62 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms */
63 #define TSCHED_WATERMARK_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
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 pa_alsa_path_set
*mixer_path_set
;
81 pa_alsa_path
*mixer_path
;
83 pa_cvolume hardware_volume
;
100 pa_bool_t use_mmap
:1, use_tsched
:1;
102 pa_rtpoll_item
*alsa_rtpoll_item
;
104 snd_mixer_selem_channel_id_t mixer_map
[SND_MIXER_SCHN_LAST
];
106 pa_smoother
*smoother
;
109 pa_reserve_wrapper
*reserve
;
110 pa_hook_slot
*reserve_slot
;
111 pa_reserve_monitor_wrapper
*monitor
;
112 pa_hook_slot
*monitor_slot
;
115 static void userdata_free(struct userdata
*u
);
117 static pa_hook_result_t
reserve_cb(pa_reserve_wrapper
*r
, void *forced
, struct userdata
*u
) {
121 if (pa_source_suspend(u
->source
, TRUE
, PA_SUSPEND_APPLICATION
) < 0)
122 return PA_HOOK_CANCEL
;
127 static void reserve_done(struct userdata
*u
) {
130 if (u
->reserve_slot
) {
131 pa_hook_slot_free(u
->reserve_slot
);
132 u
->reserve_slot
= NULL
;
136 pa_reserve_wrapper_unref(u
->reserve
);
141 static void reserve_update(struct userdata
*u
) {
142 const char *description
;
145 if (!u
->source
|| !u
->reserve
)
148 if ((description
= pa_proplist_gets(u
->source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)))
149 pa_reserve_wrapper_set_application_device_name(u
->reserve
, description
);
152 static int reserve_init(struct userdata
*u
, const char *dname
) {
161 if (pa_in_system_mode())
164 /* We are resuming, try to lock the device */
165 if (!(rname
= pa_alsa_get_reserve_name(dname
)))
168 u
->reserve
= pa_reserve_wrapper_get(u
->core
, rname
);
176 pa_assert(!u
->reserve_slot
);
177 u
->reserve_slot
= pa_hook_connect(pa_reserve_wrapper_hook(u
->reserve
), PA_HOOK_NORMAL
, (pa_hook_cb_t
) reserve_cb
, u
);
182 static pa_hook_result_t
monitor_cb(pa_reserve_monitor_wrapper
*w
, void* busy
, struct userdata
*u
) {
188 b
= PA_PTR_TO_UINT(busy
) && !u
->reserve
;
190 pa_source_suspend(u
->source
, b
, PA_SUSPEND_APPLICATION
);
194 static void monitor_done(struct userdata
*u
) {
197 if (u
->monitor_slot
) {
198 pa_hook_slot_free(u
->monitor_slot
);
199 u
->monitor_slot
= NULL
;
203 pa_reserve_monitor_wrapper_unref(u
->monitor
);
208 static int reserve_monitor_init(struct userdata
*u
, const char *dname
) {
214 if (pa_in_system_mode())
217 /* We are resuming, try to lock the device */
218 if (!(rname
= pa_alsa_get_reserve_name(dname
)))
221 u
->monitor
= pa_reserve_monitor_wrapper_get(u
->core
, rname
);
227 pa_assert(!u
->monitor_slot
);
228 u
->monitor_slot
= pa_hook_connect(pa_reserve_monitor_wrapper_hook(u
->monitor
), PA_HOOK_NORMAL
, (pa_hook_cb_t
) monitor_cb
, u
);
233 static void fix_min_sleep_wakeup(struct userdata
*u
) {
234 size_t max_use
, max_use_2
;
237 max_use
= u
->hwbuf_size
- u
->hwbuf_unused
;
238 max_use_2
= pa_frame_align(max_use
/2, &u
->source
->sample_spec
);
240 u
->min_sleep
= pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC
, &u
->source
->sample_spec
);
241 u
->min_sleep
= PA_CLAMP(u
->min_sleep
, u
->frame_size
, max_use_2
);
243 u
->min_wakeup
= pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC
, &u
->source
->sample_spec
);
244 u
->min_wakeup
= PA_CLAMP(u
->min_wakeup
, u
->frame_size
, max_use_2
);
247 static void fix_tsched_watermark(struct userdata
*u
) {
251 max_use
= u
->hwbuf_size
- u
->hwbuf_unused
;
253 if (u
->tsched_watermark
> max_use
- u
->min_sleep
)
254 u
->tsched_watermark
= max_use
- u
->min_sleep
;
256 if (u
->tsched_watermark
< u
->min_wakeup
)
257 u
->tsched_watermark
= u
->min_wakeup
;
260 static void adjust_after_overrun(struct userdata
*u
) {
261 size_t old_watermark
;
262 pa_usec_t old_min_latency
, new_min_latency
;
265 pa_assert(u
->use_tsched
);
267 /* First, just try to increase the watermark */
268 old_watermark
= u
->tsched_watermark
;
269 u
->tsched_watermark
= PA_MIN(u
->tsched_watermark
* 2, u
->tsched_watermark
+ u
->watermark_step
);
271 fix_tsched_watermark(u
);
273 if (old_watermark
!= u
->tsched_watermark
) {
274 pa_log_notice("Increasing wakeup watermark to %0.2f ms",
275 (double) pa_bytes_to_usec(u
->tsched_watermark
, &u
->source
->sample_spec
) / PA_USEC_PER_MSEC
);
279 /* Hmm, we cannot increase the watermark any further, hence let's raise the latency */
280 old_min_latency
= u
->source
->thread_info
.min_latency
;
281 new_min_latency
= PA_MIN(old_min_latency
* 2, old_min_latency
+ TSCHED_WATERMARK_STEP_USEC
);
282 new_min_latency
= PA_MIN(new_min_latency
, u
->source
->thread_info
.max_latency
);
284 if (old_min_latency
!= new_min_latency
) {
285 pa_log_notice("Increasing minimal latency to %0.2f ms",
286 (double) new_min_latency
/ PA_USEC_PER_MSEC
);
288 pa_source_set_latency_range_within_thread(u
->source
, new_min_latency
, u
->source
->thread_info
.max_latency
);
292 /* When we reach this we're officialy fucked! */
295 static pa_usec_t
hw_sleep_time(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_usec_t
*process_usec
) {
300 usec
= pa_source_get_requested_latency_within_thread(u
->source
);
302 if (usec
== (pa_usec_t
) -1)
303 usec
= pa_bytes_to_usec(u
->hwbuf_size
, &u
->source
->sample_spec
);
305 wm
= pa_bytes_to_usec(u
->tsched_watermark
, &u
->source
->sample_spec
);
310 *sleep_usec
= usec
- wm
;
314 pa_log_debug("Buffer time: %lu ms; Sleep time: %lu ms; Process time: %lu ms",
315 (unsigned long) (usec
/ PA_USEC_PER_MSEC
),
316 (unsigned long) (*sleep_usec
/ PA_USEC_PER_MSEC
),
317 (unsigned long) (*process_usec
/ PA_USEC_PER_MSEC
));
323 static int try_recover(struct userdata
*u
, const char *call
, int err
) {
328 pa_log_debug("%s: %s", call
, pa_alsa_strerror(err
));
330 pa_assert(err
!= -EAGAIN
);
333 pa_log_debug("%s: Buffer overrun!", call
);
335 if ((err
= snd_pcm_recover(u
->pcm_handle
, err
, 1)) < 0) {
336 pa_log("%s: %s", call
, pa_alsa_strerror(err
));
340 snd_pcm_start(u
->pcm_handle
);
344 static size_t check_left_to_record(struct userdata
*u
, size_t n_bytes
) {
345 size_t left_to_record
;
346 size_t rec_space
= u
->hwbuf_size
- u
->hwbuf_unused
;
348 /* We use <= instead of < for this check here because an overrun
349 * only happens after the last sample was processed, not already when
350 * it is removed from the buffer. This is particularly important
351 * when block transfer is used. */
353 if (n_bytes
<= rec_space
) {
354 left_to_record
= rec_space
- n_bytes
;
357 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
);
367 if (pa_log_ratelimit())
368 pa_log_info("Overrun!");
371 adjust_after_overrun(u
);
374 return left_to_record
;
377 static int mmap_read(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
378 pa_bool_t work_done
= FALSE
;
379 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
380 size_t left_to_record
;
384 pa_source_assert_ref(u
->source
);
387 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
394 if (PA_UNLIKELY((n
= pa_alsa_safe_avail(u
->pcm_handle
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
396 if ((r
= try_recover(u
, "snd_pcm_avail", (int) n
)) == 0)
402 n_bytes
= (size_t) n
* u
->frame_size
;
405 pa_log_debug("avail: %lu", (unsigned long) n_bytes
);
408 left_to_record
= check_left_to_record(u
, n_bytes
);
412 pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
) > process_usec
+max_sleep_usec
/2) {
414 pa_log_debug("Not reading, because too early.");
419 if (PA_UNLIKELY(n_bytes
<= 0)) {
423 char *dn
= pa_alsa_get_driver_name_by_pcm(u
->pcm_handle
);
424 pa_log(_("ALSA woke us up to read new data from the device, but there was actually nothing to read!\n"
425 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n"
426 "We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail."),
432 pa_log_debug("Not reading, because not necessary.");
439 pa_log_debug("Not filling up, because already too many iterations.");
448 pa_log_debug("Reading");
453 const snd_pcm_channel_area_t
*areas
;
454 snd_pcm_uframes_t offset
, frames
;
457 snd_pcm_sframes_t sframes
;
459 frames
= (snd_pcm_uframes_t
) (n_bytes
/ u
->frame_size
);
461 /* pa_log_debug("%lu frames to read", (unsigned long) frames); */
463 if (PA_UNLIKELY((err
= pa_alsa_safe_mmap_begin(u
->pcm_handle
, &areas
, &offset
, &frames
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
465 if ((r
= try_recover(u
, "snd_pcm_mmap_begin", err
)) == 0)
471 /* Make sure that if these memblocks need to be copied they will fit into one slot */
472 if (frames
> pa_mempool_block_size_max(u
->source
->core
->mempool
)/u
->frame_size
)
473 frames
= pa_mempool_block_size_max(u
->source
->core
->mempool
)/u
->frame_size
;
475 /* Check these are multiples of 8 bit */
476 pa_assert((areas
[0].first
& 7) == 0);
477 pa_assert((areas
[0].step
& 7)== 0);
479 /* We assume a single interleaved memory buffer */
480 pa_assert((areas
[0].first
>> 3) == 0);
481 pa_assert((areas
[0].step
>> 3) == u
->frame_size
);
483 p
= (uint8_t*) areas
[0].addr
+ (offset
* u
->frame_size
);
485 chunk
.memblock
= pa_memblock_new_fixed(u
->core
->mempool
, p
, frames
* u
->frame_size
, TRUE
);
486 chunk
.length
= pa_memblock_get_length(chunk
.memblock
);
489 pa_source_post(u
->source
, &chunk
);
490 pa_memblock_unref_fixed(chunk
.memblock
);
492 if (PA_UNLIKELY((sframes
= snd_pcm_mmap_commit(u
->pcm_handle
, offset
, frames
)) < 0)) {
494 if ((r
= try_recover(u
, "snd_pcm_mmap_commit", (int) sframes
)) == 0)
502 u
->read_count
+= frames
* u
->frame_size
;
505 pa_log_debug("Read %lu bytes (of possible %lu bytes)", (unsigned long) (frames
* u
->frame_size
), (unsigned long) n_bytes
);
508 if ((size_t) frames
* u
->frame_size
>= n_bytes
)
511 n_bytes
-= (size_t) frames
* u
->frame_size
;
515 *sleep_usec
= pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
);
517 if (*sleep_usec
> process_usec
)
518 *sleep_usec
-= process_usec
;
522 return work_done
? 1 : 0;
525 static int unix_read(struct userdata
*u
, pa_usec_t
*sleep_usec
, pa_bool_t polled
) {
526 int work_done
= FALSE
;
527 pa_usec_t max_sleep_usec
= 0, process_usec
= 0;
528 size_t left_to_record
;
532 pa_source_assert_ref(u
->source
);
535 hw_sleep_time(u
, &max_sleep_usec
, &process_usec
);
542 if (PA_UNLIKELY((n
= pa_alsa_safe_avail(u
->pcm_handle
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
544 if ((r
= try_recover(u
, "snd_pcm_avail", (int) n
)) == 0)
550 n_bytes
= (size_t) n
* u
->frame_size
;
551 left_to_record
= check_left_to_record(u
, n_bytes
);
555 pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
) > process_usec
+max_sleep_usec
/2)
558 if (PA_UNLIKELY(n_bytes
<= 0)) {
562 char *dn
= pa_alsa_get_driver_name_by_pcm(u
->pcm_handle
);
563 pa_log(_("ALSA woke us up to read new data from the device, but there was actually nothing to read!\n"
564 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n"
565 "We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail."),
575 pa_log_debug("Not filling up, because already too many iterations.");
585 snd_pcm_sframes_t frames
;
588 chunk
.memblock
= pa_memblock_new(u
->core
->mempool
, (size_t) -1);
590 frames
= (snd_pcm_sframes_t
) (pa_memblock_get_length(chunk
.memblock
) / u
->frame_size
);
592 if (frames
> (snd_pcm_sframes_t
) (n_bytes
/u
->frame_size
))
593 frames
= (snd_pcm_sframes_t
) (n_bytes
/u
->frame_size
);
595 /* pa_log_debug("%lu frames to read", (unsigned long) n); */
597 p
= pa_memblock_acquire(chunk
.memblock
);
598 frames
= snd_pcm_readi(u
->pcm_handle
, (uint8_t*) p
, (snd_pcm_uframes_t
) frames
);
599 pa_memblock_release(chunk
.memblock
);
601 pa_assert(frames
!= 0);
603 if (PA_UNLIKELY(frames
< 0)) {
604 pa_memblock_unref(chunk
.memblock
);
606 if ((r
= try_recover(u
, "snd_pcm_readi", (int) (frames
))) == 0)
613 chunk
.length
= (size_t) frames
* u
->frame_size
;
615 pa_source_post(u
->source
, &chunk
);
616 pa_memblock_unref(chunk
.memblock
);
620 u
->read_count
+= frames
* u
->frame_size
;
622 /* pa_log_debug("read %lu frames", (unsigned long) frames); */
624 if ((size_t) frames
* u
->frame_size
>= n_bytes
)
627 n_bytes
-= (size_t) frames
* u
->frame_size
;
631 *sleep_usec
= pa_bytes_to_usec(left_to_record
, &u
->source
->sample_spec
);
633 if (*sleep_usec
> process_usec
)
634 *sleep_usec
-= process_usec
;
638 return work_done
? 1 : 0;
641 static void update_smoother(struct userdata
*u
) {
642 snd_pcm_sframes_t delay
= 0;
645 pa_usec_t now1
= 0, now2
;
646 snd_pcm_status_t
*status
;
648 snd_pcm_status_alloca(&status
);
651 pa_assert(u
->pcm_handle
);
653 /* Let's update the time smoother */
655 if (PA_UNLIKELY((err
= pa_alsa_safe_delay(u
->pcm_handle
, &delay
, u
->hwbuf_size
, &u
->source
->sample_spec
)) < 0)) {
656 pa_log_warn("Failed to get delay: %s", pa_alsa_strerror(err
));
660 if (PA_UNLIKELY((err
= snd_pcm_status(u
->pcm_handle
, status
)) < 0))
661 pa_log_warn("Failed to get timestamp: %s", pa_alsa_strerror(err
));
663 snd_htimestamp_t htstamp
= { 0, 0 };
664 snd_pcm_status_get_htstamp(status
, &htstamp
);
665 now1
= pa_timespec_load(&htstamp
);
668 position
= u
->read_count
+ ((uint64_t) delay
* (uint64_t) u
->frame_size
);
670 /* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
672 now1
= pa_rtclock_usec();
674 now2
= pa_bytes_to_usec(position
, &u
->source
->sample_spec
);
676 pa_smoother_put(u
->smoother
, now1
, now2
);
679 static pa_usec_t
source_get_latency(struct userdata
*u
) {
681 pa_usec_t now1
, now2
;
685 now1
= pa_rtclock_usec();
686 now2
= pa_smoother_get(u
->smoother
, now1
);
688 delay
= (int64_t) now2
- (int64_t) pa_bytes_to_usec(u
->read_count
, &u
->source
->sample_spec
);
690 return delay
>= 0 ? (pa_usec_t
) delay
: 0;
693 static int build_pollfd(struct userdata
*u
) {
695 pa_assert(u
->pcm_handle
);
697 if (u
->alsa_rtpoll_item
)
698 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
700 if (!(u
->alsa_rtpoll_item
= pa_alsa_build_pollfd(u
->pcm_handle
, u
->rtpoll
)))
706 static int suspend(struct userdata
*u
) {
708 pa_assert(u
->pcm_handle
);
710 pa_smoother_pause(u
->smoother
, pa_rtclock_usec());
713 snd_pcm_close(u
->pcm_handle
);
714 u
->pcm_handle
= NULL
;
716 if (u
->alsa_rtpoll_item
) {
717 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
718 u
->alsa_rtpoll_item
= NULL
;
721 pa_log_info("Device suspended...");
726 static int update_sw_params(struct userdata
*u
) {
727 snd_pcm_uframes_t avail_min
;
732 /* Use the full buffer if noone asked us for anything specific */
738 if ((latency
= pa_source_get_requested_latency_within_thread(u
->source
)) != (pa_usec_t
) -1) {
741 pa_log_debug("latency set to %0.2fms", (double) latency
/ PA_USEC_PER_MSEC
);
743 b
= pa_usec_to_bytes(latency
, &u
->source
->sample_spec
);
745 /* We need at least one sample in our buffer */
747 if (PA_UNLIKELY(b
< u
->frame_size
))
750 u
->hwbuf_unused
= PA_LIKELY(b
< u
->hwbuf_size
) ? (u
->hwbuf_size
- b
) : 0;
753 fix_min_sleep_wakeup(u
);
754 fix_tsched_watermark(u
);
757 pa_log_debug("hwbuf_unused=%lu", (unsigned long) u
->hwbuf_unused
);
762 pa_usec_t sleep_usec
, process_usec
;
764 hw_sleep_time(u
, &sleep_usec
, &process_usec
);
765 avail_min
+= pa_usec_to_bytes(sleep_usec
, &u
->source
->sample_spec
) / u
->frame_size
;
768 pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min
);
770 if ((err
= pa_alsa_set_sw_params(u
->pcm_handle
, avail_min
)) < 0) {
771 pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err
));
778 static int unsuspend(struct userdata
*u
) {
783 snd_pcm_uframes_t period_size
;
786 pa_assert(!u
->pcm_handle
);
788 pa_log_info("Trying resume...");
790 snd_config_update_free_global();
792 if ((err
= snd_pcm_open(&u
->pcm_handle
, u
->device_name
, SND_PCM_STREAM_CAPTURE
,
793 /*SND_PCM_NONBLOCK|*/
794 SND_PCM_NO_AUTO_RESAMPLE
|
795 SND_PCM_NO_AUTO_CHANNELS
|
796 SND_PCM_NO_AUTO_FORMAT
)) < 0) {
797 pa_log("Error opening PCM device %s: %s", u
->device_name
, pa_alsa_strerror(err
));
801 ss
= u
->source
->sample_spec
;
802 nfrags
= u
->nfragments
;
803 period_size
= u
->fragment_size
/ u
->frame_size
;
807 if ((err
= pa_alsa_set_hw_params(u
->pcm_handle
, &ss
, &nfrags
, &period_size
, u
->hwbuf_size
/ u
->frame_size
, &b
, &d
, TRUE
)) < 0) {
808 pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err
));
812 if (b
!= u
->use_mmap
|| d
!= u
->use_tsched
) {
813 pa_log_warn("Resume failed, couldn't get original access mode.");
817 if (!pa_sample_spec_equal(&ss
, &u
->source
->sample_spec
)) {
818 pa_log_warn("Resume failed, couldn't restore original sample settings.");
822 if (nfrags
!= u
->nfragments
|| period_size
*u
->frame_size
!= u
->fragment_size
) {
823 pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
824 (unsigned long) u
->nfragments
, (unsigned long) u
->fragment_size
,
825 (unsigned long) nfrags
, period_size
* u
->frame_size
);
829 if (update_sw_params(u
) < 0)
832 if (build_pollfd(u
) < 0)
835 /* FIXME: We need to reload the volume somehow */
837 snd_pcm_start(u
->pcm_handle
);
838 pa_smoother_resume(u
->smoother
, pa_rtclock_usec(), TRUE
);
840 pa_log_info("Resumed successfully...");
846 snd_pcm_close(u
->pcm_handle
);
847 u
->pcm_handle
= NULL
;
853 static int source_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
854 struct userdata
*u
= PA_SOURCE(o
)->userdata
;
858 case PA_SOURCE_MESSAGE_GET_LATENCY
: {
862 r
= source_get_latency(u
);
864 *((pa_usec_t
*) data
) = r
;
869 case PA_SOURCE_MESSAGE_SET_STATE
:
871 switch ((pa_source_state_t
) PA_PTR_TO_UINT(data
)) {
873 case PA_SOURCE_SUSPENDED
:
874 pa_assert(PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
));
882 case PA_SOURCE_RUNNING
:
884 if (u
->source
->thread_info
.state
== PA_SOURCE_INIT
) {
885 if (build_pollfd(u
) < 0)
888 snd_pcm_start(u
->pcm_handle
);
891 if (u
->source
->thread_info
.state
== PA_SOURCE_SUSPENDED
) {
892 if (unsuspend(u
) < 0)
898 case PA_SOURCE_UNLINKED
:
900 case PA_SOURCE_INVALID_STATE
:
907 return pa_source_process_msg(o
, code
, data
, offset
, chunk
);
910 /* Called from main context */
911 static int source_set_state_cb(pa_source
*s
, pa_source_state_t new_state
) {
912 pa_source_state_t old_state
;
915 pa_source_assert_ref(s
);
916 pa_assert_se(u
= s
->userdata
);
918 old_state
= pa_source_get_state(u
->source
);
920 if (PA_SINK_IS_OPENED(old_state
) && new_state
== PA_SINK_SUSPENDED
)
922 else if (old_state
== PA_SINK_SUSPENDED
&& PA_SINK_IS_OPENED(new_state
))
923 if (reserve_init(u
, u
->device_name
) < 0)
929 static int mixer_callback(snd_mixer_elem_t
*elem
, unsigned int mask
) {
930 struct userdata
*u
= snd_mixer_elem_get_callback_private(elem
);
933 pa_assert(u
->mixer_handle
);
935 if (mask
== SND_CTL_EVENT_MASK_REMOVE
)
938 if (mask
& SND_CTL_EVENT_MASK_VALUE
) {
939 pa_source_get_volume(u
->source
, TRUE
);
940 pa_source_get_mute(u
->source
, TRUE
);
946 static void source_get_volume_cb(pa_source
*s
) {
947 struct userdata
*u
= s
->userdata
;
949 char t
[PA_CVOLUME_SNPRINT_MAX
];
952 pa_assert(u
->mixer_path
);
953 pa_assert(u
->mixer_handle
);
955 if (pa_alsa_path_get_volume(u
->mixer_path
, u
->mixer_handle
, &s
->channel_map
, &r
) < 0)
958 /* Shift down by the base volume, so that 0dB becomes maximum volume */
959 pa_sw_cvolume_multiply_scalar(&r
, &r
, s
->base_volume
);
961 pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
963 if (pa_cvolume_equal(&u
->hardware_volume
, &r
))
966 s
->virtual_volume
= u
->hardware_volume
= r
;
968 if (u
->mixer_path
->has_dB
) {
971 /* Hmm, so the hardware volume changed, let's reset our software volume */
972 pa_cvolume_reset(&reset
, s
->sample_spec
.channels
);
973 pa_source_set_soft_volume(s
, &reset
);
977 static void source_set_volume_cb(pa_source
*s
) {
978 struct userdata
*u
= s
->userdata
;
980 char t
[PA_CVOLUME_SNPRINT_MAX
];
983 pa_assert(u
->mixer_path
);
984 pa_assert(u
->mixer_handle
);
986 /* Shift up by the base volume */
987 pa_sw_cvolume_divide_scalar(&r
, &s
->virtual_volume
, s
->base_volume
);
989 if (pa_alsa_path_set_volume(u
->mixer_path
, u
->mixer_handle
, &s
->channel_map
, &r
) < 0)
992 /* Shift down by the base volume, so that 0dB becomes maximum volume */
993 pa_sw_cvolume_multiply_scalar(&r
, &r
, s
->base_volume
);
995 u
->hardware_volume
= r
;
997 if (u
->mixer_path
->has_dB
) {
999 /* Match exactly what the user requested by software */
1000 pa_sw_cvolume_divide(&s
->soft_volume
, &s
->virtual_volume
, &u
->hardware_volume
);
1002 pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->virtual_volume
));
1003 pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &u
->hardware_volume
));
1004 pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &s
->soft_volume
));
1007 pa_log_debug("Wrote hardware volume: %s", pa_cvolume_snprint(t
, sizeof(t
), &r
));
1009 /* We can't match exactly what the user requested, hence let's
1010 * at least tell the user about it */
1012 s
->virtual_volume
= r
;
1016 static void source_get_mute_cb(pa_source
*s
) {
1017 struct userdata
*u
= s
->userdata
;
1021 pa_assert(u
->mixer_path
);
1022 pa_assert(u
->mixer_handle
);
1024 if (pa_alsa_path_get_mute(u
->mixer_path
, u
->mixer_handle
, &b
) < 0)
1030 static void source_set_mute_cb(pa_source
*s
) {
1031 struct userdata
*u
= s
->userdata
;
1034 pa_assert(u
->mixer_path
);
1035 pa_assert(u
->mixer_handle
);
1037 pa_alsa_path_set_mute(u
->mixer_path
, u
->mixer_handle
, s
->muted
);
1040 static int source_set_port_cb(pa_source
*s
, pa_device_port
*p
) {
1041 struct userdata
*u
= s
->userdata
;
1042 pa_alsa_port_data
*data
;
1046 pa_assert(u
->mixer_handle
);
1048 data
= PA_DEVICE_PORT_DATA(p
);
1050 pa_assert_se(u
->mixer_path
= data
->path
);
1051 pa_alsa_path_select(u
->mixer_path
, u
->mixer_handle
);
1053 if (u
->mixer_path
->has_volume
&& u
->mixer_path
->has_dB
) {
1054 s
->base_volume
= pa_sw_volume_from_dB(-u
->mixer_path
->max_dB
);
1055 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
1057 if (u
->mixer_path
->max_dB
> 0.0)
1058 pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(s
->base_volume
));
1060 pa_log_info("No particular base volume set, fixing to 0 dB");
1062 s
->base_volume
= PA_VOLUME_NORM
;
1063 s
->n_volume_steps
= u
->mixer_path
->max_volume
- u
->mixer_path
->min_volume
+ 1;
1067 pa_alsa_setting_select(data
->setting
, u
->mixer_handle
);
1077 static void source_update_requested_latency_cb(pa_source
*s
) {
1078 struct userdata
*u
= s
->userdata
;
1084 update_sw_params(u
);
1087 static void thread_func(void *userdata
) {
1088 struct userdata
*u
= userdata
;
1089 unsigned short revents
= 0;
1093 pa_log_debug("Thread starting up");
1095 if (u
->core
->realtime_scheduling
)
1096 pa_make_realtime(u
->core
->realtime_priority
);
1098 pa_thread_mq_install(&u
->thread_mq
);
1099 pa_rtpoll_install(u
->rtpoll
);
1105 pa_log_debug("Loop");
1108 /* Read some data and pass it to the sources */
1109 if (PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
)) {
1111 pa_usec_t sleep_usec
= 0;
1114 work_done
= mmap_read(u
, &sleep_usec
, revents
& POLLIN
);
1116 work_done
= unix_read(u
, &sleep_usec
, revents
& POLLIN
);
1121 /* pa_log_debug("work_done = %i", work_done); */
1126 if (u
->use_tsched
) {
1129 /* OK, the capture buffer is now empty, let's
1130 * calculate when to wake up next */
1132 /* pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
1134 /* Convert from the sound card time domain to the
1135 * system time domain */
1136 cusec
= pa_smoother_translate(u
->smoother
, pa_rtclock_usec(), sleep_usec
);
1138 /* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
1140 /* We don't trust the conversion, so we wake up whatever comes first */
1141 pa_rtpoll_set_timer_relative(u
->rtpoll
, PA_MIN(sleep_usec
, cusec
));
1143 } else if (u
->use_tsched
)
1145 /* OK, we're in an invalid state, let's disable our timers */
1146 pa_rtpoll_set_timer_disabled(u
->rtpoll
);
1148 /* Hmm, nothing to do. Let's sleep */
1149 if ((ret
= pa_rtpoll_run(u
->rtpoll
, TRUE
)) < 0)
1155 /* Tell ALSA about this and process its response */
1156 if (PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
)) {
1157 struct pollfd
*pollfd
;
1161 pollfd
= pa_rtpoll_item_get_pollfd(u
->alsa_rtpoll_item
, &n
);
1163 if ((err
= snd_pcm_poll_descriptors_revents(u
->pcm_handle
, pollfd
, n
, &revents
)) < 0) {
1164 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", pa_alsa_strerror(err
));
1168 if (revents
& ~POLLIN
) {
1169 if (pa_alsa_recover_from_poll(u
->pcm_handle
, revents
) < 0)
1172 snd_pcm_start(u
->pcm_handle
);
1173 } else if (revents
&& u
->use_tsched
&& pa_log_ratelimit())
1174 pa_log_debug("Wakeup from ALSA!");
1181 /* If this was no regular exit from the loop we have to continue
1182 * processing messages until we received PA_MESSAGE_SHUTDOWN */
1183 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
1184 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
1187 pa_log_debug("Thread shutting down");
1190 static void set_source_name(pa_source_new_data
*data
, pa_modargs
*ma
, const char *device_id
, const char *device_name
) {
1196 pa_assert(device_name
);
1198 if ((n
= pa_modargs_get_value(ma
, "source_name", NULL
))) {
1199 pa_source_new_data_set_name(data
, n
);
1200 data
->namereg_fail
= TRUE
;
1204 if ((n
= pa_modargs_get_value(ma
, "name", NULL
)))
1205 data
->namereg_fail
= TRUE
;
1207 n
= device_id
? device_id
: device_name
;
1208 data
->namereg_fail
= FALSE
;
1211 t
= pa_sprintf_malloc("alsa_input.%s", n
);
1212 pa_source_new_data_set_name(data
, t
);
1216 static void find_mixer(struct userdata
*u
, pa_alsa_mapping
*mapping
, const char *element
, pa_bool_t ignore_dB
) {
1218 if (!mapping
&& !element
)
1221 if (!(u
->mixer_handle
= pa_alsa_open_mixer_for_pcm(u
->pcm_handle
, &u
->control_device
))) {
1222 pa_log_info("Failed to find a working mixer device.");
1228 if (!(u
->mixer_path
= pa_alsa_path_synthesize(element
, PA_ALSA_DIRECTION_INPUT
)))
1231 if (pa_alsa_path_probe(u
->mixer_path
, u
->mixer_handle
, ignore_dB
) < 0)
1234 pa_log_debug("Probed mixer path %s:", u
->mixer_path
->name
);
1235 pa_alsa_path_dump(u
->mixer_path
);
1238 if (!(u
->mixer_path_set
= pa_alsa_path_set_new(mapping
, PA_ALSA_DIRECTION_INPUT
)))
1241 pa_alsa_path_set_probe(u
->mixer_path_set
, u
->mixer_handle
, ignore_dB
);
1243 pa_log_debug("Probed mixer paths:");
1244 pa_alsa_path_set_dump(u
->mixer_path_set
);
1251 if (u
->mixer_path_set
) {
1252 pa_alsa_path_set_free(u
->mixer_path_set
);
1253 u
->mixer_path_set
= NULL
;
1254 } else if (u
->mixer_path
) {
1255 pa_alsa_path_free(u
->mixer_path
);
1256 u
->mixer_path
= NULL
;
1259 if (u
->mixer_handle
) {
1260 snd_mixer_close(u
->mixer_handle
);
1261 u
->mixer_handle
= NULL
;
1265 static int setup_mixer(struct userdata
*u
, pa_bool_t ignore_dB
) {
1268 if (!u
->mixer_handle
)
1271 if (u
->source
->active_port
) {
1272 pa_alsa_port_data
*data
;
1274 /* We have a list of supported paths, so let's activate the
1275 * one that has been chosen as active */
1277 data
= PA_DEVICE_PORT_DATA(u
->source
->active_port
);
1278 u
->mixer_path
= data
->path
;
1280 pa_alsa_path_select(data
->path
, u
->mixer_handle
);
1283 pa_alsa_setting_select(data
->setting
, u
->mixer_handle
);
1287 if (!u
->mixer_path
&& u
->mixer_path_set
)
1288 u
->mixer_path
= u
->mixer_path_set
->paths
;
1290 if (u
->mixer_path
) {
1291 /* Hmm, we have only a single path, then let's activate it */
1293 pa_alsa_path_select(u
->mixer_path
, u
->mixer_handle
);
1295 if (u
->mixer_path
->settings
)
1296 pa_alsa_setting_select(u
->mixer_path
->settings
, u
->mixer_handle
);
1301 if (!u
->mixer_path
->has_volume
)
1302 pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
1305 if (u
->mixer_path
->has_dB
) {
1306 pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u
->mixer_path
->min_dB
, u
->mixer_path
->max_dB
);
1308 u
->source
->base_volume
= pa_sw_volume_from_dB(-u
->mixer_path
->max_dB
);
1309 u
->source
->n_volume_steps
= PA_VOLUME_NORM
+1;
1311 if (u
->mixer_path
->max_dB
> 0.0)
1312 pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u
->source
->base_volume
));
1314 pa_log_info("No particular base volume set, fixing to 0 dB");
1317 pa_log_info("Hardware volume ranges from %li to %li.", u
->mixer_path
->min_volume
, u
->mixer_path
->max_volume
);
1318 u
->source
->base_volume
= PA_VOLUME_NORM
;
1319 u
->source
->n_volume_steps
= u
->mixer_path
->max_volume
- u
->mixer_path
->min_volume
+ 1;
1322 u
->source
->get_volume
= source_get_volume_cb
;
1323 u
->source
->set_volume
= source_set_volume_cb
;
1325 u
->source
->flags
|= PA_SOURCE_HW_VOLUME_CTRL
| (u
->mixer_path
->has_dB
? PA_SOURCE_DECIBEL_VOLUME
: 0);
1326 pa_log_info("Using hardware volume control. Hardware dB scale %s.", u
->mixer_path
->has_dB
? "supported" : "not supported");
1329 if (!u
->mixer_path
->has_mute
) {
1330 pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
1332 u
->source
->get_mute
= source_get_mute_cb
;
1333 u
->source
->set_mute
= source_set_mute_cb
;
1334 u
->source
->flags
|= PA_SOURCE_HW_MUTE_CTRL
;
1335 pa_log_info("Using hardware mute control.");
1338 u
->mixer_fdl
= pa_alsa_fdlist_new();
1340 if (pa_alsa_fdlist_set_mixer(u
->mixer_fdl
, u
->mixer_handle
, u
->core
->mainloop
) < 0) {
1341 pa_log("Failed to initialize file descriptor monitoring");
1345 if (u
->mixer_path_set
)
1346 pa_alsa_path_set_set_callback(u
->mixer_path_set
, u
->mixer_handle
, mixer_callback
, u
);
1348 pa_alsa_path_set_callback(u
->mixer_path
, u
->mixer_handle
, mixer_callback
, u
);
1353 pa_source
*pa_alsa_source_new(pa_module
*m
, pa_modargs
*ma
, const char*driver
, pa_card
*card
, pa_alsa_mapping
*mapping
) {
1355 struct userdata
*u
= NULL
;
1356 const char *dev_id
= NULL
;
1357 pa_sample_spec ss
, requested_ss
;
1359 uint32_t nfrags
, hwbuf_size
, frag_size
, tsched_size
, tsched_watermark
;
1360 snd_pcm_uframes_t period_frames
, tsched_frames
;
1362 pa_bool_t use_mmap
= TRUE
, b
, use_tsched
= TRUE
, d
, ignore_dB
= FALSE
;
1363 pa_source_new_data data
;
1364 pa_alsa_profile_set
*profile_set
= NULL
;
1369 ss
= m
->core
->default_sample_spec
;
1370 map
= m
->core
->default_channel_map
;
1371 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_ALSA
) < 0) {
1372 pa_log("Failed to parse sample specification");
1377 frame_size
= pa_frame_size(&ss
);
1379 nfrags
= m
->core
->default_n_fragments
;
1380 frag_size
= (uint32_t) pa_usec_to_bytes(m
->core
->default_fragment_size_msec
*PA_USEC_PER_MSEC
, &ss
);
1382 frag_size
= (uint32_t) frame_size
;
1383 tsched_size
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC
, &ss
);
1384 tsched_watermark
= (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC
, &ss
);
1386 if (pa_modargs_get_value_u32(ma
, "fragments", &nfrags
) < 0 ||
1387 pa_modargs_get_value_u32(ma
, "fragment_size", &frag_size
) < 0 ||
1388 pa_modargs_get_value_u32(ma
, "tsched_buffer_size", &tsched_size
) < 0 ||
1389 pa_modargs_get_value_u32(ma
, "tsched_buffer_watermark", &tsched_watermark
) < 0) {
1390 pa_log("Failed to parse buffer metrics");
1394 hwbuf_size
= frag_size
* nfrags
;
1395 period_frames
= frag_size
/frame_size
;
1396 tsched_frames
= tsched_size
/frame_size
;
1398 if (pa_modargs_get_value_boolean(ma
, "mmap", &use_mmap
) < 0) {
1399 pa_log("Failed to parse mmap argument.");
1403 if (pa_modargs_get_value_boolean(ma
, "tsched", &use_tsched
) < 0) {
1404 pa_log("Failed to parse timer_scheduling argument.");
1408 if (pa_modargs_get_value_boolean(ma
, "ignore_dB", &ignore_dB
) < 0) {
1409 pa_log("Failed to parse ignore_dB argument.");
1413 if (use_tsched
&& !pa_rtclock_hrtimer()) {
1414 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1418 u
= pa_xnew0(struct userdata
, 1);
1421 u
->use_mmap
= use_mmap
;
1422 u
->use_tsched
= use_tsched
;
1423 u
->rtpoll
= pa_rtpoll_new();
1424 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
1426 u
->smoother
= pa_smoother_new(
1427 DEFAULT_TSCHED_WATERMARK_USEC
*2,
1428 DEFAULT_TSCHED_WATERMARK_USEC
*2,
1435 dev_id
= pa_modargs_get_value(
1437 pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
));
1439 if (reserve_init(u
, dev_id
) < 0)
1442 if (reserve_monitor_init(u
, dev_id
) < 0)
1450 if (!(dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1451 pa_log("device_id= not set");
1455 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id_mapping(
1459 SND_PCM_STREAM_CAPTURE
,
1460 &nfrags
, &period_frames
, tsched_frames
,
1464 } else if ((dev_id
= pa_modargs_get_value(ma
, "device_id", NULL
))) {
1466 if (!(profile_set
= pa_alsa_profile_set_new(NULL
, &map
)))
1469 if (!(u
->pcm_handle
= pa_alsa_open_by_device_id_auto(
1473 SND_PCM_STREAM_CAPTURE
,
1474 &nfrags
, &period_frames
, tsched_frames
,
1475 &b
, &d
, profile_set
, &mapping
)))
1480 if (!(u
->pcm_handle
= pa_alsa_open_by_device_string(
1481 pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
),
1484 SND_PCM_STREAM_CAPTURE
,
1485 &nfrags
, &period_frames
, tsched_frames
,
1490 pa_assert(u
->device_name
);
1491 pa_log_info("Successfully opened device %s.", u
->device_name
);
1493 if (pa_alsa_pcm_is_modem(u
->pcm_handle
)) {
1494 pa_log_notice("Device %s is modem, refusing further initialization.", u
->device_name
);
1499 pa_log_info("Selected mapping '%s' (%s).", mapping
->description
, mapping
->name
);
1501 if (use_mmap
&& !b
) {
1502 pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
1503 u
->use_mmap
= use_mmap
= FALSE
;
1506 if (use_tsched
&& (!b
|| !d
)) {
1507 pa_log_info("Cannot enable timer-based scheduling, falling back to sound IRQ scheduling.");
1508 u
->use_tsched
= use_tsched
= FALSE
;
1511 if (use_tsched
&& !pa_alsa_pcm_is_hw(u
->pcm_handle
)) {
1512 pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
1513 u
->use_tsched
= use_tsched
= FALSE
;
1517 pa_log_info("Successfully enabled mmap() mode.");
1520 pa_log_info("Successfully enabled timer-based scheduling mode.");
1522 /* ALSA might tweak the sample spec, so recalculate the frame size */
1523 frame_size
= pa_frame_size(&ss
);
1525 find_mixer(u
, mapping
, pa_modargs_get_value(ma
, "control", NULL
), ignore_dB
);
1527 pa_source_new_data_init(&data
);
1528 data
.driver
= driver
;
1531 set_source_name(&data
, ma
, dev_id
, u
->device_name
);
1532 pa_source_new_data_set_sample_spec(&data
, &ss
);
1533 pa_source_new_data_set_channel_map(&data
, &map
);
1535 pa_alsa_init_proplist_pcm(m
->core
, data
.proplist
, u
->pcm_handle
);
1536 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
1537 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
* nfrags
));
1538 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE
, "%lu", (unsigned long) (period_frames
* frame_size
));
1539 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, u
->use_tsched
? "mmap+timer" : (u
->use_mmap
? "mmap" : "serial"));
1542 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_NAME
, mapping
->name
);
1543 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
, mapping
->description
);
1546 pa_alsa_init_description(data
.proplist
);
1548 if (u
->control_device
)
1549 pa_alsa_init_proplist_ctl(data
.proplist
, u
->control_device
);
1551 if (pa_modargs_get_proplist(ma
, "source_properties", data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1552 pa_log("Invalid properties");
1553 pa_source_new_data_done(&data
);
1557 if (u
->mixer_path_set
)
1558 pa_alsa_add_ports(&data
.ports
, u
->mixer_path_set
);
1560 u
->source
= pa_source_new(m
->core
, &data
, PA_SOURCE_HARDWARE
|PA_SOURCE_LATENCY
|(u
->use_tsched
? PA_SOURCE_DYNAMIC_LATENCY
: 0));
1561 pa_source_new_data_done(&data
);
1564 pa_log("Failed to create source object");
1568 u
->source
->parent
.process_msg
= source_process_msg
;
1569 u
->source
->update_requested_latency
= source_update_requested_latency_cb
;
1570 u
->source
->set_state
= source_set_state_cb
;
1571 u
->source
->set_port
= source_set_port_cb
;
1572 u
->source
->userdata
= u
;
1574 pa_source_set_asyncmsgq(u
->source
, u
->thread_mq
.inq
);
1575 pa_source_set_rtpoll(u
->source
, u
->rtpoll
);
1577 u
->frame_size
= frame_size
;
1578 u
->fragment_size
= frag_size
= (uint32_t) (period_frames
* frame_size
);
1579 u
->nfragments
= nfrags
;
1580 u
->hwbuf_size
= u
->fragment_size
* nfrags
;
1581 u
->tsched_watermark
= pa_usec_to_bytes_round_up(pa_bytes_to_usec_round_up(tsched_watermark
, &requested_ss
), &u
->source
->sample_spec
);
1582 pa_cvolume_mute(&u
->hardware_volume
, u
->source
->sample_spec
.channels
);
1584 pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
1585 nfrags
, (long unsigned) u
->fragment_size
,
1586 (double) pa_bytes_to_usec(u
->hwbuf_size
, &ss
) / PA_USEC_PER_MSEC
);
1588 if (u
->use_tsched
) {
1589 u
->watermark_step
= pa_usec_to_bytes(TSCHED_WATERMARK_STEP_USEC
, &u
->source
->sample_spec
);
1591 fix_min_sleep_wakeup(u
);
1592 fix_tsched_watermark(u
);
1594 pa_source_set_latency_range(u
->source
,
1596 pa_bytes_to_usec(u
->hwbuf_size
, &ss
));
1598 pa_log_info("Time scheduling watermark is %0.2fms",
1599 (double) pa_bytes_to_usec(u
->tsched_watermark
, &ss
) / PA_USEC_PER_MSEC
);
1601 pa_source_set_fixed_latency(u
->source
, pa_bytes_to_usec(u
->hwbuf_size
, &ss
));
1605 if (update_sw_params(u
) < 0)
1608 if (setup_mixer(u
, ignore_dB
) < 0)
1611 pa_alsa_dump(PA_LOG_DEBUG
, u
->pcm_handle
);
1613 if (!(u
->thread
= pa_thread_new(thread_func
, u
))) {
1614 pa_log("Failed to create thread.");
1617 /* Get initial mixer settings */
1618 if (data
.volume_is_set
) {
1619 if (u
->source
->set_volume
)
1620 u
->source
->set_volume(u
->source
);
1622 if (u
->source
->get_volume
)
1623 u
->source
->get_volume(u
->source
);
1626 if (data
.muted_is_set
) {
1627 if (u
->source
->set_mute
)
1628 u
->source
->set_mute(u
->source
);
1630 if (u
->source
->get_mute
)
1631 u
->source
->get_mute(u
->source
);
1634 pa_source_put(u
->source
);
1637 pa_alsa_profile_set_free(profile_set
);
1647 pa_alsa_profile_set_free(profile_set
);
1652 static void userdata_free(struct userdata
*u
) {
1656 pa_source_unlink(u
->source
);
1659 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
1660 pa_thread_free(u
->thread
);
1663 pa_thread_mq_done(&u
->thread_mq
);
1666 pa_source_unref(u
->source
);
1668 if (u
->alsa_rtpoll_item
)
1669 pa_rtpoll_item_free(u
->alsa_rtpoll_item
);
1672 pa_rtpoll_free(u
->rtpoll
);
1674 if (u
->pcm_handle
) {
1675 snd_pcm_drop(u
->pcm_handle
);
1676 snd_pcm_close(u
->pcm_handle
);
1680 pa_alsa_fdlist_free(u
->mixer_fdl
);
1682 if (u
->mixer_path_set
)
1683 pa_alsa_path_set_free(u
->mixer_path_set
);
1684 else if (u
->mixer_path
)
1685 pa_alsa_path_free(u
->mixer_path
);
1687 if (u
->mixer_handle
)
1688 snd_mixer_close(u
->mixer_handle
);
1691 pa_smoother_free(u
->smoother
);
1696 pa_xfree(u
->device_name
);
1697 pa_xfree(u
->control_device
);
1701 void pa_alsa_source_free(pa_source
*s
) {
1704 pa_source_assert_ref(s
);
1705 pa_assert_se(u
= s
->userdata
);