X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=gui.c;h=9a02bdcabc3c252fb875b893cea5610f23243b2e;hp=ab66bbb262d38efe8b4501034d3a8e651a07b5bd;hb=32d43fac23025e82b7a92bfce744207c69165a04;hpb=75529c7cb29903302931db92f04cb3b510eb6317 diff --git a/gui.c b/gui.c index ab66bbb2..9a02bdca 100644 --- a/gui.c +++ b/gui.c @@ -1,42 +1,34 @@ /* - * Copyright (C) 1998-2006 Andre Noll + * Copyright (C) 1998-2008 Andre Noll * - * 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, USA. + * Licensed under the GPL v2. For licencing details see COPYING. */ -/** \file gui.c ncurses-based interface for paraslash */ +/** \file gui.c Curses-based interface for paraslash. */ +#include +#include +#include #include "gui.cmdline.h" #include "para.h" +#include "gui.h" +#include "string.h" #include #include "ringbuffer.h" -#include "string.h" #include "fd.h" #include "error.h" +#include "list.h" +#include "sched.h" +#include "signal.h" /** define the array of error lists needed by para_gui */ INIT_GUI_ERRLISTS; -extern const char *status_item_list[NUM_STAT_ITEMS]; static char *stat_content[NUM_STAT_ITEMS]; -#define STANDARD_STATUS_BAR "para_gui " VERSION " (hit ? for help)" +#define STANDARD_STATUS_BAR "para_gui " PACKAGE_VERSION " (hit ? for help)" static int signal_pipe; -static void finish(int sig); - static struct win_data { WINDOW *win; NCURSES_SIZE_T begx; @@ -51,13 +43,13 @@ struct rb_entry { size_t len; int color; }; -void *bot_win_rb; +struct ringbuffer *bot_win_rb; #define NUM_LINES(len) (1 + (len) / bot.cols) static unsigned scroll_position; -static int external_cmd_died, curses_active; -static pid_t external_cmd_pid; +static int cmd_died, curses_active; +static pid_t cmd_pid; static int command_pipe = -1; static int audiod_pipe = -1; @@ -66,15 +58,15 @@ static struct gui_args_info conf; enum {GETCH_MODE, COMMAND_MODE, EXTERNAL_MODE}; -#define COLOR_STATUSBAR 32 -#define COLOR_COMMAND 33 -#define COLOR_OUTPUT 34 -#define COLOR_MSG 35 -#define COLOR_ERRMSG 36 -#define COLOR_WELCOME 37 -#define COLOR_SEPARATOR 38 -#define COLOR_TOP 39 -#define COLOR_BOT 40 +#define COLOR_STATUSBAR 52 +#define COLOR_COMMAND 53 +#define COLOR_OUTPUT 54 +#define COLOR_MSG 55 +#define COLOR_ERRMSG 56 +#define COLOR_WELCOME 57 +#define COLOR_SEPARATOR 58 +#define COLOR_TOP 59 +#define COLOR_BOT 60 struct gui_command { const char *key; @@ -197,6 +189,38 @@ struct gui_command command_list[] = { } }; +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; @@ -339,7 +363,7 @@ static void print_status_bar(void) if (!curses_active) return; wmove(sb.win, 0, 0); - align_str(sb.win,STANDARD_STATUS_BAR, sb.cols, CENTER); + align_str(sb.win, STANDARD_STATUS_BAR, sb.cols, CENTER); wrefresh(sb.win); } @@ -457,11 +481,12 @@ __printf_2_3 static void outputf(int color, const char* fmt,...) wrefresh(bot.win); } -static void add_output_line(char *line) +static int add_output_line(char *line, __a_unused void *data) { if (!curses_active) - return; + return 1; rb_add_entry(COLOR_OUTPUT, para_strdup(line)); + return 1; } void para_log(int ll, const char *fmt,...) @@ -494,7 +519,7 @@ static void setup_signal_handling(void) para_install_sighandler(SIGCHLD); para_install_sighandler(SIGWINCH); para_install_sighandler(SIGUSR1); - signal(SIGPIPE, SIG_IGN); +// signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); } @@ -540,7 +565,7 @@ static void print_welcome(void) int ll = conf.loglevel_arg; if (ll > NOTICE) return; - outputf(COLOR_WELCOME, "Welcome to para_gui " VERSION + outputf(COLOR_WELCOME, "Welcome to para_gui " PACKAGE_VERSION " \"" CODENAME "\". Theme: %s", theme.name); wclrtoeol(bot.win); } @@ -654,7 +679,6 @@ static void print_stat_item(int i) if (!curses_active || !d.len || !c) return; tmp = make_message("%s%s%s", d.prefix, c, d.postfix); -// PARA_DEBUG_LOG("%s: read: %s\n", __func__, tmp); wmove(top.win, d.y * top.lines / 100, d.x * COLS / 100); wrefresh(top.win); wattron(top.win, COLOR_PAIR(i + 1)); @@ -669,14 +693,15 @@ static void print_all_items(void) if (!curses_active) return; - for (i = 0; i < NUM_STAT_ITEMS; i++) + FOR_EACH_STATUS_ITEM(i) print_stat_item(i); } + static void clear_all_items(void) { int i; - for (i = 0; i < NUM_STAT_ITEMS; i++) { + FOR_EACH_STATUS_ITEM(i) { free(stat_content[i]); stat_content[i] = para_strdup(""); } @@ -685,10 +710,11 @@ static void clear_all_items(void) static void init_colors(void) { int i; + if (!has_colors()) msg_n_exit(EXIT_FAILURE, "Error: No color term\n"); start_color(); - for (i = 0; i < NUM_STAT_ITEMS; i++) + FOR_EACH_STATUS_ITEM(i) if (theme.data[i].len) init_pair(i + 1, theme.data[i].fg, theme.data[i].bg); init_pair(COLOR_STATUSBAR, theme.sb_fg, theme.sb_bg); @@ -730,14 +756,15 @@ static void init_curses(void) static void check_sigchld(void) { + int ret; pid_t pid; reap_next_child: - pid = para_reap_child(); - if (pid <= 0) + ret = para_reap_child(&pid); + if (ret <= 0) return; - if (pid == external_cmd_pid) { - external_cmd_pid = 0; - external_cmd_died = 1; + if (pid == cmd_pid) { + cmd_pid = 0; + cmd_died = 1; } goto reap_next_child; } @@ -745,7 +772,7 @@ reap_next_child: /* * print status line if line starts with known command. */ -static void check_stat_line(char *line) +static int check_stat_line(char *line, __a_unused void *data) { int i; @@ -753,11 +780,13 @@ static void check_stat_line(char *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; + return 1; } /* @@ -829,13 +858,13 @@ static void handle_signal(int sig) } return; case SIGINT: - PARA_WARNING_LOG("%s", "caught SIGINT, reset"); + 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 */ return; case SIGUSR1: - PARA_NOTICE_LOG("%s", "got SIGUSR1, rereading configuration"); + PARA_NOTICE_LOG("got SIGUSR1, rereading configuration"); com_reread_conf(); return; case SIGCHLD: @@ -867,14 +896,14 @@ static int open_audiod_pipe(void) * * EXTERNAL_MODE: Check only signal pipe. Used when an external command * is running. During that thime curses is disabled. Returns when - * external_cmd_pid == 0. + * cmd_pid == 0. */ static int do_select(int mode) { fd_set rfds; int ret; int max_fileno, cp_numread = 1; - char command_buf[STRINGSIZE] = ""; + char command_buf[4096] = ""; int cbo = 0; /* command buf offset */ struct timeval tv; repeat: @@ -893,8 +922,6 @@ repeat: /* command pipe only for COMMAND_MODE */ if (command_pipe >= 0 && mode == COMMAND_MODE) para_fd_set(command_pipe, &rfds, &max_fileno); - if (curses_active) - para_fd_set(STDIN_FILENO, &rfds, &max_fileno); ret = para_select(max_fileno + 1, &rfds, NULL, &tv); if (ret <= 0) goto check_return; /* skip fd checks */ @@ -908,7 +935,7 @@ repeat: if (command_pipe >= 0 && mode == COMMAND_MODE && FD_ISSET(command_pipe, &rfds)) { cp_numread = read(command_pipe, command_buf + cbo, - STRINGSIZE - 1 - cbo); + sizeof(command_buf) - 1 - cbo); if (cp_numread >= 0) cbo += cp_numread; else { @@ -923,8 +950,8 @@ repeat: close(audiod_pipe); audiod_pipe = -1; clear_all_items(); - free(stat_content[SI_STATUS_BAR]); - stat_content[SI_STATUS_BAR] = + free(stat_content[SI_BASENAME]); + stat_content[SI_BASENAME] = para_strdup("audiod not running!?"); print_all_items(); } @@ -934,10 +961,21 @@ check_return: if (cp_numread <= 0 && !cbo) /* command complete */ return 0; if (cbo) - cbo = for_each_line(command_buf, cbo, &add_output_line); + 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) { + close(command_pipe); + command_pipe = -1; + } + if (cmd_pid) + kill(cmd_pid, SIGTERM); + return -1; + } break; case GETCH_MODE: ret = wgetch(top.win); @@ -945,8 +983,8 @@ check_return: return ret; break; case EXTERNAL_MODE: - if (external_cmd_died) { - external_cmd_died = 0; + if (cmd_died) { + cmd_died = 0; return 0; } } @@ -958,25 +996,31 @@ check_return: */ static int send_output(void) { + int ret; + if (command_pipe < 0) return 0; + ret = mark_fd_nonblocking(command_pipe); + if (ret < 0) { + close(command_pipe); + return ret; + } if (do_select(COMMAND_MODE) >= 0) - PARA_INFO_LOG("%s", "command complete"); + PARA_INFO_LOG("command complete"); else - PARA_NOTICE_LOG("%s", "command aborted"); + PARA_NOTICE_LOG("command aborted"); print_in_bar(COLOR_MSG, " "); return 1; } static int client_cmd_cmdline(char *cmd) { - pid_t pid; int ret, fds[3] = {0, 1, 0}; - char *c = make_message(BINDIR "/para_client %s", cmd); + char *c = make_message(BINDIR "/para_client -- %s", cmd); outputf(COLOR_COMMAND, "%s", c); - print_in_bar(COLOR_MSG, "executing client command, hit q to abort\n"); - ret = para_exec_cmdline_pid(&pid, c, fds); + print_in_bar(COLOR_MSG, "executing client command, hit any key to abort\n"); + ret = para_exec_cmdline_pid(&cmd_pid, c, fds); free(c); if (ret < 0) return -1; @@ -989,12 +1033,11 @@ static int client_cmd_cmdline(char *cmd) */ static int display_cmd(char *cmd) { - pid_t pid; int fds[3] = {0, 1, 0}; - print_in_bar(COLOR_MSG, "executing display command, hit q to abort"); + print_in_bar(COLOR_MSG, "executing display command, hit any key to abort"); outputf(COLOR_COMMAND, "%s", cmd); - if (para_exec_cmdline_pid(&pid, cmd, fds) < 0) + if (para_exec_cmdline_pid(&cmd_pid, cmd, fds) < 0) return -1; command_pipe = fds[1]; return send_output(); @@ -1007,10 +1050,11 @@ static int external_cmd(char *cmd) { int fds[3] = {-1, -1, -1}; - if (external_cmd_pid) + if (cmd_pid) return -1; shutdown_curses(); - para_exec_cmdline_pid(&external_cmd_pid, cmd, fds); + para_exec_cmdline_pid(&cmd_pid, cmd, fds); + cmd_died = 0; do_select(EXTERNAL_MODE); init_curses(); return 0; @@ -1085,22 +1129,22 @@ static void com_scroll_up(void) { struct rb_entry *rbe = NULL; unsigned lines; - int i, first_rbe, scroll; + int i, first_rbe, num_scroll; /* the entry that is going to vanish */ rbe = ringbuffer_get(bot_win_rb, scroll_position); if (!rbe) goto err_out; - scroll = NUM_LINES(rbe->len); + num_scroll = NUM_LINES(rbe->len); first_rbe = first_visible_rbe(&lines); if (first_rbe < 0 || (first_rbe == ringbuffer_filled(bot_win_rb) - 1)) goto err_out; scroll_position++; - wscrl(bot.win, -scroll); + wscrl(bot.win, -num_scroll); i = draw_top_rbe(&lines); if (i < 0) goto err_out; - while (i > 0 && lines < scroll) { + while (i > 0 && lines < num_scroll) { int rbe_lines; rbe = ringbuffer_get(bot_win_rb, --i); if (!rbe) @@ -1150,15 +1194,21 @@ static void com_ll_incr(void) static void com_reread_conf(void) { char *cf =configfile_exists(); + struct gui_cmdline_parser_params params = { + .override = 1, + .initialize = 1, + .check_required = 0, + .check_ambiguity = 0 + }; if (!cf) { - PARA_WARNING_LOG("%s", "there is no configuration to read"); + PARA_WARNING_LOG("there is no configuration to read"); return; } - PARA_INFO_LOG("%s", "rereading command line options and config file"); + PARA_INFO_LOG("rereading command line options and config file"); gui_cmdline_parser(_argc, _argv, &conf); - gui_cmdline_parser_configfile(cf, &conf, 1, 1, 0); - PARA_NOTICE_LOG("%s", "configuration read"); + gui_cmdline_parser_config_file(cf, &conf, ¶ms); + PARA_NOTICE_LOG("config file reloaded"); if (check_key_map_args() < 0) finish(EXIT_FAILURE); } @@ -1203,7 +1253,7 @@ static void com_help(void) static void com_shrink_top_win(void) { if (top.lines <= theme.top_lines_min) { - PARA_WARNING_LOG("%s", "can not decrease top window"); + PARA_WARNING_LOG("can not decrease top window"); return; } init_wins(top.lines - 1); @@ -1215,7 +1265,7 @@ static void com_shrink_top_win(void) static void com_enlarge_top_win(void) { if (bot.lines < 3) { - PARA_WARNING_LOG("%s", "can not increase top window"); + PARA_WARNING_LOG("can not increase top window"); return; } init_wins(top.lines + 1); @@ -1226,7 +1276,8 @@ static void com_enlarge_top_win(void) static void com_version(void) { - print_in_bar(COLOR_MSG, "para_gui " VERSION " \"" CODENAME "\""); + print_in_bar(COLOR_MSG, "para_gui " PACKAGE_VERSION " \"" + CODENAME "\""); } static void com_quit(void) @@ -1318,6 +1369,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "parse error while reading command line\n"); exit(EXIT_FAILURE); } + HANDLE_VERSION_FLAG("gui", conf); init_theme(0, &theme); top.lines = theme.top_lines_default; if (check_key_map_args() < 0) { @@ -1330,8 +1382,15 @@ int main(int argc, char *argv[]) conf.config_file_arg); exit(EXIT_FAILURE); } - if (cf) - gui_cmdline_parser_configfile(cf, &conf, 0, 0, 0); + if (cf) { + struct gui_cmdline_parser_params params = { + .override = 0, + .initialize = 0, + .check_required = 0, + .check_ambiguity = 0 + }; + gui_cmdline_parser_config_file(cf, &conf, ¶ms); + } if (check_key_map_args() < 0) { fprintf(stderr, "invalid key map in config file\n"); exit(EXIT_FAILURE); @@ -1341,11 +1400,6 @@ int main(int argc, char *argv[]) initscr(); /* needed only once, always successful */ init_curses(); print_welcome(); - ret = mark_fd_nonblock(STDIN_FILENO); - if (ret < 0) { - PARA_EMERG_LOG("%s\n", PARA_STRERROR(-ret)); - exit(EXIT_FAILURE); - } for (;;) { print_status_bar(); ret = do_select(GETCH_MODE);