Add mood methods {artist, title, album, comment}_matches.
[paraslash.git] / gui.c
diff --git a/gui.c b/gui.c
index fc2cd9a145d25ac5ff0197fa132a87f5492661f7..394b69fe5466efe19fb532a2cf43e18381409d8e 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -6,14 +6,16 @@
 
 /** \file gui.c Curses-based interface for paraslash. */
 
+#include <regex.h>
 #include <signal.h>
 #include <sys/types.h>
 #include <dirent.h>
+#include <curses.h>
+
 #include "gui.cmdline.h"
 #include "para.h"
 #include "gui.h"
 #include "string.h"
-#include <curses.h>
 #include "ringbuffer.h"
 #include "fd.h"
 #include "error.h"
@@ -203,24 +205,6 @@ static int para_open_audiod_pipe(char *cmd)
        return ret;
 }
 
-static int read_audiod_pipe(int fd, line_handler_t *line_handler)
-{
-       static char buf[4096];
-       const ssize_t bufsize = sizeof(buf) - 1;
-       static ssize_t loaded;
-       ssize_t ret;
-
-       if (loaded >= bufsize)
-               loaded = 0;
-       ret = read(fd, buf + loaded, bufsize - loaded);
-       if (ret > 0) {
-               loaded += ret;
-               buf[loaded] = '\0';
-               loaded = for_each_line(buf, loaded, line_handler, NULL);
-       }
-       return ret;
-}
-
 static int find_cmd_byname(char *name)
 {
        int i;
@@ -312,20 +296,23 @@ static void add_spaces(WINDOW* win, unsigned int num)
  * print aligned string to curses window. This function always prints
  * exactly len chars.
  */
-static int align_str(WINDOW* win, const char *string, unsigned int len,
+static int align_str(WINDOW* win, char *str, unsigned int len,
                unsigned int align)
 {
-       int num; /* of spaces */
-       char *str;
+       int i, num; /* of spaces */
 
-       if (!win || !string)
+       if (!win || !str)
                return -1;
-       num = len - strlen(string);
-       str = para_strdup(string);
+       num = len - strlen(str);
        if (num < 0) {
                str[len] = '\0';
                num = 0;
        }
+       /* replace newlines by spaces */
+       for (i = 0; i < len; i++) {
+               if (str[i] == '\n')
+                       str[i] = ' ';
+       }
        if (align == LEFT) {
                waddstr(win, str);
                add_spaces(win, num);
@@ -337,7 +324,6 @@ static int align_str(WINDOW* win, const char *string, unsigned int len,
                waddstr(win, str[0]? str: "");
                add_spaces(win, num - num / 2);
        }
-       free(str);
        return 1;
 }
 
@@ -360,10 +346,14 @@ __printf_2_3 static void print_in_bar(int color, const char *fmt,...)
  */
 static void print_status_bar(void)
 {
+       char *tmp;
+
        if (!curses_active)
                return;
+       tmp = para_strdup(STANDARD_STATUS_BAR);
        wmove(sb.win, 0, 0);
-       align_str(sb.win, STANDARD_STATUS_BAR, sb.cols, CENTER);
+       align_str(sb.win, tmp, sb.cols, CENTER);
+       free(tmp);
        wrefresh(sb.win);
 }
 
@@ -687,6 +677,63 @@ static void print_stat_item(int i)
        wrefresh(top.win);
 }
 
+static int update_item(int item_num, char *buf)
+{
+       char **c = stat_content + item_num;
+
+       free(*c);
+       if (buf && buf[0])
+               goto dup;
+       switch (item_num) {
+       case SI_ARTIST:
+               *c = para_strdup("(artist tag not set)");
+               goto print;
+       case SI_TITLE:
+               *c = para_strdup("(title tag not set)");
+               goto print;
+       case SI_YEAR:
+               *c = para_strdup("????");
+               goto print;
+       case SI_ALBUM:
+               *c = para_strdup("(album tag not set)");
+               goto print;
+       case SI_COMMENT:
+               *c = para_strdup("(comment tag not set)");
+               goto print;
+       }
+dup:
+       *c = para_strdup(buf);
+print:
+       print_stat_item(item_num);
+       return 1;
+}
+
+static int read_audiod_pipe(int fd)
+{
+       static char *buf;
+       static int bufsize, loaded;
+       int ret;
+
+       if (loaded >= bufsize) {
+               if (bufsize > 1000 * 1000) {
+                       loaded = 0;
+                       return 0;
+               }
+               bufsize += bufsize + 1000;
+               buf = para_realloc(buf, bufsize);
+       }
+       assert(loaded < bufsize);
+       ret = read(fd, buf + loaded, bufsize - loaded);
+       if (ret <= 0)
+               return ret;
+       loaded += ret;
+       ret = for_each_stat_item(buf, loaded, update_item);
+       if (ret < 0)
+               return ret;
+       loaded = ret;
+       return 1;
+}
+
 static void print_all_items(void)
 {
        int i;
@@ -769,26 +816,6 @@ reap_next_child:
        goto reap_next_child;
 }
 
-/*
- * print status line if line starts with known command.
- */
-static int check_stat_line(char *line, __a_unused void *data)
-{
-       int i;
-
-//     PARA_INFO_LOG("%s: checking: %s\n", __func__, line);
-       i = stat_line_valid(line);
-       if (i >= 0) {
-               line += strlen(status_item_list[i]) + 1;
-               if (*line == ' ')
-                       line++;
-               free(stat_content[i]);
-               stat_content[i] = para_strdup(line);
-               print_stat_item(i);
-       }
-       return 1;
-}
-
 /*
  * This sucker modifies its first argument. *handler and *arg are
  * pointers to 0-terminated strings (inside line). Crap.
@@ -859,8 +886,8 @@ static void handle_signal(int sig)
                return;
        case SIGINT:
                PARA_WARNING_LOG("caught SIGINT, reset");
-               /* Nothing to do. SIGINT killed our child, para_client stat.
-                * This get noticed by do_select which resets everything
+               /* Nothing to do. SIGINT killed our child which gets noticed
+                * by do_select and resets everything.
                 */
                return;
        case SIGUSR1:
@@ -946,7 +973,7 @@ repeat:
                }
        }
        if (audiod_pipe >= 0 && FD_ISSET(audiod_pipe, &rfds))
-               if (read_audiod_pipe(audiod_pipe, check_stat_line) <= 0) {
+               if (read_audiod_pipe(audiod_pipe) <= 0) {
                        close(audiod_pipe);
                        audiod_pipe = -1;
                        clear_all_items();