X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=0c8ee2875873ef5c86b392448d0c80e6ec6e4540;hp=0d8745d725bce902419afdd17c50a58cf51dd7fc;hb=f23be61d476e3f354e31072da0e0e77050a8dc56;hpb=b99f2c1074bb0786c389830fc5c4db93a61a1dcc diff --git a/audiod.c b/audiod.c index 0d8745d7..0c8ee287 100644 --- a/audiod.c +++ b/audiod.c @@ -111,24 +111,34 @@ static struct timeval *now; static struct signal_task signal_task_struct, *sig_task = &signal_task_struct; +/** + * the task for handling audiod commands + * + * \sa struct task, struct sched + */ struct command_task { + /** the local listening socket */ int fd; + /** the associated task structure */ struct task task; }; -static struct command_task command_task_struct, *cmd_task = &command_task_struct; +/** + * the task for audiod's child (para_client stat) + * + * \sa struct task, struct sched + */ struct status_task { + /** the output of the stat command is read from this fd */ int fd; - struct task task; + /** stat data is stored here */ char buf[STRINGSIZE]; + /** number of bytes loaded in \a buf */ unsigned loaded; -}; -static struct status_task status_task_struct, *stat_task = &status_task_struct; - -struct audiod_task { + /** the associated task structure */ struct task task; }; -static struct audiod_task audiod_task_struct, *at = &audiod_task_struct; +static struct status_task status_task_struct, *stat_task = &status_task_struct; struct signal_task { int fd; @@ -136,13 +146,17 @@ struct signal_task { struct task task; }; - /** defines one command of para_audiod */ struct audiod_command { /** the name of the command */ const char *name; /** pointer to the function that handles the command */ int (*handler)(int, int, char**); + /** + * if the command prefers to handle the full line (rather than the usual + * argv[] array), it stores a pointer to the corresponding line handling + * function here. In this case, the above \a handler pointer must be NULL. + */ int (*line_handler)(int, char*); /** one-line description of the command */ const char *description; @@ -553,7 +567,6 @@ static void close_stat_pipe(void) static void __noreturn clean_exit(int status, const char *msg) { PARA_EMERG_LOG("%s\n", msg); - kill_all_decoders(); if (socket_name) unlink(socket_name); if (stat_task->fd >= 0) @@ -597,12 +610,13 @@ static void open_filters(int slot_num) s->fc->inbuf = s->receiver_node->buf; s->fc->in_loaded = &s->receiver_node->loaded; s->fc->input_eof = &s->receiver_node->eof; - s->fc->task.pre_select = filter_pre_select; s->fc->task.event_handler = filter_event_handler; s->fc->task.private_data = s->fc; s->fc->task.flags = 0; s->fc->eof = 0; + + s->receiver_node->output_eof = &s->fc->eof; sprintf(s->fc->task.status, "filter chain"); for (i = 0; i < nf; i++) { struct filter_node *fn = para_calloc(sizeof(struct filter_node)); @@ -619,8 +633,6 @@ static void open_filters(int slot_num) s->fc->out_loaded = &fn->loaded; } register_task(&s->fc->task); -// PARA_DEBUG_LOG("output loaded for filter chain %p: %p\n", s->fc, -// s->fc->out_loaded); } static struct filter_node *find_filter_node(int slot_num, int format, int filternum) @@ -650,8 +662,20 @@ static struct filter_node *find_filter_node(int slot_num, int format, int filter static void wng_event_handler(struct task *t) { - PARA_INFO_LOG("%s\n", PARA_STRERROR(-t->ret)); - unregister_task(t); + struct writer_node_group *wng = t->private_data; + int i; + + wng_unregister(wng); + FOR_EACH_SLOT(i) { + struct slot_info *s = &slot[i]; + if (s->wng != wng) + continue; +// if (s->fc) +// s->fc->eof = 1; +// if (s->receiver_node) +// s->receiver_node->eof = 1; + PARA_INFO_LOG("slot %d: %s\n", i, PARA_STRERROR(-t->ret)); + } } static void open_writers(int slot_num) @@ -669,7 +693,10 @@ static void open_writers(int slot_num) s->wng->buf = s->fc->outbuf; s->wng->loaded = s->fc->out_loaded; s->wng->input_eof = &s->fc->eof; + s->wng->channels = &s->fc->channels; + s->wng->samplerate = &s->fc->samplerate; s->fc->output_eof = &s->wng->eof; + PARA_INFO_LOG("samplerate: %d\n", *s->wng->samplerate); } else { s->wng->buf = s->receiver_node->buf; s->wng->loaded = &s->receiver_node->loaded; @@ -681,7 +708,7 @@ static void open_writers(int slot_num) s->wng->writer_nodes[i].writer = a->writers[i]; sprintf(s->wng->writer_nodes[i].task.status, "writer_node"); } - ret = wng_open(s->wng); + ret = wng_open(s->wng); /* FIXME */ s->wstime = *now; current_decoder = slot_num; activate_inactive_grab_clients(slot_num, s->format, &s->fc->filters); @@ -870,7 +897,6 @@ static void try_to_close_slot(int slot_num) return; PARA_INFO_LOG("closing slot %d \n", slot_num); wng_close(s->wng); - wng_destroy(s->wng); close_filters(s->fc); free(s->fc); close_receiver(slot_num); @@ -881,22 +907,33 @@ static void audiod_pre_select(struct sched *s, __a_unused struct task *t) { int i; + t->ret = 1; now = &s->now; if (audiod_status != AUDIOD_ON) kill_all_decoders(); else if (playing) open_current_receiver(); FOR_EACH_SLOT(i) { - struct receiver_node *rn; + struct slot_info *s = &slot[i]; + struct audio_format_info *a; try_to_close_slot(i); - if (slot[i].format < 0) + if (s->format < 0) + continue; + a = &afi[s->format]; + if (!s->receiver_node) + continue; + if (!a->num_filters) { + if (s->receiver_node->loaded && !s->wng) + open_writers(i); continue; - rn = slot[i].receiver_node; - if (rn && rn->loaded && !slot[i].wng) { + } + if (s->receiver_node->loaded && !s->fc) { open_filters(i); - open_writers(i); + continue; } + if (s->fc && *s->fc->out_loaded && !s->wng) + open_writers(i); } } @@ -904,15 +941,17 @@ static void audiod_post_select(struct sched *s, __a_unused struct task *t) { /* only save away the current time for other users */ now = &s->now; + t->ret = 1; } -static void init_audiod_task(struct audiod_task *at) +static void init_audiod_task(struct task *t) { - at->task.pre_select = audiod_pre_select; - at->task.post_select = audiod_post_select; - at->task.private_data = at; - at->task.flags = 0; - sprintf(at->task.status, "audiod task"); + t->pre_select = audiod_pre_select; + t->post_select = audiod_post_select; + t->event_handler = NULL; + t->private_data = t; + t->flags = 0; + sprintf(t->status, "audiod task"); } static int parse_stream_command(const char *txt, char **cmd) @@ -1335,13 +1374,13 @@ static int check_perms(uid_t uid) return -E_UCRED_PERM; } -static int handle_connect(void) +static int handle_connect(int accept_fd) { int i, argc, ret, clifd = -1; char *cmd = NULL, *p, *buf = para_calloc(MAXLINE), **argv = NULL; struct sockaddr_un unix_addr; - ret = para_accept(cmd_task->fd, &unix_addr, sizeof(struct sockaddr_un)); + ret = para_accept(accept_fd, &unix_addr, sizeof(struct sockaddr_un)); if (ret < 0) goto out; clifd = ret; @@ -1392,9 +1431,10 @@ out: return ret; } -static void audiod_get_socket(void) +static int audiod_get_socket(void) { struct sockaddr_un unix_addr; + int fd; if (conf.socket_given) socket_name = para_strdup(conf.socket_arg); @@ -1404,20 +1444,21 @@ static void audiod_get_socket(void) hn); free(hn); } - PARA_NOTICE_LOG("connecting to local socket %s\n", socket_name); + PARA_NOTICE_LOG("local socket: %s\n", socket_name); if (conf.force_given) unlink(socket_name); - cmd_task->fd = create_pf_socket(socket_name, &unix_addr, + fd = create_pf_socket(socket_name, &unix_addr, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH); - if (cmd_task->fd < 0) { + if (fd < 0) { PARA_EMERG_LOG("%s", "can not connect to socket\n"); exit(EXIT_FAILURE); /* do not unlink socket */ } - if (listen(cmd_task->fd , 5) < 0) { + if (listen(fd , 5) < 0) { PARA_EMERG_LOG("%s", "can not listen on socket\n"); exit(EXIT_FAILURE); /* do not unlink socket */ } - add_close_on_fork_list(cmd_task->fd); + add_close_on_fork_list(fd); + return fd; } static int open_stat_pipe(void) @@ -1469,6 +1510,7 @@ void signal_setup_default(struct signal_task *st) static void command_pre_select(struct sched *s, struct task *t) { struct command_task *ct = t->private_data; + t->ret = 1; para_fd_set(ct->fd, &s->rfds, &s->max_fileno); } @@ -1478,12 +1520,12 @@ static void command_post_select(struct sched *s, struct task *t) int ret; struct command_task *ct = t->private_data; + t->ret = 1; /* always successful */ if (audiod_status != AUDIOD_OFF) audiod_status_dump(); - t->ret = 1; /* always successful */ if (!FD_ISSET(ct->fd, &s->rfds)) return; - ret = handle_connect(); + ret = handle_connect(ct->fd); if (ret < 0) PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); } @@ -1492,8 +1534,10 @@ static void init_command_task(struct command_task *ct) { ct->task.pre_select = command_pre_select; ct->task.post_select = command_post_select; + ct->task.event_handler = NULL; ct->task.private_data = ct; ct->task.flags = 0; + ct->fd = audiod_get_socket(); /* doesn't return on errors */ sprintf(ct->task.status, "command task"); } @@ -1568,6 +1612,8 @@ int main(int argc, char *argv[]) char *cf; 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; init_sched(); @@ -1596,21 +1642,20 @@ int main(int argc, char *argv[]) clear_slot(i); init_grabbing(); setup_signal_handling(); - if (conf.daemon_given) - daemon_init(); - audiod_get_socket(); /* doesn't return on errors */ - signal_setup_default(sig_task); sig_task->task.event_handler = signal_event_handler; init_status_task(stat_task); init_command_task(cmd_task); - init_audiod_task(at); + init_audiod_task(audiod_task); + + if (conf.daemon_given) + daemon_init(); register_task(&sig_task->task); register_task(&cmd_task->task); register_task(&stat_task->task); - register_task(&at->task); + register_task(audiod_task); s.default_timeout.tv_sec = 0; s.default_timeout.tv_usec = 99 * 1000; ret = sched(&s);