X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=grab_client.c;h=8370649301906eaef68a4c30d1b1f3975283dea8;hp=e96fed36bc2146a1eed39a879581d0a5298c5fbc;hb=HEAD;hpb=a547c6b5cf58abbfd8afd46a661cc4a9fe6f3214 diff --git a/grab_client.c b/grab_client.c index e96fed36..1019e579 100644 --- a/grab_client.c +++ b/grab_client.c @@ -1,20 +1,17 @@ -/* - * Copyright (C) 2006-2012 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2006 Andre Noll , see file COPYING. */ /** \file grab_client.c Functions for grabbing the audio stream. */ #include #include +#include + +#include "audiod_cmd.lsg.h" #include "para.h" #include "list.h" #include "sched.h" -#include "ggo.h" #include "buffer_tree.h" -#include "filter.h" #include "grab_client.h" #include "audiod.h" #include "error.h" @@ -54,7 +51,7 @@ struct grab_client { /** The point of the grab client's node in the buffer tree. */ struct btr_node *btrn; /* The task of this grab client. */ - struct task task; + struct task *task; /** Belongs to either the active or the inactive list. */ struct list_head node; }; @@ -76,7 +73,7 @@ static int gc_write(struct grab_client *gc, char *buf, size_t len) if (gc->mode == GM_SLOPPY) return len; } - ret = write_nonblock(gc->fd, buf, len); + ret = xwrite(gc->fd, buf, len); if (ret < 0) goto err; if (ret > 0) @@ -92,23 +89,23 @@ err: return -E_GC_WRITE; } -static void gc_pre_select(struct sched *s, struct task *t) +static void gc_pre_monitor(struct sched *s, void *context) { - struct grab_client *gc = container_of(t, struct grab_client, task); + struct grab_client *gc = context; int ret = btr_node_status(gc->btrn, 0, BTR_NT_LEAF); if (ret == 0) return; if (ret < 0) sched_min_delay(s); - para_fd_set(gc->fd, &s->wfds, &s->max_fileno); + sched_monitor_writefd(gc->fd, s); } /* - * We need this forward declaration as post_select() needs + * We need this forward declaration as gc_post_monitor() needs * activate_grab_client and vice versa. */ -static void gc_post_select(struct sched *s, struct task *t); +static int gc_post_monitor(struct sched *s, void *context); /** * Move a grab client to the active list and start it. @@ -129,12 +126,13 @@ static void gc_activate(struct grab_client *gc, struct sched *s) list_move(&gc->node, &active_grab_client_list); gc->btrn = btr_new_node(&(struct btr_node_description) EMBRACE(.name = name, .parent = parent)); - gc->task.pre_select = gc_pre_select; - gc->task.post_select = gc_post_select; - snprintf(gc->task.status, sizeof(gc->task.status) - 1, "%s", name); - gc->task.status[sizeof(gc->task.status) - 1] = '\0'; - gc->task.error = 0; - register_task(s, &gc->task); + + gc->task = task_register(&(struct task_info) { + .name = name, + .pre_monitor = gc_pre_monitor, + .post_monitor = gc_post_monitor, + .context = gc, + }, s); } /** @@ -166,16 +164,14 @@ void activate_grab_clients(struct sched *s) static int gc_close(struct grab_client *gc, int err) { - btr_remove_node(gc->btrn); - btr_free_node(gc->btrn); - gc->btrn = NULL; + btr_remove_node(&gc->btrn); PARA_INFO_LOG("closing gc: %s\n", para_strerror(-err)); list_move(&gc->node, &inactive_grab_client_list); if (err == -E_GC_WRITE || (gc->flags & GF_ONE_SHOT)) { /* * We must not free the gc structure here as it contains ->task * which is still used because this function is called from - * post_select(). + * post_monitor(). */ close(gc->fd); gc->fd = -1; @@ -186,18 +182,17 @@ static int gc_close(struct grab_client *gc, int err) return 0; } -static void gc_post_select(__a_unused struct sched *s, struct task *t) +static int gc_post_monitor(__a_unused struct sched *s, void *context) { - struct grab_client *gc = container_of(t, struct grab_client, task); + struct grab_client *gc = context; struct btr_node *btrn = gc->btrn; int ret; size_t sz; char *buf; - t->error = 0; ret = btr_node_status(btrn, 0, BTR_NT_LEAF); if (ret == 0) - return; + return 0; if (ret < 0) goto err; sz = btr_next_buffer(btrn, &buf); @@ -207,86 +202,76 @@ static void gc_post_select(__a_unused struct sched *s, struct task *t) goto err; if (ret > 0) btr_consume(btrn, ret); - return; + return 0; err: gc_close(gc, ret); - t->error = ret; + return ret; } -static int gc_check_args(int argc, char **argv, struct grab_client *gc) +static int gc_check_args(struct lls_parse_result *lpr, struct grab_client *gc) { - int i; + const struct lls_opt_result *r; - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (arg[0] != '-') - break; - if (!strcmp(arg, "--")) { - i++; - break; - } - if (!strncmp(arg, "-m", 2)) { - if (*(arg + 3)) - return -E_GC_SYNTAX; - switch(*(arg + 2)) { - case 's': - gc->mode = GM_SLOPPY; - continue; - case 'a': - gc->mode = GM_AGGRESSIVE; - continue; - case 'p': - gc->mode = GM_PEDANTIC; - continue; - default: - return -E_GC_SYNTAX; - } - } - if (!strcmp(arg, "-o")) { - gc->flags |= GF_ONE_SHOT; - continue; - } - if (!strncmp(arg, "-p=", 3)) { - gc->parent = para_strdup(arg + 3); - continue; - } - if (!strncmp(arg, "-n=", 3)) { - gc->name = para_strdup(arg + 3); - continue; - } - return -E_GC_SYNTAX; + r = lls_opt_result(LSG_AUDIOD_CMD_GRAB_OPT_MODE, lpr); + if (lls_opt_given(r) > 0) { + const char *arg = lls_string_val(0, r); + if (strcmp(arg, "s") == 0) + gc->mode = GM_SLOPPY; + else if (strcmp(arg, "a") == 0) + gc->mode = GM_AGGRESSIVE; + else if (strcmp(arg, "p") == 0) + gc->mode = GM_PEDANTIC; + else + return -E_GC_SYNTAX; + } + + r = lls_opt_result(LSG_AUDIOD_CMD_GRAB_OPT_ONE_SHOT, lpr); + if (lls_opt_given(r) > 0) + gc->flags |= GF_ONE_SHOT; + + r = lls_opt_result(LSG_AUDIOD_CMD_GRAB_OPT_PARENT, lpr); + if (lls_opt_given(r) > 0) { + const char *arg = lls_string_val(0, r); + gc->parent = para_strdup(arg); + } + + r = lls_opt_result(LSG_AUDIOD_CMD_GRAB_OPT_NAME, lpr); + if (lls_opt_given(r) > 0) { + const char *arg = lls_string_val(0, r); + gc->name = para_strdup(arg); } - if (i != argc) - return -E_GC_SYNTAX; return 1; } /** - * Check the command line options and allocate a grab_client structure. + * Create and activate a grab client. * * \param fd The file descriptor of the client. - * \param argc Argument count. - * \param argv Argument vector. + * \param lpr The parsed command line of the grab command. * \param s The scheduler to register the grab client task to. * - * If the command line options given by \a argc and \a argv are valid. - * allocate a struct grab_client and initialize it with this valid - * configuration. - * - * If the new grab client can be added to an existing buffer tree, activate it. - * Otherwise, add it to the inactive list for later activation. + * This function semantically parses the arguments given as options to the grab + * command. On success it allocates a struct grab_client, associates it with + * the given file descriptor and activates it. If the new grab client can not + * be attached to an existing buffer tree node it is put into the inactive list + * for later activation. * * \return Standard. */ -int grab_client_new(int fd, int argc, char **argv, struct sched *s) +int grab_client_new(int fd, struct lls_parse_result *lpr, struct sched *s) { int ret; - struct grab_client *gc = para_calloc(sizeof(struct grab_client)); + struct grab_client *gc = zalloc(sizeof(struct grab_client)); - ret = gc_check_args(argc, argv, gc); + ret = gc_check_args(lpr, gc); if (ret < 0) goto err_out; - gc->fd = fd; + ret = dup(fd); + if (ret < 0) { + ret = -ERRNO_TO_PARA_ERROR(errno); + goto err_out; + } + gc->fd = ret; para_list_add(&gc->node, &inactive_grab_client_list); gc_activate(gc, s); return 1;