]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 'maint'
authorAndre Noll <maan@systemlinux.org>
Sun, 6 Jun 2010 16:35:47 +0000 (18:35 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 6 Jun 2010 16:35:47 +0000 (18:35 +0200)
Conflicts:
gui.c

1  2 
gui.c

diff --combined gui.c
index fa1538b0d63f3db2ca8be6497aa0ce797d3a89a1,01cca6e6d08eac45ae3fbf63b999d453e40e14e3..dbe0a19ced1d1da9e2d588a2498dfc931371ee65
--- 1/gui.c
--- 2/gui.c
+++ b/gui.c
@@@ -1,21 -1,19 +1,21 @@@
  /*
 - * Copyright (C) 1998-2009 Andre Noll <maan@systemlinux.org>
 + * Copyright (C) 1998-2010 Andre Noll <maan@systemlinux.org>
   *
   * Licensed under the GPL v2. For licencing details see COPYING.
   */
  
  /** \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"
@@@ -45,7 -43,7 +45,7 @@@ struct rb_entry 
        size_t len;
        int color;
  };
 -struct ringbuffer *bot_win_rb;
 +static struct ringbuffer *bot_win_rb;
  #define NUM_LINES(len) (1 + (len) / bot.cols)
  
  static unsigned scroll_position;
@@@ -54,7 -52,7 +54,7 @@@ static int cmd_died, curses_active
  static pid_t cmd_pid;
  
  static int command_pipe = -1;
 -static int audiod_pipe = -1;
 +static int stat_pipe = -1;
  static struct gui_args_info conf;
  
  enum {GETCH_MODE, COMMAND_MODE, EXTERNAL_MODE};
@@@ -91,8 -89,8 +91,8 @@@ struct stat_item 
  
  static struct gui_theme theme;
  
 -int _argc;
 -char **_argv;
 +static int _argc;
 +static char **_argv;
  
  static void com_help(void);
  static void com_reread_conf(void);
@@@ -110,7 -108,7 +110,7 @@@ static void com_scroll_down(void)
  static void com_page_up(void);
  static void com_page_down(void);
  
 -struct gui_command command_list[] = {
 +static struct gui_command command_list[] = {
        {
                .key = "?",
                .name = "help",
        }
  };
  
 -static int para_open_audiod_pipe(char *cmd)
 -{
 -      int fds[3] = {0, 1, 0};
 -      pid_t pid;
 -      int ret = para_exec_cmdline_pid(&pid, cmd, fds);
 -      if (ret < 0)
 -              return ret;
 -      ret = mark_fd_nonblocking(fds[1]);
 -      if (ret > 0)
 -              return fds[1];
 -      close(fds[1]);
 -      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;
@@@ -282,23 -312,20 +282,23 @@@ static void add_spaces(WINDOW* win, uns
   * 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 && str[i]; i++) {
 +              if (str[i] == '\n')
 +                      str[i] = ' ';
 +      }
        if (align == LEFT) {
                waddstr(win, str);
                add_spaces(win, num);
                waddstr(win, str[0]? str: "");
                add_spaces(win, num - num / 2);
        }
 -      free(str);
        return 1;
  }
  
@@@ -332,14 -360,10 +332,14 @@@ __printf_2_3 static void print_in_bar(i
   */
  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);
  }
  
