1/*
2 *  A simple PCM loopback utility with adaptive sample rate support
3 *
4 *     Author: Jaroslav Kysela <perex@perex.cz>
5 *
6 *
7 *   This program is free software; you can redistribute it and/or modify
8 *   it under the terms of the GNU General Public License as published by
9 *   the Free Software Foundation; either version 2 of the License, or
10 *   (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 *
21 */
22
23#include "aconfig.h"
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sched.h>
28#include <errno.h>
29#include <getopt.h>
30#include <alsa/asoundlib.h>
31#include <sys/time.h>
32#include <math.h>
33#include <pthread.h>
34#include <syslog.h>
35#include <signal.h>
36#include "alsaloop.h"
37#include "os_compat.h"
38
39struct loopback_thread {
40	int threaded;
41	pthread_t thread;
42	int exitcode;
43	struct loopback **loopbacks;
44	int loopbacks_count;
45	snd_output_t *output;
46};
47
48int quit = 0;
49int verbose = 0;
50int workarounds = 0;
51int daemonize = 0;
52int use_syslog = 0;
53struct loopback **loopbacks = NULL;
54int loopbacks_count = 0;
55char **my_argv = NULL;
56int my_argc = 0;
57struct loopback_thread *threads;
58int threads_count = 0;
59pthread_t main_job;
60int arg_default_xrun = 0;
61int arg_default_wake = 0;
62
63static void my_exit(struct loopback_thread *thread, int exitcode)
64{
65	int i;
66
67	for (i = 0; i < thread->loopbacks_count; i++)
68		pcmjob_done(thread->loopbacks[i]);
69	if (thread->threaded) {
70		thread->exitcode = exitcode;
71		pthread_exit(0);
72	}
73	exit(exitcode);
74}
75
76static int create_loopback_handle(struct loopback_handle **_handle,
77				  const char *device,
78				  const char *ctldev,
79				  const char *id)
80{
81	char idbuf[1024];
82	struct loopback_handle *handle;
83
84	handle = calloc(1, sizeof(*handle));
85	if (handle == NULL)
86		return -ENOMEM;
87	if (device == NULL)
88		device = "hw:0,0";
89	handle->device = strdup(device);
90	if (handle->device == NULL) {
91		free(handle);
92		return -ENOMEM;
93	}
94	if (ctldev) {
95		handle->ctldev = strdup(ctldev);
96		if (handle->ctldev == NULL) {
97			free(handle->device);
98			free(handle);
99			return -ENOMEM;
100		}
101	} else {
102		handle->ctldev = NULL;
103	}
104	snprintf(idbuf, sizeof(idbuf)-1, "%s %s", id, device);
105	idbuf[sizeof(idbuf)-1] = '\0';
106	handle->id = strdup(idbuf);
107	handle->access = SND_PCM_ACCESS_RW_INTERLEAVED;
108	handle->format = SND_PCM_FORMAT_S16_LE;
109	handle->rate = handle->rate_req = 48000;
110	handle->channels = 2;
111	handle->resample = 0;
112	*_handle = handle;
113	return 0;
114}
115
116static int create_loopback(struct loopback **_handle,
117			   struct loopback_handle *play,
118			   struct loopback_handle *capt,
119			   snd_output_t *output)
120{
121	struct loopback *handle;
122
123	handle = calloc(1, sizeof(*handle));
124	if (handle == NULL)
125		return -ENOMEM;
126	handle->play = play;
127	handle->capt = capt;
128	play->loopback = handle;
129	capt->loopback = handle;
130	handle->latency_req = 0;
131	handle->latency_reqtime = 10000;
132	handle->loop_time = ~0UL;
133	handle->loop_limit = ~0ULL;
134	handle->output = output;
135	handle->state = output;
136#ifdef USE_SAMPLERATE
137	handle->src_enable = 1;
138	handle->src_converter_type = SRC_SINC_BEST_QUALITY;
139#endif
140	*_handle = handle;
141	return 0;
142}
143
144static void set_loop_time(struct loopback *loop, unsigned long loop_time)
145{
146	loop->loop_time = loop_time;
147	loop->loop_limit = loop->capt->rate * loop_time;
148}
149
150static void setscheduler(void)
151{
152	struct sched_param sched_param;
153
154	if (sched_getparam(0, &sched_param) < 0) {
155		logit(LOG_WARNING, "Scheduler getparam failed.\n");
156		return;
157	}
158	sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
159	if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
160		if (verbose)
161			logit(LOG_WARNING, "Scheduler set to Round Robin with priority %i\n", sched_param.sched_priority);
162		return;
163	}
164	if (verbose)
165		logit(LOG_INFO, "!!!Scheduler set to Round Robin with priority %i FAILED!\n", sched_param.sched_priority);
166}
167
168void help(void)
169{
170	int k;
171	printf(
172"Usage: alsaloop [OPTION]...\n\n"
173"-h,--help      help\n"
174"-g,--config    configuration file (one line = one job specified)\n"
175"-d,--daemonize daemonize the main process and use syslog for errors\n"
176"-P,--pdevice   playback device\n"
177"-C,--cdevice   capture device\n"
178"-X,--pctl      playback ctl device\n"
179"-Y,--cctl      capture ctl device\n"
180"-x,--prateshift playback 'PCM Rate Shift 100000' ascii ctl name\n"
181"-l,--latency   requested latency in frames\n"
182"-t,--tlatency  requested latency in usec (1/1000000sec)\n"
183"-f,--format    sample format\n"
184"-c,--channels  channels\n"
185"-r,--rate      rate\n"
186"-n,--resample  resample in alsa-lib\n"
187"-A,--samplerate use converter (0=sincbest,1=sincmedium,2=sincfastest,\n"
188"                               3=zerohold,4=linear)\n"
189"-B,--buffer    buffer size in frames\n"
190"-E,--period    period size in frames\n"
191"-s,--seconds   duration of loop in seconds\n"
192"-b,--nblock    non-block mode (very early process wakeup)\n"
193"-S,--sync      sync mode(0=none,1=simple,2=captshift,3=playshift,4=samplerate,\n"
194"                         5=auto)\n"
195"-a,--slave     stream parameters slave mode (0=auto, 1=on, 2=off)\n"
196"-T,--thread    thread number (-1 = create unique)\n"
197"-m,--mixer	redirect mixer, argument is:\n"
198"		    SRC_SLAVE_ID(PLAYBACK)[@DST_SLAVE_ID(CAPTURE)]\n"
199"-O,--ossmixer	rescan and redirect oss mixer, argument is:\n"
200"		    ALSA_ID@OSS_ID  (for example: \"Master@VOLUME\")\n"
201"-e,--effect    apply an effect (bandpass filter sweep)\n"
202"-v,--verbose   verbose mode (more -v means more verbose)\n"
203"-w,--workaround use workaround (serialopen)\n"
204"-U,--xrun      xrun profiling\n"
205"-W,--wake      process wake timeout in ms\n"
206"-z,--syslog    use syslog for errors\n"
207);
208	printf("\nRecognized sample formats are:");
209	for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
210		const char *s = snd_pcm_format_name(k);
211		if (s)
212			printf(" %s", s);
213	}
214	printf("\n\n");
215	printf(
216"Tip #1 (usable 500ms latency, good CPU usage, superb xrun prevention):\n"
217"  alsaloop -t 500000\n"
218"Tip #2 (superb 1ms latency, but heavy CPU usage):\n"
219"  alsaloop -t 1000\n"
220);
221}
222
223static long timediff(struct timeval t1, struct timeval t2)
224{
225	signed long l;
226
227	t1.tv_sec -= t2.tv_sec;
228	l = (signed long) t1.tv_usec - (signed long) t2.tv_usec;
229	if (l < 0) {
230		t1.tv_sec--;
231		l = 1000000 + l;
232		l %= 1000000;
233	}
234	return (t1.tv_sec * 1000000) + l;
235}
236
237static void add_loop(struct loopback *loop)
238{
239	loopbacks = realloc(loopbacks, (loopbacks_count + 1) *
240						sizeof(struct loopback *));
241	if (loopbacks == NULL) {
242		logit(LOG_CRIT, "No enough memory\n");
243		exit(EXIT_FAILURE);
244	}
245	loopbacks[loopbacks_count++] = loop;
246}
247
248static int init_mixer_control(struct loopback_control *control,
249			      char *id)
250{
251	int err;
252
253	err = snd_ctl_elem_id_malloc(&control->id);
254	if (err < 0)
255		return err;
256	err = snd_ctl_elem_info_malloc(&control->info);
257	if (err < 0)
258		return err;
259	err = snd_ctl_elem_value_malloc(&control->value);
260	if (err < 0)
261		return err;
262	err = control_parse_id(id, control->id);
263	if (err < 0)
264		return err;
265	return 0;
266}
267
268static int add_mixers(struct loopback *loop,
269		      char **mixers,
270		      int mixers_count)
271{
272	struct loopback_mixer *mixer, *last = NULL;
273	char *str1;
274	int err;
275
276	while (mixers_count > 0) {
277		mixer = calloc(1, sizeof(*mixer));
278		if (mixer == NULL)
279			return -ENOMEM;
280		if (last)
281			last->next = mixer;
282		else
283			loop->controls = mixer;
284		last = mixer;
285		str1 = strchr(*mixers, '@');
286		if (str1)
287			*str1 = '\0';
288		err = init_mixer_control(&mixer->src, *mixers);
289		if (err < 0) {
290			logit(LOG_CRIT, "Wrong mixer control ID syntax '%s'\n", *mixers);
291			return -EINVAL;
292		}
293		err = init_mixer_control(&mixer->dst, str1 ? str1 + 1 : *mixers);
294		if (err < 0) {
295			logit(LOG_CRIT, "Wrong mixer control ID syntax '%s'\n", str1 ? str1 + 1 : *mixers);
296			return -EINVAL;
297		}
298		if (str1)
299			*str1 = '@';
300		mixers++;
301		mixers_count--;
302	}
303	return 0;
304}
305
306static int add_oss_mixers(struct loopback *loop,
307			  char **mixers,
308			  int mixers_count)
309{
310	struct loopback_ossmixer *mixer, *last = NULL;
311	char *str1, *str2;
312
313	while (mixers_count > 0) {
314		mixer = calloc(1, sizeof(*mixer));
315		if (mixer == NULL)
316			return -ENOMEM;
317		if (last)
318			last->next = mixer;
319		else
320			loop->oss_controls = mixer;
321		last = mixer;
322		str1 = strchr(*mixers, ',');
323		if (str1)
324			*str1 = '\0';
325		str2 = strchr(str1 ? str1 + 1 : *mixers, '@');
326		if (str2)
327			*str2 = '\0';
328		mixer->alsa_id = strdup(*mixers);
329		if (str1)
330			mixer->alsa_index = atoi(str1);
331		mixer->oss_id = strdup(str2 ? str2 + 1 : *mixers);
332		if (mixer->alsa_id == NULL || mixer->oss_id == NULL) {
333			logit(LOG_CRIT, "Not enough memory");
334			return -ENOMEM;
335		}
336		if (str1)
337			*str1 = ',';
338		if (str2)
339			*str2 = ',';
340		mixers++;
341		mixers_count--;
342	}
343	return 0;
344}
345
346static void enable_syslog(void)
347{
348	if (!use_syslog) {
349		use_syslog = 1;
350		openlog("alsaloop", LOG_NDELAY|LOG_PID, LOG_DAEMON);
351	}
352}
353
354static int parse_config_file(const char *file, snd_output_t *output);
355
356static int parse_config(int argc, char *argv[], snd_output_t *output,
357			int cmdline)
358{
359	struct option long_option[] =
360	{
361		{"help", 0, NULL, 'h'},
362		{"config", 1, NULL, 'g'},
363		{"daemonize", 0, NULL, 'd'},
364		{"pdevice", 1, NULL, 'P'},
365		{"cdevice", 1, NULL, 'C'},
366		{"pctl", 1, NULL, 'X'},
367		{"cctl", 1, NULL, 'Y'},
368		{"prateshift", 1, NULL, 'x'},
369		{"latency", 1, NULL, 'l'},
370		{"tlatency", 1, NULL, 't'},
371		{"format", 1, NULL, 'f'},
372		{"channels", 1, NULL, 'c'},
373		{"rate", 1, NULL, 'r'},
374		{"buffer", 1, NULL, 'B'},
375		{"period", 1, NULL, 'E'},
376		{"seconds", 1, NULL, 's'},
377		{"nblock", 0, NULL, 'b'},
378		{"effect", 0, NULL, 'e'},
379		{"verbose", 0, NULL, 'v'},
380		{"resample", 0, NULL, 'n'},
381		{"samplerate", 1, NULL, 'A'},
382		{"sync", 1, NULL, 'S'},
383		{"slave", 1, NULL, 'a'},
384		{"thread", 1, NULL, 'T'},
385		{"mixer", 1, NULL, 'm'},
386		{"ossmixer", 1, NULL, 'O'},
387		{"workaround", 1, NULL, 'w'},
388		{"xrun", 0, NULL, 'U'},
389		{"syslog", 0, NULL, 'z'},
390		{NULL, 0, NULL, 0},
391	};
392	int err, morehelp;
393	char *arg_config = NULL;
394	char *arg_pdevice = NULL;
395	char *arg_cdevice = NULL;
396	char *arg_pctl = NULL;
397	char *arg_cctl = NULL;
398	char *arg_prateshift = NULL;
399	unsigned int arg_latency_req = 0;
400	unsigned int arg_latency_reqtime = 10000;
401	snd_pcm_format_t arg_format = SND_PCM_FORMAT_S16_LE;
402	unsigned int arg_channels = 2;
403	unsigned int arg_rate = 48000;
404	snd_pcm_uframes_t arg_buffer_size = 0;
405	snd_pcm_uframes_t arg_period_size = 0;
406	unsigned long arg_loop_time = ~0UL;
407	int arg_nblock = 0;
408	// int arg_effect = 0;
409	int arg_resample = 0;
410#ifdef USE_SAMPLERATE
411	int arg_samplerate = SRC_SINC_FASTEST + 1;
412#endif
413	int arg_sync = SYNC_TYPE_AUTO;
414	int arg_slave = SLAVE_TYPE_AUTO;
415	int arg_thread = 0;
416	struct loopback *loop = NULL;
417	char *arg_mixers[MAX_MIXERS];
418	int arg_mixers_count = 0;
419	char *arg_ossmixers[MAX_MIXERS];
420	int arg_ossmixers_count = 0;
421	int arg_xrun = arg_default_xrun;
422	int arg_wake = arg_default_wake;
423
424	morehelp = 0;
425	while (1) {
426		int c;
427		if ((c = getopt_long(argc, argv,
428				"hdg:P:C:X:Y:x:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:UW:z",
429				long_option, NULL)) < 0)
430			break;
431		switch (c) {
432		case 'h':
433			morehelp++;
434			break;
435		case 'g':
436			arg_config = strdup(optarg);
437			break;
438		case 'd':
439			daemonize = 1;
440			enable_syslog();
441			break;
442		case 'P':
443			arg_pdevice = strdup(optarg);
444			break;
445		case 'C':
446			arg_cdevice = strdup(optarg);
447			break;
448		case 'X':
449			arg_pctl = strdup(optarg);
450			break;
451		case 'Y':
452			arg_cctl = strdup(optarg);
453			break;
454		case 'x':
455			arg_prateshift = strdup(optarg);
456			break;
457		case 'l':
458			err = atoi(optarg);
459			arg_latency_req = err >= 4 ? err : 4;
460			break;
461		case 't':
462			err = atoi(optarg);
463			arg_latency_reqtime = err >= 500 ? err : 500;
464			break;
465		case 'f':
466			arg_format = snd_pcm_format_value(optarg);
467			if (arg_format == SND_PCM_FORMAT_UNKNOWN) {
468				logit(LOG_WARNING, "Unknown format, setting to default S16_LE\n");
469				arg_format = SND_PCM_FORMAT_S16_LE;
470			}
471			break;
472		case 'c':
473			err = atoi(optarg);
474			arg_channels = err >= 1 && err < 1024 ? err : 1;
475			break;
476		case 'r':
477			err = atoi(optarg);
478			arg_rate = err >= 4000 && err < 200000 ? err : 44100;
479			break;
480		case 'B':
481			err = atoi(optarg);
482			arg_buffer_size = err >= 32 && err < 200000 ? err : 0;
483			break;
484		case 'E':
485			err = atoi(optarg);
486			arg_period_size = err >= 32 && err < 200000 ? err : 0;
487			break;
488		case 's':
489			err = atoi(optarg);
490			arg_loop_time = err >= 1 && err <= 100000 ? err : 30;
491			break;
492		case 'b':
493			arg_nblock = 1;
494			break;
495		case 'e':
496			// arg_effect = 1;
497			break;
498		case 'n':
499			arg_resample = 1;
500			break;
501#ifdef USE_SAMPLERATE
502		case 'A':
503			if (strcasecmp(optarg, "sincbest") == 0)
504				arg_samplerate = SRC_SINC_BEST_QUALITY;
505			else if (strcasecmp(optarg, "sincmedium") == 0)
506				arg_samplerate = SRC_SINC_MEDIUM_QUALITY;
507			else if (strcasecmp(optarg, "sincfastest") == 0)
508				arg_samplerate = SRC_SINC_FASTEST;
509			else if (strcasecmp(optarg, "zerohold") == 0)
510				arg_samplerate = SRC_ZERO_ORDER_HOLD;
511			else if (strcasecmp(optarg, "linear") == 0)
512				arg_samplerate = SRC_LINEAR;
513			else
514				arg_samplerate = atoi(optarg);
515			if (arg_samplerate < 0 || arg_samplerate > SRC_LINEAR)
516				arg_sync = SRC_SINC_FASTEST;
517			arg_samplerate += 1;
518			break;
519#endif
520		case 'S':
521			if (strcasecmp(optarg, "samplerate") == 0)
522				arg_sync = SYNC_TYPE_SAMPLERATE;
523			else if (optarg[0] == 'n')
524				arg_sync = SYNC_TYPE_NONE;
525			else if (optarg[0] == 's')
526				arg_sync = SYNC_TYPE_SIMPLE;
527			else if (optarg[0] == 'c')
528				arg_sync = SYNC_TYPE_CAPTRATESHIFT;
529			else if (optarg[0] == 'p')
530				arg_sync = SYNC_TYPE_PLAYRATESHIFT;
531			else if (optarg[0] == 'r')
532				arg_sync = SYNC_TYPE_SAMPLERATE;
533			else if (optarg[0] == 'a')
534				arg_sync = SYNC_TYPE_AUTO;
535			else
536				arg_sync = atoi(optarg);
537			if (arg_sync < 0 || arg_sync > SYNC_TYPE_LAST)
538				arg_sync = SYNC_TYPE_AUTO;
539			break;
540		case 'a':
541			if (optarg[0] == 'a')
542				arg_slave = SLAVE_TYPE_AUTO;
543			else if (strcasecmp(optarg, "on") == 0)
544				arg_slave = SLAVE_TYPE_ON;
545			else if (strcasecmp(optarg, "off") == 0)
546				arg_slave = SLAVE_TYPE_OFF;
547			else
548				arg_slave = atoi(optarg);
549			if (arg_slave < 0 || arg_slave > SLAVE_TYPE_LAST)
550				arg_slave = SLAVE_TYPE_AUTO;
551			break;
552		case 'T':
553			arg_thread = atoi(optarg);
554			if (arg_thread < 0)
555				arg_thread = 10000000 + loopbacks_count;
556			break;
557		case 'm':
558			if (arg_mixers_count >= MAX_MIXERS) {
559				logit(LOG_CRIT, "Maximum redirected mixer controls reached (max %i)\n", (int)MAX_MIXERS);
560				exit(EXIT_FAILURE);
561			}
562			arg_mixers[arg_mixers_count++] = optarg;
563			break;
564		case 'O':
565			if (arg_ossmixers_count >= MAX_MIXERS) {
566				logit(LOG_CRIT, "Maximum redirected mixer controls reached (max %i)\n", (int)MAX_MIXERS);
567				exit(EXIT_FAILURE);
568			}
569			arg_ossmixers[arg_ossmixers_count++] = optarg;
570			break;
571		case 'v':
572			verbose++;
573			break;
574		case 'w':
575			if (strcasecmp(optarg, "serialopen") == 0)
576				workarounds |= WORKAROUND_SERIALOPEN;
577			break;
578		case 'U':
579			arg_xrun = 1;
580			if (cmdline)
581				arg_default_xrun = 1;
582			break;
583		case 'W':
584			arg_wake = atoi(optarg);
585			if (cmdline)
586				arg_default_wake = arg_wake;
587			break;
588		case 'z':
589			enable_syslog();
590			break;
591		}
592	}
593
594	if (morehelp) {
595		help();
596		exit(EXIT_SUCCESS);
597	}
598	if (arg_config == NULL) {
599		struct loopback_handle *play;
600		struct loopback_handle *capt;
601		err = create_loopback_handle(&play, arg_pdevice, arg_pctl, "playback");
602		if (err < 0) {
603			logit(LOG_CRIT, "Unable to create playback handle.\n");
604			exit(EXIT_FAILURE);
605		}
606		err = create_loopback_handle(&capt, arg_cdevice, arg_cctl, "capture");
607		if (err < 0) {
608			logit(LOG_CRIT, "Unable to create capture handle.\n");
609			exit(EXIT_FAILURE);
610		}
611		err = create_loopback(&loop, play, capt, output);
612		if (err < 0) {
613			logit(LOG_CRIT, "Unable to create loopback handle.\n");
614			exit(EXIT_FAILURE);
615		}
616		play->format = capt->format = arg_format;
617		play->rate = play->rate_req = capt->rate = capt->rate_req = arg_rate;
618		play->channels = capt->channels = arg_channels;
619		play->buffer_size_req = capt->buffer_size_req = arg_buffer_size;
620		play->period_size_req = capt->period_size_req = arg_period_size;
621		play->resample = capt->resample = arg_resample;
622		play->nblock = capt->nblock = arg_nblock ? 1 : 0;
623		loop->latency_req = arg_latency_req;
624		loop->latency_reqtime = arg_latency_reqtime;
625		loop->sync = arg_sync;
626		loop->slave = arg_slave;
627		loop->thread = arg_thread;
628		loop->xrun = arg_xrun;
629		loop->wake = arg_wake;
630		err = add_mixers(loop, arg_mixers, arg_mixers_count);
631		if (err < 0) {
632			logit(LOG_CRIT, "Unable to add mixer controls.\n");
633			exit(EXIT_FAILURE);
634		}
635		err = add_oss_mixers(loop, arg_ossmixers, arg_ossmixers_count);
636		if (err < 0) {
637			logit(LOG_CRIT, "Unable to add ossmixer controls.\n");
638			exit(EXIT_FAILURE);
639		}
640		if (arg_prateshift)
641			play->prateshift_name = arg_prateshift;
642
643#ifdef USE_SAMPLERATE
644		loop->src_enable = arg_samplerate > 0;
645		if (loop->src_enable)
646			loop->src_converter_type = arg_samplerate - 1;
647#endif
648		set_loop_time(loop, arg_loop_time);
649		add_loop(loop);
650		return 0;
651	}
652
653	return parse_config_file(arg_config, output);
654}
655
656static int parse_config_file(const char *file, snd_output_t *output)
657{
658	FILE *fp;
659	char line[2048], word[2048];
660	char *str, *ptr;
661	int argc, c, err = 0;
662	char **argv;
663
664	fp = fopen(file, "r");
665	if (fp == NULL) {
666		logit(LOG_CRIT, "Unable to open file '%s': %s\n", file, strerror(errno));
667		return -EIO;
668	}
669	while (!feof(fp)) {
670		if (fgets(line, sizeof(line)-1, fp) == NULL)
671			break;
672		line[sizeof(line)-1] = '\0';
673		my_argv = realloc(my_argv, my_argc + MAX_ARGS * sizeof(char *));
674		if (my_argv == NULL)
675			return -ENOMEM;
676		argv = my_argv + my_argc;
677		argc = 0;
678		argv[argc++] = strdup("<prog>");
679		my_argc++;
680		str = line;
681		while (*str) {
682			ptr = word;
683			while (*str && (*str == ' ' || *str < ' '))
684				str++;
685			if (*str == '#')
686				goto __next;
687			if (*str == '\'' || *str == '\"') {
688				c = *str++;
689				while (*str && *str != c)
690					*ptr++ = *str++;
691				if (*str == c)
692					str++;
693			} else {
694				while (*str && *str != ' ' && *str != '\t')
695					*ptr++ = *str++;
696			}
697			if (ptr != word) {
698				if (*(ptr-1) == '\n')
699					ptr--;
700				*ptr = '\0';
701				if (argc >= MAX_ARGS) {
702					logit(LOG_CRIT, "Too many arguments.");
703					goto __error;
704				}
705				argv[argc++] = strdup(word);
706				my_argc++;
707			}
708		}
709		/* erase runtime variables for getopt */
710		optarg = NULL;
711		optind = opterr = 1;
712		optopt = '?';
713
714		err = parse_config(argc, argv, output, 0);
715	      __next:
716		if (err < 0)
717			break;
718		err = 0;
719	}
720      __error:
721	fclose(fp);
722
723	return err;
724}
725
726static void thread_job1(void *_data)
727{
728	struct loopback_thread *thread = _data;
729	snd_output_t *output = thread->output;
730	struct pollfd *pfds = NULL;
731	int pfds_count = 0;
732	int i, j, err, wake = 1000000;
733
734	setscheduler();
735
736	for (i = 0; i < thread->loopbacks_count; i++) {
737		err = pcmjob_init(thread->loopbacks[i]);
738		if (err < 0) {
739			logit(LOG_CRIT, "Loopback initialization failure.\n");
740			my_exit(thread, EXIT_FAILURE);
741		}
742	}
743	for (i = 0; i < thread->loopbacks_count; i++) {
744		err = pcmjob_start(thread->loopbacks[i]);
745		if (err < 0) {
746			logit(LOG_CRIT, "Loopback start failure.\n");
747			my_exit(thread, EXIT_FAILURE);
748		}
749		pfds_count += thread->loopbacks[i]->pollfd_count;
750		j = thread->loopbacks[i]->wake;
751		if (j > 0 && j < wake)
752			wake = j;
753	}
754	if (wake >= 1000000)
755		wake = -1;
756	pfds = calloc(pfds_count, sizeof(struct pollfd));
757	if (pfds == NULL || pfds_count <= 0) {
758		logit(LOG_CRIT, "Poll FDs allocation failed.\n");
759		my_exit(thread, EXIT_FAILURE);
760	}
761	while (!quit) {
762		struct timeval tv1, tv2;
763		for (i = j = 0; i < thread->loopbacks_count; i++) {
764			err = pcmjob_pollfds_init(thread->loopbacks[i], &pfds[j]);
765			if (err < 0) {
766				logit(LOG_CRIT, "Poll FD initialization failed.\n");
767				my_exit(thread, EXIT_FAILURE);
768			}
769			j += err;
770		}
771		if (verbose > 10)
772			gettimeofday(&tv1, NULL);
773		err = poll(pfds, j, wake);
774		if (err < 0)
775			err = -errno;
776		if (verbose > 10) {
777			gettimeofday(&tv2, NULL);
778			snd_output_printf(output, "pool took %lius\n", timediff(tv2, tv1));
779		}
780		if (err < 0) {
781			if (err == -EINTR || err == -ERESTART)
782				continue;
783			logit(LOG_CRIT, "Poll failed: %s\n", strerror(-err));
784			my_exit(thread, EXIT_FAILURE);
785		}
786		for (i = j = 0; i < thread->loopbacks_count; i++) {
787			struct loopback *loop = thread->loopbacks[i];
788			if (j < loop->active_pollfd_count) {
789				err = pcmjob_pollfds_handle(loop, &pfds[j]);
790				if (err < 0) {
791					logit(LOG_CRIT, "pcmjob failed.\n");
792					exit(EXIT_FAILURE);
793				}
794			}
795			j += loop->active_pollfd_count;
796		}
797	}
798
799	my_exit(thread, EXIT_SUCCESS);
800}
801
802static void thread_job(struct loopback_thread *thread)
803{
804	if (!thread->threaded) {
805		thread_job1(thread);
806		return;
807	}
808	pthread_create(&thread->thread, NULL, (void *) &thread_job1,
809					      (void *) thread);
810}
811
812static void send_to_all(int sig)
813{
814	struct loopback_thread *thread;
815	int i;
816
817	for (i = 0; i < threads_count; i++) {
818		thread = &threads[i];
819		if (thread->threaded)
820			pthread_kill(thread->thread, sig);
821	}
822}
823
824static void signal_handler(int sig ATTRIBUTE_UNUSED)
825{
826	quit = 1;
827	send_to_all(SIGUSR2);
828}
829
830static void signal_handler_state(int sig)
831{
832	pthread_t self = pthread_self();
833	struct loopback_thread *thread;
834	int i, j;
835
836	if (pthread_equal(main_job, self))
837		send_to_all(SIGUSR1);
838	for (i = 0; i < threads_count; i++) {
839		thread = &threads[i];
840		if (thread->thread == self) {
841			for (j = 0; j < thread->loopbacks_count; j++)
842				pcmjob_state(thread->loopbacks[j]);
843		}
844	}
845	signal(sig, signal_handler_state);
846}
847
848static void signal_handler_ignore(int sig)
849{
850	signal(sig, signal_handler_ignore);
851}
852
853int main(int argc, char *argv[])
854{
855	snd_output_t *output;
856	int i, j, k, l, err;
857
858	err = snd_output_stdio_attach(&output, stdout, 0);
859	if (err < 0) {
860		logit(LOG_CRIT, "Output failed: %s\n", snd_strerror(err));
861		exit(EXIT_FAILURE);
862	}
863	err = parse_config(argc, argv, output, 1);
864	if (err < 0) {
865		logit(LOG_CRIT, "Unable to parse arguments or configuration...\n");
866		exit(EXIT_FAILURE);
867	}
868	while (my_argc > 0)
869		free(my_argv[--my_argc]);
870	free(my_argv);
871
872	if (loopbacks_count <= 0) {
873		logit(LOG_CRIT, "No loopback defined...\n");
874		exit(EXIT_FAILURE);
875	}
876
877	if (daemonize) {
878		if (daemon(0, 0) < 0) {
879			logit(LOG_CRIT, "daemon() failed: %s\n", strerror(errno));
880			exit(EXIT_FAILURE);
881		}
882		i = fork();
883		if (i < 0) {
884			logit(LOG_CRIT, "fork() failed: %s\n", strerror(errno));
885			exit(EXIT_FAILURE);
886		}
887		if (i > 0) {
888			/* wait(&i); */
889			exit(EXIT_SUCCESS);
890		}
891	}
892
893	/* we must sort thread IDs */
894	j = -1;
895	do {
896		k = 0x7fffffff;
897		for (i = 0; i < loopbacks_count; i++) {
898			if (loopbacks[i]->thread < k &&
899			    loopbacks[i]->thread > j)
900				k = loopbacks[i]->thread;
901		}
902		j++;
903		for (i = 0; i < loopbacks_count; i++) {
904			if (loopbacks[i]->thread == k)
905				loopbacks[i]->thread = j;
906		}
907	} while (k != 0x7fffffff);
908	/* fix maximum thread id */
909	for (i = 0, j = -1; i < loopbacks_count; i++) {
910		if (loopbacks[i]->thread > j)
911			j = loopbacks[i]->thread;
912	}
913	j += 1;
914	threads = calloc(1, sizeof(struct loopback_thread) * j);
915	if (threads == NULL) {
916		logit(LOG_CRIT, "No enough memory\n");
917		exit(EXIT_FAILURE);
918	}
919	/* sort all threads */
920	for (k = 0; k < j; k++) {
921		for (i = l = 0; i < loopbacks_count; i++)
922			if (loopbacks[i]->thread == k)
923				l++;
924		threads[k].loopbacks = malloc(l * sizeof(struct loopback *));
925		threads[k].loopbacks_count = l;
926		threads[k].output = output;
927		threads[k].threaded = j > 1;
928		for (i = l = 0; i < loopbacks_count; i++)
929			if (loopbacks[i]->thread == k)
930				threads[k].loopbacks[l++] = loopbacks[i];
931	}
932	threads_count = j;
933	main_job = pthread_self();
934
935	signal(SIGINT, signal_handler);
936	signal(SIGTERM, signal_handler);
937	signal(SIGABRT, signal_handler);
938	signal(SIGUSR1, signal_handler_state);
939	signal(SIGUSR2, signal_handler_ignore);
940
941	for (k = 0; k < threads_count; k++)
942		thread_job(&threads[k]);
943
944	if (j > 1) {
945		for (k = 0; k < threads_count; k++)
946			pthread_join(threads[k].thread, NULL);
947	}
948
949	if (use_syslog)
950		closelog();
951	exit(EXIT_SUCCESS);
952}
953