X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=grab_client.c;h=926f47927c7617f0aa53cae4eeec7f42026ce9f6;hp=466380fd773dfe71bcf52f6c884961cbc0239980;hb=53d5ac455d0616a5ee8867c986631ed34c177a42;hpb=eecc102ad0abeb0335fe994bb72031a15b9090d7 diff --git a/grab_client.c b/grab_client.c index 466380fd..926f4792 100644 --- a/grab_client.c +++ b/grab_client.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2009 Andre Noll + * Copyright (C) 2006 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -8,15 +8,12 @@ #include #include -#include -#include #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" @@ -56,15 +53,15 @@ 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; }; /* Grab clients that are attached to a btr node. */ -INITIALIZED_LIST_HEAD(active_grab_client_list); +static INITIALIZED_LIST_HEAD(active_grab_client_list); /* Grab clients that are not currently attached any btr node. */ -INITIALIZED_LIST_HEAD(inactive_grab_client_list); +static INITIALIZED_LIST_HEAD(inactive_grab_client_list); static int gc_write(struct grab_client *gc, char *buf, size_t len) { @@ -78,7 +75,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, 0); + ret = xwrite(gc->fd, buf, len); if (ret < 0) goto err; if (ret > 0) @@ -94,18 +91,15 @@ err: return -E_GC_WRITE; } -static void gc_pre_select(struct sched *s, struct task *t) +static void gc_pre_select(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) { - s->timeout.tv_sec = 0; - s->timeout.tv_usec = 0; - return; - } + if (ret < 0) + sched_min_delay(s); para_fd_set(gc->fd, &s->wfds, &s->max_fileno); } @@ -113,14 +107,14 @@ static void gc_pre_select(struct sched *s, struct task *t) * We need this forward declaration as post_select() needs * activate_grab_client and vice versa. */ -static void gc_post_select(struct sched *s, struct task *t); +static int gc_post_select(struct sched *s, void *context); /** * Move a grab client to the active list and start it. * * \param gc The grab client to activate. */ -static void gc_activate(struct grab_client *gc) +static void gc_activate(struct grab_client *gc, struct sched *s) { struct btr_node *root = audiod_get_btr_root(), *parent; char *name = gc->name? gc->name : "grab"; @@ -134,18 +128,20 @@ static void gc_activate(struct grab_client *gc) list_move(&gc->node, &active_grab_client_list); gc->btrn = btr_new_node(&(struct btr_node_description) EMBRACE(.name = name, .parent = parent)); - if (!gc->task.pre_select) { - 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'; - register_task(&gc->task); - } + + gc->task = task_register(&(struct task_info) { + .name = name, + .pre_select = gc_pre_select, + .post_select = gc_post_select, + .context = gc, + }, s); } /** * Activate inactive grab clients if possible. * + * \param s Needed to schedule the grab client task. + * * This is called from audiod.c when the current audio file changes. It loops * over all inactive grab clients and checks each grab client's configuration * to determine if the client in question wishes to grab the new stream. If @@ -154,25 +150,23 @@ static void gc_activate(struct grab_client *gc) * This function also garbage collects all grab clients whose tasks have been * unscheduled. */ -void activate_grab_clients(void) +void activate_grab_clients(struct sched *s) { struct grab_client *gc, *tmp; list_for_each_entry_safe(gc, tmp, &inactive_grab_client_list, node) { - if (gc->task.error == -E_TASK_UNREGISTERED) { + if (gc->fd < 0) { list_del(&gc->node); free(gc); continue; } - gc_activate(gc); + gc_activate(gc, 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)) { @@ -182,26 +176,25 @@ static int gc_close(struct grab_client *gc, int err) * post_select(). */ close(gc->fd); + gc->fd = -1; free(gc->parent); free(gc->name); return 1; } - gc_activate(gc); return 0; } -static void gc_post_select(__a_unused struct sched *s, struct task *t) +static int gc_post_select(__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); @@ -211,9 +204,10 @@ 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: - t->error = gc_close(gc, ret)? ret : 0; + gc_close(gc, ret); + return ret; } static int gc_check_args(int argc, char **argv, struct grab_client *gc) @@ -270,6 +264,7 @@ static int gc_check_args(int argc, char **argv, struct grab_client *gc) * \param fd The file descriptor of the client. * \param argc Argument count. * \param argv Argument vector. + * \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 @@ -280,7 +275,7 @@ static int gc_check_args(int argc, char **argv, struct grab_client *gc) * * \return Standard. */ -int grab_client_new(int fd, int argc, char **argv) +int grab_client_new(int fd, int argc, char **argv, struct sched *s) { int ret; struct grab_client *gc = para_calloc(sizeof(struct grab_client)); @@ -288,9 +283,14 @@ int grab_client_new(int fd, int argc, char **argv) ret = gc_check_args(argc, argv, 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); + gc_activate(gc, s); return 1; err_out: free(gc);