1 /*
2  * MOC - music on console
3  * Copyright (C) 2004 Damian Pietras <daper@daper.net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  */
11 
12 /* Based on aplay copyright (c) by Jaroslav Kysela <perex@suse.cz> */
13 
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
17 
18 /* _XOPEN_SOURCE is known to break compilation under OpenBSD. */
19 #ifndef OPENBSD
20 # define _XOPEN_SOURCE  500 /* for usleep() */
21 #endif
22 
23 #define DEBUG
24 
25 #include <stdlib.h>
26 #include <inttypes.h>
27 #include <alsa/asoundlib.h>
28 #include <assert.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h>
32 
33 #include "common.h"
34 #include "server.h"
35 #include "audio.h"
36 #include "options.h"
37 #include "log.h"
38 
39 #define BUFFER_MAX_USEC	300000
40 
41 static snd_pcm_t *handle = NULL;
42 
43 static struct
44 {
45 	unsigned channels;
46 	unsigned rate;
47 	snd_pcm_format_t format;
48 } params = { 0, 0, SND_PCM_FORMAT_UNKNOWN };
49 
50 static int chunk_size = -1; /* in frames */
51 static char alsa_buf[512 * 1024];
52 static int alsa_buf_fill = 0;
53 static int bytes_per_frame;
54 
55 static snd_mixer_t *mixer_handle = NULL;
56 static snd_mixer_elem_t *mixer_elem1 = NULL;
57 static snd_mixer_elem_t *mixer_elem2 = NULL;
58 static snd_mixer_elem_t *mixer_elem_curr = NULL;
59 static long mixer1_min = -1, mixer1_max = -1;
60 static long mixer2_min = -1, mixer2_max = -1;
61 
62 /* Volume for first and second mixer in range 1-100 despite the actual device
63  * resolution. */
64 static int volume1 = -1;
65 static int volume2 = -1;
66 
67 /* Real volume setting as we last read them. */
68 static int real_volume1 = -1;
69 static int real_volume2 = -1;
70 
71 /* Scale the mixer value to 0-100 range for first and second channel */
72 #define scale_volume1(v) ((v) - mixer1_min) * 100 / (mixer1_max - mixer1_min)
73 #define scale_volume2(v) ((v) - mixer2_min) * 100 / (mixer2_max - mixer2_min)
74 
alsa_shutdown()75 static void alsa_shutdown ()
76 {
77 	int err;
78 
79 	if (mixer_handle && (err = snd_mixer_close(mixer_handle)) < 0)
80 		logit ("Can't close mixer: %s", snd_strerror(err));
81 }
82 
83 /* Fill caps with the device capabilities. Return 0 on error. */
fill_capabilities(struct output_driver_caps * caps)84 static int fill_capabilities (struct output_driver_caps *caps)
85 {
86 	snd_pcm_hw_params_t *hw_params;
87 	snd_pcm_format_mask_t *format_mask;
88 	int err;
89 	unsigned val;
90 
91 	if ((err = snd_pcm_open(&handle, options_get_str("AlsaDevice"),
92 					SND_PCM_STREAM_PLAYBACK,
93 					SND_PCM_NONBLOCK)) < 0) {
94 		error ("Can't open audio: %s", snd_strerror(err));
95 		return 0;
96 	}
97 
98 	if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
99 		error ("Can't allocate alsa hardware parameters structure: %s",
100 				snd_strerror(err));
101 		snd_pcm_close (handle);
102 		return 0;
103 	}
104 
105 	if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
106 		error ("Can't initialize hardware parameters structure: %s",
107 				snd_strerror(err));
108 		snd_pcm_hw_params_free (hw_params);
109 		snd_pcm_close (handle);
110 		return 0;
111 	}
112 
113 	if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &val)) < 0) {
114 		error ("Can't get the minimum number of channels: %s",
115 				snd_strerror(err));
116 		snd_pcm_hw_params_free (hw_params);
117 		snd_pcm_close (handle);
118 		return 0;
119 	}
120 	caps->min_channels = val;
121 
122 	if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &val)) < 0) {
123 		error ("Can't get the maximum number of channels: %s",
124 				snd_strerror(err));
125 		snd_pcm_hw_params_free (hw_params);
126 		snd_pcm_close (handle);
127 		return 0;
128 	}
129 	caps->max_channels = val;
130 
131 	if ((err = snd_pcm_format_mask_malloc(&format_mask)) < 0) {
132 		error ("Can't allocate format mask: %s", snd_strerror(err));
133 		snd_pcm_hw_params_free (hw_params);
134 		snd_pcm_close (handle);
135 		return 0;
136 	}
137 	snd_pcm_hw_params_get_format_mask (hw_params, format_mask);
138 
139 	caps->formats = SFMT_NE;
140 	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S8))
141 		caps->formats |= SFMT_S8;
142 	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U8))
143 		caps->formats |= SFMT_U8;
144 	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S16))
145 		caps->formats |= SFMT_S16;
146 	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U16))
147 		caps->formats |= SFMT_U16;
148 #if 0
149 	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S24))
150 		caps->formats |= SFMT_S32; /* conversion needed */
151 #endif
152 	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S32))
153 		caps->formats |= SFMT_S32;
154 	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U32))
155 		caps->formats |= SFMT_U32;
156 
157 	snd_pcm_format_mask_free (format_mask);
158 	snd_pcm_hw_params_free (hw_params);
159 	snd_pcm_close (handle);
160 	handle = NULL;
161 
162 	return 1;
163 }
164 
handle_mixer_events(snd_mixer_t * mixer_handle)165 static void handle_mixer_events (snd_mixer_t *mixer_handle)
166 {
167 	int count;
168 
169 	if ((count = snd_mixer_poll_descriptors_count(mixer_handle)) < 0)
170 		logit ("snd_mixer_poll_descriptors_count() failed: %s",
171 				snd_strerror(count));
172 	else {
173 		struct pollfd *fds;
174 		int err;
175 
176 		fds = xcalloc (count, sizeof(struct pollfd));
177 
178 		if ((err = snd_mixer_poll_descriptors(mixer_handle, fds,
179 						count)) < 0)
180 			logit ("snd_mixer_poll_descriptors() failed: %s",
181 					snd_strerror(err));
182 		else {
183 			err = poll (fds, count, 0);
184 			if (err < 0)
185 				error ("poll() failed: %s", strerror(errno));
186 			else if (err > 0) {
187 				debug ("Mixer event");
188 				if ((err = snd_mixer_handle_events(mixer_handle)
189 							) < 0)
190 					logit ("snd_mixer_handle_events() failed: %s",
191 							snd_strerror(err));
192 			}
193 
194 		}
195 
196 		free (fds);
197 	}
198 }
199 
alsa_read_mixer_raw(snd_mixer_elem_t * elem)200 static int alsa_read_mixer_raw (snd_mixer_elem_t *elem)
201 {
202 	if (mixer_handle) {
203 		long volume = 0;
204 		int nchannels = 0;
205 		int i;
206 		int err;
207 
208 		assert (elem != NULL);
209 
210 		handle_mixer_events (mixer_handle);
211 
212 		for (i = 0; i < SND_MIXER_SCHN_LAST; i++)
213 			if (snd_mixer_selem_has_playback_channel (elem, i)) {
214 				long vol;
215 
216 				nchannels++;
217 				err = snd_mixer_selem_get_playback_volume (elem, i, &vol);
218 				if (err < 0) {
219 					error ("Can't read mixer: %s",
220 							snd_strerror(err));
221 					return -1;
222 
223 				}
224 				/*logit ("Vol %d: %ld", i, vol);*/
225 				volume += vol;
226 			}
227 
228 		if (nchannels > 0)
229 			volume /= nchannels;
230 		else {
231 			logit ("Mixer has no channels");
232 			volume = -1;
233 		}
234 
235 		/*logit ("Max: %ld, Min: %ld", mixer_max, mixer_min);*/
236 		return volume;
237 
238 	}
239 	else
240 		return -1;
241 }
242 
alsa_init_mixer_channel(const char * name,long * vol_min,long * vol_max)243 static snd_mixer_elem_t *alsa_init_mixer_channel (const char *name,
244 		long *vol_min, long *vol_max)
245 {
246 	snd_mixer_selem_id_t *sid;
247 	snd_mixer_elem_t *elem = NULL;
248 
249 	snd_mixer_selem_id_malloc (&sid);
250 	snd_mixer_selem_id_set_index (sid, 0);
251 	snd_mixer_selem_id_set_name (sid, name);
252 
253 	if (!(elem = snd_mixer_find_selem(mixer_handle, sid)))
254 		error ("Can't find mixer %s", name);
255 	else if (!snd_mixer_selem_has_playback_volume(elem)) {
256 		error ("Mixer device has no playback volume (%s).", name);
257 		elem = NULL;
258 	}
259 	else {
260 		snd_mixer_selem_get_playback_volume_range (elem, vol_min,
261 				vol_max);
262 		logit ("Opened mixer (%s), volume range: %ld-%ld", name,
263 				*vol_min, *vol_max);
264 	}
265 
266 	snd_mixer_selem_id_free (sid);
267 
268 	return elem;
269 }
270 
alsa_init(struct output_driver_caps * caps)271 static int alsa_init (struct output_driver_caps *caps)
272 {
273 	int err;
274 
275 	logit ("Initialising ALSA device");
276 
277 	if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
278 		error ("Can't open ALSA mixer: %s", snd_strerror(err));
279 		mixer_handle = NULL;
280 	}
281 	else if ((err = snd_mixer_attach(mixer_handle,
282 					options_get_str("AlsaDevice"))) < 0) {
283 		snd_mixer_close (mixer_handle);
284 		mixer_handle = NULL;
285 		error ("Can't attach mixer: %s", snd_strerror(err));
286 	}
287 	else if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL))
288 			< 0) {
289 		snd_mixer_close (mixer_handle);
290 		mixer_handle = NULL;
291 		error ("Can't register mixer: %s", snd_strerror(err));
292 	}
293 	else if ((err = snd_mixer_load(mixer_handle)) < 0) {
294 		snd_mixer_close (mixer_handle);
295 		mixer_handle = NULL;
296 		error ("Can't load mixer: %s", snd_strerror(err));
297 	}
298 
299 	if (mixer_handle) {
300 		mixer_elem1 = alsa_init_mixer_channel (
301 				options_get_str ("ALSAMixer1"),
302 				&mixer1_min, &mixer1_max);
303 		mixer_elem2 = alsa_init_mixer_channel (
304 				options_get_str ("ALSAMixer2"),
305 				&mixer2_min, &mixer2_max);
306 	}
307 
308 	mixer_elem_curr = mixer_elem1 ? mixer_elem1 : mixer_elem2;
309 
310 	if (mixer_elem_curr) {
311 		if (mixer_elem1 && (real_volume1
312 					= alsa_read_mixer_raw(mixer_elem1))
313 				!= -1)
314 			volume1 = scale_volume1 (real_volume1);
315 		else {
316 			mixer_elem1 = NULL;
317 			mixer_elem_curr = mixer_elem2;
318 		}
319 
320 		if (mixer_elem2 && (real_volume2
321 					= alsa_read_mixer_raw(mixer_elem2))
322 				!= -1)
323 			volume2 = scale_volume2 (real_volume2);
324 		else {
325 			mixer_elem2 = NULL;
326 			mixer_elem_curr = mixer_elem1;
327 		}
328 
329 		if (!mixer_elem_curr) {
330 			snd_mixer_close (mixer_handle);
331 			mixer_handle = NULL;
332 		}
333 	}
334 	else if (mixer_handle) {
335 		snd_mixer_close (mixer_handle);
336 		mixer_handle = NULL;
337 	}
338 
339 	err = fill_capabilities (caps);
340 
341 	if (err != 0 &&
342 	    sizeof (long) < 8 && options_was_defaulted ("ALSAStutterDefeat")) {
343 		fprintf (stderr,
344 		         "\n"
345 		         "Warning: Your system may be vulnerable to stuttering audio.\n"
346 		         "         You should read the example configuration file comments\n"
347 		         "         for the 'ALSAStutterDefeat' option and set it accordingly.\n"
348 		         "         Setting the option will remove this warning.\n"
349 		         "\n");
350 		sleep (5);
351 	}
352 
353 	return err;
354 }
355 
alsa_open(struct sound_params * sound_params)356 static int alsa_open (struct sound_params *sound_params)
357 {
358 	snd_pcm_hw_params_t *hw_params;
359 	int err;
360 	unsigned int period_time;
361 	unsigned int buffer_time;
362 	snd_pcm_uframes_t chunk_frames;
363 	snd_pcm_uframes_t buffer_frames;
364 	char fmt_name[128];
365 
366 	switch (sound_params->fmt & SFMT_MASK_FORMAT) {
367 		case SFMT_S8:
368 			params.format = SND_PCM_FORMAT_S8;
369 			break;
370 		case SFMT_U8:
371 			params.format = SND_PCM_FORMAT_U8;
372 			break;
373 		case SFMT_S16:
374 			params.format = SND_PCM_FORMAT_S16;
375 			break;
376 		case SFMT_U16:
377 			params.format = SND_PCM_FORMAT_U16;
378 			break;
379 		case SFMT_S32:
380 			params.format = SND_PCM_FORMAT_S32;
381 			break;
382 		case SFMT_U32:
383 			params.format = SND_PCM_FORMAT_U32;
384 			break;
385 		default:
386 			error ("Unknown sample format: %s",
387 					sfmt_str(sound_params->fmt, fmt_name, sizeof(fmt_name)));
388 			params.format = SND_PCM_FORMAT_UNKNOWN;
389 			return 0;
390 	}
391 
392 	if ((err = snd_pcm_open(&handle, options_get_str("AlsaDevice"),
393 					SND_PCM_STREAM_PLAYBACK,
394 					SND_PCM_NONBLOCK)) < 0) {
395 		error ("Can't open audio: %s", snd_strerror(err));
396 		return 0;
397 	}
398 
399 	if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
400 		error ("Can't allocate alsa hardware parameters structure: %s",
401 				snd_strerror(err));
402 		return 0;
403 	}
404 
405 	if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
406 		error ("Can't initialize hardware parameters structure: %s",
407 				snd_strerror(err));
408 		snd_pcm_hw_params_free (hw_params);
409 		return 0;
410 	}
411 
412 	if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
413 		error ("Can't set alsa access type: %s", snd_strerror(err));
414 		snd_pcm_hw_params_free (hw_params);
415 		return 0;
416 	}
417 
418 	if ((err = snd_pcm_hw_params_set_format (handle, hw_params,
419 					params.format)) < 0) {
420 		error ("Can't set sample format: %s", snd_strerror(err));
421 		snd_pcm_hw_params_free (hw_params);
422 		return 0;
423 	}
424 
425 	if (options_get_bool ("ALSAStutterDefeat")) {
426 		err = snd_pcm_hw_params_set_rate_resample (handle, hw_params, 0);
427 		if (err == 0)
428 			logit ("ALSA resampling disabled");
429 		else
430 			logit ("Unable to disable ALSA resampling: %s", snd_strerror(err));
431 	}
432 
433 	params.rate = sound_params->rate;
434 	if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params,
435 					&params.rate, 0)) < 0) {
436 		error ("Can't set sample rate: %s", snd_strerror(err));
437 		snd_pcm_hw_params_free (hw_params);
438 		return 0;
439 	}
440 
441 	logit ("Set rate to %u", params.rate);
442 
443 	if ((err = snd_pcm_hw_params_set_channels (handle, hw_params,
444 					sound_params->channels)) < 0) {
445 		error ("Can't set number of channels: %s", snd_strerror(err));
446 		snd_pcm_hw_params_free (hw_params);
447 		return 0;
448 	}
449 
450 	if ((err = snd_pcm_hw_params_get_buffer_time_max(hw_params,
451 					&buffer_time, 0)) < 0) {
452 		error ("Can't get maximum buffer time: %s", snd_strerror(err));
453 		snd_pcm_hw_params_free (hw_params);
454 		return 0;
455 	}
456 
457 	if (buffer_time > BUFFER_MAX_USEC)
458 		buffer_time = BUFFER_MAX_USEC;
459 	period_time = buffer_time / 4;
460 
461 	if ((err = snd_pcm_hw_params_set_period_time_near(handle, hw_params,
462 					&period_time, 0)) < 0) {
463 		error ("Can't set period time: %s", snd_strerror(err));
464 		snd_pcm_hw_params_free (hw_params);
465 		return 0;
466 	}
467 
468 	if ((err = snd_pcm_hw_params_set_buffer_time_near(handle, hw_params,
469 					&buffer_time, 0)) < 0) {
470 		error ("Can't set buffer time: %s", snd_strerror(err));
471 		snd_pcm_hw_params_free (hw_params);
472 		return 0;
473 	}
474 
475 	if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) {
476 		error ("Can't set audio parameters: %s", snd_strerror(err));
477 		snd_pcm_hw_params_free (hw_params);
478 		return 0;
479 	}
480 
481 	snd_pcm_hw_params_get_period_size (hw_params, &chunk_frames, 0);
482 	snd_pcm_hw_params_get_buffer_size (hw_params, &buffer_frames);
483 
484 	bytes_per_frame = sound_params->channels
485 		* sfmt_Bps(sound_params->fmt);
486 
487 	logit ("Buffer time: %"PRIu64"us",
488 	       (uint64_t) buffer_frames * 1000000 / params.rate);
489 
490 	if (chunk_frames == buffer_frames) {
491 		error ("Can't use period equal to buffer size (%lu == %lu)",
492 				chunk_frames, buffer_frames);
493 		snd_pcm_hw_params_free (hw_params);
494 		return 0;
495 	}
496 
497 	chunk_size = chunk_frames * bytes_per_frame;
498 
499 	debug ("Chunk size: %d", chunk_size);
500 
501 	snd_pcm_hw_params_free (hw_params);
502 
503 	if ((err = snd_pcm_prepare(handle)) < 0) {
504 		error ("Can't prepare audio interface for use: %s",
505 				snd_strerror(err));
506 		return 0;
507 	}
508 
509 	logit ("ALSA device opened");
510 
511 	params.channels = sound_params->channels;
512 	alsa_buf_fill = 0;
513 	return 1;
514 }
515 
516 /* Play from alsa_buf as many chunks as possible. Move the remaining data
517  * to the beginning of the buffer. Return the number of bytes written
518  * or -1 on error. */
play_buf_chunks()519 static int play_buf_chunks ()
520 {
521 	int written = 0;
522 
523 	while (alsa_buf_fill >= chunk_size) {
524 		int err;
525 
526 		err = snd_pcm_writei (handle, alsa_buf + written,
527 				chunk_size / bytes_per_frame);
528 		if (err == -EAGAIN) {
529 			if (snd_pcm_wait(handle, 500) < 0)
530 				logit ("snd_pcm_wait() failed");
531 		}
532 		else if (err == -EPIPE) {
533 			logit ("underrun!");
534 			if ((err = snd_pcm_prepare(handle)) < 0) {
535 				error ("Can't recover after underrun: %s",
536 						snd_strerror(err));
537 				/* TODO: reopen the device */
538 				return -1;
539 			}
540 		}
541 		else if (err == -ESTRPIPE) {
542 			logit ("Suspend, trying to resume");
543 			while ((err = snd_pcm_resume(handle))
544 					== -EAGAIN)
545 				sleep (1);
546 			if (err < 0) {
547 				logit ("Failed, restarting");
548 				if ((err = snd_pcm_prepare(handle))
549 						< 0) {
550 					error ("Failed to restart device: %s",
551 							snd_strerror(err));
552 					return -1;
553 				}
554 			}
555 		}
556 		else if (err < 0) {
557 			error ("Can't play: %s", snd_strerror(err));
558 			return -1;
559 		}
560 		else {
561 			int written_bytes = err * bytes_per_frame;
562 
563 			written += written_bytes;
564 			alsa_buf_fill -= written_bytes;
565 
566 			debug ("Played %d bytes", written_bytes);
567 		}
568 	}
569 
570 	debug ("%d bytes remain in alsa_buf", alsa_buf_fill);
571 	memmove (alsa_buf, alsa_buf + written, alsa_buf_fill);
572 
573 	return written;
574 }
575 
alsa_close()576 static void alsa_close ()
577 {
578 	snd_pcm_sframes_t delay;
579 
580 	assert (handle != NULL);
581 
582 	/* play what remained in the buffer */
583 	if (alsa_buf_fill) {
584 		assert (alsa_buf_fill < chunk_size);
585 
586 		snd_pcm_format_set_silence (params.format,
587 				alsa_buf + alsa_buf_fill,
588 				(chunk_size - alsa_buf_fill) / bytes_per_frame
589 				* params.channels);
590 		alsa_buf_fill = chunk_size;
591 		play_buf_chunks ();
592 	}
593 
594 	/* Wait for ALSA buffers to empty.
595 	 * Do not be tempted to use snd_pcm_nonblock() and snd_pcm_drain()
596 	 * here; there are two bugs in ALSA which make it a bad idea (see
597 	 * the SVN commit log for r2550).  Instead we sleep for the duration
598 	 * of the still unplayed samples. */
599 	if (snd_pcm_delay (handle, &delay) == 0 && delay > 0)
600 		usleep ((uint64_t) delay * 1000000 / params.rate);
601 	snd_pcm_close (handle);
602 	logit ("ALSA device closed");
603 
604 	params.format = 0;
605 	params.rate = 0;
606 	params.channels = 0;
607 	handle = NULL;
608 }
609 
alsa_play(const char * buff,const size_t size)610 static int alsa_play (const char *buff, const size_t size)
611 {
612 	int to_write = size;
613 	int buf_pos = 0;
614 
615 	assert (chunk_size > 0);
616 
617 	debug ("Got %zu bytes to play", size);
618 
619 	while (to_write) {
620 		int to_copy = MIN((size_t)to_write,
621 				sizeof(alsa_buf) - (size_t)alsa_buf_fill);
622 
623 		memcpy (alsa_buf + alsa_buf_fill, buff + buf_pos, to_copy);
624 		to_write -= to_copy;
625 		buf_pos += to_copy;
626 		alsa_buf_fill += to_copy;
627 
628 		debug ("Copied %d bytes to alsa_buf (now filled with %d bytes)",
629 				to_copy, alsa_buf_fill);
630 
631 		if (play_buf_chunks() < 0)
632 			return -1;
633 	}
634 
635 	debug ("Played everything");
636 
637 	return size;
638 }
639 
alsa_read_mixer()640 static int alsa_read_mixer ()
641 {
642 	int curr_real_vol = alsa_read_mixer_raw (mixer_elem_curr);
643 	int *real_vol;
644 	int *vol;
645 
646 	if (mixer_elem_curr == mixer_elem1) {
647 		real_vol = &real_volume1;
648 		vol = &volume1;
649 	}
650 	else {
651 		real_vol = &real_volume2;
652 		vol = &volume2;
653 	}
654 
655 	if (*real_vol != curr_real_vol) {
656 		*real_vol = curr_real_vol;
657 		*vol = (vol == &volume1) ? scale_volume1(*real_vol)
658 			: scale_volume2(*real_vol);
659 		logit ("Mixer volume has changes since we last read it.");
660 	}
661 
662 	return *vol;
663 }
664 
alsa_set_mixer(int vol)665 static void alsa_set_mixer (int vol)
666 {
667 	if (mixer_handle) {
668 		int err;
669 		long vol_alsa;
670 		long mixer_max, mixer_min;
671 		int *real_vol;
672 
673 		if (mixer_elem_curr == mixer_elem1) {
674 			volume1 = vol;
675 			mixer_max = mixer1_max;
676 			mixer_min = mixer1_min;
677 			real_vol = &real_volume1;
678 		}
679 		else {
680 			volume2 = vol;
681 			mixer_max = mixer2_max;
682 			mixer_min = mixer2_min;
683 			real_vol = &real_volume2;
684 		}
685 
686 		vol_alsa = vol * (mixer_max - mixer_min) / 100 + mixer_min;
687 
688 		debug ("Setting vol to %ld", vol_alsa);
689 
690 		if ((err = snd_mixer_selem_set_playback_volume_all(
691 						mixer_elem_curr, vol_alsa)) < 0)
692 			error ("Can't set mixer: %s", snd_strerror(err));
693 		else
694 			*real_vol = vol_alsa;
695 	}
696 }
697 
alsa_get_buff_fill()698 static int alsa_get_buff_fill ()
699 {
700 	if (handle) {
701 		int err;
702 		snd_pcm_sframes_t delay;
703 
704 		if ((err = snd_pcm_delay(handle, &delay)) < 0) {
705 			logit ("snd_pcm_delay() failed: %s", snd_strerror(err));
706 			return 0;
707 		}
708 
709 		/* delay can be negative when underrun occur */
710 		return MAX(delay, 0) * bytes_per_frame;
711 	}
712 	return 0;
713 }
714 
alsa_reset()715 static int alsa_reset ()
716 {
717 	if (handle) {
718 		int err;
719 
720 		if ((err = snd_pcm_drop(handle)) < 0) {
721 			error ("Can't reset the device: %s", snd_strerror(err));
722 			return 0;
723 		}
724 		if ((err = snd_pcm_prepare(handle)) < 0) {
725 			error ("Can't prepare after reset: %s", snd_strerror(err));
726 			return 0;
727 		}
728 
729 		alsa_buf_fill = 0;
730 	}
731 	else
732 		logit ("alsa_reset() when the device is not opened.");
733 	return 1;
734 }
735 
alsa_get_rate()736 static int alsa_get_rate ()
737 {
738 	return params.rate;
739 }
740 
alsa_toggle_mixer_channel()741 static void alsa_toggle_mixer_channel ()
742 {
743 	if (mixer_elem_curr == mixer_elem1 && mixer_elem2)
744 		mixer_elem_curr = mixer_elem2;
745 	else if (mixer_elem1)
746 		mixer_elem_curr = mixer_elem1;
747 }
748 
alsa_get_mixer_channel_name()749 static char *alsa_get_mixer_channel_name ()
750 {
751 	if (mixer_elem_curr == mixer_elem1)
752 		return xstrdup (options_get_str ("ALSAMixer1"));
753 	return xstrdup (options_get_str ("ALSAMixer2"));
754 }
755 
alsa_funcs(struct hw_funcs * funcs)756 void alsa_funcs (struct hw_funcs *funcs)
757 {
758 	funcs->init = alsa_init;
759 	funcs->shutdown = alsa_shutdown;
760 	funcs->open = alsa_open;
761 	funcs->close = alsa_close;
762 	funcs->play = alsa_play;
763 	funcs->read_mixer = alsa_read_mixer;
764 	funcs->set_mixer = alsa_set_mixer;
765 	funcs->get_buff_fill = alsa_get_buff_fill;
766 	funcs->reset = alsa_reset;
767 	funcs->get_rate = alsa_get_rate;
768 	funcs->toggle_mixer_channel = alsa_toggle_mixer_channel;
769 	funcs->get_mixer_channel_name = alsa_get_mixer_channel_name;
770 }
771