#include #include #include #include #include "window.h" #include "layout.h" #include "util.h" #include "event.h" #include "config.h" #include "block.h" #include "lua/api.h" #define ANY_LOG_FORMAT_BEFORE(stream, level, module, func) \ fprintf(stream, "[%s%s%s%s%s%s%s] %s%s%s: ", \ ANY_LOG_COLOR_GET(ANY_LOG_COLOR_MODULE), module, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), *func ? " " : "", \ ANY_LOG_COLOR_GET(ANY_LOG_COLOR_FUNC), func, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \ ANY_LOG_COLOR_GET(level), any_log_level_strings[level], ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET)) #define ANY_LOG_VALUE_BEFORE(stream, level, module, func, message) \ fprintf(stream, "[%s%s%s%s%s%s%s] %s%s%s: %s [", \ ANY_LOG_COLOR_GET(ANY_LOG_COLOR_MODULE), module, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), *func ? " " : "", \ ANY_LOG_COLOR_GET(ANY_LOG_COLOR_FUNC), func, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \ ANY_LOG_COLOR_GET(level), any_log_level_strings[level], ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), message) #define ANY_LOG_VALUE_STRING(stream, key, value) \ fprintf(stream, "%s=\"%s\"", key, value ? value : "(null)") #define ANY_LOG_COLOR_CONTEXT_DEFAULT "\x1b[34m" #define ANY_LOG_IMPLEMENT #include "any_log.h" static sig_atomic_t running = true; static void signal_quit(int status) { running = false; } static cairo_surface_t *render_all(layout_t *layout, config_t *config, layout_info_t info) { cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, config->width, config->height); log_value_trace("Created cairo surface", "i:width", config->width, "i:height", config->height); cairo_t *cr = cairo_create(surface); cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_matrix_t matrix; cairo_matrix_init_scale(&matrix, 1.0 / config->width, 1.0); cairo_pattern_set_matrix(config->background.pattern, &matrix); cairo_set_source(cr, config->background.pattern); cairo_paint(cr); layout_render(layout, cr); log_trace("Rendered layouts"); cairo_destroy(cr); return surface; } int main(int argc, char **argv) { setlocale(LC_CTYPE, ""); any_log_level_t log_level = ANY_LOG_INFO; if (argc != 1 && !strcmp(argv[1], "--trace")) log_level = ANY_LOG_TRACE; any_log_init(log_level, stdout); config_t config; config_init(&config); log_debug("Copied default config"); lua_api_t lua; lua_api_init(&lua); (void)luaL_dostring(lua.state, "log.warn('hello')"); if (luaL_dofile(lua.state, "example.lua") != LUA_OK) { const char *error_message = lua_tostring(lua.state, -1); log_error("Lua script failed: %s", error_message); } const char *config_path = "comet.conf"; FILE *config_file = fopen(config_path, "rb"); if (config_file != NULL) { log_info("Reading config '%s'", config_path); int errors = config_read(&config, config_file); if (errors > 0) { log_error("Config file contained %d syntax errors", errors); return EXIT_FAILURE; } } int errors = config_validate(&config); if (errors > 0) { log_error("Config file contained %d errors", errors); return EXIT_FAILURE; } signal(SIGINT, signal_quit); signal(SIGTERM, signal_quit); display_t display; display_init(&display); window_t window; window_init(&window, &display, &config); log_debug("Searching font '%s'", config.font); PangoFontDescription *fontdesc = pango_font_description_from_string(config.font); log_debug("Loaded font family '%s'", pango_font_description_get_family(fontdesc)); layout_info_t info = { .fontdesc = fontdesc, .context = pango_cairo_create_context(window.cr), .x_offset = 0, .height = config.height, }; block_t *block = NULL; if (!config_resolve(&config, &block)) { log_error("Config could not be resolved"); return EXIT_FAILURE; } log_debug("Starting bar"); window_resize(&window, config.width, config.height); window_move(&window, config.x_offset, config.y_offset); const double fps = 60.0; const double freq = 1.0 / fps + 0.5e-9; // TODO: Allow ondemand/lazy rendering struct timespec rate, start, end, diff; rate.tv_sec = (long)freq; rate.tv_nsec = (freq - rate.tv_sec) * 1000000000ul; event_state_t state = { 0 }; state.config = &config; while (running) { timespec_get(&start, TIME_UTC); block_update(block); layout_t layout; layout_init(&layout, block, info); state.layout = &layout; event_dispatch(&state, &window); cairo_surface_t *surface = render_all(&layout, &config, info); window_present(&window, surface); cairo_surface_destroy(surface); layout_free(&layout); timespec_get(&end, TIME_UTC); diff = timespec_diff(rate, timespec_diff(end, start)); nanosleep(&diff, NULL); } log_debug("Quitting bar"); g_object_unref(info.context); pango_font_description_free(fontdesc); window_close(&window); display_close(&display); config_free(&config); lua_api_close(&lua); return 0; }