From d5b4c8e368050cf1b84b03c1379bbbc3c817a713 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 16 Feb 2012 23:29:29 +0000 Subject: Implement the i3bar JSON protocol This hardcodes all the JSON parts. Strings are not properly escaped currently. The best/easiest way to fix this is by actually using libyajl. --- i3status.c | 12 ++++++++++++ include/i3status.h | 2 +- src/auto_detect_format.c | 4 ++-- src/output.c | 4 ++++ src/print_battery_info.c | 6 ++++++ src/print_cpu_temperature.c | 7 +++++++ src/print_cpu_usage.c | 7 +++++++ src/print_ddate.c | 6 ++++++ src/print_disk_info.c | 6 ++++++ src/print_eth_info.c | 9 +++++++++ src/print_ipv6_addr.c | 8 ++++++++ src/print_load.c | 7 +++++++ src/print_run_watch.c | 9 +++++++++ src/print_time.c | 6 ++++++ src/print_volume.c | 4 ++++ src/print_wireless_info.c | 9 +++++++++ 16 files changed, 103 insertions(+), 3 deletions(-) diff --git a/i3status.c b/i3status.c index 9f04850..dd7d1e6 100644 --- a/i3status.c +++ b/i3status.c @@ -331,6 +331,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); @@ -341,6 +343,12 @@ int main(int argc, char *argv[]) { || !valid_color(cfg_getstr(cfg_general, "color_separator"))) die("Bad color format"); + if (output_format == O_I3BAR) { + /* Initialize the i3bar protocol. See i3/docs/i3bar-protocol + * for details. */ + printf("{\"version\":1}\n[\n"); + } + if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) die("Could not create socket\n"); @@ -356,6 +364,8 @@ int main(int argc, char *argv[]) { localtime_r(¤t_time, &tm); current_tm = &tm; } + if (output_format == O_I3BAR) + printf("["); for (j = 0; j < cfg_size(cfg, "order"); j++) { if (j > 0) print_seperator(); @@ -401,6 +411,8 @@ int main(int argc, char *argv[]) { CASE_SEC("cpu_usage") print_cpu_usage(cfg_getstr(sec, "format")); } + if (output_format == O_I3BAR) + printf("],"); printf("\n"); fflush(stdout); diff --git a/include/i3status.h b/include/i3status.h index 24097b0..e40003c 100644 --- a/include/i3status.h +++ b/include/i3status.h @@ -1,7 +1,7 @@ #ifndef _I3STATUS_H #define _I3STATUS_H -enum { O_DZEN2, O_XMOBAR, O_NONE } output_format; +enum { O_DZEN2, O_XMOBAR, O_I3BAR, O_NONE } output_format; #include #include diff --git a/src/auto_detect_format.c b/src/auto_detect_format.c index 299614a..7c4d65d 100644 --- a/src/auto_detect_format.c +++ b/src/auto_detect_format.c @@ -78,7 +78,7 @@ char *auto_detect_format() { * pipe target the parent process of i3status. If we detect that, we set * the format and we are done. */ if (strcasecmp(parentname, "i3bar") == 0) - format = "none"; + format = "i3bar"; else if (strcasecmp(parentname, "dzen2") == 0) format = "dzen2"; else if (strcasecmp(parentname, "xmobar") == 0) @@ -133,7 +133,7 @@ char *auto_detect_format() { /* Check for known destination programs and set format */ char *newfmt = NULL; if (strcasecmp(name, "i3bar") == 0) - newfmt = "none"; + newfmt = "i3bar"; else if (strcasecmp(name, "dzen2") == 0) newfmt = "dzen2"; else if (strcasecmp(name, "xmobar") == 0) diff --git a/src/output.c b/src/output.c index c0c1480..96dd3e4 100644 --- a/src/output.c +++ b/src/output.c @@ -24,6 +24,8 @@ char *color(const char *colorstr) { (void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", cfg_getstr(cfg_general, colorstr)); else if (output_format == O_XMOBAR) (void)snprintf(colorbuf, sizeof(colorbuf), "", cfg_getstr(cfg_general, colorstr)); + else if (output_format == O_I3BAR) + (void)snprintf(colorbuf, sizeof(colorbuf), "\"color\":\"%s\", ", cfg_getstr(cfg_general, colorstr)); return colorbuf; } @@ -43,6 +45,8 @@ void print_seperator() { printf("^fg(%s)^p(5;-2)^ro(2)^p()^fg()^p(5)", cfg_getstr(cfg_general, "color_separator")); else if (output_format == O_XMOBAR) printf(" | ", cfg_getstr(cfg_general, "color_separator")); + else if (output_format == O_I3BAR) + printf(", "); else if (output_format == O_NONE) printf(" | "); } diff --git a/src/print_battery_info.c b/src/print_battery_info.c index 6ee8989..10137c2 100644 --- a/src/print_battery_info.c +++ b/src/print_battery_info.c @@ -36,6 +36,9 @@ void print_battery_info(int number, const char *path, const char *format, bool l memset(remainingbuf, '\0', sizeof(remainingbuf)); memset(emptytimebuf, '\0', sizeof(emptytimebuf)); + if (output_format == O_I3BAR) + printf("{\"name\":\"battery\", \"instance\": \"%s\", \"full_text\":\"", path); + #if defined(LINUX) static char batpath[512]; sprintf(batpath, path, number); @@ -185,4 +188,7 @@ void print_battery_info(int number, const char *path, const char *format, bool l walk += strlen("emptytime"); } } + + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_cpu_temperature.c b/src/print_cpu_temperature.c index 8c343c2..08fac88 100644 --- a/src/print_cpu_temperature.c +++ b/src/print_cpu_temperature.c @@ -31,6 +31,9 @@ void print_cpu_temperature_info(int zone, const char *path, const char *format) path = thermal_zone; } + if (output_format == O_I3BAR) + printf("{\"name\":\"cpu_temperature\", \"instance\": \"%s\", \"full_text\":\"", path); + for (walk = format; *walk != '\0'; walk++) { if (*walk != '%') { putchar(*walk); @@ -58,6 +61,10 @@ void print_cpu_temperature_info(int zone, const char *path, const char *format) walk += strlen("degrees"); } } + + if (output_format == O_I3BAR) + printf("\"}"); + return; error: #endif diff --git a/src/print_cpu_usage.c b/src/print_cpu_usage.c index 1d3bac8..d97a7fa 100644 --- a/src/print_cpu_usage.c +++ b/src/print_cpu_usage.c @@ -26,6 +26,9 @@ void print_cpu_usage(const char *format) { int curr_user = 0, curr_nice = 0, curr_system = 0, curr_idle = 0, curr_total; int diff_idle, diff_total, diff_usage; + if (output_format == O_I3BAR) + printf("{\"name\":\"cpu_usage\", \"full_text\":\""); + #if defined(LINUX) static char statpath[512]; strcpy(statpath, "/proc/stat"); @@ -70,6 +73,10 @@ void print_cpu_usage(const char *format) { walk += strlen("usage"); } } + + if (output_format == O_I3BAR) + printf("\"}"); + return; error: (void)fputs("Cannot read usage\n", stderr); diff --git a/src/print_ddate.c b/src/print_ddate.c index 453e5a2..0401a3f 100644 --- a/src/print_ddate.c +++ b/src/print_ddate.c @@ -4,6 +4,8 @@ #include #include +#include "i3status.h" + /* define fixed output-Strings */ char *season_long[5] = { "Chaos", @@ -200,6 +202,10 @@ void print_ddate(const char *format, struct tm *current_tm) { if (form == NULL) if ((form = malloc(strlen(format) + 1)) == NULL) return; + if (output_format == O_I3BAR) + printf("{\"name\":\"ddate\", \"full_text\":\""); strcpy(form, format); format_output(form, dt); + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_disk_info.c b/src/print_disk_info.c index b2cbd9c..1ac22d0 100644 --- a/src/print_disk_info.c +++ b/src/print_disk_info.c @@ -45,6 +45,9 @@ static void print_bytes_human(uint64_t bytes) { void print_disk_info(const char *path, const char *format) { const char *walk; + if (output_format == O_I3BAR) + printf("{\"name\":\"disk_info\", \"instance\": \"%s\", \"full_text\":\"", path); + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) struct statfs buf; @@ -83,4 +86,7 @@ void print_disk_info(const char *path, const char *format) { walk += strlen("avail"); } } + + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_eth_info.c b/src/print_eth_info.c index 28ba6c1..4fae191 100644 --- a/src/print_eth_info.c +++ b/src/print_eth_info.c @@ -78,6 +78,9 @@ void print_eth_info(const char *interface, const char *format_up, const char *fo const char *walk; const char *ip_address = get_ip_addr(interface); + if (output_format == O_I3BAR) + printf("{\"name\":\"ethernet\", \"instance\": \"%s\", ", interface); + if (ip_address == NULL) { printf("%s", color("color_bad")); printf("%s", format_down); @@ -87,6 +90,9 @@ void print_eth_info(const char *interface, const char *format_up, const char *fo printf("%s", color("color_good")); } + if (output_format == O_I3BAR) + printf("\"full_text\":\""); + for (walk = format_up; *walk != '\0'; walk++) { if (*walk != '%') { putchar(*walk); @@ -103,4 +109,7 @@ void print_eth_info(const char *interface, const char *format_up, const char *fo } (void)printf("%s", endcolor()); + + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_ipv6_addr.c b/src/print_ipv6_addr.c index e96c0d3..3ace6a2 100644 --- a/src/print_ipv6_addr.c +++ b/src/print_ipv6_addr.c @@ -9,6 +9,8 @@ #include #include +#include "i3status.h" + static char *get_sockname(struct addrinfo *addr) { static char buf[INET6_ADDRSTRLEN+1]; struct sockaddr_storage local; @@ -111,6 +113,9 @@ void print_ipv6_info(const char *format_up, const char *format_down) { const char *walk; char *addr_string = get_ipv6_addr(); + if (output_format == O_I3BAR) + printf("{\"name\":\"ipv6\", \"full_text\":\""); + if (addr_string == NULL) { printf("%s", format_down); return; @@ -127,4 +132,7 @@ void print_ipv6_info(const char *format_up, const char *format_down) { walk += strlen("ip"); } } + + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_load.c b/src/print_load.c index d47ecea..8c2343b 100644 --- a/src/print_load.c +++ b/src/print_load.c @@ -6,6 +6,9 @@ void print_load(const char *format) { /* Get load */ + if (output_format == O_I3BAR) + printf("{\"name\":\"load\", \"full_text\":\""); + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(sun) double loadavg[3]; const char *walk; @@ -34,6 +37,10 @@ void print_load(const char *format) { walk += strlen("15min"); } } + + if (output_format == O_I3BAR) + printf("\"}"); + return; error: #endif diff --git a/src/print_run_watch.c b/src/print_run_watch.c index 455130e..c806d8e 100644 --- a/src/print_run_watch.c +++ b/src/print_run_watch.c @@ -6,8 +6,14 @@ void print_run_watch(const char *title, const char *pidfile, const char *format) bool running = process_runs(pidfile); const char *walk; + if (output_format == O_I3BAR) + printf("{\"name\":\"run_watch\", \"instance\": \"%s\", ", pidfile); + printf("%s", (running ? color("color_good") : color("color_bad"))); + if (output_format == O_I3BAR) + printf("\"full_text\":\""); + for (walk = format; *walk != '\0'; walk++) { if (*walk != '%') { putchar(*walk); @@ -24,4 +30,7 @@ void print_run_watch(const char *title, const char *pidfile, const char *format) } printf("%s", endcolor()); + + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_time.c b/src/print_time.c index 9c9df90..3c48d3f 100644 --- a/src/print_time.c +++ b/src/print_time.c @@ -3,12 +3,18 @@ #include #include +#include "i3status.h" + void print_time(const char *format, struct tm *current_tm) { static char part[512]; /* Get date & time */ if (current_tm == NULL) { return; } + if (output_format == O_I3BAR) + printf("{\"name\":\"time\", \"full_text\":\""); (void)strftime(part, sizeof(part), format, current_tm); printf("%s", part); + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_volume.c b/src/print_volume.c index c13cb17..85b6176 100644 --- a/src/print_volume.c +++ b/src/print_volume.c @@ -43,6 +43,8 @@ static void free_hdl(struct mixer_hdl *hdl) { void print_volume(const char *fmt, const char *device, const char *mixer, int mixer_idx) { /* Printing volume only works with ALSA at the moment */ + if (output_format == O_I3BAR) + printf("{\"name\":\"volume\", \"instance\": \"%s.%s.%d\", \"full_text\":\"", device, mixer, mixer_idx); #ifdef LINUX /* Check if we already opened the mixer and get the handle * from cache if so */ @@ -180,4 +182,6 @@ void print_volume(const char *fmt, const char *device, const char *mixer, int mi } close(mixfd); #endif + if (output_format == O_I3BAR) + printf("\"}"); } diff --git a/src/print_wireless_info.c b/src/print_wireless_info.c index 1aca346..530d9cf 100644 --- a/src/print_wireless_info.c +++ b/src/print_wireless_info.c @@ -224,6 +224,9 @@ static int get_wireless_info(const char *interface, wireless_info_t *info) { void print_wireless_info(const char *interface, const char *format_up, const char *format_down) { const char *walk; wireless_info_t info; + if (output_format == O_I3BAR) + printf("{\"name\":\"wireless\", \"instance\": \"%s\", ", interface); + if (get_wireless_info(interface, &info)) { walk = format_up; if (info.flags & WIRELESS_INFO_FLAG_HAS_QUALITY) @@ -234,6 +237,9 @@ void print_wireless_info(const char *interface, const char *format_up, const cha printf("%s", color("color_bad")); } + if (output_format == O_I3BAR) + printf("\"full_text\":\""); + for (; *walk != '\0'; walk++) { if (*walk != '%') { putchar(*walk); @@ -308,4 +314,7 @@ void print_wireless_info(const char *interface, const char *format_up, const cha } (void)printf("%s", endcolor()); + + if (output_format == O_I3BAR) + printf("\"}"); } -- cgit v1.2.3