3db9730e8e54a47b0f7e2f24672fe1da534a9554
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 "screen.h"
22 #include "screen_utils.h"
23 #include "config.h"
24 #include "ncmpc.h"
25 #include "support.h"
26 #include "mpdclient.h"
27 #include "utils.h"
28 #include "command.h"
29 #include "options.h"
30 #include "colors.h"
31 #include "strfsong.h"
32 #include "wreadln.h"
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #include <time.h>
39 #include <locale.h>
41 #define SCREEN_PLAYLIST_ID 0
42 #define SCREEN_BROWSE_ID 1
43 #define SCREEN_ARTIST_ID 2
44 #define SCREEN_HELP_ID 100
45 #define SCREEN_KEYDEF_ID 101
46 #define SCREEN_CLOCK_ID 102
47 #define SCREEN_SEARCH_ID 103
48 #define SCREEN_LYRICS_ID 104
52 /* screens */
53 extern screen_functions_t *get_screen_playlist(void);
54 extern screen_functions_t *get_screen_browse(void);
55 extern screen_functions_t *get_screen_help(void);
56 extern screen_functions_t *get_screen_search(void);
57 extern screen_functions_t *get_screen_artist(void);
58 extern screen_functions_t *get_screen_keydef(void);
59 extern screen_functions_t *get_screen_clock(void);
60 extern screen_functions_t *get_screen_lyrics(void);
62 typedef screen_functions_t * (*screen_get_mode_functions_fn_t) (void);
64 typedef struct
65 {
66 gint id;
67 const gchar *name;
68 screen_get_mode_functions_fn_t get_mode_functions;
69 } screen_mode_info_t;
72 static screen_mode_info_t screens[] = {
73 { SCREEN_PLAYLIST_ID, "playlist", get_screen_playlist },
74 { SCREEN_BROWSE_ID, "browse", get_screen_browse },
75 #ifdef ENABLE_ARTIST_SCREEN
76 { SCREEN_ARTIST_ID, "artist", get_screen_artist },
77 #endif
78 { SCREEN_HELP_ID, "help", get_screen_help },
79 #ifdef ENABLE_SEARCH_SCREEN
80 { SCREEN_SEARCH_ID, "search", get_screen_search },
81 #endif
82 #ifdef ENABLE_KEYDEF_SCREEN
83 { SCREEN_KEYDEF_ID, "keydef", get_screen_keydef },
84 #endif
85 #ifdef ENABLE_CLOCK_SCREEN
86 { SCREEN_CLOCK_ID, "clock", get_screen_clock },
87 #endif
88 #ifdef ENABLE_LYRICS_SCREEN
89 { SCREEN_LYRICS_ID, "lyrics", get_screen_lyrics },
90 #endif
91 { G_MAXINT, NULL, NULL }
92 };
94 static gboolean welcome = TRUE;
95 static screen_t *screen = NULL;
96 static screen_functions_t *mode_fn = NULL;
97 static int seek_id = -1;
98 static int seek_target_time = 0;
100 gint
101 screen_get_id(const char *name)
102 {
103 gint i=0;
105 while (screens[i].name) {
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 if (screens[i].id == id)
120 return i;
121 i++;
122 }
123 return -1;
124 }
126 gint get_cur_mode_id(void)
127 {
128 return screens[screen->mode].id;
129 }
131 static void
132 switch_screen_mode(gint id, mpdclient_t *c)
133 {
134 gint new_mode;
136 if( id == screens[screen->mode].id )
137 return;
139 /* close the old mode */
140 if( mode_fn && mode_fn->close )
141 mode_fn->close();
143 /* get functions for the new mode */
144 new_mode = lookup_mode(id);
145 if (new_mode>=0 && screens[new_mode].get_mode_functions) {
146 D("switch_screen(%s)\n", screens[new_mode].name );
147 mode_fn = screens[new_mode].get_mode_functions();
148 screen->mode = new_mode;
149 }
151 screen->painted = 0;
153 /* open the new mode */
154 if (mode_fn && mode_fn->open)
155 mode_fn->open(screen, c);
156 }
158 static void
159 screen_next_mode(mpdclient_t *c, int offset)
160 {
161 int max = g_strv_length(options.screen_list);
162 int current, next;
163 int i;
165 /* find current screen */
166 current = -1;
167 i = 0;
168 while (options.screen_list[i]) {
169 if (strcmp(options.screen_list[i],
170 screens[screen->mode].name) == 0)
171 current = i;
172 i++;
173 }
175 next = current + offset;
176 if (next<0)
177 next = max-1;
178 else if (next>=max)
179 next = 0;
181 D("current mode: %d:%d next:%d\n", current, max, next);
182 switch_screen_mode(screen_get_id(options.screen_list[next]), c);
183 }
185 static void
186 paint_top_window2(const char *header, mpdclient_t *c)
187 {
188 char flags[5];
189 WINDOW *w = screen->top_window.w;
190 char buf[32];
192 if (header[0]) {
193 colors_use(w, COLOR_TITLE_BOLD);
194 mvwaddstr(w, 0, 0, header);
195 } else {
196 colors_use(w, COLOR_TITLE_BOLD);
197 waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE));
198 colors_use(w, COLOR_TITLE);
199 waddstr(w, _(":Help "));
200 colors_use(w, COLOR_TITLE_BOLD);
201 waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE));
202 colors_use(w, COLOR_TITLE);
203 waddstr(w, _(":Playlist "));
204 colors_use(w, COLOR_TITLE_BOLD);
205 waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE));
206 colors_use(w, COLOR_TITLE);
207 waddstr(w, _(":Browse "));
208 #ifdef ENABLE_ARTIST_SCREEN
209 colors_use(w, COLOR_TITLE_BOLD);
210 waddstr(w, get_key_names(CMD_SCREEN_ARTIST, FALSE));
211 colors_use(w, COLOR_TITLE);
212 waddstr(w, _(":Artist "));
213 #endif
214 #ifdef ENABLE_SEARCH_SCREEN
215 colors_use(w, COLOR_TITLE_BOLD);
216 waddstr(w, get_key_names(CMD_SCREEN_SEARCH, FALSE));
217 colors_use(w, COLOR_TITLE);
218 waddstr(w, _(":Search "));
219 #endif
220 #ifdef ENABLE_LYRICS_SCREEN
221 colors_use(w, COLOR_TITLE_BOLD);
222 waddstr(w, get_key_names(CMD_SCREEN_LYRICS, FALSE));
223 colors_use(w, COLOR_TITLE);
224 waddstr(w, _(":Lyrics "));
225 #endif
226 }
227 if (c->status->volume==MPD_STATUS_NO_VOLUME) {
228 g_snprintf(buf, 32, _("Volume n/a "));
229 } else {
230 g_snprintf(buf, 32, _(" Volume %d%%"), c->status->volume);
231 }
232 colors_use(w, COLOR_TITLE);
233 mvwaddstr(w, 0, screen->top_window.cols-my_strlen(buf), buf);
235 flags[0] = 0;
236 if( c->status->repeat )
237 g_strlcat(flags, "r", sizeof(flags));
238 if( c->status->random )
239 g_strlcat(flags, "z", sizeof(flags));;
240 if( c->status->crossfade )
241 g_strlcat(flags, "x", sizeof(flags));
242 if( c->status->updatingDb )
243 g_strlcat(flags, "U", sizeof(flags));
244 colors_use(w, COLOR_LINE);
245 mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols);
246 if (flags[0]) {
247 wmove(w,1,screen->top_window.cols-strlen(flags)-3);
248 waddch(w, '[');
249 colors_use(w, COLOR_LINE_BOLD);
250 waddstr(w, flags);
251 colors_use(w, COLOR_LINE);
252 waddch(w, ']');
253 }
254 wnoutrefresh(w);
255 }
257 static void
258 paint_top_window(const char *header, mpdclient_t *c, int full_repaint)
259 {
260 static int prev_volume = -1;
261 static size_t prev_header_len = -1;
262 WINDOW *w = screen->top_window.w;
264 if (prev_header_len!=my_strlen(header)) {
265 prev_header_len = my_strlen(header);
266 full_repaint = 1;
267 }
269 if (full_repaint) {
270 wmove(w, 0, 0);
271 wclrtoeol(w);
272 }
274 if (prev_volume!=c->status->volume || full_repaint)
275 paint_top_window2(header, c);
276 }
278 static void
279 paint_progress_window(mpdclient_t *c)
280 {
281 double p;
282 int width;
283 int elapsedTime = c->status->elapsedTime;
285 if (c->status==NULL || IS_STOPPED(c->status->state)) {
286 mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE,
287 screen->progress_window.cols);
288 wnoutrefresh(screen->progress_window.w);
289 return;
290 }
292 if (c->song && seek_id == c->song->id)
293 elapsedTime = seek_target_time;
295 p = ((double) elapsedTime) / ((double) c->status->totalTime);
297 width = (int) (p * (double) screen->progress_window.cols);
298 mvwhline(screen->progress_window.w,
299 0, 0,
300 ACS_HLINE,
301 screen->progress_window.cols);
302 whline(screen->progress_window.w, '=', width-1);
303 mvwaddch(screen->progress_window.w, 0, width-1, 'O');
304 wnoutrefresh(screen->progress_window.w);
305 }
307 static void
308 paint_status_window(mpdclient_t *c)
309 {
310 WINDOW *w = screen->status_window.w;
311 mpd_Status *status = c->status;
312 mpd_Song *song = c->song;
313 int elapsedTime = 0;
314 const char *str = NULL;
315 int x = 0;
317 if( time(NULL) - screen->status_timestamp <= SCREEN_STATUS_MESSAGE_TIME )
318 return;
320 wmove(w, 0, 0);
321 wclrtoeol(w);
322 colors_use(w, COLOR_STATUS_BOLD);
324 switch(status->state) {
325 case MPD_STATUS_STATE_PLAY:
326 str = _("Playing:");
327 break;
328 case MPD_STATUS_STATE_PAUSE:
329 str = _("[Paused]");
330 break;
331 case MPD_STATUS_STATE_STOP:
332 default:
333 break;
334 }
336 if (str) {
337 waddstr(w, str);
338 x += my_strlen(str)+1;
339 }
341 /* create time string */
342 memset(screen->buf, 0, screen->buf_size);
343 if (IS_PLAYING(status->state) || IS_PAUSED(status->state)) {
344 if (status->totalTime > 0) {
345 /*checks the conf to see whether to display elapsed or remaining time */
346 if(!strcmp(options.timedisplay_type,"elapsed"))
347 elapsedTime = c->status->elapsedTime;
348 else if(!strcmp(options.timedisplay_type,"remaining"))
349 elapsedTime = (c->status->totalTime - c->status->elapsedTime);
351 if( c->song && seek_id == c->song->id )
352 elapsedTime = seek_target_time;
353 /*write out the time, using hours if time over 60 minutes*/
354 if (c->status->totalTime > 3600) {
355 g_snprintf(screen->buf, screen->buf_size,
356 " [%i:%02i:%02i/%i:%02i:%02i]",
357 elapsedTime/3600, (elapsedTime%3600)/60, elapsedTime%60,
358 status->totalTime/3600, (status->totalTime%3600)/60, status->totalTime%60);
359 } else {
360 g_snprintf(screen->buf, screen->buf_size,
361 " [%i:%02i/%i:%02i]",
362 elapsedTime/60, elapsedTime%60,
363 status->totalTime/60, status->totalTime%60 );
364 }
365 } else {
366 g_snprintf(screen->buf, screen->buf_size,
367 " [%d kbps]", status->bitRate );
368 }
369 } else {
370 time_t timep;
372 time(&timep);
373 strftime(screen->buf, screen->buf_size, "%X ",localtime(&timep));
374 }
376 /* display song */
377 if (IS_PLAYING(status->state) || IS_PAUSED(status->state)) {
378 char songname[MAX_SONGNAME_LENGTH];
379 int width = COLS-x-my_strlen(screen->buf);
381 if (song)
382 strfsong(songname, MAX_SONGNAME_LENGTH, STATUS_FORMAT, song);
383 else
384 songname[0] = '\0';
386 colors_use(w, COLOR_STATUS);
387 /* scroll if the song name is to long */
388 if (options.scroll && my_strlen(songname) > (size_t)width) {
389 static scroll_state_t st = { 0, 0 };
390 char *tmp = strscroll(songname, options.scroll_sep, width, &st);
392 g_strlcpy(songname, tmp, MAX_SONGNAME_LENGTH);
393 g_free(tmp);
394 }
395 //mvwaddnstr(w, 0, x, songname, width);
396 mvwaddstr(w, 0, x, songname);
397 }
399 /* display time string */
400 if (screen->buf[0]) {
401 x = screen->status_window.cols - strlen(screen->buf);
402 colors_use(w, COLOR_STATUS_TIME);
403 mvwaddstr(w, 0, x, screen->buf);
404 }
406 wnoutrefresh(w);
407 }
409 int
410 screen_exit(void)
411 {
412 endwin();
413 if (screen) {
414 gint i;
416 /* close and exit all screens (playlist,browse,help...) */
417 i=0;
418 while (screens[i].get_mode_functions) {
419 screen_functions_t *sf = screens[i].get_mode_functions();
421 if (sf && sf->close)
422 sf->close();
423 if (sf && sf->exit)
424 sf->exit();
426 i++;
427 }
429 string_list_free(screen->find_history);
430 g_free(screen->buf);
431 g_free(screen->findbuf);
433 g_free(screen);
434 screen = NULL;
435 }
436 return 0;
437 }
439 void
440 screen_resize(void)
441 {
442 gint i;
444 D("Resize rows %d->%d, cols %d->%d\n",screen->rows,LINES,screen->cols,COLS);
445 if (COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS) {
446 screen_exit();
447 fprintf(stderr, _("Error: Screen to small!\n"));
448 exit(EXIT_FAILURE);
449 }
451 resizeterm(LINES, COLS);
453 screen->cols = COLS;
454 screen->rows = LINES;
456 /* top window */
457 screen->top_window.cols = screen->cols;
458 wresize(screen->top_window.w, 2, screen->cols);
460 /* main window */
461 screen->main_window.cols = screen->cols;
462 screen->main_window.rows = screen->rows-4;
463 wresize(screen->main_window.w, screen->main_window.rows, screen->cols);
464 wclear(screen->main_window.w);
466 /* progress window */
467 screen->progress_window.cols = screen->cols;
468 wresize(screen->progress_window.w, 1, screen->cols);
469 mvwin(screen->progress_window.w, screen->rows-2, 0);
471 /* status window */
472 screen->status_window.cols = screen->cols;
473 wresize(screen->status_window.w, 1, screen->cols);
474 mvwin(screen->status_window.w, screen->rows-1, 0);
476 screen->buf_size = screen->cols;
477 g_free(screen->buf);
478 screen->buf = g_malloc(screen->cols);
480 /* close and exit all screens (playlist,browse,help...) */
481 i=0;
482 while (screens[i].get_mode_functions) {
483 screen_functions_t *sf = screens[i].get_mode_functions();
485 if (sf && sf->resize)
486 sf->resize(screen->main_window.cols, screen->main_window.rows);
488 i++;
489 }
491 /* ? - without this the cursor becomes visible with aterm & Eterm */
492 curs_set(1);
493 curs_set(0);
495 screen->painted = 0;
496 }
498 void
499 screen_status_message(const char *msg)
500 {
501 WINDOW *w = screen->status_window.w;
503 wmove(w, 0, 0);
504 wclrtoeol(w);
505 colors_use(w, COLOR_STATUS_ALERT);
506 waddstr(w, msg);
507 wnoutrefresh(w);
508 screen->status_timestamp = time(NULL);
509 }
511 void
512 screen_status_printf(const char *format, ...)
513 {
514 char *msg;
515 va_list ap;
517 va_start(ap,format);
518 msg = g_strdup_vprintf(format,ap);
519 va_end(ap);
520 screen_status_message(msg);
521 g_free(msg);
522 }
524 void
525 ncurses_init(void)
526 {
528 /* initialize the curses library */
529 initscr();
530 /* initialize color support */
531 colors_start();
532 /* tell curses not to do NL->CR/NL on output */
533 nonl();
534 /* use raw mode (ignore interrupt,quit,suspend, and flow control ) */
535 #ifdef ENABLE_RAW_MODE
536 // raw();
537 #endif
538 /* don't echo input */
539 noecho();
540 /* set cursor invisible */
541 curs_set(0);
542 /* enable extra keys */
543 keypad(stdscr, TRUE);
544 /* return from getch() without blocking */
545 timeout(SCREEN_TIMEOUT);
546 /* initialize mouse support */
547 #ifdef HAVE_GETMOUSE
548 if( options.enable_mouse )
549 mousemask(ALL_MOUSE_EVENTS, NULL);
550 #endif
552 if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
553 {
554 fprintf(stderr, _("Error: Screen to small!\n"));
555 exit(EXIT_FAILURE);
556 }
557 screen = g_malloc(sizeof(screen_t));
558 memset(screen, 0, sizeof(screen_t));
559 screen->mode = 0;
560 screen->cols = COLS;
561 screen->rows = LINES;
563 screen->buf = g_malloc(screen->cols);
564 screen->buf_size = screen->cols;
565 screen->findbuf = NULL;
566 screen->painted = 0;
567 screen->start_timestamp = time(NULL);
568 screen->input_timestamp = time(NULL);
569 screen->last_cmd = CMD_NONE;
571 /* create top window */
572 screen->top_window.rows = 2;
573 screen->top_window.cols = screen->cols;
574 screen->top_window.w = newwin(screen->top_window.rows,
575 screen->top_window.cols,
576 0, 0);
577 leaveok(screen->top_window.w, TRUE);
578 keypad(screen->top_window.w, TRUE);
580 /* create main window */
581 screen->main_window.rows = screen->rows-4;
582 screen->main_window.cols = screen->cols;
583 screen->main_window.w = newwin(screen->main_window.rows,
584 screen->main_window.cols,
585 2,
586 0);
588 // leaveok(screen->main_window.w, TRUE); temporary disabled
589 keypad(screen->main_window.w, TRUE);
591 /* create progress window */
592 screen->progress_window.rows = 1;
593 screen->progress_window.cols = screen->cols;
594 screen->progress_window.w = newwin(screen->progress_window.rows,
595 screen->progress_window.cols,
596 screen->rows-2,
597 0);
598 leaveok(screen->progress_window.w, TRUE);
600 /* create status window */
601 screen->status_window.rows = 1;
602 screen->status_window.cols = screen->cols;
603 screen->status_window.w = newwin(screen->status_window.rows,
604 screen->status_window.cols,
605 screen->rows-1,
606 0);
608 leaveok(screen->status_window.w, FALSE);
609 keypad(screen->status_window.w, TRUE);
611 if( options.enable_colors )
612 {
613 /* set background attributes */
614 wbkgd(stdscr, COLOR_PAIR(COLOR_LIST));
615 wbkgd(screen->main_window.w, COLOR_PAIR(COLOR_LIST));
616 wbkgd(screen->top_window.w, COLOR_PAIR(COLOR_TITLE));
617 wbkgd(screen->progress_window.w, COLOR_PAIR(COLOR_PROGRESSBAR));
618 wbkgd(screen->status_window.w, COLOR_PAIR(COLOR_STATUS));
619 colors_use(screen->progress_window.w, COLOR_PROGRESSBAR);
620 }
621 }
623 int
624 screen_init(mpdclient_t *c)
625 {
626 gint i;
628 /* initialize screens */
629 i=0;
630 while( screens[i].get_mode_functions )
631 {
632 screen_functions_t *fn = screens[i].get_mode_functions();
634 if( fn && fn->init )
635 fn->init(screen->main_window.w,
636 screen->main_window.cols,
637 screen->main_window.rows);
639 i++;
640 }
642 #if 0
643 /* broken */
644 mode_fn = NULL;
645 switch_screen_mode(screen_get_id(options.screen_list[0]), c);
646 #else
647 mode_fn = get_screen_playlist();
648 #endif
650 if( mode_fn && mode_fn->open )
651 mode_fn->open(screen, c);
653 /* initialize wreadln */
654 wrln_wgetch = my_wgetch;
655 wrln_max_history_length = 16;
657 return 0;
658 }
660 void
661 screen_paint(mpdclient_t *c)
662 {
663 const char *title = NULL;
665 if (mode_fn && mode_fn->get_title)
666 title = mode_fn->get_title(screen->buf, screen->buf_size);
668 D("screen_paint(%s)\n", title);
669 /* paint the title/header window */
670 if( title )
671 paint_top_window(title, c, 1);
672 else
673 paint_top_window("", c, 1);
675 /* paint the main window */
676 wclear(screen->main_window.w);
677 if( mode_fn && mode_fn->paint )
678 mode_fn->paint(screen, c);
680 paint_progress_window(c);
681 paint_status_window(c);
682 screen->painted = 1;
683 wmove(screen->main_window.w, 0, 0);
684 wnoutrefresh(screen->main_window.w);
686 /* tell curses to update */
687 doupdate();
688 }
690 void
691 screen_update(mpdclient_t *c)
692 {
693 static int repeat = -1;
694 static int random_enabled = -1;
695 static int crossfade = -1;
696 static int dbupdate = -1;
697 list_window_t *lw = NULL;
699 if( !screen->painted )
700 return screen_paint(c);
702 /* print a message if mpd status has changed */
703 if (repeat < 0) {
704 repeat = c->status->repeat;
705 random_enabled = c->status->random;
706 crossfade = c->status->crossfade;
707 dbupdate = c->status->updatingDb;
708 }
710 if (repeat != c->status->repeat)
711 screen_status_printf(c->status->repeat ?
712 _("Repeat is on") :
713 _("Repeat is off"));
715 if (random_enabled != c->status->random)
716 screen_status_printf(c->status->random ?
717 _("Random is on") :
718 _("Random is off"));
720 if (crossfade != c->status->crossfade)
721 screen_status_printf(_("Crossfade %d seconds"), c->status->crossfade);
723 if (dbupdate && dbupdate != c->status->updatingDb) {
724 screen_status_printf(_("Database updated!"));
725 mpdclient_browse_callback(c, BROWSE_DB_UPDATED, NULL);
726 }
728 repeat = c->status->repeat;
729 random_enabled = c->status->random;
730 crossfade = c->status->crossfade;
731 dbupdate = c->status->updatingDb;
733 /* update title/header window */
734 if (welcome && screen->last_cmd==CMD_NONE &&
735 time(NULL)-screen->start_timestamp <= SCREEN_WELCOME_TIME)
736 paint_top_window("", c, 0);
737 else if (mode_fn && mode_fn->get_title) {
738 paint_top_window(mode_fn->get_title(screen->buf,screen->buf_size), c, 0);
739 welcome = FALSE;
740 } else
741 paint_top_window("", c, 0);
743 /* update the main window */
744 if (mode_fn && mode_fn->paint)
745 mode_fn->update(screen, c);
747 if (mode_fn && mode_fn->get_lw)
748 lw = mode_fn->get_lw();
750 /* update progress window */
751 paint_progress_window(c);
753 /* update status window */
754 paint_status_window(c);
756 /* move the cursor to the selected row in the main window */
757 if (lw)
758 wmove(screen->main_window.w, LW_ROW(lw), 0);
759 else
760 wmove(screen->main_window.w, 0, 0);
761 wnoutrefresh(screen->main_window.w);
763 /* tell curses to update */
764 doupdate();
765 }
767 void
768 screen_idle(mpdclient_t *c)
769 {
770 if( c->song && seek_id == c->song->id &&
771 (screen->last_cmd == CMD_SEEK_FORWARD ||
772 screen->last_cmd == CMD_SEEK_BACKWARD) )
773 {
774 mpdclient_cmd_seek(c, seek_id, seek_target_time);
775 }
777 screen->last_cmd = CMD_NONE;
778 seek_id = -1;
779 }
781 #ifdef HAVE_GETMOUSE
782 int
783 screen_get_mouse_event(mpdclient_t *c,
784 list_window_t *lw, int lw_length,
785 unsigned long *bstate, int *row)
786 {
787 MEVENT event;
789 /* retreive the mouse event from ncurses */
790 getmouse(&event);
791 D("mouse: id=%d y=%d,x=%d,z=%d\n",event.id,event.y,event.x,event.z);
792 /* calculate the selected row in the list window */
793 *row = event.y - screen->top_window.rows;
794 /* copy button state bits */
795 *bstate = event.bstate;
796 /* if button 2 was pressed switch screen */
797 if (event.bstate & BUTTON2_CLICKED) {
798 screen_cmd(c, CMD_SCREEN_NEXT);
799 return 1;
800 }
802 /* if the even occured above the list window move up */
803 if (*row < 0 && lw) {
804 if (event.bstate & BUTTON3_CLICKED)
805 list_window_first(lw);
806 else
807 list_window_previous_page(lw);
808 return 1;
809 }
811 /* if the even occured below the list window move down */
812 if ((unsigned)*row >= lw->rows && lw) {
813 if (event.bstate & BUTTON3_CLICKED)
814 list_window_last(lw, lw_length);
815 else
816 list_window_next_page(lw, lw_length);
817 return 1;
818 }
820 return 0;
821 }
822 #endif
824 void
825 screen_cmd(mpdclient_t *c, command_t cmd)
826 {
827 screen->input_timestamp = time(NULL);
828 screen->last_cmd = cmd;
829 welcome = FALSE;
831 if( mode_fn && mode_fn->cmd && mode_fn->cmd(screen, c, cmd) )
832 return;
834 switch(cmd) {
835 case CMD_PLAY:
836 mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
837 break;
838 case CMD_PAUSE:
839 mpdclient_cmd_pause(c, !IS_PAUSED(c->status->state));
840 break;
841 case CMD_STOP:
842 mpdclient_cmd_stop(c);
843 break;
844 case CMD_SEEK_FORWARD:
845 if (!IS_STOPPED(c->status->state)) {
846 if (c->song && seek_id != c->song->id) {
847 seek_id = c->song->id;
848 seek_target_time = c->status->elapsedTime;
849 }
850 seek_target_time+=options.seek_time;
851 if (seek_target_time < c->status->totalTime)
852 break;
853 seek_target_time = c->status->totalTime;
854 /* seek_target_time=0; */
855 }
856 break;
857 /* fall through... */
858 case CMD_TRACK_NEXT:
859 if (!IS_STOPPED(c->status->state))
860 mpdclient_cmd_next(c);
861 break;
862 case CMD_SEEK_BACKWARD:
863 if (!IS_STOPPED(c->status->state)) {
864 if (seek_id != c->song->id) {
865 seek_id = c->song->id;
866 seek_target_time = c->status->elapsedTime;
867 }
868 seek_target_time-=options.seek_time;
869 if (seek_target_time < 0)
870 seek_target_time=0;
871 }
872 break;
873 case CMD_TRACK_PREVIOUS:
874 if (!IS_STOPPED(c->status->state))
875 mpdclient_cmd_prev(c);
876 break;
877 case CMD_SHUFFLE:
878 if (mpdclient_cmd_shuffle(c) == 0)
879 screen_status_message(_("Shuffled playlist!"));
880 break;
881 case CMD_CLEAR:
882 if (mpdclient_cmd_clear(c) == 0)
883 screen_status_message(_("Cleared playlist!"));
884 break;
885 case CMD_REPEAT:
886 mpdclient_cmd_repeat(c, !c->status->repeat);
887 break;
888 case CMD_RANDOM:
889 mpdclient_cmd_random(c, !c->status->random);
890 break;
891 case CMD_CROSSFADE:
892 if (c->status->crossfade)
893 mpdclient_cmd_crossfade(c, 0);
894 else
895 mpdclient_cmd_crossfade(c, options.crossfade_time);
896 break;
897 case CMD_DB_UPDATE:
898 if (!c->status->updatingDb) {
899 if( mpdclient_cmd_db_update_utf8(c,NULL)==0 )
900 screen_status_printf(_("Database update started!"));
901 } else
902 screen_status_printf(_("Database update running..."));
903 break;
904 case CMD_VOLUME_UP:
905 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
906 mpdclient_cmd_volume(c, ++c->status->volume);
907 break;
908 case CMD_VOLUME_DOWN:
909 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
910 mpdclient_cmd_volume(c, --c->status->volume);
911 break;
912 case CMD_TOGGLE_FIND_WRAP:
913 options.find_wrap = !options.find_wrap;
914 screen_status_printf(options.find_wrap ?
915 _("Find mode: Wrapped") :
916 _("Find mode: Normal"));
917 break;
918 case CMD_TOGGLE_AUTOCENTER:
919 options.auto_center = !options.auto_center;
920 screen_status_printf(options.auto_center ?
921 _("Auto center mode: On") :
922 _("Auto center mode: Off"));
923 break;
924 case CMD_SCREEN_UPDATE:
925 screen->painted = 0;
926 break;
927 case CMD_SCREEN_PREVIOUS:
928 screen_next_mode(c, -1);
929 break;
930 case CMD_SCREEN_NEXT:
931 screen_next_mode(c, 1);
932 break;
933 case CMD_SCREEN_PLAY:
934 switch_screen_mode(SCREEN_PLAYLIST_ID, c);
935 break;
936 case CMD_SCREEN_FILE:
937 switch_screen_mode(SCREEN_BROWSE_ID, c);
938 break;
939 case CMD_SCREEN_HELP:
940 switch_screen_mode(SCREEN_HELP_ID, c);
941 break;
942 case CMD_SCREEN_SEARCH:
943 switch_screen_mode(SCREEN_SEARCH_ID, c);
944 break;
945 case CMD_SCREEN_ARTIST:
946 switch_screen_mode(SCREEN_ARTIST_ID, c);
947 break;
948 case CMD_SCREEN_KEYDEF:
949 switch_screen_mode(SCREEN_KEYDEF_ID, c);
950 break;
951 case CMD_SCREEN_CLOCK:
952 switch_screen_mode(SCREEN_CLOCK_ID, c);
953 break;
954 case CMD_SCREEN_LYRICS:
955 switch_screen_mode(SCREEN_LYRICS_ID, c);
956 break;
957 case CMD_QUIT:
958 exit(EXIT_SUCCESS);
959 default:
960 break;
961 }
962 }