client: Do not leak buffer tree node on exit.
[paraslash.git] / grab_client.c
index 2c95022..9109c2f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2011 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -8,7 +8,6 @@
 
 #include <regex.h>
 #include <sys/types.h>
-#include <dirent.h>
 #include <stdbool.h>
 
 #include "para.h"
@@ -45,6 +44,8 @@ enum grab_flags {
 struct grab_client {
        /* The value of the -p option. */
        char *parent;
+       /* The value of the -n option. */
+       char *name;
        /** The file descriptor to send the grabbed stream to. */
        int fd;
        /** See \ref grab_mode. */
@@ -60,9 +61,9 @@ struct grab_client {
 };
 
 /* 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)
 {
@@ -76,7 +77,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 = write_nonblock(gc->fd, buf, len);
        if (ret < 0)
                goto err;
        if (ret > 0)
@@ -99,11 +100,8 @@ static void gc_pre_select(struct sched *s, struct task *t)
 
        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);
 }
 
@@ -121,6 +119,7 @@ static void gc_post_select(struct sched *s, struct task *t);
 static void gc_activate(struct grab_client *gc)
 {
        struct btr_node *root = audiod_get_btr_root(), *parent;
+       char *name = gc->name? gc->name : "grab";
 
        if (!root)
                return;
@@ -129,13 +128,14 @@ static void gc_activate(struct grab_client *gc)
                return;
        PARA_INFO_LOG("activating fd %d\n", gc->fd);
        list_move(&gc->node, &active_grab_client_list);
-       gc->btrn = btr_new_node("grab", parent, NULL, NULL);
-       if (!gc->task.pre_select) {
-               gc->task.pre_select = gc_pre_select;
-               gc->task.post_select = gc_post_select;
-               sprintf(gc->task.status, "grab");
-               register_task(&gc->task);
-       }
+       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(&gc->task);
 }
 
 /**
@@ -154,7 +154,7 @@ void activate_grab_clients(void)
        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;
@@ -177,10 +177,11 @@ 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;
 }
 
@@ -207,7 +208,8 @@ static void gc_post_select(__a_unused struct sched *s, struct task *t)
                btr_consume(btrn, ret);
        return;
 err:
-       t->error = gc_close(gc, ret)? ret : 0;
+       gc_close(gc, ret);
+       t->error = ret;
 }
 
 static int gc_check_args(int argc, char **argv, struct grab_client *gc)
@@ -247,6 +249,10 @@ static int gc_check_args(int argc, char **argv, struct grab_client *gc)
                        gc->parent = para_strdup(arg + 3);
                        continue;
                }
+               if (!strncmp(arg, "-n=", 3)) {
+                       gc->name = para_strdup(arg + 3);
+                       continue;
+               }
                return -E_GC_SYNTAX;
        }
        if (i != argc)