Code

Changed directory layout (for future use of gettext)
authorKalle Wallin <kaw@linux.se>
Sat, 5 Jun 2004 11:21:43 +0000 (11:21 +0000)
committerKalle Wallin <kaw@linux.se>
Sat, 5 Jun 2004 11:21:43 +0000 (11:21 +0000)
git-svn-id: https://svn.musicpd.org/ncmpc/trunk@1342 09075e82-0dd4-0310-85a5-a0d7c8717e4f

65 files changed:
ChangeLog
Makefile.am
autogen.sh
colors.c [deleted file]
colors.h [deleted file]
command.c [deleted file]
command.h [deleted file]
conf.c [deleted file]
conf.h [deleted file]
configure.ac
libmpdclient.c [deleted file]
libmpdclient.h [deleted file]
list_window.c [deleted file]
list_window.h [deleted file]
main.c [deleted file]
mpc.c [deleted file]
mpc.h [deleted file]
options.c [deleted file]
options.h [deleted file]
screen.c [deleted file]
screen.h [deleted file]
screen_file.c [deleted file]
screen_file.h [deleted file]
screen_help.c [deleted file]
screen_help.h [deleted file]
screen_keydef.c [deleted file]
screen_play.c [deleted file]
screen_play.h [deleted file]
screen_search.c [deleted file]
screen_search.h [deleted file]
screen_utils.c [deleted file]
screen_utils.h [deleted file]
src/Makefile.am [new file with mode: 0644]
src/colors.c [new file with mode: 0644]
src/colors.h [new file with mode: 0644]
src/command.c [new file with mode: 0644]
src/command.h [new file with mode: 0644]
src/conf.c [new file with mode: 0644]
src/conf.h [new file with mode: 0644]
src/libmpdclient.c [new file with mode: 0644]
src/libmpdclient.h [new file with mode: 0644]
src/list_window.c [new file with mode: 0644]
src/list_window.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/mpc.c [new file with mode: 0644]
src/mpc.h [new file with mode: 0644]
src/options.c [new file with mode: 0644]
src/options.h [new file with mode: 0644]
src/screen.c [new file with mode: 0644]
src/screen.h [new file with mode: 0644]
src/screen_file.c [new file with mode: 0644]
src/screen_file.h [new file with mode: 0644]
src/screen_help.c [new file with mode: 0644]
src/screen_help.h [new file with mode: 0644]
src/screen_keydef.c [new file with mode: 0644]
src/screen_play.c [new file with mode: 0644]
src/screen_play.h [new file with mode: 0644]
src/screen_search.c [new file with mode: 0644]
src/screen_search.h [new file with mode: 0644]
src/screen_utils.c [new file with mode: 0644]
src/screen_utils.h [new file with mode: 0644]
src/support.c [new file with mode: 0644]
src/support.h [new file with mode: 0644]
support.c [deleted file]
support.h [deleted file]

index e43c8a012590d1bc5c03bdbc6c0cc7b425fd6697..2a4de6102756a07f509341096983bf9ce7762e62 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-06-05 Kalle Wallin <kaw@linux.se>
+       * Changed directory layout to suit future use of gettext 
+       * screen.c: Added mpd update flag [U] and display a status message
+                   when a update has finished
+       * screen.c: Display bit rate instead of time when the total time
+                   is zero and display local time when mpd is stopped.
+
 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)
index 8ac5da7de15cb5e3b3b8e83a45ada462d78707bb..8bf3267ee26653491bb3ea9028560f55778aeffa 100644 (file)
@@ -1,27 +1,15 @@
 #
-# $Id: Makefile.am,v 1.5 2004/03/16 23:49:14 kalle Exp $
+# $Id$
 #
 
-bin_PROGRAMS = ncmpc
+AUTOMAKE_OPTIONS = foreign 1.6
+
+SUBDIRS = doc src
 pkgdata_DATA =
 docdir = $(prefix)/share/doc/$(PACKAGE)
-doc_DATA = AUTHORS README ChangeLog
-EXTRA_DIST = COPYING $(pkgdata_DATA) $(doc_DATA)
-
-SUBDIRS = doc
-
-#EXTRA_ncmpc_SOURCES = 
-#ncmpc_LDADD = 
-#ncmpc_DEPENDENCIES = 
-
-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 colors.h support.h 
+doc_DATA = AUTHORS README
+EXTRA_DIST = ChangeLog COPYING $(pkgdata_DATA) $(doc_DATA)
 
-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 colors.c support.c $(ncmpc_headers)
 
 
 
index 72a2352343087ba9f949882f97a40dd316a4290c..22e7897d79ea25af63dbb0bbc4a0aa6ef2b87191 100755 (executable)
-#! /bin/sh
-# Check Autoconf version
-if [ -x `which autoconf` ]; then
-       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]*$//'`
-
-       if [ "$AC_VER_MAJOR" -lt "2" ]; then
-               echo "Autoconf 2.13 or greater needed to build configure."
-               exit 1
-       fi
-
-       if [ "$AC_VER_MINOR" -lt "13" ]; then
-               echo "Autoconf 2.13 or greater needed to build configure."
-               exit 1
-       fi
-
-       if [ "$AC_VER_MINOR" -lt "50" ]; then
-               if [ ! -e configure.in ]; then
-                       ln -s configure.ac configure.in
-               fi
-               echo "If you see some warnings about cross-compiling, don't worry; this is normal."
-       else
-               echo "rm -f configure.in ?"
-       fi
-else
-       echo Autoconf not found. AlsaPlayer CVS requires autoconf to bootstrap itself.
-       exit 1
-fi
+#!/bin/sh
+# Run this to set up the build system: configure, makefiles, etc.
+# (based on the version in enlightenment's cvs)
+
+package="ncmpc"
+
+olddir=`pwd`
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+cd "$srcdir"
+DIE=0
+
+echo "checking for autoconf... "
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have autoconf installed to compile $package."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+        DIE=1
+}
+
+VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9]\.[0-9]\).*/\1/"
+VERSIONMKINT="sed -e s/[^0-9]//"
 
-run_cmd() {
-    echo running $* ...
-    if ! $*; then
-                       echo failed!
-                       exit 1
+# do we need automake?
+if test -r Makefile.am; then
+  AM_NEEDED=`fgrep AUTOMAKE_OPTIONS Makefile.am | $VERSIONGREP`
+  if test -z $AM_NEEDED; then
+    echo -n "checking for automake... "
+    AUTOMAKE=automake
+    ACLOCAL=aclocal
+    if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then
+      echo "no"
+      AUTOMAKE=
+    else
+      echo "yes"
     fi
+  else
+    echo -n "checking for automake $AM_NEEDED or later... "
+    for am in automake-$AM_NEEDED automake$AM_NEEDED automake; do
+      ($am --version < /dev/null > /dev/null 2>&1) || continue
+      ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT`
+      verneeded=`echo $AM_NEEDED | $VERSIONMKINT`
+      if test $ver -ge $verneeded; then
+        AUTOMAKE=$am
+        echo $AUTOMAKE
+        break
+      fi
+    done
+    test -z $AUTOMAKE &&  echo "no"
+    echo -n "checking for aclocal $AM_NEEDED or later... "
+    for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED aclocal; do
+      ($ac --version < /dev/null > /dev/null 2>&1) || continue
+      ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT`
+      verneeded=`echo $AM_NEEDED | $VERSIONMKINT`
+      if test $ver -ge $verneeded; then
+        ACLOCAL=$ac
+        echo $ACLOCAL
+        break
+      fi
+    done
+    test -z $ACLOCAL && echo "no"
+  fi
+  test -z $AUTOMAKE || test -z $ACLOCAL && {
+        echo
+        echo "You must have automake installed to compile $package."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+        exit 1
+  }
+fi
+
+echo -n "checking for libtool... "
+for LIBTOOLIZE in libtoolize glibtoolize nope; do
+  (which $LIBTOOLIZE) > /dev/null 2>&1 && break
+done
+if test x$LIBTOOLIZE = xnope; then
+  echo "nope."
+  LIBTOOLIZE=libtoolize
+else
+  echo $LIBTOOLIZE
+fi
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+       echo
+       echo "You must have libtool installed to compile $package."
+       echo "Download the appropriate package for your system,"
+       echo "or get the source from one of the GNU ftp sites"
+       echo "listed in http://www.gnu.org/order/ftp.html"
+       DIE=1
 }
 
-# Check if /usr/local/share/aclocal exists
-if [ -d /usr/local/share/aclocal ]; then
-       ACLOCAL_INCLUDE="$ACLOCAL_INCLUDE -I /usr/local/share/aclocal"
-fi     
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+echo "Generating configuration files for $package, please wait...."
 
 if [ -d m4 ] ; then
-  run_cmd cat m4/*.m4 > acinclude.m4
+  cat m4/*.m4 > acinclude.m4
+fi
+
+if [ -d /usr/local/share/aclocal ]; then
+       ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I /usr/local/share/aclocal"
 fi
-run_cmd aclocal $ACLOCAL_INCLUDE
-run_cmd autoheader 
-run_cmd libtoolize --automake
-run_cmd automake --add-missing
-run_cmd autoconf
-echo
-echo "Now run './configure'"
-echo
+echo "  $ACLOCAL $ACLOCAL_FLAGS"
+$ACLOCAL $ACLOCAL_FLAGS
+
+echo "  autoheader"
+autoheader
+
+echo "  $LIBTOOLIZE --automake"
+$LIBTOOLIZE --automake
+
+echo "  $AUTOMAKE --add-missing $AUTOMAKE_FLAGS"
+$AUTOMAKE --add-missing $AUTOMAKE_FLAGS 
+
+echo "  autoconf"
+autoconf
+
+cd $olddir
+$srcdir/configure "$@" && echo
diff --git a/colors.c b/colors.c
deleted file mode 100644 (file)
index f709693..0000000
--- a/colors.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/* 
- * (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
deleted file mode 100644 (file)
index a66d693..0000000
--- a/colors.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#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/command.c b/command.c
deleted file mode 100644 (file)
index 1e9edcd..0000000
--- a/command.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/* 
- * (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 <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-#include "command.h"
-
-#undef DEBUG_KEYS
-
-#ifdef DEBUG_KEYS
-#define DK(x) x
-#else
-#define DK(x)
-#endif
-
-extern void screen_resize(void);
-
-#define BS   KEY_BACKSPACE
-#define DEL  KEY_DC
-#define UP   KEY_UP
-#define DWN  KEY_DOWN
-#define LEFT KEY_LEFT
-#define RGHT KEY_RIGHT
-#define HOME KEY_HOME
-#define END  KEY_END
-#define PGDN KEY_NPAGE
-#define PGUP KEY_PPAGE
-#define TAB  0x09
-#define STAB 0x161
-#define ESC  0x1B
-#define F1   KEY_F(1)
-#define F2   KEY_F(2)
-#define F3   KEY_F(3)
-#define F4   KEY_F(4)
-#define F5   KEY_F(5)
-#define F6   KEY_F(6)
-
-
-static command_definition_t cmds[] =
-{
-  { {  13,   0,   0 }, CMD_PLAY, "play",  
-    "Play/Enter directory" },
-  { { 'P',   0,   0 }, CMD_PAUSE,"pause", 
-    "Pause" },
-  { { 's',  BS,   0 }, CMD_STOP, "stop",   
-    "Stop" },
-  { { '>',   0,   0 }, CMD_TRACK_NEXT, "next", 
-    "Next track" },
-  { { '<',   0,   0 }, CMD_TRACK_PREVIOUS, "prev", 
-    "Previous track" },
-  { { 'f',   0,   0 }, CMD_SEEK_FORWARD, "seek-forward", 
-    "Seek forward" },
-  { { 'b',   0,   0 }, CMD_SEEK_BACKWARD, "seek-backward", 
-    "Seek backward" },
-
-  { { '+', RGHT,  0 }, CMD_VOLUME_UP, "volume-up", 
-    "Increase volume" },
-  { { '-', LEFT,  0 }, CMD_VOLUME_DOWN, "volume-down", 
-    "Decrease volume" },
-
-  { { 'w',   0,   0 }, CMD_TOGGLE_FIND_WRAP,  "wrap-mode", 
-    "Toggle find mode" },
-  { { 'U',   0,   0 }, CMD_TOGGLE_AUTOCENTER, "autocenter-mode", 
-    "Toggle auto center mode" },
-
-  { { ' ',  'a',   0 }, CMD_SELECT, "select", 
-    "Select/deselect song in playlist" },
-  { { DEL,  'd',  0 }, CMD_DELETE, "delete",
-    "Delete song from playlist" },
-  { { 'Z',   0,   0 }, CMD_SHUFFLE, "shuffle",
-    "Shuffle playlist" },
-  { { 'c',   0,   0 }, CMD_CLEAR, "clear",
-    "Clear playlist" },
-  { { 'r',   0,   0 }, CMD_REPEAT, "repeat",
-    "Toggle repeat mode" },
-  { { 'z',   0,   0 }, CMD_RANDOM, "random",
-    "Toggle random mode" },
-  { { 'x',   0,   0 }, CMD_CROSSFADE, "crossfade",
-    "Toggle crossfade mode" },
-  { { 'S',   0,   0 }, CMD_SAVE_PLAYLIST, "save",
-    "Save playlist" },
-
-  { { 0,  0,   0 }, CMD_LIST_MOVE_UP,     "move-up", 
-    "Move item up" },
-  { { 0,  0,   0 }, CMD_LIST_MOVE_DOWN,   "move-down", 
-    "Move item down" },
-
-  { {  UP,  ',',   0 }, CMD_LIST_PREVIOUS,      "up",
-    "Move cursor up" },
-  { { DWN,  '.',   0 }, CMD_LIST_NEXT,          "down",
-    "Move cursor down" },
-  { { HOME, 0x01, 0 }, CMD_LIST_FIRST,          "home",
-    "Home " },
-  { { END,  0x05, 0 }, CMD_LIST_LAST,           "end",
-    "End " },
-  { { PGUP, 'A',   0 }, CMD_LIST_PREVIOUS_PAGE, "pgup",
-    "Page up" },
-  { { PGDN, 'B',   0 }, CMD_LIST_NEXT_PAGE,     "pgdn", 
-    "Page down" },
-  { { '/',   0,   0 }, CMD_LIST_FIND,           "find",
-    "Forward find" },
-  { { 'n',   0,   0 }, CMD_LIST_FIND_NEXT,      "find-next",
-    "Forward find next" },
-  { { '?',   0,   0 }, CMD_LIST_RFIND,          "rfind",
-    "Backward find" },
-  { { 'p',   0,   0 }, CMD_LIST_RFIND_NEXT,     "rfind-next",
-    "Backward find previous" },
-
-
-  { { TAB,   0,   0 }, CMD_SCREEN_NEXT,     "screen-next",
-    "Next screen" },
-
-  { { STAB,  0,   0 }, CMD_SCREEN_PREVIOUS, "screen-prev",
-    "Previous screen" },
-
-  { { '1', F1, 'h' }, CMD_SCREEN_HELP,      "screen-help",
-    "Help screen" },
-  { { '2', F2,  0 }, CMD_SCREEN_PLAY,      "screen-playlist",
-    "Playlist screen" },
-  { { '3', F3,  0 }, CMD_SCREEN_FILE,      "screen-browse",
-    "Browse screen" },
-  { {'u',   0,   0 }, CMD_SCREEN_UPDATE,    "update",
-    "Update screen" },
-#ifdef ENABLE_KEYDEF_SCREEN
-  { {'K',   0,   0 }, CMD_SCREEN_KEYDEF,    "screen-keyedit",
-    "Key configuration screen" },
-#endif
-
-  { { 'q',  0,   0 }, CMD_QUIT,   "quit",
-    "Quit " PACKAGE },  
-
-  { { -1,  -1,  -1 }, CMD_NONE, NULL, NULL }
-};
-
-command_definition_t *
-get_command_definitions(void)
-{
-  return cmds;
-}
-
-char *
-key2str(int key)
-{
-  static char buf[32];
-  int i;
-
-  buf[0] = 0;
-  switch(key)
-    {
-    case 0:
-      return "Undefined";
-    case ' ':
-      return "Space";
-    case 13:
-      return "Enter";
-    case BS:
-      return "Backspace";
-    case DEL:
-      return "Delete";
-    case UP: 
-      return "Up";
-    case DWN:
-      return "Down";
-    case LEFT:
-      return "Left";
-    case RGHT:
-      return "Right";
-    case HOME:
-      return "Home";
-    case END:
-      return "End";
-    case PGDN:
-      return "PageDown";
-    case PGUP:
-      return "PageUp";
-    case TAB: 
-      return "Tab";
-    case STAB:
-      return "Shift+Tab";
-    case ESC:
-      return "Esc";
-    case KEY_IC:
-      return "Insert";
-    default:
-      for(i=0; i<=63; i++)
-       if( key==KEY_F(i) )
-         {
-           snprintf(buf, 32, "F%d", i );
-           return buf;
-         }
-      if( !(key & ~037) )
-       snprintf(buf, 32, "Ctrl-%c", 'A'+(key & 037)-1 );
-      else if( (key & ~037) == 224 )
-       snprintf(buf, 32, "Alt-%c", 'A'+(key & 037)-1 );
-      else if( key>32 &&  key<256 )
-       snprintf(buf, 32, "%c", key);
-      else
-       snprintf(buf, 32, "0x%03X", key);
-    }
-  return buf;
-}
-
-void
-command_dump_keys(void)
-{
-  int i;
-
-  i=0;
-  while( cmds[i].description )
-    {
-      if( cmds[i].command != CMD_NONE )
-       printf(" %20s : %s\n", get_key_names(cmds[i].command,1),cmds[i].name); 
-      i++;
-    }
-}
-
-char *
-get_key_names(command_t command, int all)
-{
-  int i;
-  
-  i=0;
-  while( cmds[i].description )
-    {
-      if( cmds[i].command == command )
-       {
-         int j;
-         static char keystr[80];
-
-         strncpy(keystr, key2str(cmds[i].keys[0]), 80);
-         if( !all )
-           return keystr;
-         j=1;
-         while( j<MAX_COMMAND_KEYS && cmds[i].keys[j]>0 )
-           {
-             strcat(keystr, " ");
-             strcat(keystr, key2str(cmds[i].keys[j]));
-             j++;
-           }
-         return keystr;
-       }
-      i++;
-    }
-  return NULL;
-}
-
-char *
-get_key_description(command_t command)
-{
-  int i;
-
-  i=0;
-  while( cmds[i].description )
-    {
-      if( cmds[i].command == command )
-       return cmds[i].description;
-      i++;
-    }
-  return NULL;
-}
-
-char *
-get_key_command_name(command_t command)
-{
-  int i;
-
-  i=0;
-  while( cmds[i].name )
-    {
-      if( cmds[i].command == command )
-       return cmds[i].name;
-      i++;
-    }
-  return NULL;
-}
-
-command_t 
-get_key_command_from_name(char *name)
-{
-  int i;
-
-  i=0;
-  while( cmds[i].name )
-    {
-      if( strcmp(name, cmds[i].name) == 0 )
-       return cmds[i].command;
-      i++;
-    }
-  return CMD_NONE;
-}
-
-
-command_t 
-find_key_command(int key, command_definition_t *cmds)
-{
-  int i;
-
-  i=0;
-  while( cmds && cmds[i].name )
-    {
-      if( cmds[i].keys[0] == key || 
-         cmds[i].keys[1] == key ||
-         cmds[i].keys[2] == key )
-       return cmds[i].command;
-      i++;
-    }
-  return CMD_NONE;
-}
-
-command_t 
-get_key_command(int key)
-{
-  return find_key_command(key, cmds);
-}
-
-
-command_t
-get_keyboard_command(void)
-{
-  int key;
-
-  key = wgetch(stdscr);
-
-  if( key==KEY_RESIZE )
-    screen_resize();
-
-  if( key==ERR )
-    return CMD_NONE;
-
-  DK(fprintf(stderr, "key = 0x%02X\t", key));
-
-  return get_key_command(key);
-}
-
-int
-assign_keys(command_t command, int keys[MAX_COMMAND_KEYS])
-{
- int i;
-
-  i=0;
-  while( cmds[i].name )
-    {
-      if( cmds[i].command == command )
-       {
-         memcpy(cmds[i].keys, keys, sizeof(int)*MAX_COMMAND_KEYS);
-         return 0;
-       }
-      i++;
-    }
-  return -1;
-}
-
-int 
-check_key_bindings(void)
-{
-  int i;
-  int retval = 0;
-  
-  i=0;
-  while( cmds[i].name )
-    {
-      int j;
-      command_t cmd;
-
-      for(j=0; j<MAX_COMMAND_KEYS; j++)
-       if( cmds[i].keys[j] && 
-           (cmd=get_key_command(cmds[i].keys[j])) != cmds[i].command )
-         {
-           fprintf(stderr, "Error: Key %s assigned to %s and %s !!!\n",
-                   key2str(cmds[i].keys[j]),
-                   get_key_command_name(cmds[i].command),
-                   get_key_command_name(cmd));
-           retval = -1;
-         }
-      i++;
-    }
-  return retval;
-}
-
-int
-write_key_bindings(FILE *f)
-{
-  int i,j;
-
-  i=0;
-  while( cmds[i].name && !ferror(f) )
-    {
-      fprintf(f, "# %s\n", cmds[i].description);
-      fprintf(f, "key %s = ", cmds[i].name);
-      for(j=0; j<MAX_COMMAND_KEYS; j++)
-       {
-         if( j && cmds[i].keys[j] )
-           fprintf(f, ",  ");
-         if( !j || cmds[i].keys[j] )
-           {
-             if( cmds[i].keys[j]<256 && (isalpha(cmds[i].keys[j]) || 
-                                         isdigit(cmds[i].keys[j])) )
-               fprintf(f, "\'%c\'", cmds[i].keys[j]);
-             else
-               fprintf(f, "%d", cmds[i].keys[j]);
-           }
-       }
-      fprintf(f,"\n\n");
-      i++;
-    }
-  return ferror(f);
-}
diff --git a/command.h b/command.h
deleted file mode 100644 (file)
index 1ce67e8..0000000
--- a/command.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef COMMAND_H
-#define COMMAND_H
-
-#define MAX_COMMAND_KEYS 3
-
-typedef enum
-{
-  CMD_NONE = 0,
-  CMD_PLAY,
-  CMD_SELECT,
-  CMD_PAUSE,
-  CMD_STOP,
-  CMD_TRACK_NEXT,
-  CMD_TRACK_PREVIOUS,
-  CMD_SEEK_FORWARD,
-  CMD_SEEK_BACKWARD,
-  CMD_SHUFFLE,
-  CMD_RANDOM,
-  CMD_CLEAR,
-  CMD_DELETE,
-  CMD_REPEAT,
-  CMD_CROSSFADE,
-  CMD_VOLUME_UP,
-  CMD_VOLUME_DOWN,
-  CMD_SAVE_PLAYLIST,
-  CMD_TOGGLE_FIND_WRAP,
-  CMD_TOGGLE_AUTOCENTER,
-  CMD_LIST_PREVIOUS,
-  CMD_LIST_NEXT,
-  CMD_LIST_FIRST,
-  CMD_LIST_LAST,
-  CMD_LIST_NEXT_PAGE,
-  CMD_LIST_PREVIOUS_PAGE,
-  CMD_LIST_FIND,
-  CMD_LIST_FIND_NEXT,
-  CMD_LIST_RFIND,
-  CMD_LIST_RFIND_NEXT,
-  CMD_LIST_MOVE_UP,
-  CMD_LIST_MOVE_DOWN,
-  CMD_SCREEN_UPDATE,
-  CMD_SCREEN_PREVIOUS,
-  CMD_SCREEN_NEXT,
-  CMD_SCREEN_PLAY,
-  CMD_SCREEN_FILE,
-  CMD_SCREEN_SEARCH,
-  CMD_SCREEN_KEYDEF,
-  CMD_SCREEN_HELP,
-  CMD_QUIT
-} command_t;
-
-typedef struct 
-{
-  int keys[MAX_COMMAND_KEYS];
-  command_t command;
-  char *name;
-  char *description;
-} command_definition_t;
-
-command_definition_t *get_command_definitions(void);
-command_t find_key_command(int key, command_definition_t *cmds);
-
-void command_dump_keys(void);
-int  check_key_bindings(void);
-int  write_key_bindings(FILE *f);
-
-char *key2str(int key);
-char *get_key_description(command_t command);
-char *get_key_command_name(command_t command);
-char *get_key_names(command_t command, int all);
-command_t get_key_command(int key);
-command_t get_key_command_from_name(char *name);
-int assign_keys(command_t command, int keys[MAX_COMMAND_KEYS]);
-
-command_t get_keyboard_command(void);
-
-#endif
diff --git a/conf.c b/conf.c
deleted file mode 100644 (file)
index 06866c1..0000000
--- a/conf.c
+++ /dev/null
@@ -1,594 +0,0 @@
-/* 
- * (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 <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-#include "options.h"
-#include "support.h"
-#include "command.h"
-#include "colors.h"
-#include "conf.h"
-
-#ifdef DEBUG
-#define D(x) x
-#else
-#define D(x)
-#endif
-
-#define ENABLE_OLD_COLOR_SYNTAX
-
-#define MAX_LINE_LENGTH 1024
-#define COMMENT_TOKEN   '#'
-
-/* 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"
-
-/* Deprecated - configuration field names */
-#define CONF_COLOR_BACKGROUND        "background_color"
-#define CONF_COLOR_TITLE             "title_color"
-#define CONF_COLOR_LINE              "line_color"
-#define CONF_COLOR_LIST              "list_color"
-#define CONF_COLOR_PROGRESS          "progress_color"
-#define CONF_COLOR_STATUS            "status_color"
-#define CONF_COLOR_ALERT             "alert_color"
-
-
-typedef enum {
-  KEY_PARSER_UNKNOWN,
-  KEY_PARSER_CHAR,
-  KEY_PARSER_DEC,
-  KEY_PARSER_HEX,
-  KEY_PARSER_DONE
-} key_parser_state_t;
-
-static int
-str2bool(char *str)
-{
-  if( !strcasecmp(str,"no")  || !strcasecmp(str,"false") || 
-      !strcasecmp(str,"off") || !strcasecmp(str,"0") )
-    return 0;
-  return 1;
-}
-
-static int
-parse_key_value(char *str, size_t len, char **end)
-{
-  int i, value;
-  key_parser_state_t state;
-
-  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<len )
-       next = str[i+1];
-
-      switch(state)
-       {
-       case KEY_PARSER_UNKNOWN:
-         if( c=='\'' )
-           state = KEY_PARSER_CHAR;
-         else if( c=='0' && next=='x' )
-           state = KEY_PARSER_HEX;
-         else if( isdigit(c) )
-           state = KEY_PARSER_DEC;
-         else {
-           fprintf(stderr, "Error: Unsupported key definition - %s\n", str);
-           return -1;
-         }
-         break;
-       case KEY_PARSER_CHAR:
-         if( next!='\'' )
-           {
-             fprintf(stderr, "Error: Unsupported key definition - %s\n", str);
-             return -1;
-           }
-         value = c;
-         *end = str+i+2;
-         state = KEY_PARSER_DONE;
-         break;
-       case KEY_PARSER_DEC:
-         value = (int) strtol(str+(i-1), end, 10);
-         state = KEY_PARSER_DONE;
-         break;
-       case KEY_PARSER_HEX:
-         if( !isdigit(next) )
-           {
-             fprintf(stderr, "Error: Digit expexted after 0x - %s\n", str);
-             return -1;
-           }
-         value = (int) strtol(str+(i+1), end, 16);
-         state = KEY_PARSER_DONE;
-         break;
-       case KEY_PARSER_DONE:
-         break;
-       }
-      i++;
-    }
-
-  if( *end> str+len )
-    *end = str+len;
-
-  return value;
-}
-
-static int
-parse_key_definition(char *str)
-{
-  char buf[MAX_LINE_LENGTH];
-  char *p, *end;
-  size_t len = strlen(str);
-  int i,j,key;
-  int keys[MAX_COMMAND_KEYS];
-  command_t cmd;
-
-  /* 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++];
-  if( (cmd=get_key_command_from_name(buf)) == CMD_NONE )
-    {
-      fprintf(stderr, "Error: Unknown key command %s\n", buf);
-      return -1;
-    }
-
-  /* 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 key definition - %s\n", 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 )
-    {
-      keys[i++] = key;
-      while( p<end && (*p==',' || *p==' ' || *p=='\t') )
-       p++;
-      len = strlen(p);
-    } 
-  if( key<0 )
-    {
-      fprintf(stderr,"Error: Bad key definition - %s\n", str);
-      return -1;
-    }
-
-  return assign_keys(cmd, keys);
-}
-
-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 free_filename = 0;
-
-  if( filename==NULL )
-    return -1;
-
-  D(printf("Reading configuration file %s\n", filename));
-  if( (fd=open(filename,O_RDONLY)) <0 )
-    {
-      perror(filename);
-      if( free_filename )
-       g_free(filename);
-      return -1;
-    }
-
-  while( !quit )
-    {
-      int i,j;
-      int len;
-      int match_found;
-      char line[MAX_LINE_LENGTH];
-      char name[MAX_LINE_LENGTH];
-      char value[MAX_LINE_LENGTH];
-
-      line[0]  = '\0';
-      value[0] = '\0';
-
-      i = 0;
-      /* read a line ending with '\n' */
-      do {
-       len = read( fd, &line[i], 1 );
-       if( len == 1 )
-         i++;
-       else
-         quit = 1;
-      } while( !quit && i<MAX_LINE_LENGTH && line[i-1]!='\n' );
-      
-     
-      /* remove trailing whitespace */
-      line[i] = '\0';
-      i--;
-      while( i>=0 && IS_WHITESPACE(line[i]) )
-       {
-         line[i] = '\0';
-         i--;
-       }     
-      len = i+1;
-
-      if( len>0 )
-       {
-         i = 0;
-         /* skip whitespace */
-         while( i<len && IS_WHITESPACE(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]!='=' && !IS_WHITESPACE(line[i]) )
-               {
-                 name[j++] = line[i++];
-               }
-             name[j] = '\0';
-             
-             /* skip '=' and whitespace */
-             while( i<len && (line[i]=='=' || IS_WHITESPACE(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) )
-               {
-                 options->enable_colors = str2bool(value);
-               }
-             /* auto center */
-             else if( !strcasecmp(CONF_AUTO_CENTER, name) )
-               {
-                 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) )
-               {
-                 fprintf(stderr,"%s: %s - deprecated!\n", filename,name);
-                 colors_assign("background", value);
-               }
-             /* color - top (title) window */
-             else if( !strcasecmp(CONF_COLOR_TITLE, name) )
-               {
-                 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) )
-               {
-                 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) )
-               {
-                 fprintf(stderr,"%s: %s - deprecated!\n", filename,name);
-                 colors_assign("list", value);
-               }
-             /* color - progress bar */
-             else if( !strcasecmp(CONF_COLOR_PROGRESS, name) )
-               {
-                 fprintf(stderr,"%s: %s - deprecated!\n", filename,name);
-                 colors_assign("progressbar", value);
-               }
-             /* color - status window */
-             else if( !strcasecmp(CONF_COLOR_STATUS, name) )
-               {
-                 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) )
-               {
-                 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;
-               }
-             
-
-             if( !match_found )
-               fprintf(stderr, 
-                       "Unknown configuration parameter: %s\n", 
-                       name);
-#ifdef DEBUG
-             printf( "  %s = %s %s\n", 
-                     name, 
-                     value,
-                     match_found ? "" : "- UNKNOWN SETTING!" );
-#endif
-
-           }
-       }         
-    }
-
-  D(printf( "--\n\n" ));
-
-  if( free_filename )
-    g_free(filename);
-  return 0;
-}
-
-int
-check_user_conf_dir(void)
-{
-  int retval;
-  char *dirname = g_build_filename(g_get_home_dir(), "." PACKAGE, NULL);
-  
-  if( g_file_test(dirname, G_FILE_TEST_IS_DIR) )
-    {
-      g_free(dirname);
-      return 0;
-    }
-  retval = mkdir(dirname, 0755);
-  g_free(dirname);
-  return retval;
-}
-
-char *
-get_user_key_binding_filename(void)
-{
-  return g_build_filename(g_get_home_dir(), "." PACKAGE, "keys", NULL);
-}
-
-
-int
-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 */
-  if( 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 */
-  if( filename == NULL )
-    {
-      filename = g_build_filename(SYSCONFDIR, PACKAGE, "config", NULL);
-      if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
-       {
-         g_free(filename);
-         filename = NULL;
-       }
-    }
-
-  /* load configuration */
-  if( filename )
-    {
-      read_rc_file(filename, options);
-      g_free(filename);
-      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 */
-  if( 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 */
-  if( filename == NULL )
-    {
-      filename = g_build_filename(SYSCONFDIR, PACKAGE, "keys", NULL);
-      if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
-       {
-         g_free(filename);
-         filename = NULL;
-       }
-    }
-
-  /* load key bindings */
-  if( filename )
-    {
-      read_rc_file(filename, options);
-      g_free(filename);
-      filename = NULL;
-    }
-
-  return 0;
-}
-
-
-
diff --git a/conf.h b/conf.h
deleted file mode 100644 (file)
index 20b4f5e..0000000
--- a/conf.h
+++ /dev/null
@@ -1,7 +0,0 @@
-
-int check_user_conf_dir(void);
-
-char *get_user_key_binding_filename(void);
-
-int read_configuration(options_t *options);
-
index 87dbc6a529553340b4c38b235cfc36ddd43d6b7b..d1601f9c83b2fe6f5ee91198190034e0676be0f6 100644 (file)
@@ -3,8 +3,8 @@ dnl  $Id$
 dnl
 
 AC_INIT
-AC_CONFIG_SRCDIR([main.c])
-AM_INIT_AUTOMAKE(ncmpc, 0.10.2-svn)
+AC_CONFIG_SRCDIR([src/main.c])
+AM_INIT_AUTOMAKE(ncmpc, 0.11.0-svn)
 
 dnl Check for programs
 AC_PROG_CC
@@ -96,9 +96,9 @@ AC_ARG_WITH(default-host,
 
 dnl Default port
 AC_ARG_WITH(default-port,
-            AC_HELP_STRING(--with-default-port=ARG,Default port (2100)),
+            AC_HELP_STRING(--with-default-port=ARG,Default port (6600)),
             DEFAULT_PORT="$withval",
-            DEFAULT_PORT="2100")
+            DEFAULT_PORT="6600")
 
 
 CFLAGS="$CFLAGS $GLIB_CFLAGS -DSYSCONFDIR=\\\"\$(sysconfdir)\\\""
@@ -112,7 +112,7 @@ AC_DEFINE_UNQUOTED(DEFAULT_HOST,     "$DEFAULT_HOST",    Default MPD host)
 
 AM_CONFIG_HEADER(config.h)
 
-AC_CONFIG_FILES([doc/Makefile Makefile])
+AC_CONFIG_FILES([doc/Makefile src/Makefile Makefile])
 AC_OUTPUT
 
 echo "
diff --git a/libmpdclient.c b/libmpdclient.c
deleted file mode 100644 (file)
index aa7b757..0000000
+++ /dev/null
@@ -1,1180 +0,0 @@
-/* libmpdclient
- * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
- * This project's homepage is: http://www.musicpd.org
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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 "libmpdclient.h"
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <sys/param.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#ifndef HAVE_SOCKLEN_T
-typedef SOCKLEN_T socklen_t;
-#endif
-#endif
-
-#ifndef MPD_NO_IPV6
-#ifdef AF_INET6
-#define MPD_HAVE_IPV6
-#endif
-#endif
-
-#ifdef MPD_HAVE_IPV6        
-int mpd_ipv6Supported() {
-        int s;          
-        s = socket(AF_INET6,SOCK_STREAM,0);
-        if(s == -1) return 0;
-        close(s);       
-        return 1;                       
-}                       
-#endif  
-
-
-char * mpd_sanitizeArg(const char * arg) {
-       size_t i;
-       int count=0;
-       char * ret;
-
-       for(i=0;i<strlen(arg);i++) {
-               if(arg[i]=='"' || arg[i]=='\\') count++;
-       }
-
-       ret = malloc(strlen(arg)+count+1);
-
-       count = 0;
-       for(i=0;i<strlen(arg)+1;i++) {
-               if(arg[i]=='"' || arg[i]=='\\') {
-                       ret[i+count] = '\\';
-                       count++;
-               }
-               ret[i+count] = arg[i];
-       }
-
-       return ret;
-}
-
-mpd_ReturnElement * mpd_newReturnElement(const char * name, const char * value)
-{
-       mpd_ReturnElement * ret = malloc(sizeof(mpd_ReturnElement));
-
-       ret->name = strdup(name);
-       ret->value = strdup(value);
-
-       return ret;
-}
-
-void mpd_freeReturnElement(mpd_ReturnElement * re) {
-       free(re->name);
-       free(re->value);
-       free(re);
-}
-
-void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout) {
-               connection->timeout.tv_sec = (int)timeout;
-               connection->timeout.tv_usec = (int)(timeout*1e6 -
-                               connection->timeout.tv_sec*1000000+0.5);
-}
-
-mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
-       int err;
-       struct hostent * he;
-       struct sockaddr * dest;
-       socklen_t destlen;
-       struct sockaddr_in sin;
-       char * rt;
-       char * output;
-       mpd_Connection * connection = malloc(sizeof(mpd_Connection));
-       struct timeval tv;
-       fd_set fds;
-#ifdef MPD_HAVE_IPV6
-       struct sockaddr_in6 sin6;
-#endif
-       strcpy(connection->buffer,"");
-       connection->buflen = 0;
-       connection->bufstart = 0;
-       strcpy(connection->errorStr,"");
-       connection->error = 0;
-       connection->doneProcessing = 0;
-       connection->commandList = 0;
-       connection->returnElement = NULL;
-
-       if(!(he=gethostbyname(host))) {
-               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                               "host \"%s\" not found",host);
-               connection->error = MPD_ERROR_UNKHOST;
-               return connection;
-       }
-
-       memset(&sin,0,sizeof(struct sockaddr_in));
-       /*dest.sin_family = he->h_addrtype;*/
-       sin.sin_family = AF_INET;
-       sin.sin_port = htons(port);
-#ifdef MPD_HAVE_IPV6
-       memset(&sin6,0,sizeof(struct sockaddr_in6));
-       sin6.sin6_family = AF_INET6;
-       sin6.sin6_port = htons(port);
-#endif
-       switch(he->h_addrtype) {
-       case AF_INET:
-               memcpy((char *)&sin.sin_addr.s_addr,(char *)he->h_addr,
-                               he->h_length);
-               dest = (struct sockaddr *)&sin;
-               destlen = sizeof(struct sockaddr_in);
-               break;
-#ifdef MPD_HAVE_IPV6
-       case AF_INET6:
-               if(!mpd_ipv6Supported()) {
-                       strcpy(connection->errorStr,"no IPv6 suuport but a "
-                                       "IPv6 address found\n");
-                       connection->error = MPD_ERROR_SYSTEM;
-                       return connection;
-               }
-               memcpy((char *)&sin6.sin6_addr.s6_addr,(char *)he->h_addr,
-                               he->h_length);
-               dest = (struct sockaddr *)&sin6;
-               destlen = sizeof(struct sockaddr_in6);
-               break;
-#endif
-       default:
-               strcpy(connection->errorStr,"address type is not IPv4 or "
-                               "IPv6\n");
-               connection->error = MPD_ERROR_SYSTEM;
-               return connection;
-               break;
-       }
-       
-       if((connection->sock = socket(dest->sa_family,SOCK_STREAM,0))<0) {
-               strcpy(connection->errorStr,"problems creating socket");
-               connection->error = MPD_ERROR_SYSTEM;
-               return connection;
-       }
-
-       /* connect stuff */
-       {
-#ifdef SO_RCVTIMEO
-               struct timeval rcvoldto;
-               struct timeval sndoldto;
-               socklen_t oldlen = sizeof(struct timeval);
-
-               mpd_setConnectionTimeout(connection,timeout);
-
-               tv.tv_sec = connection->timeout.tv_sec;
-               tv.tv_usec = connection->timeout.tv_usec;
-
-               if(getsockopt(connection->sock,SOL_SOCKET,SO_RCVTIMEO,&rcvoldto,
-                                       &oldlen)<0 ||
-                               getsockopt(connection->sock,SOL_SOCKET,
-                                       SO_SNDTIMEO,&sndoldto,&oldlen)<0)
-               {
-                       strcpy(connection->errorStr,"problems getting socket "
-                                       "timeout\n");
-                       connection->error = MPD_ERROR_SYSTEM;
-                       return connection;
-               }
-               if(setsockopt(connection->sock,SOL_SOCKET,SO_RCVTIMEO,&tv,
-                                       sizeof(struct timeval))<0 ||
-                               setsockopt(connection->sock,SOL_SOCKET,
-                                       SO_SNDTIMEO,&tv,
-                                       sizeof(struct timeval))<0)
-               {
-                       strcpy(connection->errorStr,"problems setting socket "
-                                       "timeout\n");
-                       connection->error = MPD_ERROR_SYSTEM;
-                       return connection;
-               }
-#endif
-               if(connect(connection->sock,dest,destlen)<0) {
-                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                                       "problems connecting to \"%s\" on port"
-                                       " %i",host,port);
-                       connection->error = MPD_ERROR_CONNPORT;
-                       return connection;
-               }
-#ifdef SO_RCVTIMEO
-               if(setsockopt(connection->sock,SOL_SOCKET,SO_SNDTIMEO,&rcvoldto,
-                                       sizeof(struct timeval))<0 ||
-                               setsockopt(connection->sock,SOL_SOCKET,
-                                       SO_SNDTIMEO,&sndoldto,
-                                       sizeof(struct timeval))<0)
-               {
-                       strcpy(connection->errorStr,"problems setting socket "
-                                       "timeout\n");
-                       connection->error = MPD_ERROR_SYSTEM;
-                       return connection;
-               }
-#endif
-       }
-
-       while(!(rt = strstr(connection->buffer,"\n"))) {
-               tv.tv_sec = connection->timeout.tv_sec;
-               tv.tv_usec = connection->timeout.tv_usec;
-               FD_ZERO(&fds);
-               FD_SET(connection->sock,&fds);
-               if((err = select(connection->sock+1,&fds,NULL,NULL,&tv)) == 1) {
-                       int readed;
-                       readed = recv(connection->sock,
-                               &(connection->buffer[connection->buflen]),
-                               MPD_BUFFER_MAX_LENGTH-connection->buflen,0);
-                       if(readed<=0) {
-                               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                                       "problems getting a response from"
-                                       " \"%s\" on port %i",host,
-                                       port);
-                               connection->error = MPD_ERROR_NORESPONSE;
-                               return connection;
-                       }
-                       connection->buflen+=readed;
-                       connection->buffer[connection->buflen] = '\0';
-                       tv.tv_sec = connection->timeout.tv_sec;
-                       tv.tv_usec = connection->timeout.tv_usec;
-               }
-               else if(err<0 && errno==EINTR) continue;
-               else {
-                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                               "timeout in attempting to get a response from"
-                                " \"%s\" on port %i",host,port);
-                       connection->error = MPD_ERROR_NORESPONSE;
-                       return connection;
-               }
-       }
-
-       *rt = '\0';
-       output = strdup(connection->buffer);
-       strcpy(connection->buffer,rt+1);
-       connection->buflen = strlen(connection->buffer);
-
-       if(strncmp(output,MPD_WELCOME_MESSAGE,strlen(MPD_WELCOME_MESSAGE))) {
-               free(output);
-               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                               "mpd not running on port %i on host \"%s\"",
-                               port,host);
-               connection->error = MPD_ERROR_NOTMPD;
-               return connection;
-       }
-
-       {
-               char * test;
-               char * version[3];
-               char * tmp = &output[strlen(MPD_WELCOME_MESSAGE)];
-               char * search = ".";
-               int i;
-
-               for(i=0;i<3;i++) {
-                       char * tok;
-                       if(i==3) search = " ";
-                       version[i] = strtok_r(tmp,search,&tok);
-                       if(!version[i]) {
-                               free(output);
-                               snprintf(connection->errorStr,
-                                       MPD_BUFFER_MAX_LENGTH,
-                                       "error parsing version number at "
-                                       "\"%s\"",
-                                       &output[strlen(MPD_WELCOME_MESSAGE)]);
-                               connection->error = MPD_ERROR_NOTMPD;
-                               return connection;
-                       }
-                       connection->version[i] = strtol(version[i],&test,10);
-                       if(version[i]==test || *test!='\0') {
-                               free(output);
-                               snprintf(connection->errorStr,
-                                       MPD_BUFFER_MAX_LENGTH,
-                                       "error parsing version number at "
-                                       "\"%s\"",
-                                       &output[strlen(MPD_WELCOME_MESSAGE)]);
-                               connection->error = MPD_ERROR_NOTMPD;
-                               return connection;
-                       }
-                       tmp = NULL;
-               }
-       }
-
-       free(output);
-
-       connection->doneProcessing = 1;
-
-       return connection;
-}
-
-void mpd_clearError(mpd_Connection * connection) {
-       connection->error = 0;
-       connection->errorStr[0] = '\0';
-}
-
-void mpd_closeConnection(mpd_Connection * connection) {
-       close(connection->sock);
-       if(connection->returnElement) free(connection->returnElement);
-       free(connection);
-}
-
-void mpd_executeCommand(mpd_Connection * connection, char * command) {
-       int ret;
-       struct timeval tv;
-       fd_set fds;
-       char * commandPtr = command;
-       int commandLen = strlen(command);
-
-       if(!connection->doneProcessing && !connection->commandList) {
-               strcpy(connection->errorStr,"not done processing current command");
-               connection->error = 1;
-               return;
-       }
-
-       mpd_clearError(connection);
-
-       FD_ZERO(&fds);
-       FD_SET(connection->sock,&fds);
-       tv.tv_sec = connection->timeout.tv_sec;
-       tv.tv_usec = connection->timeout.tv_usec;
-
-       while((ret = select(connection->sock+1,NULL,&fds,NULL,&tv)==1) || 
-                       (ret==-1 && errno==EINTR)) {
-               ret = send(connection->sock,commandPtr,commandLen,
-                               MSG_DONTWAIT);
-               if(ret<=0)
-               {
-                       if(ret==EAGAIN || ret==EINTR) continue;
-                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                               "problems giving command \"%s\"",command);
-                       connection->error = MPD_ERROR_SENDING;
-                       return;
-               }
-               else {
-                       commandPtr+=ret;
-                       commandLen-=ret;
-               }
-
-               if(commandLen<=0) break;
-       }
-
-       if(commandLen>0) {
-               perror("");
-               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                       "timeout sending command \"%s\"",command);
-               connection->error = MPD_ERROR_TIMEOUT;
-               return;
-       }
-
-       if(!connection->commandList) connection->doneProcessing = 0;
-}
-
-void mpd_getNextReturnElement(mpd_Connection * connection) {
-       char * output = NULL;
-       char * rt = NULL;
-       char * name;
-       char * value;
-       fd_set fds;
-       struct timeval tv;
-       char * tok;
-       int readed;
-       char * bufferCheck;
-       int err;
-
-       if(connection->returnElement) mpd_freeReturnElement(connection->returnElement);
-       connection->returnElement = NULL;
-
-       if(connection->doneProcessing) {
-               strcpy(connection->errorStr,"already done processing current command");
-               connection->error = 1;
-               return;
-       }
-
-       bufferCheck = connection->buffer+connection->bufstart;
-       while(connection->bufstart>=connection->buflen || 
-                       !(rt = strstr(bufferCheck,"\n"))) {
-               if(connection->buflen>=MPD_BUFFER_MAX_LENGTH) {
-                       memmove(connection->buffer,
-                                       connection->buffer+
-                                       connection->bufstart,
-                                       connection->buflen-
-                                       connection->bufstart+1);
-                       bufferCheck-=connection->bufstart;
-                       connection->buflen-=connection->bufstart;
-                       connection->bufstart = 0;
-               }
-               if(connection->buflen>=MPD_BUFFER_MAX_LENGTH) {
-                       strcpy(connection->errorStr,"buffer overrun");
-                       connection->error = MPD_ERROR_BUFFEROVERRUN;
-                       connection->doneProcessing = 1;
-                       return;
-               }
-               bufferCheck+=connection->buflen-connection->bufstart;
-               tv.tv_sec = connection->timeout.tv_sec;
-               tv.tv_usec = connection->timeout.tv_usec;
-               FD_ZERO(&fds);
-               FD_SET(connection->sock,&fds);
-               if((err = select(connection->sock+1,&fds,NULL,NULL,&tv) == 1)) {
-                       readed = recv(connection->sock,
-                               connection->buffer+connection->buflen,
-                               MPD_BUFFER_MAX_LENGTH-connection->buflen,
-                               MSG_DONTWAIT);
-                       if(readed<0 && (errno==EAGAIN || errno==EINTR)) {
-                               continue;
-                       }
-                       if(readed<=0) {
-                               strcpy(connection->errorStr,"connection"
-                                       " closed");
-                               connection->error = MPD_ERROR_CONNCLOSED;
-                               connection->doneProcessing = 1;
-                               return;
-                       }
-                       connection->buflen+=readed;
-                       connection->buffer[connection->buflen] = '\0';
-               }
-               else if(err<0 && errno==EINTR) continue;
-               else {
-                       strcpy(connection->errorStr,"connection timeout");
-                       connection->error = MPD_ERROR_TIMEOUT;
-                       connection->doneProcessing = 1;
-                       return;
-               }
-       }
-
-       *rt = '\0';
-       output = connection->buffer+connection->bufstart;
-       connection->bufstart = rt - connection->buffer + 1;
-
-       if(strcmp(output,"OK")==0) {
-               connection->doneProcessing = 1;
-               return;
-       }
-       if(strncmp(output,"ACK",strlen("ACK"))==0) {
-               strcpy(connection->errorStr,output);
-               connection->error = MPD_ERROR_ACK;
-               connection->doneProcessing = 1;
-               return;
-       }
-
-       name = strtok_r(output,":",&tok);
-       if(name && (value = strtok_r(NULL,"",&tok)) && value[0]==' ') {
-               connection->returnElement = mpd_newReturnElement(name,&(value[1]));
-       }
-       else {
-               if(!name || !value) {
-                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                                       "error parsing: %s",output);
-               }
-               else {
-                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
-                                       "error parsing: %s:%s",name,value);
-               }
-               connection->errorStr[MPD_BUFFER_MAX_LENGTH] = '\0';
-               connection->error = 1;
-       }
-}
-
-void mpd_finishCommand(mpd_Connection * connection) {
-       while(!connection->doneProcessing) mpd_getNextReturnElement(connection);
-}
-
-
-mpd_Status * mpd_getStatus(mpd_Connection * connection) {
-       mpd_Status * status;
-
-       mpd_executeCommand(connection,"status\n");
-               
-       if(connection->error) return NULL;
-
-       status = malloc(sizeof(mpd_Status));
-       status->volume = -1;
-       status->repeat = 0;
-       status->random = 0;
-       status->playlist = -1;
-       status->playlistLength = -1;
-       status->state = -1;
-       status->song = 0;
-       status->elapsedTime = 0;
-       status->totalTime = 0;
-       status->bitRate = 0;
-       status->sampleRate = 0;
-       status->bits = 0;
-       status->channels = 0;
-       status->crossfade = -1;
-       status->error = NULL;
-
-       mpd_getNextReturnElement(connection);
-       if(connection->error) {
-               free(status);
-               return NULL;
-       }
-       while(connection->returnElement) {
-               mpd_ReturnElement * re = connection->returnElement;
-               if(strcmp(re->name,"volume")==0) {
-                       status->volume = atoi(re->value);
-               }
-               else if(strcmp(re->name,"repeat")==0) {
-                       status->repeat = atoi(re->value);
-               }
-               else if(strcmp(re->name,"random")==0) {
-                       status->random = atoi(re->value);
-               }
-               else if(strcmp(re->name,"playlist")==0) {
-                       status->playlist = strtol(re->value,NULL,10);
-               }
-               else if(strcmp(re->name,"playlistlength")==0) {
-                       status->playlistLength = atoi(re->value);
-               }
-               else if(strcmp(re->name,"bitrate")==0) {
-                       status->bitRate = atoi(re->value);
-               }
-               else if(strcmp(re->name,"state")==0) {
-                       if(strcmp(re->value,"play")==0) {
-                               status->state = MPD_STATUS_STATE_PLAY;
-                       }
-                       else if(strcmp(re->value,"stop")==0) {
-                               status->state = MPD_STATUS_STATE_STOP;
-                       }
-                       else if(strcmp(re->value,"pause")==0) {
-                               status->state = MPD_STATUS_STATE_PAUSE;
-                       }
-                       else {
-                               status->state = MPD_STATUS_STATE_UNKNOWN;
-                       }
-               }
-               else if(strcmp(re->name,"song")==0) {
-                       status->song = atoi(re->value);
-               }
-               else if(strcmp(re->name,"time")==0) {
-                       char * tok;
-                       char * copy;
-                       copy = strdup(re->value);
-                       status->elapsedTime = atoi(strtok_r(copy,":",&tok));
-                       status->totalTime = atoi(strtok_r(NULL,"",&tok));
-                       free(copy);
-               }
-               else if(strcmp(re->name,"error")==0) {
-                       status->error = strdup(re->value);
-               }
-               else if(strcmp(re->name,"xfade")==0) {
-                       status->crossfade = atoi(re->value);
-               }
-               else if(strcmp(re->name,"audio")==0) {
-                       char * tok;
-                       char * copy;
-                       copy = strdup(re->value);
-                       status->sampleRate = atoi(strtok_r(copy,":",&tok));
-                       status->bits = atoi(strtok_r(NULL,":",&tok));
-                       status->channels = atoi(strtok_r(NULL,"",&tok));
-                       free(copy);
-               }
-
-               mpd_getNextReturnElement(connection);
-               if(connection->error) {
-                       free(status);
-                       return NULL;
-               }
-       }
-
-       if(connection->error) {
-               free(status);
-               return NULL;
-       }
-       else if(status->state<0) {
-               strcpy(connection->errorStr,"state not found");
-               connection->error = 1;
-               free(status);
-               return NULL;
-       }
-
-       return status;
-}
-
-void mpd_freeStatus(mpd_Status * status) {
-       if(status->error) free(status->error);
-       free(status);
-}
-
-mpd_Stats * mpd_getStats(mpd_Connection * connection) {
-       mpd_Stats * stats;
-
-       mpd_executeCommand(connection,"stats\n");
-               
-       if(connection->error) return NULL;
-
-       stats = malloc(sizeof(mpd_Stats));
-       stats->numberOfArtists = 0;
-       stats->numberOfAlbums = 0;
-       stats->numberOfSongs = 0;
-       stats->uptime = 0;
-       stats->dbUpdateTime = 0;
-       stats->playTime = 0;
-       stats->dbPlayTime = 0;
-
-       mpd_getNextReturnElement(connection);
-       if(connection->error) {
-               free(stats);
-               return NULL;
-       }
-       while(connection->returnElement) {
-               mpd_ReturnElement * re = connection->returnElement;
-               if(strcmp(re->name,"artists")==0) {
-                       stats->numberOfArtists = atoi(re->value);
-               }
-               else if(strcmp(re->name,"albums")==0) {
-                       stats->numberOfAlbums = atoi(re->value);
-               }
-               else if(strcmp(re->name,"songs")==0) {
-                       stats->numberOfSongs = atoi(re->value);
-               }
-               else if(strcmp(re->name,"uptime")==0) {
-                       stats->uptime = strtol(re->value,NULL,10);
-               }
-               else if(strcmp(re->name,"db_update")==0) {
-                       stats->dbUpdateTime = strtol(re->value,NULL,10);
-               }
-               else if(strcmp(re->name,"playtime")==0) {
-                       stats->playTime = strtol(re->value,NULL,10);
-               }
-               else if(strcmp(re->name,"db_playtime")==0) {
-                       stats->dbPlayTime = strtol(re->value,NULL,10);
-               }
-
-               mpd_getNextReturnElement(connection);
-               if(connection->error) {
-                       free(stats);
-                       return NULL;
-               }
-       }
-
-       if(connection->error) {
-               free(stats);
-               return NULL;
-       }
-
-       return stats;
-}
-
-void mpd_freeStats(mpd_Stats * stats) {
-       free(stats);
-}
-
-void mpd_initSong(mpd_Song * song) {
-       song->file = NULL;
-       song->artist = NULL;
-       song->album = NULL;
-       song->track = NULL;
-       song->title = NULL;
-       song->time = MPD_SONG_NO_TIME;
-}
-
-void mpd_finishSong(mpd_Song * song) {
-       if(song->file) free(song->file);
-       if(song->artist) free(song->artist);
-       if(song->album) free(song->album);
-       if(song->title) free(song->title);
-       if(song->track) free(song->track);
-}
-
-mpd_Song * mpd_newSong() {
-       mpd_Song * ret = malloc(sizeof(mpd_Song));
-
-       mpd_initSong(ret);
-
-       return ret;
-}
-
-void mpd_freeSong(mpd_Song * song) {
-       mpd_finishSong(song);
-       free(song);
-}
-
-mpd_Song * mpd_songDup(mpd_Song * song) {
-       mpd_Song * ret = mpd_newSong();
-
-       if(song->file) ret->file = strdup(song->file);
-       if(song->artist) ret->artist = strdup(song->artist);
-       if(song->album) ret->album = strdup(song->album);
-       if(song->title) ret->title = strdup(song->title);
-       if(song->track) ret->track = strdup(song->track);
-       ret->time = song->time;
-
-       return ret;
-}
-
-void mpd_initDirectory(mpd_Directory * directory) {
-       directory->path = NULL;
-}
-
-void mpd_finishDirectory(mpd_Directory * directory) {
-       if(directory->path) free(directory->path);
-}
-
-mpd_Directory * mpd_newDirectory () {
-       mpd_Directory * directory = malloc(sizeof(mpd_Directory));;
-
-       mpd_initDirectory(directory);
-       
-       return directory;
-}
-
-void mpd_freeDirectory(mpd_Directory * directory) {
-       mpd_finishDirectory(directory);
-
-       free(directory);
-}
-
-mpd_Directory * mpd_directoryDup(mpd_Directory * directory) {
-       mpd_Directory * ret = mpd_newDirectory();
-
-       if(directory->path) ret->path = strdup(directory->path);
-
-       return ret;
-}
-
-void mpd_initPlaylistFile(mpd_PlaylistFile * playlist) {
-       playlist->path = NULL;
-}
-
-void mpd_finishPlaylistFile(mpd_PlaylistFile * playlist) {
-       if(playlist->path) free(playlist->path);
-}
-
-mpd_PlaylistFile * mpd_newPlaylistFile() {
-       mpd_PlaylistFile * playlist = malloc(sizeof(mpd_PlaylistFile));
-
-       mpd_initPlaylistFile(playlist);
-
-       return playlist;
-}
-
-void mpd_freePlaylistFile(mpd_PlaylistFile * playlist) {
-       mpd_finishPlaylistFile(playlist);
-       free(playlist);
-}
-
-mpd_PlaylistFile * mpd_playlistFileDup(mpd_PlaylistFile * playlist) {
-       mpd_PlaylistFile * ret = mpd_newPlaylistFile();
-
-       if(playlist->path) ret->path = strdup(playlist->path);
-
-       return ret;
-}
-
-void mpd_initInfoEntity(mpd_InfoEntity * entity) {
-       entity->info.directory = NULL;
-} 
-
-void mpd_finishInfoEntity(mpd_InfoEntity * entity) {
-       if(entity->info.directory) {
-               if(entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) {
-                       mpd_freeDirectory(entity->info.directory);
-               }
-               else if(entity->type == MPD_INFO_ENTITY_TYPE_SONG) {
-                       mpd_freeSong(entity->info.song);
-               }
-               else if(entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) {
-                       mpd_freePlaylistFile(entity->info.playlistFile);
-               }
-       }
-}
-
-mpd_InfoEntity * mpd_newInfoEntity() {
-       mpd_InfoEntity * entity = malloc(sizeof(mpd_InfoEntity));
-       
-       mpd_initInfoEntity(entity);
-
-       return entity;
-}
-
-void mpd_freeInfoEntity(mpd_InfoEntity * entity) {
-       mpd_finishInfoEntity(entity);
-       free(entity);
-}
-
-void mpd_sendInfoCommand(mpd_Connection * connection, char * command) {
-       mpd_executeCommand(connection,command);
-}
-
-mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection) {
-       mpd_InfoEntity * entity = NULL;
-
-       if(connection->doneProcessing) return NULL;
-
-       if(!connection->returnElement) mpd_getNextReturnElement(connection);
-
-       if(connection->returnElement) { 
-               if(strcmp(connection->returnElement->name,"file")==0) {
-                       entity = mpd_newInfoEntity();
-                       entity->type = MPD_INFO_ENTITY_TYPE_SONG;
-                       entity->info.song = mpd_newSong();
-                       entity->info.song->file = 
-                               strdup(connection->returnElement->value);
-               }
-               else if(strcmp(connection->returnElement->name,
-                                       "directory")==0) {
-                       entity = mpd_newInfoEntity();
-                       entity->type = MPD_INFO_ENTITY_TYPE_DIRECTORY;
-                       entity->info.directory = mpd_newDirectory();
-                       entity->info.directory->path = 
-                               strdup(connection->returnElement->value);
-               }
-               else if(strcmp(connection->returnElement->name,"playlist")==0) {
-                       entity = mpd_newInfoEntity();
-                       entity->type = MPD_INFO_ENTITY_TYPE_PLAYLISTFILE;
-                       entity->info.playlistFile = mpd_newPlaylistFile();
-                       entity->info.playlistFile->path = 
-                               strdup(connection->returnElement->value);
-               }
-               else {
-                       connection->error = 1;
-                       strcpy(connection->errorStr,"problem parsing song info");
-                       return NULL;
-               }
-       }
-       else return NULL;
-
-       mpd_getNextReturnElement(connection);
-       while(connection->returnElement) {
-               mpd_ReturnElement * re = connection->returnElement;
-
-               if(strcmp(re->name,"file")==0) return entity;
-               else if(strcmp(re->name,"directory")==0) return entity;
-               else if(strcmp(re->name,"playlist")==0) return entity;
-
-               if(entity->type == MPD_INFO_ENTITY_TYPE_SONG && 
-                               strlen(re->value)) {
-                       if(!entity->info.song->artist &&
-                                       strcmp(re->name,"Artist")==0) {
-                               entity->info.song->artist = strdup(re->value);
-                       }
-                       else if(!entity->info.song->album &&
-                                       strcmp(re->name,"Album")==0) {
-                               entity->info.song->album = strdup(re->value);
-                       }
-                       else if(!entity->info.song->title &&
-                                       strcmp(re->name,"Title")==0) {
-                               entity->info.song->title = strdup(re->value);
-                       }
-                       else if(!entity->info.song->track &&
-                                       strcmp(re->name,"Track")==0) {
-                               entity->info.song->track = strdup(re->value);
-                       }
-                       else if(entity->info.song->time==MPD_SONG_NO_TIME &&
-                                       strcmp(re->name,"Time")==0) {
-                               entity->info.song->time = atoi(re->value);
-                       }
-               }
-               else if(entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) {
-               }
-               else if(entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) {
-               }
-
-               mpd_getNextReturnElement(connection);
-       }
-
-       return entity;
-}
-
-char * mpd_getNextReturnElementNamed(mpd_Connection * connection, 
-               const char * name) 
-{
-       if(connection->doneProcessing) return NULL;
-
-       mpd_getNextReturnElement(connection);
-       while(connection->returnElement) {
-               mpd_ReturnElement * re = connection->returnElement;
-
-               if(strcmp(re->name,name)==0) return strdup(re->value);
-               mpd_getNextReturnElement(connection);
-       }
-
-       return NULL;
-}
-
-char * mpd_getNextArtist(mpd_Connection * connection) {
-       return mpd_getNextReturnElementNamed(connection,"Artist");
-}
-
-char * mpd_getNextAlbum(mpd_Connection * connection) {
-       return mpd_getNextReturnElementNamed(connection,"Album");
-}
-
-void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum) {
-       char * string = malloc(strlen("playlistinfo")+25);
-       sprintf(string,"playlistinfo \"%i\"\n",songNum);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendListallCommand(mpd_Connection * connection, const char * dir) {
-       char * sDir = mpd_sanitizeArg(dir);
-       char * string = malloc(strlen("listall")+strlen(sDir)+5);
-       sprintf(string,"listall \"%s\"\n",sDir);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-       free(sDir);
-}
-
-void mpd_sendListallInfoCommand(mpd_Connection * connection, const char * dir) {
-       char * sDir = mpd_sanitizeArg(dir);
-       char * string = malloc(strlen("listallinfo")+strlen(sDir)+5);
-       sprintf(string,"listallinfo \"%s\"\n",sDir);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-       free(sDir);
-}
-
-void mpd_sendLsInfoCommand(mpd_Connection * connection, const char * dir) {
-       char * sDir = mpd_sanitizeArg(dir);
-       char * string = malloc(strlen("lsinfo")+strlen(sDir)+5);
-       sprintf(string,"lsinfo \"%s\"\n",sDir);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-       free(sDir);
-}
-
-void mpd_sendSearchCommand(mpd_Connection * connection, int table, 
-               const char * str) 
-{
-       char st[10];
-       char * string;
-       char * sanitStr = mpd_sanitizeArg(str);
-       if(table == MPD_TABLE_ARTIST) strcpy(st,"artist");
-       else if(table == MPD_TABLE_ALBUM) strcpy(st,"album");
-       else if(table == MPD_TABLE_TITLE) strcpy(st,"title");
-       else if(table == MPD_TABLE_FILENAME) strcpy(st,"filename");
-       else {
-               connection->error = 1;
-               strcpy(connection->errorStr,"unknown table for search");
-               return;
-       }
-       string = malloc(strlen("search")+strlen(sanitStr)+strlen(st)+6);
-       sprintf(string,"search %s \"%s\"\n",st,sanitStr);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-       free(sanitStr);
-}
-
-void mpd_sendFindCommand(mpd_Connection * connection, int table, 
-               const char * str) 
-{
-       char st[10];
-       char * string;
-       char * sanitStr = mpd_sanitizeArg(str);
-       if(table == MPD_TABLE_ARTIST) strcpy(st,"artist");
-       else if(table == MPD_TABLE_ALBUM) strcpy(st,"album");
-       else if(table == MPD_TABLE_TITLE) strcpy(st,"title");
-       else {
-               connection->error = 1;
-               strcpy(connection->errorStr,"unknown table for find");
-               return;
-       }
-       string = malloc(strlen("find")+strlen(sanitStr)+strlen(st)+6);
-       sprintf(string,"find %s \"%s\"\n",st,sanitStr);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-       free(sanitStr);
-}
-
-void mpd_sendListCommand(mpd_Connection * connection, int table, 
-               const char * arg1) 
-{
-       char st[10];
-       char * string;
-       if(table == MPD_TABLE_ARTIST) strcpy(st,"artist");
-       else if(table == MPD_TABLE_ALBUM) strcpy(st,"album");
-       else {
-               connection->error = 1;
-               strcpy(connection->errorStr,"unknown table for list");
-               return;
-       }
-       if(arg1) {
-               char * sanitArg1 = mpd_sanitizeArg(arg1);
-               string = malloc(strlen("list")+strlen(sanitArg1)+strlen(st)+6);
-               sprintf(string,"list %s \"%s\"\n",st,sanitArg1);
-               free(sanitArg1);
-       }
-       else {
-               string = malloc(strlen("list")+strlen(st)+3);
-               sprintf(string,"list %s\n",st);
-       }
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendAddCommand(mpd_Connection * connection, const char * file) {
-       char * sFile = mpd_sanitizeArg(file);
-       char * string = malloc(strlen("add")+strlen(sFile)+5);
-       sprintf(string,"add \"%s\"\n",sFile);
-       mpd_executeCommand(connection,string);
-       free(string);
-       free(sFile);
-}
-
-void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum) {
-       char * string = malloc(strlen("delete")+25);
-       sprintf(string,"delete \"%i\"\n",songNum);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendSaveCommand(mpd_Connection * connection, const char * name) {
-       char * sName = mpd_sanitizeArg(name);
-       char * string = malloc(strlen("save")+strlen(sName)+5);
-       sprintf(string,"save \"%s\"\n",sName);
-       mpd_executeCommand(connection,string);
-       free(string);
-       free(sName);
-}
-
-void mpd_sendLoadCommand(mpd_Connection * connection, const char * name) {
-       char * sName = mpd_sanitizeArg(name);
-       char * string = malloc(strlen("load")+strlen(sName)+5);
-       sprintf(string,"load \"%s\"\n",sName);
-       mpd_executeCommand(connection,string);
-       free(string);
-       free(sName);
-}
-
-void mpd_sendRmCommand(mpd_Connection * connection, const char * name) {
-       char * sName = mpd_sanitizeArg(name);
-       char * string = malloc(strlen("rm")+strlen(sName)+5);
-       sprintf(string,"rm \"%s\"\n",sName);
-       mpd_executeCommand(connection,string);
-       free(string);
-       free(sName);
-}
-
-void mpd_sendShuffleCommand(mpd_Connection * connection) {
-       mpd_executeCommand(connection,"shuffle\n");
-}
-
-void mpd_sendClearCommand(mpd_Connection * connection) {
-       mpd_executeCommand(connection,"clear\n");
-}
-
-void mpd_sendPlayCommand(mpd_Connection * connection, int songNum) {
-       char * string = malloc(strlen("play")+25);
-       sprintf(string,"play \"%i\"\n",songNum);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendStopCommand(mpd_Connection * connection) {
-       mpd_executeCommand(connection,"stop\n");
-}
-
-void mpd_sendPauseCommand(mpd_Connection * connection) {
-       mpd_executeCommand(connection,"pause\n");
-}
-
-void mpd_sendNextCommand(mpd_Connection * connection) {
-       mpd_executeCommand(connection,"next\n");
-}
-
-void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to) {
-       char * string = malloc(strlen("move")+25);
-       sprintf(string,"move \"%i\" \"%i\"\n",from,to);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2) {
-       char * string = malloc(strlen("swap")+25);
-       sprintf(string,"swap \"%i\" \"%i\"\n",song1,song2);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time) {
-       char * string = malloc(strlen("seek")+25);
-       sprintf(string,"seek \"%i\" \"%i\"\n",song,time);
-       mpd_sendInfoCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendUpdateCommand(mpd_Connection * connection) {
-        mpd_executeCommand(connection,"update\n");
-}
-
-void mpd_sendPrevCommand(mpd_Connection * connection) {
-       mpd_executeCommand(connection,"previous\n");
-}
-
-void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode) {
-       char * string = malloc(strlen("repeat")+25);
-       sprintf(string,"repeat \"%i\"\n",repeatMode);
-       mpd_executeCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode) {
-       char * string = malloc(strlen("random")+25);
-       sprintf(string,"random \"%i\"\n",randomMode);
-       mpd_executeCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange) {
-       char * string = malloc(strlen("setvol")+25);
-       sprintf(string,"setvol \"%i\"\n",volumeChange);
-       mpd_executeCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange) {
-       char * string = malloc(strlen("volume")+25);
-       sprintf(string,"volume \"%i\"\n",volumeChange);
-       mpd_executeCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds) {
-       char * string = malloc(strlen("crossfade")+25);
-       sprintf(string,"crossfade \"%i\"\n",seconds);
-       mpd_executeCommand(connection,string);
-       free(string);
-}
-
-void mpd_sendPasswordCommand(mpd_Connection * connection, const char * pass) {
-       char * sPass = mpd_sanitizeArg(pass);
-       char * string = malloc(strlen("password")+strlen(sPass)+5);
-       sprintf(string,"password \"%s\"\n",sPass);
-       mpd_executeCommand(connection,string);
-       free(string);
-       free(sPass);
-}
-
-void mpd_sendCommandListBegin(mpd_Connection * connection) {
-       if(connection->commandList) {
-               strcpy(connection->errorStr,"already in command list mode");
-               connection->error = 1;
-               return;
-       }
-       connection->commandList = 1;
-       mpd_executeCommand(connection,"command_list_begin\n");
-}
-
-void mpd_sendCommandListEnd(mpd_Connection * connection) {
-       if(!connection->commandList) {
-               strcpy(connection->errorStr,"not in command list mode");
-               connection->error = 1;
-               return;
-       }
-       connection->commandList = 0;
-       mpd_executeCommand(connection,"command_list_end\n");
-}
diff --git a/libmpdclient.h b/libmpdclient.h
deleted file mode 100644 (file)
index 6d749fb..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-/* libmpdclient
- * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
- * This project's homepage is: http://www.musicpd.org
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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
- */
-
-#ifndef LIBMPDCLIENT_H
-#define LIBMPDCLIENT_H
-
-#include <sys/time.h>
-
-#define MPD_BUFFER_MAX_LENGTH  50000
-#define MPD_WELCOME_MESSAGE    "OK MPD "
-
-#define MPD_ERROR_TIMEOUT      10 /* timeout trying to talk to mpd */
-#define MPD_ERROR_SYSTEM       11 /* system error */
-#define MPD_ERROR_UNKHOST      12 /* unknown host */
-#define MPD_ERROR_CONNPORT     13 /* problems connecting to port on host */
-#define MPD_ERROR_NOTMPD       14 /* mpd not running on port at host */
-#define MPD_ERROR_NORESPONSE   15 /* no response on attempting to connect */
-#define MPD_ERROR_SENDING      16 /* error sending command */
-#define MPD_ERROR_CONNCLOSED   17 /* connection closed by mpd */
-#define MPD_ERROR_ACK          18 /* ACK returned! */
-#define MPD_ERROR_BUFFEROVERRUN        19 /* Buffer was overrun! */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* internal stuff don't touch this struct */
-typedef struct _mpd_ReturnElement {
-       char * name;
-       char * value;
-} mpd_ReturnElement;
-
-/* mpd_Connection
- * holds info about connection to mpd
- * use error, and errorStr to detect errors
- */
-typedef struct _mpd_Connection {
-       /* use this to check the version of mpd */
-       int version[3];
-       /* IMPORTANT, you want to get the error messages from here */
-       char errorStr[MPD_BUFFER_MAX_LENGTH+1];
-       /* this will be set to 1 if there is an error, 0 if not */
-       int error;
-       /* DON'T TOUCH any of the rest of this stuff */
-       int sock; 
-       char buffer[MPD_BUFFER_MAX_LENGTH+1];
-       int buflen;
-       int bufstart;
-       int doneProcessing;
-       int commandList;
-       mpd_ReturnElement * returnElement;
-       struct timeval timeout;
-} mpd_Connection;
-
-/* mpd_newConnection
- * use this to open a new connection
- * you should use mpd_closeConnection, when your done with the connection,
- * even if an error has occurred
- * _timeout_ is the connection timeout period in seconds
- */
-mpd_Connection * mpd_newConnection(const char * host, int port, float timeout);
-
-void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout);
-
-/* mpd_closeConnection
- * use this to close a connection and free'ing subsequent memory
- */
-void mpd_closeConnection(mpd_Connection * connection);
-
-/* mpd_clearError
- * clears error
- */
-void mpd_clearError(mpd_Connection * connection);
-
-/* STATUS STUFF */
-
-/* use these with status.state to determine what state the player is in */
-#define MPD_STATUS_STATE_UNKNOWN       0
-#define MPD_STATUS_STATE_STOP          1
-#define MPD_STATUS_STATE_PLAY          2
-#define MPD_STATUS_STATE_PAUSE         3
-
-/* us this with status.volume to determine if mpd has volume support */
-#define MPD_STATUS_NO_VOLUME           -1
-
-/* mpd_Status
- * holds info return from status command
- */
-typedef struct mpd_Status {
-       /* 0-100, or MPD_STATUS_NO_VOLUME when there is no volume support */
-       int volume;
-       /* 1 if repeat is on, 0 otherwise */
-       int repeat;
-       /* 1 if random is on, 0 otherwise */
-       int random;
-       /* playlist length */
-       int playlistLength;
-       /* playlist, use this to determine when the playlist has changed */
-       long long playlist;
-       /* use with MPD_STATUS_STATE_* to determine state of player */
-       int state;
-       /* crossfade setting in seconds */
-       int crossfade;
-       /* if in PLAY or PAUSE state, this is the number of the currently
-        * playing song in the playlist, beginning with 0
-        */
-       int song;
-       /* time in seconds that have elapsed in the currently playing/paused
-        * song
-        */
-       int elapsedTime;
-       /* length in seconds of the currently playing/paused song */
-       int totalTime;
-       /* current bit rate in kbs */
-       int bitRate;
-       /* audio sample rate */
-       unsigned int sampleRate;
-       /* audio bits */
-       int bits;
-       /* audio channels */
-       int channels;
-       /* error */
-       char * error;
-} mpd_Status;
-
-/* mpd_getStatus
- * returns status info, be sure to free it with mpd_freeStatus()
- */
-mpd_Status * mpd_getStatus(mpd_Connection * connection);
-
-/* mpd_freeStatus
- * free's status info malloc'd and returned by mpd_getStatus
- */
-void mpd_freeStatus(mpd_Status * status);
-
-typedef struct _mpd_Stats {
-       int numberOfArtists;
-       int numberOfAlbums;
-       int numberOfSongs;
-       unsigned long uptime;
-       unsigned long dbUpdateTime;
-       unsigned long playTime;
-       unsigned long dbPlayTime;
-} mpd_Stats;
-
-mpd_Stats * mpd_getStats(mpd_Connection * connection);
-
-void mpd_freeStats(mpd_Stats * stats);
-
-/* SONG STUFF */
-
-#define MPD_SONG_NO_TIME       -1
-
-/* mpd_Song
- * for storing song info returned by mpd
- */
-typedef struct _mpd_Song {
-       /* filename of song */
-       char * file;
-       /* artist, maybe NULL if there is no tag */
-       char * artist;
-       /* title, maybe NULL if there is no tag */
-       char * title;
-       /* album, maybe NULL if there is no tag */
-       char * album;
-       /* track, maybe NULL if there is no tag */
-       char * track;
-       /* length of song in seconds, check that it is not MPD_SONG_NO_TIME  */
-       int time;
-} mpd_Song;
-
-/* mpd_newSong
- * use to allocate memory for a new mpd_Song
- * file, artist, etc all initialized to NULL
- * if your going to assign values to file, artist, etc
- * be sure to malloc or strdup the memory
- * use mpd_freeSong to free the memory for the mpd_Song, it will also
- * free memory for file, artist, etc, so don't do it yourself
- */
-mpd_Song * mpd_newSong();
-
-/* mpd_freeSong
- * use to free memory allocated by mpd_newSong
- * also it will free memory pointed to by file, artist, etc, so be careful
- */
-void mpd_freeSong(mpd_Song * song);
-
-/* mpd_songDup
- * works like strDup, but for a mpd_Song
- */
-mpd_Song * mpd_songDup(mpd_Song * song);
-
-/* DIRECTORY STUFF */
-
-/* mpd_Directory
- * used to store info fro directory (right now that just the path)
- */
-typedef struct _mpd_Directory {
-       char * path;
-} mpd_Directory;
-
-/* mpd_newDirectory
- * allocates memory for a new directory
- * use mpd_freeDirectory to free this memory
- */
-mpd_Directory * mpd_newDirectory ();
-
-/* mpd_freeDirectory
- * used to free memory allocated with mpd_newDirectory, and it frees
- * path of mpd_Directory, so be careful
- */
-void mpd_freeDirectory(mpd_Directory * directory);
-
-/* mpd_directoryDup
- * works like strdup, but for mpd_Directory
- */
-mpd_Directory * mpd_directoryDup(mpd_Directory * directory);
-
-/* PLAYLISTFILE STUFF */
-
-/* mpd_PlaylistFile
- * stores info about playlist file returned by lsinfo
- */
-typedef struct _mpd_PlaylistFile {
-       char * path;
-} mpd_PlaylistFile;
-
-/* mpd_newPlaylistFile
- * allocates memory for new mpd_PlaylistFile, path is set to NULL
- * free this memory with mpd_freePlaylistFile
- */
-mpd_PlaylistFile * mpd_newPlaylistFile();
-
-/* mpd_freePlaylist
- * free memory allocated for freePlaylistFile, will also free
- * path, so be careful
- */
-void mpd_freePlaylistFile(mpd_PlaylistFile * playlist);
-
-/* mpd_playlistFileDup
- * works like strdup, but for mpd_PlaylistFile
- */
-mpd_PlaylistFile * mpd_playlistFileDup(mpd_PlaylistFile * playlist);
-
-/* INFO ENTITY STUFF */
-
-/* the type of entity returned from one of the commands that generates info
- * use in conjunction with mpd_InfoEntity.type
- */
-#define MPD_INFO_ENTITY_TYPE_DIRECTORY         0
-#define MPD_INFO_ENTITY_TYPE_SONG              1
-#define MPD_INFO_ENTITY_TYPE_PLAYLISTFILE      2
-
-/* mpd_InfoEntity
- * stores info on stuff returned info commands
- */
-typedef struct mpd_InfoEntity {
-       /* the type of entity, use with MPD_INFO_ENTITY_TYPE_* to determine
-        * what this entity is (song, directory, etc...)
-        */
-       int type;
-       /* the actual data you want, mpd_Song, mpd_Directory, etc */
-       union {
-               mpd_Directory * directory;
-               mpd_Song * song;
-               mpd_PlaylistFile * playlistFile;
-       } info;
-} mpd_InfoEntity;
-
-mpd_InfoEntity * mpd_newInfoEntity();
-
-void mpd_freeInfoEntity(mpd_InfoEntity * entity);
-
-/* INFO COMMANDS AND STUFF */
-
-/* use this function to loop over after calling Info/Listall functions */
-mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection);
-
-/* songNum of -1, means to display the whole list */
-void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum);
-
-void mpd_sendListallCommand(mpd_Connection * connection, const char * dir);
-
-void mpd_sendListallInfoCommand(mpd_Connection * connection, const char * dir);
-
-void mpd_sendLsInfoCommand(mpd_Connection * connection, const char * dir);
-
-#define MPD_TABLE_ARTIST       0
-#define MPD_TABLE_ALBUM                1
-#define MPD_TABLE_TITLE                2
-#define MPD_TABLE_FILENAME     3
-
-void mpd_sendSearchCommand(mpd_Connection * connection, int table, 
-               const char * str);
-
-void mpd_sendFindCommand(mpd_Connection * connection, int table, 
-               const char * str);
-
-/* LIST TAG COMMANDS */
-
-/* use this function fetch next artist entry, be sure to free the returned 
- * string.  NULL means there are no more.  Best used with sendListArtists
- */
-char * mpd_getNextArtist(mpd_Connection * connection);
-
-char * mpd_getNextAlbum(mpd_Connection * connection);
-
-/* list artist or albums by artist, arg1 should be set to the artist if
- * listing albums by a artist, otherwise NULL for listing all artists or albums
- */
-void mpd_sendListCommand(mpd_Connection * connection, int table, 
-               const char * arg1);
-
-void mpd_sendListAlbumsCommand(mpd_Connection * connection, 
-               const char * artist);
-
-/* SIMPLE COMMANDS */
-
-void mpd_sendAddCommand(mpd_Connection * connection, const char * file);
-
-void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum);
-
-void mpd_sendSaveCommand(mpd_Connection * connection, const char * name);
-
-void mpd_sendLoadCommand(mpd_Connection * connection, const char * name);
-
-void mpd_sendRmCommand(mpd_Connection * connection, const char * name);
-
-void mpd_sendShuffleCommand(mpd_Connection * connection);
-
-void mpd_sendClearCommand(mpd_Connection * connection);
-
-/* use this to start playing at the beginning, useful when in random mode */
-#define MPD_PLAY_AT_BEGINNING  -1
-
-void mpd_sendPlayCommand(mpd_Connection * connection, int songNum);
-
-void mpd_sendStopCommand(mpd_Connection * connection);
-
-void mpd_sendPauseCommand(mpd_Connection * connection);
-
-void mpd_sendNextCommand(mpd_Connection * connection);
-
-void mpd_sendPrevCommand(mpd_Connection * connection);
-
-void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to);
-
-void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2);
-
-void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time);
-
-void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode);
-
-void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode);
-
-void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange);
-
-/* WARNING: don't use volume command, its depreacted */
-void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange);
-
-void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds);
-
-void mpd_sendUpdateCommand(mpd_Connection * connection);
-
-void mpd_sendPasswordCommand(mpd_Connection * connection, const char * pass);
-
-/* after executing a command, when your done with it to get its status
- * (you want to check connection->error for an error)
- */
-void mpd_finishCommand(mpd_Connection * connection);
-
-/* command list stuff, use this to do things like add files very quickly */
-void mpd_sendCommandListBegin(mpd_Connection * connection);
-
-void mpd_sendCommandListEnd(mpd_Connection * connection);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/list_window.c b/list_window.c
deleted file mode 100644 (file)
index 6b4a41f..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/* 
- * (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 <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-#include "options.h"
-#include "support.h"
-#include "command.h"
-#include "colors.h"
-#include "list_window.h"
-
-list_window_t *
-list_window_init(WINDOW *w, int width, int height)
-{
-  list_window_t *lw;
-
-  lw = g_malloc(sizeof(list_window_t));
-  memset(lw, 0, sizeof(list_window_t));
-  lw->w = w;
-  lw->cols = width;
-  lw->rows = height;
-  lw->clear = 1;
-  return lw;
-}
-
-list_window_t *
-list_window_free(list_window_t *lw)
-{
-  if( lw )
-    {
-      memset(lw, 0, sizeof(list_window_t));
-      g_free(lw);
-    }
-  return NULL;
-}
-
-void
-list_window_reset(list_window_t *lw)
-{
-  lw->selected = 0;
-  lw->start = 0;
-  lw->clear = 1;
-}
-
-void
-list_window_check_selected(list_window_t *lw, int length)
-{
-  while( lw->start && lw->start+lw->rows>length)
-    lw->start--;
-
-  if( lw->selected<0 )
-    lw->selected=0;
-
-  while( lw->selected<lw->start )
-    lw->selected++;
-
-  while( lw->selected>0 && length>0 && lw->selected>=length )
-    lw->selected--;
-}
-
-void 
-list_window_set_selected(list_window_t *lw, int n)
-{
-  lw->selected=n;
-}
-
-void
-list_window_next(list_window_t *lw, int length)
-{
-  if( lw->selected < length-1 )
-    lw->selected++;
-}
-
-void
-list_window_previous(list_window_t *lw)
-{
-  if( lw->selected > 0 )
-    lw->selected--;
-}
-
-void
-list_window_first(list_window_t *lw)
-{
-  lw->selected = 0;
-}
-
-void
-list_window_last(list_window_t *lw, int length)
-{
-  lw->selected = length-1;
-}
-
-void
-list_window_next_page(list_window_t *lw, int length)
-{
-  int step = lw->rows-1;
-  if( step<= 0 )
-    return;
-  if( lw->selected+step < length-1 )
-    lw->selected+=step;
-  else
-    return list_window_last(lw,length);
-}
-
-void
-list_window_previous_page(list_window_t *lw)
-{
-  int step = lw->rows-1;
-  if( step<= 0 )
-    return;
-  if( lw->selected-step > 0 )
-    lw->selected-=step;
-  else
-    list_window_first(lw);
-}
-
-
-void 
-list_window_paint(list_window_t *lw,
-                 list_window_callback_fn_t callback,
-                 void *callback_data)
-{
-  int i;
-  int fill = options.wide_cursor;
-
-  while( lw->selected < lw->start )
-    {
-      lw->start--;
-      lw->clear=1;
-    }
-  while( lw->selected >= lw->start+lw->rows )
-    {
-      lw->start++;
-      lw->clear=1;
-    }
-
-  for(i=0; i<lw->rows; i++)
-    {
-      int highlight = 0;
-      char *label;
-
-      label = (callback) (lw->start+i, &highlight, callback_data);
-      wmove(lw->w, i, 0);
-      if( lw->clear && (!fill || !label) )
-       wclrtoeol(lw->w);
-      if( label )
-       {
-         int selected = lw->start+i == lw->selected;
-
-         if( highlight )
-           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( selected )
-           wattroff(lw->w, A_REVERSE);   
-       }
-       
-    }
-  lw->clear=0;
-}
-
-
-int
-list_window_find(list_window_t *lw, 
-                list_window_callback_fn_t callback,
-                void *callback_data,
-                char *str,
-                int wrap)
-{
-  int h;
-  int i = lw->selected+1;
-  char *label;
-  
-  while( wrap || i==lw->selected+1 )
-    {
-      while( (label=(callback) (i,&h,callback_data)) )
-       {
-         if( str && label && strcasestr(label, str) )
-           {
-             lw->selected = i;
-             return 0;
-           }
-         if( wrap && i==lw->selected )
-           return 1;
-         i++;
-       }
-      if( wrap )
-       {
-         i=0; /* first item */
-         beep(); 
-       }
-    }
-  return 1;
-}
-
-
-int
-list_window_rfind(list_window_t *lw, 
-                 list_window_callback_fn_t callback,
-                 void *callback_data,
-                 char *str,
-                 int wrap,
-                 int rows)
-{
-  int h;
-  int i = lw->selected-1;
-  char *label;
-
-  while( wrap || i==lw->selected-1 )
-    {
-      while( i>=0 && (label=(callback) (i,&h,callback_data)) )
-       {
-         if( str && label && strcasestr(label, str) )
-           {
-             lw->selected = i;
-             return 0;
-           }
-         if( wrap && i==lw->selected )
-           return 1;
-         i--;
-       }
-      if( wrap )
-       {
-         i=rows-1; /* last item */
-         beep();
-       }
-    }
-  return 1;
-}
-
-
-/* perform basic list window commands (movement) */
-int 
-list_window_cmd(list_window_t *lw, int rows, command_t cmd)
-{
-  switch(cmd)
-    {
-    case CMD_LIST_PREVIOUS:
-      list_window_previous(lw);
-      lw->repaint=1;
-      break;
-    case CMD_LIST_NEXT:
-      list_window_next(lw, rows);
-      lw->repaint=1;
-      break;
-    case CMD_LIST_FIRST:
-      list_window_first(lw);
-      lw->repaint  = 1;
-      break;
-    case CMD_LIST_LAST:
-      list_window_last(lw, rows);
-      lw->repaint = 1;
-      break;
-    case CMD_LIST_NEXT_PAGE:
-      list_window_next_page(lw, rows);
-      lw->repaint  = 1;
-      break;
-    case CMD_LIST_PREVIOUS_PAGE:
-      list_window_previous_page(lw);
-      lw->repaint  = 1;
-      break;
-    default:
-      return 0;
-    }
-  return 1;
-}
-
-
diff --git a/list_window.h b/list_window.h
deleted file mode 100644 (file)
index 9e91703..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef LIST_WINDOW_H
-#define LIST_WINDOW_H
-
-#define LW_ROW(lw) (lw ? lw->selected-lw->start :  0)
-
-typedef char *  (*list_window_callback_fn_t)   (int index, 
-                                               int *highlight,
-                                               void *data);
-
-typedef struct
-{
-  WINDOW *w;
-  int rows, cols;
-
-  int start;
-  int selected;
-  int clear;
-  int repaint;
-
-} list_window_t;
-
-
-/* create a new list window */
-list_window_t *list_window_init(WINDOW *w, int width, int height);
-
-/* destroy a list window (returns NULL) */
-list_window_t *list_window_free(list_window_t *lw);
-
-/* reset a list window (selected=0, start=0, clear=1) */
-void list_window_reset(list_window_t *lw);
-
-/* paint a list window */
-void list_window_paint(list_window_t *lw,
-                      list_window_callback_fn_t callback,
-                      void *callback_data);
-
-/* perform basic list window commands (movement) */
-int list_window_cmd(list_window_t *lw, int rows, command_t cmd);
-
-
-/* select functions */
-void list_window_set_selected(list_window_t *lw, int n);
-void list_window_previous(list_window_t *lw);
-void list_window_next(list_window_t *lw, int length);
-void list_window_first(list_window_t *lw);
-void list_window_last(list_window_t *lw, int length);
-void list_window_previous_page(list_window_t *lw);
-void list_window_next_page(list_window_t *lw, int length);
-void list_window_check_selected(list_window_t *lw, int length);
-
-/* find a string in a list window */
-int  list_window_find(list_window_t *lw, 
-                     list_window_callback_fn_t callback,
-                     void *callback_data,
-                     char *str,
-                     int wrap);
-
-/* find a string in a list window (reversed) */
-int
-list_window_rfind(list_window_t *lw, 
-                 list_window_callback_fn_t callback,
-                 void *callback_data,
-                 char *str,
-                 int wrap,
-                 int rows);
-
-#endif
diff --git a/main.c b/main.c
deleted file mode 100644 (file)
index bb3740b..0000000
--- a/main.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/* 
- * (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 <unistd.h>
-#include <signal.h>
-#include <glib.h>
-
-#include "config.h"
-#include "libmpdclient.h"
-#include "support.h"
-#include "mpc.h"
-#include "options.h"
-#include "command.h"
-#include "screen.h"
-#include "conf.h"
-
-/* time in seconds between mpd updates (double) */
-#define MPD_UPDATE_TIME        0.5
-
-/* timout in seconds before trying to reconnect (int) */
-#define MPD_RECONNECT_TIMEOUT  3
-
-
-static mpd_client_t *mpc = NULL;
-static GTimer       *timer = NULL;
-
-void
-exit_and_cleanup(void)
-{
-  screen_exit();
-  printf("\n");
-  charset_close();
-  if( mpc )
-    {
-      if( mpc_error(mpc) )
-       fprintf(stderr,"Error: %s\n", mpc_error_str(mpc));
-      mpc_close(mpc);
-    }
-  g_free(options.host);
-  g_free(options.password);
-  if( timer )
-    g_timer_destroy(timer);
-}
-
-void
-catch_sigint( int sig )
-{
-  printf( "\nExiting...\n");
-  exit(EXIT_SUCCESS);
-}
-
-int 
-main(int argc, const char *argv[])
-{
-  options_t *options;
-  struct sigaction act;
-  gboolean connected;
-
-  /* initialize options */
-  options = options_init();
-
-  /* parse command line options - 1 pass get configuration files */
-  options_parse(argc, argv);
-  
-  /* read configuration */
-  read_configuration(options);
-  
-  /* check key bindings */
-  if( check_key_bindings() )
-    {
-      fprintf(stderr, "Confusing key bindings - exiting!\n");
-      exit(EXIT_FAILURE);
-    }
-
-  /* parse command line options - 2 pass */
-  options_parse(argc, argv);
-
-  /* initialize local charset */
-  if( charset_init() )
-    exit(EXIT_FAILURE);
-
-  /* setup signal behavior - SIGINT */
-  sigemptyset( &act.sa_mask );
-  act.sa_flags    = 0;
-  act.sa_handler = catch_sigint;
-  if( sigaction( SIGINT, &act, NULL )<0 )
-    {
-      perror("signal");
-      exit(EXIT_FAILURE);
-    }
-  /* setup signal behavior - SIGTERM */
-  sigemptyset( &act.sa_mask );
-  act.sa_flags    = 0;
-  act.sa_handler = catch_sigint;
-  if( sigaction( SIGTERM, &act, NULL )<0 )
-    {
-      perror("sigaction()");
-      exit(EXIT_FAILURE);
-    }
-
-  /* set xterm title */
-  if( g_getenv("DISPLAY") )
-    printf("%c]0;%s%c", '\033', PACKAGE " version " VERSION, '\007');
-
-  /* install exit function */
-  atexit(exit_and_cleanup);
-
-  /* connect to our music player daemon */
-  mpc = mpc_connect(options->host, options->port, options->password);
-  if( mpc_error(mpc) )
-    exit(EXIT_FAILURE);
-
-  /* initialize curses */
-  screen_init();
-
-  /* initialize timer */
-  timer = g_timer_new();
-
-  connected = TRUE;
-  while( connected || options->reconnect )
-    {
-      static gdouble t = G_MAXDOUBLE;
-
-      if( connected && t>=MPD_UPDATE_TIME )
-       {
-         mpc_update(mpc);
-         if( mpc_error(mpc) == MPD_ERROR_ACK )
-           {
-             screen_status_printf("%s", mpc_error_str(mpc));
-             mpd_clearError(mpc->connection);
-             mpd_finishCommand(mpc->connection);
-           }
-         else if( mpc_error(mpc) )
-           {
-             screen_status_printf("Lost connection to %s", options->host);
-             connected = FALSE;         
-             doupdate();
-             mpd_clearError(mpc->connection);
-             mpd_closeConnection(mpc->connection);
-             mpc->connection = NULL;
-           }
-         else  
-           mpd_finishCommand(mpc->connection);
-         g_timer_start(timer);
-       }
-
-      if( connected )
-       {
-         command_t cmd;
-
-         screen_update(mpc);
-         if( (cmd=get_keyboard_command()) != CMD_NONE )
-           {
-             screen_cmd(mpc, cmd);
-             if( cmd==CMD_VOLUME_UP || cmd==CMD_VOLUME_DOWN)
-               /* make shure we dont update the volume yet */
-               g_timer_start(timer);
-           }
-         else
-           screen_idle(mpc);
-       }
-      else if( options->reconnect )
-       {
-         sleep(MPD_RECONNECT_TIMEOUT);
-         screen_status_printf("Connecting to %s...  [Press Ctrl-C to abort]", 
-                              options->host);
-         if( mpc_reconnect(mpc, 
-                           options->host, 
-                           options->port, 
-                           options->password) == 0 )
-           {
-             screen_status_printf("Connected to %s!", options->host);
-             connected = TRUE;
-           }
-         doupdate();
-       }
-
-      t = g_timer_elapsed(timer, NULL);
-    }
-
-  exit(EXIT_FAILURE);
-}
diff --git a/mpc.c b/mpc.c
deleted file mode 100644 (file)
index 0a80af4..0000000
--- a/mpc.c
+++ /dev/null
@@ -1,359 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <string.h>
-#include <glib.h>
-
-#include "config.h"
-#include "support.h"
-#include "libmpdclient.h"
-#include "mpc.h"
-#include "options.h"
-
-#define MAX_SONG_LENGTH 1024
-
-#ifdef DEBUG
-#define D(x) x
-#else
-#define D(x)
-#endif
-
-int 
-mpc_close(mpd_client_t *c)
-{
-  if( c->connection )
-    mpd_closeConnection(c->connection);
-  if( c->cwd )
-    g_free( c->cwd );
-  
-  return 0;
-}
-
-mpd_client_t *
-mpc_connect(char *host, int port, char *password)
-{
-  mpd_Connection *connection;
-  mpd_client_t *c;
-
-  connection =  mpd_newConnection(host, port, 10);
-  if( connection==NULL )
-    {
-      fprintf(stderr, "mpd_newConnection to %s:%d failed!\n", host, port);
-      exit(EXIT_FAILURE);
-    }
-  
-  c = g_malloc(sizeof(mpd_client_t));
-  memset(c, 0, sizeof(mpd_client_t));
-  c->connection = connection;
-  c->cwd = g_strdup("");
-
-  if( password )
-    {
-      mpd_sendPasswordCommand(connection, password);
-      mpd_finishCommand(connection);
-    }
-
-  return c;
-}
-
-int
-mpc_reconnect(mpd_client_t *c, char *host, int port, char *password)
-{
-  mpd_Connection *connection;
-
-  connection =  mpd_newConnection(host, port, 10);
-  if( connection==NULL )
-    return -1;
-  if( connection->error )
-    {
-      mpd_closeConnection(connection);
-      return -1;
-    }
-  
-  c->connection = connection;
-
-  if( password )
-    {
-      mpd_sendPasswordCommand(connection, password);
-      mpd_finishCommand(connection);
-    }
-
-  return 0;
-}
-
-
-int
-mpc_error(mpd_client_t *c)
-{
-  if( c == NULL || c->connection == NULL )
-    return 1;
-  if( c->connection->error )
-    return c->connection->error;
-
-  return 0;
-}
-
-char *
-mpc_error_str(mpd_client_t *c)
-{
-  if( c == NULL || c->connection == NULL )
-    return "Not connected";
-
-  if( c->connection && c->connection->errorStr )
-    return c->connection->errorStr;
-
-  return NULL;
-}
-
-
-
-int
-mpc_free_playlist(mpd_client_t *c)
-{
-  GList *list;
-
-  if( c==NULL || c->playlist==NULL )
-    return -1;
-
-  list=g_list_first(c->playlist);
-
-  while( list!=NULL )
-    {
-      mpd_Song *song = (mpd_Song *) list->data;
-
-      mpd_freeSong(song);
-      list=list->next;
-    }
-  g_list_free(c->playlist);
-  c->playlist=NULL;
-  c->playlist_length=0;
-
-  c->song_id = -1;
-  c->song = NULL;
-
-  return 0;
-}
-
-int 
-mpc_update_playlist(mpd_client_t *c)
-{
-  mpd_InfoEntity *entity;
-
-  D(fprintf(stderr, "mpc_update_playlist() [%d]\n",  c->status->playlist));
-
-  if( mpc_error(c) )
-    return -1;
-
-  if( c->playlist )
-    mpc_free_playlist(c);
-
-  c->playlist_length=0;
-  mpd_sendPlaylistInfoCommand(c->connection,-1);
-  if( mpc_error(c) )
-    return -1;
-  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
-    {
-      if(entity->type==MPD_INFO_ENTITY_TYPE_SONG) 
-       {
-         mpd_Song *song = mpd_songDup(entity->info.song);
-
-         c->playlist = g_list_append(c->playlist, (gpointer) song);
-         c->playlist_length++;
-       }
-      mpd_freeInfoEntity(entity);
-    }
-  c->playlist_id = c->status->playlist;
-  c->playlist_updated = 1;
-  c->song_id = -1;
-  c->song = NULL;
-
-  mpc_filelist_set_selected(c);
-
-  return 0;
-}
-
-int
-mpc_playlist_get_song_index(mpd_client_t *c, char *filename)
-{
-  GList *list = c->playlist;
-  int i=0;
-
-  while( list )
-    {
-      mpd_Song *song = (mpd_Song *) list->data;
-      if( strcmp(song->file, filename ) == 0 ) 
-       return i;
-      list=list->next;
-      i++;
-    }
-  return -1;
-}
-
-mpd_Song *
-mpc_playlist_get_song(mpd_client_t *c, int n)
-{
-  return (mpd_Song *) g_list_nth_data(c->playlist, n);
-}
-
-
-char *
-mpc_get_song_name(mpd_Song *song)
-{
-  static char buf[MAX_SONG_LENGTH];
-  char *name;
-  
-  if( song->title )
-    {
-      if( song->artist )
-       {
-         snprintf(buf, MAX_SONG_LENGTH, "%s - %s", song->artist, song->title);
-         name = utf8_to_locale(buf);
-         strncpy(buf, name, MAX_SONG_LENGTH);
-         g_free(name);
-         return buf;
-       }
-      else
-       {
-         name = utf8_to_locale(song->title);
-         strncpy(buf, name, MAX_SONG_LENGTH);
-         g_free(name);
-         return buf;
-       }
-    }
-  name = utf8_to_locale(basename(song->file));
-  strncpy(buf, name, MAX_SONG_LENGTH);
-  g_free(name);
-  return buf;
-}
-
-int 
-mpc_update(mpd_client_t *c)
-{
-  if( mpc_error(c) )
-    return -1;
-
-  if( c->status )
-    {
-      mpd_freeStatus(c->status);
-    }
-
-  c->status = mpd_getStatus(c->connection);
-  if( mpc_error(c) )
-    return -1;
-  
-  if( c->playlist_id!=c->status->playlist )
-    mpc_update_playlist(c);
-  
-  if( !c->song || c->status->song != c->song_id )
-    {
-      c->song = mpc_playlist_get_song(c, c->status->song);
-      c->song_id = c->status->song;
-      c->song_updated = 1;
-    }
-
-  return 0;
-}
-
-
-
-
-
-
-int
-mpc_free_filelist(mpd_client_t *c)
-{
-  GList *list;
-
-  if( c==NULL || c->filelist==NULL )
-    return -1;
-
-  list=g_list_first(c->filelist);
-
-  while( list!=NULL )
-    {
-      filelist_entry_t *entry = list->data;
-
-      if( entry->entity )
-       mpd_freeInfoEntity(entry->entity);
-      g_free(entry);
-      list=list->next;
-    }
-  g_list_free(c->filelist);
-  c->filelist=NULL;
-  c->filelist_length=0;
-
-  return 0;
-}
-
-
-
-int 
-mpc_update_filelist(mpd_client_t *c)
-{
-  mpd_InfoEntity *entity;
-
-  if( mpc_error(c) )
-    return -1;
-
-  if( c->filelist )
-    mpc_free_filelist(c);
-
-  c->filelist_length=0;
-
-  //  mpd_sendListallCommand(conn,"");
-  mpd_sendLsInfoCommand(c->connection, c->cwd);
-
-  if( c->cwd && c->cwd[0] )
-    {
-      /* add a dummy entry for ./.. */
-      filelist_entry_t *entry = g_malloc(sizeof(filelist_entry_t));
-      memset(entry, 0, sizeof(filelist_entry_t));
-      entry->entity = NULL;
-      c->filelist = g_list_append(c->filelist, (gpointer) entry);
-      c->filelist_length++;
-    }
-
-  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
-    {
-      filelist_entry_t *entry = g_malloc(sizeof(filelist_entry_t));
-      
-      memset(entry, 0, sizeof(filelist_entry_t));
-      entry->entity = entity;
-      c->filelist = g_list_append(c->filelist, (gpointer) entry);
-      c->filelist_length++;
-    }
-  
-  c->filelist_updated = 1;
-
-  mpd_finishCommand(c->connection);
-
-  mpc_filelist_set_selected(c);
-
-  return 0;
-}
-
-int 
-mpc_filelist_set_selected(mpd_client_t *c)
-{
-  GList *list = c->filelist;
-
-  while( list )
-    {
-      filelist_entry_t *entry = list->data;
-      mpd_InfoEntity *entity = entry->entity ;      
-      
-      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-       {
-         mpd_Song *song = entity->info.song;
-
-         if( mpc_playlist_get_song_index(c, song->file) >= 0 )
-           entry->selected = 1;
-         else
-           entry->selected = 0;
-       }
-
-      list=list->next;
-    }
-  return 0;
-}
diff --git a/mpc.h b/mpc.h
deleted file mode 100644 (file)
index a09aeee..0000000
--- a/mpc.h
+++ /dev/null
@@ -1,50 +0,0 @@
-
-typedef struct
-{
-  char selected;
-  mpd_InfoEntity *entity;
-} filelist_entry_t;
-
-typedef struct
-{
-  mpd_Connection *connection;
-  mpd_Status     *status;
-
-  mpd_Song       *song;
-  int            song_id;
-  int            song_updated;
-
-  int            seek_song_id;
-  int            seek_target_time;
-
-  GList         *playlist;
-  int            playlist_length;
-  long long      playlist_id;
-  int            playlist_updated;
-
-  char           *cwd;
-  GList          *filelist;
-  int            filelist_length;
-  int            filelist_updated;
-
-} mpd_client_t;
-
-
-int mpc_close(mpd_client_t *c);
-
-mpd_client_t *mpc_connect(char *host, int port, char *passwd);
-int mpc_reconnect(mpd_client_t *c, char *host, int port, char *passwd);
-
-int mpc_update(mpd_client_t *c);
-int mpc_update_playlist(mpd_client_t *c);
-
-int mpc_update_filelist(mpd_client_t *c);
-int mpc_filelist_set_selected(mpd_client_t *c);
-int mpc_set_cwd(mpd_client_t *c, char *dir);
-
-mpd_Song *mpc_playlist_get_song(mpd_client_t *c, int n);
-char *mpc_get_song_name(mpd_Song *song);
-int mpc_playlist_get_song_index(mpd_client_t *c, char *filename);
-
-int   mpc_error(mpd_client_t *c);
-char *mpc_error_str(mpd_client_t *c);
diff --git a/options.c b/options.c
deleted file mode 100644 (file)
index 416727a..0000000
--- a/options.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/* 
- * (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 <unistd.h>
-#include <string.h>
-#include <ncurses.h>
-#include <glib.h>
-#include <popt.h>
-
-#include "config.h"
-#include "options.h"
-#include "command.h"
-#include "support.h"
-
-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." },
-  { "colors",       'c', 0, 0, 'c', "Enable colors." },
-  { "no-colors",    'C', 0, 0, 'C', "Disable colors." },
-  { "exit",         'e', 0, 0, 'e', "Exit on connection errors." },
-  { "port",         'p', POPT_ARG_INT, &options.port, 0, 
-    "Connect to server on port [" DEFAULT_PORT_STR "].", "PORT" },
-  { "host",         'h', POPT_ARG_STRING, &mpd_host, 0, 
-    "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 }
-};
-
-static void
-usage(poptContext optCon, int exitcode, char *error, char *addl) 
-{
-  poptPrintUsage(optCon, stderr, 0);
-  if (error) 
-    fprintf(stderr, "%s: %s0", error, addl);
-  exit(exitcode);
-}
-
-options_t *
-options_parse( int argc, const char **argv)
-{
-  int c;
-  poptContext optCon;   /* context for parsing command-line options */
-
-  mpd_host = NULL;
-  mpd_password = NULL;
-  config_file = NULL;
-  key_file = NULL;
-  optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
-  while ((c = poptGetNextOpt(optCon)) >= 0) 
-    {
-      switch (c) 
-       {
-#ifdef DEBUG
-       case 'D':
-         options.debug = 1;
-         break;
-#endif
-       case 'c':
-         options.enable_colors = 1;
-         break;
-       case 'C':
-         options.enable_colors = 0;
-         break;
-       case 'V':
-         printf("Version " VERSION "\n");
-         exit(EXIT_SUCCESS);
-       case 'e':
-         options.reconnect = 0;
-         break;
-       default:
-         fprintf(stderr, "%s: %s\n",
-                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
-                 poptStrerror(c));
-         poptFreeContext(optCon);
-         exit(EXIT_FAILURE);
-         break;
-       }
-    }
-  if (c < -1) 
-    {
-      /* an error occurred during option processing */
-      fprintf(stderr, "%s: %s\n",
-             poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
-             poptStrerror(c));
-      poptFreeContext(optCon);
-      exit(EXIT_FAILURE);
-    }
-
-  if( mpd_host )
-    {
-      g_free(options.host);
-      options.host = mpd_host;
-    }
-  if( mpd_password )
-    {
-      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;
-}
-
-options_t *
-options_init( void )
-{
-  const char *value;
-  char *tmp;
-
-  memset(&options, 0, sizeof(options_t));
-
-  if( (value=g_getenv(MPD_HOST_ENV)) )
-    options.host = g_strdup(value);
-  else
-    options.host = g_strdup(DEFAULT_HOST);
-  if( (tmp=g_strstr_len(options.host, strlen(options.host), "@")) )
-    {
-      char *oldhost = options.host;
-      *tmp  = '\0';
-      options.password = locale_to_utf8(oldhost);
-      options.host = g_strdup(tmp+1);
-      g_free(oldhost);
-    }
-
-  if( (value=g_getenv(MPD_PORT_ENV)) )
-    options.port = atoi(value);
-  else
-    options.port = DEFAULT_PORT;
-
-  options.reconnect = 1;
-  options.find_wrap = 1;
-  options.wide_cursor = 1;
-
-  return &options;
-}
-
-
-options_t *
-options_get(void)
-{
-  return &options;
-}
diff --git a/options.h b/options.h
deleted file mode 100644 (file)
index 2a6681e..0000000
--- a/options.h
+++ /dev/null
@@ -1,28 +0,0 @@
-
-#define MPD_HOST_ENV "MPD_HOST"
-#define MPD_PORT_ENV "MPD_PORT"
-
-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;
-
-} options_t;
-
-extern options_t options;
-
-options_t *options_init(void);
-options_t *options_parse(int argc, const char **argv);
-
-
-
diff --git a/screen.c b/screen.c
deleted file mode 100644 (file)
index 20ece65..0000000
--- a/screen.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/* 
- * (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 <stdlib.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <signal.h>
-#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"
-#include "screen_help.h"
-#include "screen_search.h"
-#include "screen_utils.h"
-
-#undef  ENABLE_STATUS_LINE_CLOCK
-#define ENABLE_SCROLLING
-
-#define DEFAULT_CROSSFADE_TIME 10
-
-#define STATUS_MESSAGE_TIMEOUT 3
-#define STATUS_LINE_MAX_SIZE   512
-
-#ifdef ENABLE_KEYDEF_SCREEN
-extern screen_functions_t *get_screen_keydef(void);
-#endif
-
-static screen_t *screen = NULL;
-static screen_functions_t *mode_fn = NULL;
-
-static void
-switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c)
-{
-  if( new_mode == screen->mode )
-    return;
-
-  /* close the old mode */
-  if( mode_fn && mode_fn->close )
-    mode_fn->close();
-
-  /* get functions for the new mode */
-  switch(new_mode)
-    {
-    case SCREEN_PLAY_WINDOW:
-      mode_fn = get_screen_playlist();
-      break;
-    case SCREEN_FILE_WINDOW:
-      mode_fn = get_screen_file();
-      break;
-    case SCREEN_HELP_WINDOW:
-      mode_fn = get_screen_help();
-      break;
-#ifdef ENABLE_KEYDEF_SCREEN
-    case SCREEN_KEYDEF_WINDOW:
-      mode_fn = get_screen_keydef();
-      break;
-#endif
-    default:
-      break;
-    }
-
- screen->mode = new_mode;
- screen->painted = 0;
-
- /* open the new mode */
- if( mode_fn && mode_fn->open )
-   mode_fn->open(screen, 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;
-
-  if(prev_header_len!=strlen(header))
-    {
-      prev_header_len = strlen(header);
-      clear = 1;
-    }
-
-  if(clear)
-    {
-      wmove(w, 0, 0);
-      wclrtoeol(w);
-    }
-
-  if(prev_volume!=c->status->volume || clear)
-    {
-      char buf[12];
-
-      if( header[0] )
-       {
-         colors_use(w, COLOR_TITLE_BOLD);
-         mvwaddstr(w, 0, 0, header);
-       }
-      else
-       {
-         colors_use(w, COLOR_TITLE_BOLD);
-         waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE));
-         colors_use(w, COLOR_TITLE);
-         waddstr(w, ":Help  ");
-         colors_use(w, COLOR_TITLE_BOLD);
-         waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE));
-         colors_use(w, COLOR_TITLE);
-         waddstr(w, ":Playlist  ");
-         colors_use(w, COLOR_TITLE_BOLD);
-         waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE));
-         colors_use(w, COLOR_TITLE);
-         waddstr(w, ":Browse");
-       }
-      if( c->status->volume==MPD_STATUS_NO_VOLUME )
-       {
-         snprintf(buf, 12, "Volume n/a ");
-       }
-      else
-       {
-         snprintf(buf, 12, "Volume %3d%%", c->status->volume); 
-       }
-      colors_use(w, COLOR_TITLE);
-      mvwaddstr(w, 0, screen->top_window.cols-12, buf);
-
-      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);
-      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);
-    }
-}
-
-static void
-paint_progress_window(mpd_client_t *c)
-{
-  double p;
-  int width;
-  int elapsedTime = c->status->elapsedTime;
-
-  if( c->status==NULL || IS_STOPPED(c->status->state) )
-    {
-      mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE, 
-              screen->progress_window.cols);
-      wnoutrefresh(screen->progress_window.w);
-      return;
-    }
-
-  if( c->seek_song_id == c->song_id )
-    elapsedTime = c->seek_target_time;
-
-  p = ((double) elapsedTime) / ((double) c->status->totalTime);
-  
-  width = (int) (p * (double) screen->progress_window.cols);
-  mvwhline(screen->progress_window.w, 
-          0, 0,
-          ACS_HLINE, 
-          screen->progress_window.cols);
-  whline(screen->progress_window.w, '=', width-1);
-  mvwaddch(screen->progress_window.w, 0, width-1, 'O');
-  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)
-{
-  WINDOW *w = screen->status_window.w;
-  mpd_Status *status = c->status;
-  mpd_Song *song   = c->song;
-  int elapsedTime = c->status->elapsedTime;
-  int x = 0;
-
-  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:
-      waddstr(w, "Stopped! ");
-      break;
-    case MPD_STATUS_STATE_PLAY:
-      waddstr(w, "Playing:");
-      break;
-    case MPD_STATUS_STATE_PAUSE:
-      waddstr(w, "[Paused]");
-      break;
-    default:
-      break;
-    }
-  x += 9;
-
-  /* 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 )
-    {
-      char *songname = mpc_get_song_name(song);
-      int width = COLS-x-strlen(screen->buf);
-
-      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 )
-    {
-      time_t timep;
-
-      /* Note: setlocale(LC_TIME,"") should be used first */
-      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);
-}
-
-
-
-int
-screen_exit(void)
-{
-  endwin();
-  if( screen )
-    {
-      GList *list = g_list_first(screen->screen_list);
-
-      /* close and exit all screens (playlist,browse,help...) */
-      while( list )
-       {
-         screen_functions_t *mode_fn = list->data;
-
-         if( mode_fn && mode_fn->close )
-           mode_fn->close();
-         if( mode_fn && mode_fn->exit )
-           mode_fn->exit();
-         list->data = NULL;
-         list=list->next;
-       }
-      g_list_free(screen->screen_list);
-
-      g_free(screen->buf);
-      g_free(screen->findbuf);
-      g_free(screen);
-      screen = NULL;
-    }
-  return 0;
-}
-
-void
-screen_resize(void)
-{
-  GList *list;
-
-#ifdef DEBUG
-  fprintf(stderr, "Resize rows %d->%d, cols %d->%d\n",
-         screen->rows, LINES,
-         screen->cols, COLS);
-#endif
-      
-  if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
-    {
-      screen_exit();
-      fprintf(stderr, "Error: Screen to small!\n");
-      exit(EXIT_FAILURE);
-    }
-
-  resizeterm(LINES, COLS);
-
-  screen->cols = COLS;
-  screen->rows = LINES;
-
-  /* top window */
-  screen->top_window.cols = screen->cols;
-  wresize(screen->top_window.w, 2, screen->cols);
-
-  /* main window */
-  screen->main_window.cols = screen->cols;
-  screen->main_window.rows = screen->rows-4;
-  wresize(screen->main_window.w, screen->main_window.rows, screen->cols);
-  wclear(screen->main_window.w);
-
-  /* progress window */
-  screen->progress_window.cols = screen->cols;
-  wresize(screen->progress_window.w, 1, screen->cols);
-  mvwin(screen->progress_window.w, screen->rows-2, 0);
-
-  /* status window */
-  screen->status_window.cols = screen->cols;
-  wresize(screen->status_window.w, 1, screen->cols);
-  mvwin(screen->status_window.w, screen->rows-1, 0);
-
-  screen->buf_size = screen->cols;
-  g_free(screen->buf);
-  screen->buf = g_malloc(screen->cols);
-
-  list = g_list_first(screen->screen_list);
-  while( list )
-    {
-      screen_functions_t *mode_fn = list->data;
-
-      if( mode_fn && mode_fn->resize )
-       mode_fn->resize(screen->main_window.cols, screen->main_window.rows);
-
-      list=list->next;
-    }
-
-  /* ? - without this the cursor becomes visible with aterm & Eterm */
-  curs_set(1);
-  curs_set(0);     
-
-  screen->painted = 0;
-}
-
-void 
-screen_status_message(char *msg)
-{
-  WINDOW *w = screen->status_window.w;
-
-  wmove(w, 0, 0);
-  wclrtoeol(w);
-  colors_use(w, COLOR_STATUS_ALERT);
-  waddstr(w, msg);
-  wnoutrefresh(w);
-  screen->status_timestamp = time(NULL);
-}
-
-void 
-screen_status_printf(char *format, ...)
-{
-  char buffer[STATUS_LINE_MAX_SIZE];
-  va_list ap;
-  
-  va_start(ap,format);
-  vsnprintf(buffer,sizeof(buffer),format,ap);
-  va_end(ap);
-  screen_status_message(buffer);
-}
-
-int
-screen_init(void)
-{
-  GList *list;
-
-  /* initialize the curses library */
-  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 */  
-  cbreak();       
-  /* don't echo input */
-  noecho();    
-  /* set cursor invisible */     
-  curs_set(0);     
-  /* return from getch() without blocking */
-  //  nodelay(stdscr, TRUE); 
-  keypad(stdscr, TRUE);  
-  timeout(SCREEN_TIMEOUT);
-
-  if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
-    {
-      fprintf(stderr, "Error: Screen to small!\n");
-      exit(EXIT_FAILURE);
-    }
-
-  screen = g_malloc(sizeof(screen_t));
-  memset(screen, 0, sizeof(screen_t));
-  screen->mode = SCREEN_PLAY_WINDOW;
-  screen->cols = COLS;
-  screen->rows = LINES;
-  screen->buf  = g_malloc(screen->cols);
-  screen->buf_size = screen->cols;
-  screen->findbuf = NULL;
-  screen->painted = 0;
-  screen->start_timestamp = time(NULL);
-  screen->input_timestamp = time(NULL);
-  screen->last_cmd = CMD_NONE;
-
-  /* create top window */
-  screen->top_window.rows = 2;
-  screen->top_window.cols = screen->cols;
-  screen->top_window.w = newwin(screen->top_window.rows, 
-                                 screen->top_window.cols,
-                                 0, 0);
-  leaveok(screen->top_window.w, TRUE);
-  keypad(screen->top_window.w, TRUE);  
-
-  /* create main window */
-  screen->main_window.rows = screen->rows-4;
-  screen->main_window.cols = screen->cols;
-  screen->main_window.w = newwin(screen->main_window.rows, 
-                                screen->main_window.cols,
-                                2, 
-                                0);
-
-  //  leaveok(screen->main_window.w, TRUE); temporary disabled
-  keypad(screen->main_window.w, TRUE);  
-
-  /* create progress window */
-  screen->progress_window.rows = 1;
-  screen->progress_window.cols = screen->cols;
-  screen->progress_window.w = newwin(screen->progress_window.rows, 
-                                    screen->progress_window.cols,
-                                    screen->rows-2, 
-                                    0);
-  leaveok(screen->progress_window.w, TRUE);
-  
-  /* create status window */
-  screen->status_window.rows = 1;
-  screen->status_window.cols = screen->cols;
-  screen->status_window.w = newwin(screen->status_window.rows, 
-                                  screen->status_window.cols,
-                                  screen->rows-1, 
-                                  0);
-
-  leaveok(screen->status_window.w, FALSE);
-  keypad(screen->status_window.w, TRUE);  
-
-  if( options.enable_colors )
-    {
-      /* set background attributes */
-      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 */
-  screen->screen_list = NULL;
-  screen->screen_list = g_list_append(screen->screen_list, 
-                                     (gpointer) get_screen_playlist());
-  screen->screen_list = g_list_append(screen->screen_list, 
-                                     (gpointer) get_screen_file());
-  screen->screen_list = g_list_append(screen->screen_list, 
-                                     (gpointer) get_screen_help());
-#ifdef ENABLE_KEYDEF_SCREEN
-  screen->screen_list = g_list_append(screen->screen_list, 
-                                     (gpointer) get_screen_keydef());
-#endif
-
-  list = screen->screen_list;
-  while( list )
-    {
-      screen_functions_t *fn = list->data;
-      
-      if( fn && fn->init )
-       fn->init(screen->main_window.w, 
-                screen->main_window.cols,
-                screen->main_window.rows);
-      
-      list = list->next;
-    }
-
-  mode_fn = get_screen_playlist();
-
-  return 0;
-}
-
-void 
-screen_paint(mpd_client_t *c)
-{
-  /* paint the title/header window */
-  if( mode_fn && mode_fn->get_title )
-    paint_top_window(mode_fn->get_title(), c, 1);
-  else
-    paint_top_window("", c, 1);
-
-  /* paint the main window */
-  if( mode_fn && mode_fn->paint )
-    mode_fn->paint(screen, c);
-  
-  paint_progress_window(c);
-  paint_status_window(c);
-  screen->painted = 1;
-  wmove(screen->main_window.w, 0, 0);  
-  wnoutrefresh(screen->main_window.w);
-
-  /* tell curses to update */
-  doupdate();
-}
-
-void 
-screen_update(mpd_client_t *c)
-{
-  static int repeat = -1;
-  static int random = -1;
-  static int crossfade = -1;
-  static int welcome = 1;
-  list_window_t *lw = NULL;
-
-  if( !screen->painted )
-    return screen_paint(c);
-
-  /* print a message if mpd status has changed */
-  if( repeat<0 )
-    {
-      repeat = c->status->repeat;
-      random = c->status->random;
-      crossfade = c->status->crossfade;
-    }
-  if( repeat != c->status->repeat )
-    screen_status_printf("Repeat is %s", 
-                        c->status->repeat  ? "On" : "Off");
-  if( random != c->status->random )
-    screen_status_printf("Random is %s", 
-                        c->status->random ? "On" : "Off");
-  if( crossfade != c->status->crossfade )
-    screen_status_printf("Crossfade %d seconds", c->status->crossfade);
-
-  repeat = c->status->repeat;
-  random = c->status->random;
-  crossfade = c->status->crossfade;
-
-  /* update title/header window */
-  if( welcome && screen->last_cmd==CMD_NONE &&
-      time(NULL)-screen->start_timestamp <= SCREEN_WELCOME_TIME)
-    paint_top_window("", c, 0);
-  else if( mode_fn && mode_fn->get_title )
-    {
-      paint_top_window(mode_fn->get_title(), c, 0);
-      welcome = 0;
-    }
-  else
-    paint_top_window("", c, 0);
-
-  /* update the main window */
-  if( mode_fn && mode_fn->paint )
-    mode_fn->update(screen, c);
-
-  if( mode_fn && mode_fn->get_lw )
-    lw = mode_fn->get_lw();
-
-  /* update progress window */
-  paint_progress_window(c);
-
-  /* update status window */
-  paint_status_window(c);
-
-  /* move the cursor to the selected row in the main window */
-  if( lw )
-    wmove(screen->main_window.w, LW_ROW(lw), 0);   
-  else
-    wmove(screen->main_window.w, 0, 0);   
-  wnoutrefresh(screen->main_window.w);
-
-  /* tell curses to update */
-  doupdate();
-}
-
-void
-screen_idle(mpd_client_t *c)
-{
-  if( c->seek_song_id ==  c->song_id &&
-      (screen->last_cmd == CMD_SEEK_FORWARD || 
-       screen->last_cmd == CMD_SEEK_BACKWARD) )
-    {
-      mpd_sendSeekCommand(c->connection, 
-                         c->seek_song_id, 
-                         c->seek_target_time);
-      mpd_finishCommand(c->connection);
-    }
-
-  screen->last_cmd = CMD_NONE;
-  c->seek_song_id = -1;
-}
-
-void 
-screen_cmd(mpd_client_t *c, command_t cmd)
-{
-  int n;
-  screen_mode_t new_mode = screen->mode;
-
-  screen->input_timestamp = time(NULL);
-  screen->last_cmd = cmd;
-
-  if( mode_fn && mode_fn->cmd && mode_fn->cmd(screen, c, cmd) )
-    return;
-
-  switch(cmd)
-    {
-    case CMD_PLAY:
-      mpd_sendPlayCommand(c->connection, play_get_selected());
-      mpd_finishCommand(c->connection);
-      break;
-    case CMD_PAUSE:
-      mpd_sendPauseCommand(c->connection);
-      mpd_finishCommand(c->connection);
-      break;
-    case CMD_STOP:
-      mpd_sendStopCommand(c->connection);
-      mpd_finishCommand(c->connection);
-      break;
-    case CMD_SEEK_FORWARD:
-      if( !IS_STOPPED(c->status->state) )
-       {
-         if( c->seek_song_id != c->song_id )
-           {
-             c->seek_song_id = c->song_id;
-             c->seek_target_time = c->status->elapsedTime;
-           }
-         c->seek_target_time++;
-         if( c->seek_target_time < c->status->totalTime )
-           break;
-         c->seek_target_time=0;
-       }
-      /* fall through... */
-    case CMD_TRACK_NEXT:
-      if( !IS_STOPPED(c->status->state) )
-       {
-         mpd_sendNextCommand(c->connection);
-         mpd_finishCommand(c->connection);
-       }
-      break;
-    case CMD_SEEK_BACKWARD:
-      if( !IS_STOPPED(c->status->state) )
-       {
-         if( c->seek_song_id != c->song_id )
-           {
-             c->seek_song_id = c->song_id;
-             c->seek_target_time = c->status->elapsedTime;
-           }
-         c->seek_target_time--;
-         if( c->seek_target_time < 0 )
-           c->seek_target_time=0;
-       }
-      break;
-    case CMD_TRACK_PREVIOUS:
-      if( !IS_STOPPED(c->status->state) )
-       {
-         mpd_sendPrevCommand(c->connection);
-         mpd_finishCommand(c->connection);
-       }
-      break;   
-    case CMD_SHUFFLE:
-      mpd_sendShuffleCommand(c->connection);
-      mpd_finishCommand(c->connection);
-      screen_status_message("Shuffled playlist!");
-      break;
-    case CMD_CLEAR:
-      mpd_sendClearCommand(c->connection);
-      mpd_finishCommand(c->connection);
-      file_clear_highlights(c);
-      screen_status_message("Cleared playlist!");
-      break;
-    case CMD_REPEAT:
-      n = !c->status->repeat;
-      mpd_sendRepeatCommand(c->connection, n);
-      mpd_finishCommand(c->connection);
-      break;
-    case CMD_RANDOM:
-      n = !c->status->random;
-      mpd_sendRandomCommand(c->connection, n);
-      mpd_finishCommand(c->connection);
-      break;
-    case CMD_CROSSFADE:
-      if( c->status->crossfade )
-       n = 0;
-      else
-       n = DEFAULT_CROSSFADE_TIME;
-      mpd_sendCrossfadeCommand(c->connection, n);
-      mpd_finishCommand(c->connection);
-      break;
-    case CMD_VOLUME_UP:
-      if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
-       {
-         c->status->volume=c->status->volume+1;
-         mpd_sendSetvolCommand(c->connection, c->status->volume  );
-         mpd_finishCommand(c->connection);
-       }
-      break;
-    case CMD_VOLUME_DOWN:
-      if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
-       {
-         c->status->volume=c->status->volume-1;
-         mpd_sendSetvolCommand(c->connection, c->status->volume  );
-         mpd_finishCommand(c->connection);
-       }
-      break;
-    case CMD_TOGGLE_FIND_WRAP:
-      options.find_wrap = !options.find_wrap;
-      screen_status_printf("Find mode: %s", 
-                          options.find_wrap ? "Wrapped" : "Normal");
-      break;
-    case CMD_TOGGLE_AUTOCENTER:
-      options.auto_center = !options.auto_center;
-      screen_status_printf("Auto center mode: %s", 
-                          options.auto_center ? "On" : "Off");
-      break;
-    case CMD_SCREEN_PREVIOUS:
-      if( screen->mode > SCREEN_PLAY_WINDOW )
-       new_mode = screen->mode - 1;
-      else
-       new_mode = SCREEN_HELP_WINDOW-1;
-      switch_screen_mode(new_mode, c);
-      break;
-    case CMD_SCREEN_NEXT:
-      new_mode = screen->mode + 1;
-      if( new_mode >= SCREEN_HELP_WINDOW )
-       new_mode = SCREEN_PLAY_WINDOW;
-      switch_screen_mode(new_mode, c);
-      break;
-    case CMD_SCREEN_PLAY:
-      switch_screen_mode(SCREEN_PLAY_WINDOW, c);
-      break;
-    case CMD_SCREEN_FILE:
-      switch_screen_mode(SCREEN_FILE_WINDOW, c);
-      break;
-    case CMD_SCREEN_SEARCH:
-      switch_screen_mode(SCREEN_SEARCH_WINDOW, c);
-      break;
-    case CMD_SCREEN_HELP:
-      switch_screen_mode(SCREEN_HELP_WINDOW, c);
-      break;
-#ifdef ENABLE_KEYDEF_SCREEN 
-    case CMD_SCREEN_KEYDEF:
-      switch_screen_mode(SCREEN_KEYDEF_WINDOW, c);
-      break;
-#endif
-    case CMD_QUIT:
-      exit(EXIT_SUCCESS);
-    default:
-      break;
-    }
-
-}
-
-
-
diff --git a/screen.h b/screen.h
deleted file mode 100644 (file)
index a7e6b72..0000000
--- a/screen.h
+++ /dev/null
@@ -1,113 +0,0 @@
-#ifndef SCREEN_H
-#define SCREEN_H
-#include <ncurses.h>
-#include "list_window.h"
-
-/* top window headers */
-#define TOP_HEADER_PREFIX "Music Player Client - "
-#define TOP_HEADER_PLAY   TOP_HEADER_PREFIX "Playlist"
-#define TOP_HEADER_FILE   TOP_HEADER_PREFIX "Browse"
-#define TOP_HEADER_HELP   TOP_HEADER_PREFIX "Help    "
-#define TOP_HEADER_SEARCH TOP_HEADER_PREFIX "Search  "
-
-/* minumum window size */
-#define SCREEN_MIN_COLS 14
-#define SCREEN_MIN_ROWS  5
-
-/* timeout for non blocking read [ms] */
-#define SCREEN_TIMEOUT 500
-
-/* welcome message time [s] */
-#define SCREEN_WELCOME_TIME 10
-
-#define IS_PLAYING(s) (s==MPD_STATUS_STATE_PLAY)
-#define IS_PAUSED(s) (s==MPD_STATUS_STATE_PAUSE)
-#define IS_STOPPED(s) (!(IS_PLAYING(s) | IS_PAUSED(s)))
-
-
-typedef enum
-{
-  SCREEN_PLAY_WINDOW = 0,
-  SCREEN_FILE_WINDOW,
-  SCREEN_HELP_WINDOW,
-  SCREEN_KEYDEF_WINDOW,
-  SCREEN_SEARCH_WINDOW
-
-} screen_mode_t;
-
-typedef struct
-{
-  WINDOW *w;
-  int rows, cols;
-
-} window_t;
-
-
-
-typedef struct
-{
-  window_t top_window;
-  window_t main_window;
-  window_t progress_window;
-  window_t status_window;
-
-  GList *screen_list;
-
-  time_t start_timestamp;
-  time_t status_timestamp;
-  time_t input_timestamp;
-  command_t last_cmd;
-
-  int cols, rows;
-
-  screen_mode_t mode;
-
-  char *buf;
-  size_t buf_size;
-
-  char *findbuf;
-
-  int painted;
-
-} screen_t;
-
-
-typedef void (*screen_init_fn_t)   (WINDOW *w, int cols, int rows);
-typedef void (*screen_exit_fn_t)   (void);
-typedef void (*screen_open_fn_t)   (screen_t *screen, mpd_client_t *c);
-typedef void (*screen_close_fn_t)  (void);
-typedef void (*screen_resize_fn_t)   (int cols, int rows);
-typedef void (*screen_paint_fn_t)  (screen_t *screen, mpd_client_t *c);
-typedef void (*screen_update_fn_t) (screen_t *screen, mpd_client_t *c);
-typedef int (*screen_cmd_fn_t) (screen_t *scr, mpd_client_t *c, command_t cmd);
-typedef char * (*screen_title_fn_t) (void);
-typedef list_window_t * (*screen_get_lw_fn_t) (void);
-
-typedef struct
-{
-  screen_init_fn_t   init;
-  screen_exit_fn_t   exit;
-  screen_open_fn_t   open;
-  screen_close_fn_t  close;
-  screen_resize_fn_t resize;
-  screen_paint_fn_t  paint;
-  screen_update_fn_t update;
-  screen_cmd_fn_t    cmd;
-  screen_title_fn_t  get_title;
-  screen_get_lw_fn_t get_lw;
-
-} screen_functions_t;
-
-
-int screen_init(void);
-int screen_exit(void);
-void screen_resize(void);
-void screen_status_message(char *msg);
-void screen_status_printf(char *format, ...);
-char *screen_error(void);
-void screen_paint(mpd_client_t *c);
-void screen_update(mpd_client_t *c);
-void screen_idle(mpd_client_t *c);
-void screen_cmd(mpd_client_t *c, command_t cmd);
-
-#endif
diff --git a/screen_file.c b/screen_file.c
deleted file mode 100644 (file)
index d2b1f78..0000000
+++ /dev/null
@@ -1,503 +0,0 @@
-/* 
- * (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 <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-#include "support.h"
-#include "libmpdclient.h"
-#include "mpc.h"
-#include "command.h"
-#include "screen.h"
-#include "screen_utils.h"
-#include "screen_play.h"
-#include "screen_file.h"
-
-#define BUFSIZE 1024
-#define TITLESIZE 256
-
-#define USE_OLD_LAYOUT
-
-static list_window_t *lw;
-static mpd_client_t *mpc = NULL;
-
-static char *
-list_callback(int index, int *highlight, void *data)
-{
-  static char buf[BUFSIZE];
-  mpd_client_t *c = (mpd_client_t *) data;
-  filelist_entry_t *entry;
-  mpd_InfoEntity *entity;
-
-  *highlight = 0;
-  if( (entry=(filelist_entry_t *) g_list_nth_data(c->filelist, index))==NULL )
-    return NULL;
-
-  entity = entry->entity;
-  *highlight = entry->selected;
-
-  if( entity == NULL )
-    {
-#ifdef USE_OLD_LAYOUT
-      return "[..]";
-#else
-      return "d ..";
-#endif
-    }
-  if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY ) 
-    {
-      mpd_Directory *dir = entity->info.directory;
-      char *dirname = utf8_to_locale(basename(dir->path));
-
-#ifdef USE_OLD_LAYOUT
-      snprintf(buf, BUFSIZE, "[%s]", dirname);
-#else
-      snprintf(buf, BUFSIZE, "d %s", dirname);
-#endif
-      g_free(dirname);
-      return buf;
-    }
-  else if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-    {
-      mpd_Song *song = entity->info.song;
-
-#ifdef USE_OLD_LAYOUT      
-      return mpc_get_song_name(song);
-#else
-      snprintf(buf, BUFSIZE, "m %s", mpc_get_song_name(song));
-      return buf;
-#endif
-
-    }
-  else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
-    {
-      mpd_PlaylistFile *plf = entity->info.playlistFile;
-      char *filename = utf8_to_locale(basename(plf->path));
-
-#ifdef USE_OLD_LAYOUT      
-      snprintf(buf, BUFSIZE, "*%s*", filename);
-#else      
-      snprintf(buf, BUFSIZE, "p %s", filename);
-#endif
-      g_free(filename);
-      return buf;
-    }
-  return "Error: Unknow entry!";
-}
-
-static int
-change_directory(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
-{
-  mpd_InfoEntity *entity = entry->entity;
-
-  if( entity==NULL )
-    {
-      char *parent = g_path_get_dirname(c->cwd);
-
-      if( strcmp(parent,".") == 0 )
-       {
-         parent[0] = '\0';
-       }
-      if( c->cwd )
-       g_free(c->cwd);
-      c->cwd = parent;
-    }
-  else
-    if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
-      {
-       mpd_Directory *dir = entity->info.directory;
-       if( c->cwd )
-         g_free(c->cwd);
-       c->cwd = g_strdup(dir->path);      
-      }
-    else
-      return -1;
-  
-  mpc_update_filelist(c);
-  list_window_reset(lw);
-  return 0;
-}
-
-static int
-load_playlist(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
-{
-  mpd_InfoEntity *entity = entry->entity;
-  mpd_PlaylistFile *plf = entity->info.playlistFile;
-  char *filename = utf8_to_locale(basename(plf->path));
-
-  mpd_sendLoadCommand(c->connection, plf->path);
-  mpd_finishCommand(c->connection);
-
-  screen_status_printf("Loading playlist %s...", filename);
-  g_free(filename);
-  return 0;
-}
-
-static int 
-handle_delete(screen_t *screen, mpd_client_t *c)
-{
-  filelist_entry_t *entry;
-  mpd_InfoEntity *entity;
-  mpd_PlaylistFile *plf;
-  char *str, buf[BUFSIZE];
-  int key;
-
-  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
-  if( entry==NULL || entry->entity==NULL )
-    return -1;
-
-  entity = entry->entity;
-
-  if( entity->type!=MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
-    {
-      screen_status_printf("You can only delete playlists!");
-      beep();
-      return -1;
-    }
-
-  plf = entity->info.playlistFile;
-  str = utf8_to_locale(basename(plf->path));
-  snprintf(buf, BUFSIZE, "Delete playlist %s [y/n] ? ", str);
-  g_free(str);  
-  key = tolower(screen_getch(screen->status_window.w, buf));
-  if( key==KEY_RESIZE )
-    screen_resize();
-  if( key!='y' )
-    {
-      screen_status_printf("Aborted!");
-      return 0;
-    }
-
-  mpd_sendRmCommand(c->connection, plf->path);
-  mpd_finishCommand(c->connection);
-  if( mpc_error(c))
-    {
-      str = utf8_to_locale(mpc_error_str(c));
-      screen_status_printf("Error: %s", str);
-      g_free(str);
-      beep();
-      return -1;
-    }
-  screen_status_printf("Playlist deleted!");
-  mpc_update_filelist(c);
-  list_window_check_selected(lw, c->filelist_length);
-  return 0;
-}
-
-
-static int
-handle_play_cmd(screen_t *screen, mpd_client_t *c)
-{
-  filelist_entry_t *entry;
-  mpd_InfoEntity *entity;
-  
-  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
-  if( entry==NULL )
-    return -1;
-
-  entity = entry->entity;
-  if( entity==NULL || entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
-    return change_directory(screen, c, entry);
-  else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
-    return load_playlist(screen, c, entry);
-  return -1;
-}
-
-static int
-add_directory(mpd_client_t *c, char *dir)
-{
-  mpd_InfoEntity *entity;
-  GList *subdir_list = NULL;
-  GList *list = NULL;
-  char *dirname;
-
-  dirname = utf8_to_locale(dir);
-  screen_status_printf("Adding directory %s...\n", dirname);
-  doupdate(); 
-  g_free(dirname);
-  dirname = NULL;
-
-  mpd_sendLsInfoCommand(c->connection, dir);
-  mpd_sendCommandListBegin(c->connection);
-  while( (entity=mpd_getNextInfoEntity(c->connection)) )
-    {
-      if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-       {
-         mpd_Song *song = entity->info.song;
-         mpd_sendAddCommand(c->connection, song->file);
-         mpd_freeInfoEntity(entity);
-       }
-      else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
-       {
-         subdir_list = g_list_append(subdir_list, (gpointer) entity); 
-       }
-      else
-       mpd_freeInfoEntity(entity);
-    }
-  mpd_sendCommandListEnd(c->connection);
-  mpd_finishCommand(c->connection);
-  
-  list = g_list_first(subdir_list);
-  while( list!=NULL )
-    {
-      mpd_Directory *dir;
-
-      entity = list->data;
-      dir = entity->info.directory;
-      add_directory(c, dir->path);
-      mpd_freeInfoEntity(entity);
-      list->data=NULL;
-      list=list->next;
-    }
-  g_list_free(subdir_list);
-  return 0;
-}
-
-static int
-handle_select(screen_t *screen, mpd_client_t *c)
-{
-  filelist_entry_t *entry;
-
-  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
-  if( entry==NULL || entry->entity==NULL)
-    return -1;
-
-  if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
-    {
-      mpd_Directory *dir = entry->entity->info.directory;
-      add_directory(c, dir->path);
-      return 0;
-    }
-
-  if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
-    return -1; 
-
-  entry->selected = !entry->selected;
-
-  if( entry->selected )
-    {
-      if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-       {
-         mpd_Song *song = entry->entity->info.song;
-
-         playlist_add_song(c, song);
-
-         screen_status_printf("Adding \'%s\' to playlist\n", 
-                              mpc_get_song_name(song));
-       }
-    }
-  else
-    {
-      /* remove song from playlist */
-      if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-       {
-         mpd_Song *song = entry->entity->info.song;
-
-         if( song )
-           {
-             int index = mpc_playlist_get_song_index(c, song->file);
-             
-             while( (index=mpc_playlist_get_song_index(c, song->file))>=0 )
-               playlist_delete_song(c, index);
-           }
-       }
-    }
-  return 0;
-}
-
-static void
-file_init(WINDOW *w, int cols, int rows)
-{
-  lw = list_window_init(w, cols, rows);
-}
-
-static void
-file_resize(int cols, int rows)
-{
-  lw->cols = cols;
-  lw->rows = rows;
-}
-
-static void
-file_exit(void)
-{
-  list_window_free(lw);
-}
-
-static void 
-file_open(screen_t *screen, mpd_client_t *c)
-{
-  if( c->filelist == NULL )
-    {
-      mpc_update_filelist(c);
-    }
-  mpc = c;
-}
-
-static void
-file_close(void)
-{
-}
-
-static char *
-file_title(void)
-{
-  static char buf[TITLESIZE];
-  char *tmp;
-
-  tmp = utf8_to_locale(basename(mpc->cwd));
-  snprintf(buf, TITLESIZE, 
-          TOP_HEADER_FILE ": %s                          ",
-          tmp
-          );
-  g_free(tmp);
-
-  return buf;
-}
-
-static void 
-file_paint(screen_t *screen, mpd_client_t *c)
-{
-  lw->clear = 1;
-  
-  list_window_paint(lw, list_callback, (void *) c);
-  wnoutrefresh(lw->w);
-}
-
-static void 
-file_update(screen_t *screen, mpd_client_t *c)
-{
-  if( c->filelist_updated )
-    {
-      file_paint(screen, c);
-      c->filelist_updated = 0;
-      return;
-    }
-  list_window_paint(lw, list_callback, (void *) c);
-  wnoutrefresh(lw->w);
-}
-
-
-static int 
-file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
-{
-  switch(cmd)
-    {
-    case CMD_PLAY:
-      handle_play_cmd(screen, c);
-      return 1;
-    case CMD_SELECT:
-      if( handle_select(screen, c) == 0 )
-       {
-         /* continue and select next item... */
-         cmd = CMD_LIST_NEXT;
-       }
-      break;
-    case CMD_DELETE:
-      handle_delete(screen, c);
-      break;
-    case CMD_SCREEN_UPDATE:
-      mpc_update_filelist(c);
-      list_window_check_selected(lw, c->filelist_length);
-      screen_status_printf("Screen updated!");
-      return 1;
-    case CMD_LIST_FIND:
-    case CMD_LIST_RFIND:
-    case CMD_LIST_FIND_NEXT:
-    case CMD_LIST_RFIND_NEXT:
-      return screen_find(screen, c, 
-                        lw, c->filelist_length,
-                        cmd, list_callback);
-    default:
-      break;
-    }
-  return list_window_cmd(lw, c->filelist_length, cmd);
-}
-
-
-list_window_t *
-get_filelist_window()
-{
-  return lw;
-}
-
-
-void
-file_clear_highlights(mpd_client_t *c)
-{
-  GList *list = g_list_first(c->filelist);
-  
-  while( list )
-    {
-      filelist_entry_t *entry = list->data;
-
-      entry->selected = 0;
-      list = list->next;
-    }
-}
-
-void
-file_set_highlight(mpd_client_t *c, mpd_Song *song, int highlight)
-{
-  GList *list = g_list_first(c->filelist);
-
-  if( !song )
-    return;
-
-  while( list )
-    {
-      filelist_entry_t *entry = list->data;
-      mpd_InfoEntity *entity  = entry->entity;
-
-      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-       {
-         mpd_Song *song2 = entity->info.song;
-
-         if( strcmp(song->file, song2->file) == 0 )
-           {
-             entry->selected = highlight;
-           }
-       }
-      list = list->next;
-    }
-}
-
-screen_functions_t *
-get_screen_file(void)
-{
-  static screen_functions_t functions;
-
-  memset(&functions, 0, sizeof(screen_functions_t));
-  functions.init   = file_init;
-  functions.exit   = file_exit;
-  functions.open   = file_open;
-  functions.close  = file_close;
-  functions.resize = file_resize;
-  functions.paint  = file_paint;
-  functions.update = file_update;
-  functions.cmd    = file_cmd;
-  functions.get_lw = get_filelist_window;
-  functions.get_title = file_title;
-
-  return &functions;
-}
-
diff --git a/screen_file.h b/screen_file.h
deleted file mode 100644 (file)
index a7199a6..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-void file_set_highlight(mpd_client_t *c, mpd_Song *song, int hightlight);
-void file_clear_highlights(mpd_client_t *c);
-
-list_window_t *get_filelist_window(void);
-
-screen_functions_t *get_screen_file(void);
diff --git a/screen_help.c b/screen_help.c
deleted file mode 100644 (file)
index c55c963..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/* 
- * (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 <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-#include "libmpdclient.h"
-#include "mpc.h"
-#include "command.h"
-#include "screen.h"
-#include "screen_utils.h"
-#include "screen_help.h"
-
-
-typedef struct
-{
-  signed char highlight;
-  command_t command;
-  char *text;
-} help_text_row_t;
-
-static help_text_row_t help_text[] = 
-{
-  { 1, CMD_NONE,  "          Movement keys  " },
-  { 0, CMD_NONE,  "        -----------------" },
-  { 0, CMD_LIST_PREVIOUS,  NULL },
-  { 0, CMD_LIST_NEXT,      NULL },
-  { 0, CMD_LIST_PREVIOUS_PAGE, NULL }, 
-  { 0, CMD_LIST_NEXT_PAGE, NULL },
-  { 0, CMD_LIST_FIRST,     NULL },
-  { 0, CMD_LIST_LAST,      NULL },
-  { 0, CMD_NONE,           NULL },
-  { 0, CMD_SCREEN_NEXT,    NULL },
-  { 0, CMD_SCREEN_HELP,    NULL },
-  { 0, CMD_SCREEN_PLAY,    NULL },
-  { 0, CMD_SCREEN_FILE,    NULL },
-#ifdef ENABLE_KEYDEF_SCREEN
-  { 0, CMD_SCREEN_KEYDEF,  NULL },
-#endif
-
-  { 0, CMD_NONE,           NULL },
-  { 0, CMD_NONE,           NULL },
-  { 1, CMD_NONE, "          General keys " },
-  { 0, CMD_NONE, "        ----------------" },
-  { 0, CMD_STOP,           NULL },
-  { 0, CMD_PAUSE,          NULL },
-  { 0, CMD_TRACK_NEXT,     NULL },
-  { 0, CMD_TRACK_PREVIOUS, NULL },
-  { 0, CMD_SEEK_FORWARD,   NULL },
-  { 0, CMD_SEEK_BACKWARD,  NULL },
-  { 0, CMD_VOLUME_DOWN,    NULL },
-  { 0, CMD_VOLUME_UP,      NULL },
-  { 0, CMD_NONE,           NULL },
-  { 0, CMD_SHUFFLE,        NULL },
-  { 0, CMD_REPEAT,         NULL },
-  { 0, CMD_RANDOM,         NULL },
-  { 0, CMD_CROSSFADE,      NULL },
-  { 0, CMD_NONE,           NULL },
-  { 0, CMD_QUIT,           NULL },
-
-  { 0, CMD_NONE,           NULL },
-  { 0, CMD_NONE,           NULL },
-  { 1, CMD_NONE, "          Keys - Playlist screen " },
-  { 0, CMD_NONE, "        --------------------------" },
-  { 0, CMD_PLAY,           "Play" },
-  { 0, CMD_DELETE,         NULL },
-  { 0, CMD_CLEAR,          NULL },
-  { 0, CMD_LIST_MOVE_UP,   "Move song up" },
-  { 0, CMD_LIST_MOVE_DOWN, "Move song down" },
-  { 0, CMD_SAVE_PLAYLIST,  NULL },
-  { 0, CMD_SCREEN_UPDATE,  "Center" },
-  { 0, CMD_TOGGLE_AUTOCENTER, NULL },
-
-  { 0, CMD_NONE,           NULL },
-  { 0, CMD_NONE,           NULL },
-  { 1, CMD_NONE, "          Keys - Browse screen " },
-  { 0, CMD_NONE, "        ------------------------" },
-  { 0, CMD_PLAY,            "Enter directory" },
-  { 0, CMD_SELECT,          NULL },
-  { 0, CMD_DELETE,          NULL },
-  { 0, CMD_SCREEN_UPDATE,   NULL },
-
-  { 0, CMD_NONE,           NULL },
-  { 0, CMD_NONE,           NULL },
-  { 1, CMD_NONE, "               Find keys " },
-  { 0, CMD_NONE, "              -------------" },
-  { 0, CMD_LIST_FIND,      NULL },
-  { 0, CMD_LIST_RFIND,     NULL },
-  { 0, CMD_LIST_FIND_NEXT, NULL },
-  { 0, CMD_LIST_RFIND_NEXT,  NULL },
-  { 0, CMD_TOGGLE_FIND_WRAP, NULL },
-
-  { 0, CMD_NONE, NULL },
-  { 0, CMD_NONE, NULL },
-  { 1, CMD_NONE, "          ncmpc build information " },
-  { 0, CMD_NONE, "         ---------------------------" },
-  { 0, CMD_NONE, "             Version : " VERSION },
-  { 0, CMD_NONE, "  Configuration dirs : ~/.ncmpc, " SYSCONFDIR "/" PACKAGE },
-#ifdef ENABLE_KEYDEF_SCREEN
-  { 0, CMD_NONE, "          Key Editor : yes" },
-#else
-  { 0, CMD_NONE, "          Key Editor : no" },
-#endif
-
-  { 0, CMD_NONE, NULL },
-  {-1, CMD_NONE, NULL }
-};
-
-static int help_text_rows = -1;
-static list_window_t *lw = NULL;
-
-
-static char *
-list_callback(int index, int *highlight, void *data)
-{
-  static char buf[256];
-
-  if( help_text_rows<0 )
-    {
-      help_text_rows = 0;
-      while( help_text[help_text_rows].highlight != -1 )
-       help_text_rows++;
-    }
-
-  *highlight = 0;
-  if( index<help_text_rows )
-    {
-      *highlight = help_text[index].highlight > 0;
-      if( help_text[index].command == CMD_NONE )
-       {
-         if( help_text[index].text )
-           return help_text[index].text;
-         else
-           return "  ";
-       }
-      if( help_text[index].text )
-       snprintf(buf, 256, 
-                "%20s : %s   ", 
-                get_key_names(help_text[index].command, TRUE),
-                help_text[index].text);
-      else
-       snprintf(buf, 256, 
-                "%20s : %s   ", 
-                get_key_names(help_text[index].command, TRUE),
-                get_key_description(help_text[index].command));
-      return buf;
-    }
-
-  return NULL;
-}
-
-static void
-help_init(WINDOW *w, int cols, int rows)
-{
-  lw = list_window_init(w, cols, rows);
-}
-
-static void
-help_resize(int cols, int rows)
-{
-  lw->cols = cols;
-  lw->rows = rows;
-}
-
-static void
-help_exit(void)
-{
-  list_window_free(lw);
-}
-
-
-static char *
-help_title(void)
-{
-  return (TOP_HEADER_PREFIX "Help");
-}
-
-static void 
-help_paint(screen_t *screen, mpd_client_t *c)
-{
-  lw->clear = 1;
-  list_window_paint(lw, list_callback, NULL);
-  wrefresh(lw->w);
-}
-
-static void 
-help_update(screen_t *screen, mpd_client_t *c)
-{  
-  if( lw->repaint )
-    {
-      list_window_paint(lw, list_callback, NULL);
-      wrefresh(lw->w);
-      lw->repaint = 0;
-    }
-}
-
-
-static int 
-help_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
-{
-  int retval;
-
-  retval = list_window_cmd(lw, help_text_rows, cmd);
-  if( !retval )
-    return screen_find(screen, c, 
-                      lw,  help_text_rows,
-                      cmd, list_callback);
-
-  return retval;
-}
-
-static list_window_t *
-help_lw(void)
-{
-  return lw;
-}
-
-screen_functions_t *
-get_screen_help(void)
-{
-  static screen_functions_t functions;
-
-  memset(&functions, 0, sizeof(screen_functions_t));
-  functions.init   = help_init;
-  functions.exit   = help_exit;
-  functions.open   = NULL;
-  functions.close  = NULL;
-  functions.resize = help_resize;
-  functions.paint  = help_paint;
-  functions.update = help_update;
-  functions.cmd    = help_cmd;
-  functions.get_lw = help_lw;
-  functions.get_title = help_title;
-
-  return &functions;
-}
diff --git a/screen_help.h b/screen_help.h
deleted file mode 100644 (file)
index ba2c57c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-screen_functions_t *get_screen_help(void);
diff --git a/screen_keydef.c b/screen_keydef.c
deleted file mode 100644 (file)
index 4bda6ea..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/* 
- * (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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-
-#ifdef  ENABLE_KEYDEF_SCREEN
-#include "libmpdclient.h"
-#include "options.h"
-#include "conf.h"
-#include "mpc.h"
-#include "command.h"
-#include "screen.h"
-#include "screen_utils.h"
-
-#define STATIC_ITEMS      0
-#define STATIC_SUB_ITEMS  1
-#define BUFSIZE 256
-
-#define LIST_ITEM_APPLY()   (command_list_length)
-#define LIST_ITEM_SAVE()    (LIST_ITEM_APPLY()+1)
-#define LIST_LENGTH()       (LIST_ITEM_SAVE()+1)
-
-#define LIST_ITEM_SAVE_LABEL  "===> Apply & Save key bindings  "
-#define LIST_ITEM_APPLY_LABEL "===> Apply key bindings "
-
-
-static list_window_t *lw = NULL;
-static int command_list_length = 0;
-static command_definition_t *cmds = NULL;
-
-static int subcmd = -1;
-static int subcmd_length = 0;
-static int subcmd_addpos = 0;
-
-static int
-keybindings_changed(void)
-{
-  command_definition_t *orginal_cmds = get_command_definitions();
-  size_t size = command_list_length*sizeof(command_definition_t);
-  
-  return memcmp(orginal_cmds, cmds, size);
-}
-
-static void
-apply_keys(void)
-{
-  if( keybindings_changed() )
-    {
-      command_definition_t *orginal_cmds = get_command_definitions();
-      size_t size = command_list_length*sizeof(command_definition_t);
-
-      memcpy(orginal_cmds, cmds, size);
-      screen_status_printf("You have new key bindings!");
-    }
-  else
-    screen_status_printf("Keybindings unchanged.");
-}
-
-static int
-save_keys(void)
-{
-  FILE *f;
-  char *filename;
-
-  if( check_user_conf_dir() )
-    {
-      screen_status_printf("Error: Unable to create direcory ~/.ncmpc - %s", 
-                          strerror(errno));
-      beep();
-      return -1;
-    }
-
-  filename = get_user_key_binding_filename();
-
-  if( (f=fopen(filename,"w")) == NULL )
-    {
-      screen_status_printf("Error: %s - %s", filename, strerror(errno));
-      beep();
-      g_free(filename);
-      return -1;
-    }
-  if( write_key_bindings(f) )
-    screen_status_printf("Error: %s - %s", filename, strerror(errno));
-  else
-    screen_status_printf("Wrote %s", filename);
-  
-  g_free(filename);
-  return fclose(f);
-}
-
-static void
-check_subcmd_length(void)
-{
-  subcmd_length = 0;
-  while( subcmd_length<MAX_COMMAND_KEYS && cmds[subcmd].keys[subcmd_length]>0 )
-   subcmd_length ++;
-
-  if( subcmd_length<MAX_COMMAND_KEYS )
-    {
-      subcmd_addpos = subcmd_length;
-      subcmd_length++;
-    }
-  else
-    subcmd_addpos = 0;
-  subcmd_length += STATIC_SUB_ITEMS;
-}
-
-static void
-delete_key(int cmd_index, int key_index)
-{
-  int i = key_index+1;
-
-  screen_status_printf("Delete...");
-  while( i<MAX_COMMAND_KEYS && cmds[cmd_index].keys[i] )
-    cmds[cmd_index].keys[key_index++] = cmds[cmd_index].keys[i++];
-  cmds[cmd_index].keys[key_index] = 0;
-
-  check_subcmd_length();
-  lw->clear = 1;
-  lw->repaint = 1;
-}
-
-static void
-assign_new_key(WINDOW *w, int cmd_index, int key_index)
-{
-  int key;
-  char buf[BUFSIZE];
-  command_t cmd;
-
-  snprintf(buf, BUFSIZE, "Enter new key for %s: ", cmds[cmd_index].name);
-  key = screen_getch(w, buf);
-  if( key==KEY_RESIZE )
-    screen_resize();
-  if( key==ERR )
-    {
-      screen_status_printf("Aborted!");
-      return;
-    }
-  cmd = find_key_command(key, cmds);
-  if( cmd!=CMD_NONE && cmd!= cmds[cmd_index].command )
-    {
-      screen_status_printf("Error: key %s is already used for %s", 
-                          key2str(key),
-                          get_key_command_name(cmd));
-      beep();
-      return;
-    }
-  cmds[cmd_index].keys[key_index] = key;
-  screen_status_printf("Assigned %s to %s", key2str(key),cmds[cmd_index].name);
-  check_subcmd_length();
-  lw->repaint = 1;
-}
-
-static char *
-list_callback(int index, int *highlight, void *data)
-{
-  static char buf[BUFSIZE];
-
-  if( subcmd <0 )
-    {
-      if( index<command_list_length )
-       return cmds[index].name;
-      else if( index==LIST_ITEM_APPLY() )
-       return LIST_ITEM_APPLY_LABEL;
-      else if( index==LIST_ITEM_SAVE() )
-       return LIST_ITEM_SAVE_LABEL;
-    }
-  else
-  {
-    if( index== 0 )
-      return "[..]";
-    index--;
-    if( index<MAX_COMMAND_KEYS && cmds[subcmd].keys[index]>0 )
-      {
-       snprintf(buf, 
-                BUFSIZE, "%d. %-20s   (%d) ", 
-                index+1, 
-                key2str(cmds[subcmd].keys[index]),
-                cmds[subcmd].keys[index]);
-       return buf;
-      } 
-    else if ( index==subcmd_addpos )
-      {
-       snprintf(buf, BUFSIZE, "%d. Add new key ", index+1 );
-       return buf;
-      }
-  }
-  
-  return NULL;
-}
-
-static void 
-keydef_init(WINDOW *w, int cols, int rows)
-{
-  lw = list_window_init(w, cols, rows);
-}
-
-static void
-keydef_resize(int cols, int rows)
-{
-  lw->cols = cols;
-  lw->rows = rows;
-}
-
-static void 
-keydef_exit(void)
-{
-  list_window_free(lw);
-  if( cmds )
-    g_free(cmds);
-  cmds = NULL;
-  lw = NULL;
-}
-
-static void 
-keydef_open(screen_t *screen, mpd_client_t *c)
-{
-  if( cmds == NULL )
-    {
-      command_definition_t *current_cmds = get_command_definitions();
-      size_t cmds_size;
-
-      command_list_length = 0;
-      while( current_cmds[command_list_length].name )
-       command_list_length++;
-
-      cmds_size = (command_list_length+1)*sizeof(command_definition_t);
-      cmds = g_malloc0(cmds_size);
-      memcpy(cmds, current_cmds, cmds_size);
-      command_list_length += STATIC_ITEMS;
-      screen_status_printf("Welcome to the key editor!");
-    }
-
-  subcmd = -1;
-  list_window_check_selected(lw, LIST_LENGTH());  
-}
-
-static void 
-keydef_close(void)
-{
-  if( cmds && !keybindings_changed() )
-    {
-      g_free(cmds);
-      cmds = NULL;
-    }
-  else
-    screen_status_printf("Note: Did you forget to \'Apply\' your changes?");
-}
-
-static char *
-keydef_title(void)
-{
-  static char buf[BUFSIZE];
-
-  if( subcmd<0 )
-    return (TOP_HEADER_PREFIX "Edit key bindings");
-  
-  snprintf(buf, BUFSIZE, 
-          TOP_HEADER_PREFIX "Edit keys for %s", 
-          cmds[subcmd].name);
-  return buf;
-}
-
-static void 
-keydef_paint(screen_t *screen, mpd_client_t *c)
-{
-  lw->clear = 1;
-  list_window_paint(lw, list_callback, NULL);
-  wrefresh(lw->w);
-}
-
-static void 
-keydef_update(screen_t *screen, mpd_client_t *c)
-{  
-  if( lw->repaint )
-    {
-      list_window_paint(lw, list_callback, NULL);
-      wrefresh(lw->w);
-      lw->repaint = 0;
-    }
-}
-
-static int 
-keydef_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
-{
-  int length = LIST_LENGTH();
-
-  if( subcmd>=0 )
-    length = subcmd_length;
-
-  switch(cmd)
-    {
-    case CMD_PLAY:
-      if( subcmd<0 )
-       {
-         if( lw->selected == LIST_ITEM_APPLY() )
-           apply_keys();
-         else if( lw->selected == LIST_ITEM_SAVE() )
-           {
-             apply_keys();
-             save_keys();
-           }
-         else
-           {
-             subcmd = lw->selected;
-             lw->selected=0;
-             check_subcmd_length();
-           }
-       }
-      else
-       {
-         if( lw->selected == 0 ) /* up */
-           {
-             lw->selected = subcmd;
-             subcmd = -1;
-           }
-         else
-           assign_new_key(screen->status_window.w, 
-                          subcmd,
-                          lw->selected-STATIC_SUB_ITEMS);
-       }
-      lw->repaint = 1;
-      lw->clear = 1;
-      return 1;
-    case CMD_DELETE:
-      if( subcmd>=0 && lw->selected-STATIC_SUB_ITEMS>=0 )
-       delete_key(subcmd, lw->selected-STATIC_SUB_ITEMS);
-      return 1;
-      break;
-    case CMD_LIST_FIND:
-    case CMD_LIST_RFIND:
-    case CMD_LIST_FIND_NEXT:
-    case CMD_LIST_RFIND_NEXT:
-      return screen_find(screen, c, 
-                        lw,  length,
-                        cmd, list_callback);
-
-    default:
-      break;
-    }
-
-  return list_window_cmd(lw, length, cmd);
-}
-
-static list_window_t *
-keydef_lw(void)
-{
-  return lw;
-}
-
-screen_functions_t *
-get_screen_keydef(void)
-{
-  static screen_functions_t functions;
-
-  memset(&functions, 0, sizeof(screen_functions_t));
-  functions.init   = keydef_init;
-  functions.exit   = keydef_exit;
-  functions.open   = keydef_open;
-  functions.close  = keydef_close;
-  functions.resize = keydef_resize;
-  functions.paint  = keydef_paint;
-  functions.update = keydef_update;
-  functions.cmd    = keydef_cmd;
-  functions.get_lw = keydef_lw;
-  functions.get_title = keydef_title;
-
-  return &functions;
-}
-
-
-#endif
diff --git a/screen_play.c b/screen_play.c
deleted file mode 100644 (file)
index cdec4f7..0000000
+++ /dev/null
@@ -1,390 +0,0 @@
-/* 
- * (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 <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-#include "options.h"
-#include "support.h"
-#include "libmpdclient.h"
-#include "mpc.h"
-#include "command.h"
-#include "screen.h"
-#include "screen_utils.h"
-#include "screen_file.h"
-#include "screen_play.h"
-
-#ifdef DEBUG
-#define D(x) x
-#else
-#define D(x)
-#endif
-
-#define BUFSIZE 256
-
-static list_window_t *lw = NULL;
-
-static char *
-list_callback(int index, int *highlight, void *data)
-{
-  mpd_client_t *c = (mpd_client_t *) data;
-  mpd_Song *song;
-
-  *highlight = 0;
-  if( (song=mpc_playlist_get_song(c, index)) == NULL )
-    {
-      return NULL;
-    }
-
-  if( index==c->song_id && !IS_STOPPED(c->status->state) )
-    {
-      *highlight = 1;
-    }
-
-  return mpc_get_song_name(song);
-}
-
-static int
-center_playing_item(screen_t *screen, mpd_client_t *c)
-{
-  int length = c->playlist_length;
-  int offset = lw->selected-lw->start;
-  
-  if( !lw || length<lw->rows || IS_STOPPED(c->status->state) )
-    return 0;
-
-  /* try to center the song that are playing */
-  lw->start = c->song_id-(lw->rows/2);
-  if( lw->start+lw->rows > length )
-    lw->start = length-lw->rows;
-  if( lw->start<0 )
-    lw->start=0;
-
-  /* make sure the cursor is in the window */
-  lw->selected = lw->start+offset;
-  list_window_check_selected(lw, length);
-
-  lw->clear = 1;
-  lw->repaint = 1;
-
-  return 0;
-}
-
-static int
-handle_save_playlist(screen_t *screen, mpd_client_t *c)
-{
-  char *filename, *filename_utf8;
-
-  filename=screen_getstr(screen->status_window.w, "Save playlist as: ");
-  filename=trim(filename);
-  if( filename==NULL || filename[0]=='\0' )
-    return -1;
-  /* convert filename to utf-8 */
-  filename_utf8 = locale_to_utf8(filename);
-  /* send save command to mpd */
-  mpd_sendSaveCommand(c->connection, filename_utf8);
-  mpd_finishCommand(c->connection);
-  g_free(filename_utf8);
-  /* handle errors */
-  if( mpc_error(c))
-    {
-      if(  mpc_error_str(c) )
-       {
-         char *str = utf8_to_locale(mpc_error_str(c));
-         screen_status_message(str);
-         g_free(str);
-       }
-      else
-       screen_status_printf("Error: Unable to save playlist as %s", filename);
-      mpd_clearError(c->connection);
-      beep();
-      return -1;
-    }
-  /* success */
-  screen_status_printf("Saved %s", filename);
-  g_free(filename);
-  /* update the file list if it has been initalized */
-  if( c->filelist )
-    {
-      list_window_t *file_lw = get_filelist_window();
-
-      mpc_update_filelist(c);
-      list_window_check_selected(file_lw, c->filelist_length);
-    }
-  return 0;
-}
-
-static void
-play_init(WINDOW *w, int cols, int rows)
-{
-  lw = list_window_init(w, cols, rows);
-}
-
-static void
-play_resize(int cols, int rows)
-{
-  lw->cols = cols;
-  lw->rows = rows;
-}
-
-
-static void
-play_exit(void)
-{
-  list_window_free(lw);
-}
-
-static char *
-play_title(void)
-{
-  return (TOP_HEADER_PREFIX "Playlist");
-}
-
-static void
-play_paint(screen_t *screen, mpd_client_t *c)
-{ 
-  lw->clear = 1;
-
-  list_window_paint(lw, list_callback, (void *) c);
-  wnoutrefresh(lw->w);
-}
-
-static void
-play_update(screen_t *screen, mpd_client_t *c)
-{
-  if( options.auto_center )
-    {
-      static int prev_song_id = 0;
-      
-      if( prev_song_id != c->song_id ) 
-       {
-         center_playing_item(screen, c);
-         prev_song_id = c->song_id;
-       }
-    }
-
-  if( c->playlist_updated )
-    {
-      if( lw->selected >= c->playlist_length )
-       lw->selected = c->playlist_length-1;
-      if( lw->start    >= c->playlist_length )
-       list_window_reset(lw);
-
-      play_paint(screen, c);
-      c->playlist_updated = 0;
-    }
-  else if( lw->repaint || 1)
-    {
-      list_window_paint(lw, list_callback, (void *) c);
-      wnoutrefresh(lw->w);
-      lw->repaint = 0;
-    }
-}
-
-static int
-play_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
-{
-  switch(cmd)
-    {
-    case CMD_DELETE:
-      playlist_delete_song(c, lw->selected);
-      return 1;
-    case CMD_SAVE_PLAYLIST:
-      handle_save_playlist(screen, c);
-      return 1;
-    case CMD_SCREEN_UPDATE:
-      center_playing_item(screen, c);
-      return 1;
-    case CMD_LIST_MOVE_UP:
-      playlist_move_song(c, lw->selected, lw->selected-1);
-      break;
-    case CMD_LIST_MOVE_DOWN:
-      playlist_move_song(c, lw->selected, lw->selected+1);
-      break;
-    case CMD_LIST_FIND:
-    case CMD_LIST_RFIND:
-    case CMD_LIST_FIND_NEXT:
-    case CMD_LIST_RFIND_NEXT:
-      return screen_find(screen, c, 
-                        lw, c->playlist_length,
-                        cmd, list_callback);
-    default:
-      break;
-    }
-  return list_window_cmd(lw, c->playlist_length, cmd) ;
-}
-
-
-
-static list_window_t *
-play_lw(void)
-{
-  return lw;
-}
-
-int 
-play_get_selected(void)
-{
-  return lw->selected;
-}
-
-int
-playlist_move_song(mpd_client_t *c, int old_index, int new_index)
-{
-  int index1, index2;
-  GList *item1, *item2;
-  gpointer data1, data2;
-
-  if( old_index==new_index || new_index<0 || new_index>=c->playlist_length )
-    return -1;
-
-  /* send the move command to mpd */
-  mpd_sendMoveCommand(c->connection, old_index, new_index);
-  mpd_finishCommand(c->connection);
-  if( mpc_error(c) )
-    return -1;
-
-  index1 = MIN(old_index, new_index);
-  index2 = MAX(old_index, new_index);
-  item1 = g_list_nth(c->playlist, index1);
-  item2 = g_list_nth(c->playlist, index2);
-  data1 = item1->data;
-  data2 = item2->data;
-
-  /* move the second item */
-  D(fprintf(stderr, "move second item [%d->%d]...\n", index2, index1));
-  c->playlist = g_list_remove(c->playlist, data2);
-  c->playlist = g_list_insert_before(c->playlist, item1, data2);
-
-  /* move the first item */
-  if( index2-index1 >1 )
-    {
-      D(fprintf(stderr, "move first item [%d->%d]...\n", index1, index2));
-      item2 = g_list_nth(c->playlist, index2);
-      c->playlist = g_list_remove(c->playlist, data1);
-      c->playlist = g_list_insert_before(c->playlist, item2, data1);
-    }
-  
-  /* increment the playlist id, so we dont retrives a new playlist */
-  c->playlist_id++;
-
-  /* make shure the playlist is repainted */
-  lw->clear = 1;
-  lw->repaint = 1;
-
-  /* keep song selected */
-  lw->selected = new_index;
-
-  return 0;
-}
-
-int
-playlist_add_song(mpd_client_t *c, mpd_Song *song)
-{
-  if( !song || !song->file )
-    return -1;
-
-  /* send the add command to mpd */
-  mpd_sendAddCommand(c->connection, song->file);
-  mpd_finishCommand(c->connection);
-  if( mpc_error(c) )
-    return -1;
-
-  /* add the song to playlist */
-  c->playlist = g_list_append(c->playlist, (gpointer) mpd_songDup(song));
-  c->playlist_length++;
-
-  /* increment the playlist id, so we dont retrives a new playlist */
-  c->playlist_id++;
-
-  /* make shure the playlist is repainted */
-  lw->clear = 1;
-  lw->repaint = 1;
-
-  /* set selected highlight in the browse screen */
-  file_set_highlight(c, song, 1);
-
-  return 0;
-}
-
-int
-playlist_delete_song(mpd_client_t *c, int index)
-{
-  mpd_Song *song = mpc_playlist_get_song(c, index);
-
-  if( !song )
-    return -1;
-
-  /* send the delete command to mpd */
-  mpd_sendDeleteCommand(c->connection, index);
-  mpd_finishCommand(c->connection); 
-  if( mpc_error(c) )
-    return -1;
-
-  /* print a status message */
-  screen_status_printf("Removed \'%s\' from playlist!",
-                      mpc_get_song_name(song));
-  /* clear selected highlight in the browse screen */
-  file_set_highlight(c, song, 0);
-
-  /* increment the playlist id, so we dont retrives a new playlist */
-  c->playlist_id++;
-
-  /* remove references to the song */
-  if( c->song == song )
-    {
-      c->song = NULL;
-      c->song_id = -1;
-    }
-  
-  /* remove the song from the playlist */
-  c->playlist = g_list_remove(c->playlist, (gpointer) song);
-  c->playlist_length = g_list_length(c->playlist);
-  mpd_freeSong(song);
-
-  /* make shure the playlist is repainted */
-  lw->clear = 1;
-  lw->repaint = 1;
-  list_window_check_selected(lw, c->playlist_length);
-
-  return 0;
-}
-
-
-screen_functions_t *
-get_screen_playlist(void)
-{
-  static screen_functions_t functions;
-
-  memset(&functions, 0, sizeof(screen_functions_t));
-  functions.init   = play_init;
-  functions.exit   = play_exit;
-  functions.open   = NULL;
-  functions.close  = NULL;
-  functions.resize = play_resize;
-  functions.paint  = play_paint;
-  functions.update = play_update;
-  functions.cmd    = play_cmd;
-  functions.get_lw = play_lw;
-  functions.get_title = play_title;
-
-  return &functions;
-}
diff --git a/screen_play.h b/screen_play.h
deleted file mode 100644 (file)
index 2155ae5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-int play_get_selected(void);
-
-int playlist_move_song(mpd_client_t *c, int old_index, int new_index);
-int playlist_add_song(mpd_client_t *c, mpd_Song *song);
-int playlist_delete_song(mpd_client_t *c, int index);
-
-screen_functions_t *get_screen_playlist(void);
-
diff --git a/screen_search.c b/screen_search.c
deleted file mode 100644 (file)
index 6b6719e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "libmpdclient.h"
-#include "config.h"
-#include "mpc.h"
-#include "command.h"
-#include "screen.h"
-#include "screen_search.h"
-
diff --git a/screen_search.h b/screen_search.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/screen_utils.c b/screen_utils.c
deleted file mode 100644 (file)
index f8dfa4c..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/* 
- * (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 <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "config.h"
-#include "libmpdclient.h"
-#include "mpc.h"
-#include "support.h"
-#include "command.h"
-#include "options.h"
-#include "list_window.h"
-#include "colors.h"
-#include "screen.h"
-
-#define FIND_PROMPT  "Find: "
-#define RFIND_PROMPT "Find backward: "
-
-int
-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);
-  wmove(w, 0, prompt_len);
-  
-  echo();
-  curs_set(1);
-  timeout(-1);
-
-  key = wgetch(w);
-  if( key==KEY_RESIZE )
-    screen_resize();
-
-  noecho();
-  curs_set(0);
-  timeout(SCREEN_TIMEOUT);
-
-  return key;
-}
-
-
-char *
-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);
-  wmove(w, 0, prompt_len);
-  
-  echo();
-  curs_set(1);
-
-  if( wgetnstr(w, buf, 256) == OK )
-    line = g_strdup(buf);
-
-  noecho();
-  curs_set(0);
-
-  return line;
-}
-
-
-/* query user for a string and find it in a list window */
-int 
-screen_find(screen_t *screen,
-           mpd_client_t *c,
-           list_window_t *lw, 
-           int rows,
-           command_t findcmd,
-           list_window_callback_fn_t callback_fn)
-{
-  int reversed = 0;
-  int retval   = 0;
-  char *prompt = FIND_PROMPT;
-
-  if( findcmd==CMD_LIST_RFIND ||findcmd==CMD_LIST_RFIND_NEXT ) 
-    {
-      prompt = RFIND_PROMPT;
-      reversed = 1;
-    }
-
-  switch(findcmd)
-    {
-    case CMD_LIST_FIND:
-    case CMD_LIST_RFIND:
-      if( screen->findbuf )
-       {
-         g_free(screen->findbuf);
-         screen->findbuf=NULL;
-       }
-      /* continue... */
-    case CMD_LIST_FIND_NEXT:
-    case CMD_LIST_RFIND_NEXT:
-      if( !screen->findbuf )
-       screen->findbuf=screen_getstr(screen->status_window.w, prompt);
-      if( reversed )
-       retval = list_window_rfind(lw, 
-                                  callback_fn,
-                                  c, 
-                                  screen->findbuf,
-                                  options.find_wrap,
-                                  rows);
-      else
-       retval = list_window_find(lw,
-                                 callback_fn,
-                                 c,
-                                 screen->findbuf,
-                                 options.find_wrap);
-      if( retval == 0 )
-       {
-         lw->repaint  = 1;
-       }
-      else
-       {
-         screen_status_printf("Unable to find \'%s\'", screen->findbuf);
-         beep();
-       }
-      return 1;
-    default:
-      break;
-    }
-  return 0;
-}
-
-
diff --git a/screen_utils.h b/screen_utils.h
deleted file mode 100644 (file)
index 30c58bf..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-/* read a characher from the status window */
-int screen_getch(WINDOW *w, char *prompt);
-
-/* read a string from the status window */
-char *screen_getstr(WINDOW *w, char *prompt);
-
-/* query user for a string and find it in a list window */
-int screen_find(screen_t *screen,
-               mpd_client_t *c,
-               list_window_t *lw, 
-               int rows,
-               command_t findcmd,
-               list_window_callback_fn_t callback_fn);
-
-
-int my_waddstr(WINDOW *, const char *, int);
-int my_mvwaddstr(WINDOW *, int, int, const char *, int);
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..abf121c
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# $Id$
+#
+
+bin_PROGRAMS = ncmpc
+
+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 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 colors.c support.c $(ncmpc_headers)
+
+
+
+
+
+
diff --git a/src/colors.c b/src/colors.c
new file mode 100644 (file)
index 0000000..f709693
--- /dev/null
@@ -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/src/colors.h b/src/colors.h
new file mode 100644 (file)
index 0000000..a66d693
--- /dev/null
@@ -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/src/command.c b/src/command.c
new file mode 100644 (file)
index 0000000..1e9edcd
--- /dev/null
@@ -0,0 +1,429 @@
+/* 
+ * (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 <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+#include "command.h"
+
+#undef DEBUG_KEYS
+
+#ifdef DEBUG_KEYS
+#define DK(x) x
+#else
+#define DK(x)
+#endif
+
+extern void screen_resize(void);
+
+#define BS   KEY_BACKSPACE
+#define DEL  KEY_DC
+#define UP   KEY_UP
+#define DWN  KEY_DOWN
+#define LEFT KEY_LEFT
+#define RGHT KEY_RIGHT
+#define HOME KEY_HOME
+#define END  KEY_END
+#define PGDN KEY_NPAGE
+#define PGUP KEY_PPAGE
+#define TAB  0x09
+#define STAB 0x161
+#define ESC  0x1B
+#define F1   KEY_F(1)
+#define F2   KEY_F(2)
+#define F3   KEY_F(3)
+#define F4   KEY_F(4)
+#define F5   KEY_F(5)
+#define F6   KEY_F(6)
+
+
+static command_definition_t cmds[] =
+{
+  { {  13,   0,   0 }, CMD_PLAY, "play",  
+    "Play/Enter directory" },
+  { { 'P',   0,   0 }, CMD_PAUSE,"pause", 
+    "Pause" },
+  { { 's',  BS,   0 }, CMD_STOP, "stop",   
+    "Stop" },
+  { { '>',   0,   0 }, CMD_TRACK_NEXT, "next", 
+    "Next track" },
+  { { '<',   0,   0 }, CMD_TRACK_PREVIOUS, "prev", 
+    "Previous track" },
+  { { 'f',   0,   0 }, CMD_SEEK_FORWARD, "seek-forward", 
+    "Seek forward" },
+  { { 'b',   0,   0 }, CMD_SEEK_BACKWARD, "seek-backward", 
+    "Seek backward" },
+
+  { { '+', RGHT,  0 }, CMD_VOLUME_UP, "volume-up", 
+    "Increase volume" },
+  { { '-', LEFT,  0 }, CMD_VOLUME_DOWN, "volume-down", 
+    "Decrease volume" },
+
+  { { 'w',   0,   0 }, CMD_TOGGLE_FIND_WRAP,  "wrap-mode", 
+    "Toggle find mode" },
+  { { 'U',   0,   0 }, CMD_TOGGLE_AUTOCENTER, "autocenter-mode", 
+    "Toggle auto center mode" },
+
+  { { ' ',  'a',   0 }, CMD_SELECT, "select", 
+    "Select/deselect song in playlist" },
+  { { DEL,  'd',  0 }, CMD_DELETE, "delete",
+    "Delete song from playlist" },
+  { { 'Z',   0,   0 }, CMD_SHUFFLE, "shuffle",
+    "Shuffle playlist" },
+  { { 'c',   0,   0 }, CMD_CLEAR, "clear",
+    "Clear playlist" },
+  { { 'r',   0,   0 }, CMD_REPEAT, "repeat",
+    "Toggle repeat mode" },
+  { { 'z',   0,   0 }, CMD_RANDOM, "random",
+    "Toggle random mode" },
+  { { 'x',   0,   0 }, CMD_CROSSFADE, "crossfade",
+    "Toggle crossfade mode" },
+  { { 'S',   0,   0 }, CMD_SAVE_PLAYLIST, "save",
+    "Save playlist" },
+
+  { { 0,  0,   0 }, CMD_LIST_MOVE_UP,     "move-up", 
+    "Move item up" },
+  { { 0,  0,   0 }, CMD_LIST_MOVE_DOWN,   "move-down", 
+    "Move item down" },
+
+  { {  UP,  ',',   0 }, CMD_LIST_PREVIOUS,      "up",
+    "Move cursor up" },
+  { { DWN,  '.',   0 }, CMD_LIST_NEXT,          "down",
+    "Move cursor down" },
+  { { HOME, 0x01, 0 }, CMD_LIST_FIRST,          "home",
+    "Home " },
+  { { END,  0x05, 0 }, CMD_LIST_LAST,           "end",
+    "End " },
+  { { PGUP, 'A',   0 }, CMD_LIST_PREVIOUS_PAGE, "pgup",
+    "Page up" },
+  { { PGDN, 'B',   0 }, CMD_LIST_NEXT_PAGE,     "pgdn", 
+    "Page down" },
+  { { '/',   0,   0 }, CMD_LIST_FIND,           "find",
+    "Forward find" },
+  { { 'n',   0,   0 }, CMD_LIST_FIND_NEXT,      "find-next",
+    "Forward find next" },
+  { { '?',   0,   0 }, CMD_LIST_RFIND,          "rfind",
+    "Backward find" },
+  { { 'p',   0,   0 }, CMD_LIST_RFIND_NEXT,     "rfind-next",
+    "Backward find previous" },
+
+
+  { { TAB,   0,   0 }, CMD_SCREEN_NEXT,     "screen-next",
+    "Next screen" },
+
+  { { STAB,  0,   0 }, CMD_SCREEN_PREVIOUS, "screen-prev",
+    "Previous screen" },
+
+  { { '1', F1, 'h' }, CMD_SCREEN_HELP,      "screen-help",
+    "Help screen" },
+  { { '2', F2,  0 }, CMD_SCREEN_PLAY,      "screen-playlist",
+    "Playlist screen" },
+  { { '3', F3,  0 }, CMD_SCREEN_FILE,      "screen-browse",
+    "Browse screen" },
+  { {'u',   0,   0 }, CMD_SCREEN_UPDATE,    "update",
+    "Update screen" },
+#ifdef ENABLE_KEYDEF_SCREEN
+  { {'K',   0,   0 }, CMD_SCREEN_KEYDEF,    "screen-keyedit",
+    "Key configuration screen" },
+#endif
+
+  { { 'q',  0,   0 }, CMD_QUIT,   "quit",
+    "Quit " PACKAGE },  
+
+  { { -1,  -1,  -1 }, CMD_NONE, NULL, NULL }
+};
+
+command_definition_t *
+get_command_definitions(void)
+{
+  return cmds;
+}
+
+char *
+key2str(int key)
+{
+  static char buf[32];
+  int i;
+
+  buf[0] = 0;
+  switch(key)
+    {
+    case 0:
+      return "Undefined";
+    case ' ':
+      return "Space";
+    case 13:
+      return "Enter";
+    case BS:
+      return "Backspace";
+    case DEL:
+      return "Delete";
+    case UP: 
+      return "Up";
+    case DWN:
+      return "Down";
+    case LEFT:
+      return "Left";
+    case RGHT:
+      return "Right";
+    case HOME:
+      return "Home";
+    case END:
+      return "End";
+    case PGDN:
+      return "PageDown";
+    case PGUP:
+      return "PageUp";
+    case TAB: 
+      return "Tab";
+    case STAB:
+      return "Shift+Tab";
+    case ESC:
+      return "Esc";
+    case KEY_IC:
+      return "Insert";
+    default:
+      for(i=0; i<=63; i++)
+       if( key==KEY_F(i) )
+         {
+           snprintf(buf, 32, "F%d", i );
+           return buf;
+         }
+      if( !(key & ~037) )
+       snprintf(buf, 32, "Ctrl-%c", 'A'+(key & 037)-1 );
+      else if( (key & ~037) == 224 )
+       snprintf(buf, 32, "Alt-%c", 'A'+(key & 037)-1 );
+      else if( key>32 &&  key<256 )
+       snprintf(buf, 32, "%c", key);
+      else
+       snprintf(buf, 32, "0x%03X", key);
+    }
+  return buf;
+}
+
+void
+command_dump_keys(void)
+{
+  int i;
+
+  i=0;
+  while( cmds[i].description )
+    {
+      if( cmds[i].command != CMD_NONE )
+       printf(" %20s : %s\n", get_key_names(cmds[i].command,1),cmds[i].name); 
+      i++;
+    }
+}
+
+char *
+get_key_names(command_t command, int all)
+{
+  int i;
+  
+  i=0;
+  while( cmds[i].description )
+    {
+      if( cmds[i].command == command )
+       {
+         int j;
+         static char keystr[80];
+
+         strncpy(keystr, key2str(cmds[i].keys[0]), 80);
+         if( !all )
+           return keystr;
+         j=1;
+         while( j<MAX_COMMAND_KEYS && cmds[i].keys[j]>0 )
+           {
+             strcat(keystr, " ");
+             strcat(keystr, key2str(cmds[i].keys[j]));
+             j++;
+           }
+         return keystr;
+       }
+      i++;
+    }
+  return NULL;
+}
+
+char *
+get_key_description(command_t command)
+{
+  int i;
+
+  i=0;
+  while( cmds[i].description )
+    {
+      if( cmds[i].command == command )
+       return cmds[i].description;
+      i++;
+    }
+  return NULL;
+}
+
+char *
+get_key_command_name(command_t command)
+{
+  int i;
+
+  i=0;
+  while( cmds[i].name )
+    {
+      if( cmds[i].command == command )
+       return cmds[i].name;
+      i++;
+    }
+  return NULL;
+}
+
+command_t 
+get_key_command_from_name(char *name)
+{
+  int i;
+
+  i=0;
+  while( cmds[i].name )
+    {
+      if( strcmp(name, cmds[i].name) == 0 )
+       return cmds[i].command;
+      i++;
+    }
+  return CMD_NONE;
+}
+
+
+command_t 
+find_key_command(int key, command_definition_t *cmds)
+{
+  int i;
+
+  i=0;
+  while( cmds && cmds[i].name )
+    {
+      if( cmds[i].keys[0] == key || 
+         cmds[i].keys[1] == key ||
+         cmds[i].keys[2] == key )
+       return cmds[i].command;
+      i++;
+    }
+  return CMD_NONE;
+}
+
+command_t 
+get_key_command(int key)
+{
+  return find_key_command(key, cmds);
+}
+
+
+command_t
+get_keyboard_command(void)
+{
+  int key;
+
+  key = wgetch(stdscr);
+
+  if( key==KEY_RESIZE )
+    screen_resize();
+
+  if( key==ERR )
+    return CMD_NONE;
+
+  DK(fprintf(stderr, "key = 0x%02X\t", key));
+
+  return get_key_command(key);
+}
+
+int
+assign_keys(command_t command, int keys[MAX_COMMAND_KEYS])
+{
+ int i;
+
+  i=0;
+  while( cmds[i].name )
+    {
+      if( cmds[i].command == command )
+       {
+         memcpy(cmds[i].keys, keys, sizeof(int)*MAX_COMMAND_KEYS);
+         return 0;
+       }
+      i++;
+    }
+  return -1;
+}
+
+int 
+check_key_bindings(void)
+{
+  int i;
+  int retval = 0;
+  
+  i=0;
+  while( cmds[i].name )
+    {
+      int j;
+      command_t cmd;
+
+      for(j=0; j<MAX_COMMAND_KEYS; j++)
+       if( cmds[i].keys[j] && 
+           (cmd=get_key_command(cmds[i].keys[j])) != cmds[i].command )
+         {
+           fprintf(stderr, "Error: Key %s assigned to %s and %s !!!\n",
+                   key2str(cmds[i].keys[j]),
+                   get_key_command_name(cmds[i].command),
+                   get_key_command_name(cmd));
+           retval = -1;
+         }
+      i++;
+    }
+  return retval;
+}
+
+int
+write_key_bindings(FILE *f)
+{
+  int i,j;
+
+  i=0;
+  while( cmds[i].name && !ferror(f) )
+    {
+      fprintf(f, "# %s\n", cmds[i].description);
+      fprintf(f, "key %s = ", cmds[i].name);
+      for(j=0; j<MAX_COMMAND_KEYS; j++)
+       {
+         if( j && cmds[i].keys[j] )
+           fprintf(f, ",  ");
+         if( !j || cmds[i].keys[j] )
+           {
+             if( cmds[i].keys[j]<256 && (isalpha(cmds[i].keys[j]) || 
+                                         isdigit(cmds[i].keys[j])) )
+               fprintf(f, "\'%c\'", cmds[i].keys[j]);
+             else
+               fprintf(f, "%d", cmds[i].keys[j]);
+           }
+       }
+      fprintf(f,"\n\n");
+      i++;
+    }
+  return ferror(f);
+}
diff --git a/src/command.h b/src/command.h
new file mode 100644 (file)
index 0000000..1ce67e8
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef COMMAND_H
+#define COMMAND_H
+
+#define MAX_COMMAND_KEYS 3
+
+typedef enum
+{
+  CMD_NONE = 0,
+  CMD_PLAY,
+  CMD_SELECT,
+  CMD_PAUSE,
+  CMD_STOP,
+  CMD_TRACK_NEXT,
+  CMD_TRACK_PREVIOUS,
+  CMD_SEEK_FORWARD,
+  CMD_SEEK_BACKWARD,
+  CMD_SHUFFLE,
+  CMD_RANDOM,
+  CMD_CLEAR,
+  CMD_DELETE,
+  CMD_REPEAT,
+  CMD_CROSSFADE,
+  CMD_VOLUME_UP,
+  CMD_VOLUME_DOWN,
+  CMD_SAVE_PLAYLIST,
+  CMD_TOGGLE_FIND_WRAP,
+  CMD_TOGGLE_AUTOCENTER,
+  CMD_LIST_PREVIOUS,
+  CMD_LIST_NEXT,
+  CMD_LIST_FIRST,
+  CMD_LIST_LAST,
+  CMD_LIST_NEXT_PAGE,
+  CMD_LIST_PREVIOUS_PAGE,
+  CMD_LIST_FIND,
+  CMD_LIST_FIND_NEXT,
+  CMD_LIST_RFIND,
+  CMD_LIST_RFIND_NEXT,
+  CMD_LIST_MOVE_UP,
+  CMD_LIST_MOVE_DOWN,
+  CMD_SCREEN_UPDATE,
+  CMD_SCREEN_PREVIOUS,
+  CMD_SCREEN_NEXT,
+  CMD_SCREEN_PLAY,
+  CMD_SCREEN_FILE,
+  CMD_SCREEN_SEARCH,
+  CMD_SCREEN_KEYDEF,
+  CMD_SCREEN_HELP,
+  CMD_QUIT
+} command_t;
+
+typedef struct 
+{
+  int keys[MAX_COMMAND_KEYS];
+  command_t command;
+  char *name;
+  char *description;
+} command_definition_t;
+
+command_definition_t *get_command_definitions(void);
+command_t find_key_command(int key, command_definition_t *cmds);
+
+void command_dump_keys(void);
+int  check_key_bindings(void);
+int  write_key_bindings(FILE *f);
+
+char *key2str(int key);
+char *get_key_description(command_t command);
+char *get_key_command_name(command_t command);
+char *get_key_names(command_t command, int all);
+command_t get_key_command(int key);
+command_t get_key_command_from_name(char *name);
+int assign_keys(command_t command, int keys[MAX_COMMAND_KEYS]);
+
+command_t get_keyboard_command(void);
+
+#endif
diff --git a/src/conf.c b/src/conf.c
new file mode 100644 (file)
index 0000000..06866c1
--- /dev/null
@@ -0,0 +1,594 @@
+/* 
+ * (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 <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+#include "options.h"
+#include "support.h"
+#include "command.h"
+#include "colors.h"
+#include "conf.h"
+
+#ifdef DEBUG
+#define D(x) x
+#else
+#define D(x)
+#endif
+
+#define ENABLE_OLD_COLOR_SYNTAX
+
+#define MAX_LINE_LENGTH 1024
+#define COMMENT_TOKEN   '#'
+
+/* 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"
+
+/* Deprecated - configuration field names */
+#define CONF_COLOR_BACKGROUND        "background_color"
+#define CONF_COLOR_TITLE             "title_color"
+#define CONF_COLOR_LINE              "line_color"
+#define CONF_COLOR_LIST              "list_color"
+#define CONF_COLOR_PROGRESS          "progress_color"
+#define CONF_COLOR_STATUS            "status_color"
+#define CONF_COLOR_ALERT             "alert_color"
+
+
+typedef enum {
+  KEY_PARSER_UNKNOWN,
+  KEY_PARSER_CHAR,
+  KEY_PARSER_DEC,
+  KEY_PARSER_HEX,
+  KEY_PARSER_DONE
+} key_parser_state_t;
+
+static int
+str2bool(char *str)
+{
+  if( !strcasecmp(str,"no")  || !strcasecmp(str,"false") || 
+      !strcasecmp(str,"off") || !strcasecmp(str,"0") )
+    return 0;
+  return 1;
+}
+
+static int
+parse_key_value(char *str, size_t len, char **end)
+{
+  int i, value;
+  key_parser_state_t state;
+
+  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<len )
+       next = str[i+1];
+
+      switch(state)
+       {
+       case KEY_PARSER_UNKNOWN:
+         if( c=='\'' )
+           state = KEY_PARSER_CHAR;
+         else if( c=='0' && next=='x' )
+           state = KEY_PARSER_HEX;
+         else if( isdigit(c) )
+           state = KEY_PARSER_DEC;
+         else {
+           fprintf(stderr, "Error: Unsupported key definition - %s\n", str);
+           return -1;
+         }
+         break;
+       case KEY_PARSER_CHAR:
+         if( next!='\'' )
+           {
+             fprintf(stderr, "Error: Unsupported key definition - %s\n", str);
+             return -1;
+           }
+         value = c;
+         *end = str+i+2;
+         state = KEY_PARSER_DONE;
+         break;
+       case KEY_PARSER_DEC:
+         value = (int) strtol(str+(i-1), end, 10);
+         state = KEY_PARSER_DONE;
+         break;
+       case KEY_PARSER_HEX:
+         if( !isdigit(next) )
+           {
+             fprintf(stderr, "Error: Digit expexted after 0x - %s\n", str);
+             return -1;
+           }
+         value = (int) strtol(str+(i+1), end, 16);
+         state = KEY_PARSER_DONE;
+         break;
+       case KEY_PARSER_DONE:
+         break;
+       }
+      i++;
+    }
+
+  if( *end> str+len )
+    *end = str+len;
+
+  return value;
+}
+
+static int
+parse_key_definition(char *str)
+{
+  char buf[MAX_LINE_LENGTH];
+  char *p, *end;
+  size_t len = strlen(str);
+  int i,j,key;
+  int keys[MAX_COMMAND_KEYS];
+  command_t cmd;
+
+  /* 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++];
+  if( (cmd=get_key_command_from_name(buf)) == CMD_NONE )
+    {
+      fprintf(stderr, "Error: Unknown key command %s\n", buf);
+      return -1;
+    }
+
+  /* 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 key definition - %s\n", 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 )
+    {
+      keys[i++] = key;
+      while( p<end && (*p==',' || *p==' ' || *p=='\t') )
+       p++;
+      len = strlen(p);
+    } 
+  if( key<0 )
+    {
+      fprintf(stderr,"Error: Bad key definition - %s\n", str);
+      return -1;
+    }
+
+  return assign_keys(cmd, keys);
+}
+
+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 free_filename = 0;
+
+  if( filename==NULL )
+    return -1;
+
+  D(printf("Reading configuration file %s\n", filename));
+  if( (fd=open(filename,O_RDONLY)) <0 )
+    {
+      perror(filename);
+      if( free_filename )
+       g_free(filename);
+      return -1;
+    }
+
+  while( !quit )
+    {
+      int i,j;
+      int len;
+      int match_found;
+      char line[MAX_LINE_LENGTH];
+      char name[MAX_LINE_LENGTH];
+      char value[MAX_LINE_LENGTH];
+
+      line[0]  = '\0';
+      value[0] = '\0';
+
+      i = 0;
+      /* read a line ending with '\n' */
+      do {
+       len = read( fd, &line[i], 1 );
+       if( len == 1 )
+         i++;
+       else
+         quit = 1;
+      } while( !quit && i<MAX_LINE_LENGTH && line[i-1]!='\n' );
+      
+     
+      /* remove trailing whitespace */
+      line[i] = '\0';
+      i--;
+      while( i>=0 && IS_WHITESPACE(line[i]) )
+       {
+         line[i] = '\0';
+         i--;
+       }     
+      len = i+1;
+
+      if( len>0 )
+       {
+         i = 0;
+         /* skip whitespace */
+         while( i<len && IS_WHITESPACE(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]!='=' && !IS_WHITESPACE(line[i]) )
+               {
+                 name[j++] = line[i++];
+               }
+             name[j] = '\0';
+             
+             /* skip '=' and whitespace */
+             while( i<len && (line[i]=='=' || IS_WHITESPACE(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) )
+               {
+                 options->enable_colors = str2bool(value);
+               }
+             /* auto center */
+             else if( !strcasecmp(CONF_AUTO_CENTER, name) )
+               {
+                 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) )
+               {
+                 fprintf(stderr,"%s: %s - deprecated!\n", filename,name);
+                 colors_assign("background", value);
+               }
+             /* color - top (title) window */
+             else if( !strcasecmp(CONF_COLOR_TITLE, name) )
+               {
+                 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) )
+               {
+                 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) )
+               {
+                 fprintf(stderr,"%s: %s - deprecated!\n", filename,name);
+                 colors_assign("list", value);
+               }
+             /* color - progress bar */
+             else if( !strcasecmp(CONF_COLOR_PROGRESS, name) )
+               {
+                 fprintf(stderr,"%s: %s - deprecated!\n", filename,name);
+                 colors_assign("progressbar", value);
+               }
+             /* color - status window */
+             else if( !strcasecmp(CONF_COLOR_STATUS, name) )
+               {
+                 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) )
+               {
+                 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;
+               }
+             
+
+             if( !match_found )
+               fprintf(stderr, 
+                       "Unknown configuration parameter: %s\n", 
+                       name);
+#ifdef DEBUG
+             printf( "  %s = %s %s\n", 
+                     name, 
+                     value,
+                     match_found ? "" : "- UNKNOWN SETTING!" );
+#endif
+
+           }
+       }         
+    }
+
+  D(printf( "--\n\n" ));
+
+  if( free_filename )
+    g_free(filename);
+  return 0;
+}
+
+int
+check_user_conf_dir(void)
+{
+  int retval;
+  char *dirname = g_build_filename(g_get_home_dir(), "." PACKAGE, NULL);
+  
+  if( g_file_test(dirname, G_FILE_TEST_IS_DIR) )
+    {
+      g_free(dirname);
+      return 0;
+    }
+  retval = mkdir(dirname, 0755);
+  g_free(dirname);
+  return retval;
+}
+
+char *
+get_user_key_binding_filename(void)
+{
+  return g_build_filename(g_get_home_dir(), "." PACKAGE, "keys", NULL);
+}
+
+
+int
+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 */
+  if( 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 */
+  if( filename == NULL )
+    {
+      filename = g_build_filename(SYSCONFDIR, PACKAGE, "config", NULL);
+      if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
+       {
+         g_free(filename);
+         filename = NULL;
+       }
+    }
+
+  /* load configuration */
+  if( filename )
+    {
+      read_rc_file(filename, options);
+      g_free(filename);
+      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 */
+  if( 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 */
+  if( filename == NULL )
+    {
+      filename = g_build_filename(SYSCONFDIR, PACKAGE, "keys", NULL);
+      if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
+       {
+         g_free(filename);
+         filename = NULL;
+       }
+    }
+
+  /* load key bindings */
+  if( filename )
+    {
+      read_rc_file(filename, options);
+      g_free(filename);
+      filename = NULL;
+    }
+
+  return 0;
+}
+
+
+
diff --git a/src/conf.h b/src/conf.h
new file mode 100644 (file)
index 0000000..20b4f5e
--- /dev/null
@@ -0,0 +1,7 @@
+
+int check_user_conf_dir(void);
+
+char *get_user_key_binding_filename(void);
+
+int read_configuration(options_t *options);
+
diff --git a/src/libmpdclient.c b/src/libmpdclient.c
new file mode 100644 (file)
index 0000000..2e8b579
--- /dev/null
@@ -0,0 +1,1211 @@
+/* libmpdclient
+ * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 "libmpdclient.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#ifndef HAVE_SOCKLEN_T
+typedef SOCKLEN_T socklen_t;
+#endif
+#endif
+
+
+#ifndef MPD_NO_IPV6
+#ifdef AF_INET6
+#define MPD_HAVE_IPV6
+#endif
+#endif
+
+#ifdef MPD_HAVE_IPV6        
+int mpd_ipv6Supported() {
+        int s;          
+        s = socket(AF_INET6,SOCK_STREAM,0);
+        if(s == -1) return 0;
+        close(s);       
+        return 1;                       
+}                       
+#endif  
+
+
+char * mpd_sanitizeArg(const char * arg) {
+       size_t i;
+       int count=0;
+       char * ret;
+
+       for(i=0;i<strlen(arg);i++) {
+               if(arg[i]=='"' || arg[i]=='\\') count++;
+       }
+
+       ret = malloc(strlen(arg)+count+1);
+
+       count = 0;
+       for(i=0;i<strlen(arg)+1;i++) {
+               if(arg[i]=='"' || arg[i]=='\\') {
+                       ret[i+count] = '\\';
+                       count++;
+               }
+               ret[i+count] = arg[i];
+       }
+
+       return ret;
+}
+
+mpd_ReturnElement * mpd_newReturnElement(const char * name, const char * value)
+{
+       mpd_ReturnElement * ret = malloc(sizeof(mpd_ReturnElement));
+
+       ret->name = strdup(name);
+       ret->value = strdup(value);
+
+       return ret;
+}
+
+void mpd_freeReturnElement(mpd_ReturnElement * re) {
+       free(re->name);
+       free(re->value);
+       free(re);
+}
+
+void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout) {
+               connection->timeout.tv_sec = (int)timeout;
+               connection->timeout.tv_usec = (int)(timeout*1e6 -
+                               connection->timeout.tv_sec*1000000+0.5);
+}
+
+mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
+       int err;
+       struct hostent * he;
+       struct sockaddr * dest;
+       socklen_t destlen;
+       struct sockaddr_in sin;
+       char * rt;
+       char * output;
+       mpd_Connection * connection = malloc(sizeof(mpd_Connection));
+       struct timeval tv;
+       fd_set fds;
+#ifdef MPD_HAVE_IPV6
+       struct sockaddr_in6 sin6;
+#endif
+       strcpy(connection->buffer,"");
+       connection->buflen = 0;
+       connection->bufstart = 0;
+       strcpy(connection->errorStr,"");
+       connection->error = 0;
+       connection->doneProcessing = 0;
+       connection->commandList = 0;
+       connection->returnElement = NULL;
+
+       if(!(he=gethostbyname(host))) {
+               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                               "host \"%s\" not found",host);
+               connection->error = MPD_ERROR_UNKHOST;
+               return connection;
+       }
+
+       memset(&sin,0,sizeof(struct sockaddr_in));
+       /*dest.sin_family = he->h_addrtype;*/
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(port);
+#ifdef MPD_HAVE_IPV6
+       memset(&sin6,0,sizeof(struct sockaddr_in6));
+       sin6.sin6_family = AF_INET6;
+       sin6.sin6_port = htons(port);
+#endif
+       switch(he->h_addrtype) {
+       case AF_INET:
+               memcpy((char *)&sin.sin_addr.s_addr,(char *)he->h_addr,
+                               he->h_length);
+               dest = (struct sockaddr *)&sin;
+               destlen = sizeof(struct sockaddr_in);
+               break;
+#ifdef MPD_HAVE_IPV6
+       case AF_INET6:
+               if(!mpd_ipv6Supported()) {
+                       strcpy(connection->errorStr,"no IPv6 suuport but a "
+                                       "IPv6 address found\n");
+                       connection->error = MPD_ERROR_SYSTEM;
+                       return connection;
+               }
+               memcpy((char *)&sin6.sin6_addr.s6_addr,(char *)he->h_addr,
+                               he->h_length);
+               dest = (struct sockaddr *)&sin6;
+               destlen = sizeof(struct sockaddr_in6);
+               break;
+#endif
+       default:
+               strcpy(connection->errorStr,"address type is not IPv4 or "
+                               "IPv6\n");
+               connection->error = MPD_ERROR_SYSTEM;
+               return connection;
+               break;
+       }
+       
+       if((connection->sock = socket(dest->sa_family,SOCK_STREAM,0))<0) {
+               strcpy(connection->errorStr,"problems creating socket");
+               connection->error = MPD_ERROR_SYSTEM;
+               return connection;
+       }
+
+       /* connect stuff */
+       {
+#ifdef SO_RCVTIMEO
+               struct timeval rcvoldto;
+               struct timeval sndoldto;
+               socklen_t oldlen = sizeof(struct timeval);
+
+               mpd_setConnectionTimeout(connection,timeout);
+
+               tv.tv_sec = connection->timeout.tv_sec;
+               tv.tv_usec = connection->timeout.tv_usec;
+
+               if(getsockopt(connection->sock,SOL_SOCKET,SO_RCVTIMEO,&rcvoldto,
+                                       &oldlen)<0 ||
+                               getsockopt(connection->sock,SOL_SOCKET,
+                                       SO_SNDTIMEO,&sndoldto,&oldlen)<0)
+               {
+                       strcpy(connection->errorStr,"problems getting socket "
+                                       "timeout\n");
+                       connection->error = MPD_ERROR_SYSTEM;
+                       return connection;
+               }
+               if(setsockopt(connection->sock,SOL_SOCKET,SO_RCVTIMEO,&tv,
+                                       sizeof(struct timeval))<0 ||
+                               setsockopt(connection->sock,SOL_SOCKET,
+                                       SO_SNDTIMEO,&tv,
+                                       sizeof(struct timeval))<0)
+               {
+                       strcpy(connection->errorStr,"problems setting socket "
+                                       "timeout\n");
+                       connection->error = MPD_ERROR_SYSTEM;
+                       return connection;
+               }
+#endif
+               if(connect(connection->sock,dest,destlen)<0) {
+                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                                       "problems connecting to \"%s\" on port"
+                                       " %i",host,port);
+                       connection->error = MPD_ERROR_CONNPORT;
+                       return connection;
+               }
+#ifdef SO_RCVTIMEO
+               if(setsockopt(connection->sock,SOL_SOCKET,SO_SNDTIMEO,&rcvoldto,
+                                       sizeof(struct timeval))<0 ||
+                               setsockopt(connection->sock,SOL_SOCKET,
+                                       SO_SNDTIMEO,&sndoldto,
+                                       sizeof(struct timeval))<0)
+               {
+                       strcpy(connection->errorStr,"problems setting socket "
+                                       "timeout\n");
+                       connection->error = MPD_ERROR_SYSTEM;
+                       return connection;
+               }
+#endif
+       }
+
+       while(!(rt = strstr(connection->buffer,"\n"))) {
+               tv.tv_sec = connection->timeout.tv_sec;
+               tv.tv_usec = connection->timeout.tv_usec;
+               FD_ZERO(&fds);
+               FD_SET(connection->sock,&fds);
+               if((err = select(connection->sock+1,&fds,NULL,NULL,&tv)) == 1) {
+                       int readed;
+                       readed = recv(connection->sock,
+                               &(connection->buffer[connection->buflen]),
+                               MPD_BUFFER_MAX_LENGTH-connection->buflen,0);
+                       if(readed<=0) {
+                               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                                       "problems getting a response from"
+                                       " \"%s\" on port %i",host,
+                                       port);
+                               connection->error = MPD_ERROR_NORESPONSE;
+                               return connection;
+                       }
+                       connection->buflen+=readed;
+                       connection->buffer[connection->buflen] = '\0';
+                       tv.tv_sec = connection->timeout.tv_sec;
+                       tv.tv_usec = connection->timeout.tv_usec;
+               }
+               else if(err<0 && errno==EINTR) continue;
+               else {
+                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                               "timeout in attempting to get a response from"
+                                " \"%s\" on port %i",host,port);
+                       connection->error = MPD_ERROR_NORESPONSE;
+                       return connection;
+               }
+       }
+
+       *rt = '\0';
+       output = strdup(connection->buffer);
+       strcpy(connection->buffer,rt+1);
+       connection->buflen = strlen(connection->buffer);
+
+       if(strncmp(output,MPD_WELCOME_MESSAGE,strlen(MPD_WELCOME_MESSAGE))) {
+               free(output);
+               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                               "mpd not running on port %i on host \"%s\"",
+                               port,host);
+               connection->error = MPD_ERROR_NOTMPD;
+               return connection;
+       }
+
+       {
+               char * test;
+               char * version[3];
+               char * tmp = &output[strlen(MPD_WELCOME_MESSAGE)];
+               char * search = ".";
+               int i;
+
+               for(i=0;i<3;i++) {
+                       char * tok;
+                       if(i==3) search = " ";
+                       version[i] = strtok_r(tmp,search,&tok);
+                       if(!version[i]) {
+                               free(output);
+                               snprintf(connection->errorStr,
+                                       MPD_BUFFER_MAX_LENGTH,
+                                       "error parsing version number at "
+                                       "\"%s\"",
+                                       &output[strlen(MPD_WELCOME_MESSAGE)]);
+                               connection->error = MPD_ERROR_NOTMPD;
+                               return connection;
+                       }
+                       connection->version[i] = strtol(version[i],&test,10);
+                       if(version[i]==test || *test!='\0') {
+                               free(output);
+                               snprintf(connection->errorStr,
+                                       MPD_BUFFER_MAX_LENGTH,
+                                       "error parsing version number at "
+                                       "\"%s\"",
+                                       &output[strlen(MPD_WELCOME_MESSAGE)]);
+                               connection->error = MPD_ERROR_NOTMPD;
+                               return connection;
+                       }
+                       tmp = NULL;
+               }
+       }
+
+       free(output);
+
+       connection->doneProcessing = 1;
+
+       return connection;
+}
+
+void mpd_clearError(mpd_Connection * connection) {
+       connection->error = 0;
+       connection->errorStr[0] = '\0';
+}
+
+void mpd_closeConnection(mpd_Connection * connection) {
+       close(connection->sock);
+       if(connection->returnElement) free(connection->returnElement);
+       free(connection);
+}
+
+void mpd_executeCommand(mpd_Connection * connection, char * command) {
+       int ret;
+       struct timeval tv;
+       fd_set fds;
+       char * commandPtr = command;
+       int commandLen = strlen(command);
+
+       if(!connection->doneProcessing && !connection->commandList) {
+               strcpy(connection->errorStr,"not done processing current command");
+               connection->error = 1;
+               return;
+       }
+
+       mpd_clearError(connection);
+
+       FD_ZERO(&fds);
+       FD_SET(connection->sock,&fds);
+       tv.tv_sec = connection->timeout.tv_sec;
+       tv.tv_usec = connection->timeout.tv_usec;
+
+       while((ret = select(connection->sock+1,NULL,&fds,NULL,&tv)==1) || 
+                       (ret==-1 && errno==EINTR)) {
+               ret = send(connection->sock,commandPtr,commandLen,
+                               MSG_DONTWAIT);
+               if(ret<=0)
+               {
+                       if(ret==EAGAIN || ret==EINTR) continue;
+                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                               "problems giving command \"%s\"",command);
+                       connection->error = MPD_ERROR_SENDING;
+                       return;
+               }
+               else {
+                       commandPtr+=ret;
+                       commandLen-=ret;
+               }
+
+               if(commandLen<=0) break;
+       }
+
+       if(commandLen>0) {
+               perror("");
+               snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                       "timeout sending command \"%s\"",command);
+               connection->error = MPD_ERROR_TIMEOUT;
+               return;
+       }
+
+       if(!connection->commandList) connection->doneProcessing = 0;
+}
+
+void mpd_getNextReturnElement(mpd_Connection * connection) {
+       char * output = NULL;
+       char * rt = NULL;
+       char * name;
+       char * value;
+       fd_set fds;
+       struct timeval tv;
+       char * tok;
+       int readed;
+       char * bufferCheck;
+       int err;
+
+       if(connection->returnElement) mpd_freeReturnElement(connection->returnElement);
+       connection->returnElement = NULL;
+
+       if(connection->doneProcessing) {
+               strcpy(connection->errorStr,"already done processing current command");
+               connection->error = 1;
+               return;
+       }
+
+       bufferCheck = connection->buffer+connection->bufstart;
+       while(connection->bufstart>=connection->buflen || 
+                       !(rt = strstr(bufferCheck,"\n"))) {
+               if(connection->buflen>=MPD_BUFFER_MAX_LENGTH) {
+                       memmove(connection->buffer,
+                                       connection->buffer+
+                                       connection->bufstart,
+                                       connection->buflen-
+                                       connection->bufstart+1);
+                       bufferCheck-=connection->bufstart;
+                       connection->buflen-=connection->bufstart;
+                       connection->bufstart = 0;
+               }
+               if(connection->buflen>=MPD_BUFFER_MAX_LENGTH) {
+                       strcpy(connection->errorStr,"buffer overrun");
+                       connection->error = MPD_ERROR_BUFFEROVERRUN;
+                       connection->doneProcessing = 1;
+                       return;
+               }
+               bufferCheck+=connection->buflen-connection->bufstart;
+               tv.tv_sec = connection->timeout.tv_sec;
+               tv.tv_usec = connection->timeout.tv_usec;
+               FD_ZERO(&fds);
+               FD_SET(connection->sock,&fds);
+               if((err = select(connection->sock+1,&fds,NULL,NULL,&tv) == 1)) {
+                       readed = recv(connection->sock,
+                               connection->buffer+connection->buflen,
+                               MPD_BUFFER_MAX_LENGTH-connection->buflen,
+                               MSG_DONTWAIT);
+                       if(readed<0 && (errno==EAGAIN || errno==EINTR)) {
+                               continue;
+                       }
+                       if(readed<=0) {
+                               strcpy(connection->errorStr,"connection"
+                                       " closed");
+                               connection->error = MPD_ERROR_CONNCLOSED;
+                               connection->doneProcessing = 1;
+                               return;
+                       }
+                       connection->buflen+=readed;
+                       connection->buffer[connection->buflen] = '\0';
+               }
+               else if(err<0 && errno==EINTR) continue;
+               else {
+                       strcpy(connection->errorStr,"connection timeout");
+                       connection->error = MPD_ERROR_TIMEOUT;
+                       connection->doneProcessing = 1;
+                       return;
+               }
+       }
+
+       *rt = '\0';
+       output = connection->buffer+connection->bufstart;
+       connection->bufstart = rt - connection->buffer + 1;
+
+       if(strcmp(output,"OK")==0) {
+               connection->doneProcessing = 1;
+               return;
+       }
+       if(strncmp(output,"ACK",strlen("ACK"))==0) {
+               strcpy(connection->errorStr,output);
+               connection->error = MPD_ERROR_ACK;
+               connection->doneProcessing = 1;
+               return;
+       }
+
+       name = strtok_r(output,":",&tok);
+       if(name && (value = strtok_r(NULL,"",&tok)) && value[0]==' ') {
+               connection->returnElement = mpd_newReturnElement(name,&(value[1]));
+       }
+       else {
+               if(!name || !value) {
+                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                                       "error parsing: %s",output);
+               }
+               else {
+                       snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
+                                       "error parsing: %s:%s",name,value);
+               }
+               connection->errorStr[MPD_BUFFER_MAX_LENGTH] = '\0';
+               connection->error = 1;
+       }
+}
+
+void mpd_finishCommand(mpd_Connection * connection) {
+       while(!connection->doneProcessing) mpd_getNextReturnElement(connection);
+}
+
+
+mpd_Status * mpd_getStatus(mpd_Connection * connection) {
+       mpd_Status * status;
+
+       mpd_executeCommand(connection,"status\n");
+               
+       if(connection->error) return NULL;
+
+       status = malloc(sizeof(mpd_Status));
+       status->volume = -1;
+       status->repeat = 0;
+       status->random = 0;
+       status->playlist = -1;
+       status->playlistLength = -1;
+       status->state = -1;
+       status->song = 0;
+       status->elapsedTime = 0;
+       status->totalTime = 0;
+       status->bitRate = 0;
+       status->sampleRate = 0;
+       status->bits = 0;
+       status->channels = 0;
+       status->crossfade = -1;
+       status->error = NULL;
+       status->updatingDb = 0;
+
+       mpd_getNextReturnElement(connection);
+       if(connection->error) {
+               free(status);
+               return NULL;
+       }
+       while(connection->returnElement) {
+               mpd_ReturnElement * re = connection->returnElement;
+               if(strcmp(re->name,"volume")==0) {
+                       status->volume = atoi(re->value);
+               }
+               else if(strcmp(re->name,"repeat")==0) {
+                       status->repeat = atoi(re->value);
+               }
+               else if(strcmp(re->name,"random")==0) {
+                       status->random = atoi(re->value);
+               }
+               else if(strcmp(re->name,"playlist")==0) {
+                       status->playlist = strtol(re->value,NULL,10);
+               }
+               else if(strcmp(re->name,"playlistlength")==0) {
+                       status->playlistLength = atoi(re->value);
+               }
+               else if(strcmp(re->name,"bitrate")==0) {
+                       status->bitRate = atoi(re->value);
+               }
+               else if(strcmp(re->name,"state")==0) {
+                       if(strcmp(re->value,"play")==0) {
+                               status->state = MPD_STATUS_STATE_PLAY;
+                       }
+                       else if(strcmp(re->value,"stop")==0) {
+                               status->state = MPD_STATUS_STATE_STOP;
+                       }
+                       else if(strcmp(re->value,"pause")==0) {
+                               status->state = MPD_STATUS_STATE_PAUSE;
+                       }
+                       else {
+                               status->state = MPD_STATUS_STATE_UNKNOWN;
+                       }
+               }
+               else if(strcmp(re->name,"song")==0) {
+                       status->song = atoi(re->value);
+               }
+               else if(strcmp(re->name,"time")==0) {
+                       char * tok;
+                       char * copy;
+                       char * temp;
+                       copy = strdup(re->value);
+                       temp = strtok_r(copy,":",&tok);
+                       if(temp) {
+                               status->elapsedTime = atoi(temp);
+                               temp = strtok_r(NULL,"",&tok);
+                               if(temp) status->totalTime = atoi(temp);
+                       }
+                       free(copy);
+               }
+               else if(strcmp(re->name,"error")==0) {
+                       status->error = strdup(re->value);
+               }
+               else if(strcmp(re->name,"xfade")==0) {
+                       status->crossfade = atoi(re->value);
+               }
+               else if(strcmp(re->name,"updating_db")==0) {
+                       status->updatingDb = atoi(re->value);
+               }
+               else if(strcmp(re->name,"audio")==0) {
+                       char * tok;
+                       char * copy;
+                       char * temp;
+                       copy = strdup(re->value);
+                       temp = strtok_r(copy,":",&tok);
+                       if(temp) {
+                               status->sampleRate = atoi(temp);
+                               temp = strtok_r(NULL,":",&tok);
+                               if(temp) {
+                                       status->bits = atoi(temp);
+                                       temp = strtok_r(NULL,"",&tok);
+                                       if(temp) status->channels = atoi(temp);
+                               }
+                       }
+                       free(copy);
+               }
+
+               mpd_getNextReturnElement(connection);
+               if(connection->error) {
+                       free(status);
+                       return NULL;
+               }
+       }
+
+       if(connection->error) {
+               free(status);
+               return NULL;
+       }
+       else if(status->state<0) {
+               strcpy(connection->errorStr,"state not found");
+               connection->error = 1;
+               free(status);
+               return NULL;
+       }
+
+       return status;
+}
+
+void mpd_freeStatus(mpd_Status * status) {
+       if(status->error) free(status->error);
+       free(status);
+}
+
+mpd_Stats * mpd_getStats(mpd_Connection * connection) {
+       mpd_Stats * stats;
+
+       mpd_executeCommand(connection,"stats\n");
+               
+       if(connection->error) return NULL;
+
+       stats = malloc(sizeof(mpd_Stats));
+       stats->numberOfArtists = 0;
+       stats->numberOfAlbums = 0;
+       stats->numberOfSongs = 0;
+       stats->uptime = 0;
+       stats->dbUpdateTime = 0;
+       stats->playTime = 0;
+       stats->dbPlayTime = 0;
+
+       mpd_getNextReturnElement(connection);
+       if(connection->error) {
+               free(stats);
+               return NULL;
+       }
+       while(connection->returnElement) {
+               mpd_ReturnElement * re = connection->returnElement;
+               if(strcmp(re->name,"artists")==0) {
+                       stats->numberOfArtists = atoi(re->value);
+               }
+               else if(strcmp(re->name,"albums")==0) {
+                       stats->numberOfAlbums = atoi(re->value);
+               }
+               else if(strcmp(re->name,"songs")==0) {
+                       stats->numberOfSongs = atoi(re->value);
+               }
+               else if(strcmp(re->name,"uptime")==0) {
+                       stats->uptime = strtol(re->value,NULL,10);
+               }
+               else if(strcmp(re->name,"db_update")==0) {
+                       stats->dbUpdateTime = strtol(re->value,NULL,10);
+               }
+               else if(strcmp(re->name,"playtime")==0) {
+                       stats->playTime = strtol(re->value,NULL,10);
+               }
+               else if(strcmp(re->name,"db_playtime")==0) {
+                       stats->dbPlayTime = strtol(re->value,NULL,10);
+               }
+
+               mpd_getNextReturnElement(connection);
+               if(connection->error) {
+                       free(stats);
+                       return NULL;
+               }
+       }
+
+       if(connection->error) {
+               free(stats);
+               return NULL;
+       }
+
+       return stats;
+}
+
+void mpd_freeStats(mpd_Stats * stats) {
+       free(stats);
+}
+
+void mpd_initSong(mpd_Song * song) {
+       song->file = NULL;
+       song->artist = NULL;
+       song->album = NULL;
+       song->track = NULL;
+       song->title = NULL;
+       song->time = MPD_SONG_NO_TIME;
+}
+
+void mpd_finishSong(mpd_Song * song) {
+       if(song->file) free(song->file);
+       if(song->artist) free(song->artist);
+       if(song->album) free(song->album);
+       if(song->title) free(song->title);
+       if(song->track) free(song->track);
+}
+
+mpd_Song * mpd_newSong() {
+       mpd_Song * ret = malloc(sizeof(mpd_Song));
+
+       mpd_initSong(ret);
+
+       return ret;
+}
+
+void mpd_freeSong(mpd_Song * song) {
+       mpd_finishSong(song);
+       free(song);
+}
+
+mpd_Song * mpd_songDup(mpd_Song * song) {
+       mpd_Song * ret = mpd_newSong();
+
+       if(song->file) ret->file = strdup(song->file);
+       if(song->artist) ret->artist = strdup(song->artist);
+       if(song->album) ret->album = strdup(song->album);
+       if(song->title) ret->title = strdup(song->title);
+       if(song->track) ret->track = strdup(song->track);
+       ret->time = song->time;
+
+       return ret;
+}
+
+void mpd_initDirectory(mpd_Directory * directory) {
+       directory->path = NULL;
+}
+
+void mpd_finishDirectory(mpd_Directory * directory) {
+       if(directory->path) free(directory->path);
+}
+
+mpd_Directory * mpd_newDirectory () {
+       mpd_Directory * directory = malloc(sizeof(mpd_Directory));;
+
+       mpd_initDirectory(directory);
+       
+       return directory;
+}
+
+void mpd_freeDirectory(mpd_Directory * directory) {
+       mpd_finishDirectory(directory);
+
+       free(directory);
+}
+
+mpd_Directory * mpd_directoryDup(mpd_Directory * directory) {
+       mpd_Directory * ret = mpd_newDirectory();
+
+       if(directory->path) ret->path = strdup(directory->path);
+
+       return ret;
+}
+
+void mpd_initPlaylistFile(mpd_PlaylistFile * playlist) {
+       playlist->path = NULL;
+}
+
+void mpd_finishPlaylistFile(mpd_PlaylistFile * playlist) {
+       if(playlist->path) free(playlist->path);
+}
+
+mpd_PlaylistFile * mpd_newPlaylistFile() {
+       mpd_PlaylistFile * playlist = malloc(sizeof(mpd_PlaylistFile));
+
+       mpd_initPlaylistFile(playlist);
+
+       return playlist;
+}
+
+void mpd_freePlaylistFile(mpd_PlaylistFile * playlist) {
+       mpd_finishPlaylistFile(playlist);
+       free(playlist);
+}
+
+mpd_PlaylistFile * mpd_playlistFileDup(mpd_PlaylistFile * playlist) {
+       mpd_PlaylistFile * ret = mpd_newPlaylistFile();
+
+       if(playlist->path) ret->path = strdup(playlist->path);
+
+       return ret;
+}
+
+void mpd_initInfoEntity(mpd_InfoEntity * entity) {
+       entity->info.directory = NULL;
+} 
+
+void mpd_finishInfoEntity(mpd_InfoEntity * entity) {
+       if(entity->info.directory) {
+               if(entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) {
+                       mpd_freeDirectory(entity->info.directory);
+               }
+               else if(entity->type == MPD_INFO_ENTITY_TYPE_SONG) {
+                       mpd_freeSong(entity->info.song);
+               }
+               else if(entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) {
+                       mpd_freePlaylistFile(entity->info.playlistFile);
+               }
+       }
+}
+
+mpd_InfoEntity * mpd_newInfoEntity() {
+       mpd_InfoEntity * entity = malloc(sizeof(mpd_InfoEntity));
+       
+       mpd_initInfoEntity(entity);
+
+       return entity;
+}
+
+void mpd_freeInfoEntity(mpd_InfoEntity * entity) {
+       mpd_finishInfoEntity(entity);
+       free(entity);
+}
+
+void mpd_sendInfoCommand(mpd_Connection * connection, char * command) {
+       mpd_executeCommand(connection,command);
+}
+
+mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection) {
+       mpd_InfoEntity * entity = NULL;
+
+       if(connection->doneProcessing) return NULL;
+
+       if(!connection->returnElement) mpd_getNextReturnElement(connection);
+
+       if(connection->returnElement) { 
+               if(strcmp(connection->returnElement->name,"file")==0) {
+                       entity = mpd_newInfoEntity();
+                       entity->type = MPD_INFO_ENTITY_TYPE_SONG;
+                       entity->info.song = mpd_newSong();
+                       entity->info.song->file = 
+                               strdup(connection->returnElement->value);
+               }
+               else if(strcmp(connection->returnElement->name,
+                                       "directory")==0) {
+                       entity = mpd_newInfoEntity();
+                       entity->type = MPD_INFO_ENTITY_TYPE_DIRECTORY;
+                       entity->info.directory = mpd_newDirectory();
+                       entity->info.directory->path = 
+                               strdup(connection->returnElement->value);
+               }
+               else if(strcmp(connection->returnElement->name,"playlist")==0) {
+                       entity = mpd_newInfoEntity();
+                       entity->type = MPD_INFO_ENTITY_TYPE_PLAYLISTFILE;
+                       entity->info.playlistFile = mpd_newPlaylistFile();
+                       entity->info.playlistFile->path = 
+                               strdup(connection->returnElement->value);
+               }
+               else {
+                       connection->error = 1;
+                       strcpy(connection->errorStr,"problem parsing song info");
+                       return NULL;
+               }
+       }
+       else return NULL;
+
+       mpd_getNextReturnElement(connection);
+       while(connection->returnElement) {
+               mpd_ReturnElement * re = connection->returnElement;
+
+               if(strcmp(re->name,"file")==0) return entity;
+               else if(strcmp(re->name,"directory")==0) return entity;
+               else if(strcmp(re->name,"playlist")==0) return entity;
+
+               if(entity->type == MPD_INFO_ENTITY_TYPE_SONG && 
+                               strlen(re->value)) {
+                       if(!entity->info.song->artist &&
+                                       strcmp(re->name,"Artist")==0) {
+                               entity->info.song->artist = strdup(re->value);
+                       }
+                       else if(!entity->info.song->album &&
+                                       strcmp(re->name,"Album")==0) {
+                               entity->info.song->album = strdup(re->value);
+                       }
+                       else if(!entity->info.song->title &&
+                                       strcmp(re->name,"Title")==0) {
+                               entity->info.song->title = strdup(re->value);
+                       }
+                       else if(!entity->info.song->track &&
+                                       strcmp(re->name,"Track")==0) {
+                               entity->info.song->track = strdup(re->value);
+                       }
+                       else if(entity->info.song->time==MPD_SONG_NO_TIME &&
+                                       strcmp(re->name,"Time")==0) {
+                               entity->info.song->time = atoi(re->value);
+                       }
+               }
+               else if(entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) {
+               }
+               else if(entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) {
+               }
+
+               mpd_getNextReturnElement(connection);
+       }
+
+       return entity;
+}
+
+char * mpd_getNextReturnElementNamed(mpd_Connection * connection, 
+               const char * name) 
+{
+       if(connection->doneProcessing) return NULL;
+
+       mpd_getNextReturnElement(connection);
+       while(connection->returnElement) {
+               mpd_ReturnElement * re = connection->returnElement;
+
+               if(strcmp(re->name,name)==0) return strdup(re->value);
+               mpd_getNextReturnElement(connection);
+       }
+
+       return NULL;
+}
+
+char * mpd_getNextArtist(mpd_Connection * connection) {
+       return mpd_getNextReturnElementNamed(connection,"Artist");
+}
+
+char * mpd_getNextAlbum(mpd_Connection * connection) {
+       return mpd_getNextReturnElementNamed(connection,"Album");
+}
+
+void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum) {
+       char * string = malloc(strlen("playlistinfo")+25);
+       sprintf(string,"playlistinfo \"%i\"\n",songNum);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendListallCommand(mpd_Connection * connection, const char * dir) {
+       char * sDir = mpd_sanitizeArg(dir);
+       char * string = malloc(strlen("listall")+strlen(sDir)+5);
+       sprintf(string,"listall \"%s\"\n",sDir);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+       free(sDir);
+}
+
+void mpd_sendListallInfoCommand(mpd_Connection * connection, const char * dir) {
+       char * sDir = mpd_sanitizeArg(dir);
+       char * string = malloc(strlen("listallinfo")+strlen(sDir)+5);
+       sprintf(string,"listallinfo \"%s\"\n",sDir);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+       free(sDir);
+}
+
+void mpd_sendLsInfoCommand(mpd_Connection * connection, const char * dir) {
+       char * sDir = mpd_sanitizeArg(dir);
+       char * string = malloc(strlen("lsinfo")+strlen(sDir)+5);
+       sprintf(string,"lsinfo \"%s\"\n",sDir);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+       free(sDir);
+}
+
+void mpd_sendSearchCommand(mpd_Connection * connection, int table, 
+               const char * str) 
+{
+       char st[10];
+       char * string;
+       char * sanitStr = mpd_sanitizeArg(str);
+       if(table == MPD_TABLE_ARTIST) strcpy(st,"artist");
+       else if(table == MPD_TABLE_ALBUM) strcpy(st,"album");
+       else if(table == MPD_TABLE_TITLE) strcpy(st,"title");
+       else if(table == MPD_TABLE_FILENAME) strcpy(st,"filename");
+       else {
+               connection->error = 1;
+               strcpy(connection->errorStr,"unknown table for search");
+               return;
+       }
+       string = malloc(strlen("search")+strlen(sanitStr)+strlen(st)+6);
+       sprintf(string,"search %s \"%s\"\n",st,sanitStr);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+       free(sanitStr);
+}
+
+void mpd_sendFindCommand(mpd_Connection * connection, int table, 
+               const char * str) 
+{
+       char st[10];
+       char * string;
+       char * sanitStr = mpd_sanitizeArg(str);
+       if(table == MPD_TABLE_ARTIST) strcpy(st,"artist");
+       else if(table == MPD_TABLE_ALBUM) strcpy(st,"album");
+       else if(table == MPD_TABLE_TITLE) strcpy(st,"title");
+       else {
+               connection->error = 1;
+               strcpy(connection->errorStr,"unknown table for find");
+               return;
+       }
+       string = malloc(strlen("find")+strlen(sanitStr)+strlen(st)+6);
+       sprintf(string,"find %s \"%s\"\n",st,sanitStr);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+       free(sanitStr);
+}
+
+void mpd_sendListCommand(mpd_Connection * connection, int table, 
+               const char * arg1) 
+{
+       char st[10];
+       char * string;
+       if(table == MPD_TABLE_ARTIST) strcpy(st,"artist");
+       else if(table == MPD_TABLE_ALBUM) strcpy(st,"album");
+       else {
+               connection->error = 1;
+               strcpy(connection->errorStr,"unknown table for list");
+               return;
+       }
+       if(arg1) {
+               char * sanitArg1 = mpd_sanitizeArg(arg1);
+               string = malloc(strlen("list")+strlen(sanitArg1)+strlen(st)+6);
+               sprintf(string,"list %s \"%s\"\n",st,sanitArg1);
+               free(sanitArg1);
+       }
+       else {
+               string = malloc(strlen("list")+strlen(st)+3);
+               sprintf(string,"list %s\n",st);
+       }
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendAddCommand(mpd_Connection * connection, const char * file) {
+       char * sFile = mpd_sanitizeArg(file);
+       char * string = malloc(strlen("add")+strlen(sFile)+5);
+       sprintf(string,"add \"%s\"\n",sFile);
+       mpd_executeCommand(connection,string);
+       free(string);
+       free(sFile);
+}
+
+void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum) {
+       char * string = malloc(strlen("delete")+25);
+       sprintf(string,"delete \"%i\"\n",songNum);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendSaveCommand(mpd_Connection * connection, const char * name) {
+       char * sName = mpd_sanitizeArg(name);
+       char * string = malloc(strlen("save")+strlen(sName)+5);
+       sprintf(string,"save \"%s\"\n",sName);
+       mpd_executeCommand(connection,string);
+       free(string);
+       free(sName);
+}
+
+void mpd_sendLoadCommand(mpd_Connection * connection, const char * name) {
+       char * sName = mpd_sanitizeArg(name);
+       char * string = malloc(strlen("load")+strlen(sName)+5);
+       sprintf(string,"load \"%s\"\n",sName);
+       mpd_executeCommand(connection,string);
+       free(string);
+       free(sName);
+}
+
+void mpd_sendRmCommand(mpd_Connection * connection, const char * name) {
+       char * sName = mpd_sanitizeArg(name);
+       char * string = malloc(strlen("rm")+strlen(sName)+5);
+       sprintf(string,"rm \"%s\"\n",sName);
+       mpd_executeCommand(connection,string);
+       free(string);
+       free(sName);
+}
+
+void mpd_sendShuffleCommand(mpd_Connection * connection) {
+       mpd_executeCommand(connection,"shuffle\n");
+}
+
+void mpd_sendClearCommand(mpd_Connection * connection) {
+       mpd_executeCommand(connection,"clear\n");
+}
+
+void mpd_sendPlayCommand(mpd_Connection * connection, int songNum) {
+       char * string = malloc(strlen("play")+25);
+       sprintf(string,"play \"%i\"\n",songNum);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendStopCommand(mpd_Connection * connection) {
+       mpd_executeCommand(connection,"stop\n");
+}
+
+void mpd_sendPauseCommand(mpd_Connection * connection) {
+       mpd_executeCommand(connection,"pause\n");
+}
+
+void mpd_sendNextCommand(mpd_Connection * connection) {
+       mpd_executeCommand(connection,"next\n");
+}
+
+void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to) {
+       char * string = malloc(strlen("move")+25);
+       sprintf(string,"move \"%i\" \"%i\"\n",from,to);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2) {
+       char * string = malloc(strlen("swap")+25);
+       sprintf(string,"swap \"%i\" \"%i\"\n",song1,song2);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time) {
+       char * string = malloc(strlen("seek")+25);
+       sprintf(string,"seek \"%i\" \"%i\"\n",song,time);
+       mpd_sendInfoCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendUpdateCommand(mpd_Connection * connection) {
+        mpd_executeCommand(connection,"update\n");
+}
+
+int mpd_getUpdateId(mpd_Connection * connection) {
+       char * jobid;
+       int ret = 0;
+
+       jobid = mpd_getNextReturnElementNamed(connection,"updating_db");
+       if(jobid) {
+               ret = atoi(jobid);
+               free(jobid);
+       }
+
+       return ret;
+}
+
+void mpd_sendPrevCommand(mpd_Connection * connection) {
+       mpd_executeCommand(connection,"previous\n");
+}
+
+void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode) {
+       char * string = malloc(strlen("repeat")+25);
+       sprintf(string,"repeat \"%i\"\n",repeatMode);
+       mpd_executeCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode) {
+       char * string = malloc(strlen("random")+25);
+       sprintf(string,"random \"%i\"\n",randomMode);
+       mpd_executeCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange) {
+       char * string = malloc(strlen("setvol")+25);
+       sprintf(string,"setvol \"%i\"\n",volumeChange);
+       mpd_executeCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange) {
+       char * string = malloc(strlen("volume")+25);
+       sprintf(string,"volume \"%i\"\n",volumeChange);
+       mpd_executeCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds) {
+       char * string = malloc(strlen("crossfade")+25);
+       sprintf(string,"crossfade \"%i\"\n",seconds);
+       mpd_executeCommand(connection,string);
+       free(string);
+}
+
+void mpd_sendPasswordCommand(mpd_Connection * connection, const char * pass) {
+       char * sPass = mpd_sanitizeArg(pass);
+       char * string = malloc(strlen("password")+strlen(sPass)+5);
+       sprintf(string,"password \"%s\"\n",sPass);
+       mpd_executeCommand(connection,string);
+       free(string);
+       free(sPass);
+}
+
+void mpd_sendCommandListBegin(mpd_Connection * connection) {
+       if(connection->commandList) {
+               strcpy(connection->errorStr,"already in command list mode");
+               connection->error = 1;
+               return;
+       }
+       connection->commandList = 1;
+       mpd_executeCommand(connection,"command_list_begin\n");
+}
+
+void mpd_sendCommandListEnd(mpd_Connection * connection) {
+       if(!connection->commandList) {
+               strcpy(connection->errorStr,"not in command list mode");
+               connection->error = 1;
+               return;
+       }
+       connection->commandList = 0;
+       mpd_executeCommand(connection,"command_list_end\n");
+}
diff --git a/src/libmpdclient.h b/src/libmpdclient.h
new file mode 100644 (file)
index 0000000..e5e5879
--- /dev/null
@@ -0,0 +1,399 @@
+/* libmpdclient
+ * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#ifndef LIBMPDCLIENT_H
+#define LIBMPDCLIENT_H
+
+#include <sys/time.h>
+
+#define MPD_BUFFER_MAX_LENGTH  50000
+#define MPD_WELCOME_MESSAGE    "OK MPD "
+
+#define MPD_ERROR_TIMEOUT      10 /* timeout trying to talk to mpd */
+#define MPD_ERROR_SYSTEM       11 /* system error */
+#define MPD_ERROR_UNKHOST      12 /* unknown host */
+#define MPD_ERROR_CONNPORT     13 /* problems connecting to port on host */
+#define MPD_ERROR_NOTMPD       14 /* mpd not running on port at host */
+#define MPD_ERROR_NORESPONSE   15 /* no response on attempting to connect */
+#define MPD_ERROR_SENDING      16 /* error sending command */
+#define MPD_ERROR_CONNCLOSED   17 /* connection closed by mpd */
+#define MPD_ERROR_ACK          18 /* ACK returned! */
+#define MPD_ERROR_BUFFEROVERRUN        19 /* Buffer was overrun! */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* internal stuff don't touch this struct */
+typedef struct _mpd_ReturnElement {
+       char * name;
+       char * value;
+} mpd_ReturnElement;
+
+/* mpd_Connection
+ * holds info about connection to mpd
+ * use error, and errorStr to detect errors
+ */
+typedef struct _mpd_Connection {
+       /* use this to check the version of mpd */
+       int version[3];
+       /* IMPORTANT, you want to get the error messages from here */
+       char errorStr[MPD_BUFFER_MAX_LENGTH+1];
+       /* this will be set to 1 if there is an error, 0 if not */
+       int error;
+       /* DON'T TOUCH any of the rest of this stuff */
+       int sock; 
+       char buffer[MPD_BUFFER_MAX_LENGTH+1];
+       int buflen;
+       int bufstart;
+       int doneProcessing;
+       int commandList;
+       mpd_ReturnElement * returnElement;
+       struct timeval timeout;
+} mpd_Connection;
+
+/* mpd_newConnection
+ * use this to open a new connection
+ * you should use mpd_closeConnection, when your done with the connection,
+ * even if an error has occurred
+ * _timeout_ is the connection timeout period in seconds
+ */
+mpd_Connection * mpd_newConnection(const char * host, int port, float timeout);
+
+void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout);
+
+/* mpd_closeConnection
+ * use this to close a connection and free'ing subsequent memory
+ */
+void mpd_closeConnection(mpd_Connection * connection);
+
+/* mpd_clearError
+ * clears error
+ */
+void mpd_clearError(mpd_Connection * connection);
+
+/* STATUS STUFF */
+
+/* use these with status.state to determine what state the player is in */
+#define MPD_STATUS_STATE_UNKNOWN       0
+#define MPD_STATUS_STATE_STOP          1
+#define MPD_STATUS_STATE_PLAY          2
+#define MPD_STATUS_STATE_PAUSE         3
+
+/* us this with status.volume to determine if mpd has volume support */
+#define MPD_STATUS_NO_VOLUME           -1
+
+/* mpd_Status
+ * holds info return from status command
+ */
+typedef struct mpd_Status {
+       /* 0-100, or MPD_STATUS_NO_VOLUME when there is no volume support */
+       int volume;
+       /* 1 if repeat is on, 0 otherwise */
+       int repeat;
+       /* 1 if random is on, 0 otherwise */
+       int random;
+       /* playlist length */
+       int playlistLength;
+       /* playlist, use this to determine when the playlist has changed */
+       long long playlist;
+       /* use with MPD_STATUS_STATE_* to determine state of player */
+       int state;
+       /* crossfade setting in seconds */
+       int crossfade;
+       /* if in PLAY or PAUSE state, this is the number of the currently
+        * playing song in the playlist, beginning with 0
+        */
+       int song;
+       /* time in seconds that have elapsed in the currently playing/paused
+        * song
+        */
+       int elapsedTime;
+       /* length in seconds of the currently playing/paused song */
+       int totalTime;
+       /* current bit rate in kbs */
+       int bitRate;
+       /* audio sample rate */
+       unsigned int sampleRate;
+       /* audio bits */
+       int bits;
+       /* audio channels */
+       int channels;
+       /* 1 if mpd is updating, 0 otherwise */
+       int updatingDb;
+       /* error */
+       char * error;
+} mpd_Status;
+
+/* mpd_getStatus
+ * returns status info, be sure to free it with mpd_freeStatus()
+ */
+mpd_Status * mpd_getStatus(mpd_Connection * connection);
+
+/* mpd_freeStatus
+ * free's status info malloc'd and returned by mpd_getStatus
+ */
+void mpd_freeStatus(mpd_Status * status);
+
+typedef struct _mpd_Stats {
+       int numberOfArtists;
+       int numberOfAlbums;
+       int numberOfSongs;
+       unsigned long uptime;
+       unsigned long dbUpdateTime;
+       unsigned long playTime;
+       unsigned long dbPlayTime;
+} mpd_Stats;
+
+mpd_Stats * mpd_getStats(mpd_Connection * connection);
+
+void mpd_freeStats(mpd_Stats * stats);
+
+/* SONG STUFF */
+
+#define MPD_SONG_NO_TIME       -1
+
+/* mpd_Song
+ * for storing song info returned by mpd
+ */
+typedef struct _mpd_Song {
+       /* filename of song */
+       char * file;
+       /* artist, maybe NULL if there is no tag */
+       char * artist;
+       /* title, maybe NULL if there is no tag */
+       char * title;
+       /* album, maybe NULL if there is no tag */
+       char * album;
+       /* track, maybe NULL if there is no tag */
+       char * track;
+       /* length of song in seconds, check that it is not MPD_SONG_NO_TIME  */
+       int time;
+} mpd_Song;
+
+/* mpd_newSong
+ * use to allocate memory for a new mpd_Song
+ * file, artist, etc all initialized to NULL
+ * if your going to assign values to file, artist, etc
+ * be sure to malloc or strdup the memory
+ * use mpd_freeSong to free the memory for the mpd_Song, it will also
+ * free memory for file, artist, etc, so don't do it yourself
+ */
+mpd_Song * mpd_newSong();
+
+/* mpd_freeSong
+ * use to free memory allocated by mpd_newSong
+ * also it will free memory pointed to by file, artist, etc, so be careful
+ */
+void mpd_freeSong(mpd_Song * song);
+
+/* mpd_songDup
+ * works like strDup, but for a mpd_Song
+ */
+mpd_Song * mpd_songDup(mpd_Song * song);
+
+/* DIRECTORY STUFF */
+
+/* mpd_Directory
+ * used to store info fro directory (right now that just the path)
+ */
+typedef struct _mpd_Directory {
+       char * path;
+} mpd_Directory;
+
+/* mpd_newDirectory
+ * allocates memory for a new directory
+ * use mpd_freeDirectory to free this memory
+ */
+mpd_Directory * mpd_newDirectory ();
+
+/* mpd_freeDirectory
+ * used to free memory allocated with mpd_newDirectory, and it frees
+ * path of mpd_Directory, so be careful
+ */
+void mpd_freeDirectory(mpd_Directory * directory);
+
+/* mpd_directoryDup
+ * works like strdup, but for mpd_Directory
+ */
+mpd_Directory * mpd_directoryDup(mpd_Directory * directory);
+
+/* PLAYLISTFILE STUFF */
+
+/* mpd_PlaylistFile
+ * stores info about playlist file returned by lsinfo
+ */
+typedef struct _mpd_PlaylistFile {
+       char * path;
+} mpd_PlaylistFile;
+
+/* mpd_newPlaylistFile
+ * allocates memory for new mpd_PlaylistFile, path is set to NULL
+ * free this memory with mpd_freePlaylistFile
+ */
+mpd_PlaylistFile * mpd_newPlaylistFile();
+
+/* mpd_freePlaylist
+ * free memory allocated for freePlaylistFile, will also free
+ * path, so be careful
+ */
+void mpd_freePlaylistFile(mpd_PlaylistFile * playlist);
+
+/* mpd_playlistFileDup
+ * works like strdup, but for mpd_PlaylistFile
+ */
+mpd_PlaylistFile * mpd_playlistFileDup(mpd_PlaylistFile * playlist);
+
+/* INFO ENTITY STUFF */
+
+/* the type of entity returned from one of the commands that generates info
+ * use in conjunction with mpd_InfoEntity.type
+ */
+#define MPD_INFO_ENTITY_TYPE_DIRECTORY         0
+#define MPD_INFO_ENTITY_TYPE_SONG              1
+#define MPD_INFO_ENTITY_TYPE_PLAYLISTFILE      2
+
+/* mpd_InfoEntity
+ * stores info on stuff returned info commands
+ */
+typedef struct mpd_InfoEntity {
+       /* the type of entity, use with MPD_INFO_ENTITY_TYPE_* to determine
+        * what this entity is (song, directory, etc...)
+        */
+       int type;
+       /* the actual data you want, mpd_Song, mpd_Directory, etc */
+       union {
+               mpd_Directory * directory;
+               mpd_Song * song;
+               mpd_PlaylistFile * playlistFile;
+       } info;
+} mpd_InfoEntity;
+
+mpd_InfoEntity * mpd_newInfoEntity();
+
+void mpd_freeInfoEntity(mpd_InfoEntity * entity);
+
+/* INFO COMMANDS AND STUFF */
+
+/* use this function to loop over after calling Info/Listall functions */
+mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection);
+
+/* songNum of -1, means to display the whole list */
+void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum);
+
+void mpd_sendListallCommand(mpd_Connection * connection, const char * dir);
+
+void mpd_sendListallInfoCommand(mpd_Connection * connection, const char * dir);
+
+void mpd_sendLsInfoCommand(mpd_Connection * connection, const char * dir);
+
+#define MPD_TABLE_ARTIST       0
+#define MPD_TABLE_ALBUM                1
+#define MPD_TABLE_TITLE                2
+#define MPD_TABLE_FILENAME     3
+
+void mpd_sendSearchCommand(mpd_Connection * connection, int table, 
+               const char * str);
+
+void mpd_sendFindCommand(mpd_Connection * connection, int table, 
+               const char * str);
+
+/* LIST TAG COMMANDS */
+
+/* use this function fetch next artist entry, be sure to free the returned 
+ * string.  NULL means there are no more.  Best used with sendListArtists
+ */
+char * mpd_getNextArtist(mpd_Connection * connection);
+
+char * mpd_getNextAlbum(mpd_Connection * connection);
+
+/* list artist or albums by artist, arg1 should be set to the artist if
+ * listing albums by a artist, otherwise NULL for listing all artists or albums
+ */
+void mpd_sendListCommand(mpd_Connection * connection, int table, 
+               const char * arg1);
+
+/* SIMPLE COMMANDS */
+
+void mpd_sendAddCommand(mpd_Connection * connection, const char * file);
+
+void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum);
+
+void mpd_sendSaveCommand(mpd_Connection * connection, const char * name);
+
+void mpd_sendLoadCommand(mpd_Connection * connection, const char * name);
+
+void mpd_sendRmCommand(mpd_Connection * connection, const char * name);
+
+void mpd_sendShuffleCommand(mpd_Connection * connection);
+
+void mpd_sendClearCommand(mpd_Connection * connection);
+
+/* use this to start playing at the beginning, useful when in random mode */
+#define MPD_PLAY_AT_BEGINNING  -1
+
+void mpd_sendPlayCommand(mpd_Connection * connection, int songNum);
+
+void mpd_sendStopCommand(mpd_Connection * connection);
+
+void mpd_sendPauseCommand(mpd_Connection * connection);
+
+void mpd_sendNextCommand(mpd_Connection * connection);
+
+void mpd_sendPrevCommand(mpd_Connection * connection);
+
+void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to);
+
+void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2);
+
+void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time);
+
+void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode);
+
+void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode);
+
+void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange);
+
+/* WARNING: don't use volume command, its depreacted */
+void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange);
+
+void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds);
+
+void mpd_sendUpdateCommand(mpd_Connection * connection);
+
+/* returns the update job id, call this after a update command*/
+int mpd_getUpdateId(mpd_Connection * connection);
+
+void mpd_sendPasswordCommand(mpd_Connection * connection, const char * pass);
+
+/* after executing a command, when your done with it to get its status
+ * (you want to check connection->error for an error)
+ */
+void mpd_finishCommand(mpd_Connection * connection);
+
+/* command list stuff, use this to do things like add files very quickly */
+void mpd_sendCommandListBegin(mpd_Connection * connection);
+
+void mpd_sendCommandListEnd(mpd_Connection * connection);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/list_window.c b/src/list_window.c
new file mode 100644 (file)
index 0000000..6b4a41f
--- /dev/null
@@ -0,0 +1,296 @@
+/* 
+ * (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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+#include "options.h"
+#include "support.h"
+#include "command.h"
+#include "colors.h"
+#include "list_window.h"
+
+list_window_t *
+list_window_init(WINDOW *w, int width, int height)
+{
+  list_window_t *lw;
+
+  lw = g_malloc(sizeof(list_window_t));
+  memset(lw, 0, sizeof(list_window_t));
+  lw->w = w;
+  lw->cols = width;
+  lw->rows = height;
+  lw->clear = 1;
+  return lw;
+}
+
+list_window_t *
+list_window_free(list_window_t *lw)
+{
+  if( lw )
+    {
+      memset(lw, 0, sizeof(list_window_t));
+      g_free(lw);
+    }
+  return NULL;
+}
+
+void
+list_window_reset(list_window_t *lw)
+{
+  lw->selected = 0;
+  lw->start = 0;
+  lw->clear = 1;
+}
+
+void
+list_window_check_selected(list_window_t *lw, int length)
+{
+  while( lw->start && lw->start+lw->rows>length)
+    lw->start--;
+
+  if( lw->selected<0 )
+    lw->selected=0;
+
+  while( lw->selected<lw->start )
+    lw->selected++;
+
+  while( lw->selected>0 && length>0 && lw->selected>=length )
+    lw->selected--;
+}
+
+void 
+list_window_set_selected(list_window_t *lw, int n)
+{
+  lw->selected=n;
+}
+
+void
+list_window_next(list_window_t *lw, int length)
+{
+  if( lw->selected < length-1 )
+    lw->selected++;
+}
+
+void
+list_window_previous(list_window_t *lw)
+{
+  if( lw->selected > 0 )
+    lw->selected--;
+}
+
+void
+list_window_first(list_window_t *lw)
+{
+  lw->selected = 0;
+}
+
+void
+list_window_last(list_window_t *lw, int length)
+{
+  lw->selected = length-1;
+}
+
+void
+list_window_next_page(list_window_t *lw, int length)
+{
+  int step = lw->rows-1;
+  if( step<= 0 )
+    return;
+  if( lw->selected+step < length-1 )
+    lw->selected+=step;
+  else
+    return list_window_last(lw,length);
+}
+
+void
+list_window_previous_page(list_window_t *lw)
+{
+  int step = lw->rows-1;
+  if( step<= 0 )
+    return;
+  if( lw->selected-step > 0 )
+    lw->selected-=step;
+  else
+    list_window_first(lw);
+}
+
+
+void 
+list_window_paint(list_window_t *lw,
+                 list_window_callback_fn_t callback,
+                 void *callback_data)
+{
+  int i;
+  int fill = options.wide_cursor;
+
+  while( lw->selected < lw->start )
+    {
+      lw->start--;
+      lw->clear=1;
+    }
+  while( lw->selected >= lw->start+lw->rows )
+    {
+      lw->start++;
+      lw->clear=1;
+    }
+
+  for(i=0; i<lw->rows; i++)
+    {
+      int highlight = 0;
+      char *label;
+
+      label = (callback) (lw->start+i, &highlight, callback_data);
+      wmove(lw->w, i, 0);
+      if( lw->clear && (!fill || !label) )
+       wclrtoeol(lw->w);
+      if( label )
+       {
+         int selected = lw->start+i == lw->selected;
+
+         if( highlight )
+           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( selected )
+           wattroff(lw->w, A_REVERSE);   
+       }
+       
+    }
+  lw->clear=0;
+}
+
+
+int
+list_window_find(list_window_t *lw, 
+                list_window_callback_fn_t callback,
+                void *callback_data,
+                char *str,
+                int wrap)
+{
+  int h;
+  int i = lw->selected+1;
+  char *label;
+  
+  while( wrap || i==lw->selected+1 )
+    {
+      while( (label=(callback) (i,&h,callback_data)) )
+       {
+         if( str && label && strcasestr(label, str) )
+           {
+             lw->selected = i;
+             return 0;
+           }
+         if( wrap && i==lw->selected )
+           return 1;
+         i++;
+       }
+      if( wrap )
+       {
+         i=0; /* first item */
+         beep(); 
+       }
+    }
+  return 1;
+}
+
+
+int
+list_window_rfind(list_window_t *lw, 
+                 list_window_callback_fn_t callback,
+                 void *callback_data,
+                 char *str,
+                 int wrap,
+                 int rows)
+{
+  int h;
+  int i = lw->selected-1;
+  char *label;
+
+  while( wrap || i==lw->selected-1 )
+    {
+      while( i>=0 && (label=(callback) (i,&h,callback_data)) )
+       {
+         if( str && label && strcasestr(label, str) )
+           {
+             lw->selected = i;
+             return 0;
+           }
+         if( wrap && i==lw->selected )
+           return 1;
+         i--;
+       }
+      if( wrap )
+       {
+         i=rows-1; /* last item */
+         beep();
+       }
+    }
+  return 1;
+}
+
+
+/* perform basic list window commands (movement) */
+int 
+list_window_cmd(list_window_t *lw, int rows, command_t cmd)
+{
+  switch(cmd)
+    {
+    case CMD_LIST_PREVIOUS:
+      list_window_previous(lw);
+      lw->repaint=1;
+      break;
+    case CMD_LIST_NEXT:
+      list_window_next(lw, rows);
+      lw->repaint=1;
+      break;
+    case CMD_LIST_FIRST:
+      list_window_first(lw);
+      lw->repaint  = 1;
+      break;
+    case CMD_LIST_LAST:
+      list_window_last(lw, rows);
+      lw->repaint = 1;
+      break;
+    case CMD_LIST_NEXT_PAGE:
+      list_window_next_page(lw, rows);
+      lw->repaint  = 1;
+      break;
+    case CMD_LIST_PREVIOUS_PAGE:
+      list_window_previous_page(lw);
+      lw->repaint  = 1;
+      break;
+    default:
+      return 0;
+    }
+  return 1;
+}
+
+
diff --git a/src/list_window.h b/src/list_window.h
new file mode 100644 (file)
index 0000000..9e91703
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef LIST_WINDOW_H
+#define LIST_WINDOW_H
+
+#define LW_ROW(lw) (lw ? lw->selected-lw->start :  0)
+
+typedef char *  (*list_window_callback_fn_t)   (int index, 
+                                               int *highlight,
+                                               void *data);
+
+typedef struct
+{
+  WINDOW *w;
+  int rows, cols;
+
+  int start;
+  int selected;
+  int clear;
+  int repaint;
+
+} list_window_t;
+
+
+/* create a new list window */
+list_window_t *list_window_init(WINDOW *w, int width, int height);
+
+/* destroy a list window (returns NULL) */
+list_window_t *list_window_free(list_window_t *lw);
+
+/* reset a list window (selected=0, start=0, clear=1) */
+void list_window_reset(list_window_t *lw);
+
+/* paint a list window */
+void list_window_paint(list_window_t *lw,
+                      list_window_callback_fn_t callback,
+                      void *callback_data);
+
+/* perform basic list window commands (movement) */
+int list_window_cmd(list_window_t *lw, int rows, command_t cmd);
+
+
+/* select functions */
+void list_window_set_selected(list_window_t *lw, int n);
+void list_window_previous(list_window_t *lw);
+void list_window_next(list_window_t *lw, int length);
+void list_window_first(list_window_t *lw);
+void list_window_last(list_window_t *lw, int length);
+void list_window_previous_page(list_window_t *lw);
+void list_window_next_page(list_window_t *lw, int length);
+void list_window_check_selected(list_window_t *lw, int length);
+
+/* find a string in a list window */
+int  list_window_find(list_window_t *lw, 
+                     list_window_callback_fn_t callback,
+                     void *callback_data,
+                     char *str,
+                     int wrap);
+
+/* find a string in a list window (reversed) */
+int
+list_window_rfind(list_window_t *lw, 
+                 list_window_callback_fn_t callback,
+                 void *callback_data,
+                 char *str,
+                 int wrap,
+                 int rows);
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..bb3740b
--- /dev/null
@@ -0,0 +1,199 @@
+/* 
+ * (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 <unistd.h>
+#include <signal.h>
+#include <glib.h>
+
+#include "config.h"
+#include "libmpdclient.h"
+#include "support.h"
+#include "mpc.h"
+#include "options.h"
+#include "command.h"
+#include "screen.h"
+#include "conf.h"
+
+/* time in seconds between mpd updates (double) */
+#define MPD_UPDATE_TIME        0.5
+
+/* timout in seconds before trying to reconnect (int) */
+#define MPD_RECONNECT_TIMEOUT  3
+
+
+static mpd_client_t *mpc = NULL;
+static GTimer       *timer = NULL;
+
+void
+exit_and_cleanup(void)
+{
+  screen_exit();
+  printf("\n");
+  charset_close();
+  if( mpc )
+    {
+      if( mpc_error(mpc) )
+       fprintf(stderr,"Error: %s\n", mpc_error_str(mpc));
+      mpc_close(mpc);
+    }
+  g_free(options.host);
+  g_free(options.password);
+  if( timer )
+    g_timer_destroy(timer);
+}
+
+void
+catch_sigint( int sig )
+{
+  printf( "\nExiting...\n");
+  exit(EXIT_SUCCESS);
+}
+
+int 
+main(int argc, const char *argv[])
+{
+  options_t *options;
+  struct sigaction act;
+  gboolean connected;
+
+  /* initialize options */
+  options = options_init();
+
+  /* parse command line options - 1 pass get configuration files */
+  options_parse(argc, argv);
+  
+  /* read configuration */
+  read_configuration(options);
+  
+  /* check key bindings */
+  if( check_key_bindings() )
+    {
+      fprintf(stderr, "Confusing key bindings - exiting!\n");
+      exit(EXIT_FAILURE);
+    }
+
+  /* parse command line options - 2 pass */
+  options_parse(argc, argv);
+
+  /* initialize local charset */
+  if( charset_init() )
+    exit(EXIT_FAILURE);
+
+  /* setup signal behavior - SIGINT */
+  sigemptyset( &act.sa_mask );
+  act.sa_flags    = 0;
+  act.sa_handler = catch_sigint;
+  if( sigaction( SIGINT, &act, NULL )<0 )
+    {
+      perror("signal");
+      exit(EXIT_FAILURE);
+    }
+  /* setup signal behavior - SIGTERM */
+  sigemptyset( &act.sa_mask );
+  act.sa_flags    = 0;
+  act.sa_handler = catch_sigint;
+  if( sigaction( SIGTERM, &act, NULL )<0 )
+    {
+      perror("sigaction()");
+      exit(EXIT_FAILURE);
+    }
+
+  /* set xterm title */
+  if( g_getenv("DISPLAY") )
+    printf("%c]0;%s%c", '\033', PACKAGE " version " VERSION, '\007');
+
+  /* install exit function */
+  atexit(exit_and_cleanup);
+
+  /* connect to our music player daemon */
+  mpc = mpc_connect(options->host, options->port, options->password);
+  if( mpc_error(mpc) )
+    exit(EXIT_FAILURE);
+
+  /* initialize curses */
+  screen_init();
+
+  /* initialize timer */
+  timer = g_timer_new();
+
+  connected = TRUE;
+  while( connected || options->reconnect )
+    {
+      static gdouble t = G_MAXDOUBLE;
+
+      if( connected && t>=MPD_UPDATE_TIME )
+       {
+         mpc_update(mpc);
+         if( mpc_error(mpc) == MPD_ERROR_ACK )
+           {
+             screen_status_printf("%s", mpc_error_str(mpc));
+             mpd_clearError(mpc->connection);
+             mpd_finishCommand(mpc->connection);
+           }
+         else if( mpc_error(mpc) )
+           {
+             screen_status_printf("Lost connection to %s", options->host);
+             connected = FALSE;         
+             doupdate();
+             mpd_clearError(mpc->connection);
+             mpd_closeConnection(mpc->connection);
+             mpc->connection = NULL;
+           }
+         else  
+           mpd_finishCommand(mpc->connection);
+         g_timer_start(timer);
+       }
+
+      if( connected )
+       {
+         command_t cmd;
+
+         screen_update(mpc);
+         if( (cmd=get_keyboard_command()) != CMD_NONE )
+           {
+             screen_cmd(mpc, cmd);
+             if( cmd==CMD_VOLUME_UP || cmd==CMD_VOLUME_DOWN)
+               /* make shure we dont update the volume yet */
+               g_timer_start(timer);
+           }
+         else
+           screen_idle(mpc);
+       }
+      else if( options->reconnect )
+       {
+         sleep(MPD_RECONNECT_TIMEOUT);
+         screen_status_printf("Connecting to %s...  [Press Ctrl-C to abort]", 
+                              options->host);
+         if( mpc_reconnect(mpc, 
+                           options->host, 
+                           options->port, 
+                           options->password) == 0 )
+           {
+             screen_status_printf("Connected to %s!", options->host);
+             connected = TRUE;
+           }
+         doupdate();
+       }
+
+      t = g_timer_elapsed(timer, NULL);
+    }
+
+  exit(EXIT_FAILURE);
+}
diff --git a/src/mpc.c b/src/mpc.c
new file mode 100644 (file)
index 0000000..0a80af4
--- /dev/null
+++ b/src/mpc.c
@@ -0,0 +1,359 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+
+#include "config.h"
+#include "support.h"
+#include "libmpdclient.h"
+#include "mpc.h"
+#include "options.h"
+
+#define MAX_SONG_LENGTH 1024
+
+#ifdef DEBUG
+#define D(x) x
+#else
+#define D(x)
+#endif
+
+int 
+mpc_close(mpd_client_t *c)
+{
+  if( c->connection )
+    mpd_closeConnection(c->connection);
+  if( c->cwd )
+    g_free( c->cwd );
+  
+  return 0;
+}
+
+mpd_client_t *
+mpc_connect(char *host, int port, char *password)
+{
+  mpd_Connection *connection;
+  mpd_client_t *c;
+
+  connection =  mpd_newConnection(host, port, 10);
+  if( connection==NULL )
+    {
+      fprintf(stderr, "mpd_newConnection to %s:%d failed!\n", host, port);
+      exit(EXIT_FAILURE);
+    }
+  
+  c = g_malloc(sizeof(mpd_client_t));
+  memset(c, 0, sizeof(mpd_client_t));
+  c->connection = connection;
+  c->cwd = g_strdup("");
+
+  if( password )
+    {
+      mpd_sendPasswordCommand(connection, password);
+      mpd_finishCommand(connection);
+    }
+
+  return c;
+}
+
+int
+mpc_reconnect(mpd_client_t *c, char *host, int port, char *password)
+{
+  mpd_Connection *connection;
+
+  connection =  mpd_newConnection(host, port, 10);
+  if( connection==NULL )
+    return -1;
+  if( connection->error )
+    {
+      mpd_closeConnection(connection);
+      return -1;
+    }
+  
+  c->connection = connection;
+
+  if( password )
+    {
+      mpd_sendPasswordCommand(connection, password);
+      mpd_finishCommand(connection);
+    }
+
+  return 0;
+}
+
+
+int
+mpc_error(mpd_client_t *c)
+{
+  if( c == NULL || c->connection == NULL )
+    return 1;
+  if( c->connection->error )
+    return c->connection->error;
+
+  return 0;
+}
+
+char *
+mpc_error_str(mpd_client_t *c)
+{
+  if( c == NULL || c->connection == NULL )
+    return "Not connected";
+
+  if( c->connection && c->connection->errorStr )
+    return c->connection->errorStr;
+
+  return NULL;
+}
+
+
+
+int
+mpc_free_playlist(mpd_client_t *c)
+{
+  GList *list;
+
+  if( c==NULL || c->playlist==NULL )
+    return -1;
+
+  list=g_list_first(c->playlist);
+
+  while( list!=NULL )
+    {
+      mpd_Song *song = (mpd_Song *) list->data;
+
+      mpd_freeSong(song);
+      list=list->next;
+    }
+  g_list_free(c->playlist);
+  c->playlist=NULL;
+  c->playlist_length=0;
+
+  c->song_id = -1;
+  c->song = NULL;
+
+  return 0;
+}
+
+int 
+mpc_update_playlist(mpd_client_t *c)
+{
+  mpd_InfoEntity *entity;
+
+  D(fprintf(stderr, "mpc_update_playlist() [%d]\n",  c->status->playlist));
+
+  if( mpc_error(c) )
+    return -1;
+
+  if( c->playlist )
+    mpc_free_playlist(c);
+
+  c->playlist_length=0;
+  mpd_sendPlaylistInfoCommand(c->connection,-1);
+  if( mpc_error(c) )
+    return -1;
+  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
+    {
+      if(entity->type==MPD_INFO_ENTITY_TYPE_SONG) 
+       {
+         mpd_Song *song = mpd_songDup(entity->info.song);
+
+         c->playlist = g_list_append(c->playlist, (gpointer) song);
+         c->playlist_length++;
+       }
+      mpd_freeInfoEntity(entity);
+    }
+  c->playlist_id = c->status->playlist;
+  c->playlist_updated = 1;
+  c->song_id = -1;
+  c->song = NULL;
+
+  mpc_filelist_set_selected(c);
+
+  return 0;
+}
+
+int
+mpc_playlist_get_song_index(mpd_client_t *c, char *filename)
+{
+  GList *list = c->playlist;
+  int i=0;
+
+  while( list )
+    {
+      mpd_Song *song = (mpd_Song *) list->data;
+      if( strcmp(song->file, filename ) == 0 ) 
+       return i;
+      list=list->next;
+      i++;
+    }
+  return -1;
+}
+
+mpd_Song *
+mpc_playlist_get_song(mpd_client_t *c, int n)
+{
+  return (mpd_Song *) g_list_nth_data(c->playlist, n);
+}
+
+
+char *
+mpc_get_song_name(mpd_Song *song)
+{
+  static char buf[MAX_SONG_LENGTH];
+  char *name;
+  
+  if( song->title )
+    {
+      if( song->artist )
+       {
+         snprintf(buf, MAX_SONG_LENGTH, "%s - %s", song->artist, song->title);
+         name = utf8_to_locale(buf);
+         strncpy(buf, name, MAX_SONG_LENGTH);
+         g_free(name);
+         return buf;
+       }
+      else
+       {
+         name = utf8_to_locale(song->title);
+         strncpy(buf, name, MAX_SONG_LENGTH);
+         g_free(name);
+         return buf;
+       }
+    }
+  name = utf8_to_locale(basename(song->file));
+  strncpy(buf, name, MAX_SONG_LENGTH);
+  g_free(name);
+  return buf;
+}
+
+int 
+mpc_update(mpd_client_t *c)
+{
+  if( mpc_error(c) )
+    return -1;
+
+  if( c->status )
+    {
+      mpd_freeStatus(c->status);
+    }
+
+  c->status = mpd_getStatus(c->connection);
+  if( mpc_error(c) )
+    return -1;
+  
+  if( c->playlist_id!=c->status->playlist )
+    mpc_update_playlist(c);
+  
+  if( !c->song || c->status->song != c->song_id )
+    {
+      c->song = mpc_playlist_get_song(c, c->status->song);
+      c->song_id = c->status->song;
+      c->song_updated = 1;
+    }
+
+  return 0;
+}
+
+
+
+
+
+
+int
+mpc_free_filelist(mpd_client_t *c)
+{
+  GList *list;
+
+  if( c==NULL || c->filelist==NULL )
+    return -1;
+
+  list=g_list_first(c->filelist);
+
+  while( list!=NULL )
+    {
+      filelist_entry_t *entry = list->data;
+
+      if( entry->entity )
+       mpd_freeInfoEntity(entry->entity);
+      g_free(entry);
+      list=list->next;
+    }
+  g_list_free(c->filelist);
+  c->filelist=NULL;
+  c->filelist_length=0;
+
+  return 0;
+}
+
+
+
+int 
+mpc_update_filelist(mpd_client_t *c)
+{
+  mpd_InfoEntity *entity;
+
+  if( mpc_error(c) )
+    return -1;
+
+  if( c->filelist )
+    mpc_free_filelist(c);
+
+  c->filelist_length=0;
+
+  //  mpd_sendListallCommand(conn,"");
+  mpd_sendLsInfoCommand(c->connection, c->cwd);
+
+  if( c->cwd && c->cwd[0] )
+    {
+      /* add a dummy entry for ./.. */
+      filelist_entry_t *entry = g_malloc(sizeof(filelist_entry_t));
+      memset(entry, 0, sizeof(filelist_entry_t));
+      entry->entity = NULL;
+      c->filelist = g_list_append(c->filelist, (gpointer) entry);
+      c->filelist_length++;
+    }
+
+  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
+    {
+      filelist_entry_t *entry = g_malloc(sizeof(filelist_entry_t));
+      
+      memset(entry, 0, sizeof(filelist_entry_t));
+      entry->entity = entity;
+      c->filelist = g_list_append(c->filelist, (gpointer) entry);
+      c->filelist_length++;
+    }
+  
+  c->filelist_updated = 1;
+
+  mpd_finishCommand(c->connection);
+
+  mpc_filelist_set_selected(c);
+
+  return 0;
+}
+
+int 
+mpc_filelist_set_selected(mpd_client_t *c)
+{
+  GList *list = c->filelist;
+
+  while( list )
+    {
+      filelist_entry_t *entry = list->data;
+      mpd_InfoEntity *entity = entry->entity ;      
+      
+      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song = entity->info.song;
+
+         if( mpc_playlist_get_song_index(c, song->file) >= 0 )
+           entry->selected = 1;
+         else
+           entry->selected = 0;
+       }
+
+      list=list->next;
+    }
+  return 0;
+}
diff --git a/src/mpc.h b/src/mpc.h
new file mode 100644 (file)
index 0000000..a09aeee
--- /dev/null
+++ b/src/mpc.h
@@ -0,0 +1,50 @@
+
+typedef struct
+{
+  char selected;
+  mpd_InfoEntity *entity;
+} filelist_entry_t;
+
+typedef struct
+{
+  mpd_Connection *connection;
+  mpd_Status     *status;
+
+  mpd_Song       *song;
+  int            song_id;
+  int            song_updated;
+
+  int            seek_song_id;
+  int            seek_target_time;
+
+  GList         *playlist;
+  int            playlist_length;
+  long long      playlist_id;
+  int            playlist_updated;
+
+  char           *cwd;
+  GList          *filelist;
+  int            filelist_length;
+  int            filelist_updated;
+
+} mpd_client_t;
+
+
+int mpc_close(mpd_client_t *c);
+
+mpd_client_t *mpc_connect(char *host, int port, char *passwd);
+int mpc_reconnect(mpd_client_t *c, char *host, int port, char *passwd);
+
+int mpc_update(mpd_client_t *c);
+int mpc_update_playlist(mpd_client_t *c);
+
+int mpc_update_filelist(mpd_client_t *c);
+int mpc_filelist_set_selected(mpd_client_t *c);
+int mpc_set_cwd(mpd_client_t *c, char *dir);
+
+mpd_Song *mpc_playlist_get_song(mpd_client_t *c, int n);
+char *mpc_get_song_name(mpd_Song *song);
+int mpc_playlist_get_song_index(mpd_client_t *c, char *filename);
+
+int   mpc_error(mpd_client_t *c);
+char *mpc_error_str(mpd_client_t *c);
diff --git a/src/options.c b/src/options.c
new file mode 100644 (file)
index 0000000..416727a
--- /dev/null
@@ -0,0 +1,185 @@
+/* 
+ * (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 <unistd.h>
+#include <string.h>
+#include <ncurses.h>
+#include <glib.h>
+#include <popt.h>
+
+#include "config.h"
+#include "options.h"
+#include "command.h"
+#include "support.h"
+
+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." },
+  { "colors",       'c', 0, 0, 'c', "Enable colors." },
+  { "no-colors",    'C', 0, 0, 'C', "Disable colors." },
+  { "exit",         'e', 0, 0, 'e', "Exit on connection errors." },
+  { "port",         'p', POPT_ARG_INT, &options.port, 0, 
+    "Connect to server on port [" DEFAULT_PORT_STR "].", "PORT" },
+  { "host",         'h', POPT_ARG_STRING, &mpd_host, 0, 
+    "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 }
+};
+
+static void
+usage(poptContext optCon, int exitcode, char *error, char *addl) 
+{
+  poptPrintUsage(optCon, stderr, 0);
+  if (error) 
+    fprintf(stderr, "%s: %s0", error, addl);
+  exit(exitcode);
+}
+
+options_t *
+options_parse( int argc, const char **argv)
+{
+  int c;
+  poptContext optCon;   /* context for parsing command-line options */
+
+  mpd_host = NULL;
+  mpd_password = NULL;
+  config_file = NULL;
+  key_file = NULL;
+  optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
+  while ((c = poptGetNextOpt(optCon)) >= 0) 
+    {
+      switch (c) 
+       {
+#ifdef DEBUG
+       case 'D':
+         options.debug = 1;
+         break;
+#endif
+       case 'c':
+         options.enable_colors = 1;
+         break;
+       case 'C':
+         options.enable_colors = 0;
+         break;
+       case 'V':
+         printf("Version " VERSION "\n");
+         exit(EXIT_SUCCESS);
+       case 'e':
+         options.reconnect = 0;
+         break;
+       default:
+         fprintf(stderr, "%s: %s\n",
+                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
+                 poptStrerror(c));
+         poptFreeContext(optCon);
+         exit(EXIT_FAILURE);
+         break;
+       }
+    }
+  if (c < -1) 
+    {
+      /* an error occurred during option processing */
+      fprintf(stderr, "%s: %s\n",
+             poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
+             poptStrerror(c));
+      poptFreeContext(optCon);
+      exit(EXIT_FAILURE);
+    }
+
+  if( mpd_host )
+    {
+      g_free(options.host);
+      options.host = mpd_host;
+    }
+  if( mpd_password )
+    {
+      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;
+}
+
+options_t *
+options_init( void )
+{
+  const char *value;
+  char *tmp;
+
+  memset(&options, 0, sizeof(options_t));
+
+  if( (value=g_getenv(MPD_HOST_ENV)) )
+    options.host = g_strdup(value);
+  else
+    options.host = g_strdup(DEFAULT_HOST);
+  if( (tmp=g_strstr_len(options.host, strlen(options.host), "@")) )
+    {
+      char *oldhost = options.host;
+      *tmp  = '\0';
+      options.password = locale_to_utf8(oldhost);
+      options.host = g_strdup(tmp+1);
+      g_free(oldhost);
+    }
+
+  if( (value=g_getenv(MPD_PORT_ENV)) )
+    options.port = atoi(value);
+  else
+    options.port = DEFAULT_PORT;
+
+  options.reconnect = 1;
+  options.find_wrap = 1;
+  options.wide_cursor = 1;
+
+  return &options;
+}
+
+
+options_t *
+options_get(void)
+{
+  return &options;
+}
diff --git a/src/options.h b/src/options.h
new file mode 100644 (file)
index 0000000..2a6681e
--- /dev/null
@@ -0,0 +1,28 @@
+
+#define MPD_HOST_ENV "MPD_HOST"
+#define MPD_PORT_ENV "MPD_PORT"
+
+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;
+
+} options_t;
+
+extern options_t options;
+
+options_t *options_init(void);
+options_t *options_parse(int argc, const char **argv);
+
+
+
diff --git a/src/screen.c b/src/screen.c
new file mode 100644 (file)
index 0000000..d846f3d
--- /dev/null
@@ -0,0 +1,869 @@
+/* 
+ * (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 <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+//#include <signal.h>
+#include <locale.h>
+#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"
+#include "screen_help.h"
+#include "screen_search.h"
+#include "screen_utils.h"
+
+#undef  ENABLE_STATUS_LINE_CLOCK
+#define ENABLE_SCROLLING
+
+#define DEFAULT_CROSSFADE_TIME 10
+
+#define STATUS_MESSAGE_TIMEOUT 3
+#define STATUS_LINE_MAX_SIZE   512
+
+#ifdef ENABLE_KEYDEF_SCREEN
+extern screen_functions_t *get_screen_keydef(void);
+#endif
+
+static screen_t *screen = NULL;
+static screen_functions_t *mode_fn = NULL;
+
+static void
+switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c)
+{
+  if( new_mode == screen->mode )
+    return;
+
+  /* close the old mode */
+  if( mode_fn && mode_fn->close )
+    mode_fn->close();
+
+  /* get functions for the new mode */
+  switch(new_mode)
+    {
+    case SCREEN_PLAY_WINDOW:
+      mode_fn = get_screen_playlist();
+      break;
+    case SCREEN_FILE_WINDOW:
+      mode_fn = get_screen_file();
+      break;
+    case SCREEN_HELP_WINDOW:
+      mode_fn = get_screen_help();
+      break;
+#ifdef ENABLE_KEYDEF_SCREEN
+    case SCREEN_KEYDEF_WINDOW:
+      mode_fn = get_screen_keydef();
+      break;
+#endif
+    default:
+      break;
+    }
+
+ screen->mode = new_mode;
+ screen->painted = 0;
+
+ /* open the new mode */
+ if( mode_fn && mode_fn->open )
+   mode_fn->open(screen, 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;
+
+  if(prev_header_len!=strlen(header))
+    {
+      prev_header_len = strlen(header);
+      clear = 1;
+    }
+
+  if(clear)
+    {
+      wmove(w, 0, 0);
+      wclrtoeol(w);
+    }
+
+  if(prev_volume!=c->status->volume || clear)
+    {
+      char buf[32];
+
+      if( header[0] )
+       {
+         colors_use(w, COLOR_TITLE_BOLD);
+         mvwaddstr(w, 0, 0, header);
+       }
+      else
+       {
+         colors_use(w, COLOR_TITLE_BOLD);
+         waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE));
+         colors_use(w, COLOR_TITLE);
+         waddstr(w, ":Help  ");
+         colors_use(w, COLOR_TITLE_BOLD);
+         waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE));
+         colors_use(w, COLOR_TITLE);
+         waddstr(w, ":Playlist  ");
+         colors_use(w, COLOR_TITLE_BOLD);
+         waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE));
+         colors_use(w, COLOR_TITLE);
+         waddstr(w, ":Browse");
+       }
+      if( c->status->volume==MPD_STATUS_NO_VOLUME )
+       {
+         snprintf(buf, 32, "Volume n/a ");
+       }
+      else
+       {
+         snprintf(buf, 32, " Volume %d%%", c->status->volume); 
+       }
+      colors_use(w, COLOR_TITLE);
+      mvwaddstr(w, 0, screen->top_window.cols-strlen(buf), buf);
+
+      flags[0] = 0;
+      if( c->status->repeat )
+       strcat(flags, "r");
+      if( c->status->random )
+       strcat(flags, "z");
+      if( c->status->crossfade )
+       strcat(flags, "x");
+      if( c->status->updatingDb )
+       strcat(flags, "U");
+      colors_use(w, COLOR_LINE);
+      mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols);
+      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);
+    }
+}
+
+static void
+paint_progress_window(mpd_client_t *c)
+{
+  double p;
+  int width;
+  int elapsedTime = c->status->elapsedTime;
+
+  if( c->status==NULL || IS_STOPPED(c->status->state) )
+    {
+      mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE, 
+              screen->progress_window.cols);
+      wnoutrefresh(screen->progress_window.w);
+      return;
+    }
+
+  if( c->seek_song_id == c->song_id )
+    elapsedTime = c->seek_target_time;
+
+  p = ((double) elapsedTime) / ((double) c->status->totalTime);
+  
+  width = (int) (p * (double) screen->progress_window.cols);
+  mvwhline(screen->progress_window.w, 
+          0, 0,
+          ACS_HLINE, 
+          screen->progress_window.cols);
+  whline(screen->progress_window.w, '=', width-1);
+  mvwaddch(screen->progress_window.w, 0, width-1, 'O');
+  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)
+{
+  WINDOW *w = screen->status_window.w;
+  mpd_Status *status = c->status;
+  mpd_Song *song   = c->song;
+  int elapsedTime = c->status->elapsedTime;
+  int x = 0;
+
+  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:
+      waddstr(w, "Stopped! ");
+      break;
+    case MPD_STATUS_STATE_PLAY:
+      waddstr(w, "Playing:");
+      break;
+    case MPD_STATUS_STATE_PAUSE:
+      waddstr(w, "[Paused]");
+      break;
+    default:
+      break;
+    }
+  x += 9;
+
+  /* create time string */
+  memset(screen->buf, 0, screen->buf_size);
+  if( IS_PLAYING(status->state) || IS_PAUSED(status->state) )
+    {
+      if( status->totalTime > 0 )
+       {
+         if( c->seek_song_id == c->song_id )
+           elapsedTime = c->seek_target_time;
+         snprintf(screen->buf, screen->buf_size, 
+                  " [%i:%02i/%i:%02i]",
+                  elapsedTime/60, elapsedTime%60,
+                  status->totalTime/60,   status->totalTime%60 );
+       }
+      else
+       {
+         snprintf(screen->buf, screen->buf_size,  " [%d kbps]", status->bitRate );
+       }
+    }
+  else
+    {
+      time_t timep;
+
+      time(&timep);
+      /* Note: setlocale(LC_TIME,"") should be used first */
+      //strftime(screen->buf, screen->buf_size, "%X ",  localtime(&timep));
+      strftime(screen->buf, screen->buf_size, " %k:%M",  localtime(&timep));
+    }
+
+  /* display song */
+  if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) &&  song )
+    {
+      char *songname = mpc_get_song_name(song);
+      int width = COLS-x-strlen(screen->buf);
+
+      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 )
+    {
+      time_t timep;
+
+      /* Note: setlocale(LC_TIME,"") should be used first */
+      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);
+}
+
+
+
+int
+screen_exit(void)
+{
+  endwin();
+  if( screen )
+    {
+      GList *list = g_list_first(screen->screen_list);
+
+      /* close and exit all screens (playlist,browse,help...) */
+      while( list )
+       {
+         screen_functions_t *mode_fn = list->data;
+
+         if( mode_fn && mode_fn->close )
+           mode_fn->close();
+         if( mode_fn && mode_fn->exit )
+           mode_fn->exit();
+         list->data = NULL;
+         list=list->next;
+       }
+      g_list_free(screen->screen_list);
+
+      g_free(screen->buf);
+      g_free(screen->findbuf);
+      g_free(screen);
+      screen = NULL;
+    }
+  return 0;
+}
+
+void
+screen_resize(void)
+{
+  GList *list;
+
+#ifdef DEBUG
+  fprintf(stderr, "Resize rows %d->%d, cols %d->%d\n",
+         screen->rows, LINES,
+         screen->cols, COLS);
+#endif
+      
+  if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
+    {
+      screen_exit();
+      fprintf(stderr, "Error: Screen to small!\n");
+      exit(EXIT_FAILURE);
+    }
+
+  resizeterm(LINES, COLS);
+
+  screen->cols = COLS;
+  screen->rows = LINES;
+
+  /* top window */
+  screen->top_window.cols = screen->cols;
+  wresize(screen->top_window.w, 2, screen->cols);
+
+  /* main window */
+  screen->main_window.cols = screen->cols;
+  screen->main_window.rows = screen->rows-4;
+  wresize(screen->main_window.w, screen->main_window.rows, screen->cols);
+  wclear(screen->main_window.w);
+
+  /* progress window */
+  screen->progress_window.cols = screen->cols;
+  wresize(screen->progress_window.w, 1, screen->cols);
+  mvwin(screen->progress_window.w, screen->rows-2, 0);
+
+  /* status window */
+  screen->status_window.cols = screen->cols;
+  wresize(screen->status_window.w, 1, screen->cols);
+  mvwin(screen->status_window.w, screen->rows-1, 0);
+
+  screen->buf_size = screen->cols;
+  g_free(screen->buf);
+  screen->buf = g_malloc(screen->cols);
+
+  list = g_list_first(screen->screen_list);
+  while( list )
+    {
+      screen_functions_t *mode_fn = list->data;
+
+      if( mode_fn && mode_fn->resize )
+       mode_fn->resize(screen->main_window.cols, screen->main_window.rows);
+
+      list=list->next;
+    }
+
+  /* ? - without this the cursor becomes visible with aterm & Eterm */
+  curs_set(1);
+  curs_set(0);     
+
+  screen->painted = 0;
+}
+
+void 
+screen_status_message(char *msg)
+{
+  WINDOW *w = screen->status_window.w;
+
+  wmove(w, 0, 0);
+  wclrtoeol(w);
+  colors_use(w, COLOR_STATUS_ALERT);
+  waddstr(w, msg);
+  wnoutrefresh(w);
+  screen->status_timestamp = time(NULL);
+}
+
+void 
+screen_status_printf(char *format, ...)
+{
+  char buffer[STATUS_LINE_MAX_SIZE];
+  va_list ap;
+  
+  va_start(ap,format);
+  vsnprintf(buffer,sizeof(buffer),format,ap);
+  va_end(ap);
+  screen_status_message(buffer);
+}
+
+int
+screen_init(void)
+{
+  GList *list;
+
+  /* initialize the curses library */
+  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 */  
+  cbreak();       
+  /* don't echo input */
+  noecho();    
+  /* set cursor invisible */     
+  curs_set(0);     
+  /* return from getch() without blocking */
+  //  nodelay(stdscr, TRUE); 
+  keypad(stdscr, TRUE);  
+  timeout(SCREEN_TIMEOUT);
+
+  if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
+    {
+      fprintf(stderr, "Error: Screen to small!\n");
+      exit(EXIT_FAILURE);
+    }
+
+  screen = g_malloc(sizeof(screen_t));
+  memset(screen, 0, sizeof(screen_t));
+  screen->mode = SCREEN_PLAY_WINDOW;
+  screen->cols = COLS;
+  screen->rows = LINES;
+  screen->buf  = g_malloc(screen->cols);
+  screen->buf_size = screen->cols;
+  screen->findbuf = NULL;
+  screen->painted = 0;
+  screen->start_timestamp = time(NULL);
+  screen->input_timestamp = time(NULL);
+  screen->last_cmd = CMD_NONE;
+
+  /* create top window */
+  screen->top_window.rows = 2;
+  screen->top_window.cols = screen->cols;
+  screen->top_window.w = newwin(screen->top_window.rows, 
+                                 screen->top_window.cols,
+                                 0, 0);
+  leaveok(screen->top_window.w, TRUE);
+  keypad(screen->top_window.w, TRUE);  
+
+  /* create main window */
+  screen->main_window.rows = screen->rows-4;
+  screen->main_window.cols = screen->cols;
+  screen->main_window.w = newwin(screen->main_window.rows, 
+                                screen->main_window.cols,
+                                2, 
+                                0);
+
+  //  leaveok(screen->main_window.w, TRUE); temporary disabled
+  keypad(screen->main_window.w, TRUE);  
+
+  /* create progress window */
+  screen->progress_window.rows = 1;
+  screen->progress_window.cols = screen->cols;
+  screen->progress_window.w = newwin(screen->progress_window.rows, 
+                                    screen->progress_window.cols,
+                                    screen->rows-2, 
+                                    0);
+  leaveok(screen->progress_window.w, TRUE);
+  
+  /* create status window */
+  screen->status_window.rows = 1;
+  screen->status_window.cols = screen->cols;
+  screen->status_window.w = newwin(screen->status_window.rows, 
+                                  screen->status_window.cols,
+                                  screen->rows-1, 
+                                  0);
+
+  leaveok(screen->status_window.w, FALSE);
+  keypad(screen->status_window.w, TRUE);  
+
+  if( options.enable_colors )
+    {
+      /* set background attributes */
+      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 */
+  screen->screen_list = NULL;
+  screen->screen_list = g_list_append(screen->screen_list, 
+                                     (gpointer) get_screen_playlist());
+  screen->screen_list = g_list_append(screen->screen_list, 
+                                     (gpointer) get_screen_file());
+  screen->screen_list = g_list_append(screen->screen_list, 
+                                     (gpointer) get_screen_help());
+#ifdef ENABLE_KEYDEF_SCREEN
+  screen->screen_list = g_list_append(screen->screen_list, 
+                                     (gpointer) get_screen_keydef());
+#endif
+
+  list = screen->screen_list;
+  while( list )
+    {
+      screen_functions_t *fn = list->data;
+      
+      if( fn && fn->init )
+       fn->init(screen->main_window.w, 
+                screen->main_window.cols,
+                screen->main_window.rows);
+      
+      list = list->next;
+    }
+
+  mode_fn = get_screen_playlist();
+
+  return 0;
+}
+
+void 
+screen_paint(mpd_client_t *c)
+{
+  /* paint the title/header window */
+  if( mode_fn && mode_fn->get_title )
+    paint_top_window(mode_fn->get_title(), c, 1);
+  else
+    paint_top_window("", c, 1);
+
+  /* paint the main window */
+  if( mode_fn && mode_fn->paint )
+    mode_fn->paint(screen, c);
+  
+  paint_progress_window(c);
+  paint_status_window(c);
+  screen->painted = 1;
+  wmove(screen->main_window.w, 0, 0);  
+  wnoutrefresh(screen->main_window.w);
+
+  /* tell curses to update */
+  doupdate();
+}
+
+void 
+screen_update(mpd_client_t *c)
+{
+  static int repeat = -1;
+  static int random = -1;
+  static int crossfade = -1;
+  static int dbupdate = -1;
+  static int welcome = 1;
+  list_window_t *lw = NULL;
+
+  if( !screen->painted )
+    return screen_paint(c);
+
+  /* print a message if mpd status has changed */
+  if( repeat<0 )
+    {
+      repeat = c->status->repeat;
+      random = c->status->random;
+      crossfade = c->status->crossfade;
+      dbupdate = c->status->updatingDb;
+    }
+  if( repeat != c->status->repeat )
+    screen_status_printf("Repeat is %s", 
+                        c->status->repeat  ? "On" : "Off");
+  if( random != c->status->random )
+    screen_status_printf("Random is %s", 
+                        c->status->random ? "On" : "Off");
+  if( crossfade != c->status->crossfade )
+    screen_status_printf("Crossfade %d seconds", c->status->crossfade);
+  if( dbupdate && dbupdate != c->status->updatingDb )
+    screen_status_printf("Database updated!");
+
+  repeat = c->status->repeat;
+  random = c->status->random;
+  crossfade = c->status->crossfade;
+  dbupdate = c->status->updatingDb;
+
+  /* update title/header window */
+  if( welcome && screen->last_cmd==CMD_NONE &&
+      time(NULL)-screen->start_timestamp <= SCREEN_WELCOME_TIME)
+    paint_top_window("", c, 0);
+  else if( mode_fn && mode_fn->get_title )
+    {
+      paint_top_window(mode_fn->get_title(), c, 0);
+      welcome = 0;
+    }
+  else
+    paint_top_window("", c, 0);
+
+  /* update the main window */
+  if( mode_fn && mode_fn->paint )
+    mode_fn->update(screen, c);
+
+  if( mode_fn && mode_fn->get_lw )
+    lw = mode_fn->get_lw();
+
+  /* update progress window */
+  paint_progress_window(c);
+
+  /* update status window */
+  paint_status_window(c);
+
+  /* move the cursor to the selected row in the main window */
+  if( lw )
+    wmove(screen->main_window.w, LW_ROW(lw), 0);   
+  else
+    wmove(screen->main_window.w, 0, 0);   
+  wnoutrefresh(screen->main_window.w);
+
+  /* tell curses to update */
+  doupdate();
+}
+
+void
+screen_idle(mpd_client_t *c)
+{
+  if( c->seek_song_id ==  c->song_id &&
+      (screen->last_cmd == CMD_SEEK_FORWARD || 
+       screen->last_cmd == CMD_SEEK_BACKWARD) )
+    {
+      mpd_sendSeekCommand(c->connection, 
+                         c->seek_song_id, 
+                         c->seek_target_time);
+      mpd_finishCommand(c->connection);
+    }
+
+  screen->last_cmd = CMD_NONE;
+  c->seek_song_id = -1;
+}
+
+void 
+screen_cmd(mpd_client_t *c, command_t cmd)
+{
+  int n;
+  screen_mode_t new_mode = screen->mode;
+
+  screen->input_timestamp = time(NULL);
+  screen->last_cmd = cmd;
+
+  if( mode_fn && mode_fn->cmd && mode_fn->cmd(screen, c, cmd) )
+    return;
+
+  switch(cmd)
+    {
+    case CMD_PLAY:
+      mpd_sendPlayCommand(c->connection, play_get_selected());
+      mpd_finishCommand(c->connection);
+      break;
+    case CMD_PAUSE:
+      mpd_sendPauseCommand(c->connection);
+      mpd_finishCommand(c->connection);
+      break;
+    case CMD_STOP:
+      mpd_sendStopCommand(c->connection);
+      mpd_finishCommand(c->connection);
+      break;
+    case CMD_SEEK_FORWARD:
+      if( !IS_STOPPED(c->status->state) )
+       {
+         if( c->seek_song_id != c->song_id )
+           {
+             c->seek_song_id = c->song_id;
+             c->seek_target_time = c->status->elapsedTime;
+           }
+         c->seek_target_time++;
+         if( c->seek_target_time < c->status->totalTime )
+           break;
+         c->seek_target_time=0;
+       }
+      /* fall through... */
+    case CMD_TRACK_NEXT:
+      if( !IS_STOPPED(c->status->state) )
+       {
+         mpd_sendNextCommand(c->connection);
+         mpd_finishCommand(c->connection);
+       }
+      break;
+    case CMD_SEEK_BACKWARD:
+      if( !IS_STOPPED(c->status->state) )
+       {
+         if( c->seek_song_id != c->song_id )
+           {
+             c->seek_song_id = c->song_id;
+             c->seek_target_time = c->status->elapsedTime;
+           }
+         c->seek_target_time--;
+         if( c->seek_target_time < 0 )
+           c->seek_target_time=0;
+       }
+      break;
+    case CMD_TRACK_PREVIOUS:
+      if( !IS_STOPPED(c->status->state) )
+       {
+         mpd_sendPrevCommand(c->connection);
+         mpd_finishCommand(c->connection);
+       }
+      break;   
+    case CMD_SHUFFLE:
+      mpd_sendShuffleCommand(c->connection);
+      mpd_finishCommand(c->connection);
+      screen_status_message("Shuffled playlist!");
+      break;
+    case CMD_CLEAR:
+      mpd_sendClearCommand(c->connection);
+      mpd_finishCommand(c->connection);
+      file_clear_highlights(c);
+      screen_status_message("Cleared playlist!");
+      break;
+    case CMD_REPEAT:
+      n = !c->status->repeat;
+      mpd_sendRepeatCommand(c->connection, n);
+      mpd_finishCommand(c->connection);
+      break;
+    case CMD_RANDOM:
+      n = !c->status->random;
+      mpd_sendRandomCommand(c->connection, n);
+      mpd_finishCommand(c->connection);
+      break;
+    case CMD_CROSSFADE:
+      if( c->status->crossfade )
+       n = 0;
+      else
+       n = DEFAULT_CROSSFADE_TIME;
+      mpd_sendCrossfadeCommand(c->connection, n);
+      mpd_finishCommand(c->connection);
+      break;
+    case CMD_VOLUME_UP:
+      if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
+       {
+         c->status->volume=c->status->volume+1;
+         mpd_sendSetvolCommand(c->connection, c->status->volume  );
+         mpd_finishCommand(c->connection);
+       }
+      break;
+    case CMD_VOLUME_DOWN:
+      if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
+       {
+         c->status->volume=c->status->volume-1;
+         mpd_sendSetvolCommand(c->connection, c->status->volume  );
+         mpd_finishCommand(c->connection);
+       }
+      break;
+    case CMD_TOGGLE_FIND_WRAP:
+      options.find_wrap = !options.find_wrap;
+      screen_status_printf("Find mode: %s", 
+                          options.find_wrap ? "Wrapped" : "Normal");
+      break;
+    case CMD_TOGGLE_AUTOCENTER:
+      options.auto_center = !options.auto_center;
+      screen_status_printf("Auto center mode: %s", 
+                          options.auto_center ? "On" : "Off");
+      break;
+    case CMD_SCREEN_PREVIOUS:
+      if( screen->mode > SCREEN_PLAY_WINDOW )
+       new_mode = screen->mode - 1;
+      else
+       new_mode = SCREEN_HELP_WINDOW-1;
+      switch_screen_mode(new_mode, c);
+      break;
+    case CMD_SCREEN_NEXT:
+      new_mode = screen->mode + 1;
+      if( new_mode >= SCREEN_HELP_WINDOW )
+       new_mode = SCREEN_PLAY_WINDOW;
+      switch_screen_mode(new_mode, c);
+      break;
+    case CMD_SCREEN_PLAY:
+      switch_screen_mode(SCREEN_PLAY_WINDOW, c);
+      break;
+    case CMD_SCREEN_FILE:
+      switch_screen_mode(SCREEN_FILE_WINDOW, c);
+      break;
+    case CMD_SCREEN_SEARCH:
+      switch_screen_mode(SCREEN_SEARCH_WINDOW, c);
+      break;
+    case CMD_SCREEN_HELP:
+      switch_screen_mode(SCREEN_HELP_WINDOW, c);
+      break;
+#ifdef ENABLE_KEYDEF_SCREEN 
+    case CMD_SCREEN_KEYDEF:
+      switch_screen_mode(SCREEN_KEYDEF_WINDOW, c);
+      break;
+#endif
+    case CMD_QUIT:
+      exit(EXIT_SUCCESS);
+    default:
+      break;
+    }
+
+}
+
+
+
diff --git a/src/screen.h b/src/screen.h
new file mode 100644 (file)
index 0000000..a7e6b72
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef SCREEN_H
+#define SCREEN_H
+#include <ncurses.h>
+#include "list_window.h"
+
+/* top window headers */
+#define TOP_HEADER_PREFIX "Music Player Client - "
+#define TOP_HEADER_PLAY   TOP_HEADER_PREFIX "Playlist"
+#define TOP_HEADER_FILE   TOP_HEADER_PREFIX "Browse"
+#define TOP_HEADER_HELP   TOP_HEADER_PREFIX "Help    "
+#define TOP_HEADER_SEARCH TOP_HEADER_PREFIX "Search  "
+
+/* minumum window size */
+#define SCREEN_MIN_COLS 14
+#define SCREEN_MIN_ROWS  5
+
+/* timeout for non blocking read [ms] */
+#define SCREEN_TIMEOUT 500
+
+/* welcome message time [s] */
+#define SCREEN_WELCOME_TIME 10
+
+#define IS_PLAYING(s) (s==MPD_STATUS_STATE_PLAY)
+#define IS_PAUSED(s) (s==MPD_STATUS_STATE_PAUSE)
+#define IS_STOPPED(s) (!(IS_PLAYING(s) | IS_PAUSED(s)))
+
+
+typedef enum
+{
+  SCREEN_PLAY_WINDOW = 0,
+  SCREEN_FILE_WINDOW,
+  SCREEN_HELP_WINDOW,
+  SCREEN_KEYDEF_WINDOW,
+  SCREEN_SEARCH_WINDOW
+
+} screen_mode_t;
+
+typedef struct
+{
+  WINDOW *w;
+  int rows, cols;
+
+} window_t;
+
+
+
+typedef struct
+{
+  window_t top_window;
+  window_t main_window;
+  window_t progress_window;
+  window_t status_window;
+
+  GList *screen_list;
+
+  time_t start_timestamp;
+  time_t status_timestamp;
+  time_t input_timestamp;
+  command_t last_cmd;
+
+  int cols, rows;
+
+  screen_mode_t mode;
+
+  char *buf;
+  size_t buf_size;
+
+  char *findbuf;
+
+  int painted;
+
+} screen_t;
+
+
+typedef void (*screen_init_fn_t)   (WINDOW *w, int cols, int rows);
+typedef void (*screen_exit_fn_t)   (void);
+typedef void (*screen_open_fn_t)   (screen_t *screen, mpd_client_t *c);
+typedef void (*screen_close_fn_t)  (void);
+typedef void (*screen_resize_fn_t)   (int cols, int rows);
+typedef void (*screen_paint_fn_t)  (screen_t *screen, mpd_client_t *c);
+typedef void (*screen_update_fn_t) (screen_t *screen, mpd_client_t *c);
+typedef int (*screen_cmd_fn_t) (screen_t *scr, mpd_client_t *c, command_t cmd);
+typedef char * (*screen_title_fn_t) (void);
+typedef list_window_t * (*screen_get_lw_fn_t) (void);
+
+typedef struct
+{
+  screen_init_fn_t   init;
+  screen_exit_fn_t   exit;
+  screen_open_fn_t   open;
+  screen_close_fn_t  close;
+  screen_resize_fn_t resize;
+  screen_paint_fn_t  paint;
+  screen_update_fn_t update;
+  screen_cmd_fn_t    cmd;
+  screen_title_fn_t  get_title;
+  screen_get_lw_fn_t get_lw;
+
+} screen_functions_t;
+
+
+int screen_init(void);
+int screen_exit(void);
+void screen_resize(void);
+void screen_status_message(char *msg);
+void screen_status_printf(char *format, ...);
+char *screen_error(void);
+void screen_paint(mpd_client_t *c);
+void screen_update(mpd_client_t *c);
+void screen_idle(mpd_client_t *c);
+void screen_cmd(mpd_client_t *c, command_t cmd);
+
+#endif
diff --git a/src/screen_file.c b/src/screen_file.c
new file mode 100644 (file)
index 0000000..d2b1f78
--- /dev/null
@@ -0,0 +1,503 @@
+/* 
+ * (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 <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+#include "support.h"
+#include "libmpdclient.h"
+#include "mpc.h"
+#include "command.h"
+#include "screen.h"
+#include "screen_utils.h"
+#include "screen_play.h"
+#include "screen_file.h"
+
+#define BUFSIZE 1024
+#define TITLESIZE 256
+
+#define USE_OLD_LAYOUT
+
+static list_window_t *lw;
+static mpd_client_t *mpc = NULL;
+
+static char *
+list_callback(int index, int *highlight, void *data)
+{
+  static char buf[BUFSIZE];
+  mpd_client_t *c = (mpd_client_t *) data;
+  filelist_entry_t *entry;
+  mpd_InfoEntity *entity;
+
+  *highlight = 0;
+  if( (entry=(filelist_entry_t *) g_list_nth_data(c->filelist, index))==NULL )
+    return NULL;
+
+  entity = entry->entity;
+  *highlight = entry->selected;
+
+  if( entity == NULL )
+    {
+#ifdef USE_OLD_LAYOUT
+      return "[..]";
+#else
+      return "d ..";
+#endif
+    }
+  if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY ) 
+    {
+      mpd_Directory *dir = entity->info.directory;
+      char *dirname = utf8_to_locale(basename(dir->path));
+
+#ifdef USE_OLD_LAYOUT
+      snprintf(buf, BUFSIZE, "[%s]", dirname);
+#else
+      snprintf(buf, BUFSIZE, "d %s", dirname);
+#endif
+      g_free(dirname);
+      return buf;
+    }
+  else if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+    {
+      mpd_Song *song = entity->info.song;
+
+#ifdef USE_OLD_LAYOUT      
+      return mpc_get_song_name(song);
+#else
+      snprintf(buf, BUFSIZE, "m %s", mpc_get_song_name(song));
+      return buf;
+#endif
+
+    }
+  else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
+    {
+      mpd_PlaylistFile *plf = entity->info.playlistFile;
+      char *filename = utf8_to_locale(basename(plf->path));
+
+#ifdef USE_OLD_LAYOUT      
+      snprintf(buf, BUFSIZE, "*%s*", filename);
+#else      
+      snprintf(buf, BUFSIZE, "p %s", filename);
+#endif
+      g_free(filename);
+      return buf;
+    }
+  return "Error: Unknow entry!";
+}
+
+static int
+change_directory(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
+{
+  mpd_InfoEntity *entity = entry->entity;
+
+  if( entity==NULL )
+    {
+      char *parent = g_path_get_dirname(c->cwd);
+
+      if( strcmp(parent,".") == 0 )
+       {
+         parent[0] = '\0';
+       }
+      if( c->cwd )
+       g_free(c->cwd);
+      c->cwd = parent;
+    }
+  else
+    if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
+      {
+       mpd_Directory *dir = entity->info.directory;
+       if( c->cwd )
+         g_free(c->cwd);
+       c->cwd = g_strdup(dir->path);      
+      }
+    else
+      return -1;
+  
+  mpc_update_filelist(c);
+  list_window_reset(lw);
+  return 0;
+}
+
+static int
+load_playlist(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
+{
+  mpd_InfoEntity *entity = entry->entity;
+  mpd_PlaylistFile *plf = entity->info.playlistFile;
+  char *filename = utf8_to_locale(basename(plf->path));
+
+  mpd_sendLoadCommand(c->connection, plf->path);
+  mpd_finishCommand(c->connection);
+
+  screen_status_printf("Loading playlist %s...", filename);
+  g_free(filename);
+  return 0;
+}
+
+static int 
+handle_delete(screen_t *screen, mpd_client_t *c)
+{
+  filelist_entry_t *entry;
+  mpd_InfoEntity *entity;
+  mpd_PlaylistFile *plf;
+  char *str, buf[BUFSIZE];
+  int key;
+
+  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
+  if( entry==NULL || entry->entity==NULL )
+    return -1;
+
+  entity = entry->entity;
+
+  if( entity->type!=MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
+    {
+      screen_status_printf("You can only delete playlists!");
+      beep();
+      return -1;
+    }
+
+  plf = entity->info.playlistFile;
+  str = utf8_to_locale(basename(plf->path));
+  snprintf(buf, BUFSIZE, "Delete playlist %s [y/n] ? ", str);
+  g_free(str);  
+  key = tolower(screen_getch(screen->status_window.w, buf));
+  if( key==KEY_RESIZE )
+    screen_resize();
+  if( key!='y' )
+    {
+      screen_status_printf("Aborted!");
+      return 0;
+    }
+
+  mpd_sendRmCommand(c->connection, plf->path);
+  mpd_finishCommand(c->connection);
+  if( mpc_error(c))
+    {
+      str = utf8_to_locale(mpc_error_str(c));
+      screen_status_printf("Error: %s", str);
+      g_free(str);
+      beep();
+      return -1;
+    }
+  screen_status_printf("Playlist deleted!");
+  mpc_update_filelist(c);
+  list_window_check_selected(lw, c->filelist_length);
+  return 0;
+}
+
+
+static int
+handle_play_cmd(screen_t *screen, mpd_client_t *c)
+{
+  filelist_entry_t *entry;
+  mpd_InfoEntity *entity;
+  
+  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
+  if( entry==NULL )
+    return -1;
+
+  entity = entry->entity;
+  if( entity==NULL || entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
+    return change_directory(screen, c, entry);
+  else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
+    return load_playlist(screen, c, entry);
+  return -1;
+}
+
+static int
+add_directory(mpd_client_t *c, char *dir)
+{
+  mpd_InfoEntity *entity;
+  GList *subdir_list = NULL;
+  GList *list = NULL;
+  char *dirname;
+
+  dirname = utf8_to_locale(dir);
+  screen_status_printf("Adding directory %s...\n", dirname);
+  doupdate(); 
+  g_free(dirname);
+  dirname = NULL;
+
+  mpd_sendLsInfoCommand(c->connection, dir);
+  mpd_sendCommandListBegin(c->connection);
+  while( (entity=mpd_getNextInfoEntity(c->connection)) )
+    {
+      if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song = entity->info.song;
+         mpd_sendAddCommand(c->connection, song->file);
+         mpd_freeInfoEntity(entity);
+       }
+      else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
+       {
+         subdir_list = g_list_append(subdir_list, (gpointer) entity); 
+       }
+      else
+       mpd_freeInfoEntity(entity);
+    }
+  mpd_sendCommandListEnd(c->connection);
+  mpd_finishCommand(c->connection);
+  
+  list = g_list_first(subdir_list);
+  while( list!=NULL )
+    {
+      mpd_Directory *dir;
+
+      entity = list->data;
+      dir = entity->info.directory;
+      add_directory(c, dir->path);
+      mpd_freeInfoEntity(entity);
+      list->data=NULL;
+      list=list->next;
+    }
+  g_list_free(subdir_list);
+  return 0;
+}
+
+static int
+handle_select(screen_t *screen, mpd_client_t *c)
+{
+  filelist_entry_t *entry;
+
+  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
+  if( entry==NULL || entry->entity==NULL)
+    return -1;
+
+  if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
+    {
+      mpd_Directory *dir = entry->entity->info.directory;
+      add_directory(c, dir->path);
+      return 0;
+    }
+
+  if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
+    return -1; 
+
+  entry->selected = !entry->selected;
+
+  if( entry->selected )
+    {
+      if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song = entry->entity->info.song;
+
+         playlist_add_song(c, song);
+
+         screen_status_printf("Adding \'%s\' to playlist\n", 
+                              mpc_get_song_name(song));
+       }
+    }
+  else
+    {
+      /* remove song from playlist */
+      if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song = entry->entity->info.song;
+
+         if( song )
+           {
+             int index = mpc_playlist_get_song_index(c, song->file);
+             
+             while( (index=mpc_playlist_get_song_index(c, song->file))>=0 )
+               playlist_delete_song(c, index);
+           }
+       }
+    }
+  return 0;
+}
+
+static void
+file_init(WINDOW *w, int cols, int rows)
+{
+  lw = list_window_init(w, cols, rows);
+}
+
+static void
+file_resize(int cols, int rows)
+{
+  lw->cols = cols;
+  lw->rows = rows;
+}
+
+static void
+file_exit(void)
+{
+  list_window_free(lw);
+}
+
+static void 
+file_open(screen_t *screen, mpd_client_t *c)
+{
+  if( c->filelist == NULL )
+    {
+      mpc_update_filelist(c);
+    }
+  mpc = c;
+}
+
+static void
+file_close(void)
+{
+}
+
+static char *
+file_title(void)
+{
+  static char buf[TITLESIZE];
+  char *tmp;
+
+  tmp = utf8_to_locale(basename(mpc->cwd));
+  snprintf(buf, TITLESIZE, 
+          TOP_HEADER_FILE ": %s                          ",
+          tmp
+          );
+  g_free(tmp);
+
+  return buf;
+}
+
+static void 
+file_paint(screen_t *screen, mpd_client_t *c)
+{
+  lw->clear = 1;
+  
+  list_window_paint(lw, list_callback, (void *) c);
+  wnoutrefresh(lw->w);
+}
+
+static void 
+file_update(screen_t *screen, mpd_client_t *c)
+{
+  if( c->filelist_updated )
+    {
+      file_paint(screen, c);
+      c->filelist_updated = 0;
+      return;
+    }
+  list_window_paint(lw, list_callback, (void *) c);
+  wnoutrefresh(lw->w);
+}
+
+
+static int 
+file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+{
+  switch(cmd)
+    {
+    case CMD_PLAY:
+      handle_play_cmd(screen, c);
+      return 1;
+    case CMD_SELECT:
+      if( handle_select(screen, c) == 0 )
+       {
+         /* continue and select next item... */
+         cmd = CMD_LIST_NEXT;
+       }
+      break;
+    case CMD_DELETE:
+      handle_delete(screen, c);
+      break;
+    case CMD_SCREEN_UPDATE:
+      mpc_update_filelist(c);
+      list_window_check_selected(lw, c->filelist_length);
+      screen_status_printf("Screen updated!");
+      return 1;
+    case CMD_LIST_FIND:
+    case CMD_LIST_RFIND:
+    case CMD_LIST_FIND_NEXT:
+    case CMD_LIST_RFIND_NEXT:
+      return screen_find(screen, c, 
+                        lw, c->filelist_length,
+                        cmd, list_callback);
+    default:
+      break;
+    }
+  return list_window_cmd(lw, c->filelist_length, cmd);
+}
+
+
+list_window_t *
+get_filelist_window()
+{
+  return lw;
+}
+
+
+void
+file_clear_highlights(mpd_client_t *c)
+{
+  GList *list = g_list_first(c->filelist);
+  
+  while( list )
+    {
+      filelist_entry_t *entry = list->data;
+
+      entry->selected = 0;
+      list = list->next;
+    }
+}
+
+void
+file_set_highlight(mpd_client_t *c, mpd_Song *song, int highlight)
+{
+  GList *list = g_list_first(c->filelist);
+
+  if( !song )
+    return;
+
+  while( list )
+    {
+      filelist_entry_t *entry = list->data;
+      mpd_InfoEntity *entity  = entry->entity;
+
+      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song2 = entity->info.song;
+
+         if( strcmp(song->file, song2->file) == 0 )
+           {
+             entry->selected = highlight;
+           }
+       }
+      list = list->next;
+    }
+}
+
+screen_functions_t *
+get_screen_file(void)
+{
+  static screen_functions_t functions;
+
+  memset(&functions, 0, sizeof(screen_functions_t));
+  functions.init   = file_init;
+  functions.exit   = file_exit;
+  functions.open   = file_open;
+  functions.close  = file_close;
+  functions.resize = file_resize;
+  functions.paint  = file_paint;
+  functions.update = file_update;
+  functions.cmd    = file_cmd;
+  functions.get_lw = get_filelist_window;
+  functions.get_title = file_title;
+
+  return &functions;
+}
+
diff --git a/src/screen_file.h b/src/screen_file.h
new file mode 100644 (file)
index 0000000..a7199a6
--- /dev/null
@@ -0,0 +1,7 @@
+
+void file_set_highlight(mpd_client_t *c, mpd_Song *song, int hightlight);
+void file_clear_highlights(mpd_client_t *c);
+
+list_window_t *get_filelist_window(void);
+
+screen_functions_t *get_screen_file(void);
diff --git a/src/screen_help.c b/src/screen_help.c
new file mode 100644 (file)
index 0000000..c55c963
--- /dev/null
@@ -0,0 +1,254 @@
+/* 
+ * (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 <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+#include "libmpdclient.h"
+#include "mpc.h"
+#include "command.h"
+#include "screen.h"
+#include "screen_utils.h"
+#include "screen_help.h"
+
+
+typedef struct
+{
+  signed char highlight;
+  command_t command;
+  char *text;
+} help_text_row_t;
+
+static help_text_row_t help_text[] = 
+{
+  { 1, CMD_NONE,  "          Movement keys  " },
+  { 0, CMD_NONE,  "        -----------------" },
+  { 0, CMD_LIST_PREVIOUS,  NULL },
+  { 0, CMD_LIST_NEXT,      NULL },
+  { 0, CMD_LIST_PREVIOUS_PAGE, NULL }, 
+  { 0, CMD_LIST_NEXT_PAGE, NULL },
+  { 0, CMD_LIST_FIRST,     NULL },
+  { 0, CMD_LIST_LAST,      NULL },
+  { 0, CMD_NONE,           NULL },
+  { 0, CMD_SCREEN_NEXT,    NULL },
+  { 0, CMD_SCREEN_HELP,    NULL },
+  { 0, CMD_SCREEN_PLAY,    NULL },
+  { 0, CMD_SCREEN_FILE,    NULL },
+#ifdef ENABLE_KEYDEF_SCREEN
+  { 0, CMD_SCREEN_KEYDEF,  NULL },
+#endif
+
+  { 0, CMD_NONE,           NULL },
+  { 0, CMD_NONE,           NULL },
+  { 1, CMD_NONE, "          General keys " },
+  { 0, CMD_NONE, "        ----------------" },
+  { 0, CMD_STOP,           NULL },
+  { 0, CMD_PAUSE,          NULL },
+  { 0, CMD_TRACK_NEXT,     NULL },
+  { 0, CMD_TRACK_PREVIOUS, NULL },
+  { 0, CMD_SEEK_FORWARD,   NULL },
+  { 0, CMD_SEEK_BACKWARD,  NULL },
+  { 0, CMD_VOLUME_DOWN,    NULL },
+  { 0, CMD_VOLUME_UP,      NULL },
+  { 0, CMD_NONE,           NULL },
+  { 0, CMD_SHUFFLE,        NULL },
+  { 0, CMD_REPEAT,         NULL },
+  { 0, CMD_RANDOM,         NULL },
+  { 0, CMD_CROSSFADE,      NULL },
+  { 0, CMD_NONE,           NULL },
+  { 0, CMD_QUIT,           NULL },
+
+  { 0, CMD_NONE,           NULL },
+  { 0, CMD_NONE,           NULL },
+  { 1, CMD_NONE, "          Keys - Playlist screen " },
+  { 0, CMD_NONE, "        --------------------------" },
+  { 0, CMD_PLAY,           "Play" },
+  { 0, CMD_DELETE,         NULL },
+  { 0, CMD_CLEAR,          NULL },
+  { 0, CMD_LIST_MOVE_UP,   "Move song up" },
+  { 0, CMD_LIST_MOVE_DOWN, "Move song down" },
+  { 0, CMD_SAVE_PLAYLIST,  NULL },
+  { 0, CMD_SCREEN_UPDATE,  "Center" },
+  { 0, CMD_TOGGLE_AUTOCENTER, NULL },
+
+  { 0, CMD_NONE,           NULL },
+  { 0, CMD_NONE,           NULL },
+  { 1, CMD_NONE, "          Keys - Browse screen " },
+  { 0, CMD_NONE, "        ------------------------" },
+  { 0, CMD_PLAY,            "Enter directory" },
+  { 0, CMD_SELECT,          NULL },
+  { 0, CMD_DELETE,          NULL },
+  { 0, CMD_SCREEN_UPDATE,   NULL },
+
+  { 0, CMD_NONE,           NULL },
+  { 0, CMD_NONE,           NULL },
+  { 1, CMD_NONE, "               Find keys " },
+  { 0, CMD_NONE, "              -------------" },
+  { 0, CMD_LIST_FIND,      NULL },
+  { 0, CMD_LIST_RFIND,     NULL },
+  { 0, CMD_LIST_FIND_NEXT, NULL },
+  { 0, CMD_LIST_RFIND_NEXT,  NULL },
+  { 0, CMD_TOGGLE_FIND_WRAP, NULL },
+
+  { 0, CMD_NONE, NULL },
+  { 0, CMD_NONE, NULL },
+  { 1, CMD_NONE, "          ncmpc build information " },
+  { 0, CMD_NONE, "         ---------------------------" },
+  { 0, CMD_NONE, "             Version : " VERSION },
+  { 0, CMD_NONE, "  Configuration dirs : ~/.ncmpc, " SYSCONFDIR "/" PACKAGE },
+#ifdef ENABLE_KEYDEF_SCREEN
+  { 0, CMD_NONE, "          Key Editor : yes" },
+#else
+  { 0, CMD_NONE, "          Key Editor : no" },
+#endif
+
+  { 0, CMD_NONE, NULL },
+  {-1, CMD_NONE, NULL }
+};
+
+static int help_text_rows = -1;
+static list_window_t *lw = NULL;
+
+
+static char *
+list_callback(int index, int *highlight, void *data)
+{
+  static char buf[256];
+
+  if( help_text_rows<0 )
+    {
+      help_text_rows = 0;
+      while( help_text[help_text_rows].highlight != -1 )
+       help_text_rows++;
+    }
+
+  *highlight = 0;
+  if( index<help_text_rows )
+    {
+      *highlight = help_text[index].highlight > 0;
+      if( help_text[index].command == CMD_NONE )
+       {
+         if( help_text[index].text )
+           return help_text[index].text;
+         else
+           return "  ";
+       }
+      if( help_text[index].text )
+       snprintf(buf, 256, 
+                "%20s : %s   ", 
+                get_key_names(help_text[index].command, TRUE),
+                help_text[index].text);
+      else
+       snprintf(buf, 256, 
+                "%20s : %s   ", 
+                get_key_names(help_text[index].command, TRUE),
+                get_key_description(help_text[index].command));
+      return buf;
+    }
+
+  return NULL;
+}
+
+static void
+help_init(WINDOW *w, int cols, int rows)
+{
+  lw = list_window_init(w, cols, rows);
+}
+
+static void
+help_resize(int cols, int rows)
+{
+  lw->cols = cols;
+  lw->rows = rows;
+}
+
+static void
+help_exit(void)
+{
+  list_window_free(lw);
+}
+
+
+static char *
+help_title(void)
+{
+  return (TOP_HEADER_PREFIX "Help");
+}
+
+static void 
+help_paint(screen_t *screen, mpd_client_t *c)
+{
+  lw->clear = 1;
+  list_window_paint(lw, list_callback, NULL);
+  wrefresh(lw->w);
+}
+
+static void 
+help_update(screen_t *screen, mpd_client_t *c)
+{  
+  if( lw->repaint )
+    {
+      list_window_paint(lw, list_callback, NULL);
+      wrefresh(lw->w);
+      lw->repaint = 0;
+    }
+}
+
+
+static int 
+help_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+{
+  int retval;
+
+  retval = list_window_cmd(lw, help_text_rows, cmd);
+  if( !retval )
+    return screen_find(screen, c, 
+                      lw,  help_text_rows,
+                      cmd, list_callback);
+
+  return retval;
+}
+
+static list_window_t *
+help_lw(void)
+{
+  return lw;
+}
+
+screen_functions_t *
+get_screen_help(void)
+{
+  static screen_functions_t functions;
+
+  memset(&functions, 0, sizeof(screen_functions_t));
+  functions.init   = help_init;
+  functions.exit   = help_exit;
+  functions.open   = NULL;
+  functions.close  = NULL;
+  functions.resize = help_resize;
+  functions.paint  = help_paint;
+  functions.update = help_update;
+  functions.cmd    = help_cmd;
+  functions.get_lw = help_lw;
+  functions.get_title = help_title;
+
+  return &functions;
+}
diff --git a/src/screen_help.h b/src/screen_help.h
new file mode 100644 (file)
index 0000000..ba2c57c
--- /dev/null
@@ -0,0 +1,2 @@
+
+screen_functions_t *get_screen_help(void);
diff --git a/src/screen_keydef.c b/src/screen_keydef.c
new file mode 100644 (file)
index 0000000..4bda6ea
--- /dev/null
@@ -0,0 +1,393 @@
+/* 
+ * (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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+
+#ifdef  ENABLE_KEYDEF_SCREEN
+#include "libmpdclient.h"
+#include "options.h"
+#include "conf.h"
+#include "mpc.h"
+#include "command.h"
+#include "screen.h"
+#include "screen_utils.h"
+
+#define STATIC_ITEMS      0
+#define STATIC_SUB_ITEMS  1
+#define BUFSIZE 256
+
+#define LIST_ITEM_APPLY()   (command_list_length)
+#define LIST_ITEM_SAVE()    (LIST_ITEM_APPLY()+1)
+#define LIST_LENGTH()       (LIST_ITEM_SAVE()+1)
+
+#define LIST_ITEM_SAVE_LABEL  "===> Apply & Save key bindings  "
+#define LIST_ITEM_APPLY_LABEL "===> Apply key bindings "
+
+
+static list_window_t *lw = NULL;
+static int command_list_length = 0;
+static command_definition_t *cmds = NULL;
+
+static int subcmd = -1;
+static int subcmd_length = 0;
+static int subcmd_addpos = 0;
+
+static int
+keybindings_changed(void)
+{
+  command_definition_t *orginal_cmds = get_command_definitions();
+  size_t size = command_list_length*sizeof(command_definition_t);
+  
+  return memcmp(orginal_cmds, cmds, size);
+}
+
+static void
+apply_keys(void)
+{
+  if( keybindings_changed() )
+    {
+      command_definition_t *orginal_cmds = get_command_definitions();
+      size_t size = command_list_length*sizeof(command_definition_t);
+
+      memcpy(orginal_cmds, cmds, size);
+      screen_status_printf("You have new key bindings!");
+    }
+  else
+    screen_status_printf("Keybindings unchanged.");
+}
+
+static int
+save_keys(void)
+{
+  FILE *f;
+  char *filename;
+
+  if( check_user_conf_dir() )
+    {
+      screen_status_printf("Error: Unable to create direcory ~/.ncmpc - %s", 
+                          strerror(errno));
+      beep();
+      return -1;
+    }
+
+  filename = get_user_key_binding_filename();
+
+  if( (f=fopen(filename,"w")) == NULL )
+    {
+      screen_status_printf("Error: %s - %s", filename, strerror(errno));
+      beep();
+      g_free(filename);
+      return -1;
+    }
+  if( write_key_bindings(f) )
+    screen_status_printf("Error: %s - %s", filename, strerror(errno));
+  else
+    screen_status_printf("Wrote %s", filename);
+  
+  g_free(filename);
+  return fclose(f);
+}
+
+static void
+check_subcmd_length(void)
+{
+  subcmd_length = 0;
+  while( subcmd_length<MAX_COMMAND_KEYS && cmds[subcmd].keys[subcmd_length]>0 )
+   subcmd_length ++;
+
+  if( subcmd_length<MAX_COMMAND_KEYS )
+    {
+      subcmd_addpos = subcmd_length;
+      subcmd_length++;
+    }
+  else
+    subcmd_addpos = 0;
+  subcmd_length += STATIC_SUB_ITEMS;
+}
+
+static void
+delete_key(int cmd_index, int key_index)
+{
+  int i = key_index+1;
+
+  screen_status_printf("Delete...");
+  while( i<MAX_COMMAND_KEYS && cmds[cmd_index].keys[i] )
+    cmds[cmd_index].keys[key_index++] = cmds[cmd_index].keys[i++];
+  cmds[cmd_index].keys[key_index] = 0;
+
+  check_subcmd_length();
+  lw->clear = 1;
+  lw->repaint = 1;
+}
+
+static void
+assign_new_key(WINDOW *w, int cmd_index, int key_index)
+{
+  int key;
+  char buf[BUFSIZE];
+  command_t cmd;
+
+  snprintf(buf, BUFSIZE, "Enter new key for %s: ", cmds[cmd_index].name);
+  key = screen_getch(w, buf);
+  if( key==KEY_RESIZE )
+    screen_resize();
+  if( key==ERR )
+    {
+      screen_status_printf("Aborted!");
+      return;
+    }
+  cmd = find_key_command(key, cmds);
+  if( cmd!=CMD_NONE && cmd!= cmds[cmd_index].command )
+    {
+      screen_status_printf("Error: key %s is already used for %s", 
+                          key2str(key),
+                          get_key_command_name(cmd));
+      beep();
+      return;
+    }
+  cmds[cmd_index].keys[key_index] = key;
+  screen_status_printf("Assigned %s to %s", key2str(key),cmds[cmd_index].name);
+  check_subcmd_length();
+  lw->repaint = 1;
+}
+
+static char *
+list_callback(int index, int *highlight, void *data)
+{
+  static char buf[BUFSIZE];
+
+  if( subcmd <0 )
+    {
+      if( index<command_list_length )
+       return cmds[index].name;
+      else if( index==LIST_ITEM_APPLY() )
+       return LIST_ITEM_APPLY_LABEL;
+      else if( index==LIST_ITEM_SAVE() )
+       return LIST_ITEM_SAVE_LABEL;
+    }
+  else
+  {
+    if( index== 0 )
+      return "[..]";
+    index--;
+    if( index<MAX_COMMAND_KEYS && cmds[subcmd].keys[index]>0 )
+      {
+       snprintf(buf, 
+                BUFSIZE, "%d. %-20s   (%d) ", 
+                index+1, 
+                key2str(cmds[subcmd].keys[index]),
+                cmds[subcmd].keys[index]);
+       return buf;
+      } 
+    else if ( index==subcmd_addpos )
+      {
+       snprintf(buf, BUFSIZE, "%d. Add new key ", index+1 );
+       return buf;
+      }
+  }
+  
+  return NULL;
+}
+
+static void 
+keydef_init(WINDOW *w, int cols, int rows)
+{
+  lw = list_window_init(w, cols, rows);
+}
+
+static void
+keydef_resize(int cols, int rows)
+{
+  lw->cols = cols;
+  lw->rows = rows;
+}
+
+static void 
+keydef_exit(void)
+{
+  list_window_free(lw);
+  if( cmds )
+    g_free(cmds);
+  cmds = NULL;
+  lw = NULL;
+}
+
+static void 
+keydef_open(screen_t *screen, mpd_client_t *c)
+{
+  if( cmds == NULL )
+    {
+      command_definition_t *current_cmds = get_command_definitions();
+      size_t cmds_size;
+
+      command_list_length = 0;
+      while( current_cmds[command_list_length].name )
+       command_list_length++;
+
+      cmds_size = (command_list_length+1)*sizeof(command_definition_t);
+      cmds = g_malloc0(cmds_size);
+      memcpy(cmds, current_cmds, cmds_size);
+      command_list_length += STATIC_ITEMS;
+      screen_status_printf("Welcome to the key editor!");
+    }
+
+  subcmd = -1;
+  list_window_check_selected(lw, LIST_LENGTH());  
+}
+
+static void 
+keydef_close(void)
+{
+  if( cmds && !keybindings_changed() )
+    {
+      g_free(cmds);
+      cmds = NULL;
+    }
+  else
+    screen_status_printf("Note: Did you forget to \'Apply\' your changes?");
+}
+
+static char *
+keydef_title(void)
+{
+  static char buf[BUFSIZE];
+
+  if( subcmd<0 )
+    return (TOP_HEADER_PREFIX "Edit key bindings");
+  
+  snprintf(buf, BUFSIZE, 
+          TOP_HEADER_PREFIX "Edit keys for %s", 
+          cmds[subcmd].name);
+  return buf;
+}
+
+static void 
+keydef_paint(screen_t *screen, mpd_client_t *c)
+{
+  lw->clear = 1;
+  list_window_paint(lw, list_callback, NULL);
+  wrefresh(lw->w);
+}
+
+static void 
+keydef_update(screen_t *screen, mpd_client_t *c)
+{  
+  if( lw->repaint )
+    {
+      list_window_paint(lw, list_callback, NULL);
+      wrefresh(lw->w);
+      lw->repaint = 0;
+    }
+}
+
+static int 
+keydef_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+{
+  int length = LIST_LENGTH();
+
+  if( subcmd>=0 )
+    length = subcmd_length;
+
+  switch(cmd)
+    {
+    case CMD_PLAY:
+      if( subcmd<0 )
+       {
+         if( lw->selected == LIST_ITEM_APPLY() )
+           apply_keys();
+         else if( lw->selected == LIST_ITEM_SAVE() )
+           {
+             apply_keys();
+             save_keys();
+           }
+         else
+           {
+             subcmd = lw->selected;
+             lw->selected=0;
+             check_subcmd_length();
+           }
+       }
+      else
+       {
+         if( lw->selected == 0 ) /* up */
+           {
+             lw->selected = subcmd;
+             subcmd = -1;
+           }
+         else
+           assign_new_key(screen->status_window.w, 
+                          subcmd,
+                          lw->selected-STATIC_SUB_ITEMS);
+       }
+      lw->repaint = 1;
+      lw->clear = 1;
+      return 1;
+    case CMD_DELETE:
+      if( subcmd>=0 && lw->selected-STATIC_SUB_ITEMS>=0 )
+       delete_key(subcmd, lw->selected-STATIC_SUB_ITEMS);
+      return 1;
+      break;
+    case CMD_LIST_FIND:
+    case CMD_LIST_RFIND:
+    case CMD_LIST_FIND_NEXT:
+    case CMD_LIST_RFIND_NEXT:
+      return screen_find(screen, c, 
+                        lw,  length,
+                        cmd, list_callback);
+
+    default:
+      break;
+    }
+
+  return list_window_cmd(lw, length, cmd);
+}
+
+static list_window_t *
+keydef_lw(void)
+{
+  return lw;
+}
+
+screen_functions_t *
+get_screen_keydef(void)
+{
+  static screen_functions_t functions;
+
+  memset(&functions, 0, sizeof(screen_functions_t));
+  functions.init   = keydef_init;
+  functions.exit   = keydef_exit;
+  functions.open   = keydef_open;
+  functions.close  = keydef_close;
+  functions.resize = keydef_resize;
+  functions.paint  = keydef_paint;
+  functions.update = keydef_update;
+  functions.cmd    = keydef_cmd;
+  functions.get_lw = keydef_lw;
+  functions.get_title = keydef_title;
+
+  return &functions;
+}
+
+
+#endif
diff --git a/src/screen_play.c b/src/screen_play.c
new file mode 100644 (file)
index 0000000..cdec4f7
--- /dev/null
@@ -0,0 +1,390 @@
+/* 
+ * (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 <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+#include "options.h"
+#include "support.h"
+#include "libmpdclient.h"
+#include "mpc.h"
+#include "command.h"
+#include "screen.h"
+#include "screen_utils.h"
+#include "screen_file.h"
+#include "screen_play.h"
+
+#ifdef DEBUG
+#define D(x) x
+#else
+#define D(x)
+#endif
+
+#define BUFSIZE 256
+
+static list_window_t *lw = NULL;
+
+static char *
+list_callback(int index, int *highlight, void *data)
+{
+  mpd_client_t *c = (mpd_client_t *) data;
+  mpd_Song *song;
+
+  *highlight = 0;
+  if( (song=mpc_playlist_get_song(c, index)) == NULL )
+    {
+      return NULL;
+    }
+
+  if( index==c->song_id && !IS_STOPPED(c->status->state) )
+    {
+      *highlight = 1;
+    }
+
+  return mpc_get_song_name(song);
+}
+
+static int
+center_playing_item(screen_t *screen, mpd_client_t *c)
+{
+  int length = c->playlist_length;
+  int offset = lw->selected-lw->start;
+  
+  if( !lw || length<lw->rows || IS_STOPPED(c->status->state) )
+    return 0;
+
+  /* try to center the song that are playing */
+  lw->start = c->song_id-(lw->rows/2);
+  if( lw->start+lw->rows > length )
+    lw->start = length-lw->rows;
+  if( lw->start<0 )
+    lw->start=0;
+
+  /* make sure the cursor is in the window */
+  lw->selected = lw->start+offset;
+  list_window_check_selected(lw, length);
+
+  lw->clear = 1;
+  lw->repaint = 1;
+
+  return 0;
+}
+
+static int
+handle_save_playlist(screen_t *screen, mpd_client_t *c)
+{
+  char *filename, *filename_utf8;
+
+  filename=screen_getstr(screen->status_window.w, "Save playlist as: ");
+  filename=trim(filename);
+  if( filename==NULL || filename[0]=='\0' )
+    return -1;
+  /* convert filename to utf-8 */
+  filename_utf8 = locale_to_utf8(filename);
+  /* send save command to mpd */
+  mpd_sendSaveCommand(c->connection, filename_utf8);
+  mpd_finishCommand(c->connection);
+  g_free(filename_utf8);
+  /* handle errors */
+  if( mpc_error(c))
+    {
+      if(  mpc_error_str(c) )
+       {
+         char *str = utf8_to_locale(mpc_error_str(c));
+         screen_status_message(str);
+         g_free(str);
+       }
+      else
+       screen_status_printf("Error: Unable to save playlist as %s", filename);
+      mpd_clearError(c->connection);
+      beep();
+      return -1;
+    }
+  /* success */
+  screen_status_printf("Saved %s", filename);
+  g_free(filename);
+  /* update the file list if it has been initalized */
+  if( c->filelist )
+    {
+      list_window_t *file_lw = get_filelist_window();
+
+      mpc_update_filelist(c);
+      list_window_check_selected(file_lw, c->filelist_length);
+    }
+  return 0;
+}
+
+static void
+play_init(WINDOW *w, int cols, int rows)
+{
+  lw = list_window_init(w, cols, rows);
+}
+
+static void
+play_resize(int cols, int rows)
+{
+  lw->cols = cols;
+  lw->rows = rows;
+}
+
+
+static void
+play_exit(void)
+{
+  list_window_free(lw);
+}
+
+static char *
+play_title(void)
+{
+  return (TOP_HEADER_PREFIX "Playlist");
+}
+
+static void
+play_paint(screen_t *screen, mpd_client_t *c)
+{ 
+  lw->clear = 1;
+
+  list_window_paint(lw, list_callback, (void *) c);
+  wnoutrefresh(lw->w);
+}
+
+static void
+play_update(screen_t *screen, mpd_client_t *c)
+{
+  if( options.auto_center )
+    {
+      static int prev_song_id = 0;
+      
+      if( prev_song_id != c->song_id ) 
+       {
+         center_playing_item(screen, c);
+         prev_song_id = c->song_id;
+       }
+    }
+
+  if( c->playlist_updated )
+    {
+      if( lw->selected >= c->playlist_length )
+       lw->selected = c->playlist_length-1;
+      if( lw->start    >= c->playlist_length )
+       list_window_reset(lw);
+
+      play_paint(screen, c);
+      c->playlist_updated = 0;
+    }
+  else if( lw->repaint || 1)
+    {
+      list_window_paint(lw, list_callback, (void *) c);
+      wnoutrefresh(lw->w);
+      lw->repaint = 0;
+    }
+}
+
+static int
+play_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+{
+  switch(cmd)
+    {
+    case CMD_DELETE:
+      playlist_delete_song(c, lw->selected);
+      return 1;
+    case CMD_SAVE_PLAYLIST:
+      handle_save_playlist(screen, c);
+      return 1;
+    case CMD_SCREEN_UPDATE:
+      center_playing_item(screen, c);
+      return 1;
+    case CMD_LIST_MOVE_UP:
+      playlist_move_song(c, lw->selected, lw->selected-1);
+      break;
+    case CMD_LIST_MOVE_DOWN:
+      playlist_move_song(c, lw->selected, lw->selected+1);
+      break;
+    case CMD_LIST_FIND:
+    case CMD_LIST_RFIND:
+    case CMD_LIST_FIND_NEXT:
+    case CMD_LIST_RFIND_NEXT:
+      return screen_find(screen, c, 
+                        lw, c->playlist_length,
+                        cmd, list_callback);
+    default:
+      break;
+    }
+  return list_window_cmd(lw, c->playlist_length, cmd) ;
+}
+
+
+
+static list_window_t *
+play_lw(void)
+{
+  return lw;
+}
+
+int 
+play_get_selected(void)
+{
+  return lw->selected;
+}
+
+int
+playlist_move_song(mpd_client_t *c, int old_index, int new_index)
+{
+  int index1, index2;
+  GList *item1, *item2;
+  gpointer data1, data2;
+
+  if( old_index==new_index || new_index<0 || new_index>=c->playlist_length )
+    return -1;
+
+  /* send the move command to mpd */
+  mpd_sendMoveCommand(c->connection, old_index, new_index);
+  mpd_finishCommand(c->connection);
+  if( mpc_error(c) )
+    return -1;
+
+  index1 = MIN(old_index, new_index);
+  index2 = MAX(old_index, new_index);
+  item1 = g_list_nth(c->playlist, index1);
+  item2 = g_list_nth(c->playlist, index2);
+  data1 = item1->data;
+  data2 = item2->data;
+
+  /* move the second item */
+  D(fprintf(stderr, "move second item [%d->%d]...\n", index2, index1));
+  c->playlist = g_list_remove(c->playlist, data2);
+  c->playlist = g_list_insert_before(c->playlist, item1, data2);
+
+  /* move the first item */
+  if( index2-index1 >1 )
+    {
+      D(fprintf(stderr, "move first item [%d->%d]...\n", index1, index2));
+      item2 = g_list_nth(c->playlist, index2);
+      c->playlist = g_list_remove(c->playlist, data1);
+      c->playlist = g_list_insert_before(c->playlist, item2, data1);
+    }
+  
+  /* increment the playlist id, so we dont retrives a new playlist */
+  c->playlist_id++;
+
+  /* make shure the playlist is repainted */
+  lw->clear = 1;
+  lw->repaint = 1;
+
+  /* keep song selected */
+  lw->selected = new_index;
+
+  return 0;
+}
+
+int
+playlist_add_song(mpd_client_t *c, mpd_Song *song)
+{
+  if( !song || !song->file )
+    return -1;
+
+  /* send the add command to mpd */
+  mpd_sendAddCommand(c->connection, song->file);
+  mpd_finishCommand(c->connection);
+  if( mpc_error(c) )
+    return -1;
+
+  /* add the song to playlist */
+  c->playlist = g_list_append(c->playlist, (gpointer) mpd_songDup(song));
+  c->playlist_length++;
+
+  /* increment the playlist id, so we dont retrives a new playlist */
+  c->playlist_id++;
+
+  /* make shure the playlist is repainted */
+  lw->clear = 1;
+  lw->repaint = 1;
+
+  /* set selected highlight in the browse screen */
+  file_set_highlight(c, song, 1);
+
+  return 0;
+}
+
+int
+playlist_delete_song(mpd_client_t *c, int index)
+{
+  mpd_Song *song = mpc_playlist_get_song(c, index);
+
+  if( !song )
+    return -1;
+
+  /* send the delete command to mpd */
+  mpd_sendDeleteCommand(c->connection, index);
+  mpd_finishCommand(c->connection); 
+  if( mpc_error(c) )
+    return -1;
+
+  /* print a status message */
+  screen_status_printf("Removed \'%s\' from playlist!",
+                      mpc_get_song_name(song));
+  /* clear selected highlight in the browse screen */
+  file_set_highlight(c, song, 0);
+
+  /* increment the playlist id, so we dont retrives a new playlist */
+  c->playlist_id++;
+
+  /* remove references to the song */
+  if( c->song == song )
+    {
+      c->song = NULL;
+      c->song_id = -1;
+    }
+  
+  /* remove the song from the playlist */
+  c->playlist = g_list_remove(c->playlist, (gpointer) song);
+  c->playlist_length = g_list_length(c->playlist);
+  mpd_freeSong(song);
+
+  /* make shure the playlist is repainted */
+  lw->clear = 1;
+  lw->repaint = 1;
+  list_window_check_selected(lw, c->playlist_length);
+
+  return 0;
+}
+
+
+screen_functions_t *
+get_screen_playlist(void)
+{
+  static screen_functions_t functions;
+
+  memset(&functions, 0, sizeof(screen_functions_t));
+  functions.init   = play_init;
+  functions.exit   = play_exit;
+  functions.open   = NULL;
+  functions.close  = NULL;
+  functions.resize = play_resize;
+  functions.paint  = play_paint;
+  functions.update = play_update;
+  functions.cmd    = play_cmd;
+  functions.get_lw = play_lw;
+  functions.get_title = play_title;
+
+  return &functions;
+}
diff --git a/src/screen_play.h b/src/screen_play.h
new file mode 100644 (file)
index 0000000..2155ae5
--- /dev/null
@@ -0,0 +1,9 @@
+
+int play_get_selected(void);
+
+int playlist_move_song(mpd_client_t *c, int old_index, int new_index);
+int playlist_add_song(mpd_client_t *c, mpd_Song *song);
+int playlist_delete_song(mpd_client_t *c, int index);
+
+screen_functions_t *get_screen_playlist(void);
+
diff --git a/src/screen_search.c b/src/screen_search.c
new file mode 100644 (file)
index 0000000..6b6719e
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "libmpdclient.h"
+#include "config.h"
+#include "mpc.h"
+#include "command.h"
+#include "screen.h"
+#include "screen_search.h"
+
diff --git a/src/screen_search.h b/src/screen_search.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/screen_utils.c b/src/screen_utils.c
new file mode 100644 (file)
index 0000000..f8dfa4c
--- /dev/null
@@ -0,0 +1,153 @@
+/* 
+ * (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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "config.h"
+#include "libmpdclient.h"
+#include "mpc.h"
+#include "support.h"
+#include "command.h"
+#include "options.h"
+#include "list_window.h"
+#include "colors.h"
+#include "screen.h"
+
+#define FIND_PROMPT  "Find: "
+#define RFIND_PROMPT "Find backward: "
+
+int
+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);
+  wmove(w, 0, prompt_len);
+  
+  echo();
+  curs_set(1);
+  timeout(-1);
+
+  key = wgetch(w);
+  if( key==KEY_RESIZE )
+    screen_resize();
+
+  noecho();
+  curs_set(0);
+  timeout(SCREEN_TIMEOUT);
+
+  return key;
+}
+
+
+char *
+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);
+  wmove(w, 0, prompt_len);
+  
+  echo();
+  curs_set(1);
+
+  if( wgetnstr(w, buf, 256) == OK )
+    line = g_strdup(buf);
+
+  noecho();
+  curs_set(0);
+
+  return line;
+}
+
+
+/* query user for a string and find it in a list window */
+int 
+screen_find(screen_t *screen,
+           mpd_client_t *c,
+           list_window_t *lw, 
+           int rows,
+           command_t findcmd,
+           list_window_callback_fn_t callback_fn)
+{
+  int reversed = 0;
+  int retval   = 0;
+  char *prompt = FIND_PROMPT;
+
+  if( findcmd==CMD_LIST_RFIND ||findcmd==CMD_LIST_RFIND_NEXT ) 
+    {
+      prompt = RFIND_PROMPT;
+      reversed = 1;
+    }
+
+  switch(findcmd)
+    {
+    case CMD_LIST_FIND:
+    case CMD_LIST_RFIND:
+      if( screen->findbuf )
+       {
+         g_free(screen->findbuf);
+         screen->findbuf=NULL;
+       }
+      /* continue... */
+    case CMD_LIST_FIND_NEXT:
+    case CMD_LIST_RFIND_NEXT:
+      if( !screen->findbuf )
+       screen->findbuf=screen_getstr(screen->status_window.w, prompt);
+      if( reversed )
+       retval = list_window_rfind(lw, 
+                                  callback_fn,
+                                  c, 
+                                  screen->findbuf,
+                                  options.find_wrap,
+                                  rows);
+      else
+       retval = list_window_find(lw,
+                                 callback_fn,
+                                 c,
+                                 screen->findbuf,
+                                 options.find_wrap);
+      if( retval == 0 )
+       {
+         lw->repaint  = 1;
+       }
+      else
+       {
+         screen_status_printf("Unable to find \'%s\'", screen->findbuf);
+         beep();
+       }
+      return 1;
+    default:
+      break;
+    }
+  return 0;
+}
+
+
diff --git a/src/screen_utils.h b/src/screen_utils.h
new file mode 100644 (file)
index 0000000..30c58bf
--- /dev/null
@@ -0,0 +1,18 @@
+
+/* read a characher from the status window */
+int screen_getch(WINDOW *w, char *prompt);
+
+/* read a string from the status window */
+char *screen_getstr(WINDOW *w, char *prompt);
+
+/* query user for a string and find it in a list window */
+int screen_find(screen_t *screen,
+               mpd_client_t *c,
+               list_window_t *lw, 
+               int rows,
+               command_t findcmd,
+               list_window_callback_fn_t callback_fn);
+
+
+int my_waddstr(WINDOW *, const char *, int);
+int my_mvwaddstr(WINDOW *, int, int, const char *, int);
diff --git a/src/support.c b/src/support.c
new file mode 100644 (file)
index 0000000..d292e84
--- /dev/null
@@ -0,0 +1,216 @@
+/* 
+ * (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 <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include "config.h"
+#include "support.h"
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef DEBUG
+#define D(x) x
+#else 
+#define D(x)
+#endif
+
+#define BUFSIZE 1024
+
+extern void screen_status_printf(char *format, ...);
+
+static const char *charset = NULL;
+static const char *locale = NULL;
+static gboolean noconvert = TRUE;
+
+char *
+trim(char *str)
+{
+  char *end;
+
+  if( str==NULL )
+    return NULL;
+
+  while( IS_WHITESPACE(*str) )
+    str++;
+
+  end=str+strlen(str)-1;
+  while( end>str && IS_WHITESPACE(*end) )
+    {
+      *end = '\0';
+      end--;
+    }
+  return str;
+}
+
+char *
+remove_trailing_slash(char *path)
+{
+  int len;
+
+  if( path==NULL )
+    return NULL;
+
+  len=strlen(path);
+  if( len>1 && path[len-1] == '/' )
+    path[len-1] = '\0';
+
+  return path;
+}
+
+char *
+lowerstr(char *str)
+{
+  size_t i;
+  size_t len = strlen(str);
+
+  if( str==NULL )
+    return NULL;
+
+  i=0;
+  while(i<len && str[i])
+    {
+      str[i] = tolower(str[i]);
+      i++;
+    }
+  return str;
+}
+
+
+#ifndef HAVE_BASENAME
+char *
+basename(char *path)
+{
+  char *end;
+
+  path = remove_trailing_slash(path);
+  end = path + strlen(path);
+
+  while( end>path && *end!='/' )
+    end--;
+
+  if( *end=='/' && end!=path )
+    return end+1;
+
+  return path;
+}
+#endif /* HAVE_BASENAME */
+
+
+#ifndef HAVE_STRCASESTR
+char *
+strcasestr(const char *haystack, const char *needle)
+{
+  return strstr(lowerstr(haystack), lowerstr(needle));
+}
+#endif /* HAVE_STRCASESTR */
+
+
+int
+charset_init(void)
+{
+#ifdef HAVE_LOCALE_H
+  /* get current locale */
+  if( (locale=setlocale(LC_CTYPE,"")) == NULL )
+    {
+      g_printerr("setlocale() - failed!\n");
+      return -1;
+    }
+#endif
+
+  /* get charset */
+  noconvert = g_get_charset(&charset);
+
+#ifdef DEBUG
+  g_printerr("charset: %s [%d]\n", charset, noconvert);
+  fflush(stderr);
+#endif
+  
+  return 0;
+}
+
+int
+charset_close(void)
+{
+  return 0;
+}
+
+char *
+utf8_to_locale(char *utf8str)
+{
+  gchar *str;
+  gsize rb, wb;
+  GError *error;
+
+  if( noconvert )
+    return g_strdup(utf8str);
+
+  rb = 0; /* bytes read */
+  wb = 0; /* bytes written */
+  error = NULL;
+  str=g_locale_from_utf8(utf8str, 
+                        strlen(utf8str),
+                        &wb, &rb,
+                        &error);
+  if( error )
+    {
+      screen_status_printf("Error: Unable to convert characters to %s",
+                          charset);
+      D(g_printerr("utf8_to_locale(): %s\n", error->message));
+      g_error_free(error);
+      return g_strdup(utf8str);
+    }
+  
+  return str;
+}
+
+char *
+locale_to_utf8(char *localestr)
+{
+  gchar *str;
+  gsize rb, wb;
+  GError *error;
+
+  if( noconvert )
+    return g_strdup(localestr);
+
+  rb = 0; /* bytes read */
+  wb = 0; /* bytes written */
+  error = NULL;
+  str=g_locale_to_utf8(localestr, 
+                      strlen(localestr), 
+                      &wb, &rb,
+                      &error);
+  if( error )
+    {
+      screen_status_printf("Error: Unable to convert characters to UTF-8");
+      D(g_printerr("locale_to_utf8: %s\n", error->message));
+      g_error_free(error);
+      return g_strdup(localestr);
+    }
+
+  return str;
+}
+
+
+
diff --git a/src/support.h b/src/support.h
new file mode 100644 (file)
index 0000000..1f3aca1
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef SUPPORT_H
+#define SUPPORT_H
+
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#ifndef HAVE_BASENAME
+char *basename(char *path);
+#endif
+
+#define IS_WHITESPACE(c) (c==' ' || c=='\t' || c=='\r' || c=='\n')
+
+char *trim(char *str);
+char *remove_trailing_slash(char *path);
+char *lowerstr(char *str);
+char *strcasestr(const char *haystack, const char *needle);
+
+int charset_init(void);
+int charset_close(void);
+char *utf8_to_locale(char *str);
+char *locale_to_utf8(char *str);
+
+#endif 
diff --git a/support.c b/support.c
deleted file mode 100644 (file)
index d292e84..0000000
--- a/support.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* 
- * (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 <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#include "config.h"
-#include "support.h"
-
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#ifdef DEBUG
-#define D(x) x
-#else 
-#define D(x)
-#endif
-
-#define BUFSIZE 1024
-
-extern void screen_status_printf(char *format, ...);
-
-static const char *charset = NULL;
-static const char *locale = NULL;
-static gboolean noconvert = TRUE;
-
-char *
-trim(char *str)
-{
-  char *end;
-
-  if( str==NULL )
-    return NULL;
-
-  while( IS_WHITESPACE(*str) )
-    str++;
-
-  end=str+strlen(str)-1;
-  while( end>str && IS_WHITESPACE(*end) )
-    {
-      *end = '\0';
-      end--;
-    }
-  return str;
-}
-
-char *
-remove_trailing_slash(char *path)
-{
-  int len;
-
-  if( path==NULL )
-    return NULL;
-
-  len=strlen(path);
-  if( len>1 && path[len-1] == '/' )
-    path[len-1] = '\0';
-
-  return path;
-}
-
-char *
-lowerstr(char *str)
-{
-  size_t i;
-  size_t len = strlen(str);
-
-  if( str==NULL )
-    return NULL;
-
-  i=0;
-  while(i<len && str[i])
-    {
-      str[i] = tolower(str[i]);
-      i++;
-    }
-  return str;
-}
-
-
-#ifndef HAVE_BASENAME
-char *
-basename(char *path)
-{
-  char *end;
-
-  path = remove_trailing_slash(path);
-  end = path + strlen(path);
-
-  while( end>path && *end!='/' )
-    end--;
-
-  if( *end=='/' && end!=path )
-    return end+1;
-
-  return path;
-}
-#endif /* HAVE_BASENAME */
-
-
-#ifndef HAVE_STRCASESTR
-char *
-strcasestr(const char *haystack, const char *needle)
-{
-  return strstr(lowerstr(haystack), lowerstr(needle));
-}
-#endif /* HAVE_STRCASESTR */
-
-
-int
-charset_init(void)
-{
-#ifdef HAVE_LOCALE_H
-  /* get current locale */
-  if( (locale=setlocale(LC_CTYPE,"")) == NULL )
-    {
-      g_printerr("setlocale() - failed!\n");
-      return -1;
-    }
-#endif
-
-  /* get charset */
-  noconvert = g_get_charset(&charset);
-
-#ifdef DEBUG
-  g_printerr("charset: %s [%d]\n", charset, noconvert);
-  fflush(stderr);
-#endif
-  
-  return 0;
-}
-
-int
-charset_close(void)
-{
-  return 0;
-}
-
-char *
-utf8_to_locale(char *utf8str)
-{
-  gchar *str;
-  gsize rb, wb;
-  GError *error;
-
-  if( noconvert )
-    return g_strdup(utf8str);
-
-  rb = 0; /* bytes read */
-  wb = 0; /* bytes written */
-  error = NULL;
-  str=g_locale_from_utf8(utf8str, 
-                        strlen(utf8str),
-                        &wb, &rb,
-                        &error);
-  if( error )
-    {
-      screen_status_printf("Error: Unable to convert characters to %s",
-                          charset);
-      D(g_printerr("utf8_to_locale(): %s\n", error->message));
-      g_error_free(error);
-      return g_strdup(utf8str);
-    }
-  
-  return str;
-}
-
-char *
-locale_to_utf8(char *localestr)
-{
-  gchar *str;
-  gsize rb, wb;
-  GError *error;
-
-  if( noconvert )
-    return g_strdup(localestr);
-
-  rb = 0; /* bytes read */
-  wb = 0; /* bytes written */
-  error = NULL;
-  str=g_locale_to_utf8(localestr, 
-                      strlen(localestr), 
-                      &wb, &rb,
-                      &error);
-  if( error )
-    {
-      screen_status_printf("Error: Unable to convert characters to UTF-8");
-      D(g_printerr("locale_to_utf8: %s\n", error->message));
-      g_error_free(error);
-      return g_strdup(localestr);
-    }
-
-  return str;
-}
-
-
-
diff --git a/support.h b/support.h
deleted file mode 100644 (file)
index 1f3aca1..0000000
--- a/support.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef SUPPORT_H
-#define SUPPORT_H
-
-#ifdef HAVE_LIBGEN_H
-#include <libgen.h>
-#endif
-
-#ifndef HAVE_BASENAME
-char *basename(char *path);
-#endif
-
-#define IS_WHITESPACE(c) (c==' ' || c=='\t' || c=='\r' || c=='\n')
-
-char *trim(char *str);
-char *remove_trailing_slash(char *path);
-char *lowerstr(char *str);
-char *strcasestr(const char *haystack, const char *needle);
-
-int charset_init(void);
-int charset_close(void);
-char *utf8_to_locale(char *str);
-char *locale_to_utf8(char *str);
-
-#endif