aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ChangeLog16
-rw-r--r--Makefile.am4
-rwxr-xr-xautogen.sh2
-rw-r--r--colors.c336
-rw-r--r--colors.h27
-rw-r--r--conf.c209
-rw-r--r--doc/config.sample32
-rw-r--r--doc/ncmpc.150
-rw-r--r--list_window.c16
-rw-r--r--main.c5
-rw-r--r--options.c33
-rw-r--r--options.h12
-rw-r--r--screen.c208
-rw-r--r--screen.h8
-rw-r--r--screen_utils.c31
15 files changed, 750 insertions, 239 deletions
diff --git a/ChangeLog b/ChangeLog
index 930038764..e43c8a012 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 */
+
+
+
diff --git a/conf.c b/conf.c
index 1205af5ec..06866c13e 100644
--- a/conf.c
+++ b/conf.c
@@ -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);
}
}
diff --git a/main.c b/main.c
index 1d4588418..bb3740b62 100644
--- a/main.c
+++ b/main.c
@@ -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 */
diff --git a/options.c b/options.c
index 16a61ece0..416727ad3 100644
--- a/options.c
+++ b/options.c
@@ -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;
}
diff --git a/options.h b/options.h
index a06eda2ed..2a6681e2a 100644
--- a/options.h
+++ b/options.h
@@ -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;
diff --git a/screen.c b/screen.c
index 67cbf6bc4..20ece65ff 100644
--- a/screen.c
+++ b/screen.c
@@ -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:
diff --git a/screen.h b/screen.h
index a95269337..a7e6b7250 100644
--- a/screen.h
+++ b/screen.h
@@ -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;
-}
-