1 #ifndef _I3STATUS_H 2 #define _I3STATUS_H 3 4 typedef enum { 5 O_DZEN2, 6 O_XMOBAR, 7 O_I3BAR, 8 O_LEMONBAR, 9 O_TERM, 10 O_NONE 11 } output_format_t; 12 extern output_format_t output_format; 13 14 typedef enum { 15 M_PANGO, 16 M_NONE 17 } markup_format_t; 18 extern markup_format_t markup_format; 19 20 extern char *pct_mark; 21 22 #include <stdbool.h> 23 #include <confuse.h> 24 #include <time.h> 25 #include <yajl/yajl_gen.h> 26 #include <yajl/yajl_version.h> 27 #include <unistd.h> 28 #include <string.h> 29 #include <pthread.h> 30 #include <stdint.h> 31 32 #define BEGINS_WITH(haystack, needle) (strncmp(haystack, needle, strlen(needle)) == 0) 33 #define max(a, b) ((a) > (b) ? (a) : (b)) 34 35 #define DEFAULT_SINK_INDEX UINT32_MAX 36 #define COMPOSE_VOLUME_MUTE(vol, mute) ((vol) | ((mute) ? (1 << 30) : 0)) 37 #define DECOMPOSE_VOLUME(cvol) ((cvol) & ~(1 << 30)) 38 #define DECOMPOSE_MUTED(cvol) (((cvol) & (1 << 30)) != 0) 39 #define MAX_SINK_DESCRIPTION_LEN (128) /* arbitrary */ 40 41 #if defined(__linux__) 42 43 #define THERMAL_ZONE "/sys/class/thermal/thermal_zone%d/temp" 44 45 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 46 47 /* this needs the coretemp module to be loaded */ 48 #if defined(__DragonFly__) 49 #define THERMAL_ZONE "hw.sensors.cpu%d.temp0" 50 #else 51 #define THERMAL_ZONE "dev.cpu.%d.temperature" 52 #endif 53 #define BATT_LIFE "hw.acpi.battery.life" 54 #define BATT_TIME "hw.acpi.battery.time" 55 #define BATT_STATE "hw.acpi.battery.state" 56 57 #elif defined(__OpenBSD__) || defined(__NetBSD__) 58 /* Default to acpitz(4) if no path is set. */ 59 #define THERMAL_ZONE "acpitz%d" 60 #endif 61 62 #if defined(__FreeBSD_kernel__) && defined(__GLIBC__) 63 64 #include <sys/stat.h> 65 #include <sys/param.h> 66 67 #endif 68 69 /* Allows for the definition of a variable without opening a new scope, thus 70 * suited for usage in a macro. Idea from wmii. */ 71 #define with(type, var, init) \ 72 for (type var = (type)-1; (var == (type)-1) && ((var = (init)) || 1); var = (type)1) 73 74 #define CASE_SEC(name) \ 75 if (BEGINS_WITH(current, name)) \ 76 with(cfg_t *, sec, cfg_section = cfg_getsec(cfg, name)) if (sec != NULL) 77 78 #define CASE_SEC_TITLE(name) \ 79 if (BEGINS_WITH(current, name)) \ 80 with(const char *, title, current + strlen(name) + 1) \ 81 with(cfg_t *, sec, cfg_section = cfg_gettsec(cfg, name, title)) if (sec != NULL) 82 83 /* Macro which any plugin can use to output the full_text part (when the output 84 * format is JSON) or just output to stdout (any other output format). */ 85 #define OUTPUT_FULL_TEXT(text) \ 86 do { \ 87 /* Terminate the output buffer here in any case, so that it’s \ 88 * not forgotten in the module */ \ 89 *outwalk = '\0'; \ 90 if (output_format == O_I3BAR) { \ 91 char *_markup = cfg_getstr(cfg_general, "markup"); \ 92 yajl_gen_string(ctx->json_gen, (const unsigned char *)"markup", strlen("markup")); \ 93 yajl_gen_string(ctx->json_gen, (const unsigned char *)_markup, strlen(_markup)); \ 94 yajl_gen_string(ctx->json_gen, (const unsigned char *)"full_text", strlen("full_text")); \ 95 yajl_gen_string(ctx->json_gen, (const unsigned char *)text, strlen(text)); \ 96 } else { \ 97 printf("%s", text); \ 98 } \ 99 } while (0) 100 101 #define SEC_OPEN_MAP(name) \ 102 do { \ 103 if (output_format == O_I3BAR) { \ 104 yajl_gen_map_open(json_gen); \ 105 yajl_gen_string(json_gen, (const unsigned char *)"name", strlen("name")); \ 106 yajl_gen_string(json_gen, (const unsigned char *)name, strlen(name)); \ 107 } \ 108 } while (0) 109 110 #define SEC_CLOSE_MAP \ 111 do { \ 112 if (output_format == O_I3BAR) { \ 113 char *_align = cfg_getstr(sec, "align"); \ 114 if (_align) { \ 115 yajl_gen_string(json_gen, (const unsigned char *)"align", strlen("align")); \ 116 yajl_gen_string(json_gen, (const unsigned char *)_align, strlen(_align)); \ 117 } \ 118 struct min_width *_width = cfg_getptr(sec, "min_width"); \ 119 if (_width) { \ 120 /* if the value can be parsed as a number, we use the numerical value */ \ 121 if (_width->num > 0) { \ 122 yajl_gen_string(json_gen, (const unsigned char *)"min_width", strlen("min_width")); \ 123 yajl_gen_integer(json_gen, _width->num); \ 124 } else { \ 125 yajl_gen_string(json_gen, (const unsigned char *)"min_width", strlen("min_width")); \ 126 yajl_gen_string(json_gen, (const unsigned char *)_width->str, strlen(_width->str)); \ 127 } \ 128 } \ 129 if (cfg_size(sec, "separator") > 0) { \ 130 yajl_gen_string(json_gen, (const unsigned char *)"separator", strlen("separator")); \ 131 yajl_gen_bool(json_gen, cfg_getbool(sec, "separator")); \ 132 } \ 133 if (cfg_size(sec, "separator_block_width") > 0) { \ 134 yajl_gen_string(json_gen, (const unsigned char *)"separator_block_width", strlen("separator_block_width")); \ 135 yajl_gen_integer(json_gen, cfg_getint(sec, "separator_block_width")); \ 136 } \ 137 const char *_sep = cfg_getstr(cfg_general, "separator"); \ 138 if (strlen(_sep) == 0) { \ 139 yajl_gen_string(json_gen, (const unsigned char *)"separator", strlen("separator")); \ 140 yajl_gen_bool(json_gen, false); \ 141 } \ 142 yajl_gen_map_close(json_gen); \ 143 } \ 144 } while (0) 145 146 #define START_COLOR(colorstr) \ 147 do { \ 148 if (cfg_getbool(cfg_general, "colors")) { \ 149 const char *_val = NULL; \ 150 if (cfg_section) \ 151 _val = cfg_getstr(cfg_section, colorstr); \ 152 if (!_val) \ 153 _val = cfg_getstr(cfg_general, colorstr); \ 154 if (output_format == O_I3BAR) { \ 155 yajl_gen_string(ctx->json_gen, (const unsigned char *)"color", strlen("color")); \ 156 yajl_gen_string(ctx->json_gen, (const unsigned char *)_val, strlen(_val)); \ 157 } else { \ 158 outwalk += sprintf(outwalk, "%s", color(colorstr)); \ 159 } \ 160 } \ 161 } while (0) 162 163 #define END_COLOR \ 164 do { \ 165 if (cfg_getbool(cfg_general, "colors") && output_format != O_I3BAR) { \ 166 outwalk += sprintf(outwalk, "%s", endcolor()); \ 167 } \ 168 } while (0) 169 170 #define INSTANCE(instance) \ 171 do { \ 172 if (output_format == O_I3BAR) { \ 173 yajl_gen_string(ctx->json_gen, (const unsigned char *)"instance", strlen("instance")); \ 174 yajl_gen_string(ctx->json_gen, (const unsigned char *)instance, strlen(instance)); \ 175 } \ 176 } while (0) 177 178 #define OUTPUT_FORMATTED \ 179 do { \ 180 const size_t remaining = ctx->buflen - (outwalk - ctx->buf); \ 181 strncpy(outwalk, formatted, remaining); \ 182 outwalk += strlen(formatted); \ 183 } while (0) 184 185 /* 186 * The "min_width" module option may either be defined as a string or a number. 187 */ 188 struct min_width { 189 long num; 190 const char *str; 191 }; 192 193 /* src/general.c */ 194 char *skip_character(char *input, char character, int amount); 195 196 void die(const char *fmt, ...) __attribute__((format(printf, 1, 2), noreturn)); 197 bool slurp(const char *filename, char *destination, int size); 198 char *resolve_tilde(const char *path); 199 void *scalloc(size_t size); 200 char *sstrdup(const char *str); 201 202 /* src/output.c */ 203 void print_separator(const char *separator); 204 char *color(const char *colorstr); 205 char *endcolor() __attribute__((pure)); 206 void reset_cursor(void); 207 void maybe_escape_markup(char *text, char **buffer); 208 209 char *rtrim(const char *s); 210 char *ltrim(const char *s); 211 char *trim(const char *s); 212 213 // copied from i3:libi3/format_placeholders.c 214 /* src/format_placeholders.c */ 215 typedef struct { 216 /* The placeholder to be replaced, e.g., "%title". */ 217 const char *name; 218 /* The value this placeholder should be replaced with. */ 219 const char *value; 220 } placeholder_t; 221 char *format_placeholders(const char *format, placeholder_t *placeholders, int num); 222 223 /* src/auto_detect_format.c */ 224 char *auto_detect_format(); 225 226 /* src/print_time.c */ 227 void set_timezone(const char *tz); 228 229 /* src/first_network_device.c */ 230 typedef enum { 231 NET_TYPE_WIRELESS = 0, 232 NET_TYPE_ETHERNET = 1, 233 NET_TYPE_OTHER = 2 234 } net_type_t; 235 const char *first_eth_interface(const net_type_t type); 236 237 typedef struct { 238 yajl_gen json_gen; 239 char *buf; 240 const size_t buflen; 241 const char *format_up; 242 const char *format_down; 243 } ipv6_info_ctx_t; 244 245 void print_ipv6_info(ipv6_info_ctx_t *ctx); 246 247 typedef struct { 248 yajl_gen json_gen; 249 char *buf; 250 const size_t buflen; 251 const char *path; 252 const char *format; 253 const char *format_below_threshold; 254 const char *format_not_mounted; 255 const char *prefix_type; 256 const char *threshold_type; 257 const double low_threshold; 258 } disk_info_ctx_t; 259 260 void print_disk_info(disk_info_ctx_t *ctx); 261 262 typedef struct { 263 yajl_gen json_gen; 264 char *buf; 265 const size_t buflen; 266 int number; 267 const char *path; 268 const char *format; 269 const char *format_down; 270 const char *status_chr; 271 const char *status_bat; 272 const char *status_unk; 273 const char *status_full; 274 int low_threshold; 275 char *threshold_type; 276 bool last_full_capacity; 277 const char *format_percentage; 278 bool hide_seconds; 279 } battery_info_ctx_t; 280 281 void print_battery_info(battery_info_ctx_t *ctx); 282 283 typedef struct { 284 yajl_gen json_gen; 285 char *buf; 286 const size_t buflen; 287 const char *title; 288 const char *format; 289 const char *tz; 290 const char *locale; 291 const char *format_time; 292 bool hide_if_equals_localtime; 293 time_t t; 294 } time_ctx_t; 295 296 void print_time(time_ctx_t *ctx); 297 298 typedef struct { 299 yajl_gen json_gen; 300 char *buf; 301 const size_t buflen; 302 const char *format; 303 time_t t; 304 } ddate_ctx_t; 305 306 void print_ddate(ddate_ctx_t *ctx); 307 308 const char *get_ip_addr(const char *interface, int family); 309 310 typedef struct { 311 yajl_gen json_gen; 312 char *buf; 313 const size_t buflen; 314 const char *interface; 315 const char *format_up; 316 const char *format_down; 317 const char *format_bitrate; 318 const char *format_noise; 319 const char *format_quality; 320 const char *format_signal; 321 } wireless_info_ctx_t; 322 323 void print_wireless_info(wireless_info_ctx_t *ctx); 324 325 typedef struct { 326 yajl_gen json_gen; 327 char *buf; 328 const size_t buflen; 329 const char *title; 330 const char *pidfile; 331 const char *format; 332 const char *format_down; 333 } run_watch_ctx_t; 334 335 void print_run_watch(run_watch_ctx_t *ctx); 336 337 typedef struct { 338 yajl_gen json_gen; 339 char *buf; 340 const size_t buflen; 341 const char *title; 342 const char *path; 343 const char *format; 344 const char *format_down; 345 } path_exists_ctx_t; 346 347 void print_path_exists(path_exists_ctx_t *ctx); 348 349 typedef struct { 350 yajl_gen json_gen; 351 char *buf; 352 const size_t buflen; 353 int zone; 354 const char *path; 355 const char *format; 356 const char *format_above_threshold; 357 int max_threshold; 358 } cpu_temperature_ctx_t; 359 360 void print_cpu_temperature_info(cpu_temperature_ctx_t *ctx); 361 362 typedef struct { 363 yajl_gen json_gen; 364 char *buf; 365 const size_t buflen; 366 const char *format; 367 const char *format_above_threshold; 368 const char *format_above_degraded_threshold; 369 const char *path; 370 const float max_threshold; 371 const float degraded_threshold; 372 } cpu_usage_ctx_t; 373 374 void print_cpu_usage(cpu_usage_ctx_t *ctx); 375 376 typedef struct { 377 yajl_gen json_gen; 378 char *buf; 379 const size_t buflen; 380 const char *interface; 381 const char *format_up; 382 const char *format_down; 383 } eth_info_ctx_t; 384 385 void print_eth_info(eth_info_ctx_t *ctx); 386 387 typedef struct { 388 yajl_gen json_gen; 389 char *buf; 390 const size_t buflen; 391 const char *format; 392 const char *format_above_threshold; 393 const float max_threshold; 394 } load_ctx_t; 395 396 void print_load(load_ctx_t *ctx); 397 398 typedef struct { 399 yajl_gen json_gen; 400 char *buf; 401 const size_t buflen; 402 const char *format; 403 const char *format_degraded; 404 const char *threshold_degraded; 405 const char *threshold_critical; 406 const char *memory_used_method; 407 const char *unit; 408 const int decimals; 409 } memory_ctx_t; 410 411 void print_memory(memory_ctx_t *ctx); 412 413 typedef struct { 414 yajl_gen json_gen; 415 char *buf; 416 const size_t buflen; 417 const char *fmt; 418 const char *fmt_muted; 419 const char *device; 420 const char *mixer; 421 int mixer_idx; 422 } volume_ctx_t; 423 424 void print_volume(volume_ctx_t *ctx); 425 426 bool process_runs(const char *path); 427 int volume_pulseaudio(uint32_t sink_idx, const char *sink_name); 428 bool description_pulseaudio(uint32_t sink_idx, const char *sink_name, char buffer[MAX_SINK_DESCRIPTION_LEN]); 429 bool pulse_initialize(void); 430 431 typedef struct { 432 yajl_gen json_gen; 433 char *buf; 434 const size_t buflen; 435 const char *title; 436 const char *path; 437 const char *format; 438 const char *format_bad; 439 const int max_chars; 440 } file_contents_ctx_t; 441 442 void print_file_contents(file_contents_ctx_t *ctx); 443 444 /* socket file descriptor for general purposes */ 445 extern int general_socket; 446 447 extern cfg_t *cfg, *cfg_general, *cfg_section; 448 449 extern void **cur_instance; 450 451 extern pthread_t main_thread; 452 #endif 453