#include #include #include #include #include #include #include #include "curses_printf.h" #include "kbd_constants.h" #include "main.h" #include "playlist.h" #include "playlist_jump.h" #include "settings.h" /* This file is part of xmms-curses, copyright 2003-2005 Knut Auvor Grythe. xmms-curses 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. xmms-curses 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 xmms-curses; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ static char* playing_status(void); static void mainwin_repaint(void); static void controls(char c); void finish(void); void window_changed(int sig); struct timespec interval = {0, SLEEP_TIME}; prefs settings; windows wins; playlist list; int main(int argc, char *argv[]) { set_defaults(); read_conffiles(); arguments(argc, argv); list.pos = -1; list.length = -1; list.scrolledto = -1; list.song = (song*)malloc(sizeof(song)); list.song_mask = NULL; (void) atexit(finish); (void) initscr(); // initialize the curses library (void) nonl(); // tell curses not to do NL->CR/NL on output keypad(stdscr, true); // enable keyboard mapping (void) cbreak(); // take input chars one at a time, no wait for \n (void) noecho(); // don't echo input - in color (void) nodelay(stdscr, 1); curs_set(0); // turn off cursor signal(SIGWINCH, window_changed); if (has_colors()) { start_color(); init_pair(1, COLOR_WHITE, COLOR_BLUE); init_pair(2, COLOR_GREEN, COLOR_BLUE); init_pair(3, COLOR_RED, COLOR_YELLOW); } wins.status = newwin(2, 0, 0, 0); wins.title = newwin(1, 0, 2, 0); wins.list = newwin(0, 0, 3, 0); wins.term_resized = false; wcolor_set(wins.status, 1, NULL); wcolor_set(wins.title, 2, NULL); wcolor_set(wins.list, 1, NULL); int repaint = true; while (true) { int length, prev_length; char c; if (wins.term_resized == true) { wins.term_resized = false; // Unset trigger repaint = true; resize_windows(); } // no use messing with this prog without XMMS running if (!xmms_remote_is_running(0)) { while((c = getch()) != ERR) { if (c == 'q' || c == ESCAPE) exit (EXIT_SUCCESS); } mvwtitledhline(wins.status, 0, "XMMS NOT RUNNING"); wnoutrefresh(wins.status); doupdate(); nanosleep(&interval, NULL); continue; } list.prev_pos = list.pos; list.pos = xmms_remote_get_playlist_pos(0); prev_length = list.length; //prev_selector = list.selector; length = xmms_remote_get_playlist_length(0); if(length != list.length) { playlist_read(length); } if (length == 0) list.pos = -1; /* input */ while((c = getch()) != ERR) controls(c); paint_playback(); paint_songinfo(); if (list.pos != list.prev_pos || list.length != prev_length) { list.selector = list.pos; playlist_paint(&list); } wnoutrefresh(wins.status); if (repaint) { repaint = false; mainwin_repaint(); } doupdate(); nanosleep(&interval, NULL); } exit(EXIT_SUCCESS); /* we're done */ } static void controls(char c) { int height, width; getmaxyx(wins.list, height, width); // process the command keystroke switch (c) { case 'z': xmms_remote_playlist_prev(0); break; case 'x': xmms_remote_play(0); break; case 'c': xmms_remote_pause(0); break; case 'v': xmms_remote_stop(0); break; case 'b': xmms_remote_playlist_next(0); break; case 's': xmms_remote_toggle_shuffle(0); break; case 'r': xmms_remote_toggle_repeat(0); break; case 'j': playlist_jump(list); mainwin_repaint(); break; case '+': case '0': xmms_remote_set_main_volume(0,xmms_remote_get_main_volume(0)+5); break; case '-': case '9': xmms_remote_set_main_volume(0,xmms_remote_get_main_volume(0)-5); break; case ARROW_LEFT: xmms_remote_jump_to_time(0, xmms_remote_get_output_time(0)-5000); break; case ARROW_RIGHT: xmms_remote_jump_to_time(0, xmms_remote_get_output_time(0)+5000); break; case ARROW_DOWN: if( list.selector < (list.length - 1) ) { ++(list.selector); playlist_paint(&list); } break; case ARROW_UP: if ( list.selector > 0 ) { --(list.selector); playlist_paint(&list); } break; case PG_DOWN: list.selector+=height; if(list.selector>=list.length) list.selector = list.length-1; playlist_paint(&list); break; case PG_UP: list.selector-=height; if(list.selector<0) list.selector = 0; playlist_paint(&list); break; case ENTER: xmms_remote_set_playlist_pos(0, list.selector); xmms_remote_play(0); break; case 'q': case ESCAPE: exit(EXIT_SUCCESS); break; case 'L': playlist_read(xmms_remote_get_playlist_length(0)); playlist_paint(&list); break; } } void paint_playback(void) { int time; time = xmms_remote_get_output_time(0)/1000; mvwaddnstrf(wins.status, 0, 0, "%s [%02i:%02i] %s", -1, playing_status(), time/60, time%60, song_title(list.pos)); wclrtoeol(wins.status); mvwchgat(wins.status, 0, 0, -1, A_BOLD, 1, NULL); } void paint_songinfo(void) { int rate, freq, nch; xmms_remote_get_info(0, &rate, &freq, &nch); mvwaddnstrf(wins.status, 1, 0, "Tot %02i:%02i, %i kbps, %i KHz, %s - %s - %s - vol: %3d%%", -1, song_length(list.pos)/60, song_length(list.pos)%60, rate/1000, freq/1000, nch>1 ? "stereo" : " mono ", xmms_remote_is_shuffle(0) ? "*shuf*" : "noshuf", xmms_remote_is_repeat(0) ? "*rep*" : "norep", xmms_remote_get_main_volume(0)); wclrtoeol(wins.status); wchgat(wins.status, -1, A_NORMAL, 1, NULL); } void mvwtitledhline(WINDOW *win, int y, char *label) { int height, width; getmaxyx(win, height, width); mvwhline(win, y, 0, 0, width); mvwaddch(win, y, width/2-strlen(label)/2-1, ' '); waddstr(win, label); waddch(win, ' '); } static char* playing_status() { if (xmms_remote_is_playing(0)) { if (!xmms_remote_is_paused(0)) { return("|>"); } else { return("||"); } } else { return("[]"); } } void resize_windows(void) { struct winsize size; ioctl(1, TIOCGWINSZ, &size); endwin(); resizeterm(size.ws_col, size.ws_row); wresize(wins.status, 2, size.ws_col); wresize(wins.title, 1, size.ws_col); wresize(wins.list, size.ws_row-3, size.ws_col); } static void mainwin_repaint(void) { playlist_paint(&list); mvwtitledhline(wins.title, 0, "Playlist"); wnoutrefresh(wins.title); } void finish() { endwin(); /* do your non-curses wrapup here */ } void window_changed(int sig) { wins.term_resized = true; }