X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fconf.c;h=7f3ddd51814b4750c4052a9e0a70c481cc7f75ff;hb=07749b7365764dd7a43d476936cb18bf6366e9f8;hp=4485cda5981660676f4de691d81bdf7a9cde96ff;hpb=88af2c3ace0fa42dbb816cc9fe8c4b54ce89233a;p=ncmpc.git diff --git a/src/conf.c b/src/conf.c index 4485cda..7f3ddd5 100644 --- a/src/conf.c +++ b/src/conf.c @@ -1,5 +1,6 @@ -/* - * (c) 2004 by Kalle Wallin +/* ncmpc (Ncurses MPD Client) + * (c) 2004-2010 The Music Player Daemon Project + * Project homepage: http://musicpd.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,13 +11,12 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define NO_GLOBAL_OPTIONS #include "conf.h" #include "config.h" #include "defaults.h" @@ -41,9 +41,9 @@ /* configuration field names */ #define CONF_ENABLE_COLORS "enable-colors" +#define CONF_SCROLL_OFFSET "scroll-offset" #define CONF_AUTO_CENTER "auto-center" #define CONF_WIDE_CURSOR "wide-cursor" -#define CONF_ENABLE_BELL "enable-bell" #define CONF_KEY_DEFINITION "key" #define CONF_COLOR "color" #define CONF_COLOR_DEFINITION "colordef" @@ -55,6 +55,8 @@ #define CONF_FIND_SHOW_LAST "find-show-last" #define CONF_AUDIBLE_BELL "audible-bell" #define CONF_VISIBLE_BELL "visible-bell" +#define CONF_BELL_ON_WRAP "bell-on-wrap" +#define CONF_STATUS_MESSAGE_TIME "status-message-time" #define CONF_XTERM_TITLE "set-xterm-title" #define CONF_ENABLE_MOUSE "enable-mouse" #define CONF_CROSSFADE_TIME "crossfade-time" @@ -66,20 +68,19 @@ #define CONF_HOST "host" #define CONF_PORT "port" #define CONF_PASSWORD "password" +#define CONF_TIMEOUT "timeout" #define CONF_LYRICS_TIMEOUT "lyrics-timeout" -#define CONF_SHOW_SPLASH "show-splash" #define CONF_SCROLL "scroll" #define CONF_SCROLL_SEP "scroll-sep" #define CONF_VISIBLE_BITRATE "visible-bitrate" #define CONF_WELCOME_SCREEN_LIST "welcome-screen-list" - -typedef enum { - KEY_PARSER_UNKNOWN, - KEY_PARSER_CHAR, - KEY_PARSER_DEC, - KEY_PARSER_HEX, - KEY_PARSER_DONE -} key_parser_state_t; +#define CONF_DISPLAY_TIME "display-time" +#define CONF_JUMP_PREFIX_ONLY "jump-prefix-only" +#define CONF_LYRICS_AUTOSAVE "lyrics-autosave" +#define CONF_LYRICS_SHOW_PLUGIN "lyrics-show-plugin" +#define CONF_TEXT_EDITOR "text-editor" +#define CONF_TEXT_EDITOR_ASK "text-editor-ask" +#define CONF_SECOND_COLUMN "second-column" static bool str2bool(char *str) @@ -88,80 +89,41 @@ str2bool(char *str) strcasecmp(str, "on") == 0 || strcasecmp(str, "1") == 0; } -static int -parse_key_value(char *str, size_t len, char **end) +static void +print_error(const char *msg, const char *input) { - size_t i; - int value; - key_parser_state_t state; + fprintf(stderr, "%s: %s ('%s')\n", + /* To translators: prefix for error messages */ + _("Error"), msg, input); +} - i=0; - value=0; - state=KEY_PARSER_UNKNOWN; - *end = str; - - while (i < len && state != KEY_PARSER_DONE) { - int next = 0; - int c = str[i]; - - if( i+1 str+len ) - *end = str+len; + *end = str + 3; + return str[1]; + } else { + long value = strtol(str, end, 0); + if (*end == str) { + print_error(_("Malformed hotkey definition"), str); + return -1; + } - return value; + return (int)value; + } } static int parse_key_definition(char *str) { char buf[MAX_LINE_LENGTH]; - char *p, *end; + char *p; size_t len = strlen(str), i; int j,key; int keys[MAX_COMMAND_KEYS]; @@ -174,7 +136,9 @@ parse_key_definition(char *str) while (i < len && str[i] != '=' && !g_ascii_isspace(str[i])) buf[j++] = str[i++]; if( (cmd=get_key_command_from_name(buf)) == CMD_NONE ) { - fprintf(stderr, _("Error: Unknown key command %s\n"), buf); + /* the hotkey configuration contains an unknown + command */ + print_error(_("Unknown command"), buf); return -1; } @@ -185,133 +149,141 @@ parse_key_definition(char *str) /* get the value part */ memset(buf, 0, MAX_LINE_LENGTH); g_strlcpy(buf, str+i, MAX_LINE_LENGTH); - len = strlen(buf); - if (len == 0) { - fprintf(stderr,_("Error: Incomplete key definition - %s\n"), str); + if (*buf == 0) { + /* the hotkey configuration line is incomplete */ + print_error(_("Incomplete hotkey configuration"), str); return -1; } /* parse key values */ i = 0; key = 0; - len = strlen(buf); p = buf; - end = buf+len; memset(keys, 0, sizeof(int)*MAX_COMMAND_KEYS); - while (i < MAX_COMMAND_KEYS && p < end && - (key = parse_key_value(p, len + 1, &p)) >= 0) { + while (i < MAX_COMMAND_KEYS && *p != 0 && + (key = parse_key_value(p, &p)) >= 0) { keys[i++] = key; - while (p < end && (*p==',' || *p==' ' || *p=='\t')) + while (*p==',' || *p==' ' || *p=='\t') p++; - len = strlen(p); } - if (key < 0) { - fprintf(stderr,_("Error: Bad key definition - %s\n"), str); + if (key < 0) return -1; - } return assign_keys(cmd, keys); } -static const char * +static bool parse_timedisplay_type(const char *str) { - if (!strcmp(str,"elapsed") || !strcmp(str,"remaining")) - return str; + if (strcmp(str, "elapsed") == 0) + return false; + else if (strcmp(str, "remaining") == 0) + return true; else { - fprintf(stderr,_("Error: Bad time display type - %s\n"), str); - return DEFAULT_TIMEDISPLAY_TYPE; + /* translators: ncmpc supports displaying the + "elapsed" or "remaining" time of a song being + played; in this case, the configuration file + contained an invalid setting */ + print_error(_("Bad time display type"), str); + return false; } } #ifdef ENABLE_COLORS +static char * +separate_value(char *p) +{ + char *value; + + value = strchr(p, '='); + if (value == NULL) { + /* an equals sign '=' was expected while parsing a + configuration file line */ + fprintf(stderr, "%s\n", _("Missing '='")); + return NULL; + } + + *value++ = 0; + + g_strchomp(p); + return g_strchug(value); +} + static int parse_color(char *str) { - const char *name = str; - const char *value = NULL; - int len,i; + char *value; - i=0; - len=strlen(str); - /* get the color name */ - while (i < len && str[i] != '=' && !g_ascii_isspace(str[i])) - i++; + value = separate_value(str); + if (value == NULL) + return -1; - /* skip whitespace */ - while (i < len && (str[i] == '=' || g_ascii_isspace(str[i]))) { - str[i]='\0'; - i++; - } + return colors_assign(str, value); +} + +/** + * Returns the first non-whitespace character after the next comma + * character, or the end of the string. This is used to parse comma + * separated values. + */ +static char * +after_comma(char *p) +{ + char *comma = strchr(p, ','); - if (i < len) - value = str+i; + if (comma != NULL) { + *comma++ = 0; + comma = g_strchug(comma); + } else + comma = p + strlen(p); - return colors_assign(name, value); + g_strchomp(p); + return comma; } static int parse_color_definition(char *str) { char buf[MAX_LINE_LENGTH]; - char *p, *end, *name; - size_t len = strlen(str), i; - int j,value; + char *value; short color, rgb[3]; + value = separate_value(str); + if (value == NULL) + return -1; + /* get the command name */ - i=0; - j=0; - memset(buf, 0, MAX_LINE_LENGTH); - while (i < len && str[i] != '=' && !g_ascii_isspace(str[i])) - buf[j++] = str[i++]; - color = colors_str2color(buf); + color = colors_str2color(str); if (color < 0) { - fprintf(stderr,_("Error: Bad color %s [%d]\n"), buf, color); + print_error(_("Bad color name"), buf); return -1; } - name = g_strdup(buf); - /* skip whitespace */ - while (i < len && (str[i] == '=' || g_ascii_isspace(str[i]))) - i++; + /* parse r,g,b values */ - /* get the value part */ - memset(buf, 0, MAX_LINE_LENGTH); - g_strlcpy(buf, str+i, MAX_LINE_LENGTH); - len = strlen(buf); - if (len == 0) { - fprintf(stderr, _("Error: Incomplete color definition - %s\n"), - str); - g_free(name); - return -1; - } + for (unsigned i = 0; i < 3; ++i) { + char *next = after_comma(value), *endptr; + if (*value == 0) { + print_error(_("Incomplete color definition"), str); + return -1; + } - /* parse r,g.b values with the key definition parser */ - i = 0; - value = 0; - len = strlen(buf); - p = buf; - end = buf + len; - memset(rgb, 0, sizeof(short)*3); - while (i < 3 && p < end && - (value = parse_key_value(p,len+1,&p)) >= 0) { - rgb[i++] = value; - while( p= 0 && g_ascii_isspace(line[i])) { - line[i] = '\0'; - i--; - } + name[j] = '\0'; + + /* skip '=' and whitespace */ + while (i < len && (line[i] == '=' || g_ascii_isspace(line[i]))) + i++; - len = i + 1; - if (len > 0) { - i = 0; - /* skip whitespace */ - while (i < len && g_ascii_isspace(line[i])) - i++; - - /* continue if this line is not a comment */ - if (line[i] != COMMENT_TOKEN) { - /* get the name part */ - j = 0; - while (i < len && line[i] != '=' && - !g_ascii_isspace(line[i])) { - name[j++] = line[i++]; - } - - name[j] = '\0'; - - /* skip '=' and whitespace */ - while (i < len && (line[i] == '=' || g_ascii_isspace(line[i]))) - i++; - - /* get the value part */ - j = 0; - while (i < len) - value[j++] = line[i++]; - value[j] = '\0'; - - match_found = 1; - - /* key definition */ - if (!strcasecmp(CONF_KEY_DEFINITION, name)) - parse_key_definition(value); - /* enable colors */ - else if(!strcasecmp(CONF_ENABLE_COLORS, name)) + /* get the value part */ + j = 0; + while (i < len) + value[j++] = line[i++]; + value[j] = '\0'; + + match_found = true; + + /* key definition */ + if (!strcasecmp(CONF_KEY_DEFINITION, name)) + parse_key_definition(value); + /* enable colors */ + else if(!strcasecmp(CONF_ENABLE_COLORS, name)) #ifdef ENABLE_COLORS - options->enable_colors = str2bool(value); + options.enable_colors = str2bool(value); #else - {} + {} #endif - /* auto center */ - else if (!strcasecmp(CONF_AUTO_CENTER, name)) - options->auto_center = str2bool(value); - /* color assignment */ - else if (!strcasecmp(CONF_COLOR, name)) + else if (!strcasecmp(CONF_SCROLL_OFFSET, name)) + options.scroll_offset = atoi(value); + /* auto center */ + else if (!strcasecmp(CONF_AUTO_CENTER, name)) + options.auto_center = str2bool(value); + /* color assignment */ + else if (!strcasecmp(CONF_COLOR, name)) #ifdef ENABLE_COLORS - parse_color(value); + parse_color(value); #else - {} + {} #endif - /* wide cursor */ - else if (!strcasecmp(CONF_WIDE_CURSOR, name)) - options->wide_cursor = str2bool(value); - /* welcome screen list */ - else if (!strcasecmp(CONF_WELCOME_SCREEN_LIST, name)) - options->welcome_screen_list = str2bool(value); - /* visible bitrate */ - else if (!strcasecmp(CONF_VISIBLE_BITRATE, name)) - options->visible_bitrate = str2bool(value); - /* timer display type */ - else if (!strcasecmp(CONF_TIMEDISPLAY_TYPE, name)) { - g_free(options->timedisplay_type); - options->timedisplay_type=g_strdup(parse_timedisplay_type(value)); - /* color definition */ - } else if (!strcasecmp(CONF_COLOR_DEFINITION, name)) + /* wide cursor */ + else if (!strcasecmp(CONF_WIDE_CURSOR, name)) + options.wide_cursor = str2bool(value); + else if (strcasecmp(name, "hardware-cursor") == 0) + options.hardware_cursor = str2bool(value); + /* welcome screen list */ + else if (!strcasecmp(CONF_WELCOME_SCREEN_LIST, name)) + options.welcome_screen_list = str2bool(value); + /* visible bitrate */ + else if (!strcasecmp(CONF_VISIBLE_BITRATE, name)) + options.visible_bitrate = str2bool(value); + /* timer display type */ + else if (!strcasecmp(CONF_TIMEDISPLAY_TYPE, name)) + options.display_remaining_time = parse_timedisplay_type(value); + /* color definition */ + else if (!strcasecmp(CONF_COLOR_DEFINITION, name)) #ifdef ENABLE_COLORS - parse_color_definition(value); + parse_color_definition(value); #else - {} + {} #endif - /* list format string */ - else if (!strcasecmp(CONF_LIST_FORMAT, name)) { - g_free(options->list_format); - options->list_format = get_format(value); - /* status format string */ - } else if (!strcasecmp(CONF_STATUS_FORMAT, name)) { - g_free(options->status_format); - options->status_format = get_format(value); - /* xterm title format string */ - } else if (!strcasecmp(CONF_XTERM_TITLE_FORMAT, name)) { - g_free(options->xterm_title_format); - options->xterm_title_format = get_format(value); - } else if (!strcasecmp(CONF_LIST_WRAP, name)) - options->list_wrap = str2bool(value); - else if (!strcasecmp(CONF_FIND_WRAP, name)) - options->find_wrap = str2bool(value); - else if (!strcasecmp(CONF_FIND_SHOW_LAST,name)) - options->find_show_last_pattern = str2bool(value); - else if (!strcasecmp(CONF_AUDIBLE_BELL, name)) - options->audible_bell = str2bool(value); - else if (!strcasecmp(CONF_VISIBLE_BELL, name)) - options->visible_bell = str2bool(value); - else if (!strcasecmp(CONF_XTERM_TITLE, name)) - options->enable_xterm_title = str2bool(value); - else if (!strcasecmp(CONF_ENABLE_MOUSE, name)) - options->enable_mouse = str2bool(value); - else if (!strcasecmp(CONF_CROSSFADE_TIME, name)) - options->crossfade_time = atoi(value); - else if (!strcasecmp(CONF_SEARCH_MODE, name)) - options->search_mode = atoi(value); - else if (!strcasecmp(CONF_HIDE_CURSOR, name)) - options->hide_cursor = atoi(value); - else if (!strcasecmp(CONF_SEEK_TIME, name)) - options->seek_time = atoi(value); - else if (!strcasecmp(CONF_SCREEN_LIST, name)) { - g_strfreev(options->screen_list); - options->screen_list = check_screen_list(value); - } else if (!strcasecmp(CONF_SHOW_SPLASH, name)) { - /* the splash screen was removed */ - } else if (!strcasecmp(CONF_HOST, name)) - options->host = get_format(value); - else if (!strcasecmp(CONF_PORT, name)) - options->port = atoi(get_format(value)); - else if (!strcasecmp(CONF_PASSWORD, name)) - options->password = get_format(value); - else if (!strcasecmp(CONF_LYRICS_TIMEOUT, name)) - options->lyrics_timeout = atoi(get_format(value)); - else if (!strcasecmp(CONF_SCROLL, name)) - options->scroll = str2bool(value); - else if (!strcasecmp(CONF_SCROLL_SEP, name)) { - g_free(options->scroll_sep); - options->scroll_sep = get_format(value); - } else - match_found = 0; - - if (!match_found) - fprintf(stderr, - _("Unknown configuration parameter: %s\n"), - name); - } + /* list format string */ + else if (!strcasecmp(CONF_LIST_FORMAT, name)) { + g_free(options.list_format); + options.list_format = get_format(value); + /* status format string */ + } else if (!strcasecmp(CONF_STATUS_FORMAT, name)) { + g_free(options.status_format); + options.status_format = get_format(value); + /* xterm title format string */ + } else if (!strcasecmp(CONF_XTERM_TITLE_FORMAT, name)) { + g_free(options.xterm_title_format); + options.xterm_title_format = get_format(value); + } else if (!strcasecmp(CONF_LIST_WRAP, name)) + options.list_wrap = str2bool(value); + else if (!strcasecmp(CONF_FIND_WRAP, name)) + options.find_wrap = str2bool(value); + else if (!strcasecmp(CONF_FIND_SHOW_LAST,name)) + options.find_show_last_pattern = str2bool(value); + else if (!strcasecmp(CONF_AUDIBLE_BELL, name)) + options.audible_bell = str2bool(value); + else if (!strcasecmp(CONF_VISIBLE_BELL, name)) + options.visible_bell = str2bool(value); + else if (!strcasecmp(CONF_BELL_ON_WRAP, name)) + options.bell_on_wrap = str2bool(value); + else if (!strcasecmp(CONF_STATUS_MESSAGE_TIME, name)) + options.status_message_time = atoi(value); + else if (!strcasecmp(CONF_XTERM_TITLE, name)) + options.enable_xterm_title = str2bool(value); + else if (!strcasecmp(CONF_ENABLE_MOUSE, name)) +#ifdef HAVE_GETMOUSE + options.enable_mouse = str2bool(value); +#else + {} +#endif + else if (!strcasecmp(CONF_CROSSFADE_TIME, name)) + options.crossfade_time = atoi(value); + else if (!strcasecmp(CONF_SEARCH_MODE, name)) + options.search_mode = get_search_mode(value); + else if (!strcasecmp(CONF_HIDE_CURSOR, name)) + options.hide_cursor = atoi(value); + else if (!strcasecmp(CONF_SEEK_TIME, name)) + options.seek_time = atoi(value); + else if (!strcasecmp(CONF_SCREEN_LIST, name)) { + g_strfreev(options.screen_list); + options.screen_list = check_screen_list(value); + } else if (!strcasecmp(CONF_HOST, name)) + options.host = get_format(value); + else if (!strcasecmp(CONF_PORT, name)) + options.port = atoi(get_format(value)); + else if (!strcasecmp(CONF_PASSWORD, name)) + options.password = get_format(value); + else if (!strcasecmp(CONF_TIMEOUT, name)) + options.timeout_ms = atoi(get_format(value)) + * 1000 /* seconds -> milliseconds */; + else if (!strcasecmp(CONF_LYRICS_TIMEOUT, name)) +#ifdef ENABLE_LYRICS_SCREEN + options.lyrics_timeout = atoi(get_format(value)); +#else + {} +#endif + else if (!strcasecmp(CONF_SCROLL, name)) + options.scroll = str2bool(value); + else if (!strcasecmp(CONF_SCROLL_SEP, name)) { + g_free(options.scroll_sep); + options.scroll_sep = get_format(value); + } else if (!strcasecmp(CONF_DISPLAY_TIME, name)) +#ifdef NCMPC_MINI + {} +#else + options.display_time = str2bool(value); +#endif + else if (!strcasecmp(CONF_JUMP_PREFIX_ONLY, name)) +#ifdef NCMPC_MINI + {} +#else + options.jump_prefix_only = str2bool(value); +#endif + else if (!strcasecmp(CONF_LYRICS_AUTOSAVE, name)) +#ifdef ENABLE_LYRICS_SCREEN + options.lyrics_autosave = str2bool(value); +#else + {} +#endif + else if (!strcasecmp(CONF_LYRICS_SHOW_PLUGIN, name)) +#ifdef ENABLE_LYRICS_SCREEN + options.lyrics_show_plugin = str2bool(value); +#else + {} +#endif + else if (!strcasecmp(name, CONF_TEXT_EDITOR)) +#ifdef ENABLE_LYRICS_SCREEN + { + g_free(options.text_editor); + options.text_editor = get_format(value); } - } +#else + {} +#endif + else if (!strcasecmp(name, CONF_TEXT_EDITOR_ASK)) +#ifdef ENABLE_LYRICS_SCREEN + options.text_editor_ask = str2bool(value); +#else + {} +#endif + else if (!strcasecmp(CONF_SECOND_COLUMN, name)) +#ifdef NCMPC_MINI + {} +#else + options.second_column = str2bool(value); +#endif + else + match_found = false; - if (free_filename) - g_free(filename); + if (!match_found) + print_error(_("Unknown configuration parameter"), name); + return match_found; +} + +static int +read_rc_file(char *filename) +{ + FILE *file; + char line[MAX_LINE_LENGTH]; + + if (filename == NULL) + return -1; + + file = fopen(filename, "r"); + if (file == NULL) { + perror(filename); + return -1; + } + + while (fgets(line, sizeof(line), file) != NULL) { + char *p = g_strchug(line); + + if (*p != 0 && *p != COMMENT_TOKEN) + parse_line(g_strchomp(p)); + } + + fclose(file); return 0; } @@ -555,7 +596,11 @@ check_user_conf_dir(void) return 0; } +#ifndef WIN32 retval = mkdir(directory, 0755); +#else + retval = mkdir(directory); +#endif g_free(directory); return retval; } @@ -567,13 +612,13 @@ get_user_key_binding_filename(void) } int -read_configuration(options_t *options) +read_configuration(void) { char *filename = NULL; /* check for command line configuration file */ - if (options->config_file) - filename = g_strdup(options->config_file); + if (options.config_file) + filename = g_strdup(options.config_file); /* check for user configuration ~/.ncmpc/config */ if (filename == NULL) { @@ -596,14 +641,14 @@ read_configuration(options_t *options) /* load configuration */ if (filename) { - read_rc_file(filename, options); + read_rc_file(filename); g_free(filename); filename = NULL; } /* check for command line key binding file */ - if (options->key_file) - filename = g_strdup(options->key_file); + if (options.key_file) + filename = g_strdup(options.key_file); /* check for user key bindings ~/.ncmpc/keys */ if (filename == NULL) { @@ -625,7 +670,7 @@ read_configuration(options_t *options) /* load key bindings */ if (filename) { - read_rc_file(filename, options); + read_rc_file(filename); g_free(filename); filename = NULL; }