diff options
Diffstat (limited to 'screen.c')
-rw-r--r-- | screen.c | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/screen.c b/screen.c new file mode 100644 index 000000000..74244befc --- /dev/null +++ b/screen.c @@ -0,0 +1,520 @@ +/* + * $Id: screen.c,v 1.10 2004/03/17 14:50:12 kalle Exp $ + * + */ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <glib.h> +#include <ncurses.h> + +#include "libmpdclient.h" +#include "mpc.h" +#include "command.h" +#include "screen.h" +#include "screen_play.h" +#include "screen_file.h" +#include "screen_help.h" +#include "screen_search.h" + +#define STATUS_MESSAGE_TIMEOUT 3 + +static screen_t *screen = NULL; + +static void +switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c) +{ + if( new_mode == screen->mode ) + return; + + switch(screen->mode) + { + case SCREEN_PLAY_WINDOW: + play_close(screen, c); + break; + case SCREEN_FILE_WINDOW: + file_close(screen, c); + break; + case SCREEN_SEARCH_WINDOW: + search_close(screen, c); + break; + case SCREEN_HELP_WINDOW: + help_close(screen, c); + break; + } + + screen->mode = new_mode; + screen->painted = 0; + + switch(screen->mode) + { + case SCREEN_PLAY_WINDOW: + play_open(screen, c); + break; + case SCREEN_FILE_WINDOW: + file_open(screen, c); + break; + case SCREEN_SEARCH_WINDOW: + search_open(screen, c); + break; + case SCREEN_HELP_WINDOW: + help_open(screen, c); + break; + } +} + +static void +paint_top_window(char *header, int volume, int clear) +{ + static int prev_volume = -1; + WINDOW *w = screen->top_window.w; + + if(clear) + { + wclear(w); + } + + if(prev_volume!=volume || clear) + { + char buf[12]; + + wattron(w, A_BOLD); + mvwaddstr(w, 0, 0, header ); + wattroff(w, A_BOLD); + if( volume==MPD_STATUS_NO_VOLUME ) + { + snprintf(buf, 12, "Volume n/a "); + } + else + { + snprintf(buf, 12, "Volume %3d%%", volume); + } + mvwaddstr(w, 0, screen->top_window.cols-12, buf); + + mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols); + + wrefresh(w); + } +} + +static void +paint_progress_window(mpd_client_t *c) +{ + double p; + int width; + + if( c->status==NULL || !IS_PLAYING(c->status->state) ) + { + mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE, + screen->progress_window.cols); + wrefresh(screen->progress_window.w); + return; + } + + p = ((double) c->status->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'); + wrefresh(screen->progress_window.w); +} + +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 x = 0; + + if( time(NULL) - screen->status_timestamp <= STATUS_MESSAGE_TIMEOUT ) + return; + + wmove(w, 0, 0); + wclrtoeol(w); + + switch(status->state) + { + case MPD_STATUS_STATE_STOP: + wattron(w, A_BOLD); + waddstr(w, "Stopped! "); + wattroff(w, A_BOLD); + break; + case MPD_STATUS_STATE_PLAY: + waddstr(w, "Playing:"); + break; + case MPD_STATUS_STATE_PAUSE: + wattron(w, A_BOLD); + waddstr(w, "Paused:"); + wattroff(w, A_BOLD); + break; + default: + waddstr(w, "Warning: Music Player Daemon in unknown state!"); + break; + } + x += 10; + + if( IS_PLAYING(status->state) && song ) + { + mvwaddstr(w, 0, x, mpc_get_song_name(song)); + } + + + /* time */ + if( IS_PLAYING(status->state) ) + { + x = screen->status_window.cols - strlen(screen->buf); + + if( c->status->repeat ) + mvwaddstr(w, 0, x-3, "<R>"); + else + mvwaddstr(w, 0, x-3, " "); + + snprintf(screen->buf, screen->buf_size, + " [%i:%02i/%i:%02i] ", + status->elapsedTime/60, status->elapsedTime%60, + status->totalTime/60, status->totalTime%60 ); + mvwaddstr(w, 0, x, screen->buf); + + } + + + wrefresh(w); +} + + + +int +screen_exit(void) +{ + endwin(); + if( screen ) + { + screen->playlist = list_window_free(screen->playlist); + screen->filelist = list_window_free(screen->filelist); + screen->helplist = list_window_free(screen->helplist); + free(screen->buf); + free(screen); + screen = NULL; + } + return 0; +} + +void +screen_resized(int sig) +{ + screen_exit(); + if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS ) + { + fprintf(stderr, "Error: Screen to small!\n"); + exit(EXIT_FAILURE); + } + screen_init(); +} + +void +screen_status_message(mpd_client_t *c, char *msg) +{ + WINDOW *w = screen->status_window.w; + + wmove(w, 0, 0); + wclrtoeol(w); + wattron(w, A_BOLD); + waddstr(w, msg); + wattroff(w, A_BOLD); + wrefresh(w); + screen->status_timestamp = time(NULL); +} + +int +screen_init(void) +{ + /* initialize the curses library */ + initscr(); + start_color(); + use_default_colors(); + /* 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(100); /*void wtimeout(WINDOW *win, int delay);*/ + + + if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS ) + { + fprintf(stderr, "Error: Screen to small!\n"); + exit(EXIT_FAILURE); + } + + screen = malloc(sizeof(screen_t)); + memset(screen, 0, sizeof(screen_t)); + screen->mode = SCREEN_PLAY_WINDOW; + screen->cols = COLS; + screen->rows = LINES; + screen->buf = malloc(screen->cols); + screen->buf_size = screen->cols; + screen->painted = 0; + + /* 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); + screen->playlist = list_window_init( screen->main_window.w, + screen->main_window.cols, + screen->main_window.rows ); + screen->filelist = list_window_init( screen->main_window.w, + screen->main_window.cols, + screen->main_window.rows ); + screen->helplist = list_window_init( screen->main_window.w, + screen->main_window.cols, + screen->main_window.rows ); + leaveok(screen->main_window.w, TRUE); + 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); + + return 0; +} + +void +screen_paint(mpd_client_t *c) +{ + switch(screen->mode) + { + case SCREEN_PLAY_WINDOW: + paint_top_window(TOP_HEADER_PLAY, c->status->volume, 1); + play_paint(screen, c); + break; + case SCREEN_FILE_WINDOW: + paint_top_window(file_get_header(c), c->status->volume, 1); + file_paint(screen, c); + break; + case SCREEN_SEARCH_WINDOW: + paint_top_window(TOP_HEADER_SEARCH, c->status->volume, 1); + search_paint(screen, c); + break; + case SCREEN_HELP_WINDOW: + paint_top_window(TOP_HEADER_PLAY, c->status->volume, 1); + help_paint(screen, c); + break; + } + + paint_progress_window(c); + paint_status_window(c); + screen->painted = 1; +} + +void +screen_update(mpd_client_t *c) +{ + if( !screen->painted ) + return screen_paint(c); + + switch(screen->mode) + { + case SCREEN_PLAY_WINDOW: + paint_top_window(TOP_HEADER_PLAY, c->status->volume, 0); + play_update(screen, c); + break; + case SCREEN_FILE_WINDOW: + paint_top_window(file_get_header(c), c->status->volume, 0); + file_update(screen, c); + break; + case SCREEN_SEARCH_WINDOW: + paint_top_window(TOP_HEADER_SEARCH, c->status->volume, 0); + search_update(screen, c); + break; + case SCREEN_HELP_WINDOW: + paint_top_window(TOP_HEADER_HELP, c->status->volume, 0); + help_update(screen, c); + break; + } + paint_progress_window(c); + paint_status_window(c); +} + +void +screen_cmd(mpd_client_t *c, command_t cmd) +{ + int n; + char buf[256]; + screen_mode_t new_mode = screen->mode; + + switch(screen->mode) + { + case SCREEN_PLAY_WINDOW: + if( play_cmd(screen, c, cmd) ) + return; + break; + case SCREEN_FILE_WINDOW: + if( file_cmd(screen, c, cmd) ) + return; + break; + case SCREEN_SEARCH_WINDOW: + if( search_cmd(screen, c, cmd) ) + return; + break; + case SCREEN_HELP_WINDOW: + if( help_cmd(screen, c, cmd) ) + return; + break; + } + + switch(cmd) + { + case CMD_PLAY: + mpd_sendPlayCommand(c->connection, screen->playlist->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_TRACK_NEXT: + if( IS_PLAYING(c->status->state) ) + { + mpd_sendNextCommand(c->connection); + mpd_finishCommand(c->connection); + } + break; + case CMD_TRACK_PREVIOUS: + if( IS_PLAYING(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(c, "Shuffled playlist!"); + break; + case CMD_CLEAR: + mpd_sendClearCommand(c->connection); + mpd_finishCommand(c->connection); + file_clear_highlights(c); + screen_status_message(c, "Cleared playlist!"); + break; + case CMD_REPEAT: + n = !c->status->repeat; + mpd_sendRepeatCommand(c->connection, n); + mpd_finishCommand(c->connection); + snprintf(buf, 256, "Repeat is %s", n ? "On" : "Off"); + screen_status_message(c, buf); + break; + case CMD_RANDOM: + n = !c->status->random; + mpd_sendRandomCommand(c->connection, n); + mpd_finishCommand(c->connection); + snprintf(buf, 256, "Random is %s", n ? "On" : "Off"); + screen_status_message(c, buf); + break; + case CMD_VOLUME_UP: + mpd_sendVolumeCommand(c->connection, 1); + mpd_finishCommand(c->connection); + if( c->status->volume!=MPD_STATUS_NO_VOLUME ) + { + snprintf(buf, 256, "Volume %d%%", c->status->volume+1); + screen_status_message(c, buf); + } + break; + case CMD_VOLUME_DOWN: + mpd_sendVolumeCommand(c->connection, -1); + mpd_finishCommand(c->connection); + if( c->status->volume!=MPD_STATUS_NO_VOLUME ) + { + snprintf(buf, 256, "Volume %d%%", c->status->volume-1); + screen_status_message(c, buf); + } + 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; + case CMD_QUIT: + exit(EXIT_SUCCESS); + case CMD_NONE: + case CMD_DELETE: + case CMD_SELECT: + case CMD_LIST_PREVIOUS: + case CMD_LIST_NEXT: + case CMD_LIST_FIRST: + case CMD_LIST_LAST: + case CMD_LIST_NEXT_PAGE: + case CMD_LIST_PREVIOUS_PAGE: + break; + } + +} + + |