1 /*
2 * $Id$
3 *
4 * (c) 2004 by Kalle Wallin <kaw@linux.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <time.h>
26 #include <locale.h>
27 #include <glib.h>
28 #include <ncurses.h>
30 #include "config.h"
31 #include "ncmpc.h"
32 #include "support.h"
33 #include "mpdclient.h"
34 #include "utils.h"
35 #include "command.h"
36 #include "options.h"
37 #include "colors.h"
38 #include "strfsong.h"
39 #include "wreadln.h"
40 #include "screen.h"
41 #include "screen_utils.h"
43 #define MAX_SONGNAME_LENGTH 512
45 #define SCREEN_PLAYLIST_ID 0
46 #define SCREEN_BROWSE_ID 1
47 #define SCREEN_ARTIST_ID 2
48 #define SCREEN_HELP_ID 100
49 #define SCREEN_KEYDEF_ID 101
50 #define SCREEN_CLOCK_ID 102
51 #define SCREEN_SEARCH_ID 103
55 /* screens */
56 extern screen_functions_t *get_screen_playlist(void);
57 extern screen_functions_t *get_screen_browse(void);
58 extern screen_functions_t *get_screen_help(void);
59 extern screen_functions_t *get_screen_search(void);
60 extern screen_functions_t *get_screen_artist(void);
61 extern screen_functions_t *get_screen_keydef(void);
62 extern screen_functions_t *get_screen_clock(void);
64 typedef screen_functions_t * (*screen_get_mode_functions_fn_t) (void);
66 typedef struct
67 {
68 gint id;
69 gchar *name;
70 screen_get_mode_functions_fn_t get_mode_functions;
71 } screen_mode_info_t;
74 static screen_mode_info_t screens[] = {
75 { SCREEN_PLAYLIST_ID, "playlist", get_screen_playlist },
76 { SCREEN_BROWSE_ID, "browse", get_screen_browse },
77 { SCREEN_HELP_ID, "help", get_screen_help },
78 #ifdef ENABLE_ARTIST_SCREEN
79 { SCREEN_ARTIST_ID, "artist", get_screen_artist },
80 #endif
81 #ifdef ENABLE_SEARCH_SCREEN
82 { SCREEN_SEARCH_ID, "search", get_screen_search },
83 #endif
84 #ifdef ENABLE_KEYDEF_SCREEN
85 { SCREEN_KEYDEF_ID, "keydef", get_screen_keydef },
86 #endif
87 #ifdef ENABLE_CLOCK_SCREEN
88 { SCREEN_CLOCK_ID, "clock", get_screen_clock },
89 #endif
90 { G_MAXINT, NULL, NULL }
91 };
93 static gboolean welcome = TRUE;
94 static screen_t *screen = NULL;
95 static screen_functions_t *mode_fn = NULL;
96 static int seek_id = -1;
97 static int seek_target_time = 0;
99 static gint
100 lookup_mode(gint id)
101 {
102 gint i=0;
104 while( screens[i].name )
105 {
106 if( screens[i].id == id )
107 return i;
108 i++;
109 }
110 return -1;
111 }
113 static void
114 switch_screen_mode(gint id, mpdclient_t *c)
115 {
116 gint new_mode;
118 if( id == screens[screen->mode].id )
119 return;
121 /* close the old mode */
122 if( mode_fn && mode_fn->close )
123 mode_fn->close();
125 /* get functions for the new mode */
126 new_mode = lookup_mode(id);
127 if( new_mode>=0 && screens[new_mode].get_mode_functions )
128 {
129 D("switch_screen(%s)\n", screens[new_mode].name );
130 mode_fn = screens[new_mode].get_mode_functions();
131 screen->mode = new_mode;
132 }
134 screen->painted = 0;
136 /* open the new mode */
137 if( mode_fn && mode_fn->open )
138 mode_fn->open(screen, c);
140 }
142 static void
143 paint_top_window(char *header, mpdclient_t *c, int clear)
144 {
145 char flags[5];
146 static int prev_volume = -1;
147 static int prev_header_len = -1;
148 WINDOW *w = screen->top_window.w;
150 if(prev_header_len!=strlen(header))
151 {
152 prev_header_len = strlen(header);
153 clear = 1;
154 }
156 if(clear)
157 {
158 wmove(w, 0, 0);
159 wclrtoeol(w);
160 }
162 if(prev_volume!=c->status->volume || clear)
163 {
164 char buf[32];
166 if( header[0] )
167 {
168 colors_use(w, COLOR_TITLE_BOLD);
169 mvwaddstr(w, 0, 0, header);
170 }
171 else
172 {
173 colors_use(w, COLOR_TITLE_BOLD);
174 waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE));
175 colors_use(w, COLOR_TITLE);
176 waddstr(w, _(":Help "));
177 colors_use(w, COLOR_TITLE_BOLD);
178 waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE));
179 colors_use(w, COLOR_TITLE);
180 waddstr(w, _(":Playlist "));
181 colors_use(w, COLOR_TITLE_BOLD);
182 waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE));
183 colors_use(w, COLOR_TITLE);
184 waddstr(w, _(":Browse "));
185 #ifdef ENABLE_ARTIST_SCREEN
186 colors_use(w, COLOR_TITLE_BOLD);
187 waddstr(w, get_key_names(CMD_SCREEN_ARTIST, FALSE));
188 colors_use(w, COLOR_TITLE);
189 waddstr(w, _(":Artist "));
190 #endif
191 #ifdef ENABLE_SEARCH_SCREEN
192 colors_use(w, COLOR_TITLE_BOLD);
193 waddstr(w, get_key_names(CMD_SCREEN_SEARCH, FALSE));
194 colors_use(w, COLOR_TITLE);
195 waddstr(w, _(":Search "));
196 #endif
197 }
198 if( c->status->volume==MPD_STATUS_NO_VOLUME )
199 {
200 g_snprintf(buf, 32, _("Volume n/a "));
201 }
202 else
203 {
204 g_snprintf(buf, 32, _(" Volume %d%%"), c->status->volume);
205 }
206 colors_use(w, COLOR_TITLE);
207 mvwaddstr(w, 0, screen->top_window.cols-strlen(buf), buf);
209 flags[0] = 0;
210 if( c->status->repeat )
211 g_strlcat(flags, "r", sizeof(flags));
212 if( c->status->random )
213 g_strlcat(flags, "z", sizeof(flags));;
214 if( c->status->crossfade )
215 g_strlcat(flags, "x", sizeof(flags));
216 if( c->status->updatingDb )
217 g_strlcat(flags, "U", sizeof(flags));
218 colors_use(w, COLOR_LINE);
219 mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols);
220 if( flags[0] )
221 {
222 wmove(w,1,screen->top_window.cols-strlen(flags)-3);
223 waddch(w, '[');
224 colors_use(w, COLOR_LINE_BOLD);
225 waddstr(w, flags);
226 colors_use(w, COLOR_LINE);
227 waddch(w, ']');
228 }
229 wnoutrefresh(w);
230 }
231 }
233 static void
234 paint_progress_window(mpdclient_t *c)
235 {
236 double p;
237 int width;
238 int elapsedTime = c->status->elapsedTime;
240 if( c->status==NULL || IS_STOPPED(c->status->state) )
241 {
242 mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE,
243 screen->progress_window.cols);
244 wnoutrefresh(screen->progress_window.w);
245 return;
246 }
248 if( c->song && seek_id == c->song->id )
249 elapsedTime = seek_target_time;
251 p = ((double) elapsedTime) / ((double) c->status->totalTime);
253 width = (int) (p * (double) screen->progress_window.cols);
254 mvwhline(screen->progress_window.w,
255 0, 0,
256 ACS_HLINE,
257 screen->progress_window.cols);
258 whline(screen->progress_window.w, '=', width-1);
259 mvwaddch(screen->progress_window.w, 0, width-1, 'O');
260 wnoutrefresh(screen->progress_window.w);
261 }
263 static void
264 paint_status_window(mpdclient_t *c)
265 {
266 WINDOW *w = screen->status_window.w;
267 mpd_Status *status = c->status;
268 mpd_Song *song = c->song;
269 int elapsedTime = c->status->elapsedTime;
270 char *str = NULL;
271 int x = 0;
273 if( time(NULL) - screen->status_timestamp <= SCREEN_STATUS_MESSAGE_TIME )
274 return;
276 wmove(w, 0, 0);
277 wclrtoeol(w);
278 colors_use(w, COLOR_STATUS_BOLD);
280 switch(status->state)
281 {
282 case MPD_STATUS_STATE_PLAY:
283 str = _("Playing:");
284 break;
285 case MPD_STATUS_STATE_PAUSE:
286 str = _("[Paused]");
287 break;
288 case MPD_STATUS_STATE_STOP:
289 default:
290 break;
291 }
293 if( str )
294 {
295 waddstr(w, str);
296 x += strlen(str)+1;
297 }
299 /* create time string */
300 memset(screen->buf, 0, screen->buf_size);
301 if( IS_PLAYING(status->state) || IS_PAUSED(status->state) )
302 {
303 if( status->totalTime > 0 )
304 {
305 if( c->song && seek_id == c->song->id )
306 elapsedTime = seek_target_time;
307 g_snprintf(screen->buf, screen->buf_size,
308 " [%i:%02i/%i:%02i]",
309 elapsedTime/60, elapsedTime%60,
310 status->totalTime/60, status->totalTime%60 );
311 }
312 else
313 {
314 g_snprintf(screen->buf, screen->buf_size,
315 " [%d kbps]", status->bitRate );
316 }
317 }
318 else
319 {
320 time_t timep;
322 time(&timep);
323 strftime(screen->buf, screen->buf_size, "%X ",localtime(&timep));
324 }
326 /* display song */
327 if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) )
328 {
329 char songname[MAX_SONGNAME_LENGTH];
330 int width = COLS-x-strlen(screen->buf);
332 if( song )
333 strfsong(songname, MAX_SONGNAME_LENGTH, STATUS_FORMAT, song);
334 else
335 songname[0] = '\0';
337 colors_use(w, COLOR_STATUS);
338 /* scroll if the song name is to long */
339 if( strlen(songname) > width )
340 {
341 static scroll_state_t st = { 0, 0 };
342 char *tmp = strscroll(songname, " *** ", width, &st);
344 g_strlcpy(songname, tmp, MAX_SONGNAME_LENGTH);
345 g_free(tmp);
346 }
347 mvwaddnstr(w, 0, x, songname, width);
348 }
350 /* display time string */
351 if( screen->buf[0] )
352 {
353 x = screen->status_window.cols - strlen(screen->buf);
354 colors_use(w, COLOR_STATUS_TIME);
355 mvwaddstr(w, 0, x, screen->buf);
356 }
358 wnoutrefresh(w);
359 }
361 int
362 screen_exit(void)
363 {
364 endwin();
365 if( screen )
366 {
367 gint i;
369 /* close and exit all screens (playlist,browse,help...) */
370 i=0;
371 while( screens[i].get_mode_functions )
372 {
373 screen_functions_t *mode_fn = screens[i].get_mode_functions();
375 if( mode_fn && mode_fn->close )
376 mode_fn->close();
377 if( mode_fn && mode_fn->exit )
378 mode_fn->exit();
380 i++;
381 }
383 string_list_free(screen->find_history);
384 g_free(screen->buf);
385 g_free(screen->findbuf);
387 g_free(screen);
388 screen = NULL;
389 }
390 return 0;
391 }
393 void
394 screen_resize(void)
395 {
396 gint i;
398 D("Resize rows %d->%d, cols %d->%d\n",screen->rows,LINES,screen->cols,COLS);
399 if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
400 {
401 screen_exit();
402 fprintf(stderr, _("Error: Screen to small!\n"));
403 exit(EXIT_FAILURE);
404 }
406 resizeterm(LINES, COLS);
408 screen->cols = COLS;
409 screen->rows = LINES;
411 /* top window */
412 screen->top_window.cols = screen->cols;
413 wresize(screen->top_window.w, 2, screen->cols);
415 /* main window */
416 screen->main_window.cols = screen->cols;
417 screen->main_window.rows = screen->rows-4;
418 wresize(screen->main_window.w, screen->main_window.rows, screen->cols);
419 wclear(screen->main_window.w);
421 /* progress window */
422 screen->progress_window.cols = screen->cols;
423 wresize(screen->progress_window.w, 1, screen->cols);
424 mvwin(screen->progress_window.w, screen->rows-2, 0);
426 /* status window */
427 screen->status_window.cols = screen->cols;
428 wresize(screen->status_window.w, 1, screen->cols);
429 mvwin(screen->status_window.w, screen->rows-1, 0);
431 screen->buf_size = screen->cols;
432 g_free(screen->buf);
433 screen->buf = g_malloc(screen->cols);
435 /* close and exit all screens (playlist,browse,help...) */
436 i=0;
437 while( screens[i].get_mode_functions )
438 {
439 screen_functions_t *mode_fn = screens[i].get_mode_functions();
441 if( mode_fn && mode_fn->resize )
442 mode_fn->resize(screen->main_window.cols, screen->main_window.rows);
444 i++;
445 }
447 /* ? - without this the cursor becomes visible with aterm & Eterm */
448 curs_set(1);
449 curs_set(0);
451 screen->painted = 0;
452 }
454 void
455 screen_status_message(char *msg)
456 {
457 WINDOW *w = screen->status_window.w;
459 wmove(w, 0, 0);
460 wclrtoeol(w);
461 colors_use(w, COLOR_STATUS_ALERT);
462 waddstr(w, msg);
463 wnoutrefresh(w);
464 screen->status_timestamp = time(NULL);
465 }
467 void
468 screen_status_printf(char *format, ...)
469 {
470 char *msg;
471 va_list ap;
473 va_start(ap,format);
474 msg = g_strdup_vprintf(format,ap);
475 va_end(ap);
476 screen_status_message(msg);
477 g_free(msg);
478 }
480 int
481 screen_init(mpdclient_t *c)
482 {
483 gint i;
485 /* initialize the curses library */
486 initscr();
487 /* initialize color support */
488 colors_start();
489 /* tell curses not to do NL->CR/NL on output */
490 nonl();
491 /* use raw mode (ignore interrupt,quit,suspend, and flow control ) */
492 #ifdef ENABLE_RAW_MODE
493 raw();
494 #endif
495 /* don't echo input */
496 noecho();
497 /* set cursor invisible */
498 curs_set(0);
499 /* enable extra keys */
500 keypad(stdscr, TRUE);
501 /* return from getch() without blocking */
502 timeout(SCREEN_TIMEOUT);
503 /* initialize mouse support */
504 #ifdef HAVE_GETMOUSE
505 if( options.enable_mouse )
506 mousemask(ALL_MOUSE_EVENTS, NULL);
507 #endif
509 if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
510 {
511 fprintf(stderr, _("Error: Screen to small!\n"));
512 exit(EXIT_FAILURE);
513 }
515 screen = g_malloc(sizeof(screen_t));
516 memset(screen, 0, sizeof(screen_t));
517 screen->mode = 0;
518 screen->cols = COLS;
519 screen->rows = LINES;
520 screen->buf = g_malloc(screen->cols);
521 screen->buf_size = screen->cols;
522 screen->findbuf = NULL;
523 screen->painted = 0;
524 screen->start_timestamp = time(NULL);
525 screen->input_timestamp = time(NULL);
526 screen->last_cmd = CMD_NONE;
528 /* create top window */
529 screen->top_window.rows = 2;
530 screen->top_window.cols = screen->cols;
531 screen->top_window.w = newwin(screen->top_window.rows,
532 screen->top_window.cols,
533 0, 0);
534 leaveok(screen->top_window.w, TRUE);
535 keypad(screen->top_window.w, TRUE);
537 /* create main window */
538 screen->main_window.rows = screen->rows-4;
539 screen->main_window.cols = screen->cols;
540 screen->main_window.w = newwin(screen->main_window.rows,
541 screen->main_window.cols,
542 2,
543 0);
545 // leaveok(screen->main_window.w, TRUE); temporary disabled
546 keypad(screen->main_window.w, TRUE);
548 /* create progress window */
549 screen->progress_window.rows = 1;
550 screen->progress_window.cols = screen->cols;
551 screen->progress_window.w = newwin(screen->progress_window.rows,
552 screen->progress_window.cols,
553 screen->rows-2,
554 0);
555 leaveok(screen->progress_window.w, TRUE);
557 /* create status window */
558 screen->status_window.rows = 1;
559 screen->status_window.cols = screen->cols;
560 screen->status_window.w = newwin(screen->status_window.rows,
561 screen->status_window.cols,
562 screen->rows-1,
563 0);
565 leaveok(screen->status_window.w, FALSE);
566 keypad(screen->status_window.w, TRUE);
568 if( options.enable_colors )
569 {
570 /* set background attributes */
571 wbkgd(stdscr, COLOR_PAIR(COLOR_LIST));
572 wbkgd(screen->main_window.w, COLOR_PAIR(COLOR_LIST));
573 wbkgd(screen->top_window.w, COLOR_PAIR(COLOR_TITLE));
574 wbkgd(screen->progress_window.w, COLOR_PAIR(COLOR_PROGRESSBAR));
575 wbkgd(screen->status_window.w, COLOR_PAIR(COLOR_STATUS));
576 colors_use(screen->progress_window.w, COLOR_PROGRESSBAR);
577 }
579 /* initialize screens */
580 i=0;
581 while( screens[i].get_mode_functions )
582 {
583 screen_functions_t *fn = screens[i].get_mode_functions();
585 if( fn && fn->init )
586 fn->init(screen->main_window.w,
587 screen->main_window.cols,
588 screen->main_window.rows);
590 i++;
591 }
593 mode_fn = get_screen_playlist();
594 if( mode_fn && mode_fn->open )
595 mode_fn->open(screen, c);
597 /* initialize wreadln */
598 wrln_wgetch = my_wgetch;
599 wrln_max_history_length = 16;
601 return 0;
602 }
604 void
605 screen_paint(mpdclient_t *c)
606 {
607 char *title = NULL;
609 if( mode_fn && mode_fn->get_title )
610 title = mode_fn->get_title(screen->buf,screen->buf_size);
612 D("screen_paint(%s)\n", title);
613 /* paint the title/header window */
614 if( title )
615 paint_top_window(title, c, 1);
616 else
617 paint_top_window("", c, 1);
619 /* paint the main window */
620 wclear(screen->main_window.w);
621 if( mode_fn && mode_fn->paint )
622 mode_fn->paint(screen, c);
624 paint_progress_window(c);
625 paint_status_window(c);
626 screen->painted = 1;
627 wmove(screen->main_window.w, 0, 0);
628 wnoutrefresh(screen->main_window.w);
630 /* tell curses to update */
631 doupdate();
632 }
634 void
635 screen_update(mpdclient_t *c)
636 {
637 static int repeat = -1;
638 static int random = -1;
639 static int crossfade = -1;
640 static int dbupdate = -1;
641 list_window_t *lw = NULL;
643 if( !screen->painted )
644 return screen_paint(c);
646 /* print a message if mpd status has changed */
647 if( repeat<0 )
648 {
649 repeat = c->status->repeat;
650 random = c->status->random;
651 crossfade = c->status->crossfade;
652 dbupdate = c->status->updatingDb;
653 }
654 if( repeat != c->status->repeat )
655 screen_status_printf(c->status->repeat ?
656 _("Repeat is on") :
657 _("Repeat is off"));
658 if( random != c->status->random )
659 screen_status_printf(c->status->random ?
660 _("Random is on") :
661 _("Random is off"));
663 if( crossfade != c->status->crossfade )
664 screen_status_printf(_("Crossfade %d seconds"), c->status->crossfade);
665 if( dbupdate && dbupdate != c->status->updatingDb )
666 {
667 screen_status_printf(_("Database updated!"));
668 mpdclient_browse_callback(c, BROWSE_DB_UPDATED, NULL);
669 }
671 repeat = c->status->repeat;
672 random = c->status->random;
673 crossfade = c->status->crossfade;
674 dbupdate = c->status->updatingDb;
676 /* update title/header window */
677 if( welcome && screen->last_cmd==CMD_NONE &&
678 time(NULL)-screen->start_timestamp <= SCREEN_WELCOME_TIME)
679 paint_top_window("", c, 0);
680 else if( mode_fn && mode_fn->get_title )
681 {
682 paint_top_window(mode_fn->get_title(screen->buf,screen->buf_size), c, 0);
683 welcome = FALSE;
684 }
685 else
686 paint_top_window("", c, 0);
688 /* update the main window */
689 if( mode_fn && mode_fn->paint )
690 mode_fn->update(screen, c);
692 if( mode_fn && mode_fn->get_lw )
693 lw = mode_fn->get_lw();
695 /* update progress window */
696 paint_progress_window(c);
698 /* update status window */
699 paint_status_window(c);
701 /* move the cursor to the selected row in the main window */
702 if( lw )
703 wmove(screen->main_window.w, LW_ROW(lw), 0);
704 else
705 wmove(screen->main_window.w, 0, 0);
706 wnoutrefresh(screen->main_window.w);
708 /* tell curses to update */
709 doupdate();
710 }
712 void
713 screen_idle(mpdclient_t *c)
714 {
715 if( c->song && seek_id == c->song->id &&
716 (screen->last_cmd == CMD_SEEK_FORWARD ||
717 screen->last_cmd == CMD_SEEK_BACKWARD) )
718 {
719 mpdclient_cmd_seek(c, seek_id, seek_target_time);
720 }
722 screen->last_cmd = CMD_NONE;
723 seek_id = -1;
724 }
726 #ifdef HAVE_GETMOUSE
727 int
728 screen_get_mouse_event(mpdclient_t *c,
729 list_window_t *lw, int lw_length,
730 unsigned long *bstate, int *row)
731 {
732 MEVENT event;
734 /* retreive the mouse event from ncurses */
735 getmouse(&event);
736 D("mouse: id=%d y=%d,x=%d,z=%d\n",event.id,event.y,event.x,event.z);
737 /* calculate the selected row in the list window */
738 *row = event.y - screen->top_window.rows;
739 /* copy button state bits */
740 *bstate = event.bstate;
741 /* if button 2 was pressed switch screen */
742 if( event.bstate & BUTTON2_CLICKED )
743 {
744 screen_cmd(c, CMD_SCREEN_NEXT);
745 return 1;
746 }
747 /* if the even occured above the list window move up */
748 if( *row<0 && lw )
749 {
750 if( event.bstate & BUTTON3_CLICKED )
751 list_window_first(lw);
752 else
753 list_window_previous_page(lw);
754 return 1;
755 }
756 /* if the even occured below the list window move down */
757 if( *row>=lw->rows && lw )
758 {
759 if( event.bstate & BUTTON3_CLICKED )
760 list_window_last(lw, lw_length);
761 else
762 list_window_next_page(lw, lw_length);
763 return 1;
764 }
765 return 0;
766 }
767 #endif
769 void
770 screen_cmd(mpdclient_t *c, command_t cmd)
771 {
772 screen->input_timestamp = time(NULL);
773 screen->last_cmd = cmd;
774 welcome = FALSE;
776 if( mode_fn && mode_fn->cmd && mode_fn->cmd(screen, c, cmd) )
777 return;
779 switch(cmd)
780 {
781 case CMD_PLAY:
782 mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
783 break;
784 case CMD_PAUSE:
785 mpdclient_cmd_pause(c, !IS_PAUSED(c->status->state));
786 break;
787 case CMD_STOP:
788 mpdclient_cmd_stop(c);
789 break;
790 case CMD_SEEK_FORWARD:
791 if( !IS_STOPPED(c->status->state) )
792 {
793 if( c->song && seek_id != c->song->id )
794 {
795 seek_id = c->song->id;
796 seek_target_time = c->status->elapsedTime;
797 }
798 seek_target_time+=options.seek_time;
799 if( seek_target_time < c->status->totalTime )
800 break;
801 seek_target_time = c->status->totalTime;
802 /* seek_target_time=0; */
803 }
804 break;
805 /* fall through... */
806 case CMD_TRACK_NEXT:
807 if( !IS_STOPPED(c->status->state) )
808 mpdclient_cmd_next(c);
809 break;
810 case CMD_SEEK_BACKWARD:
811 if( !IS_STOPPED(c->status->state) )
812 {
813 if( seek_id != c->song->id )
814 {
815 seek_id = c->song->id;
816 seek_target_time = c->status->elapsedTime;
817 }
818 seek_target_time-=options.seek_time;
819 if( seek_target_time < 0 )
820 seek_target_time=0;
821 }
822 break;
823 case CMD_TRACK_PREVIOUS:
824 if( !IS_STOPPED(c->status->state) )
825 mpdclient_cmd_prev(c);
826 break;
827 case CMD_SHUFFLE:
828 if( mpdclient_cmd_shuffle(c) == 0 )
829 screen_status_message(_("Shuffled playlist!"));
830 break;
831 case CMD_CLEAR:
832 if( mpdclient_cmd_clear(c) == 0 )
833 screen_status_message(_("Cleared playlist!"));
834 break;
835 case CMD_REPEAT:
836 mpdclient_cmd_repeat(c, !c->status->repeat);
837 break;
838 case CMD_RANDOM:
839 mpdclient_cmd_random(c, !c->status->random);
840 break;
841 case CMD_CROSSFADE:
842 if( c->status->crossfade )
843 mpdclient_cmd_crossfade(c, 0);
844 else
845 mpdclient_cmd_crossfade(c, options.crossfade_time);
846 break;
847 case CMD_DB_UPDATE:
848 if( !c->status->updatingDb )
849 {
850 if( mpdclient_cmd_db_update_utf8(c,NULL)==0 )
851 screen_status_printf(_("Database update started!"));
852 }
853 else
854 screen_status_printf(_("Database update running..."));
855 break;
856 case CMD_VOLUME_UP:
857 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
858 mpdclient_cmd_volume(c, ++c->status->volume);
859 break;
860 case CMD_VOLUME_DOWN:
861 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
862 mpdclient_cmd_volume(c, --c->status->volume);
863 break;
864 case CMD_TOGGLE_FIND_WRAP:
865 options.find_wrap = !options.find_wrap;
866 screen_status_printf(options.find_wrap ?
867 _("Find mode: Wrapped") :
868 _("Find mode: Normal"));
869 break;
870 case CMD_TOGGLE_AUTOCENTER:
871 options.auto_center = !options.auto_center;
872 screen_status_printf(options.auto_center ?
873 _("Auto center mode: On") :
874 _("Auto center mode: Off"));
875 break;
876 case CMD_SCREEN_UPDATE:
877 screen->painted = 0;
878 break;
879 case CMD_SCREEN_PREVIOUS:
880 if( screen->mode > 0 )
881 switch_screen_mode(screens[screen->mode-1].id, c);
882 else
883 switch_screen_mode(lookup_mode(SCREEN_HELP_ID)-1, c);
884 break;
885 case CMD_SCREEN_NEXT:
886 if( screens[screen->mode+1].id < SCREEN_HELP_ID )
887 switch_screen_mode(screens[screen->mode+1].id, c);
888 else
889 switch_screen_mode(screens[0].id, c);
890 break;
891 case CMD_SCREEN_PLAY:
892 switch_screen_mode(SCREEN_PLAYLIST_ID, c);
893 break;
894 case CMD_SCREEN_FILE:
895 switch_screen_mode(SCREEN_BROWSE_ID, c);
896 break;
897 case CMD_SCREEN_HELP:
898 switch_screen_mode(SCREEN_HELP_ID, c);
899 break;
900 case CMD_SCREEN_SEARCH:
901 switch_screen_mode(SCREEN_SEARCH_ID, c);
902 break;
903 case CMD_SCREEN_ARTIST:
904 switch_screen_mode(SCREEN_ARTIST_ID, c);
905 break;
906 case CMD_SCREEN_KEYDEF:
907 switch_screen_mode(SCREEN_KEYDEF_ID, c);
908 break;
909 case CMD_SCREEN_CLOCK:
910 switch_screen_mode(SCREEN_CLOCK_ID, c);
911 break;
912 case CMD_QUIT:
913 exit(EXIT_SUCCESS);
914 default:
915 break;
916 }
917 }