#include "../include/Config.hpp" #include "../include/Storage.hpp" #include #include #include // TODO: Show nice error message if config looks wrong (wrong types, has configs that do not exist (maybe spelling mistake?)) namespace QuickMedia { static bool config_initialized = false; static Config *config = nullptr; static float scale = 1.0f; static bool scale_set = false; static const int XFT_DPI_DEFAULT = 96; // Returns XFT_DPI_DEFAULT on error static int xrdb_get_dpi() { int xft_dpi = XFT_DPI_DEFAULT; Display *display = XOpenDisplay(nullptr); if(!display) { fprintf(stderr, "Failed to open x display\n"); return xft_dpi; } char *dpi = XGetDefault(display, "Xft", "dpi"); if(dpi) { xft_dpi = strtol(dpi, nullptr, 10); if(xft_dpi == 0) xft_dpi = XFT_DPI_DEFAULT; } XCloseDisplay(display); return xft_dpi; } static float get_ui_scale() { if(scale_set) return scale; const char *gdk_scale = getenv("GDK_SCALE"); if(gdk_scale) { setlocale(LC_ALL, "C"); // Sigh... stupid C scale = atof(gdk_scale); } else { scale = (float)xrdb_get_dpi() / (float)XFT_DPI_DEFAULT; } if(scale < 0.0001f) scale = 1.0f; scale_set = true; return scale; } static std::string path_expanduser(const std::string &path) { std::string result; if(!path.empty() && path[0] == '~') result = get_home_dir().data + path.substr(1); else result = path; return result; } // No-op if this has already been called before static void init_config() { if(config_initialized) return; setlocale(LC_ALL, "C"); // Sigh... stupid C config_initialized = true; // Wtf? can't use static non-pointer config because it causes a segfault when setting config.theme. // It looks like a libc bug??? crashes for both gcc and clang. config = new Config(); config->scale = get_ui_scale(); Path config_path = get_storage_dir().join("config.json"); if(get_file_type(config_path) != FileType::REGULAR) { return; } Json::Value json_root; if(!read_file_as_json(config_path, json_root) || !json_root.isObject()) { fprintf(stderr, "Warning: failed to parse config file: %s\n", config_path.data.c_str()); return; } const Json::Value &search_json = json_root["search"]; if(search_json.isObject()) { const Json::Value &font_size_json = search_json["font_size"]; if(font_size_json.isNumeric()) config->search.font_size = font_size_json.asInt(); } const Json::Value &tab_json = json_root["tab"]; if(tab_json.isObject()) { const Json::Value &font_size_json = tab_json["font_size"]; if(font_size_json.isNumeric()) config->tab.font_size = font_size_json.asInt(); } const Json::Value &body_json = json_root["body"]; if(body_json.isObject()) { const Json::Value &title_font_size = body_json["title_font_size"]; if(title_font_size.isNumeric()) config->body.title_font_size = title_font_size.asInt(); const Json::Value &author_font_size = body_json["author_font_size"]; if(author_font_size.isNumeric()) config->body.author_font_size = author_font_size.asInt(); const Json::Value &description_font_size = body_json["description_font_size"]; if(description_font_size.isNumeric()) config->body.description_font_size = description_font_size.asInt(); const Json::Value ×tamp_font_size = body_json["timestamp_font_size"]; if(timestamp_font_size.isNumeric()) config->body.timestamp_font_size = timestamp_font_size.asInt(); const Json::Value &reaction_font_size = body_json["reaction_font_size"]; if(reaction_font_size.isNumeric()) config->body.reaction_font_size = reaction_font_size.asInt(); const Json::Value &embedded_load_font_size = body_json["embedded_load_font_size"]; if(embedded_load_font_size.isNumeric()) config->body.embedded_load_font_size = embedded_load_font_size.asInt(); } const Json::Value &input_json = json_root["input"]; if(input_json.isObject()) { const Json::Value &font_size_json = input_json["font_size"]; if(font_size_json.isNumeric()) config->input.font_size = font_size_json.asInt(); } const Json::Value &video_json = json_root["video"]; if(video_json.isObject()) { const Json::Value &max_height_json = video_json["max_height"]; if(max_height_json.isNumeric()) config->video.max_height = max_height_json.asInt(); } const Json::Value &local_manga_json = json_root["local_manga"]; if(local_manga_json.isObject()) { const Json::Value &directory_json = local_manga_json["directory"]; if(directory_json.isString()) { config->local_manga.directory = path_expanduser(directory_json.asString()); while(config->local_manga.directory.size() > 1 && config->local_manga.directory.back() == '/') { config->local_manga.directory.pop_back(); } } const Json::Value &sort_by_name_json = local_manga_json["sort_by_name"]; if(sort_by_name_json.isBool()) config->local_manga.sort_by_name = sort_by_name_json.asBool(); const Json::Value &sort_chapters_by_name_json = local_manga_json["sort_chapters_by_name"]; if(sort_chapters_by_name_json.isBool()) config->local_manga.sort_chapters_by_name = sort_chapters_by_name_json.asBool(); } const Json::Value &local_anime_json = json_root["local_anime"]; if(local_anime_json.isObject()) { const Json::Value &directory_json = local_anime_json["directory"]; if(directory_json.isString()) { config->local_anime.directory = path_expanduser(directory_json.asString()); while(config->local_anime.directory.size() > 1 && config->local_anime.directory.back() == '/') { config->local_anime.directory.pop_back(); } } const Json::Value &sort_by_name_json = local_anime_json["sort_by_name"]; if(sort_by_name_json.isBool()) config->local_anime.sort_by_name = sort_by_name_json.asBool(); const Json::Value &auto_group_episodes_json = local_anime_json["auto_group_episodes"]; if(auto_group_episodes_json.isBool()) config->local_anime.auto_group_episodes = auto_group_episodes_json.asBool(); } const Json::Value &youtube_json = json_root["youtube"]; if(youtube_json.isObject()) { const Json::Value &load_progress_json = youtube_json["load_progress"]; if(load_progress_json.isBool()) config->youtube.load_progress = load_progress_json.asBool(); } const Json::Value &use_system_fonts_json = json_root["use_system_fonts"]; if(use_system_fonts_json.isBool()) config->use_system_fonts = use_system_fonts_json.asBool(); const Json::Value &use_system_mpv_config_json = json_root["use_system_mpv_config"]; if(use_system_mpv_config_json.isBool()) config->use_system_mpv_config = use_system_mpv_config_json.asBool(); const Json::Value &theme_json = json_root["theme"]; if(theme_json.isString()) config->theme = theme_json.asString(); const Json::Value &scale_json = json_root["scale"]; if(scale_json.isNumeric()) config->scale = scale_json.asFloat(); const Json::Value &font_scale = json_root["font_scale"]; if(font_scale.isNumeric()) config->font_scale = font_scale.asFloat(); const Json::Value &spacing_scale = json_root["spacing_scale"]; if(spacing_scale.isNumeric()) config->spacing_scale = spacing_scale.asFloat(); } const Config& get_config() { init_config(); return *config; } }