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.
This commit is contained in:
Michael Stapelberg 2012-02-16 23:29:29 +00:00
parent 7149f6f78e
commit d5b4c8e368
16 changed files with 103 additions and 3 deletions

View File

@ -331,6 +331,8 @@ int main(int argc, char *argv[]) {
output_format = O_DZEN2; output_format = O_DZEN2;
else if (strcasecmp(output_str, "xmobar") == 0) else if (strcasecmp(output_str, "xmobar") == 0)
output_format = O_XMOBAR; output_format = O_XMOBAR;
else if (strcasecmp(output_str, "i3bar") == 0)
output_format = O_I3BAR;
else if (strcasecmp(output_str, "none") == 0) else if (strcasecmp(output_str, "none") == 0)
output_format = O_NONE; output_format = O_NONE;
else die("Unknown output format: \"%s\"\n", output_str); 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"))) || !valid_color(cfg_getstr(cfg_general, "color_separator")))
die("Bad color format"); 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) if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
die("Could not create socket\n"); die("Could not create socket\n");
@ -356,6 +364,8 @@ int main(int argc, char *argv[]) {
localtime_r(&current_time, &tm); localtime_r(&current_time, &tm);
current_tm = &tm; current_tm = &tm;
} }
if (output_format == O_I3BAR)
printf("[");
for (j = 0; j < cfg_size(cfg, "order"); j++) { for (j = 0; j < cfg_size(cfg, "order"); j++) {
if (j > 0) if (j > 0)
print_seperator(); print_seperator();
@ -401,6 +411,8 @@ int main(int argc, char *argv[]) {
CASE_SEC("cpu_usage") CASE_SEC("cpu_usage")
print_cpu_usage(cfg_getstr(sec, "format")); print_cpu_usage(cfg_getstr(sec, "format"));
} }
if (output_format == O_I3BAR)
printf("],");
printf("\n"); printf("\n");
fflush(stdout); fflush(stdout);

View File

@ -1,7 +1,7 @@
#ifndef _I3STATUS_H #ifndef _I3STATUS_H
#define _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 <stdbool.h> #include <stdbool.h>
#include <confuse.h> #include <confuse.h>

View File

@ -78,7 +78,7 @@ char *auto_detect_format() {
* pipe target the parent process of i3status. If we detect that, we set * pipe target the parent process of i3status. If we detect that, we set
* the format and we are done. */ * the format and we are done. */
if (strcasecmp(parentname, "i3bar") == 0) if (strcasecmp(parentname, "i3bar") == 0)
format = "none"; format = "i3bar";
else if (strcasecmp(parentname, "dzen2") == 0) else if (strcasecmp(parentname, "dzen2") == 0)
format = "dzen2"; format = "dzen2";
else if (strcasecmp(parentname, "xmobar") == 0) else if (strcasecmp(parentname, "xmobar") == 0)
@ -133,7 +133,7 @@ char *auto_detect_format() {
/* Check for known destination programs and set format */ /* Check for known destination programs and set format */
char *newfmt = NULL; char *newfmt = NULL;
if (strcasecmp(name, "i3bar") == 0) if (strcasecmp(name, "i3bar") == 0)
newfmt = "none"; newfmt = "i3bar";
else if (strcasecmp(name, "dzen2") == 0) else if (strcasecmp(name, "dzen2") == 0)
newfmt = "dzen2"; newfmt = "dzen2";
else if (strcasecmp(name, "xmobar") == 0) else if (strcasecmp(name, "xmobar") == 0)

View File

@ -24,6 +24,8 @@ char *color(const char *colorstr) {
(void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", cfg_getstr(cfg_general, colorstr)); (void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", cfg_getstr(cfg_general, colorstr));
else if (output_format == O_XMOBAR) else if (output_format == O_XMOBAR)
(void)snprintf(colorbuf, sizeof(colorbuf), "<fc=%s>", cfg_getstr(cfg_general, colorstr)); (void)snprintf(colorbuf, sizeof(colorbuf), "<fc=%s>", 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; 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")); printf("^fg(%s)^p(5;-2)^ro(2)^p()^fg()^p(5)", cfg_getstr(cfg_general, "color_separator"));
else if (output_format == O_XMOBAR) else if (output_format == O_XMOBAR)
printf("<fc=%s> | </fc>", cfg_getstr(cfg_general, "color_separator")); printf("<fc=%s> | </fc>", cfg_getstr(cfg_general, "color_separator"));
else if (output_format == O_I3BAR)
printf(", ");
else if (output_format == O_NONE) else if (output_format == O_NONE)
printf(" | "); printf(" | ");
} }

View File

@ -36,6 +36,9 @@ void print_battery_info(int number, const char *path, const char *format, bool l
memset(remainingbuf, '\0', sizeof(remainingbuf)); memset(remainingbuf, '\0', sizeof(remainingbuf));
memset(emptytimebuf, '\0', sizeof(emptytimebuf)); memset(emptytimebuf, '\0', sizeof(emptytimebuf));
if (output_format == O_I3BAR)
printf("{\"name\":\"battery\", \"instance\": \"%s\", \"full_text\":\"", path);
#if defined(LINUX) #if defined(LINUX)
static char batpath[512]; static char batpath[512];
sprintf(batpath, path, number); 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"); walk += strlen("emptytime");
} }
} }
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -31,6 +31,9 @@ void print_cpu_temperature_info(int zone, const char *path, const char *format)
path = thermal_zone; path = thermal_zone;
} }
if (output_format == O_I3BAR)
printf("{\"name\":\"cpu_temperature\", \"instance\": \"%s\", \"full_text\":\"", path);
for (walk = format; *walk != '\0'; walk++) { for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') { if (*walk != '%') {
putchar(*walk); putchar(*walk);
@ -58,6 +61,10 @@ void print_cpu_temperature_info(int zone, const char *path, const char *format)
walk += strlen("degrees"); walk += strlen("degrees");
} }
} }
if (output_format == O_I3BAR)
printf("\"}");
return; return;
error: error:
#endif #endif

