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 #ifdef ENABLE_ARTIST_SCREEN
78 { SCREEN_ARTIST_ID, "artist", get_screen_artist },
79 #endif
80 { SCREEN_HELP_ID, "help", get_screen_help },
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 gint
100 screen_get_id(char *name)
101 {
102 gint i=0;
104 while( screens[i].name )
105 {
106 if( strcmp(name, screens[i].name) == 0 )
107 return screens[i].id;
108 i++;
109 }
110 return -1;
111 }
113 static gint
114 lookup_mode(gint id)
115 {
116 gint i=0;
118 while( screens[i].name )
119 {
120 if( screens[i].id == id )
121 return i;
122 i++;
123 }
124 return -1;
125 }
127 static void
128 switch_screen_mode(gint id, mpdclient_t *c)
129 {
130 gint new_mode;
132 if( id == screens[screen->mode].id )
133 return;
135 /* close the old mode */
136 if( mode_fn && mode_fn->close )
137 mode_fn->close();
139 /* get functions for the new mode */
140 new_mode = lookup_mode(id);
141 if( new_mode>=0 && screens[new_mode].get_mode_functions )
142 {
143 D("switch_screen(%s)\n", screens[new_mode].name );
144 mode_fn = screens[new_mode].get_mode_functions();
145 screen->mode = new_mode;
146 }
148 screen->painted = 0;
150 /* open the new mode */
151 if( mode_fn && mode_fn->open )
152 mode_fn->open(screen, c);
154 }
156 static void
157 screen_next_mode(mpdclient_t *c, int offset)
158 {
159 int max = g_strv_length(options.screen_list);
160 int current, next;
161 int i;
163 /* find current screen */
164 current = -1;
165 i = 0;
166 while( options.screen_list[i] )
167 {
168 if( strcmp(options.screen_list[i], screens[screen->mode].name) == 0 )
169 current = i;
170 i++;
171 }
172 next = current + offset;
173 if( next<0 )
174 next = max-1;
175 else if( next>=max )
176 next = 0;
178 D("current mode: %d:%d next:%d\n", current, max, next);
179 switch_screen_mode(screen_get_id(options.screen_list[next]), c);
180 }
182 static void
183 paint_top_window(char *header, mpdclient_t *c, int clear)
184 {
185 char flags[5];
186 static int prev_volume = -1;
187 static int prev_header_len = -1;
188 WINDOW *w = screen->top_window.w;
190 if(prev_header_len!=strlen(header))
191 {
192 prev_header_len = strlen(header);
193 clear = 1;
194 }
196 if(clear)
197 {
198 wmove(w, 0, 0);
199 wclrtoeol(w);
200 }
202 if(prev_volume!=c->status->volume || clear)
203 {
204 char buf[32];
206 if( header[0] )
207 {
208 colors_use(w, COLOR_TITLE_BOLD);
209 mvwaddstr(w, 0, 0, header);
210 }
211 else
212 {
213 colors_use(w, COLOR_TITLE_BOLD);
214 waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE));
215 colors_use(w, COLOR_TITLE);
216 waddstr(w, _(":Help "));
217 colors_use(w, COLOR_TITLE_BOLD);
218 waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE));
219 colors_use(w, COLOR_TITLE);
220 waddstr(w, _(":Playlist "));
221 colors_use(w, COLOR_TITLE_BOLD);
222 waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE));
223 colors_use(w, COLOR_TITLE);
224 waddstr(w, _(":Browse "));
225 #ifdef ENABLE_ARTIST_SCREEN
226 colors_use(w, COLOR_TITLE_BOLD);
227 waddstr(w, get_key_names(CMD_SCREEN_ARTIST, FALSE));
228 colors_use(w, COLOR_TITLE);
229 waddstr(w, _(":Artist "));
230 #endif
231 #ifdef ENABLE_SEARCH_SCREEN
232 colors_use(w, COLOR_TITLE_BOLD);
233 waddstr(w, get_key_names(CMD_SCREEN_SEARCH, FALSE));
234 colors_use(w, COLOR_TITLE);
235 waddstr(w, _(":Search "));
236 #endif
237 }
238 if( c->status->volume==MPD_STATUS_NO_VOLUME )
239 {
240 g_snprintf(buf, 32, _("Volume n/a "));
241 }
242 else
243 {
244 g_snprintf(buf, 32, _(" Volume %d%%"), c->status->volume);
245 }
246 colors_use(w, COLOR_TITLE);
247 mvwaddstr(w, 0, screen->top_window.cols-strlen(buf), buf);
249 flags[0] = 0;
250 if( c->status->repeat )
251 g_strlcat(flags, "r", sizeof(flags));
252 if( c->status->random )
253 g_strlcat(flags, "z", sizeof(flags));;
254 if( c->status->crossfade )
255 g_strlcat(flags, "x", sizeof(flags));
256 if( c->status->updatingDb )
257 g_strlcat(flags, "U", sizeof(flags));
258 colors_use(w, COLOR_LINE);
259 mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols);
260 if( flags[0] )
261 {
262 wmove(w,1,screen->top_window.cols-strlen(flags)-3);
263 waddch(w, '[');
264 colors_use(w, COLOR_LINE_BOLD);
265 waddstr(w, flags);
266 colors_use(w, COLOR_LINE);
267 waddch(w, ']');
268 }
269 wnoutrefresh(w);
270 }
271 }
273 static void
274 paint_progress_window(mpdclient_t *c)
275 {
276 double p;
277 int width;
278 int elapsedTime = c->status->elapsedTime;
280 if( c->status==NULL || IS_STOPPED(c->status->state) )
281 {
282 mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE,
283 screen->progress_window.cols);
284 wnoutrefresh(screen->progress_window.w);
285 return;
286 }
288 if( c->song && seek_id == c->song->id )
289 elapsedTime = seek_target_time;
291 p = ((double) elapsedTime) / ((double) c->status->totalTime);
293 width = (int) (p * (double) screen->progress_window.cols);
294 mvwhline(screen->progress_window.w,
295 0, 0,
296 ACS_HLINE,
297 screen->progress_window.cols);
298 whline(screen->progress_window.w, '=', width-1);
299 mvwaddch(screen->progress_window.w, 0, width-1, 'O');
300 wnoutrefresh(screen->progress_window.w);
301 }
303 static void
304 paint_status_window(mpdclient_t *c)
305 {
306 WINDOW *w = screen->status_window.w;
307 mpd_Status *status = c->status;
308 mpd_Song *song = c->song;
309 int elapsedTime = 0;
310 char *str = NULL;
311 char *timestr = NULL;
312 int x = 0;
314 if( time(NULL) - screen->status_timestamp <= SCREEN_STATUS_MESSAGE_TIME )
315 return;
317 wmove(w, 0, 0);
318 wclrtoeol(w);
319 colors_use(w, COLOR_STATUS_BOLD);
321 switch(status->state)
322 {
323 case MPD_STATUS_STATE_PLAY:
324 str = _("Playing:");
325 break;
326 case MPD_STATUS_STATE_PAUSE:
327 str = _("[Paused]");
328 break;
329 case MPD_STATUS_STATE_STOP:
330 default:
331 break;
332 }
334 if( str )
335 {
336 waddstr(w, str);
337 x += strlen(str)+1;
338 }
340 /* create time string */
341 memset(screen->buf, 0, screen->buf_size);
342 if( IS_PLAYING(status->state) || IS_PAUSED(status->state) )
343 {
344 if( status->totalTime > 0 )
345 {
347 /*checks the conf to see whether to display elapsed or remaining time */
348 if(!strcmp(options.timedisplay_type,"elapsed"))
349 {
350 timestr= " [%i:%02i/%i:%02i]";
351 elapsedTime = c->status->elapsedTime;
352 }
353 else if(!strcmp(options.timedisplay_type,"remaining"))
354 {
355 timestr= " [-%i:%02i/%i:%02i]";
356 elapsedTime = (c->status->totalTime - c->status->elapsedTime);
357 }
358 if( c->song && seek_id == c->song->id )
359 elapsedTime = seek_target_time;
360 /*write out the time*/
361 g_snprintf(screen->buf, screen->buf_size,
362 timestr,
363 elapsedTime/60, elapsedTime%60,
364 status->totalTime/60, status->totalTime%60 );
365 }
366 else
367 {
368 g_snprintf(screen->buf, screen->buf_size,
369 " [%d kbps]", status->bitRate );
370 }
371 }
372 else
373 {
374 time_t timep;
376 time(&timep);
377 strftime(screen->buf, screen->buf_size, "%X ",localtime(&timep));
378 }
380 /* display song */
381 if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) )
382 {
383 char songname[MAX_SONGNAME_LENGTH];
384 int width = COLS-x-strlen(screen->buf);
386 if( song )
387 strfsong(songname, MAX_SONGNAME_LENGTH, STATUS_FORMAT, song);
388 else
389 songname[0] = '\0';
391 colors_use(w, COLOR_STATUS);
392 /* scroll if the song name is to long */
393 if( strlen(songname) > width )
394 {
395 static scroll_state_t st = { 0, 0 };
396 char *tmp = strscroll(songname, " *** ", width, &st);
398 g_strlcpy(songname, tmp, MAX_SONGNAME_LENGTH);
399 g_free(tmp);
400 }
401 mvwaddnstr(w, 0, x, songname, width);
402 }
404 /* display time string */
405 if( screen->buf[0] )
406 {
407 x = screen->status_window.cols - strlen(screen->buf);
408 colors_use(w, COLOR_STATUS_TIME);
409 mvwaddstr(w, 0, x, screen->buf);
410 }
412 wnoutrefresh(w);
413 }
415 int
416 screen_exit(void)
417 {
418 endwin();
419 if( screen )
420 {
421 gint i;
423 /* close and exit all screens (playlist,browse,help...) */
424 i=0;
425 while( screens[i].get_mode_functions )
426 {
427 screen_functions_t *mode_fn = screens[i].get_mode_functions();
429 if( mode_fn && mode_fn->close )
430 mode_fn->close();
431 if( mode_fn && mode_fn->exit )
432 mode_fn->exit();
434 i++;
435 }
437 string_list_free(screen->find_history);
438 g_free(screen->buf);
439 g_free(screen->findbuf);
441 g_free(screen);
442 screen = NULL;
443 }
444 return 0;
445 }
447 void
448 screen_resize(void)
449 {
450 gint i;
452 D("Resize rows %d->%d, cols %d->%d\n",screen->rows,LINES,screen->cols,COLS);
453 if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
454 {
455 screen_exit();
456 fprintf(stderr, _("Error: Screen to small!\n"));
457 exit(EXIT_FAILURE);
458 }
460 resizeterm(LINES, COLS);
462 screen->cols = COLS;
463 screen->rows = LINES;
465 /* top window */
466 screen->top_window.cols = screen->cols;
467 wresize(screen->top_window.w, 2, screen->cols);
469 /* main window */
470 screen->main_window.cols = screen->cols;
471 screen->main_window.rows = screen->rows-4;
472 wresize(screen->main_window.w, screen->main_window.rows, screen->cols);
473 wclear(screen->main_window.w);
475 /* progress window */
476 screen->progress_window.cols = screen->cols;
477 wresize(screen->progress_window.w, 1, screen->cols);
478 mvwin(screen->progress_window.w, screen->rows-2, 0);
480 /* status window */
481 screen->status_window.cols = screen->cols;
482 wresize(screen->status_window.w, 1, screen->cols);
483 mvwin(screen->status_window.w, screen->rows-1, 0);
485 screen->buf_size = screen->cols;
486 g_free(screen->buf);
487 screen->buf = g_malloc(screen->cols);
489 /* close and exit all screens (playlist,browse,help...) */
490 i=0;
491 while( screens[i].get_mode_functions )
492 {
493 screen_functions_t *mode_fn = screens[i].get_mode_functions();
495 if( mode_fn && mode_fn->resize )
496 mode_fn->resize(screen->main_window.cols, screen->main_window.rows);
498 i++;
499 }
501 /* ? - without this the cursor becomes visible with aterm & Eterm */
502 curs_set(1);
503 curs_set(0);
505 screen->painted = 0;
506 }
508 void
509 screen_status_message(char *msg)
510 {
511 WINDOW *w = screen->status_window.w;
513 wmove(w, 0, 0);
514 wclrtoeol(w);
515 colors_use(w, COLOR_STATUS_ALERT);
516 waddstr(w, msg);
517 wnoutrefresh(w);
518 screen->status_timestamp = time(NULL);
519 }
521 void
522 screen_status_printf(char *format, ...)
523 {
524 char *msg;
525 va_list ap;
527 va_start(ap,format);
528 msg = g_strdup_vprintf(format,ap);
529 va_end(ap);
530 screen_status_message(msg);
531 g_free(msg);
532 }
534 int
535 screen_init(mpdclient_t *c)
536 {
537 gint i;
539 /* initialize the curses library */
540 initscr();
541 /* initialize color support */
542 colors_start();
543 /* tell curses not to do NL->CR/NL on output */
544 nonl();
545 /* use raw mode (ignore interrupt,quit,suspend, and flow control ) */
546 #ifdef ENABLE_RAW_MODE
547 raw();
548 #endif
549 /* don't echo input */
550 noecho();
551 /* set cursor invisible */
552 curs_set(0);
553 /* enable extra keys */
554 keypad(stdscr, TRUE);
555 /* return from getch() without blocking */
556 timeout(SCREEN_TIMEOUT);
557 /* initialize mouse support */
558 #ifdef HAVE_GETMOUSE
559 if( options.enable_mouse )
560 mousemask(ALL_MOUSE_EVENTS, NULL);
561 #endif
563 if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
564 {
565 fprintf(stderr, _("Error: Screen to small!\n"));
566 exit(EXIT_FAILURE);
567 }
569 screen = g_malloc(sizeof(screen_t));
570 memset(screen, 0, sizeof(screen_t));
571 screen->mode = 0;
572 screen->cols = COLS;
573 screen->rows = LINES;
574 screen->buf = g_malloc(screen->cols);
575 screen->buf_size = screen->cols;
576 screen->findbuf = NULL;
577 screen->painted = 0;
578 screen->start_timestamp = time(NULL);
579 screen->input_timestamp = time(NULL);
580 screen->last_cmd = CMD_NONE;
582 /* create top window */
583 screen->top_window.rows = 2;
584 screen->top_window.cols = screen->cols;
585 screen->top_window.w = newwin(screen->top_window.rows,
586 screen->top_window.cols,
587 0, 0);
588 leaveok(screen->top_window.w, TRUE);
589 keypad(screen->top_window.w, TRUE);
591 /* create main window */
592 screen->main_window.rows = screen->rows-4;
593 screen->main_window.cols = screen->cols;
594 screen->main_window.w = newwin(screen->main_window.rows,
595 screen->main_window.cols,
596 2,
597 0);
599 // leaveok(screen->main_window.w, TRUE); temporary disabled
600 keypad(screen->main_window.w, TRUE);
602 /* create progress window */
603 screen->progress_window.rows = 1;
604 screen->progress_window.cols = screen->cols;
605 screen->progress_window.w = newwin(screen->progress_window.rows,
606 screen->progress_window.cols,
607 screen->rows-2,
608 0);
609 leaveok(screen->progress_window.w, TRUE);
611 /* create status window */
612 screen->status_window.rows = 1;
613 screen->status_window.cols = screen->cols;
614 screen->status_window.w = newwin(screen->status_window.rows,
615 screen->status_window.cols,
616 screen->rows-1,
617 0);
619 leaveok(screen->status_window.w, FALSE);
620 keypad(screen->status_window.w, TRUE);
622 if( options.enable_colors )
623 {
624 /* set background attributes */
625 wbkgd(stdscr, COLOR_PAIR(COLOR_LIST));
626 wbkgd(screen->main_window.w, COLOR_PAIR(COLOR_LIST));
627 wbkgd(screen->top_window.w, COLOR_PAIR(COLOR_TITLE));
628 wbkgd(screen->progress_window.w, COLOR_PAIR(COLOR_PROGRESSBAR));
629 wbkgd(screen->status_window.w, COLOR_PAIR(COLOR_STATUS));
630 colors_use(screen->progress_window.w, COLOR_PROGRESSBAR);
631 }
633 /* initialize screens */
634 i=0;
635 while( screens[i].get_mode_functions )
636 {
637 screen_functions_t *fn = screens[i].get_mode_functions();
639 if( fn && fn->init )
640 fn->init(screen->main_window.w,
641 screen->main_window.cols,
642 screen->main_window.rows);
644 i++;
645 }
647 #if 0
648 /* broken */
649 mode_fn = NULL;
650 switch_screen_mode(screen_get_id(options.screen_list[0]), c);
651 #else
652 mode_fn = get_screen_playlist();
653 #endif
655 if( mode_fn && mode_fn->open )
656 mode_fn->open(screen, c);
658 /* initialize wreadln */
659 wrln_wgetch = my_wgetch;
660 wrln_max_history_length = 16;
662 return 0;
663 }
665 void
666 screen_paint(mpdclient_t *c)
667 {
668 char *title = NULL;
670 if( mode_fn && mode_fn->get_title )
671 title = mode_fn->get_title(screen->buf,screen->buf_size);
673 D("screen_paint(%s)\n", title);
674 /* paint the title/header window */
675 if( title )
676 paint_top_window(title, c, 1);
677 else
678 paint_top_window("", c, 1);
680 /* paint the main window */
681 wclear(screen->main_window.w);
682 if( mode_fn && mode_fn->paint )
683 mode_fn->paint(screen, c);
685 paint_progress_window(c);
686 paint_status_window(c);
687 screen->painted = 1;
688 wmove(screen->main_window.w, 0, 0);
689 wnoutrefresh(screen->main_window.w);
691 /* tell curses to update */
692 doupdate();
693 }
695 void
696 screen_update(mpdclient_t *c)
697 {
698 static int repeat = -1;
699 static int random = -1;
700 static int crossfade = -1;
701 static int dbupdate = -1;
702 list_window_t *lw = NULL;
704 if( !screen->painted )
705 return screen_paint(c);
707 /* print a message if mpd status has changed */
708 if( repeat<0 )
709 {
710 repeat = c->status->repeat;
711 random = c->status->random;
712 crossfade = c->status->crossfade;
713 dbupdate = c->status->updatingDb;
714 }
715 if( repeat != c->status->repeat )
716 screen_status_printf(c->status->repeat ?
717 _("Repeat is on") :
718 _("Repeat is off"));
719 if( random != c->status->random )
720 screen_status_printf(c->status->random ?
721 _("Random is on") :
722 _("Random is off"));
724 if( crossfade != c->status->crossfade )
725 screen_status_printf(_("Crossfade %d seconds"), c->status->crossfade);
726 if( dbupdate && dbupdate != c->status->updatingDb )
727 {
728 screen_status_printf(_("Database updated!"));
729 mpdclient_browse_callback(c, BROWSE_DB_UPDATED, NULL);
730 }
732 repeat = c->status->repeat;
733 random = c->status->random;
734 crossfade = c->status->crossfade;
735 dbupdate = c->status->updatingDb;
737 /* update title/header window */
738 if( welcome && screen->last_cmd==CMD_NONE &&
739 time(NULL)-screen->start_timestamp <= SCREEN_WELCOME_TIME)
740 paint_top_window("", c, 0);
741 else if( mode_fn && mode_fn->get_title )
742 {
743 paint_top_window(mode_fn->get_title(screen->buf,screen->buf_size), c, 0);
744 welcome = FALSE;
745 }
746 else
747 paint_top_window("", c, 0);
749 /* update the main window */
750 if( mode_fn && mode_fn->paint )
751 mode_fn->update(screen, c);
753 if( mode_fn && mode_fn->get_lw )
754 lw = mode_fn->get_lw();
756 /* update progress window */
757 paint_progress_window(c);
759 /* update status window */
760 paint_status_window(c);
762 /* move the cursor to the selected row in the main window */
763 if( lw )
764 wmove(screen->main_window.w, LW_ROW(lw), 0);
765 else
766 wmove(screen->main_window.w, 0, 0);
767 wnoutrefresh(screen->main_window.w);
769 /* tell curses to update */
770 doupdate();
771 }
773 void
774 screen_idle(mpdclient_t *c)
775 {
776 if( c->song && seek_id == c->song->id &&
777 (screen->last_cmd == CMD_SEEK_FORWARD ||
778 screen->last_cmd == CMD_SEEK_BACKWARD) )
779 {
780 mpdclient_cmd_seek(c, seek_id, seek_target_time);
781 }
783 screen->last_cmd = CMD_NONE;
784 seek_id = -1;
785 }
787 #ifdef HAVE_GETMOUSE
788 int
789 screen_get_mouse_event(mpdclient_t *c,
790 list_window_t *lw, int lw_length,
791 unsigned long *bstate, int *row)
792 {
793 MEVENT event;
795 /* retreive the mouse event from ncurses */
796 getmouse(&event);
797 D("mouse: id=%d y=%d,x=%d,z=%d\n",event.id,event.y,event.x,event.z);
798 /* calculate the selected row in the list window */
799 *row = event.y - screen->top_window.rows;
800 /* copy button state bits */
801 *bstate = event.bstate;
802 /* if button 2 was pressed switch screen */
803 if( event.bstate & BUTTON2_CLICKED )
804 {
805 screen_cmd(c, CMD_SCREEN_NEXT);
806 return 1;
807 }
808 /* if the even occured above the list window move up */
809 if( *row<0 && lw )
810 {
811 if( event.bstate & BUTTON3_CLICKED )
812 list_window_first(lw);
813 else
814 list_window_previous_page(lw);
815 return 1;
816 }
817 /* if the even occured below the list window move down */
818 if( *row>=lw->rows && lw )
819 {
820 if( event.bstate & BUTTON3_CLICKED )
821 list_window_last(lw, lw_length);
822 else
823 list_window_next_page(lw, lw_length);
824 return 1;
825 }
826 return 0;
827 }
828 #endif
830 void
831 screen_cmd(mpdclient_t *c, command_t cmd)
832 {
833 screen->input_timestamp = time(NULL);
834 screen->last_cmd = cmd;
835 welcome = FALSE;
837 if( mode_fn && mode_fn->cmd && mode_fn->cmd(screen, c, cmd) )
838 return;
840 switch(cmd)
841 {
842 case CMD_PLAY:
843 mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
844 break;
845 case CMD_PAUSE:
846 mpdclient_cmd_pause(c, !IS_PAUSED(c->status->state));
847 break;
848 case CMD_STOP:
849 mpdclient_cmd_stop(c);
850 break;
851 case CMD_SEEK_FORWARD:
852 if( !IS_STOPPED(c->status->state) )
853 {
854 if( c->song && seek_id != c->song->id )
855 {
856 seek_id = c->song->id;
857 seek_target_time = c->status->elapsedTime;
858 }
859 seek_target_time+=options.seek_time;
860 if( seek_target_time < c->status->totalTime )
861 break;
862 seek_target_time = c->status->totalTime;
863 /* seek_target_time=0; */
864 }
865 break;
866 /* fall through... */
867 case CMD_TRACK_NEXT:
868 if( !IS_STOPPED(c->status->state) )
869 mpdclient_cmd_next(c);
870 break;
871 case CMD_SEEK_BACKWARD:
872 if( !IS_STOPPED(c->status->state) )
873 {
874 if( seek_id != c->song->id )
875 {
876 seek_id = c->song->id;
877 seek_target_time = c->status->elapsedTime;
878 }
879 seek_target_time-=options.seek_time;
880 if( seek_target_time < 0 )
881 seek_target_time=0;
882 }
883 break;
884 case CMD_TRACK_PREVIOUS:
885 if( !IS_STOPPED(c->status->state) )
886 mpdclient_cmd_prev(c);
887 break;
888 case CMD_SHUFFLE:
889 if( mpdclient_cmd_shuffle(c) == 0 )
890 screen_status_message(_("Shuffled playlist!"));
891 break;
892 case CMD_CLEAR:
893 if( mpdclient_cmd_clear(c) == 0 )
894 screen_status_message(_("Cleared playlist!"));
895 break;
896 case CMD_REPEAT:
897 mpdclient_cmd_repeat(c, !c->status->repeat);
898 break;
899 case CMD_RANDOM:
900 mpdclient_cmd_random(c, !c->status->random);
901 break;
902 case CMD_CROSSFADE:
903 if( c->status->crossfade )
904 mpdclient_cmd_crossfade(c, 0);
905 else
906 mpdclient_cmd_crossfade(c, options.crossfade_time);
907 break;
908 case CMD_DB_UPDATE:
909 if( !c->status->updatingDb )
910 {
911 if( mpdclient_cmd_db_update_utf8(c,NULL)==0 )
912 screen_status_printf(_("Database update started!"));
913 }
914 else
915 screen_status_printf(_("Database update running..."));
916 break;
917 case CMD_VOLUME_UP:
918 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
919 mpdclient_cmd_volume(c, ++c->status->volume);
920 break;
921 case CMD_VOLUME_DOWN:
922 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
923 mpdclient_cmd_volume(c, --c->status->volume);
924 break;
925 case CMD_TOGGLE_FIND_WRAP:
926 options.find_wrap = !options.find_wrap;
927 screen_status_printf(options.find_wrap ?
928 _("Find mode: Wrapped") :
929 _("Find mode: Normal"));
930 break;
931 case CMD_TOGGLE_AUTOCENTER:
932 options.auto_center = !options.auto_center;
933 screen_status_printf(options.auto_center ?
934 _("Auto center mode: On") :
935 _("Auto center mode: Off"));
936 break;
937 case CMD_SCREEN_UPDATE:
938 screen->painted = 0;
939 break;
940 case CMD_SCREEN_PREVIOUS:
941 screen_next_mode(c, -1);
942 break;
943 case CMD_SCREEN_NEXT:
944 screen_next_mode(c, 1);
945 break;
946 case CMD_SCREEN_PLAY:
947 switch_screen_mode(SCREEN_PLAYLIST_ID, c);
948 break;
949 case CMD_SCREEN_FILE:
950 switch_screen_mode(SCREEN_BROWSE_ID, c);
951 break;
952 case CMD_SCREEN_HELP:
953 switch_screen_mode(SCREEN_HELP_ID, c);
954 break;
955 case CMD_SCREEN_SEARCH:
956 switch_screen_mode(SCREEN_SEARCH_ID, c);
957 break;
958 case CMD_SCREEN_ARTIST:
959 switch_screen_mode(SCREEN_ARTIST_ID, c);
960 break;
961 case CMD_SCREEN_KEYDEF:
962 switch_screen_mode(SCREEN_KEYDEF_ID, c);
963 break;
964 case CMD_SCREEN_CLOCK:
965 switch_screen_mode(SCREEN_CLOCK_ID, c);
966 break;
967 case CMD_QUIT:
968 exit(EXIT_SUCCESS);
969 default:
970 break;
971 }
972 }