X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=i3status.c;h=503f76382b9103ecea50ff9663e0bdb80385f6fb;hb=2f20400d7af06d1a283bf727ce7af27f68f255f5;hp=523ba7ebd10d174e87edd6bd9bb3426890184820;hpb=631e460f8afb6b483fa0e84844996cf97953d670;p=i3%2Fi3status diff --git a/i3status.c b/i3status.c index 523ba7e..503f763 100644 --- a/i3status.c +++ b/i3status.c @@ -3,7 +3,7 @@ * * i3status – Generates a status line for dzen2 or xmobar * - * Copyright © 2008-2011 Michael Stapelberg and contributors + * Copyright © 2008-2012 Michael Stapelberg and contributors * Copyright © 2009 Thorsten Toepper * Copyright © 2010 Axel Wagner * Copyright © 2010 Fernando Tarlá Cardoso Lemos @@ -28,14 +28,24 @@ #include #include +#include +#include + #include "i3status.h" #define exit_if_null(pointer, ...) { if (pointer == NULL) die(__VA_ARGS__); } +#define CFG_COLOR_OPTS(good, degraded, bad) \ + CFG_STR("color_good", good, CFGF_NONE), \ + CFG_STR("color_degraded", degraded, CFGF_NONE), \ + CFG_STR("color_bad", bad, CFGF_NONE) + +#define CFG_CUSTOM_COLOR_OPTS CFG_COLOR_OPTS(NULL, NULL, NULL) + /* socket file descriptor for general purposes */ int general_socket; -cfg_t *cfg, *cfg_general; +cfg_t *cfg, *cfg_general, *cfg_section; /* * Exit upon SIGPIPE because when we have nowhere to write to, gathering @@ -110,14 +120,15 @@ static char *resolve_tilde(const char *path) { head = globbuf.gl_pathv[0]; result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1); strncpy(result, head, strlen(head)); - strncat(result, tail, strlen(tail)); + if (tail) + strncat(result, tail, strlen(tail)); } globfree(&globbuf); return result; } -static char *get_config_path() { +static char *get_config_path(void) { char *xdg_config_home, *xdg_config_dirs, *config_path; /* 1: check the traditional path under the home directory */ @@ -164,8 +175,8 @@ static char *get_config_path() { free(buf); die("Unable to find the configuration file (looked at " - "~/.i3status/config, $XDG_CONFIG_HOME/i3status/config, " - "/etc/i3status/config and $XDG_CONFIG_DIRS/i3status/config)"); + "~/.i3status.conf, $XDG_CONFIG_HOME/i3status/config, " + "/etc/i3status.conf and $XDG_CONFIG_DIRS/i3status/config)"); return NULL; } @@ -175,41 +186,47 @@ int main(int argc, char *argv[]) { cfg_opt_t general_opts[] = { CFG_STR("output_format", "auto", CFGF_NONE), CFG_BOOL("colors", 1, CFGF_NONE), - CFG_STR("color_good", "#00FF00", CFGF_NONE), - CFG_STR("color_degraded", "#FFFF00", CFGF_NONE), - CFG_STR("color_bad", "#FF0000", CFGF_NONE), CFG_STR("color_separator", "#333333", CFGF_NONE), CFG_INT("interval", 1, CFGF_NONE), + CFG_COLOR_OPTS("#00FF00", "#FFFF00", "#FF0000"), CFG_END() }; cfg_opt_t run_watch_opts[] = { CFG_STR("pidfile", NULL, CFGF_NONE), CFG_STR("format", "%title: %status", CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; cfg_opt_t wireless_opts[] = { CFG_STR("format_up", "W: (%quality at %essid, %bitrate) %ip", CFGF_NONE), CFG_STR("format_down", "W: down", CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; cfg_opt_t ethernet_opts[] = { CFG_STR("format_up", "E: %ip (%speed)", CFGF_NONE), CFG_STR("format_down", "E: down", CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; cfg_opt_t ipv6_opts[] = { CFG_STR("format_up", "%ip", CFGF_NONE), CFG_STR("format_down", "no IPv6", CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; cfg_opt_t battery_opts[] = { CFG_STR("format", "%status %percentage %remaining", CFGF_NONE), + CFG_STR("path", "/sys/class/power_supply/BAT%d/uevent", CFGF_NONE), + CFG_INT("low_threshold", 30, CFGF_NONE), + CFG_STR("threshold_type", "time", CFGF_NONE), CFG_BOOL("last_full_capacity", false, CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; @@ -236,6 +253,8 @@ int main(int argc, char *argv[]) { cfg_opt_t temp_opts[] = { CFG_STR("format", "%degrees C", CFGF_NONE), CFG_STR("path", NULL, CFGF_NONE), + CFG_INT("max_threshold", 75, CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; @@ -249,6 +268,7 @@ int main(int argc, char *argv[]) { CFG_STR("device", "default", CFGF_NONE), CFG_STR("mixer", "Master", CFGF_NONE), CFG_INT("mixer_idx", 0, CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; @@ -267,6 +287,7 @@ int main(int argc, char *argv[]) { CFG_SEC("ddate", ddate_opts, CFGF_NONE), CFG_SEC("load", load_opts, CFGF_NONE), CFG_SEC("cpu_usage", usage_opts, CFGF_NONE), + CFG_CUSTOM_COLOR_OPTS, CFG_END() }; @@ -291,11 +312,11 @@ int main(int argc, char *argv[]) { if ((char)o == 'c') configfile = optarg; else if ((char)o == 'h') { - printf("i3status " VERSION " © 2008-2011 Michael Stapelberg and contributors\n" + printf("i3status " VERSION " © 2008-2012 Michael Stapelberg and contributors\n" "Syntax: %s [-c ] [-h] [-v]\n", argv[0]); return 0; } else if ((char)o == 'v') { - printf("i3status " VERSION " © 2008-2011 Michael Stapelberg and contributors\n"); + printf("i3status " VERSION " © 2008-2012 Michael Stapelberg and contributors\n"); return 0; } @@ -330,6 +351,8 @@ int main(int argc, char *argv[]) { output_format = O_DZEN2; else if (strcasecmp(output_str, "xmobar") == 0) output_format = O_XMOBAR; + else if (strcasecmp(output_str, "i3bar") == 0) + output_format = O_I3BAR; else if (strcasecmp(output_str, "none") == 0) output_format = O_NONE; else die("Unknown output format: \"%s\"\n", output_str); @@ -340,11 +363,34 @@ int main(int argc, char *argv[]) { || !valid_color(cfg_getstr(cfg_general, "color_separator"))) die("Bad color format"); +#if YAJL_MAJOR >= 2 + yajl_gen json_gen = yajl_gen_alloc(NULL); +#else + yajl_gen json_gen = yajl_gen_alloc(NULL, NULL); +#endif + + if (output_format == O_I3BAR) { + /* Initialize the i3bar protocol. See i3/docs/i3bar-protocol + * for details. */ + printf("{\"version\":1}\n[\n"); + fflush(stdout); + yajl_gen_array_open(json_gen); + yajl_gen_clear(json_gen); + } + if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) die("Could not create socket\n"); int interval = cfg_getint(cfg_general, "interval"); + /* One memory page which each plugin can use to buffer output. + * Even though it’s unclean, we just assume that the user will not + * specify a format string which expands to something longer than 4096 + * bytes — given that the output of i3status is used to display + * information on screen, more than 1024 characters for the full line + * (!), not individual plugins, seem very unlikely. */ + char buffer[4096]; + struct tm tm; while (1) { struct timeval tv; @@ -355,51 +401,102 @@ int main(int argc, char *argv[]) { localtime_r(¤t_time, &tm); current_tm = &tm; } + if (output_format == O_I3BAR) + yajl_gen_array_open(json_gen); for (j = 0; j < cfg_size(cfg, "order"); j++) { if (j > 0) print_seperator(); const char *current = cfg_getnstr(cfg, "order", j); - CASE_SEC("ipv6") - print_ipv6_info(cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); - - CASE_SEC_TITLE("wireless") - print_wireless_info(title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); - - CASE_SEC_TITLE("ethernet") - print_eth_info(title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); - - CASE_SEC_TITLE("battery") - print_battery_info(atoi(title), cfg_getstr(sec, "format"), cfg_getbool(sec, "last_full_capacity")); - - CASE_SEC_TITLE("run_watch") - print_run_watch(title, cfg_getstr(sec, "pidfile"), cfg_getstr(sec, "format")); - - CASE_SEC_TITLE("disk") - print_disk_info(title, cfg_getstr(sec, "format")); - - CASE_SEC("load") - print_load(cfg_getstr(sec, "format")); - - CASE_SEC("time") - print_time(cfg_getstr(sec, "format"), current_tm); - - CASE_SEC("ddate") - print_ddate(cfg_getstr(sec, "format"), current_tm); - - CASE_SEC_TITLE("volume") - print_volume(cfg_getstr(sec, "format"), + CASE_SEC("ipv6") { + SEC_OPEN_MAP("ipv6"); + print_ipv6_info(json_gen, buffer, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); + SEC_CLOSE_MAP; + } + + CASE_SEC_TITLE("wireless") { + SEC_OPEN_MAP("wireless"); + print_wireless_info(json_gen, buffer, title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); + SEC_CLOSE_MAP; + } + + CASE_SEC_TITLE("ethernet") { + SEC_OPEN_MAP("ethernet"); + print_eth_info(json_gen, buffer, title, cfg_getstr(sec, "format_up"), cfg_getstr(sec, "format_down")); + SEC_CLOSE_MAP; + } + + CASE_SEC_TITLE("battery") { + SEC_OPEN_MAP("battery"); + print_battery_info(json_gen, buffer, atoi(title), cfg_getstr(sec, "path"), cfg_getstr(sec, "format"), cfg_getint(sec, "low_threshold"), cfg_getstr(sec, "threshold_type"), cfg_getbool(sec, "last_full_capacity")); + SEC_CLOSE_MAP; + } + + CASE_SEC_TITLE("run_watch") { + SEC_OPEN_MAP("run_watch"); + print_run_watch(json_gen, buffer, title, cfg_getstr(sec, "pidfile"), cfg_getstr(sec, "format")); + SEC_CLOSE_MAP; + } + + CASE_SEC_TITLE("disk") { + SEC_OPEN_MAP("disk_info"); + print_disk_info(json_gen, buffer, title, cfg_getstr(sec, "format")); + SEC_CLOSE_MAP; + } + + CASE_SEC("load") { + SEC_OPEN_MAP("load"); + print_load(json_gen, buffer, cfg_getstr(sec, "format")); + SEC_CLOSE_MAP; + } + + CASE_SEC("time") { + SEC_OPEN_MAP("time"); + print_time(json_gen, buffer, cfg_getstr(sec, "format"), current_tm); + SEC_CLOSE_MAP; + } + + CASE_SEC("ddate") { + SEC_OPEN_MAP("ddate"); + print_ddate(json_gen, buffer, cfg_getstr(sec, "format"), current_tm); + SEC_CLOSE_MAP; + } + + CASE_SEC_TITLE("volume") { + SEC_OPEN_MAP("volume"); + print_volume(json_gen, buffer, cfg_getstr(sec, "format"), cfg_getstr(sec, "device"), cfg_getstr(sec, "mixer"), cfg_getint(sec, "mixer_idx")); - - CASE_SEC_TITLE("cpu_temperature") - print_cpu_temperature_info(atoi(title), cfg_getstr(sec, "path"), cfg_getstr(sec, "format")); - - CASE_SEC("cpu_usage") - print_cpu_usage(cfg_getstr(sec, "format")); + SEC_CLOSE_MAP; + } + + CASE_SEC_TITLE("cpu_temperature") { + SEC_OPEN_MAP("cpu_temperature"); + print_cpu_temperature_info(json_gen, buffer, atoi(title), cfg_getstr(sec, "path"), cfg_getstr(sec, "format"), cfg_getint(sec, "max_threshold")); + SEC_CLOSE_MAP; + } + + CASE_SEC("cpu_usage") { + SEC_OPEN_MAP("cpu_usage"); + print_cpu_usage(json_gen, buffer, cfg_getstr(sec, "format")); + SEC_CLOSE_MAP; + } } + if (output_format == O_I3BAR) { + yajl_gen_array_close(json_gen); + const unsigned char *buf; +#if YAJL_MAJOR >= 2 + size_t len; +#else + unsigned int len; +#endif + yajl_gen_get_buf(json_gen, &buf, &len); + write(STDOUT_FILENO, buf, len); + yajl_gen_clear(json_gen); + } + printf("\n"); fflush(stdout);