1 /*
2  *  ALSA streaming support
3  *
4  *  Originally written by:
5  *      Copyright (c) by Devin Heitmueller <dheitmueller@kernellabs.com>
6  *	for usage at tvtime
7  *  Derived from the alsa-driver test tool latency.c:
8  *    Copyright (c) by Jaroslav Kysela <perex@perex.cz>
9  *
10  *  Copyright (c) 2011 - Mauro Carvalho Chehab
11  *	Ported to xawtv, with bug fixes and improvements
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to the Free Software
25  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
26  *
27  */
28 
29 #include <config.h>
30 
31 #ifdef HAVE_ALSA
32 #include "alsa_stream.h"
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sched.h>
38 #include <errno.h>
39 #include <getopt.h>
40 #include <pthread.h>
41 #include <alsa/asoundlib.h>
42 #include <sys/time.h>
43 #include <math.h>
44 
45 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
46 
47 /* Private vars to control alsa thread status */
48 static int stop_alsa = 0;
49 static snd_htimestamp_t timestamp;
50 
51 /* Error handlers */
52 snd_output_t *output = NULL;
53 FILE *error_fp;
54 int verbose = 0;
55 
56 struct final_params {
57     int bufsize;
58     int rate;
59     int latency;
60     int channels;
61 };
62 
setparams_stream(snd_pcm_t * handle,snd_pcm_hw_params_t * params,snd_pcm_format_t format,int * channels,const char * id)63 static int setparams_stream(snd_pcm_t *handle,
64 			    snd_pcm_hw_params_t *params,
65 			    snd_pcm_format_t format,
66 			    int *channels,
67 			    const char *id)
68 {
69     int err;
70 
71     err = snd_pcm_hw_params_any(handle, params);
72     if (err < 0) {
73 	fprintf(error_fp,
74 		"alsa: Broken configuration for %s PCM: no configurations available: %s\n",
75 		snd_strerror(err), id);
76 	return err;
77     }
78 
79     err = snd_pcm_hw_params_set_access(handle, params,
80 				       SND_PCM_ACCESS_RW_INTERLEAVED);
81     if (err < 0) {
82 	fprintf(error_fp, "alsa: Access type not available for %s: %s\n", id,
83 		snd_strerror(err));
84 	return err;
85     }
86 
87     err = snd_pcm_hw_params_set_format(handle, params, format);
88     if (err < 0) {
89 	fprintf(error_fp, "alsa: Sample format not available for %s: %s\n", id,
90 	       snd_strerror(err));
91 	return err;
92     }
93 
94 retry:
95     err = snd_pcm_hw_params_set_channels(handle, params, *channels);
96     if (err < 0) {
97 	if (strcmp(id, "capture") == 0 && *channels == 2) {
98 	    *channels = 1;
99 	    goto retry; /* Retry with mono capture */
100 	}
101 	fprintf(error_fp, "alsa: Channels count (%i) not available for %s: %s\n",
102 		*channels, id, snd_strerror(err));
103 	return err;
104     }
105 
106     return 0;
107 }
108 
getparams_periods(snd_pcm_t * handle,snd_pcm_hw_params_t * params,unsigned int * usecs,unsigned int * count,const char * id)109 static void getparams_periods(snd_pcm_t *handle,
110 		      snd_pcm_hw_params_t *params,
111 		      unsigned int *usecs,
112 		      unsigned int *count,
113 		      const char *id)
114 {
115     unsigned min = 0, max = 0;
116 
117     snd_pcm_hw_params_get_periods_min(params, &min, 0);
118     snd_pcm_hw_params_get_periods_max(params, &max, 0);
119     if (min && max) {
120 	if (verbose)
121 	    fprintf(error_fp, "alsa: %s periods range between %u and %u. Want: %u\n",
122 		    id, min, max, *count);
123 	if (*count < min)
124 	    *count = min;
125 	if (*count > max)
126 	    *count = max;
127     }
128 
129     min = max = 0;
130     snd_pcm_hw_params_get_period_time_min(params, &min, 0);
131     snd_pcm_hw_params_get_period_time_max(params, &max, 0);
132     if (min && max) {
133 	if (verbose)
134 	    fprintf(error_fp, "alsa: %s period time range between %u and %u. Want: %u\n",
135 		    id, min, max, *usecs);
136 	if (*usecs < min)
137 	    *usecs = min;
138 	if (*usecs > max)
139 	    *usecs = max;
140     }
141 }
142 
setparams_periods(snd_pcm_t * handle,snd_pcm_hw_params_t * params,unsigned int * usecs,unsigned int * count,const char * id)143 static int setparams_periods(snd_pcm_t *handle,
144 		      snd_pcm_hw_params_t *params,
145 		      unsigned int *usecs,
146 		      unsigned int *count,
147 		      const char *id)
148 {
149     int err;
150 
151     err = snd_pcm_hw_params_set_period_time_near(handle, params, usecs, 0);
152     if (err < 0) {
153 	    fprintf(error_fp, "alsa: Unable to set period time %u for %s: %s\n",
154 		    *usecs, id, snd_strerror(err));
155 	    return err;
156     }
157 
158     err = snd_pcm_hw_params_set_periods_near(handle, params, count, 0);
159     if (err < 0) {
160 	fprintf(error_fp, "alsa: Unable to set %u periods for %s: %s\n",
161 		*count, id, snd_strerror(err));
162 	return err;
163     }
164 
165     if (verbose)
166 	fprintf(error_fp, "alsa: %s period set to %u periods of %u time\n",
167 		id, *count, *usecs);
168 
169     return 0;
170 }
171 
setparams_set(snd_pcm_t * handle,snd_pcm_hw_params_t * params,snd_pcm_sw_params_t * swparams,snd_pcm_uframes_t start_treshold,const char * id)172 static int setparams_set(snd_pcm_t *handle,
173 			 snd_pcm_hw_params_t *params,
174 			 snd_pcm_sw_params_t *swparams,
175 			 snd_pcm_uframes_t start_treshold,
176 			 const char *id)
177 {
178     int err;
179 
180     err = snd_pcm_hw_params(handle, params);
181     if (err < 0) {
182 	fprintf(error_fp, "alsa: Unable to set hw params for %s: %s\n",
183 		id, snd_strerror(err));
184 	return err;
185     }
186     err = snd_pcm_sw_params_current(handle, swparams);
187     if (err < 0) {
188 	fprintf(error_fp, "alsa: Unable to determine current swparams for %s: %s\n",
189 		id, snd_strerror(err));
190 	return err;
191     }
192     err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
193 						start_treshold);
194     if (err < 0) {
195 	fprintf(error_fp, "alsa: Unable to set start threshold mode for %s: %s\n",
196 		id, snd_strerror(err));
197 	return err;
198     }
199 
200     err = snd_pcm_sw_params_set_avail_min(handle, swparams, 4);
201     if (err < 0) {
202 	fprintf(error_fp, "alsa: Unable to set avail min for %s: %s\n",
203 		id, snd_strerror(err));
204 	return err;
205     }
206 
207     err = snd_pcm_sw_params_set_tstamp_mode(handle, swparams, SND_PCM_TSTAMP_ENABLE);
208     if (err < 0) {
209 	fprintf(error_fp, "alsa: Unable to enable timestamps for %s: %s\n",
210 		id, snd_strerror(err));
211     }
212 
213     err = snd_pcm_sw_params(handle, swparams);
214     if (err < 0) {
215 	fprintf(error_fp, "alsa: Unable to set sw params for %s: %s\n",
216 		id, snd_strerror(err));
217 	return err;
218     }
219     return 0;
220 }
221 
alsa_try_rate(snd_pcm_t * phandle,snd_pcm_t * chandle,snd_pcm_hw_params_t * p_hwparams,snd_pcm_hw_params_t * c_hwparams,int allow_resample,unsigned * ratep,unsigned * ratec)222 static int alsa_try_rate(snd_pcm_t *phandle, snd_pcm_t *chandle,
223                         snd_pcm_hw_params_t *p_hwparams,
224                         snd_pcm_hw_params_t *c_hwparams,
225                         int allow_resample, unsigned *ratep, unsigned *ratec)
226 {
227     int err;
228 
229     err = snd_pcm_hw_params_set_rate_near(chandle, c_hwparams, ratec, 0);
230     if (err)
231         return err;
232 
233     *ratep = *ratec;
234     err = snd_pcm_hw_params_set_rate_near(phandle, p_hwparams, ratep, 0);
235     if (err)
236         return err;
237 
238     if (*ratep == *ratec)
239         return 0;
240 
241     if (verbose)
242         fprintf(error_fp,
243                 "alsa_try_rate: capture wanted %u, playback wanted %u%s\n",
244                 *ratec, *ratep, allow_resample ? " with resample enabled": "");
245 
246     return 1; /* No error, but also no match */
247 }
248 
setparams(snd_pcm_t * phandle,snd_pcm_t * chandle,snd_pcm_format_t format,int latency,int allow_resample,struct final_params * negotiated)249 static int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle,
250 		     snd_pcm_format_t format,
251 		     int latency, int allow_resample,
252 		     struct final_params *negotiated)
253 {
254     int i;
255     unsigned ratep, ratec = 0;
256     unsigned ratemin = 32000, ratemax = 96000, val;
257     int err, channels = 2;
258     snd_pcm_hw_params_t *p_hwparams, *c_hwparams;
259     snd_pcm_sw_params_t *p_swparams, *c_swparams;
260     snd_pcm_uframes_t c_size, p_psize, c_psize;
261     /* Our latency is 2 periods (in usecs) */
262     unsigned int c_periods = 2, p_periods;
263     unsigned int c_periodtime, p_periodtime;
264     const unsigned int prefered_rates[] = { 44100, 48000, 32000 };
265 
266     snd_pcm_hw_params_alloca(&p_hwparams);
267     snd_pcm_hw_params_alloca(&c_hwparams);
268     snd_pcm_sw_params_alloca(&p_swparams);
269     snd_pcm_sw_params_alloca(&c_swparams);
270 
271     if (setparams_stream(chandle, c_hwparams, format, &channels, "capture"))
272 	return 1;
273 
274     if (setparams_stream(phandle, p_hwparams, format, &channels, "playback"))
275 	return 1;
276 
277     if (allow_resample) {
278 	err = snd_pcm_hw_params_set_rate_resample(chandle, c_hwparams, 1);
279 	if (err < 0) {
280 	    fprintf(error_fp, "alsa: Resample setup failed: %s\n", snd_strerror(err));
281 	    return 1;
282 	} else if (verbose)
283 	   fprintf(error_fp, "alsa: Resample enabled.\n");
284     }
285 
286     err = snd_pcm_hw_params_get_rate_min(c_hwparams, &ratemin, 0);
287     if (err >= 0 && verbose)
288 	fprintf(error_fp, "alsa: Capture min rate is %d\n", ratemin);
289     err = snd_pcm_hw_params_get_rate_max(c_hwparams, &ratemax, 0);
290     if (err >= 0 && verbose)
291 	fprintf(error_fp, "alsa: Capture max rate is %u\n", ratemax);
292 
293     err = snd_pcm_hw_params_get_rate_min(p_hwparams, &val, 0);
294     if (err >= 0) {
295 	if (verbose)
296 	    fprintf(error_fp, "alsa: Playback min rate is %u\n", val);
297 	if (val > ratemin)
298 		ratemin = val;
299     }
300     err = snd_pcm_hw_params_get_rate_max(p_hwparams, &val, 0);
301     if (err >= 0) {
302 	if (verbose)
303 	    fprintf(error_fp, "alsa: Playback max rate is %u\n", val);
304 	if (val < ratemax)
305 		ratemax = val;
306     }
307 
308     if (verbose)
309 	fprintf(error_fp,
310 	        "alsa: Will search a common rate between %u and %u\n",
311 		ratemin, ratemax);
312 
313     /* First try a set of common rates */
314     err = -1;
315     for (i = 0; i < ARRAY_SIZE(prefered_rates); i++) {
316         if (prefered_rates[i] < ratemin || prefered_rates[i] > ratemax)
317             continue;
318         ratep = ratec = prefered_rates[i];
319         err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
320                             allow_resample, &ratep, &ratec);
321         if (err == 0)
322             break;
323     }
324 
325     if (err != 0) {
326         if (ratemin >= 44100) {
327             for (i = ratemin; i <= ratemax; i += 100) {
328                 ratep = ratec = i;
329                 err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
330                                     allow_resample, &ratep, &ratec);
331                 if (err == 0)
332                     break;
333             }
334         } else {
335             for (i = ratemax; i >= ratemin; i -= 100) {
336                 ratep = ratec = i;
337                 err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
338                                     allow_resample, &ratep, &ratec);
339                 if (err == 0)
340                     break;
341             }
342         }
343     }
344 
345     if (err < 0) {
346 	fprintf(error_fp, "alsa: Failed to set a supported rate: %s\n",
347 		snd_strerror(err));
348 	return 1;
349     }
350     if (ratep != ratec) {
351 	if (verbose || allow_resample)
352 	    fprintf(error_fp,
353 		    "alsa: Couldn't find a rate that it is supported by both playback and capture\n");
354 	return 2;
355     }
356     if (verbose)
357 	fprintf(error_fp, "alsa: Using Rate %d\n", ratec);
358 
359     /* Negotiate period parameters */
360 
361     c_periodtime = latency * 1000 / c_periods;
362     getparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture");
363     p_periods = c_periods * 2;
364     p_periodtime = c_periodtime;
365     getparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback");
366     c_periods = p_periods / 2;
367 
368     /*
369      * Some playback devices support a very limited periodtime range. If the user needs to
370      * use a higher latency to avoid overrun/underrun, use an alternate algorithm of incresing
371      * the number of periods, to archive the needed latency
372      */
373     if (p_periodtime < c_periodtime) {
374 	c_periodtime = p_periodtime;
375 	c_periods = round (latency * 1000.0 / c_periodtime + 0.5);
376 	getparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture");
377 	p_periods = c_periods * 2;
378 	p_periodtime = c_periodtime;
379 	getparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback");
380 	c_periods = p_periods / 2;
381     }
382 
383     if (setparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture"))
384 	return 1;
385 
386     /* Note we use twice as much periods for the playback buffer, since we
387        will get a period size near the requested time and we don't want it to
388        end up smaller than the capture buffer as then we could end up blocking
389        on writing to it. Note we will configure the playback dev to start
390        playing as soon as it has 2 capture periods worth of data, so this
391        won't influence latency */
392     if (setparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback"))
393 	return 1;
394 
395     snd_pcm_hw_params_get_period_size(p_hwparams, &p_psize, NULL);
396     snd_pcm_hw_params_get_period_size(c_hwparams, &c_psize, NULL);
397     snd_pcm_hw_params_get_buffer_size(c_hwparams, &c_size);
398 
399     latency = c_periods * c_psize;
400     if (setparams_set(phandle, p_hwparams, p_swparams, latency, "playback"))
401 	return 1;
402 
403     if (setparams_set(chandle, c_hwparams, c_swparams, c_psize, "capture"))
404 	return 1;
405 
406     if ((err = snd_pcm_prepare(phandle)) < 0) {
407 	fprintf(error_fp, "alsa: Prepare error: %s\n", snd_strerror(err));
408 	return 1;
409     }
410 
411     if (verbose) {
412 	fprintf(error_fp, "alsa: Negotiated configuration:\n");
413 	snd_pcm_dump_setup(phandle, output);
414 	snd_pcm_dump_setup(chandle, output);
415 	fprintf(error_fp, "alsa: Parameters are %iHz, %s, %i channels\n",
416 		ratep, snd_pcm_format_name(format), channels);
417 	fprintf(error_fp, "alsa: Set bitrate to %u%s, buffer size is %u\n", ratec,
418 		allow_resample ? " with resample enabled at playback": "",
419 		(unsigned int)c_size);
420     }
421 
422     negotiated->bufsize = c_size;
423     negotiated->rate = ratep;
424     negotiated->channels = channels;
425     negotiated->latency = latency;
426     return 0;
427 }
428 
429 /* Read up to len frames */
readbuf(snd_pcm_t * handle,char * buf,long len)430 static snd_pcm_sframes_t readbuf(snd_pcm_t *handle, char *buf, long len)
431 {
432     snd_pcm_sframes_t r;
433     snd_pcm_uframes_t frames;
434     snd_pcm_htimestamp(handle, &frames, &timestamp);
435     r = snd_pcm_readi(handle, buf, len);
436     if (r < 0 && !(r == -EAGAIN || r == -ENODEV)) {
437 	r = snd_pcm_recover(handle, r, 0);
438 	if (r < 0)
439 	    fprintf(error_fp, "alsa: overrun recover error: %s\n", snd_strerror(r));
440     }
441     return r;
442 }
443 
444 /* Write len frames (note not up to len, but all of len!) */
writebuf(snd_pcm_t * handle,char * buf,long len)445 static snd_pcm_sframes_t writebuf(snd_pcm_t *handle, char *buf, long len)
446 {
447     snd_pcm_sframes_t r;
448 
449     while (!stop_alsa) {
450 	r = snd_pcm_writei(handle, buf, len);
451 	if (r == len)
452 	    return 0;
453 	if (r < 0) {
454 	    r = snd_pcm_recover(handle, r, 0);
455 	    if (r < 0) {
456 		fprintf(error_fp, "alsa: underrun recover error: %s\n",
457 			snd_strerror(r));
458 		return r;
459 	    }
460 	}
461 	buf += r * 4;
462 	len -= r;
463 	snd_pcm_wait(handle, 100);
464     }
465     return -1;
466 }
467 
alsa_stream(const char * pdevice,const char * cdevice,int latency)468 static int alsa_stream(const char *pdevice, const char *cdevice, int latency)
469 {
470     snd_pcm_t *phandle, *chandle;
471     char *buffer;
472     int err;
473     ssize_t r;
474     struct final_params negotiated;
475     snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
476     char pdevice_new[32];
477 
478     err = snd_output_stdio_attach(&output, error_fp, 0);
479     if (err < 0) {
480 	fprintf(error_fp, "alsa: Output failed: %s\n", snd_strerror(err));
481 	return 0;
482     }
483 
484     /* Open the devices */
485     if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK,
486 			    0)) < 0) {
487 	fprintf(error_fp, "alsa: Cannot open playback device %s: %s\n",
488 		pdevice, snd_strerror(err));
489 	return 0;
490     }
491     if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE,
492 			    SND_PCM_NONBLOCK)) < 0) {
493 	fprintf(error_fp, "alsa: Cannot open capture device %s: %s\n",
494 		cdevice, snd_strerror(err));
495 	snd_pcm_close(phandle);
496 	return 0;
497     }
498 
499     err = setparams(phandle, chandle, format, latency, 0, &negotiated);
500 
501     /* Try to use plughw instead, as it allows emulating speed */
502     if (err == 2 && strncmp(pdevice, "hw", 2) == 0) {
503 
504 	snd_pcm_close(phandle);
505 
506 	sprintf(pdevice_new, "plug%s", pdevice);
507 	pdevice = pdevice_new;
508 	if (verbose)
509 	    fprintf(error_fp, "alsa: Trying %s for playback\n", pdevice);
510 	if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK,
511 				0)) < 0) {
512 	    fprintf(error_fp, "alsa: Cannot open playback device %s: %s\n",
513 		    pdevice, snd_strerror(err));
514 	    snd_pcm_close(chandle);
515 	    return 0;
516 	}
517 
518 	err = setparams(phandle, chandle, format, latency, 1, &negotiated);
519     }
520 
521     if (err != 0) {
522 	fprintf(error_fp, "alsa: setparams failed\n");
523 	snd_pcm_close(phandle);
524 	snd_pcm_close(chandle);
525 	return 1;
526     }
527 
528     buffer = malloc((negotiated.bufsize * snd_pcm_format_width(format) / 8)
529 		    * negotiated.channels);
530     if (buffer == NULL) {
531 	fprintf(error_fp, "alsa: Failed allocating buffer for audio\n");
532 	snd_pcm_close(phandle);
533 	snd_pcm_close(chandle);
534 	return 0;
535     }
536 
537     if (verbose)
538         fprintf(error_fp,
539 	    "alsa: stream started from %s to %s (%i Hz, buffer delay = %.2f ms)\n",
540 	    cdevice, pdevice, negotiated.rate,
541 	    negotiated.latency * 1000.0 / negotiated.rate);
542 
543     while (!stop_alsa) {
544 	/* We start with a read and not a wait to auto(re)start the capture */
545 	r = readbuf(chandle, buffer, negotiated.bufsize);
546 	if (r == 0)   /* Succesfully recovered from an overrun? */
547 	    continue; /* Force restart of capture stream */
548 	if (r > 0)
549 	    writebuf(phandle, buffer, r);
550 	/* use poll to wait for next event */
551 	while (!stop_alsa && !snd_pcm_wait(chandle, 50))
552 	    ;
553     }
554 
555     snd_pcm_drop(chandle);
556     snd_pcm_drop(phandle);
557 
558     snd_pcm_unlink(chandle);
559     snd_pcm_hw_free(phandle);
560     snd_pcm_hw_free(chandle);
561 
562     snd_pcm_close(phandle);
563     snd_pcm_close(chandle);
564 
565     return 0;
566 }
567 
568 struct input_params {
569     char *pdevice;
570     char *cdevice;
571     int latency;
572 };
573 
alsa_thread_entry(void * whatever)574 static void *alsa_thread_entry(void *whatever)
575 {
576     struct input_params *inputs = (struct input_params *) whatever;
577 
578     if (verbose)
579 	fprintf(error_fp, "alsa: starting copying alsa stream from %s to %s\n",
580 		inputs->cdevice, inputs->pdevice);
581     alsa_stream(inputs->pdevice, inputs->cdevice, inputs->latency);
582     if (verbose)
583         fprintf(error_fp, "alsa: stream stopped\n");
584 
585     free(inputs->pdevice);
586     free(inputs->cdevice);
587     free(inputs);
588 
589     return NULL;
590 }
591 
592 /*************************************************************************
593  Public functions
594  *************************************************************************/
595 
596 static int alsa_is_running = 0;
597 static pthread_t alsa_thread;
598 
alsa_thread_startup(const char * pdevice,const char * cdevice,int latency,FILE * __error_fp,int __verbose)599 int alsa_thread_startup(const char *pdevice, const char *cdevice, int latency,
600 			FILE *__error_fp, int __verbose)
601 {
602     int ret;
603     struct input_params *inputs;
604 
605     if ((strcasecmp(pdevice, "disabled") == 0) ||
606 	(strcasecmp(cdevice, "disabled") == 0))
607 	return 0;
608 
609     if (__error_fp)
610 	error_fp = __error_fp;
611     else
612 	error_fp = stderr;
613 
614     verbose = __verbose;
615 
616     if (alsa_is_running) {
617         fprintf(error_fp, "alsa: Already running\n");
618         return EBUSY;
619     }
620 
621     inputs = malloc(sizeof(struct input_params));
622     if (inputs == NULL) {
623 	fprintf(error_fp, "alsa: failed allocating memory for inputs\n");
624 	return ENOMEM;
625     }
626 
627     inputs->pdevice = strdup(pdevice);
628     inputs->cdevice = strdup(cdevice);
629     inputs->latency = latency;
630 
631     stop_alsa = 0;
632     ret = pthread_create(&alsa_thread, NULL,
633 			 &alsa_thread_entry, (void *) inputs);
634     if (ret == 0)
635         alsa_is_running = 1;
636 
637     return ret;
638 }
639 
alsa_thread_stop(void)640 void alsa_thread_stop(void)
641 {
642     if (!alsa_is_running)
643         return;
644 
645     stop_alsa = 1;
646     pthread_join(alsa_thread, NULL);
647     alsa_is_running = 0;
648 }
649 
alsa_thread_is_running(void)650 int alsa_thread_is_running(void)
651 {
652     return alsa_is_running;
653 }
654 
alsa_thread_timestamp(struct timeval * tv)655 void alsa_thread_timestamp(struct timeval *tv)
656 {
657 	if (alsa_thread_is_running()) {
658 		tv->tv_sec = timestamp.tv_sec;
659 		tv->tv_usec = timestamp.tv_nsec / 1000;
660 	} else {
661 		tv->tv_sec = 0;
662 		tv->tv_usec = 0;
663 	}
664 }
665 #endif
666