X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=61711dc3f5591d9396ebe62496871404834dea47;hp=cd43f24f47fa31beb27184a39f6dcd560fe3fb3e;hb=959d66719258a7b3d5028e5e6770972768621a4f;hpb=1f556ae88bd8c85d4452f689f532f5a6abeabe92 diff --git a/audiod.c b/audiod.c index cd43f24f..61711dc3 100644 --- a/audiod.c +++ b/audiod.c @@ -28,13 +28,13 @@ #include "filter.h" #include "grab_client.cmdline.h" #include "grab_client.h" -#include "ringbuffer.h" #include "error.h" #include "audiod.h" #include "net.h" #include "daemon.h" #include "string.h" +#include "fd.h" /** define the array of error lists needed by para_audiod */ INIT_AUDIOD_ERRLISTS; @@ -131,23 +131,11 @@ static int playing, current_decoder = -1, sa_time_diff_sign = 1, audiod_socket = -1; static char *af_status, /* the audio format announced in server status */ *socket_name, *hostname; -/** how many status items to remember */ -#define RINGBUFFER_SIZE 32 -static void *stat_item_ringbuf; +static char *stat_item_values[NUM_STAT_ITEMS]; static FILE *logfile; static const struct timeval restart_delay = {0, 300 * 1000}; -static struct audio_format_info afi[] = { - -[AUDIO_FORMAT_MP3] = - { - .write_cmd = "para_play", - }, -[AUDIO_FORMAT_OGG] = - { - .write_cmd = "para_play", - }, -}; +static struct audio_format_info afi[NUM_AUDIO_FORMATS]; static struct audiod_command cmds[] = { { @@ -166,11 +154,13 @@ static struct audiod_command cmds[] = { .description = "grab the audio stream", .synopsis = "-- grab [grab_options]", .help = + "grab ('splice') the audio stream at any position in the filter \n" -"chain and send that data back to the client. \n" -"Available options:\n\n" -GRAB_HELP_TXT +"chain and send that data back to the client. Try\n" +"\t para_audioc -- grab -h\n" +"for the list of available options.\n" }, + { .name = "help", .handler = com_help, @@ -221,11 +211,10 @@ GRAB_HELP_TXT .name = "stat", .handler = com_stat, .description = "print status information", -.synopsis = "stat", +.synopsis = "stat [item1 ...]", .help = -"Add para_audiod status information to para_server's status information\n" -"and dump everything to stdout.\n" +"Dump given status items (all if none given) to stdout.\n" }, { @@ -269,7 +258,7 @@ int get_audio_format_num(char *name) /* * log function. first argument is loglevel. */ -void para_log(int ll, char* fmt,...) +void para_log(int ll, const char* fmt,...) { va_list argp; FILE *outfd; @@ -279,17 +268,7 @@ void para_log(int ll, char* fmt,...) if (ll < conf.loglevel_arg) return; - if (!logfile && conf.logfile_given) - logfile = open_log(conf.logfile_arg); - if (!logfile && conf.daemon_given) - return; - if (!logfile) { - if (ll < WARNING) - outfd = stdout; - else - outfd = stderr; - } else - outfd = logfile; + outfd = logfile? logfile : stderr; time(&t1); tm = localtime(&t1); strftime(str, MAXLINE, "%b %d %H:%M:%S", tm); @@ -312,9 +291,11 @@ static char *get_time_string(struct timeval *newest_stime) struct timeval now, diff, adj_stream_start, tmp; int total = 0, use_server_time = 1; - if (!playing) - return make_message("%s:", length_seconds? - "" : status_item_list[SI_PLAY_TIME]); + if (!playing) { + if (length_seconds) + return NULL; + return make_message("%s:\n", status_item_list[SI_PLAY_TIME]); + } if (audiod_status == AUDIOD_OFF) goto out; if (sa_time_diff_sign > 0) @@ -340,7 +321,7 @@ static char *get_time_string(struct timeval *newest_stime) total = 0; out: return make_message( - "%s:%s%d:%02d [%d:%02d] (%d%%/%d:%02d)", + "%s:%s%d:%02d [%d:%02d] (%d%%/%d:%02d)\n", status_item_list[SI_PLAY_TIME], use_server_time? "~" : "", total / 60, @@ -354,12 +335,31 @@ out: ); } -static char *audiod_status_string(void) +__malloc static char *audiod_status_string(void) +{ + const char *status = (audiod_status == AUDIOD_ON)? + "on" : (audiod_status == AUDIOD_OFF)? "off": "sb"; + return make_message("%s:%s\n", status_item_list[SI_AUDIOD_STATUS], status); +} + +static struct timeval *wstime(void) +{ + int i; + struct timeval *max = NULL; + FOR_EACH_SLOT(i) { + struct slot_info *s = &slot[i]; + if (s->wpid <= 0) + continue; + if (max && tv_diff(&s->wstime, max, NULL) <= 0) + continue; + max = &s->wstime; + } + return max; +} +__malloc static char *decoder_flags(void) { int i; - struct timeval *newest_stime = NULL; - char *ret, *time_string, *uptime_string, *decoder_flags = - para_malloc((MAX_STREAM_SLOTS + 1) * sizeof(char)); + char decoder_flags[MAX_STREAM_SLOTS + 1]; FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; @@ -371,25 +371,10 @@ static char *audiod_status_string(void) if (flag != '0') flag += s->format * 4; decoder_flags[i] = flag; - if (s->wpid <= 0) - continue; - if (newest_stime && tv_diff(&s->wstime, newest_stime, NULL) <= 0) - continue; - newest_stime = &s->wstime; } decoder_flags[MAX_STREAM_SLOTS] = '\0'; - time_string = get_time_string(newest_stime); - uptime_string = uptime_str(); - ret = make_message("%s:%s\n%s:%s\n%s:%s\n%s", - status_item_list[SI_AUDIOD_UPTIME], uptime_string, - status_item_list[SI_DECODER_FLAGS], decoder_flags, - status_item_list[SI_AUDIOD_STATUS], audiod_status == AUDIOD_ON? - "on" : (audiod_status == AUDIOD_OFF? "off": "sb"), - time_string); - free(uptime_string); - free(decoder_flags); - free(time_string); - return ret; + return make_message("%s:%s\n", status_item_list[SI_DECODER_FLAGS], + decoder_flags); } static char *configfile_exists(void) @@ -417,13 +402,34 @@ static void setup_signal_handling(void) static void audiod_status_dump(void) { - static char *prev_status; - char *tmp = audiod_status_string(); - - if (!prev_status || strcmp(tmp, prev_status)) - stat_client_write(tmp); - free(prev_status); - prev_status = tmp; + static char *p_ts, *p_us, *p_as, *p_df; + struct timeval *t = wstime(); + char *us, *tmp = get_time_string(t); + + if (tmp && (!p_ts || strcmp(tmp, p_ts))) + stat_client_write(tmp, SI_PLAY_TIME); + free(p_ts); + p_ts = tmp; + + us = uptime_str(); + tmp = make_message("%s:%s\n", status_item_list[SI_AUDIOD_UPTIME], us); + free(us); + if (!p_us || strcmp(p_us, tmp)) + stat_client_write(tmp, SI_AUDIOD_UPTIME); + free(p_us); + p_us = tmp; + + tmp = audiod_status_string(); + if (!p_as || strcmp(p_as, tmp)) + stat_client_write(tmp, SI_AUDIOD_STATUS); + free(p_as); + p_as = tmp; + + tmp = decoder_flags(); + if (!p_df || strcmp(p_df, tmp)) + stat_client_write(tmp, SI_DECODER_FLAGS); + free(p_df); + p_df = tmp; } static void clear_slot(int slot_num) @@ -448,11 +454,21 @@ static void kill_stream_writer(int slot_num) s->fci->error = 1; } +static void set_restart_barrier(int format, struct timeval *now) +{ + struct timeval tmp; + + if (now) + tmp = *now; + else + gettimeofday(&tmp, NULL); + tv_add(&tmp, &restart_delay, &afi[format].restart_barrier); +} + static void close_receiver(int slot_num) { struct slot_info *s = &slot[slot_num]; struct audio_format_info *a; - struct timeval now; if (s->format < 0 || !s->receiver_node) return; @@ -462,8 +478,7 @@ static void close_receiver(int slot_num) a->receiver->close(s->receiver_node); free(s->receiver_node); s->receiver_node = NULL; - gettimeofday(&now, NULL); - tv_add(&now, &restart_delay, &a->restart_barrier); /* FIXME: Use set_restart_barrier() */ + set_restart_barrier(s->format, NULL); } static void kill_all_decoders(void) @@ -477,17 +492,6 @@ static void kill_all_decoders(void) } } -static void set_restart_barrier(int format, struct timeval *now) -{ - struct timeval tmp; - - if (now) - tmp = *now; - else - gettimeofday(&tmp, NULL); - tv_add(&tmp, &restart_delay, &afi[format].restart_barrier); -} - static void check_sigchld(void) { pid_t pid; @@ -558,7 +562,6 @@ static int decoder_running(int format) static void close_stat_pipe(void) { - char *msg; int i; if (stat_pipe < 0) @@ -568,17 +571,18 @@ static void close_stat_pipe(void) del_close_on_fork_list(stat_pipe); stat_pipe = -1; kill_all_decoders(); - for (i = 0; i < RINGBUFFER_SIZE; i++) - free(ringbuffer_add(stat_item_ringbuf, para_strdup(NULL))); + for (i = 0; i < NUM_STAT_ITEMS; i++) { + free(stat_item_values[i]); + stat_item_values[i] = NULL; + } dump_empty_status(); length_seconds = 0; offset_seconds = 0; audiod_status_dump(); playing = 0; - msg = make_message("%s:no connection to para_server\n", + stat_item_values[SI_STATUS_BAR] = make_message("%s:no connection to para_server\n", status_item_list[SI_STATUS_BAR]); - free(ringbuffer_add(stat_item_ringbuf, msg)); - stat_client_write(msg); + stat_client_write(stat_item_values[SI_STATUS_BAR], SI_STATUS_BAR); } static void __noreturn clean_exit(int status, const char *msg) @@ -592,7 +596,7 @@ static void __noreturn clean_exit(int status, const char *msg) exit(status); } -static char *glob_cmd(char *cmd) +__malloc static char *glob_cmd(char *cmd) { char *ret, *replacement; struct timeval tmp, delay, rss; /* real stream start */ @@ -605,17 +609,14 @@ static char *glob_cmd(char *cmd) else tv_diff(&server_stream_start, &sa_time_diff, &rss); tv_add(&rss, &delay, &tmp); - replacement = make_message("%lu:%lu", tmp.tv_sec, tmp.tv_usec); + replacement = make_message("%lu:%lu", + (long unsigned)tmp.tv_sec, + (long unsigned)tmp.tv_usec); ret = s_a_r(cmd, "STREAM_START", replacement); free(replacement); if (!ret) goto out; PARA_INFO_LOG("cmd: %s, repl: %s\n", cmd, ret); - { - struct timeval now; - gettimeofday(&now, NULL); - PARA_INFO_LOG("now: %lu:%lu\n", now.tv_sec, now.tv_usec); - } out: return ret; } @@ -690,12 +691,15 @@ static void start_stream_writer(int slot_num) int ret, fds[3] = {1, -1, -1}; struct slot_info *s = &slot[slot_num]; struct audio_format_info *a = &afi[s->format]; - char *glob = glob_cmd(a->write_cmd); + char *glob = NULL; - PARA_INFO_LOG("starting stream writer: %s\n", glob? glob : a->write_cmd); + if (a->write_cmd) + glob = glob_cmd(a->write_cmd); + if (!glob) + glob = para_strdup("para_write -w alsa"); + PARA_INFO_LOG("starting stream writer: %s\n", glob); open_filters(slot_num); - - ret = para_exec_cmdline_pid(&s->wpid, glob? glob : a->write_cmd, fds); + ret = para_exec_cmdline_pid(&s->wpid, glob, fds); free(glob); if (ret < 0) { PARA_ERROR_LOG("exec failed (%d)\n", ret); @@ -704,7 +708,7 @@ static void start_stream_writer(int slot_num) s->write_fd = fds[0]; add_close_on_fork_list(s->write_fd); /* we write to this fd in do_select, so we need non-blocking */ - fcntl(s->write_fd, F_SETFL, O_NONBLOCK); + mark_fd_nonblock(s->write_fd); gettimeofday(&s->wstime, NULL); current_decoder = slot_num; activate_inactive_grab_clients(slot_num, s->format, &s->fci->filters); @@ -790,26 +794,34 @@ static void compute_time_diff(const struct timeval *status_time) count > 10? sign : sign * time_smooth, &diff, &tmp); sa_time_diff = tmp; - PARA_INFO_LOG("time diff (cur/avg): " - "%li:%lu/%li:%lu\n", - sign * diff.tv_sec, (diff.tv_usec + 500) / 1000, - sa_time_diff_sign * sa_time_diff.tv_sec, - (sa_time_diff.tv_usec + 500)/ 1000); + PARA_INFO_LOG("time diff (cur/avg): %s%lums/%s%lums\n", + sign > 0? "+" : "-", + tv2ms(&diff), + sa_time_diff_sign ? "+" : "-", + tv2ms(&sa_time_diff) + ); } static void check_stat_line(char *line) { int itemnum; size_t ilen = 0; - struct timeval tv; + long unsigned sec, usec; + char *tmp; + PARA_INFO_LOG("line: %s\n", line); if (!line) return; - free(ringbuffer_add(stat_item_ringbuf, para_strdup(line))); - stat_client_write(line); itemnum = stat_line_valid(line); - if (itemnum < 0) + if (itemnum < 0) { + PARA_WARNING_LOG("invalid status line: %s\n", line); return; + } + tmp = make_message("%s\n", line); + stat_client_write(tmp, itemnum); + free(tmp); + free(stat_item_values[itemnum]); + stat_item_values[itemnum] = para_strdup(line); ilen = strlen(status_item_list[itemnum]); switch (itemnum) { case SI_STATUS: @@ -826,14 +838,16 @@ static void check_stat_line(char *line) length_seconds = atoi(line + ilen + 1); break; case SI_STREAM_START: - if (sscanf(line + ilen + 1, "%lu.%lu", - &tv.tv_sec, &tv.tv_usec) == 2) - server_stream_start = tv; + if (sscanf(line + ilen + 1, "%lu.%lu", &sec, &usec) == 2) { + server_stream_start.tv_sec = sec; + server_stream_start.tv_usec = usec; + } break; case SI_CURRENT_TIME: - if (sscanf(line + ilen + 1, "%lu.%lu", &tv.tv_sec, - &tv.tv_usec) == 2) + if (sscanf(line + ilen + 1, "%lu.%lu", &sec, &usec) == 2) { + struct timeval tv = {sec, usec}; compute_time_diff(&tv); + } break; } } @@ -938,9 +952,9 @@ static void close_decoder_if_idle(int slot_num) clear_slot(slot_num); } -static int set_stream_fds(fd_set *wfds) +static void set_stream_fds(fd_set *wfds, int *max_fileno) { - int i, max_fileno = -1; + int i; check_timeouts(); FOR_EACH_SLOT(i) { @@ -962,12 +976,9 @@ static int set_stream_fds(fd_set *wfds) continue; if (!get_loaded_bytes(i)) continue; - FD_SET(s->write_fd, wfds); + para_fd_set(s->write_fd, wfds, max_fileno); s->wcheck = 1; - max_fileno = MAX(s->write_fd, max_fileno); } -// PARA_INFO_LOG("return %d\n", max_fileno); - return max_fileno; } static int write_audio_data(int slot_num) @@ -1086,7 +1097,7 @@ static int setup_default_filters(void) if (ret < 0) goto out; PARA_INFO_LOG("%s -> default filter: %s\n", audio_formats[i], filters[j].name); - ret = add_filter(i, "wav"); + ret = add_filter(i, para_strdup("wav")); if (ret < 0) goto out; PARA_INFO_LOG("%s -> default filter: wav\n", audio_formats[i]); @@ -1097,7 +1108,7 @@ out: static int init_stream_io(void) { - int i, ret, receiver_num; + int i, ret, receiver_num, nf; char *cmd; for (i = 0; i < conf.stream_write_cmd_given; i++) { @@ -1146,9 +1157,11 @@ static int init_stream_io(void) free(cmd); /* filters */ filter_init(filters); + nf = PARA_MAX(2, conf.filter_given) + 1; + PARA_INFO_LOG("allocating space for %d filters\n", nf); FOR_EACH_AUDIO_FORMAT(i) { - afi[i].filter_conf = para_malloc((conf.filter_given + 1) * sizeof(char *)); - afi[i].filters = para_malloc((conf.filter_given + 1) * sizeof(struct filter *)); + afi[i].filter_conf = para_malloc(nf * sizeof(char *)); + afi[i].filters = para_malloc(nf * sizeof(struct filter *)); } if (!conf.no_default_filters_given) return setup_default_filters(); @@ -1192,7 +1205,7 @@ static int dump_commands(int fd) /* * command handlers don't close their fd on errors (ret < 0) so that * its caller can send an error message. Otherwise (ret >= 0) it's up - * to each individual command to close the fd if necessary. + * to each individual command to close the fd if necessary. */ static int com_help(int fd, int argc, char **argv) @@ -1230,23 +1243,71 @@ out: return ret; } -static int com_stat(int fd, __unused int argc, __unused char **argv) +static int com_stat(int fd, __a_unused int argc, __a_unused char **argv) { int i, ret; - char *buf = audiod_status_string(); + char *buf = NULL; + long unsigned mask = ~0LU; - buf = para_strcat(buf, "\n"); - for (i = RINGBUFFER_SIZE - 1; i >= 0; i--) { - char *tmp, *line = ringbuffer_get(stat_item_ringbuf, i); - if (!line) - continue; - tmp = make_message("%s\n", line); - buf = para_strcat(buf, tmp); + if (argc > 1) { + mask = 0; + for (i = 1; i < argc; i++) { + ret = stat_item_valid(argv[i]); + if (ret < 0) + return ret; + mask |= (1 << ret); + } + } + PARA_INFO_LOG("mask: 0x%lx\n", mask); + if (mask & (1 << SI_PLAY_TIME)) { + struct timeval *t = wstime(); + char *ts = get_time_string(t); + if (ts) { + ret = client_write(fd, ts); + if (ret < 0) + goto out; + free(ts); + } + } + if (mask & (1 << SI_AUDIOD_UPTIME)) { + char *tmp, *us = uptime_str(); + tmp = make_message("%s:%s\n", + status_item_list[SI_AUDIOD_UPTIME], us); + free(us); + ret = client_write(fd, tmp); + if (ret < 0) + goto out; free(tmp); } + if (mask & (1 << SI_AUDIOD_STATUS)) { + char *s = audiod_status_string(); + ret = client_write(fd, s); + if (ret < 0) + goto out; + free(s); + } + if (mask & (1 << SI_DECODER_FLAGS)) { + char *df =decoder_flags(); + ret = client_write(fd, df); + if (ret < 0) + goto out; + free(df); + } + + for (i = 0; i < NUM_STAT_ITEMS; i++) { + char *tmp, *v; + if (!((1 << i) & mask)) + continue; + v = stat_item_values[i]; + tmp = make_message("%s%s%s", buf? buf: "", + v? v : "", v? "\n" : ""); + free(buf); + buf = tmp; + } ret = client_write(fd, buf); +out: if (ret > 0) - ret = stat_client_add(fd); + ret = stat_client_add(fd, mask); free(buf); return ret; } @@ -1277,7 +1338,8 @@ static int com_grab(int fd, int argc, char **argv) { struct grab_client *gc; struct filter_node *fn; - int err; + int i, err; + char *msg; PARA_INFO_LOG("argc: %d, argv[0]: %s, optind: %d\n", argc, argv[0], optind); gc = grab_client_new(fd, argc, argv, &err); @@ -1289,40 +1351,49 @@ static int com_grab(int fd, int argc, char **argv) activate_grab_client(gc, fn); return 1; err_out: - if (err != -E_GC_HELP_GIVEN) - return err; - err = client_write(fd, "Usage: para_audioc [audioc_options] -- " - "grab [grab_options]\nAvailable options:\n"); - if (err < 0) + if (err != -E_GC_HELP_GIVEN && err != -E_GC_VERSION_GIVEN) return err; - err = client_write(fd, GRAB_HELP_TXT); + if (err == -E_GC_HELP_GIVEN) { + msg = make_message("%s\n\n", grab_client_args_info_usage); + for (i = 0; grab_client_args_info_help[i]; i++) { + char *tmp = make_message("%s%s\n", msg, + grab_client_args_info_help[i]); + free(msg); + msg = tmp; + } + } else + msg = make_message("%s %s\n", + GRAB_CLIENT_CMDLINE_PARSER_PACKAGE, + GRAB_CLIENT_CMDLINE_PARSER_VERSION); + err = client_write(fd, msg); + free(msg); if (err < 0) return err; close(fd); return 1; } -static int __noreturn com_term(int fd, __unused int argc, __unused char **argv) +static int __noreturn com_term(int fd, __a_unused int argc, __a_unused char **argv) { close(fd); clean_exit(EXIT_SUCCESS, "terminating on user request"); } -static int com_on(int fd, __unused int argc, __unused char **argv) +static int com_on(int fd, __a_unused int argc, __a_unused char **argv) { audiod_status = AUDIOD_ON; close(fd); return 1; } -static int com_off(int fd, __unused int argc, __unused char **argv) +static int com_off(int fd, __a_unused int argc, __a_unused char **argv) { audiod_status = AUDIOD_OFF; close(fd); return 1; } -static int com_sb(int fd, __unused int argc, __unused char **argv) +static int com_sb(int fd, __a_unused int argc, __a_unused char **argv) { audiod_status = AUDIOD_STANDBY; close(fd); @@ -1346,14 +1417,14 @@ static int com_cycle(int fd, int argc, char **argv) return 1; } -static int check_perms(struct ucred *c) +static int check_perms(uid_t uid) { int i; if (!conf.user_allow_given) return 1; for (i = 0; i < conf.user_allow_given; i++) - if (c->uid == conf.user_allow_arg[i]) + if (uid == conf.user_allow_arg[i]) return 1; return -E_UCRED_PERM; } @@ -1361,7 +1432,6 @@ static int check_perms(struct ucred *c) static int handle_connect(void) { int i, argc, ret, clifd = -1; - struct ucred c; char *buf = para_malloc(MAXLINE), **argv = NULL; struct sockaddr_un unix_addr; @@ -1369,20 +1439,19 @@ static int handle_connect(void) if (ret < 0) goto out; clifd = ret; - ret = recv_cred_buffer(clifd, buf, MAXLINE - 1, &c); + ret = recv_cred_buffer(clifd, buf, MAXLINE - 1); if (ret < 0) goto out; - PARA_INFO_LOG("pid: %i, uid: %i, gid: %i, ret: %i, buf: %s\n", c.pid, c.uid, c.gid, ret, buf); - buf[ret] = '\0'; - ret = check_perms(&c); + PARA_INFO_LOG("connection from user %i\n", ret); + ret = check_perms(ret); if (ret < 0) goto out; - argc = split_args(buf, &argv, '\n'); - PARA_INFO_LOG("argv[0]: %s\n", argv[0]); + argc = split_args(buf, &argv, "\n"); + PARA_INFO_LOG("argv[0]: %s, argc= %d\n", argv[0], argc); for (i = 0; cmds[i].name; i++) { if (strcmp(cmds[i].name, argv[0])) continue; - ret = cmds[i].handler(clifd, argc + 1, argv); + ret = cmds[i].handler(clifd, argc, argv); goto out; } ret = -E_INVALID_AUDIOD_CMD; /* cmd not found */ @@ -1429,9 +1498,8 @@ static void audiod_get_socket(void) static int open_stat_pipe(void) { int ret, fd[3] = {-1, 1, 0}; - char *argv[] = {BINDIR "/para_client", "stat", NULL}; pid_t pid; - ret = para_exec(&pid, BINDIR "/para_client", argv, fd); + ret = para_exec_cmdline_pid(&pid, BINDIR "/para_client stat", fd); if (ret >= 0) { ret = fd[1]; PARA_NOTICE_LOG("stat pipe opened, fd %d\n", ret); @@ -1441,9 +1509,10 @@ static int open_stat_pipe(void) return ret; } -static int pre_select(fd_set *rfds, fd_set *wfds, struct timeval *tv) +static void audiod_pre_select(fd_set *rfds, fd_set *wfds, struct timeval *tv, + int *max_fileno) { - int i, ret, max = -1; + int i, ret; FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; @@ -1454,10 +1523,8 @@ static int pre_select(fd_set *rfds, fd_set *wfds, struct timeval *tv) a = &afi[s->format]; ret = a->receiver->pre_select(rn, rfds, wfds, tv); // PARA_NOTICE_LOG("%s preselect: %d\n", a->receiver->name, ret); - max = MAX(max, ret); + *max_fileno = PARA_MAX(*max_fileno, ret); } - return max; - } static void audiod_post_select(int select_ret, fd_set *rfds, fd_set *wfds) { @@ -1492,15 +1559,19 @@ static void __noreturn audiod_mainloop(void) char status_buf[STRINGSIZE] = ""; struct timeval tv; repeat: - FD_ZERO(&rfds); FD_ZERO(&wfds); - max_fileno = 0; + FD_ZERO(&rfds); + /* always check signal pipe and the local socket */ + para_fd_set(signal_pipe, &rfds, &max_fileno); + para_fd_set(audiod_socket, &rfds, &max_fileno); + if (audiod_status != AUDIOD_ON) kill_all_decoders(); else if (playing) start_current_receiver(); - max_fileno = set_stream_fds(&wfds); - /* stat pipe (read) */ + + set_stream_fds(&wfds, &max_fileno); + /* status pipe */ if (stat_pipe >= 0 && audiod_status == AUDIOD_OFF) close_stat_pipe(); if (stat_pipe < 0 && audiod_status != AUDIOD_OFF) { @@ -1508,30 +1579,17 @@ repeat: sbo = 0; status_buf[0] = '\0'; } - if (stat_pipe >= 0 && audiod_status != AUDIOD_OFF) { - FD_SET(stat_pipe, &rfds); - max_fileno = MAX(max_fileno, stat_pipe); - } - /* always check signal pipe */ - FD_SET(signal_pipe, &rfds); - max_fileno = MAX(max_fileno, signal_pipe); + if (stat_pipe >= 0 && audiod_status != AUDIOD_OFF) + para_fd_set(stat_pipe, &rfds, &max_fileno); /* local socket */ - if (audiod_socket < 0) - audiod_get_socket(); /* doesn't return on errors */ - FD_SET(audiod_socket, &rfds); - max_fileno = MAX(max_fileno, audiod_socket); tv.tv_sec = 0; tv.tv_usec = 200 * 1000; - ret = pre_select(&rfds, &wfds, &tv); - max_fileno = MAX(max_fileno, ret); - ret = select(max_fileno + 1, &rfds, &wfds, NULL, &tv); - if (ret < 0 && errno != EINTR) - PARA_ERROR_LOG("select returned %d (%s)\n", ret, - strerror(errno)); - if (audiod_status != AUDIOD_OFF) - audiod_status_dump(); + audiod_pre_select(&rfds, &wfds, &tv, &max_fileno); + ret = para_select(max_fileno + 1, &rfds, &wfds, &tv); if (ret < 0) goto repeat; + if (audiod_status != AUDIOD_OFF) + audiod_status_dump(); audiod_post_select(ret, &rfds, &wfds); /* read status pipe */ if (stat_pipe >=0 && FD_ISSET(stat_pipe, &rfds)) { @@ -1585,32 +1643,34 @@ int __noreturn main(int argc, char *argv[]) char *cf; int i; + fprintf(stderr, "argc: %d\n", argc); valid_fd_012(); hostname = para_hostname(); cmdline_parser(argc, argv, &conf); - para_drop_privileges(conf.user_arg); + para_drop_privileges(conf.user_arg, conf.group_arg); cf = configfile_exists(); if (cf) { if (cmdline_parser_configfile(cf, &conf, 0, 0, 0)) { - fprintf(stderr, "parse error in config file\n"); + PARA_EMERG_LOG("%s", "parse error in config file\n"); exit(EXIT_FAILURE); } } + if (conf.logfile_given) + logfile = open_log(conf.logfile_arg); log_welcome("para_audiod", conf.loglevel_arg); i = init_stream_io(); if (i < 0) { - fprintf(stderr, "init stream io error: %s\n", - PARA_STRERROR(-i)); + PARA_EMERG_LOG("init stream io error: %s\n", PARA_STRERROR(-i)); exit(EXIT_FAILURE); } server_uptime(UPTIME_SET); set_initial_status(); FOR_EACH_SLOT(i) clear_slot(i); - stat_item_ringbuf = ringbuffer_new(RINGBUFFER_SIZE); init_grabbing(); setup_signal_handling(); if (conf.daemon_given) daemon_init(); + audiod_get_socket(); /* doesn't return on errors */ audiod_mainloop(); }