@@@ -663,70 -687,6 +663,70 @@@ 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_stat_pipe(fd_set *rfds)
 +{
 +      static char *buf;
 +      static int bufsize, loaded;
 +      int ret, ret2;
 +      size_t sz;
 +
 +      if (stat_pipe < 0)
 +              return 0;
 +      if (loaded >= bufsize) {
 +              if (bufsize > 1000 * 1000) {
 +                      loaded = 0;
 +                      return 0;
 +              }
 +              bufsize += bufsize + 1000;
 +              buf = para_realloc(buf, bufsize);
 +      }
 +      assert(loaded < bufsize);
 +      ret = read_nonblock(stat_pipe, buf + loaded, bufsize - loaded,
 +              rfds, &sz);
 +      loaded += sz;
 +      ret2 = for_each_stat_item(buf, loaded, update_item);
 +      if (ret < 0 || ret2 < 0) {
 +              loaded = 0;
 +              return ret2 < 0? ret2 : ret;
 +      }
 +      sz = ret2; /* what is left */
 +      if (sz > 0 && sz < loaded)
 +              memmove(buf, buf + loaded - sz, sz);
 +      loaded = sz;
 +      return 1;
 +}
 +
  static void print_all_items(void)
  {
        int i;
@@@ -809,6 -769,26 +809,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.
@@@ -879,8 -859,8 +879,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:
        }
  }
  
 -static int open_audiod_pipe(void)
 +static int open_stat_pipe(void)
  {
        static int init = 1;
 +      int ret, fds[3] = {0, 1, 0};
 +      pid_t pid;
  
        if (init)
                init = 0;
        else
-               sleep(1);
+               /*
+                * Sleep a bit to avoid a busy loop. As the call to sleep() may
+                * be interrupted by SIGCHLD, we simply wait until the call
+                * succeeds.
+                */
+               while (sleep(2))
+                       ; /* nothing */
 -      return para_open_audiod_pipe(conf.stat_cmd_arg);
 +      ret = para_exec_cmdline_pid(&pid, conf.stat_cmd_arg, fds);
 +      if (ret < 0)
 +              return ret;
 +      ret = mark_fd_nonblocking(fds[1]);
 +      if (ret >= 0)
 +              return fds[1];
 +      close(fds[1]);
 +      return ret;
  }
  
  /*
@@@ -931,7 -908,7 +937,7 @@@ static int do_select(int mode
  {
        fd_set rfds;
        int ret;
 -      int max_fileno, cp_numread = 1;
 +      int max_fileno;
        char command_buf[4096] = "";
        int cbo = 0; /* command buf offset */
        struct timeval tv;
