X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod_command.c;h=98e83b3cefc1e40a17c7a7e902dcf914dd07a92c;hp=773bba8b07e1e1c06468d79cedb4a7f115aeec42;hb=bced94f9f81fdf355b61738e968aa8b61bfc36e7;hpb=c73d23911d78ed10179c12ef8f79a3fcf3bbcdaf diff --git a/audiod_command.c b/audiod_command.c index 773bba8b..98e83b3c 100644 --- a/audiod_command.c +++ b/audiod_command.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Andre Noll + * Copyright (C) 2005-2009 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -14,6 +14,7 @@ #include "list.h" #include "close_on_fork.h" #include "sched.h" +#include "ggo.h" #include "filter.h" #include "grab_client.cmdline.h" #include "grab_client.h" @@ -26,85 +27,45 @@ #include "fd.h" #include "audiod_command_list.h" +extern char *stat_item_values[NUM_STAT_ITEMS]; + + /** iterate over the array of all audiod commands */ #define FOR_EACH_COMMAND(c) for (c = 0; audiod_cmds[c].name; c++) static int client_write(int fd, const char *buf) { - size_t len = strlen(buf); - return write(fd, buf, len) != len? -E_CLIENT_WRITE: 1; -} + size_t len; -static char *get_time_string(struct timeval *newest_stime) -{ - struct timeval diff, adj_stream_start, tmp; - int total = 0, use_server_time = 1, - length_seconds = stat_task->length_seconds; - - if (!stat_task->playing) { - if (length_seconds) - return NULL; - return make_message("%s:\n", status_item_list[SI_PLAY_TIME]); - } - if (audiod_status == AUDIOD_OFF) - goto out; - if (stat_task->sa_time_diff_sign > 0) - tv_diff(&stat_task->server_stream_start, &stat_task->sa_time_diff, - &adj_stream_start); - else - tv_add(&stat_task->server_stream_start, &stat_task->sa_time_diff, - &adj_stream_start); - tmp = adj_stream_start; - if (newest_stime && audiod_status == AUDIOD_ON) { - tv_diff(newest_stime, &adj_stream_start, &diff); - if (tv2ms(&diff) < 5000) { - tmp = *newest_stime; - use_server_time = 0; - } - } - tv_diff(now, &tmp, &diff); - total = diff.tv_sec + stat_task->offset_seconds; - if (total > length_seconds) - total = length_seconds; - if (total < 0) - total = 0; -out: - return make_message( - "%s: %s%d:%02d [%d:%02d] (%d%%/%d:%02d)\n", - status_item_list[SI_PLAY_TIME], - use_server_time? "~" : "", - total / 60, - total % 60, - (length_seconds - total) / 60, - (length_seconds - total) % 60, - length_seconds? (total * 100 + length_seconds / 2) / - length_seconds : 0, - length_seconds / 60, - length_seconds % 60 - ); + if (!buf) + return 0; + len = strlen(buf); + return write(fd, buf, len) != len? -E_CLIENT_WRITE: 1; } __malloc static char *audiod_status_string(void) { const char *status = (audiod_status == AUDIOD_ON)? "on" : (audiod_status == AUDIOD_OFF)? "off": "sb"; - return make_message("%s: %s\n", status_item_list[SI_AUDIOD_STATUS], status); + return para_strdup(status); } -static struct timeval *wstime(void) +static int get_play_time_slot_num(void) { - int i; - struct timeval *max = NULL; + int i, oldest = -1; + FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; if (!s->wng) continue; - if (max && tv_diff(&s->wstime, max, NULL) <= 0) + if (oldest >= 0 && tv_diff(&s->wstime, &slot[oldest].wstime, + NULL) > 0) continue; - max = &s->wstime; + oldest = i; } - return max; + return oldest; } + __malloc static char *decoder_flags(void) { int i; @@ -115,13 +76,14 @@ __malloc static char *decoder_flags(void) char flag = '0'; if (s->receiver_node) flag += 1; - if (s->wng) + if (s->fc) flag += 2; + if (s->wng) + flag += 4; flags[i] = flag; } flags[MAX_STREAM_SLOTS] = '\0'; - return make_message("%s: %s\n", status_item_list[SI_DECODER_FLAGS], - flags); + return para_strdup(flags); } static int dump_commands(int fd) @@ -209,78 +171,52 @@ int com_kill(int fd, int argc, char **argv) return ret; } -int com_stat(int fd, __a_unused int argc, __a_unused char **argv) +int com_stat(int fd, int argc, char **argv) { - int i, ret; - char *buf = NULL; - long unsigned mask = ~0LU; - - if (argc > 1) { - mask = 0; - for (i = 1; i < argc; i++) { - ret = stat_item_valid(argv[i]); - if (ret < 0) - return ret; - mask |= (1 << ret); + int i, ret, parser_friendly = 0; + uint64_t mask = 0; + const uint64_t one = 1; + struct para_buffer b = {.flags = 0}; + + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (arg[0] != '-') + break; + if (!strcmp(arg, "--")) { + i++; + break; } - } - PARA_INFO_LOG("mask: 0x%lx\n", mask); - if (mask & (1 << SI_PLAY_TIME)) { - struct timeval *t = wstime(); - char *ts = get_time_string(t); - if (ts) { - ret = client_write(fd, ts); - if (ret < 0) - goto out; - free(ts); + if (!strncmp(arg, "-p", 2)) { + parser_friendly = 1; + b.flags = PBF_SIZE_PREFIX; + continue; } } - if (mask & (1 << SI_AUDIOD_UPTIME)) { - char *tmp, *us = uptime_str(); - tmp = make_message("%s: %s\n", - status_item_list[SI_AUDIOD_UPTIME], us); - free(us); - ret = client_write(fd, tmp); - if (ret < 0) - goto out; - free(tmp); - } - if (mask & (1 << SI_AUDIOD_STATUS)) { - char *s = audiod_status_string(); - ret = client_write(fd, s); + if (i >= argc) + mask--; /* set all bits */ + for (; i < argc; i++) { + ret = stat_item_valid(argv[i]); if (ret < 0) - goto out; - free(s); - } - if (mask & (1 << SI_DECODER_FLAGS)) { - char *df = decoder_flags(); - ret = client_write(fd, df); - if (ret < 0) - goto out; - free(df); + return ret; + mask |= (one << ret); } + PARA_INFO_LOG("mask: 0x%llx\n", (long long unsigned)mask); FOR_EACH_STATUS_ITEM(i) { - char *tmp, *v; - if (!((1 << i) & mask)) + char *item = stat_item_values[i]; + if (!((one << i) & mask)) continue; - v = stat_task->stat_item_values[i]; - tmp = make_message("%s%s%s", buf? buf: "", - v? v : "", v? "\n" : ""); - free(buf); - buf = tmp; + WRITE_STATUS_ITEM(&b, i, "%s\n", item? item : ""); } - ret = client_write(fd, buf); -out: - if (ret > 0) - ret = stat_client_add(fd, mask); - free(buf); + ret = client_write(fd, b.buf); + if (ret >= 0) + ret = stat_client_add(fd, mask, parser_friendly); + free(b.buf); return ret; } static struct filter_node *find_filter_node(int slot_num, int format, int filternum) { - struct filter_node *fn; - int i, j; + int i; FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; @@ -290,14 +226,10 @@ static struct filter_node *find_filter_node(int slot_num, int format, int filter continue; if (format >= 0 && s->format != format) continue; - if (num_filters(i) < filternum) + if (num_filters(i) <= filternum) continue; /* success */ - j = 1; - list_for_each_entry(fn, &s->fc->filters, node) - if (filternum <= 0 || j++ == filternum) - break; - return fn; + return s->fc->filter_nodes + filternum; } return NULL; } @@ -429,7 +361,6 @@ int handle_connect(int accept_fd) ret = check_perms(uid); if (ret < 0) goto out; - ret = -E_INVALID_AUDIOD_CMD; cmd = para_strdup(buf); p = strchr(cmd, '\n'); if (!p) @@ -469,70 +400,65 @@ out: return ret; } /** - * send the current audiod status to all connected stat clients + * Send the current audiod status to all connected stat clients. */ void audiod_status_dump(void) { - struct timeval *t = wstime(); - char *old, *new, *tmp; + int slot_num = get_play_time_slot_num(); + char *old, *new; - old = stat_task->stat_item_values[SI_PLAY_TIME]; - new = get_time_string(t); + old = stat_item_values[SI_PLAY_TIME]; + new = get_time_string(slot_num); if (new) { if (!old || strcmp(old, new)) { free(old); - stat_client_write(new, SI_PLAY_TIME); - stat_task->stat_item_values[SI_PLAY_TIME] = new; + stat_item_values[SI_PLAY_TIME] = new; + stat_client_write_item(SI_PLAY_TIME); } else free(new); } new = uptime_str(); - old = stat_task->stat_item_values[SI_AUDIOD_UPTIME]; + old = stat_item_values[SI_AUDIOD_UPTIME]; if (!old || strcmp(old, new)) { free(old); - tmp = make_message("%s: %s\n", - status_item_list[SI_AUDIOD_UPTIME], new); - stat_client_write(tmp, SI_AUDIOD_UPTIME); - free(tmp); - stat_task->stat_item_values[SI_AUDIOD_UPTIME] = new; + stat_item_values[SI_AUDIOD_UPTIME] = new; + stat_client_write_item(SI_AUDIOD_UPTIME); } else free(new); - old = stat_task->stat_item_values[SI_AUDIOD_STATUS]; + old = stat_item_values[SI_AUDIOD_STATUS]; new = audiod_status_string(); if (!old || strcmp(old, new)) { free(old); - stat_client_write(new, SI_AUDIOD_STATUS); - stat_task->stat_item_values[SI_AUDIOD_STATUS] = new; + stat_item_values[SI_AUDIOD_STATUS] = new; + stat_client_write_item(SI_AUDIOD_STATUS); } else free(new); - old = stat_task->stat_item_values[SI_DECODER_FLAGS]; + old = stat_item_values[SI_DECODER_FLAGS]; new = decoder_flags(); if (!old || strcmp(old, new)) { free(old); - stat_client_write(new, SI_DECODER_FLAGS); - stat_task->stat_item_values[SI_DECODER_FLAGS] = new; + stat_item_values[SI_DECODER_FLAGS] = new; + stat_client_write_item(SI_DECODER_FLAGS); } else free(new); } /** - * send empty status list + * Flush and send all status items. * * Send to each connected client the full status item list * with empty values. */ -void dump_empty_status(void) +void clear_and_dump_items(void) { int i; FOR_EACH_STATUS_ITEM(i) { - char *tmp = make_message("%s:\n", status_item_list[i]); - stat_client_write(tmp, i); - free(tmp); - free(stat_task->stat_item_values[i]); - stat_task->stat_item_values[i] = NULL; + free(stat_item_values[i]); + stat_item_values[i] = NULL; + stat_client_write_item(i); } }