From 513a3be6c609dd812e2b7755bab533d28676bd9c Mon Sep 17 00:00:00 2001 From: Andre Date: Mon, 27 Mar 2006 05:36:52 +0200 Subject: [PATCH] audiod: boost the stat command It now takes any number of arguments, including zero which selects the old behaviour (dump _all_ status items to stdout). If called with arguments, each arg must be a valid status item and only these are written to sdout. --- audiod.c | 157 +++++++++++++++++++++++++++++++++++++++++-------------- para.h | 5 +- stat.c | 48 ++++++++++++----- 3 files changed, 154 insertions(+), 56 deletions(-) diff --git a/audiod.c b/audiod.c index c9a0ff7f..741bd68b 100644 --- a/audiod.c +++ b/audiod.c @@ -208,11 +208,10 @@ GRAB_HELP_TXT .name = "stat", .handler = com_stat, .description = "print status information", -.synopsis = "stat", +.synopsis = "stat [item1 ...]", .help = -"Add para_audiod status information to para_server's status information\n" -"and dump everything to stdout.\n" +"Dump given status items (all if none given) to stdout.\n" }, { @@ -302,7 +301,7 @@ static char *get_time_string(struct timeval *newest_stime) if (!playing) { if (length_seconds) return NULL; - return make_message("%s:", status_item_list[SI_PLAY_TIME]); + return make_message("%s:\n", status_item_list[SI_PLAY_TIME]); } if (audiod_status == AUDIOD_OFF) goto out; @@ -329,7 +328,7 @@ static char *get_time_string(struct timeval *newest_stime) total = 0; out: return make_message( - "%s:%s%d:%02d [%d:%02d] (%d%%/%d:%02d)", + "%s:%s%d:%02d [%d:%02d] (%d%%/%d:%02d)\n", status_item_list[SI_PLAY_TIME], use_server_time? "~" : "", total / 60, @@ -343,12 +342,31 @@ out: ); } -static char *audiod_status_string(void) +__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); +} + +static struct timeval *wstime(void) { int i; - struct timeval *newest_stime = NULL; - char *ret, *time_string, *uptime_string, *decoder_flags = - para_malloc((MAX_STREAM_SLOTS + 1) * sizeof(char)); + struct timeval *max = NULL; + FOR_EACH_SLOT(i) { + struct slot_info *s = &slot[i]; + if (s->wpid <= 0) + continue; + if (max && tv_diff(&s->wstime, max, NULL) <= 0) + continue; + max = &s->wstime; + } + return max; +} +__malloc static char *decoder_flags(void) +{ + int i; + char decoder_flags[MAX_STREAM_SLOTS + 1]; FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; @@ -360,26 +378,10 @@ static char *audiod_status_string(void) if (flag != '0') flag += s->format * 4; decoder_flags[i] = flag; - if (s->wpid <= 0) - continue; - if (newest_stime && tv_diff(&s->wstime, newest_stime, NULL) <= 0) - continue; - newest_stime = &s->wstime; } decoder_flags[MAX_STREAM_SLOTS] = '\0'; - time_string = get_time_string(newest_stime); - uptime_string = uptime_str(); - ret = make_message("%s:%s\n%s:%s\n%s:%s", - status_item_list[SI_AUDIOD_UPTIME], uptime_string, - status_item_list[SI_DECODER_FLAGS], decoder_flags, - status_item_list[SI_AUDIOD_STATUS], audiod_status == AUDIOD_ON? - "on" : (audiod_status == AUDIOD_OFF? "off": "sb")); - if (time_string) - ret = make_message("%s\n%s", ret, time_string); - free(uptime_string); - free(decoder_flags); - free(time_string); - return ret; + return make_message("%s:%s\n", status_item_list[SI_DECODER_FLAGS], + decoder_flags); } static char *configfile_exists(void) @@ -407,13 +409,34 @@ static void setup_signal_handling(void) static void audiod_status_dump(void) { - static char *prev_status; - char *tmp = audiod_status_string(); - - if (!prev_status || strcmp(tmp, prev_status)) - stat_client_write(tmp); - free(prev_status); - prev_status = tmp; + static char *p_ts, *p_us, *p_as, *p_df; + struct timeval *t = wstime(); + char *us, *tmp = get_time_string(t); + + if (tmp && (!p_ts || strcmp(tmp, p_ts))) + stat_client_write(tmp, SI_PLAY_TIME); + free(p_ts); + p_ts = tmp; + + us = uptime_str(); + tmp = make_message("%s:%s\n", status_item_list[SI_AUDIOD_UPTIME], us); + free(us); + if (!p_us || strcmp(p_us, tmp)) + stat_client_write(tmp, SI_AUDIOD_UPTIME); + free(p_us); + p_us = tmp; + + tmp = audiod_status_string(); + if (!p_as || strcmp(p_as, tmp)) + stat_client_write(tmp, SI_AUDIOD_STATUS); + free(p_as); + p_as = tmp; + + tmp = decoder_flags(); + if (!p_df || strcmp(p_df, tmp)) + stat_client_write(tmp, SI_DECODER_FLAGS); + free(p_df); + p_df = tmp; } static void clear_slot(int slot_num) @@ -566,7 +589,7 @@ static void close_stat_pipe(void) playing = 0; stat_item_values[SI_STATUS_BAR] = make_message("%s:no connection to para_server\n", status_item_list[SI_STATUS_BAR]); - stat_client_write(stat_item_values[SI_STATUS_BAR]); + stat_client_write(stat_item_values[SI_STATUS_BAR], SI_STATUS_BAR); } static void __noreturn clean_exit(int status, const char *msg) @@ -793,6 +816,7 @@ static void check_stat_line(char *line) int itemnum; size_t ilen = 0; struct timeval tv; + char *tmp; if (!line) return; @@ -801,7 +825,9 @@ static void check_stat_line(char *line) PARA_WARNING_LOG("invalid status line: %s\n", line); return; } - stat_client_write(line); + tmp = make_message("%s\n", line); + stat_client_write(tmp, itemnum); + free(tmp); free(stat_item_values[itemnum]); stat_item_values[itemnum] = para_strdup(line); ilen = strlen(status_item_list[itemnum]); @@ -1227,17 +1253,68 @@ out: static int com_stat(int fd, __unused int argc, __unused char **argv) { int i, ret; - char *buf = make_message("%s\n", audiod_status_string()); + 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); + } + } + 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 (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 (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); + } for (i = 0; i < NUM_STAT_ITEMS; i++) { - char *tmp, *v = stat_item_values[i]; - tmp = make_message("%s%s%s", buf, v? v : "", v? "\n" : ""); + char *tmp, *v; + if (!((1 << i) & mask)) + continue; + v = stat_item_values[i]; + tmp = make_message("%s%s%s", buf? buf: "", + v? v : "", v? "\n" : ""); free(buf); buf = tmp; } ret = client_write(fd, buf); +out: if (ret > 0) - ret = stat_client_add(fd); + ret = stat_client_add(fd, mask); free(buf); return ret; } diff --git a/para.h b/para.h index 9c0618f7..87c52d03 100644 --- a/para.h +++ b/para.h @@ -158,9 +158,10 @@ enum { SI_AUDIOD_UPTIME, SI_SELECTOR, NUM_STAT_ITEMS }; +int stat_item_valid(const char *item); int stat_line_valid(const char *); -void stat_client_write(char *msg); -int stat_client_add(int); +void stat_client_write(char *msg, int itemnum); +int stat_client_add(int fd, long unsigned mask); void dump_empty_status(void); unsigned for_each_line(char *, int, void (*)(char *)); diff --git a/stat.c b/stat.c index 536807dc..9b73fcd9 100644 --- a/stat.c +++ b/stat.c @@ -43,6 +43,7 @@ struct stat_client { * the stat client's file descriptor */ int fd; +long unsigned item_mask; /** * * its entry in the list of stat clients @@ -110,7 +111,7 @@ static void dump_stat_client_list(void) * \return Positive value on success, or -E_TOO_MANY_CLIENTS if * the number of connected clients exceeds #MAX_STAT_CLIENTS */ -int stat_client_add(int fd) +int stat_client_add(int fd, long unsigned mask) { struct stat_client *new_client; @@ -126,6 +127,7 @@ int stat_client_add(int fd) PARA_INFO_LOG("adding client on fd %d\n", fd); new_client = para_malloc(sizeof(struct stat_client)); new_client->fd = fd; + new_client->item_mask = mask; add_close_on_fork_list(fd); list_add(&new_client->node, &client_list); dump_stat_client_list(); @@ -137,20 +139,23 @@ int stat_client_add(int fd) * * \param msg a \p NULL terminated buffer */ -void stat_client_write(char *msg) +void stat_client_write(char *msg, int itemnum) { struct stat_client *sc, *tmp; - char *buf; +// char *buf; ssize_t len; struct timeval tv = {0 , 0}; if (!initialized) return; - buf = make_message("%s\n", msg); - len = strlen(buf); +// buf = make_message("%s\n", msg); + len = strlen(msg); list_for_each_entry_safe(sc, tmp, &client_list, node) { int fd = sc->fd, ret; fd_set wfds; + + if (!((1 << itemnum) & sc->item_mask)) + continue; FD_ZERO(&wfds); FD_SET(fd, &wfds); // PARA_DEBUG_LOG("%s: p=%lx\n", __func__, (long)p); @@ -158,7 +163,7 @@ void stat_client_write(char *msg) ret = select(fd + 1, NULL, &wfds, NULL, &tv); while (ret < 0 && errno == EINTR); if (ret) { - ret = write(fd, buf, len); + ret = write(fd, msg, len); PARA_DEBUG_LOG("dumped %s to fd %d, ret = %d\n", msg, fd, ret); if (ret == len ) continue; @@ -172,7 +177,7 @@ void stat_client_write(char *msg) free(sc); dump_stat_client_list(); } - free(buf); +// free(buf); PARA_DEBUG_LOG("%d client(s)\n", num_clients); } @@ -185,18 +190,33 @@ void stat_client_write(char *msg) void dump_empty_status(void) { int i; - char *empty_items = NULL; if (!initialized) return; FOR_EACH_STAT_ITEM(i) { - char *tmp = make_message("%s%s:\n", empty_items? empty_items : "", - status_item_list[i]); - free(empty_items); - empty_items = tmp; + char *tmp = make_message("%s:\n", status_item_list[i]); + stat_client_write(tmp, i); + free(tmp); } - stat_client_write(empty_items); - free(empty_items); +} + +/** + * check if string is a known status item. + * + * \param item buffer containing the text to check + * + * \return If \a item is a valid status item, the number of that status item is + * returned. Otherwise, this function returns \p -E_UNKNOWN_STAT_ITEM. + */ +int stat_item_valid(const char *item) +{ + int i; + if (!item || !*item) + return -E_UNKNOWN_STAT_ITEM; + FOR_EACH_STAT_ITEM(i) + if (!strcmp(status_item_list[i], item)) + return i; + return -E_UNKNOWN_STAT_ITEM; } /** -- 2.39.2