@@@ -941,10 -918,11 +947,10 @@@ repeat
  //    ret = refresh_status();
        FD_ZERO(&rfds);
        max_fileno = 0;
 -      /* audiod pipe */
 -      if (audiod_pipe < 0)
 -              audiod_pipe = open_audiod_pipe();
 -      if (audiod_pipe >= 0)
 -              para_fd_set(audiod_pipe, &rfds, &max_fileno);
 +      if (stat_pipe < 0)
 +              stat_pipe = open_stat_pipe();
 +      if (stat_pipe >= 0)
 +              para_fd_set(stat_pipe, &rfds, &max_fileno);
        /* signal pipe */
        para_fd_set(signal_pipe, &rfds, &max_fileno);
        /* command pipe only for COMMAND_MODE */
        if (ret <= 0)
                goto check_return; /* skip fd checks */
        /* signals */
 -      if (FD_ISSET(signal_pipe, &rfds)) {
 -              int sig_nr = para_next_signal();
 -              if (sig_nr > 0)
 -                      handle_signal(sig_nr);
 -      }
 +      ret = para_next_signal(&rfds);
 +      if (ret > 0)
 +              handle_signal(ret);
        /* read command pipe if ready */
 -      if (command_pipe >= 0 && mode == COMMAND_MODE &&
 -                      FD_ISSET(command_pipe, &rfds)) {
 -              cp_numread = read(command_pipe, command_buf + cbo,
 -                      sizeof(command_buf) - 1 - cbo);
 -              if (cp_numread >= 0)
 -                      cbo += cp_numread;
 -              else {
 -                      if (cp_numread < 0)
 -                              PARA_ERROR_LOG("read error (%d)", cp_numread);
 +      if (command_pipe >= 0 && mode == COMMAND_MODE) {
 +              size_t sz;
 +              ret = read_nonblock(command_pipe, command_buf + cbo,
 +                      sizeof(command_buf) - 1 - cbo, &rfds, &sz);
 +              cbo += sz;
 +              sz = cbo;
 +              cbo = for_each_line(command_buf, cbo, &add_output_line, NULL);
 +              if (sz != cbo)
 +                      wrefresh(bot.win);
 +              if (ret < 0) {
 +                      PARA_NOTICE_LOG("closing command pipe: %s",
 +                              para_strerror(-ret));
                        close(command_pipe);
                        command_pipe = -1;
 +                      return 0;
                }
        }
 -      if (audiod_pipe >= 0 && FD_ISSET(audiod_pipe, &rfds))
 -              if (read_audiod_pipe(audiod_pipe, check_stat_line) <= 0) {
 -                      close(audiod_pipe);
 -                      audiod_pipe = -1;
 -                      clear_all_items();
 -                      free(stat_content[SI_BASENAME]);
 -                      stat_content[SI_BASENAME] =
 -                              para_strdup("audiod not running!?");
 -                      print_all_items();
 -              }
 +      ret = read_stat_pipe(&rfds);
 +      if (ret < 0) {
 +              PARA_NOTICE_LOG("closing stat pipe: %s\n", para_strerror(-ret));
 +              close(stat_pipe);
 +              stat_pipe = -1;
 +              clear_all_items();
 +              free(stat_content[SI_BASENAME]);
 +              stat_content[SI_BASENAME] =
 +                      para_strdup("stat command terminated!?");
 +              print_all_items();
 +      }
  check_return:
        switch (mode) {
        case COMMAND_MODE:
 -              if (cp_numread <= 0 && !cbo) /* command complete */
 -                      return 0;
 -              if (cbo)
 -                      cbo = for_each_line(command_buf, cbo,
 -                              &add_output_line, NULL);
 -              if (cp_numread <= 0)
 -                      cbo = 0;
 -              wrefresh(bot.win);
                ret = wgetch(top.win);
                if (ret != ERR && ret != KEY_RESIZE) {
                        if (command_pipe) {
@@@ -1344,30 -1327,31 +1350,30 @@@ static void handle_command(int c
  
        /* first check user's key bindings */
        for (i = 0; i < conf.key_map_given; ++i) {
 -              char tmp[MAXLINE], *handler, *arg;
 +              char *tmp, *handler, *arg;
  
 -              strcpy(tmp, conf.key_map_arg[i]);
 -              if (!split_key_map(tmp, &handler, &arg))
 +              tmp = para_strdup(conf.key_map_arg[i]);
 +              if (!split_key_map(tmp, &handler, &arg)) {
 +                      free(tmp);
                        return;
 -              if (!strcmp(tmp, km_keyname(c))) {
 -                      if (*handler == 'd') {
 -                              display_cmd(arg);
 -                              return;
 -                      }
 -                      if (*handler == 'x') {
 -                              external_cmd(arg);
 -                              return;
 -                      }
 -                      if (*handler == 'p') {
 -                              client_cmd_cmdline(arg);
 -                              return;
 -                      }
 -                      if (*handler == 'i') {
 -                              int num = find_cmd_byname(arg);
 -                              if (num >= 0)
 -                                      command_list[num].handler();
 -                              return;
 -                      }
                }
 +              if (strcmp(tmp, km_keyname(c))) {
 +                      free(tmp);
 +                      continue;
 +              }
 +              if (*handler == 'd')
 +                      display_cmd(arg);
 +              else if (*handler == 'x')
 +                      external_cmd(arg);
 +              else if (*handler == 'p')
 +                      client_cmd_cmdline(arg);
 +              else if (*handler == 'i') {
 +                      int num = find_cmd_byname(arg);
 +                      if (num >= 0)
 +                              command_list[num].handler();
 +              }
 +              free(tmp);
 +              return;
        }
        /* not found, check internal key bindings */
        for (i = 0; command_list[i].handler; i++) {