View File

@ -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 curr_user = 0, curr_nice = 0, curr_system = 0, curr_idle = 0, curr_total;
int diff_idle, diff_total, diff_usage; int diff_idle, diff_total, diff_usage;
if (output_format == O_I3BAR)
printf("{\"name\":\"cpu_usage\", \"full_text\":\"");
#if defined(LINUX) #if defined(LINUX)
static char statpath[512]; static char statpath[512];
strcpy(statpath, "/proc/stat"); strcpy(statpath, "/proc/stat");
@ -70,6 +73,10 @@ void print_cpu_usage(const char *format) {
walk += strlen("usage"); walk += strlen("usage");
} }
} }
if (output_format == O_I3BAR)
printf("\"}");
return; return;
error: error:
(void)fputs("Cannot read usage\n", stderr); (void)fputs("Cannot read usage\n", stderr);

View File

@ -4,6 +4,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "i3status.h"
/* define fixed output-Strings */ /* define fixed output-Strings */
char *season_long[5] = { char *season_long[5] = {
"Chaos", "Chaos",
@ -200,6 +202,10 @@ void print_ddate(const char *format, struct tm *current_tm) {
if (form == NULL) if (form == NULL)
if ((form = malloc(strlen(format) + 1)) == NULL) if ((form = malloc(strlen(format) + 1)) == NULL)
return; return;
if (output_format == O_I3BAR)
printf("{\"name\":\"ddate\", \"full_text\":\"");
strcpy(form, format); strcpy(form, format);
format_output(form, dt); format_output(form, dt);
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -45,6 +45,9 @@ static void print_bytes_human(uint64_t bytes) {
void print_disk_info(const char *path, const char *format) { void print_disk_info(const char *path, const char *format) {
const char *walk; const char *walk;
if (output_format == O_I3BAR)
printf("{\"name\":\"disk_info\", \"instance\": \"%s\", \"full_text\":\"", path);
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
struct statfs buf; struct statfs buf;
@ -83,4 +86,7 @@ void print_disk_info(const char *path, const char *format) {
walk += strlen("avail"); walk += strlen("avail");
} }
} }
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -78,6 +78,9 @@ void print_eth_info(const char *interface, const char *format_up, const char *fo
const char *walk; const char *walk;
const char *ip_address = get_ip_addr(interface); const char *ip_address = get_ip_addr(interface);
if (output_format == O_I3BAR)
printf("{\"name\":\"ethernet\", \"instance\": \"%s\", ", interface);
if (ip_address == NULL) { if (ip_address == NULL) {
printf("%s", color("color_bad")); printf("%s", color("color_bad"));
printf("%s", format_down); 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")); printf("%s", color("color_good"));
} }
if (output_format == O_I3BAR)
printf("\"full_text\":\"");
for (walk = format_up; *walk != '\0'; walk++) { for (walk = format_up; *walk != '\0'; walk++) {
if (*walk != '%') { if (*walk != '%') {
putchar(*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()); (void)printf("%s", endcolor());
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -9,6 +9,8 @@
#include <string.h> #include <string.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "i3status.h"
static char *get_sockname(struct addrinfo *addr) { static char *get_sockname(struct addrinfo *addr) {
static char buf[INET6_ADDRSTRLEN+1]; static char buf[INET6_ADDRSTRLEN+1];
struct sockaddr_storage local; struct sockaddr_storage local;
@ -111,6 +113,9 @@ void print_ipv6_info(const char *format_up, const char *format_down) {
const char *walk; const char *walk;
char *addr_string = get_ipv6_addr(); char *addr_string = get_ipv6_addr();
if (output_format == O_I3BAR)
printf("{\"name\":\"ipv6\", \"full_text\":\"");
if (addr_string == NULL) { if (addr_string == NULL) {
printf("%s", format_down); printf("%s", format_down);
return; return;
@ -127,4 +132,7 @@ void print_ipv6_info(const char *format_up, const char *format_down) {
walk += strlen("ip"); walk += strlen("ip");
} }
} }
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -6,6 +6,9 @@
void print_load(const char *format) { void print_load(const char *format) {
/* Get load */ /* 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) #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(sun)
double loadavg[3]; double loadavg[3];
const char *walk; const char *walk;
@ -34,6 +37,10 @@ void print_load(const char *format) {
walk += strlen("15min"); walk += strlen("15min");
} }
} }
if (output_format == O_I3BAR)
printf("\"}");
return; return;
error: error:
#endif #endif

View File

@ -6,8 +6,14 @@ void print_run_watch(const char *title, const char *pidfile, const char *format)
bool running = process_runs(pidfile); bool running = process_runs(pidfile);
const char *walk; const char *walk;
if (output_format == O_I3BAR)
printf("{\"name\":\"run_watch\", \"instance\": \"%s\", ", pidfile);
printf("%s", (running ? color("color_good") : color("color_bad"))); printf("%s", (running ? color("color_good") : color("color_bad")));
if (output_format == O_I3BAR)
printf("\"full_text\":\"");
for (walk = format; *walk != '\0'; walk++) { for (walk = format; *walk != '\0'; walk++) {
if (*walk != '%') { if (*walk != '%') {
putchar(*walk); putchar(*walk);
@ -24,4 +30,7 @@ void print_run_watch(const char *title, const char *pidfile, const char *format)
} }
printf("%s", endcolor()); printf("%s", endcolor());
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -3,12 +3,18 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "i3status.h"
void print_time(const char *format, struct tm *current_tm) { void print_time(const char *format, struct tm *current_tm) {
static char part[512]; static char part[512];
/* Get date & time */ /* Get date & time */
if (current_tm == NULL) { if (current_tm == NULL) {
return; return;
} }
if (output_format == O_I3BAR)
printf("{\"name\":\"time\", \"full_text\":\"");
(void)strftime(part, sizeof(part), format, current_tm); (void)strftime(part, sizeof(part), format, current_tm);
printf("%s", part); printf("%s", part);
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -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) { void print_volume(const char *fmt, const char *device, const char *mixer, int mixer_idx) {
/* Printing volume only works with ALSA at the moment */ /* 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 #ifdef LINUX
/* Check if we already opened the mixer and get the handle /* Check if we already opened the mixer and get the handle
* from cache if so */ * from cache if so */
@ -180,4 +182,6 @@ void print_volume(const char *fmt, const char *device, const char *mixer, int mi
} }
close(mixfd); close(mixfd);
#endif #endif
if (output_format == O_I3BAR)
printf("\"}");
} }

View File

@ -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) { void print_wireless_info(const char *interface, const char *format_up, const char *format_down) {
const char *walk; const char *walk;
wireless_info_t info; wireless_info_t info;
if (output_format == O_I3BAR)
printf("{\"name\":\"wireless\", \"instance\": \"%s\", ", interface);
if (get_wireless_info(interface, &info)) { if (get_wireless_info(interface, &info)) {
walk = format_up; walk = format_up;
if (info.flags & WIRELESS_INFO_FLAG_HAS_QUALITY) 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")); printf("%s", color("color_bad"));
} }
if (output_format == O_I3BAR)
printf("\"full_text\":\"");
for (; *walk != '\0'; walk++) { for (; *walk != '\0'; walk++) {
if (*walk != '%') { if (*walk != '%') {
putchar(*walk); putchar(*walk);
@ -308,4 +314,7 @@ void print_wireless_info(const char *interface, const char *format_up, const cha
} }
(void)printf("%s", endcolor()); (void)printf("%s", endcolor());
if (output_format == O_I3BAR)
printf("\"}");
} }