diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rwxr-xr-x | autogen.sh | 2 | ||||
-rw-r--r-- | colors.c | 336 | ||||
-rw-r--r-- | colors.h | 27 | ||||
-rw-r--r-- | conf.c | 209 | ||||
-rw-r--r-- | doc/config.sample | 32 | ||||
-rw-r--r-- | doc/ncmpc.1 | 50 | ||||
-rw-r--r-- | list_window.c | 16 | ||||
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | options.c | 33 | ||||
-rw-r--r-- | options.h | 12 | ||||
-rw-r--r-- | screen.c | 208 | ||||
-rw-r--r-- | screen.h | 8 | ||||
-rw-r--r-- | screen_utils.c | 31 |
15 files changed, 750 insertions, 239 deletions
@@ -1,3 +1,19 @@ +2004-05-07 Kalle Wallin <kaw@linux.se> + * Redesigned ncmpc's color support - view the manual for details! + * Added support for moving songs in a playlist (move-up, move-down) + * options.c: added new command line options --config and --key-file, + wide_cursor is now enabled by default + * screen.c: scroll long song titles in the status window, + dont display volume changes in the status window. + +2004-05-03 Kalle Wallin <kaw@linux.se> + * configure.ac: display default values for --enable-x, + version updated to 0.10.2-svn + * conf.c: The background color can now be assigned to 'none'. + +2004-04-26 Kalle Wallin <kaw@linux.se> + * ncmpc-0.10.1 released (r892) + 2004-04-23 Kalle Wallin <kaw@linux.se> * Updated Changelog, TODO, NEWS and the manual page. * screen_play.c: Make shure the cursor stays on the same row when diff --git a/Makefile.am b/Makefile.am index bada1ea01..8ac5da7de 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,12 +16,12 @@ SUBDIRS = doc ncmpc_headers = libmpdclient.h mpc.h options.h conf.h command.h screen.h \ screen_utils.h screen_play.h screen_file.h screen_search.h \ - screen_help.h list_window.h support.h + screen_help.h list_window.h colors.h support.h ncmpc_SOURCES = libmpdclient.c main.c mpc.c options.c conf.c command.c \ screen.c screen_utils.c screen_play.c screen_file.c \ screen_search.c screen_help.c screen_keydef.c \ - list_window.c support.c $(ncmpc_headers) + list_window.c colors.c support.c $(ncmpc_headers) diff --git a/autogen.sh b/autogen.sh index 8d47e6127..72a235234 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,7 +1,7 @@ #! /bin/sh # Check Autoconf version if [ -x `which autoconf` ]; then - AC_VER=`autoconf --version | head -1 | sed 's/^[^0-9]*//'` + AC_VER=`autoconf --version | head -n 1 | sed 's/^[^0-9]*//'` AC_VER_MAJOR=`echo $AC_VER | cut -f1 -d'.'` AC_VER_MINOR=`echo $AC_VER | cut -f2 -d'.' | sed 's/[^0-9]*$//'` diff --git a/colors.c b/colors.c new file mode 100644 index 000000000..f70969390 --- /dev/null +++ b/colors.c @@ -0,0 +1,336 @@ +/* + * (c) 2004 by Kalle Wallin (kaw@linux.se) + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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 + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ncurses.h> +#include <glib.h> + +#include "config.h" +#include "options.h" +#include "support.h" +#include "colors.h" + +#ifdef DEBUG +#define D(x) x +#else +#define D(x) +#endif + +#define COLOR_BRIGHT_MASK (1<<7) + +#define COLOR_BRIGHT_BLACK (COLOR_BLACK | COLOR_BRIGHT_MASK) +#define COLOR_BRIGHT_RED (COLOR_RED | COLOR_BRIGHT_MASK) +#define COLOR_BRIGHT_GREEN (COLOR_GREEN | COLOR_BRIGHT_MASK) +#define COLOR_BRIGHT_YELLOW (COLOR_YELLOW | COLOR_BRIGHT_MASK) +#define COLOR_BRIGHT_BLUE (COLOR_BLUE | COLOR_BRIGHT_MASK) +#define COLOR_BRIGHT_MAGENTA (COLOR_MAGENTA | COLOR_BRIGHT_MASK) +#define COLOR_BRIGHT_CYAN (COLOR_CYAN | COLOR_BRIGHT_MASK) +#define COLOR_BRIGHT_WHITE (COLOR_WHITE | COLOR_BRIGHT_MASK) + +#define IS_BRIGHT(color) (color & COLOR_BRIGHT_MASK) + +/* name of the color fields */ +#define NAME_TITLE "title" +#define NAME_TITLE_BOLD "title-bold" +#define NAME_LINE "line" +#define NAME_LINE_BOLD "line-flags" +#define NAME_LIST "list" +#define NAME_LIST_BOLD "list-bold" +#define NAME_PROGRESS "progressbar" +#define NAME_STATUS "status-song" +#define NAME_STATUS_BOLD "status-state" +#define NAME_STATUS_TIME "status-time" +#define NAME_ALERT "alert" +#define NAME_BGCOLOR "background" + +typedef struct { + short color; + short r,g,b; +} color_definition_entry_t; + +typedef struct { + int id; + char *name; + short fg; + attr_t attrs; +} color_entry_t; + +static color_entry_t colors[] = { + + /* color pair, field name, color, mono attribute */ + /*-------------------------------------------------------------------------*/ + { COLOR_TITLE, NAME_TITLE, COLOR_YELLOW, A_NORMAL }, + { COLOR_TITLE_BOLD, NAME_TITLE_BOLD, COLOR_BRIGHT_YELLOW, A_BOLD }, + { COLOR_LINE, NAME_LINE, COLOR_WHITE, A_NORMAL }, + { COLOR_LINE_BOLD, NAME_LINE_BOLD, COLOR_BRIGHT_WHITE, A_BOLD }, + { COLOR_LIST, NAME_LIST, COLOR_GREEN, A_NORMAL }, + { COLOR_LIST_BOLD, NAME_LIST_BOLD, COLOR_BRIGHT_GREEN, A_BOLD }, + { COLOR_PROGRESSBAR, NAME_PROGRESS, COLOR_WHITE, A_NORMAL }, + { COLOR_STATUS, NAME_STATUS, COLOR_YELLOW, A_NORMAL }, + { COLOR_STATUS_BOLD, NAME_STATUS_BOLD, COLOR_BRIGHT_YELLOW, A_BOLD }, + { COLOR_STATUS_TIME, NAME_STATUS_TIME, COLOR_RED, A_NORMAL }, + { COLOR_STATUS_ALERT, NAME_ALERT, COLOR_BRIGHT_RED, A_BOLD }, + { 0, NULL, 0, 0 } +}; + +/* background color */ +static short bg = COLOR_BLACK; + +static GList *color_definition_list = NULL; + +static color_entry_t * +colors_lookup(int id) +{ + int i; + + i=0; + while( colors[i].name != NULL ) + { + if( colors[i].id == id ) + return &colors[i]; + i++; + } + return NULL; +} + +static color_entry_t * +colors_lookup_by_name(char *name) +{ + int i; + + i=0; + while( colors[i].name != NULL ) + { + if( !strcasecmp(colors[i].name, name) ) + return &colors[i]; + i++; + } + return NULL; +} + +static int +colors_update_pair(int id) +{ + color_entry_t *entry = colors_lookup(id); + short fg = -1; + + if( !entry ) + return -1; + + if( IS_BRIGHT(entry->fg) ) + { + entry->attrs = A_BOLD; + fg = entry->fg & ~COLOR_BRIGHT_MASK; + } + else + { + entry->attrs = A_NORMAL; + fg = entry->fg; + } + + init_pair(entry->id, fg, bg); + + return 0; +} + +short +colors_str2color(char *str) +{ + if( !strcasecmp(str,"black") ) + return COLOR_BLACK; + else if( !strcasecmp(str,"red") ) + return COLOR_RED; + else if( !strcasecmp(str,"green") ) + return COLOR_GREEN; + else if( !strcasecmp(str,"yellow") ) + return COLOR_YELLOW; + else if( !strcasecmp(str,"blue") ) + return COLOR_BLUE; + else if( !strcasecmp(str,"magenta") ) + return COLOR_MAGENTA; + else if( !strcasecmp(str,"cyan") ) + return COLOR_CYAN; + else if( !strcasecmp(str,"white") ) + return COLOR_WHITE; + else if( !strcasecmp(str,"brightred") ) + return COLOR_BRIGHT_RED; + else if( !strcasecmp(str,"brightgreen") ) + return COLOR_BRIGHT_GREEN; + else if( !strcasecmp(str,"brightyellow") ) + return COLOR_BRIGHT_YELLOW; + else if( !strcasecmp(str,"brightblue") ) + return COLOR_BRIGHT_BLUE; + else if( !strcasecmp(str,"brightmagenta") ) + return COLOR_BRIGHT_MAGENTA; + else if( !strcasecmp(str,"brightcyan") ) + return COLOR_BRIGHT_CYAN; + else if( !strcasecmp(str,"brightwhite") ) + return COLOR_BRIGHT_WHITE; + else if( !strcasecmp(str,"grey") || !strcasecmp(str,"gray") ) + return COLOR_BRIGHT_BLACK; + else if( !strcasecmp(str,"none") ) + return -1; + fprintf(stderr,"Warning: Unknown color - %s\n", str); + return -2; +} + +/* This function is called from conf.c before curses have been started, + * it adds the definition to the color_definition_list and init_color() is + * done in colors_start() */ +int +colors_define(char *name, short r, short g, short b) +{ + color_definition_entry_t *entry; + short color = colors_str2color(name); + + if( color<0 ) + return -1; + + entry = g_malloc(sizeof(color_definition_entry_t)); + entry->color = color; + entry->r = r; + entry->g = g; + entry->b = b; + + color_definition_list = g_list_append(color_definition_list, entry); + + return 0; +} + + +int +colors_assign(char *name, char *value) +{ + color_entry_t *entry = colors_lookup_by_name(name); + short color; + + if( !entry ) + { + if( !strcasecmp(NAME_BGCOLOR, name) ) + { + if( (color=colors_str2color(value)) < -1 ) + return -1; + if( color > COLORS ) + color = color & ~COLOR_BRIGHT_MASK; + bg = color; + return 0; + } + fprintf(stderr,"Warning: Unknown color field - %s\n", name); + return -1; + } + + if( (color=colors_str2color(value)) < -1 ) + return -1; + entry->fg = color; + + return 0; +} + + +int +colors_start(void) +{ + if( has_colors() ) + { + /* initialize color support */ + start_color(); + use_default_colors(); + /* define any custom colors defined in the configuration file */ + if( color_definition_list && can_change_color() ) + { + GList *list = color_definition_list; + + while( list ) + { + color_definition_entry_t *entry = list->data; + + if( entry->color <= COLORS ) + init_color(entry->color, entry->r, entry->g, entry->b); + list=list->next; + } + } + else if( !can_change_color() ) + fprintf(stderr, "Terminal lacks support for changing colors!\n"); + + if( options.enable_colors ) + { + int i = 0; + + while(colors[i].name) + { + /* update the color pairs */ + colors_update_pair(colors[i].id); + i++; + } + + } + } + else if( options.enable_colors ) + { + fprintf(stderr, "Terminal lacks color capabilities!\n"); + options.enable_colors = 0; + } + + /* free the color_definition_list */ + if( color_definition_list ) + { + GList *list = color_definition_list; + + while( list ) + { + g_free(list->data); + list=list->next; + } + g_list_free(color_definition_list); + color_definition_list = NULL; + } + + return 0; +} + + +int +colors_use(WINDOW *w, int id) +{ + color_entry_t *entry = colors_lookup(id); + short pair; + attr_t attrs; + + if( !entry ) + return -1; + + wattr_get(w, &attrs, &pair, NULL); + + if( options.enable_colors ) + { + /* color mode */ + if( attrs != entry->attrs || id!=pair ) + wattr_set(w, entry->attrs, id, NULL); + } + else + { + /* mono mode */ + if( attrs != entry->attrs ) + wattrset(w, entry->attrs); + } + + return 0; +} + diff --git a/colors.h b/colors.h new file mode 100644 index 000000000..a66d693cc --- /dev/null +++ b/colors.h @@ -0,0 +1,27 @@ +#ifndef COLORS_H +#define COLORS_H + +#define COLOR_TITLE 1 +#define COLOR_TITLE_BOLD 2 +#define COLOR_LINE 3 +#define COLOR_LINE_BOLD 4 +#define COLOR_LIST 5 +#define COLOR_LIST_BOLD 6 +#define COLOR_PROGRESSBAR 7 +#define COLOR_STATUS 8 +#define COLOR_STATUS_BOLD 9 +#define COLOR_STATUS_TIME 10 +#define COLOR_STATUS_ALERT 11 + +short colors_str2color(char *str); + +int colors_assign(char *name, char *value); +int colors_define(char *name, short r, short g, short b); +int colors_start(void); +int colors_use(WINDOW *w, int id); + + +#endif /* COLORS_H */ + + + @@ -33,6 +33,7 @@ #include "options.h" #include "support.h" #include "command.h" +#include "colors.h" #include "conf.h" #ifdef DEBUG @@ -41,7 +42,7 @@ #define D(x) #endif -#define RCFILE "." PACKAGE "rc" +#define ENABLE_OLD_COLOR_SYNTAX #define MAX_LINE_LENGTH 1024 #define COMMENT_TOKEN '#' @@ -49,8 +50,12 @@ /* configuration field names */ #define CONF_ENABLE_COLORS "enable_colors" #define CONF_AUTO_CENTER "auto_center" +#define CONF_WIDE_CURSOR "wide_cursor" +#define CONF_KEY_DEFINITION "key" +#define CONF_COLOR "color" +#define CONF_COLOR_DEFINITION "colordef" -/* configuration field names - colors */ +/* Deprecated - configuration field names */ #define CONF_COLOR_BACKGROUND "background_color" #define CONF_COLOR_TITLE "title_color" #define CONF_COLOR_LINE "line_color" @@ -58,8 +63,7 @@ #define CONF_COLOR_PROGRESS "progress_color" #define CONF_COLOR_STATUS "status_color" #define CONF_COLOR_ALERT "alert_color" -#define CONF_WIDE_CURSOR "wide_cursor" -#define CONF_KEY_DEFINITION "key" + typedef enum { KEY_PARSER_UNKNOWN, @@ -79,31 +83,6 @@ str2bool(char *str) } static int -str2color(char *str) -{ - if( !strcasecmp(str,"black") ) - return COLOR_BLACK; - else if( !strcasecmp(str,"red") ) - return COLOR_RED; - else if( !strcasecmp(str,"green") ) - return COLOR_GREEN; - else if( !strcasecmp(str,"yellow") ) - return COLOR_YELLOW; - else if( !strcasecmp(str,"blue") ) - return COLOR_BLUE; - else if( !strcasecmp(str,"magenta") ) - return COLOR_MAGENTA; - else if( !strcasecmp(str,"cyan") ) - return COLOR_CYAN; - else if( !strcasecmp(str,"white") ) - return COLOR_WHITE; - else if( !strcasecmp(str,"default") || !strcasecmp(str,"none") ) - return -1; - fprintf(stderr,"Warning: unknown color %s\n", str); - return -2; -} - -static int parse_key_value(char *str, size_t len, char **end) { int i, value; @@ -231,11 +210,101 @@ parse_key_definition(char *str) } static int +parse_color(char *str) +{ + char *name = str; + char *value = NULL; + int len,i; + + i=0; + len=strlen(str); + /* get the color name */ + while( i<len && str[i]!='=' && !IS_WHITESPACE(str[i]) ) + i++; + + /* skip whitespace */ + while( i<len && (str[i]=='=' || IS_WHITESPACE(str[i])) ) + { + str[i]='\0'; + i++; + } + + if( i<len ) + value = str+i; + + return colors_assign(name, value); +} + + +static int +parse_color_definition(char *str) +{ + char buf[MAX_LINE_LENGTH]; + char *p, *end, *name; + size_t len = strlen(str); + int i,j,value; + short color, rgb[3]; + + /* get the command name */ + i=0; + j=0; + memset(buf, 0, MAX_LINE_LENGTH); + while( i<len && str[i]!='=' && !IS_WHITESPACE(str[i]) ) + buf[j++] = str[i++]; + color=colors_str2color(buf); + if( color<0 ) + { + fprintf(stderr, "Error: Bad color %s [%d]\n", buf, color); + return -1; + } + name = g_strdup(buf); + + /* skip whitespace */ + while( i<len && (str[i]=='=' || IS_WHITESPACE(str[i])) ) + i++; + + /* get the value part */ + memset(buf, 0, MAX_LINE_LENGTH); + strncpy(buf, str+i, len-i); + len = strlen(buf); + if( len==0 ) + { + fprintf(stderr,"Error: Incomplete color definition - %s\n", str); + g_free(name); + 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<end && (*p==',' || *p==' ' || *p=='\t') ) + p++; + len = strlen(p); + } + if( value<0 || i!=3) + { + fprintf(stderr,"Error: Bad color definition - %s\n", str); + g_free(name); + return -1; + } + value = colors_define(name, rgb[0], rgb[1], rgb[2]); + g_free(name); + return value; +} + + +static int read_rc_file(char *filename, options_t *options) { int fd; int quit = 0; - int color = -1; int free_filename = 0; if( filename==NULL ) @@ -244,7 +313,7 @@ read_rc_file(char *filename, options_t *options) D(printf("Reading configuration file %s\n", filename)); if( (fd=open(filename,O_RDONLY)) <0 ) { - D(perror(filename)); + perror(filename); if( free_filename ) g_free(filename); return -1; @@ -314,7 +383,8 @@ read_rc_file(char *filename, options_t *options) value[j] = '\0'; match_found = 1; - + + /* key definition */ if( !strcasecmp(CONF_KEY_DEFINITION, name) ) { parse_key_definition(value); @@ -329,52 +399,68 @@ read_rc_file(char *filename, options_t *options) { options->auto_center = str2bool(value); } + /* color assignment */ + else if( !strcasecmp(CONF_COLOR, name) ) + { + parse_color(value); + } +#ifdef ENABLE_OLD_COLOR_SYNTAX /* background color */ else if( !strcasecmp(CONF_COLOR_BACKGROUND, name) ) { - if( (color=str2color(value)) >= -1 ) - options->bg_color = color; + fprintf(stderr,"%s: %s - deprecated!\n", filename,name); + colors_assign("background", value); } /* color - top (title) window */ else if( !strcasecmp(CONF_COLOR_TITLE, name) ) { - if( (color=str2color(value)) >= 0 ) - options->title_color = color; + fprintf(stderr,"%s: %s - deprecated!\n", filename,name); + colors_assign("title", value); + colors_assign("title2", value); } /* color - line (title) window */ else if( !strcasecmp(CONF_COLOR_LINE, name) ) { - if( (color=str2color(value)) >= 0 ) - options->line_color = color; + fprintf(stderr,"%s: %s - deprecated!\n", filename,name); + colors_assign("line", value); + colors_assign("line2", value); } /* color - list window */ else if( !strcasecmp(CONF_COLOR_LIST, name) ) { - if( (color=str2color(value)) >= 0 ) - options->list_color = color; + fprintf(stderr,"%s: %s - deprecated!\n", filename,name); + colors_assign("list", value); } /* color - progress bar */ else if( !strcasecmp(CONF_COLOR_PROGRESS, name) ) { - if( (color=str2color(value)) >= 0 ) - options->progress_color = color; + fprintf(stderr,"%s: %s - deprecated!\n", filename,name); + colors_assign("progressbar", value); } /* color - status window */ else if( !strcasecmp(CONF_COLOR_STATUS, name) ) { - if( (color=str2color(value)) >= 0 ) - options->status_color = color; + fprintf(stderr,"%s: %s - deprecated!\n", filename,name); + colors_assign("status", value); + colors_assign("status2", value); } /* color - alerts */ else if( !strcasecmp(CONF_COLOR_ALERT, name) ) { - if( (color=str2color(value)) >= 0 ) - options->alert_color = color; + fprintf(stderr,"%s: %s - deprecated!\n", filename,name); + colors_assign("alert", value); } +#endif + /* wide cursor */ else if( !strcasecmp(CONF_WIDE_CURSOR, name) ) { options->wide_cursor = str2bool(value); } + /* color definition */ + else if( !strcasecmp(CONF_COLOR_DEFINITION, name) ) + { + parse_color_definition(value); + } else { match_found = 0; @@ -432,12 +518,20 @@ read_configuration(options_t *options) { char *filename = NULL; + /* check for command line configuration file */ + if( options->config_file ) + filename = g_strdup(options->config_file); + /* check for user configuration ~/.ncmpc/config */ - filename = g_build_filename(g_get_home_dir(), "." PACKAGE, "config", NULL); - if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + if( filename == NULL ) { - g_free(filename); - filename = NULL; + filename = g_build_filename(g_get_home_dir(), + "." PACKAGE, "config", NULL); + if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + { + g_free(filename); + filename = NULL; + } } /* check for global configuration SYSCONFDIR/ncmpc/config */ @@ -459,12 +553,19 @@ read_configuration(options_t *options) filename = NULL; } + /* check for command line key binding file */ + if( options->key_file ) + filename = g_strdup(options->key_file); + /* check for user key bindings ~/.ncmpc/keys */ - filename = get_user_key_binding_filename(); - if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + if( filename == NULL ) { - g_free(filename); - filename = NULL; + filename = get_user_key_binding_filename(); + if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + { + g_free(filename); + filename = NULL; + } } /* check for global key bindings SYSCONFDIR/ncmpc/keys */ diff --git a/doc/config.sample b/doc/config.sample index d97f69937..f8d2ad4d3 100644 --- a/doc/config.sample +++ b/doc/config.sample @@ -6,7 +6,7 @@ #auto_center = no ## wide_cursor - make the cursor as wide as the screen -#wide_cursor = no +#wide_cursor = yes ## ## Color configuration @@ -17,17 +17,25 @@ ## enable/disable colors #enable_colors = no -## background color -#background_color = black - -## text colors -#title_color = white -#line_color = green -#list_color = yellow -#progress_color = green -#status_color = white -#alert_color = yellow - +## background colors: black,red,green,yellow,blue,magenta,cyan,white, none +#color background = black + +## text colors: black, red, green, yellow, blue, magenta, cyan, white, +## brightblack, brightred, brightgreen, brightyellow, brightblue, +## brightmagenta, brightcyan, brightwhite + + +#color title = yellow +#color title-bold = brightyellow +#color line = white +#color line-flags = brightwhite +#color list = green +#color list-bold = brightgreen +#color progressbar = white +#color status-state = brightyellow +#color status-song = yellow +#color status-time = red +#color alert = brightred diff --git a/doc/ncmpc.1 b/doc/ncmpc.1 index 25b6951ca..93d297ff5 100644 --- a/doc/ncmpc.1 +++ b/doc/ncmpc.1 @@ -48,11 +48,20 @@ Connect to server on PORT. .B \-P, \-\-password=PASSWORD Use password when connecting. .TP +.B \-f, \-\-config=FILE +Read configuration from file. +.TP +.B \-P, \-\-key\-file=FILE +Read key bindings from FILE. +.TP Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options. .SH "CONFIGURATION" When ncmpc start it tries to read user setting from the ~/ncmpc/config file. If no user configuration is found ncmpc tries to load global settings from $SYSCONFDIR/ncmpc/config (the actual path is displayed on the help screen). An example configuration file (config.sample) should be provided with ncmpc. -Avalible colors: black, red, green, yellow, blue, magenta, cyan and white. +Base colors are: black, red, green, yellow, blue, magenta, cyan and white. + +Possible text colors are the base colors plus grey, brightred, brightgreen, brightyellow, brightblue, brightmagenta, brightcyan and brightwhite. + Supported configuration options: .TP @@ -66,26 +75,45 @@ Make the cursor as wide as the screen. .B enable_colors = yes|no Enable/disable colors. .TP -.B background_color = color|none -Set the background color. If the background color is assigned to the keyword \fBnone\fR, ncmpc will not change the background color. +.B color background = COLOR +Set the background color. If the background color is assigned to the keyword \fBnone\fR, ncmpc will not change the background color. Only the base colors are valid background colors. +.TP +.B color title = TEXTCOLOR +Set the text color for the title row. .TP -.B title_color = color -Set the text color for the title row (first row). +.B color title\-bold = TEXTCOLOR +Set the text color for the title row (the bold part). .TP -.B line_color = color +.B color line = TEXTCOLOR Set the color of the line on the second row. .TP -.B list_color = color +.B color line\-flags = TEXTCOLOR +Set the text color used to indicate mpd flags on the second row. +.TP +.B color list = TEXTCOLOR Set the text color in the main area of ncmpc. .TP -.B progress_color = color +.B color list\-bold = TEXTCOLOR +Set the bold text color in the main area of ncmpc. +.TP +.B color progressbar = TEXTCOLOR Set the color of the progress indicator. .TP -.B status_color = color -Set the text color used in the status window (last row). +.B color status\-state = TEXTCOLOR +Set the text color used to display mpd status in the status window. +.TP +.B color status\-song = TEXTCOLOR +Set the text color used to display song names in the status window. .TP -.B alert_color = color +.B color status\-time = TEXTCOLOR +Set the text color used to display time the status window. +.TP +.B color alert = TEXTCOLOR Text color used to display alerts in the status window. +.TP +.B colordef COLOR = R, G, B +Redefine any of the base colors. The RGB values must be an integer value between 0 and 1000. +\fBNote\fR: Only some terminals allow redefinitions of colors! .SH "KEYS" When ncmpc start it tries to read user key bindings from the ~/ncmpc/keys file. If no user key bindings is found ncmpc tries to load global key bindings from $SYSCONFDIR/ncmpc/keys (the actual path is displayed on the help screen). diff --git a/list_window.c b/list_window.c index b251310be..6b4a41f0c 100644 --- a/list_window.c +++ b/list_window.c @@ -26,6 +26,7 @@ #include "options.h" #include "support.h" #include "command.h" +#include "colors.h" #include "list_window.h" list_window_t * @@ -164,19 +165,22 @@ list_window_paint(list_window_t *lw, wclrtoeol(lw->w); if( label ) { + int selected = lw->start+i == lw->selected; + if( highlight ) - wattron(lw->w, A_BOLD); - if( lw->start+i == lw->selected ) + colors_use(lw->w, COLOR_LIST_BOLD); + else + colors_use(lw->w, COLOR_LIST); + + if( selected ) wattron(lw->w, A_REVERSE); waddnstr(lw->w, label, lw->cols-1); if( fill ) mvwhline(lw->w, i, strlen(label), ' ', lw->cols-1); - if( highlight ) - wattroff(lw->w, A_BOLD); - if( lw->start+i == lw->selected ) - wattroff(lw->w, A_REVERSE); + if( selected ) + wattroff(lw->w, A_REVERSE); } } @@ -75,6 +75,9 @@ main(int argc, const char *argv[]) /* initialize options */ options = options_init(); + + /* parse command line options - 1 pass get configuration files */ + options_parse(argc, argv); /* read configuration */ read_configuration(options); @@ -86,7 +89,7 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); } - /* parse command line options */ + /* parse command line options - 2 pass */ options_parse(argc, argv); /* initialize local charset */ @@ -33,13 +33,14 @@ options_t options; static char *mpd_host = NULL; static char *mpd_password = NULL; +static char *config_file = NULL; +static char *key_file = NULL; static struct poptOption optionsTable[] = { #ifdef DEBUG { "debug", 'D', 0, 0, 'D', "Enable debug output." }, #endif { "version", 'V', 0, 0, 'V', "Display version information." }, - { "keys", 'k', 0, 0, 'k', "Display key bindings." }, { "colors", 'c', 0, 0, 'c', "Enable colors." }, { "no-colors", 'C', 0, 0, 'C', "Disable colors." }, { "exit", 'e', 0, 0, 'e', "Exit on connection errors." }, @@ -49,6 +50,11 @@ static struct poptOption optionsTable[] = { "Connect to server [" DEFAULT_HOST "].", "HOSTNAME" }, { "password", 'P', POPT_ARG_STRING, &mpd_password, 0, "Connect with password.", "PASSWORD" }, + { "config", 'f', POPT_ARG_STRING, &config_file, 0, + "Read config from FILE." , "FILE" }, + { "key-file", 'k', POPT_ARG_STRING, &key_file, 0, + "Read key bindings from FILE." , "FILE" }, + POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; @@ -70,6 +76,8 @@ options_parse( int argc, const char **argv) mpd_host = NULL; mpd_password = NULL; + config_file = NULL; + key_file = NULL; optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((c = poptGetNextOpt(optCon)) >= 0) { @@ -89,9 +97,6 @@ options_parse( int argc, const char **argv) case 'V': printf("Version " VERSION "\n"); exit(EXIT_SUCCESS); - case 'k': - command_dump_keys(); - exit(EXIT_SUCCESS); case 'e': options.reconnect = 0; break; @@ -124,6 +129,17 @@ options_parse( int argc, const char **argv) g_free(options.password); options.password = mpd_password; } + if( config_file ) + { + g_free(options.config_file); + options.config_file = config_file; + } + if( key_file ) + { + g_free(options.key_file); + options.key_file = key_file; + } + poptFreeContext(optCon); return &options; } @@ -156,14 +172,7 @@ options_init( void ) options.reconnect = 1; options.find_wrap = 1; - - options.bg_color = COLOR_BLACK; - options.title_color = COLOR_YELLOW; - options.line_color = COLOR_WHITE; - options.list_color = COLOR_GREEN; - options.progress_color = COLOR_WHITE; - options.status_color = COLOR_YELLOW; - options.alert_color = COLOR_RED; + options.wide_cursor = 1; return &options; } @@ -7,21 +7,15 @@ typedef struct char *host; char *username; char *password; + char *config_file; + char *key_file; int port; int reconnect; int debug; int find_wrap; int auto_center; - + int wide_cursor; int enable_colors; - int bg_color; - int title_color; - int line_color; - int list_color; - int progress_color; - int status_color; - int alert_color; - int wide_cursor; } options_t; @@ -25,10 +25,12 @@ #include <glib.h> #include <ncurses.h> +#include "config.h" #include "libmpdclient.h" #include "mpc.h" #include "command.h" #include "options.h" +#include "colors.h" #include "screen.h" #include "screen_play.h" #include "screen_file.h" @@ -36,8 +38,8 @@ #include "screen_search.h" #include "screen_utils.h" -#define ENABLE_MP_FLAGS_DISPLAY #undef ENABLE_STATUS_LINE_CLOCK +#define ENABLE_SCROLLING #define DEFAULT_CROSSFADE_TIME 10 @@ -94,6 +96,7 @@ switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c) static void paint_top_window(char *header, mpd_client_t *c, int clear) { + char flags[4]; static int prev_volume = -1; static int prev_header_len = -1; WINDOW *w = screen->top_window.w; @@ -116,23 +119,22 @@ paint_top_window(char *header, mpd_client_t *c, int clear) if( header[0] ) { - wattron(w, A_BOLD); + colors_use(w, COLOR_TITLE_BOLD); mvwaddstr(w, 0, 0, header); - wattroff(w, A_BOLD); } else { - wattron(w, A_BOLD); + colors_use(w, COLOR_TITLE_BOLD); waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE)); - wattroff(w, A_BOLD); + colors_use(w, COLOR_TITLE); waddstr(w, ":Help "); - wattron(w, A_BOLD); + colors_use(w, COLOR_TITLE_BOLD); waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE)); - wattroff(w, A_BOLD); + colors_use(w, COLOR_TITLE); waddstr(w, ":Playlist "); - wattron(w, A_BOLD); + colors_use(w, COLOR_TITLE_BOLD); waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE)); - wattroff(w, A_BOLD); + colors_use(w, COLOR_TITLE); waddstr(w, ":Browse"); } if( c->status->volume==MPD_STATUS_NO_VOLUME ) @@ -143,41 +145,27 @@ paint_top_window(char *header, mpd_client_t *c, int clear) { snprintf(buf, 12, "Volume %3d%%", c->status->volume); } + colors_use(w, COLOR_TITLE); mvwaddstr(w, 0, screen->top_window.cols-12, buf); - if( options.enable_colors ) - wattron(w, LINE_COLORS); - -#ifdef ENABLE_MP_FLAGS_DISPLAY - { - char buf[4]; - - buf[0] = 0; - if( c->status->repeat ) - strcat(buf, "r"); - if( c->status->random ) - strcat(buf, "z"); - if( c->status->crossfade ) - strcat(buf, "x"); - - mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols); - if( buf[0] ) - { - wmove(w,1,screen->top_window.cols-strlen(buf)-3); - waddch(w, '['); - wattron(w, A_BOLD); - waddstr(w, buf); - wattroff(w, A_BOLD); - waddch(w, ']'); - } - } -#else + flags[0] = 0; + if( c->status->repeat ) + strcat(flags, "r"); + if( c->status->random ) + strcat(flags, "z"); + if( c->status->crossfade ) + strcat(flags, "x"); + colors_use(w, COLOR_LINE); mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols); -#endif - - if( options.enable_colors ) - wattroff(w, LINE_COLORS); - + if( flags[0] ) + { + wmove(w,1,screen->top_window.cols-strlen(flags)-3); + waddch(w, '['); + colors_use(w, COLOR_LINE_BOLD); + waddstr(w, flags); + colors_use(w, COLOR_LINE); + waddch(w, ']'); + } wnoutrefresh(w); } } @@ -212,6 +200,46 @@ paint_progress_window(mpd_client_t *c) wnoutrefresh(screen->progress_window.w); } +#ifdef ENABLE_SCROLLING +static char * +scroll_string(char *str, char *sep, int width) +{ + static int offset = 0; + static time_t t = 0; + char *tmp, *buf; + size_t len; + + if( offset==0 ) + { + offset++; + return g_strdup(str); + } + + /* create a buffer containing the string and the separator */ + tmp = g_malloc(strlen(str)+strlen(sep)+1); + strcpy(tmp, str); + strcat(tmp, sep); + len = strlen(tmp); + + if( offset >= len ) + offset = 0; + + /* create the new scrolled string */ + buf = g_malloc(width+1); + strncpy(buf, tmp+offset, width); + if( strlen(buf) < width ) + strncat(buf, tmp, width-strlen(buf)); + + if( time(NULL)-t >= 1 ) + { + t = time(NULL); + offset++; + } + g_free(tmp); + return buf; +} +#endif + static void paint_status_window(mpd_client_t *c) { @@ -224,54 +252,63 @@ paint_status_window(mpd_client_t *c) if( time(NULL) - screen->status_timestamp <= STATUS_MESSAGE_TIMEOUT ) return; + wmove(w, 0, 0); wclrtoeol(w); + colors_use(w, COLOR_STATUS_BOLD); switch(status->state) { case MPD_STATUS_STATE_STOP: - wattron(w, A_BOLD); waddstr(w, "Stopped! "); - wattroff(w, A_BOLD); break; case MPD_STATUS_STATE_PLAY: - wattron(w, A_BOLD); waddstr(w, "Playing:"); - wattroff(w, A_BOLD); break; case MPD_STATUS_STATE_PAUSE: - wattron(w, A_BOLD); waddstr(w, "[Paused]"); - wattroff(w, A_BOLD); break; default: - my_waddstr(w, - "Warning: Music Player Daemon in unknown state!", - ALERT_COLORS); break; } - x += 10; + x += 9; - if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) && song ) - { - mvwaddstr(w, 0, x, mpc_get_song_name(song)); - } - - - /* time */ + /* create time string */ + memset(screen->buf, 0, screen->buf_size); if( c->seek_song_id == c->song_id ) elapsedTime = c->seek_target_time; if( IS_PLAYING(status->state) || IS_PAUSED(status->state) ) + snprintf(screen->buf, screen->buf_size, + " [%i:%02i/%i:%02i] ", + elapsedTime/60, elapsedTime%60, + status->totalTime/60, status->totalTime%60 ); + + /* display song */ + if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) && song ) { - x = screen->status_window.cols - strlen(screen->buf); + char *songname = mpc_get_song_name(song); + int width = COLS-x-strlen(screen->buf); - snprintf(screen->buf, screen->buf_size, - " [%i:%02i/%i:%02i] ", - elapsedTime/60, elapsedTime%60, - status->totalTime/60, status->totalTime%60 ); + colors_use(w, COLOR_STATUS); +#ifdef ENABLE_SCROLLING + if( strlen(songname) > width ) + { + char *tmp = scroll_string(songname, " *** ", width); + strcpy(songname, tmp); + g_free(tmp); + } +#endif + mvwaddnstr(w, 0, x, songname, width); + } + + /* distplay time string */ + if( screen->buf[0] ) + { + x = screen->status_window.cols - strlen(screen->buf); + colors_use(w, COLOR_STATUS_TIME); mvwaddstr(w, 0, x, screen->buf); - } + #ifdef ENABLE_STATUS_LINE_CLOCK else if( c->status->state == MPD_STATUS_STATE_STOP ) { @@ -281,10 +318,10 @@ paint_status_window(mpd_client_t *c) time(&timep); strftime(screen->buf, screen->buf_size, "%X ", localtime(&timep)); x = screen->status_window.cols - strlen(screen->buf) ; + colors_use(w, COLOR_STATUS_TIME); mvwaddstr(w, 0, x, screen->buf); } #endif - wnoutrefresh(w); } @@ -393,9 +430,8 @@ screen_status_message(char *msg) wmove(w, 0, 0); wclrtoeol(w); - wattron(w, A_BOLD); - my_waddstr(w, msg, ALERT_COLORS); - wattroff(w, A_BOLD); + colors_use(w, COLOR_STATUS_ALERT); + waddstr(w, msg); wnoutrefresh(w); screen->status_timestamp = time(NULL); } @@ -418,27 +454,9 @@ screen_init(void) GList *list; /* initialize the curses library */ - initscr(); - if( has_colors() ) - { - start_color(); - use_default_colors(); - if( options.enable_colors ) - { - init_pair(1, options.title_color, options.bg_color); - init_pair(2, options.line_color, options.bg_color); - init_pair(3, options.list_color, options.bg_color); - init_pair(4, options.progress_color, options.bg_color); - init_pair(5, options.status_color, options.bg_color); - init_pair(6, options.alert_color, options.bg_color); - } - } - else if( options.enable_colors ) - { - fprintf(stderr, "Terminal lacks color capabilities.\n"); - options.enable_colors = 0; - } - + initscr(); + /* initialize color support */ + colors_start(); /* tell curses not to do NL->CR/NL on output */ nonl(); /* take input chars one at a time, no wait for \n */ @@ -514,10 +532,12 @@ screen_init(void) if( options.enable_colors ) { /* set background attributes */ - wbkgd(screen->main_window.w, LIST_COLORS); - wbkgd(screen->top_window.w, TITLE_COLORS); - wbkgd(screen->progress_window.w, PROGRESS_COLORS); - wbkgd(screen->status_window.w, STATUS_COLORS); + wbkgd(stdscr, COLOR_PAIR(COLOR_LIST)); + wbkgd(screen->main_window.w, COLOR_PAIR(COLOR_LIST)); + wbkgd(screen->top_window.w, COLOR_PAIR(COLOR_TITLE)); + wbkgd(screen->progress_window.w, COLOR_PAIR(COLOR_PROGRESSBAR)); + wbkgd(screen->status_window.w, COLOR_PAIR(COLOR_STATUS)); + colors_use(screen->progress_window.w, COLOR_PROGRESSBAR); } /* initialize screens */ @@ -761,7 +781,6 @@ screen_cmd(mpd_client_t *c, command_t cmd) c->status->volume=c->status->volume+1; mpd_sendSetvolCommand(c->connection, c->status->volume ); mpd_finishCommand(c->connection); - screen_status_printf("Volume %d%%", c->status->volume); } break; case CMD_VOLUME_DOWN: @@ -770,7 +789,6 @@ screen_cmd(mpd_client_t *c, command_t cmd) c->status->volume=c->status->volume-1; mpd_sendSetvolCommand(c->connection, c->status->volume ); mpd_finishCommand(c->connection); - screen_status_printf("Volume %d%%", c->status->volume); } break; case CMD_TOGGLE_FIND_WRAP: @@ -10,14 +10,6 @@ #define TOP_HEADER_HELP TOP_HEADER_PREFIX "Help " #define TOP_HEADER_SEARCH TOP_HEADER_PREFIX "Search " -/* colors */ -#define TITLE_COLORS COLOR_PAIR(1) -#define LINE_COLORS COLOR_PAIR(2) -#define LIST_COLORS COLOR_PAIR(3) -#define PROGRESS_COLORS COLOR_PAIR(4) -#define STATUS_COLORS COLOR_PAIR(5) -#define ALERT_COLORS COLOR_PAIR(6) - /* minumum window size */ #define SCREEN_MIN_COLS 14 #define SCREEN_MIN_ROWS 5 diff --git a/screen_utils.c b/screen_utils.c index 1fb581aaa..f8dfa4c1d 100644 --- a/screen_utils.c +++ b/screen_utils.c @@ -29,6 +29,7 @@ #include "command.h" #include "options.h" #include "list_window.h" +#include "colors.h" #include "screen.h" #define FIND_PROMPT "Find: " @@ -40,6 +41,7 @@ screen_getch(WINDOW *w, char *prompt) int key = -1; int prompt_len = strlen(prompt); + colors_use(w, COLOR_STATUS_ALERT); wclear(w); wmove(w, 0, 0); waddstr(w, prompt); @@ -67,6 +69,7 @@ screen_getstr(WINDOW *w, char *prompt) char buf[256], *line = NULL; int prompt_len = strlen(prompt); + colors_use(w, COLOR_STATUS_ALERT); wclear(w); wmove(w, 0, 0); waddstr(w, prompt); @@ -148,31 +151,3 @@ screen_find(screen_t *screen, } -int -my_waddstr(WINDOW *w, const char *text, int color) -{ - int ret; - - if( options.enable_colors ) - wattron(w, color); - ret = waddstr(w, text); - if( options.enable_colors ) - wattroff(w, color); - - return ret; -} - -int -my_mvwaddstr(WINDOW *w, int x, int y, const char *text, int color) -{ - int ret; - - if( options.enable_colors ) - wattron(w, color); - ret = mvwaddstr(w, x, y, text); - if( options.enable_colors ) - wattroff(w, color); - - return ret; -} - |