]> code.delx.au - pulseaudio/blob - src/modules/module-alsa-sink.c
define minimal and maximal wakeup/sleep times; check for underrun condition only...
[pulseaudio] / src / modules / module-alsa-sink.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30
31 #include <asoundlib.h>
32
33 #include <pulse/xmalloc.h>
34 #include <pulse/util.h>
35 #include <pulse/timeval.h>
36
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/rtclock.h>
51 #include <pulsecore/time-smoother.h>
52
53 #include "alsa-util.h"
54 #include "module-alsa-sink-symdef.h"
55
56 PA_MODULE_AUTHOR("Lennart Poettering");
57 PA_MODULE_DESCRIPTION("ALSA Sink");
58 PA_MODULE_VERSION(PACKAGE_VERSION);
59 PA_MODULE_LOAD_ONCE(FALSE);
60 PA_MODULE_USAGE(
61 "sink_name=<name for the sink> "
62 "device=<ALSA device> "
63 "device_id=<ALSA card index> "
64 "format=<sample format> "
65 "rate=<sample rate> "
66 "channels=<number of channels> "
67 "channel_map=<channel map> "
68 "fragments=<number of fragments> "
69 "fragment_size=<fragment size> "
70 "mmap=<enable memory mapping?> "
71 "tsched=<enable system timer based scheduling mode?> "
72 "tsched_buffer_size=<buffer size when using timer based scheduling> "
73 "tsched_buffer_watermark=<lower fill watermark> "
74 "mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>");
75
76 static const char* const valid_modargs[] = {
77 "sink_name",
78 "device",
79 "device_id",
80 "format",
81 "rate",
82 "channels",
83 "channel_map",
84 "fragments",
85 "fragment_size",
86 "mmap",
87 "tsched",
88 "tsched_buffer_size",
89 "tsched_buffer_watermark",
90 "mixer_reset",
91 NULL
92 };
93
94 #define DEFAULT_DEVICE "default"
95 #define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC) /* 5s */
96 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms */
97 #define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC) /* 3ms */
98 #define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC) /* 3ms */
99
100 struct userdata {
101 pa_core *core;
102 pa_module *module;
103 pa_sink *sink;
104
105 pa_thread *thread;
106 pa_thread_mq thread_mq;
107 pa_rtpoll *rtpoll;
108
109 snd_pcm_t *pcm_handle;
110
111 pa_alsa_fdlist *mixer_fdl;
112 snd_mixer_t *mixer_handle;
113 snd_mixer_elem_t *mixer_elem;
114 long hw_volume_max, hw_volume_min;
115 long hw_dB_max, hw_dB_min;
116 pa_bool_t hw_dB_supported;
117
118 size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
119 unsigned nfragments;
120 pa_memchunk memchunk;
121
122 char *device_name;
123
124 pa_bool_t use_mmap, use_tsched;
125
126 pa_bool_t first, after_rewind;
127
128 pa_rtpoll_item *alsa_rtpoll_item;
129
130 snd_mixer_selem_channel_id_t mixer_map[SND_MIXER_SCHN_LAST];
131
132 pa_smoother *smoother;
133 int64_t frame_index;
134
135 snd_pcm_sframes_t hwbuf_unused_frames;
136 };
137
138 static void fix_tsched_watermark(struct userdata *u) {
139 size_t max_use;
140 size_t min_sleep, min_wakeup;
141 pa_assert(u);
142
143 max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
144
145 min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->sink->sample_spec);
146 min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->sink->sample_spec);
147
148 if (min_sleep > max_use/2)
149 min_sleep = pa_frame_align(max_use/2, &u->sink->sample_spec);
150 if (min_sleep < u->frame_size)
151 min_sleep = u->frame_size;
152
153 if (min_wakeup > max_use/2)
154 min_wakeup = pa_frame_align(max_use/2, &u->sink->sample_spec);
155 if (min_wakeup < u->frame_size)
156 min_wakeup = u->frame_size;
157
158 if (u->tsched_watermark > max_use-min_sleep)
159 u->tsched_watermark = max_use-min_sleep;
160
161 if (u->tsched_watermark < min_wakeup)
162 u->tsched_watermark = min_wakeup;
163 }
164
165 static int try_recover(struct userdata *u, const char *call, int err) {
166 pa_assert(u);
167 pa_assert(call);
168 pa_assert(err < 0);
169
170 pa_log_debug("%s: %s", call, snd_strerror(err));
171
172 if (err == -EAGAIN) {
173 pa_log_debug("%s: EAGAIN", call);
174 return 1;
175 }
176
177 if (err == -EPIPE)
178 pa_log_debug("%s: Buffer underrun!", call);
179
180 if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
181 u->first = TRUE;
182 return 0;
183 }
184
185 pa_log("%s: %s", call, snd_strerror(err));
186 return -1;
187 }
188
189 static void check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
190 size_t left_to_play;
191
192 if (u->first || u->after_rewind)
193 return;
194
195 if (n*u->frame_size < u->hwbuf_size)
196 left_to_play = u->hwbuf_size - (n*u->frame_size);
197 else
198 left_to_play = 0;
199
200 if (left_to_play > 0)
201 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);
202 else {
203 pa_log_info("Underrun!");
204
205 if (u->use_tsched) {
206 size_t old_watermark = u->tsched_watermark;
207
208 u->tsched_watermark *= 2;
209 fix_tsched_watermark(u);
210
211 if (old_watermark != u->tsched_watermark)
212 pa_log_notice("Increasing wakeup watermark to %0.2f ms",
213 (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
214 }
215 }
216 }
217
218 static int mmap_write(struct userdata *u) {
219 int work_done = 0;
220 pa_bool_t checked_left_to_play = FALSE;
221
222 pa_assert(u);
223 pa_sink_assert_ref(u->sink);
224
225 for (;;) {
226 pa_memchunk chunk;
227 void *p;
228 snd_pcm_sframes_t n;
229 int err, r;
230 const snd_pcm_channel_area_t *areas;
231 snd_pcm_uframes_t offset, frames;
232
233 snd_pcm_hwsync(u->pcm_handle);
234
235 /* First we determine how many samples are missing to fill the
236 * buffer up to 100% */
237
238 if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
239
240 if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
241 continue;
242 else if (r > 0)
243 return work_done;
244
245 return r;
246 }
247
248 if (!checked_left_to_play) {
249 check_left_to_play(u, n);
250 checked_left_to_play = TRUE;
251 }
252
253 /* We only use part of the buffer that matches our
254 * dynamically requested latency */
255
256 if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
257 return work_done;
258
259 frames = n = n - u->hwbuf_unused_frames;
260
261 pa_log_debug("%lu frames to write", (unsigned long) frames);
262
263 if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
264
265 if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
266 continue;
267 else if (r > 0)
268 return work_done;
269
270 return r;
271 }
272
273 /* Make sure that if these memblocks need to be copied they will fit into one slot */
274 if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size)
275 frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size;
276
277 /* Check these are multiples of 8 bit */
278 pa_assert((areas[0].first & 7) == 0);
279 pa_assert((areas[0].step & 7)== 0);
280
281 /* We assume a single interleaved memory buffer */
282 pa_assert((areas[0].first >> 3) == 0);
283 pa_assert((areas[0].step >> 3) == u->frame_size);
284
285 p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
286
287 chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
288 chunk.length = pa_memblock_get_length(chunk.memblock);
289 chunk.index = 0;
290
291 pa_sink_render_into_full(u->sink, &chunk);
292
293 /* FIXME: Maybe we can do something to keep this memory block
294 * a little bit longer around? */
295 pa_memblock_unref_fixed(chunk.memblock);
296
297 if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
298
299 if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
300 continue;
301 else if (r > 0)
302 return work_done;
303
304 return r;
305 }
306
307 work_done = 1;
308
309 u->frame_index += frames;
310
311 pa_log_debug("wrote %lu frames", (unsigned long) frames);
312
313 if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
314 return work_done;
315 }
316 }
317
318 static int unix_write(struct userdata *u) {
319 int work_done = 0;
320 pa_bool_t checked_left_to_play = FALSE;
321
322 pa_assert(u);
323 pa_sink_assert_ref(u->sink);
324
325 for (;;) {
326 void *p;
327 snd_pcm_sframes_t n, frames;
328 int r;
329
330 snd_pcm_hwsync(u->pcm_handle);
331
332 if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
333
334 if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
335 continue;
336 else if (r > 0)
337 return work_done;
338
339 return r;
340 }
341
342 if (!checked_left_to_play) {
343 check_left_to_play(u, n);
344 checked_left_to_play = TRUE;
345 }
346
347 if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
348 return work_done;
349
350 n -= u->hwbuf_unused_frames;
351
352 pa_log_debug("%lu frames to write", (unsigned long) frames);
353
354 if (u->memchunk.length <= 0)
355 pa_sink_render(u->sink, n * u->frame_size, &u->memchunk);
356
357 pa_assert(u->memchunk.length > 0);
358
359 frames = u->memchunk.length / u->frame_size;
360
361 if (frames > n)
362 frames = n;
363
364 p = pa_memblock_acquire(u->memchunk.memblock);
365 frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, frames);
366 pa_memblock_release(u->memchunk.memblock);
367
368 pa_assert(frames != 0);
369
370 if (PA_UNLIKELY(frames < 0)) {
371
372 if ((r = try_recover(u, "snd_pcm_writei", n)) == 0)
373 continue;
374 else if (r > 0)
375 return work_done;
376
377 return r;
378 }
379
380 u->memchunk.index += frames * u->frame_size;
381 u->memchunk.length -= frames * u->frame_size;
382
383 if (u->memchunk.length <= 0) {
384 pa_memblock_unref(u->memchunk.memblock);
385 pa_memchunk_reset(&u->memchunk);
386 }
387
388 work_done = 1;
389
390 u->frame_index += frames;
391
392 pa_log_debug("wrote %lu frames", (unsigned long) frames);
393
394 if (PA_LIKELY(frames >= n))
395 return work_done;
396 }
397 }
398
399 static void update_smoother(struct userdata *u) {
400 snd_pcm_sframes_t delay = 0;
401 int64_t frames;
402 int err;
403 pa_usec_t now1, now2;
404 /* struct timeval timestamp; */
405 snd_pcm_status_t *status;
406
407 snd_pcm_status_alloca(&status);
408
409 pa_assert(u);
410 pa_assert(u->pcm_handle);
411
412 /* Let's update the time smoother */
413
414 snd_pcm_hwsync(u->pcm_handle);
415 snd_pcm_avail_update(u->pcm_handle);
416
417 /* if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) { */
418 /* pa_log("Failed to query DSP status data: %s", snd_strerror(err)); */
419 /* return; */
420 /* } */
421
422 /* delay = snd_pcm_status_get_delay(status); */
423
424 if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
425 pa_log("Failed to query DSP status data: %s", snd_strerror(err));
426 return;
427 }
428
429 frames = u->frame_index - delay;
430
431 /* pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames); */
432
433 /* snd_pcm_status_get_tstamp(status, &timestamp); */
434 /* pa_rtclock_from_wallclock(&timestamp); */
435 /* now1 = pa_timeval_load(&timestamp); */
436
437 now1 = pa_rtclock_usec();
438 now2 = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
439 pa_smoother_put(u->smoother, now1, now2);
440 }
441
442 static pa_usec_t sink_get_latency(struct userdata *u) {
443 pa_usec_t r = 0;
444 int64_t delay;
445 pa_usec_t now1, now2;
446
447 pa_assert(u);
448
449 now1 = pa_rtclock_usec();
450 now2 = pa_smoother_get(u->smoother, now1);
451
452 delay = (int64_t) pa_bytes_to_usec(u->frame_index * u->frame_size, &u->sink->sample_spec) - (int64_t) now2;
453
454 if (delay > 0)
455 r = (pa_usec_t) delay;
456
457 if (u->memchunk.memblock)
458 r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
459
460 return r;
461 }
462
463 static int build_pollfd(struct userdata *u) {
464 pa_assert(u);
465 pa_assert(u->pcm_handle);
466
467 if (u->alsa_rtpoll_item)
468 pa_rtpoll_item_free(u->alsa_rtpoll_item);
469
470 if (!(u->alsa_rtpoll_item = pa_alsa_build_pollfd(u->pcm_handle, u->rtpoll)))
471 return -1;
472
473 return 0;
474 }
475
476 static int suspend(struct userdata *u) {
477 pa_assert(u);
478 pa_assert(u->pcm_handle);
479
480 pa_smoother_pause(u->smoother, pa_rtclock_usec());
481
482 /* Let's suspend */
483 snd_pcm_drain(u->pcm_handle);
484 snd_pcm_close(u->pcm_handle);
485 u->pcm_handle = NULL;
486
487 if (u->alsa_rtpoll_item) {
488 pa_rtpoll_item_free(u->alsa_rtpoll_item);
489 u->alsa_rtpoll_item = NULL;
490 }
491
492 pa_log_info("Device suspended...");
493
494 return 0;
495 }
496
497 static pa_usec_t hw_sleep_time(struct userdata *u) {
498 pa_usec_t usec, wm;
499
500 pa_assert(u);
501
502 usec = pa_sink_get_requested_latency_within_thread(u->sink);
503
504 if (usec == (pa_usec_t) -1)
505 usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
506
507 pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
508
509 wm = pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec);
510
511 if (usec >= wm)
512 usec -= wm;
513 else
514 usec /= 2;
515
516 if (u->first) {
517 pa_log_debug("Decreasing wakeup time for the first iteration by half.");
518 usec /= 2;
519 }
520
521 pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
522
523 return usec;
524 }
525
526 static int update_sw_params(struct userdata *u) {
527 snd_pcm_uframes_t avail_min;
528 int err;
529
530 pa_assert(u);
531
532 /* Use the full buffer if noone asked us for anything specific */
533 u->hwbuf_unused_frames = 0;
534
535 if (u->use_tsched) {
536 pa_usec_t latency;
537
538 if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) != (pa_usec_t) -1) {
539 size_t b;
540
541 pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC);
542
543 b = pa_usec_to_bytes(latency, &u->sink->sample_spec);
544
545 /* We need at least one sample in our buffer */
546
547 if (PA_UNLIKELY(b < u->frame_size))
548 b = u->frame_size;
549
550 u->hwbuf_unused_frames =
551 PA_LIKELY(b < u->hwbuf_size) ?
552 ((u->hwbuf_size - b) / u->frame_size) : 0;
553
554 fix_tsched_watermark(u);
555 }
556 }
557
558 pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
559
560 /* We need at last one frame in the used part of the buffer */
561 avail_min = u->hwbuf_unused_frames + 1;
562
563 if (u->use_tsched) {
564 pa_usec_t usec;
565
566 usec = hw_sleep_time(u);
567 avail_min += pa_usec_to_bytes(usec, &u->sink->sample_spec);
568 }
569
570 pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
571
572 if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
573 pa_log("Failed to set software parameters: %s", snd_strerror(err));
574 return err;
575 }
576
577 return 0;
578 }
579
580 static int unsuspend(struct userdata *u) {
581 pa_sample_spec ss;
582 int err;
583 pa_bool_t b, d;
584 unsigned nfrags;
585 snd_pcm_uframes_t period_size;
586
587 pa_assert(u);
588 pa_assert(!u->pcm_handle);
589
590 pa_log_info("Trying resume...");
591
592 snd_config_update_free_global();
593 if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
594 pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err));
595 goto fail;
596 }
597
598 ss = u->sink->sample_spec;
599 nfrags = u->nfragments;
600 period_size = u->fragment_size / u->frame_size;
601 b = u->use_mmap;
602 d = u->use_tsched;
603
604 if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
605 pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
606 goto fail;
607 }
608
609 if (b != u->use_mmap || d != u->use_tsched) {
610 pa_log_warn("Resume failed, couldn't get original access mode.");
611 goto fail;
612 }
613
614 if (!pa_sample_spec_equal(&ss, &u->sink->sample_spec)) {
615 pa_log_warn("Resume failed, couldn't restore original sample settings.");
616 goto fail;
617 }
618
619 if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
620 pa_log_warn("Resume failed, couldn't restore original fragment settings.");
621 goto fail;
622 }
623
624 if (update_sw_params(u) < 0)
625 goto fail;
626
627 if (build_pollfd(u) < 0)
628 goto fail;
629
630 /* FIXME: We need to reload the volume somehow */
631
632 u->first = TRUE;
633
634 pa_log_info("Resumed successfully...");
635
636 return 0;
637
638 fail:
639 if (u->pcm_handle) {
640 snd_pcm_close(u->pcm_handle);
641 u->pcm_handle = NULL;
642 }
643
644 return -1;
645 }
646
647 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
648 struct userdata *u = PA_SINK(o)->userdata;
649
650 switch (code) {
651
652 case PA_SINK_MESSAGE_GET_LATENCY: {
653 pa_usec_t r = 0;
654
655 if (u->pcm_handle)
656 r = sink_get_latency(u);
657
658 *((pa_usec_t*) data) = r;
659
660 return 0;
661 }
662
663 case PA_SINK_MESSAGE_SET_STATE:
664
665 switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
666
667 case PA_SINK_SUSPENDED:
668 pa_assert(PA_SINK_OPENED(u->sink->thread_info.state));
669
670 if (suspend(u) < 0)
671 return -1;
672
673 break;
674
675 case PA_SINK_IDLE:
676 case PA_SINK_RUNNING:
677
678 if (u->sink->thread_info.state == PA_SINK_INIT) {
679 if (build_pollfd(u) < 0)
680 return -1;
681 }
682
683 if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
684 if (unsuspend(u) < 0)
685 return -1;
686 }
687
688 break;
689
690 case PA_SINK_UNLINKED:
691 case PA_SINK_INIT:
692 ;
693 }
694
695 break;
696 }
697
698 return pa_sink_process_msg(o, code, data, offset, chunk);
699 }
700
701 static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
702 struct userdata *u = snd_mixer_elem_get_callback_private(elem);
703
704 pa_assert(u);
705 pa_assert(u->mixer_handle);
706
707 if (mask == SND_CTL_EVENT_MASK_REMOVE)
708 return 0;
709
710 if (mask & SND_CTL_EVENT_MASK_VALUE) {
711 pa_sink_get_volume(u->sink);
712 pa_sink_get_mute(u->sink);
713 }
714
715 return 0;
716 }
717
718 static int sink_get_volume_cb(pa_sink *s) {
719 struct userdata *u = s->userdata;
720 int err;
721 int i;
722
723 pa_assert(u);
724 pa_assert(u->mixer_elem);
725
726 for (i = 0; i < s->sample_spec.channels; i++) {
727 long alsa_vol;
728
729 pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i]));
730
731 if (u->hw_dB_supported) {
732
733 if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) {
734 s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
735 continue;
736 }
737
738 u->hw_dB_supported = FALSE;
739 }
740
741 if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
742 goto fail;
743
744 s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
745 }
746
747 return 0;
748
749 fail:
750 pa_log_error("Unable to read volume: %s", snd_strerror(err));
751
752 return -1;
753 }
754
755 static int sink_set_volume_cb(pa_sink *s) {
756 struct userdata *u = s->userdata;
757 int err;
758 int i;
759
760 pa_assert(u);
761 pa_assert(u->mixer_elem);
762
763 for (i = 0; i < s->sample_spec.channels; i++) {
764 long alsa_vol;
765 pa_volume_t vol;
766
767 pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i]));
768
769 vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM);
770
771 if (u->hw_dB_supported) {
772 alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
773 alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
774
775 if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) {
776
777 if (snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
778 s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
779
780 continue;
781 }
782
783 u->hw_dB_supported = FALSE;
784
785 }
786
787 alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
788 alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
789
790 if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
791 goto fail;
792
793 if (snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
794 s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
795 }
796
797 return 0;
798
799 fail:
800 pa_log_error("Unable to set volume: %s", snd_strerror(err));
801
802 return -1;
803 }
804
805 static int sink_get_mute_cb(pa_sink *s) {
806 struct userdata *u = s->userdata;
807 int err, sw;
808
809 pa_assert(u);
810 pa_assert(u->mixer_elem);
811
812 if ((err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw)) < 0) {
813 pa_log_error("Unable to get switch: %s", snd_strerror(err));
814 return -1;
815 }
816
817 s->muted = !sw;
818
819 return 0;
820 }
821
822 static int sink_set_mute_cb(pa_sink *s) {
823 struct userdata *u = s->userdata;
824 int err;
825
826 pa_assert(u);
827 pa_assert(u->mixer_elem);
828
829 if ((err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->muted)) < 0) {
830 pa_log_error("Unable to set switch: %s", snd_strerror(err));
831 return -1;
832 }
833
834 return 0;
835 }
836
837 static void sink_update_requested_latency_cb(pa_sink *s) {
838 struct userdata *u = s->userdata;
839 pa_assert(u);
840
841 update_sw_params(u);
842 }
843
844 static int process_rewind(struct userdata *u) {
845 snd_pcm_sframes_t unused;
846 size_t rewind_nbytes, unused_nbytes, limit_nbytes;
847 pa_assert(u);
848
849 rewind_nbytes = u->sink->thread_info.rewind_nbytes;
850 u->sink->thread_info.rewind_nbytes = 0;
851
852 pa_assert(rewind_nbytes > 0);
853 pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
854
855 snd_pcm_hwsync(u->pcm_handle);
856 if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
857 pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused));
858 return -1;
859 }
860
861 unused_nbytes = u->tsched_watermark + (size_t) unused * u->frame_size;
862
863 if (u->hwbuf_size > unused_nbytes)
864 limit_nbytes = u->hwbuf_size - unused_nbytes;
865 else
866 limit_nbytes = 0;
867
868 if (rewind_nbytes > limit_nbytes)
869 rewind_nbytes = limit_nbytes;
870
871 if (rewind_nbytes > 0) {
872 snd_pcm_sframes_t in_frames, out_frames;
873
874 pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes);
875
876 in_frames = (snd_pcm_sframes_t) rewind_nbytes / u->frame_size;
877 pa_log_debug("before: %lu", (unsigned long) in_frames);
878 if ((out_frames = snd_pcm_rewind(u->pcm_handle, in_frames)) < 0) {
879 pa_log("snd_pcm_rewind() failed: %s", snd_strerror(out_frames));
880 return -1;
881 }
882 pa_log_debug("after: %lu", (unsigned long) out_frames);
883
884 rewind_nbytes = out_frames * u->frame_size;
885
886 if (rewind_nbytes <= 0)
887 pa_log_info("Tried rewind, but was apparently not possible.");
888 else {
889 u->frame_index -= out_frames;
890 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
891 pa_sink_process_rewind(u->sink, rewind_nbytes);
892
893 u->after_rewind = TRUE;
894 }
895 } else
896 pa_log_debug("Mhmm, actually there is nothing to rewind.");
897
898 return 0;
899 }
900
901 static void thread_func(void *userdata) {
902 struct userdata *u = userdata;
903
904 pa_assert(u);
905
906 pa_log_debug("Thread starting up");
907
908 if (u->core->realtime_scheduling)
909 pa_make_realtime(u->core->realtime_priority);
910
911 pa_thread_mq_install(&u->thread_mq);
912 pa_rtpoll_install(u->rtpoll);
913
914 for (;;) {
915 int ret;
916
917 /* pa_log_debug("loop"); */
918
919 /* Render some data and write it to the dsp */
920 if (PA_SINK_OPENED(u->sink->thread_info.state)) {
921 int work_done = 0;
922
923 if (u->sink->thread_info.rewind_nbytes > 0)
924 if (process_rewind(u) < 0)
925 goto fail;
926
927 if (u->use_mmap)
928 work_done = mmap_write(u);
929 else
930 work_done = unix_write(u);
931
932 if (work_done < 0)
933 goto fail;
934
935 /* pa_log_debug("work_done = %i", work_done); */
936
937 if (work_done) {
938
939 if (u->first) {
940 pa_log_info("Starting playback.");
941 snd_pcm_start(u->pcm_handle);
942
943 pa_smoother_resume(u->smoother, pa_rtclock_usec());
944 }
945
946 update_smoother(u);
947 }
948
949 if (u->use_tsched) {
950 pa_usec_t usec, cusec;
951
952 /* OK, the playback buffer is now full, let's
953 * calculate when to wake up next */
954
955 usec = hw_sleep_time(u);
956
957 /* pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC); */
958
959 /* Convert from the sound card time domain to the
960 * system time domain */
961 cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), usec);
962
963 /* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
964
965 /* We don't trust the conversion, so we wake up whatever comes first */
966 pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
967 }
968
969 u->first = FALSE;
970 u->after_rewind = FALSE;
971
972 } else if (u->use_tsched)
973
974 /* OK, we're in an invalid state, let's disable our timers */
975 pa_rtpoll_set_timer_disabled(u->rtpoll);
976
977 /* Hmm, nothing to do. Let's sleep */
978 if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
979 goto fail;
980
981 if (ret == 0)
982 goto finish;
983
984 /* Tell ALSA about this and process its response */
985 if (PA_SINK_OPENED(u->sink->thread_info.state)) {
986 struct pollfd *pollfd;
987 unsigned short revents = 0;
988 int err;
989 unsigned n;
990
991 pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, &n);
992
993 if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd, n, &revents)) < 0) {
994 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
995 goto fail;
996 }
997
998 if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
999 if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
1000 goto fail;
1001
1002 u->first = TRUE;
1003 }
1004
1005 if (revents)
1006 pa_log_debug("Wakeup from ALSA! (%i)", revents);
1007 }
1008 }
1009
1010 fail:
1011 /* If this was no regular exit from the loop we have to continue
1012 * processing messages until we received PA_MESSAGE_SHUTDOWN */
1013 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
1014 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
1015
1016 finish:
1017 pa_log_debug("Thread shutting down");
1018 }
1019
1020 int pa__init(pa_module*m) {
1021
1022 pa_modargs *ma = NULL;
1023 struct userdata *u = NULL;
1024 const char *dev_id;
1025 pa_sample_spec ss;
1026 pa_channel_map map;
1027 uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
1028 snd_pcm_uframes_t period_frames, tsched_frames;
1029 size_t frame_size;
1030 snd_pcm_info_t *pcm_info = NULL;
1031 int err;
1032 const char *name;
1033 char *name_buf = NULL;
1034 pa_bool_t namereg_fail;
1035 pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
1036 pa_usec_t usec;
1037 pa_sink_new_data data;
1038
1039 snd_pcm_info_alloca(&pcm_info);
1040
1041 pa_assert(m);
1042
1043 pa_alsa_redirect_errors_inc();
1044
1045 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1046 pa_log("Failed to parse module arguments");
1047 goto fail;
1048 }
1049
1050 ss = m->core->default_sample_spec;
1051 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) {
1052 pa_log("Failed to parse sample specification and channel map");
1053 goto fail;
1054 }
1055
1056 frame_size = pa_frame_size(&ss);
1057
1058 nfrags = m->core->default_n_fragments;
1059 frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
1060 if (frag_size <= 0)
1061 frag_size = frame_size;
1062 tsched_size = pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
1063 tsched_watermark = pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
1064
1065 if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 ||
1066 pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 ||
1067 pa_modargs_get_value_u32(ma, "tsched_buffer_size", &tsched_size) < 0 ||
1068 pa_modargs_get_value_u32(ma, "tsched_buffer_watermark", &tsched_watermark) < 0) {
1069 pa_log("Failed to parse buffer metrics");
1070 goto fail;
1071 }
1072
1073 hwbuf_size = frag_size * nfrags;
1074 period_frames = frag_size/frame_size;
1075 tsched_frames = tsched_size/frame_size;
1076
1077 if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
1078 pa_log("Failed to parse mmap argument.");
1079 goto fail;
1080 }
1081
1082 if (pa_modargs_get_value_boolean(ma, "tsched", &use_tsched) < 0) {
1083 pa_log("Failed to parse timer_scheduling argument.");
1084 goto fail;
1085 }
1086
1087 if (use_tsched && !pa_rtclock_hrtimer()) {
1088 pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1089 use_tsched = FALSE;
1090 }
1091
1092 if (pa_modargs_get_value_boolean(ma, "mixer_reset", &mixer_reset) < 0) {
1093 pa_log("Failed to parse mixer_reset argument.");
1094 goto fail;
1095 }
1096
1097 u = pa_xnew0(struct userdata, 1);
1098 u->core = m->core;
1099 u->module = m;
1100 m->userdata = u;
1101 u->use_mmap = use_mmap;
1102 u->use_tsched = use_tsched;
1103 u->first = TRUE;
1104 u->after_rewind = FALSE;
1105 u->rtpoll = pa_rtpoll_new();
1106 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
1107 u->alsa_rtpoll_item = NULL;
1108
1109 u->smoother = pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC*2, DEFAULT_TSCHED_BUFFER_USEC*2, TRUE);
1110 usec = pa_rtclock_usec();
1111 pa_smoother_set_time_offset(u->smoother, usec);
1112 pa_smoother_pause(u->smoother, usec);
1113
1114 snd_config_update_free_global();
1115
1116 b = use_mmap;
1117 d = use_tsched;
1118
1119 if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
1120
1121 if (!(u->pcm_handle = pa_alsa_open_by_device_id(
1122 dev_id,
1123 &u->device_name,
1124 &ss, &map,
1125 SND_PCM_STREAM_PLAYBACK,
1126 &nfrags, &period_frames, tsched_frames,
1127 &b, &d)))
1128
1129 goto fail;
1130
1131 } else {
1132
1133 if (!(u->pcm_handle = pa_alsa_open_by_device_string(
1134 pa_modargs_get_value(ma, "device", DEFAULT_DEVICE),
1135 &u->device_name,
1136 &ss, &map,
1137 SND_PCM_STREAM_PLAYBACK,
1138 &nfrags, &period_frames, tsched_frames,
1139 &b, &d)))
1140 goto fail;
1141
1142 }
1143
1144 pa_assert(u->device_name);
1145 pa_log_info("Successfully opened device %s.", u->device_name);
1146
1147 if (use_mmap && !b) {
1148 pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
1149 u->use_mmap = use_mmap = FALSE;
1150 }
1151
1152 if (use_tsched && (!b || !d)) {
1153 pa_log_info("Cannot enabled timer-based scheduling, falling back to sound IRQ scheduling.");
1154 u->use_tsched = use_tsched = FALSE;
1155 }
1156
1157 if (u->use_mmap)
1158 pa_log_info("Successfully enabled mmap() mode.");
1159
1160 if (u->use_tsched)
1161 pa_log_info("Successfully enabled timer-based scheduling mode.");
1162
1163 if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
1164 pa_log("Error fetching PCM info: %s", snd_strerror(err));
1165 goto fail;
1166 }
1167
1168 /* ALSA might tweak the sample spec, so recalculate the frame size */
1169 frame_size = pa_frame_size(&ss);
1170
1171 if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
1172 pa_log_warn("Error opening mixer: %s", snd_strerror(err));
1173 else {
1174 pa_bool_t found = FALSE;
1175
1176 if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
1177 found = TRUE;
1178 else {
1179 snd_pcm_info_t *info;
1180
1181 snd_pcm_info_alloca(&info);
1182
1183 if (snd_pcm_info(u->pcm_handle, info) >= 0) {
1184 char *md;
1185 int card;
1186
1187 if ((card = snd_pcm_info_get_card(info)) >= 0) {
1188
1189 md = pa_sprintf_malloc("hw:%i", card);
1190
1191 if (strcmp(u->device_name, md))
1192 if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
1193 found = TRUE;
1194 pa_xfree(md);
1195 }
1196 }
1197 }
1198
1199 if (found)
1200 if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM")))
1201 found = FALSE;
1202
1203 if (!found) {
1204 snd_mixer_close(u->mixer_handle);
1205 u->mixer_handle = NULL;
1206 }
1207 }
1208
1209 if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
1210 namereg_fail = TRUE;
1211 else {
1212 name = name_buf = pa_sprintf_malloc("alsa_output.%s", u->device_name);
1213 namereg_fail = FALSE;
1214 }
1215
1216 pa_sink_new_data_init(&data);
1217 data.driver = __FILE__;
1218 data.module = m;
1219 pa_sink_new_data_set_name(&data, name);
1220 data.namereg_fail = namereg_fail;
1221 pa_sink_new_data_set_sample_spec(&data, &ss);
1222 pa_sink_new_data_set_channel_map(&data, &map);
1223
1224 pa_alsa_init_proplist(data.proplist, pcm_info);
1225 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
1226 pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
1227 pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
1228 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
1229
1230 u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
1231 pa_sink_new_data_done(&data);
1232 pa_xfree(name_buf);
1233
1234 if (!u->sink) {
1235 pa_log("Failed to create sink object");
1236 goto fail;
1237 }
1238
1239 u->sink->parent.process_msg = sink_process_msg;
1240 u->sink->update_requested_latency = sink_update_requested_latency_cb;
1241 u->sink->userdata = u;
1242
1243 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
1244 pa_sink_set_rtpoll(u->sink, u->rtpoll);
1245
1246 u->frame_size = frame_size;
1247 u->fragment_size = frag_size = period_frames * frame_size;
1248 u->nfragments = nfrags;
1249 u->hwbuf_size = u->fragment_size * nfrags;
1250 u->hwbuf_unused_frames = 0;
1251 u->tsched_watermark = tsched_watermark;
1252 u->frame_index = 0;
1253 u->hw_dB_supported = FALSE;
1254 u->hw_dB_min = u->hw_dB_max = 0;
1255 u->hw_volume_min = u->hw_volume_max = 0;
1256
1257 if (use_tsched)
1258 fix_tsched_watermark(u);
1259
1260 u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
1261 u->sink->max_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
1262 if (!use_tsched)
1263 u->sink->min_latency = u->sink->max_latency;
1264
1265 pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
1266 nfrags, (long unsigned) u->fragment_size,
1267 (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
1268
1269 if (use_tsched)
1270 pa_log_info("Time scheduling watermark is %0.2fms",
1271 (double) pa_bytes_to_usec(u->tsched_watermark, &ss) / PA_USEC_PER_MSEC);
1272
1273 if (update_sw_params(u) < 0)
1274 goto fail;
1275
1276 pa_memchunk_reset(&u->memchunk);
1277
1278 if (u->mixer_handle) {
1279 pa_assert(u->mixer_elem);
1280
1281 if (snd_mixer_selem_has_playback_volume(u->mixer_elem))
1282
1283 if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0 &&
1284 snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) {
1285
1286 pa_bool_t suitable = TRUE;
1287
1288 pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
1289
1290 if (u->hw_volume_min > u->hw_volume_max) {
1291
1292 pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max);
1293 suitable = FALSE;
1294
1295 } else if (u->hw_volume_max - u->hw_volume_min < 3) {
1296
1297 pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
1298 suitable = FALSE;
1299
1300 } else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
1301
1302 pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
1303
1304 /* Let's see if this thing actually is useful for muting */
1305 if (u->hw_dB_min > -6000) {
1306 pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100);
1307
1308 suitable = FALSE;
1309 } else if (u->hw_dB_max < 0) {
1310
1311 pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100);
1312 suitable = FALSE;
1313
1314 } else if (u->hw_dB_min >= u->hw_dB_max) {
1315
1316 pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100);
1317 suitable = FALSE;
1318
1319 } else {
1320
1321 if (u->hw_dB_max > 0) {
1322 /* dB > 0 means overamplification, and clipping, we don't want that here */
1323 pa_log_info("Device can do overamplification for %0.2f dB. Limiting to 0 db", ((double) u->hw_dB_max) / 100);
1324 u->hw_dB_max = 0;
1325 }
1326
1327 u->hw_dB_supported = TRUE;
1328 }
1329 }
1330
1331 if (suitable) {
1332 u->sink->get_volume = sink_get_volume_cb;
1333 u->sink->set_volume = sink_set_volume_cb;
1334 u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
1335 pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
1336
1337 } else if (mixer_reset) {
1338 pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
1339 pa_alsa_0dB_playback(u->mixer_elem);
1340 } else
1341 pa_log_info("Using software volume control. Leaving hw mixer controls untouched.");
1342 }
1343
1344 if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
1345 u->sink->get_mute = sink_get_mute_cb;
1346 u->sink->set_mute = sink_set_mute_cb;
1347 u->sink->flags |= PA_SINK_HW_MUTE_CTRL;
1348 }
1349
1350 u->mixer_fdl = pa_alsa_fdlist_new();
1351
1352 if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) {
1353 pa_log("Failed to initialize file descriptor monitoring");
1354 goto fail;
1355 }
1356
1357 snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback);
1358 snd_mixer_elem_set_callback_private(u->mixer_elem, u);
1359 } else
1360 u->mixer_fdl = NULL;
1361
1362 pa_alsa_dump(u->pcm_handle);
1363
1364 if (!(u->thread = pa_thread_new(thread_func, u))) {
1365 pa_log("Failed to create thread.");
1366 goto fail;
1367 }
1368
1369 /* Get initial mixer settings */
1370 if (data.volume_is_set) {
1371 if (u->sink->set_volume)
1372 u->sink->set_volume(u->sink);
1373 } else {
1374 if (u->sink->get_volume)
1375 u->sink->get_volume(u->sink);
1376 }
1377
1378 if (data.muted_is_set) {
1379 if (u->sink->set_mute)
1380 u->sink->set_mute(u->sink);
1381 } else {
1382 if (u->sink->get_mute)
1383 u->sink->get_mute(u->sink);
1384 }
1385
1386 pa_sink_put(u->sink);
1387
1388 pa_modargs_free(ma);
1389
1390 return 0;
1391
1392 fail:
1393
1394 if (ma)
1395 pa_modargs_free(ma);
1396
1397 pa__done(m);
1398
1399 return -1;
1400 }
1401
1402 void pa__done(pa_module*m) {
1403 struct userdata *u;
1404
1405 pa_assert(m);
1406
1407 if (!(u = m->userdata)) {
1408 pa_alsa_redirect_errors_dec();
1409 return;
1410 }
1411
1412 if (u->sink)
1413 pa_sink_unlink(u->sink);
1414
1415 if (u->thread) {
1416 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
1417 pa_thread_free(u->thread);
1418 }
1419
1420 pa_thread_mq_done(&u->thread_mq);
1421
1422 if (u->sink)
1423 pa_sink_unref(u->sink);
1424
1425 if (u->memchunk.memblock)
1426 pa_memblock_unref(u->memchunk.memblock);
1427
1428 if (u->alsa_rtpoll_item)
1429 pa_rtpoll_item_free(u->alsa_rtpoll_item);
1430
1431 if (u->rtpoll)
1432 pa_rtpoll_free(u->rtpoll);
1433
1434 if (u->mixer_fdl)
1435 pa_alsa_fdlist_free(u->mixer_fdl);
1436
1437 if (u->mixer_handle)
1438 snd_mixer_close(u->mixer_handle);
1439
1440 if (u->pcm_handle) {
1441 snd_pcm_drop(u->pcm_handle);
1442 snd_pcm_close(u->pcm_handle);
1443 }
1444
1445 if (u->smoother)
1446 pa_smoother_free(u->smoother);
1447
1448 pa_xfree(u->device_name);
1449 pa_xfree(u);
1450
1451 snd_config_update_free_global();
1452
1453 pa_alsa_redirect_errors_dec();
1454 }