X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=9d32e889ea37364addb3258bd15458615e776a78;hp=a76ee1fdc9866756645caf11f576461343b5bf8c;hb=31bc1f853b69884dd8659efe7455386211648476;hpb=d32eb7a5cf569ee842d91f3f830a8562fa0ae12d diff --git a/audiod.c b/audiod.c index a76ee1fd..9d32e889 100644 --- a/audiod.c +++ b/audiod.c @@ -212,20 +212,17 @@ static void kill_all_decoders(int error) FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; - if (s->wng && !s->wng->task.error) { - PARA_INFO_LOG("unregistering writer node group in slot %d\n", + if (s->wng && s->wng->task.error >= 0) { + PARA_INFO_LOG("deactivating wng in slot %d\n", i); - wng_unregister(s->wng); s->wng->task.error = error; } - if (s->fc && !s->fc->task.error) { - PARA_INFO_LOG("unregistering filter chain in slot %d\n", i); - unregister_task(&s->fc->task); + if (s->fc && s->fc->task.error >= 0) { + PARA_INFO_LOG("deactivatimg filter chain in slot %d\n", i); s->fc->task.error = error; } - if (s->receiver_node && !s->receiver_node->task.error) { - PARA_INFO_LOG("unregistering receiver_node in slot %d\n", i); - unregister_task(&s->receiver_node->task); + if (s->receiver_node && s->receiver_node->task.error >= 0) { + PARA_INFO_LOG("deactivating receiver_node in slot %d\n", i); s->receiver_node->task.error = error; } } @@ -528,8 +525,6 @@ static int check_stat_line(char *line, __a_unused void *data) struct timeval tv = {sec, usec}; compute_time_diff(&tv); } - if (stat_task->clock_diff_count) - stat_task->clock_diff_count--; break; case SI_FORMAT: stat_task->current_audio_format_num = get_audio_format_num( @@ -538,96 +533,6 @@ static int check_stat_line(char *line, __a_unused void *data) return 1; } -static void try_to_close_slot(int slot_num) -{ - struct slot_info *s = &slot[slot_num]; - - if (s->format < 0) - return; - if (s->receiver_node && s->receiver_node->task.error >= 0) - return; - if (s->fc && s->fc->task.error >= 0) - return; - if (s->wng && s->wng->task.error >= 0) - return; - PARA_INFO_LOG("closing slot %d\n", slot_num); - wng_close(s->wng); - close_filters(s->fc); - free(s->fc); - close_receiver(slot_num); - clear_slot(slot_num); -} - -/* - * Check if any receivers/filters/writers need to be started and do so if - * necessary. Since the pre_select function didn't have a chance yet to put - * file descriptors into the fd sets given by s, make the upcoming select() - * return immediately to avoid a long timeout in case we started something. - */ -static void audiod_pre_select(struct sched *s, __a_unused struct task *t) -{ - int i; - struct timeval min_delay = {0, 1}; - - if (audiod_status != AUDIOD_ON || !stat_task->playing) - return kill_all_decoders(-E_NOT_PLAYING); - if (open_current_receiver(s)) - s->timeout = min_delay; - FOR_EACH_SLOT(i) { - struct slot_info *sl = &slot[i]; - struct audio_format_info *a; - struct timeval diff; - - if (sl->format < 0) - continue; - a = &afi[sl->format]; - if (!sl->receiver_node) - continue; - if ((!a->num_filters || sl->fc) && sl->wng) - continue; /* everything already started */ - if (!a->num_filters) { - if (sl->receiver_node->loaded && !sl->wng) { - open_writers(i); - s->timeout = min_delay; - } - continue; - } - if (sl->receiver_node->loaded && !sl->fc) { - open_filters(i); - s->timeout = min_delay; - continue; - } - if (sl->wng || !sl->fc || !*sl->fc->out_loaded) - continue; - if (tv_diff(now, &initial_delay_barrier, &diff) > 0) { - open_writers(i); - s->timeout = min_delay; - continue; - } - PARA_INFO_LOG("initial delay: %lu ms left\n", tv2ms(&diff)); - if (tv_diff(&s->timeout, &diff, NULL) > 0) { - s->timeout = diff; - } - } -} - -static void audiod_post_select(__a_unused struct sched *s, - __a_unused struct task *t) -{ - int i; - - FOR_EACH_SLOT(i) - try_to_close_slot(i); -} - -static void init_audiod_task(struct task *t) -{ - t->pre_select = audiod_pre_select; - t->post_select = audiod_post_select; - t->error = 0; - sprintf(t->status, "audiod task"); -} - static int parse_stream_command(const char *txt, char **cmd) { char *p = strchr(txt, ':'); @@ -944,10 +849,6 @@ static void close_stat_pipe(void) status_item_list[SI_BASENAME]); stat_client_write(stat_task->stat_item_values[SI_BASENAME], SI_BASENAME); - if (stat_task->clock_diff_count) { - stat_task->clock_diff_barrier.tv_sec = now->tv_sec + 1; - stat_task->clock_diff_barrier.tv_usec = now->tv_usec; - } } /** @@ -972,76 +873,147 @@ void __noreturn clean_exit(int status, const char *msg) } /* avoid busy loop if server is down */ -static void set_stat_task_restart_barrier(void) +static void set_stat_task_restart_barrier(unsigned seconds) { - struct timeval delay = {5, 0}; + struct timeval delay = {seconds, 0}; tv_add(now, &delay, &stat_task->restart_barrier); } -/* restart the client task if necessary */ -static void status_pre_select(struct sched *s, struct task *t) +static void try_to_close_slot(int slot_num) { - struct status_task *st = container_of(t, struct status_task, task); - int ret; + struct slot_info *s = &slot[slot_num]; - if (st->ct || audiod_status == AUDIOD_OFF) /* no need to restart */ + if (s->format < 0) return; - if (!st->clock_diff_count && tv_diff(now, &st->restart_barrier, NULL) - < 0) + if (s->receiver_node && s->receiver_node->task.error != -E_TASK_UNREGISTERED) return; - if (st->clock_diff_count) { /* get status only one time */ - char *argv[] = {"audiod", "stat", "1", NULL}; - int argc = 3; - if (tv_diff(now, &st->clock_diff_barrier, NULL) < 0) - return; - PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count); - ret = client_open(argc, argv, &st->ct); + if (s->fc && s->fc->task.error != -E_TASK_UNREGISTERED) + return; + if (s->wng && s->wng->task.error != -E_TASK_UNREGISTERED) + return; + PARA_INFO_LOG("closing slot %d\n", slot_num); + wng_close(s->wng); + close_filters(s->fc); + free(s->fc); + close_receiver(slot_num); + clear_slot(slot_num); +} - } else { - char *argv[] = {"audiod", "stat", NULL}; - int argc = 2; - ret = client_open(argc, argv, &st->ct); +/* + * Check if any receivers/filters/writers need to be started and do so if + * necessary. + */ +static void start_stop_decoders(struct sched *s) +{ + int i; + + FOR_EACH_SLOT(i) + try_to_close_slot(i); + if (audiod_status != AUDIOD_ON || !stat_task->playing) + return kill_all_decoders(-E_NOT_PLAYING); + open_current_receiver(s); + FOR_EACH_SLOT(i) { + struct slot_info *sl = &slot[i]; + struct audio_format_info *a; + struct timeval diff; + + if (sl->format < 0) + continue; + a = &afi[sl->format]; + if (!sl->receiver_node) + continue; + if ((!a->num_filters || sl->fc) && sl->wng) + continue; /* everything already started */ + if (!a->num_filters) { + if (sl->receiver_node->loaded && !sl->wng) { + open_writers(i); + } + continue; + } + if (sl->receiver_node->loaded && !sl->fc) { + open_filters(i); + continue; + } + if (sl->wng || !sl->fc || !*sl->fc->out_loaded) + continue; + if (tv_diff(now, &initial_delay_barrier, &diff) > 0) { + open_writers(i); + continue; + } + PARA_INFO_LOG("initial delay: %lu ms left\n", tv2ms(&diff)); + if (tv_diff(&s->timeout, &diff, NULL) > 0) { + s->timeout = diff; + } } - set_stat_task_restart_barrier(); - if (ret < 0) - return; - s->timeout.tv_sec = 0; - s->timeout.tv_usec = 1; } -static void status_post_select(__a_unused struct sched *s, struct task *t) + +/* restart the client task if necessary */ +static void status_pre_select(struct sched *s, struct task *t) { struct status_task *st = container_of(t, struct status_task, task); - unsigned bytes_left; - if (!st->ct || st->ct->status != CL_RECEIVING) - return; - if (audiod_status == AUDIOD_OFF || st->ct->task.error < 0) { - if (st->ct->task.error >= 0) - unregister_task(&st->ct->task); - if (audiod_status == AUDIOD_OFF) - st->clock_diff_count = conf.clock_diff_count_arg; + if (audiod_status == AUDIOD_OFF) { + if (!st->ct) + goto out; + if (st->ct->task.error >= 0) { + st->ct->task.error = -E_AUDIOD_OFF; + goto out; + } + if (st->ct->task.error != -E_TASK_UNREGISTERED) + goto out; close_stat_pipe(); - return; + st->clock_diff_count = conf.clock_diff_count_arg; + goto out; } - bytes_left = for_each_line(st->ct->buf, st->ct->loaded, - &check_stat_line, NULL); - if (st->ct->loaded != bytes_left) { - st->last_status_read = *now; - st->ct->loaded = bytes_left; - } else { - struct timeval diff; - tv_diff(now, &st->last_status_read, &diff); - if (diff.tv_sec > 61) + if (st->ct) { + unsigned bytes_left; + if (st->ct->task.error < 0) { + if (st->ct->task.error != -E_TASK_UNREGISTERED) + goto out; close_stat_pipe(); + goto out; + } + if (st->ct->status != CL_RECEIVING) + goto out; + bytes_left = for_each_line(st->ct->buf, st->ct->loaded, + &check_stat_line, NULL); + if (st->ct->loaded != bytes_left) { + st->last_status_read = *now; + st->ct->loaded = bytes_left; + } else { + struct timeval diff; + tv_diff(now, &st->last_status_read, &diff); + if (diff.tv_sec > 61) + st->ct->task.error = -E_STATUS_TIMEOUT; + } + goto out; + } + if (tv_diff(now, &st->restart_barrier, NULL) < 0) + goto out; + if (st->clock_diff_count) { /* get status only one time */ + char *argv[] = {"audiod", "stat", "1", NULL}; + int argc = 3; + PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count); + st->clock_diff_count--; + client_open(argc, argv, &st->ct); + set_stat_task_restart_barrier(2); + + } else { + char *argv[] = {"audiod", "stat", NULL}; + int argc = 2; + client_open(argc, argv, &st->ct); + set_stat_task_restart_barrier(5); } + st->last_status_read = *now; +out: + start_stop_decoders(s); } static void init_status_task(struct status_task *st) { memset(st, 0, sizeof(struct status_task)); st->task.pre_select = status_pre_select; - st->task.post_select = status_post_select; st->sa_time_diff_sign = 1; st->clock_diff_count = conf.clock_diff_count_arg; st->current_audio_format_num = -1; @@ -1081,7 +1053,6 @@ int main(int argc, char *argv[]) int ret, i; struct sched s; struct command_task command_task_struct, *cmd_task = &command_task_struct; - struct task audiod_task_struct, *audiod_task = &audiod_task_struct; valid_fd_012(); audiod_cmdline_parser(argc, argv, &conf); @@ -1120,7 +1091,6 @@ int main(int argc, char *argv[]) init_status_task(stat_task); init_command_task(cmd_task); - init_audiod_task(audiod_task); if (conf.daemon_given) daemon_init(); @@ -1128,7 +1098,6 @@ int main(int argc, char *argv[]) register_task(&sig_task->task); register_task(&cmd_task->task); register_task(&stat_task->task); - register_task(audiod_task); s.default_timeout.tv_sec = 0; s.default_timeout.tv_usec = 99 * 1000; ret = schedule(&s);