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