Code

85f1250ae31ed258831fc356f58d9912d2c9a87d
[ncmpc.git] / src / screen.c
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2009 The Music Player Daemon Project
3  * Project homepage: http://musicpd.org
4  
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
20 #include "screen.h"
21 #include "screen_list.h"
22 #include "screen_utils.h"
23 #include "config.h"
24 #include "i18n.h"
25 #include "charset.h"
26 #include "mpdclient.h"
27 #include "utils.h"
28 #include "options.h"
29 #include "colors.h"
30 #include "strfsong.h"
32 #ifndef NCMPC_MINI
33 #include "hscroll.h"
34 #endif
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <time.h>
41 #include <locale.h>
43 #ifndef NCMPC_MINI
44 /** welcome message time [s] */
45 static const GTime SCREEN_WELCOME_TIME = 10;
46 #endif
48 /* minimum window size */
49 static const int SCREEN_MIN_COLS = 14;
50 static const int SCREEN_MIN_ROWS = 5;
52 /* screens */
54 #ifndef NCMPC_MINI
55 static gboolean welcome = TRUE;
56 #endif
58 struct screen screen;
59 static const struct screen_functions *mode_fn = &screen_playlist;
60 static const struct screen_functions *mode_fn_prev = &screen_playlist;
61 static int seek_id = -1;
62 static int seek_target_time = 0;
64 gboolean
65 screen_is_visible(const struct screen_functions *sf)
66 {
67         return sf == mode_fn;
68 }
70 void
71 screen_switch(const struct screen_functions *sf, struct mpdclient *c)
72 {
73         assert(sf != NULL);
75         if (sf == mode_fn)
76                 return;
78         mode_fn_prev = mode_fn;
80         /* close the old mode */
81         if (mode_fn->close != NULL)
82                 mode_fn->close();
84         /* get functions for the new mode */
85         mode_fn = sf;
87         /* open the new mode */
88         if (mode_fn->open != NULL)
89                 mode_fn->open(c);
91         screen_paint(c);
92 }
94 void 
95 screen_swap(struct mpdclient *c, const struct mpd_song *song)
96 {
97         if (song != NULL)
98         {
99                 if (false)
100                         { /* just a hack to make the ifdefs less ugly */ }
101 #ifdef ENABLE_SONG_SCREEN
102                 if (mode_fn_prev == &screen_song)
103                         screen_song_switch(c, song);
104 #endif
105 #ifdef ENABLE_LYRICS_SCREEN
106                 else if (mode_fn_prev == &screen_lyrics)
107                         screen_lyrics_switch(c, song);
108 #endif
109                 else
110                         screen_switch(mode_fn_prev, c);
111         }
112         else
113                 screen_switch(mode_fn_prev, c);
116 static int
117 find_configured_screen(const char *name)
119         unsigned i;
121         for (i = 0; options.screen_list[i] != NULL; ++i)
122                 if (strcmp(options.screen_list[i], name) == 0)
123                         return i;
125         return -1;
128 static void
129 screen_next_mode(mpdclient_t *c, int offset)
131         int max = g_strv_length(options.screen_list);
132         int current, next;
133         const struct screen_functions *sf;
135         /* find current screen */
136         current = find_configured_screen(screen_get_name(mode_fn));
137         next = current + offset;
138         if (next<0)
139                 next = max-1;
140         else if (next>=max)
141                 next = 0;
143         sf = screen_lookup_name(options.screen_list[next]);
144         if (sf != NULL)
145                 screen_switch(sf, c);
148 #ifndef NCMPC_MINI
149 static void
150 print_hotkey(WINDOW *w, command_t cmd, const char *label)
152         colors_use(w, COLOR_TITLE_BOLD);
153         waddstr(w, get_key_names(cmd, FALSE));
154         colors_use(w, COLOR_TITLE);
155         waddch(w, ':');
156         waddstr(w, label);
157         waddch(w, ' ');
158         waddch(w, ' ');
160 #endif
162 static void
163 paint_top_window2(const char *header, mpdclient_t *c)
165         char flags[5];
166         WINDOW *w = screen.top_window.w;
167         char buf[32];
169         if (header[0]) {
170                 colors_use(w, COLOR_TITLE_BOLD);
171                 mvwaddstr(w, 0, 0, header);
172 #ifndef NCMPC_MINI
173         } else {
174 #ifdef ENABLE_HELP_SCREEN
175                 print_hotkey(w, CMD_SCREEN_HELP, _("Help"));
176 #endif
177                 print_hotkey(w, CMD_SCREEN_PLAY, _("Playlist"));
178                 print_hotkey(w, CMD_SCREEN_FILE, _("Browse"));
179 #ifdef ENABLE_ARTIST_SCREEN
180                 print_hotkey(w, CMD_SCREEN_ARTIST, _("Artist"));
181 #endif
182 #ifdef ENABLE_SEARCH_SCREEN
183                 print_hotkey(w, CMD_SCREEN_SEARCH, _("Search"));
184 #endif
185 #ifdef ENABLE_LYRICS_SCREEN
186                 print_hotkey(w, CMD_SCREEN_LYRICS, _("Lyrics"));
187 #endif
188 #ifdef ENABLE_OUTPUTS_SCREEN
189                 print_hotkey(w, CMD_SCREEN_OUTPUTS, _("Outputs"));
190 #endif
191 #endif
192         }
194         if (c->status == NULL || c->status->volume == MPD_STATUS_NO_VOLUME) {
195                 g_snprintf(buf, 32, _("Volume n/a "));
196         } else {
197                 g_snprintf(buf, 32, _(" Volume %d%%"), c->status->volume);
198         }
199         colors_use(w, COLOR_TITLE);
200         mvwaddstr(w, 0, screen.top_window.cols - utf8_width(buf), buf);
202         flags[0] = 0;
203         if (c->status != NULL) {
204                 if (c->status->repeat)
205                         g_strlcat(flags, "r", sizeof(flags));
206                 if (c->status->random)
207                         g_strlcat(flags, "z", sizeof(flags));;
208                 if (c->status->crossfade)
209                         g_strlcat(flags, "x", sizeof(flags));
210                 if (c->status->updatingDb)
211                         g_strlcat(flags, "U", sizeof(flags));
212         }
214         colors_use(w, COLOR_LINE);
215         mvwhline(w, 1, 0, ACS_HLINE, screen.top_window.cols);
216         if (flags[0]) {
217                 wmove(w,1,screen.top_window.cols-strlen(flags)-3);
218                 waddch(w, '[');
219                 colors_use(w, COLOR_LINE_BOLD);
220                 waddstr(w, flags);
221                 colors_use(w, COLOR_LINE);
222                 waddch(w, ']');
223         }
224         wnoutrefresh(w);
227 static void
228 paint_top_window(const char *header, mpdclient_t *c, int full_repaint)
230         static int prev_volume = -1;
231         static unsigned prev_header_len = -1;
232         WINDOW *w = screen.top_window.w;
234         if (prev_header_len != utf8_width(header)) {
235                 prev_header_len = utf8_width(header);
236                 full_repaint = 1;
237         }
239         if (full_repaint) {
240                 wmove(w, 0, 0);
241                 wclrtoeol(w);
242         }
244         if ((c->status != NULL && prev_volume != c->status->volume) ||
245             full_repaint)
246                 paint_top_window2(header, c);
249 static void
250 paint_progress_window(mpdclient_t *c)
252         double p;
253         int width;
254         int elapsedTime;
256         if (c->status==NULL || IS_STOPPED(c->status->state)) {
257                 mvwhline(screen.progress_window.w, 0, 0, ACS_HLINE,
258                          screen.progress_window.cols);
259                 wnoutrefresh(screen.progress_window.w);
260                 return;
261         }
263         if (c->song && seek_id == c->song->id)
264                 elapsedTime = seek_target_time;
265         else
266                 elapsedTime = c->status->elapsedTime;
268         p = ((double) elapsedTime) / ((double) c->status->totalTime);
270         width = (int) (p * (double) screen.progress_window.cols);
271         mvwhline(screen.progress_window.w,
272                  0, 0,
273                  ACS_HLINE,
274                  screen.progress_window.cols);
275         whline(screen.progress_window.w, '=', width-1);
276         mvwaddch(screen.progress_window.w, 0, width-1, 'O');
277         wnoutrefresh(screen.progress_window.w);
280 static void
281 paint_status_window(mpdclient_t *c)
283         WINDOW *w = screen.status_window.w;
284         mpd_Status *status = c->status;
285         mpd_Song *song = c->song;
286         int elapsedTime = 0;
287 #ifdef NCMPC_MINI
288         static char bitrate[1];
289 #else
290         char bitrate[16];
291 #endif
292         const char *str = NULL;
293         int x = 0;
295         if( time(NULL) - screen.status_timestamp <= options.status_message_time )
296                 return;
298         wmove(w, 0, 0);
299         wclrtoeol(w);
300         colors_use(w, COLOR_STATUS_BOLD);
302         switch (status == NULL ? MPD_STATUS_STATE_STOP : status->state) {
303         case MPD_STATUS_STATE_PLAY:
304                 str = _("Playing:");
305                 break;
306         case MPD_STATUS_STATE_PAUSE:
307                 str = _("[Paused]");
308                 break;
309         case MPD_STATUS_STATE_STOP:
310         default:
311                 break;
312         }
314         if (str) {
315                 waddstr(w, str);
316                 x += utf8_width(str) + 1;
317         }
319         /* create time string */
320         memset(screen.buf, 0, screen.buf_size);
321         if (status != NULL && (IS_PLAYING(status->state) ||
322                                IS_PAUSED(status->state))) {
323                 if (status->totalTime > 0) {
324                         /*checks the conf to see whether to display elapsed or remaining time */
325                         if(!strcmp(options.timedisplay_type,"elapsed"))
326                                 elapsedTime = c->status->elapsedTime;
327                         else if(!strcmp(options.timedisplay_type,"remaining"))
328                                 elapsedTime = (c->status->totalTime - c->status->elapsedTime);
330                         if( c->song && seek_id == c->song->id )
331                                 elapsedTime = seek_target_time;
333                         /* display bitrate if visible-bitrate is true */
334 #ifndef NCMPC_MINI
335                         if (options.visible_bitrate) {
336                                 g_snprintf(bitrate, 16,
337                                            " [%d kbps]", status->bitRate);
338                         } else {
339                                 bitrate[0] = '\0';
340                         }
341 #endif
343                         /*write out the time, using hours if time over 60 minutes*/
344                         if (c->status->totalTime > 3600) {
345                                 g_snprintf(screen.buf, screen.buf_size,
346                                            "%s [%i:%02i:%02i/%i:%02i:%02i]",
347                                            bitrate, elapsedTime/3600, (elapsedTime%3600)/60, elapsedTime%60,
348                                            status->totalTime/3600, (status->totalTime%3600)/60,  status->totalTime%60);
349                         } else {
350                                 g_snprintf(screen.buf, screen.buf_size,
351                                            "%s [%i:%02i/%i:%02i]",
352                                            bitrate, elapsedTime/60, elapsedTime%60,
353                                            status->totalTime/60,   status->totalTime%60 );
354                         }
355 #ifndef NCMPC_MINI
356                 } else {
357                         g_snprintf(screen.buf, screen.buf_size,
358                                    " [%d kbps]", status->bitRate );
359 #endif
360                 }
361 #ifndef NCMPC_MINI
362         } else {
363                 if (options.display_time) {
364                         time_t timep;
366                         time(&timep);
367                         strftime(screen.buf, screen.buf_size, "%X ",localtime(&timep));
368                 }
369 #endif
370         }
372         /* display song */
373         if (status != NULL && (IS_PLAYING(status->state) ||
374                                IS_PAUSED(status->state))) {
375                 char songname[MAX_SONGNAME_LENGTH];
376 #ifndef NCMPC_MINI
377                 int width = COLS - x - utf8_width(screen.buf);
378 #endif
380                 if (song)
381                         strfsong(songname, MAX_SONGNAME_LENGTH,
382                                  options.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 #ifndef NCMPC_MINI
389                 if (options.scroll && utf8_width(songname) > (unsigned)width) {
390                         static  scroll_state_t st = { 0, 0 };
391                         char *tmp = strscroll(songname, options.scroll_sep, width, &st);
393                         g_strlcpy(songname, tmp, MAX_SONGNAME_LENGTH);
394                         g_free(tmp);
395                 }
396 #endif
397                 //mvwaddnstr(w, 0, x, songname, width);
398                 mvwaddstr(w, 0, x, songname);
399         }
401         /* display time string */
402         if (screen.buf[0]) {
403                 x = screen.status_window.cols - strlen(screen.buf);
404                 colors_use(w, COLOR_STATUS_TIME);
405                 mvwaddstr(w, 0, x, screen.buf);
406         }
408         wnoutrefresh(w);
411 void
412 screen_exit(void)
414         if (mode_fn->close != NULL)
415                 mode_fn->close();
417         screen_list_exit();
419         string_list_free(screen.find_history);
420         g_free(screen.buf);
421         g_free(screen.findbuf);
424 void
425 screen_resize(struct mpdclient *c)
427         if (COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS) {
428                 screen_exit();
429                 fprintf(stderr, "%s", _("Error: Screen too small"));
430                 exit(EXIT_FAILURE);
431         }
433         resizeterm(LINES, COLS);
435         screen.cols = COLS;
436         screen.rows = LINES;
438         /* top window */
439         screen.top_window.cols = screen.cols;
440         wresize(screen.top_window.w, 2, screen.cols);
442         /* main window */
443         screen.main_window.cols = screen.cols;
444         screen.main_window.rows = screen.rows-4;
445         wresize(screen.main_window.w, screen.main_window.rows, screen.cols);
446         wclear(screen.main_window.w);
448         /* progress window */
449         screen.progress_window.cols = screen.cols;
450         wresize(screen.progress_window.w, 1, screen.cols);
451         mvwin(screen.progress_window.w, screen.rows-2, 0);
453         /* status window */
454         screen.status_window.cols = screen.cols;
455         wresize(screen.status_window.w, 1, screen.cols);
456         mvwin(screen.status_window.w, screen.rows-1, 0);
458         screen.buf_size = screen.cols;
459         g_free(screen.buf);
460         screen.buf = g_malloc(screen.cols);
462         /* resize all screens */
463         screen_list_resize(screen.main_window.cols, screen.main_window.rows);
465         /* ? - without this the cursor becomes visible with aterm & Eterm */
466         curs_set(1);
467         curs_set(0);
469         screen_paint(c);
472 void
473 screen_status_message(const char *msg)
475         WINDOW *w = screen.status_window.w;
477         wmove(w, 0, 0);
478         wclrtoeol(w);
479         colors_use(w, COLOR_STATUS_ALERT);
480         waddstr(w, msg);
481         wnoutrefresh(w);
482         screen.status_timestamp = time(NULL);
485 void
486 screen_status_printf(const char *format, ...)
488         char *msg;
489         va_list ap;
491         va_start(ap,format);
492         msg = g_strdup_vprintf(format,ap);
493         va_end(ap);
494         screen_status_message(msg);
495         g_free(msg);
498 void
499 screen_init(mpdclient_t *c)
501         if (COLS < SCREEN_MIN_COLS || LINES < SCREEN_MIN_ROWS) {
502                 fprintf(stderr, "%s\n", _("Error: Screen too small"));
503                 exit(EXIT_FAILURE);
504         }
506         screen.cols = COLS;
507         screen.rows = LINES;
509         screen.buf  = g_malloc(screen.cols);
510         screen.buf_size = screen.cols;
511         screen.findbuf = NULL;
512         screen.start_timestamp = time(NULL);
513         screen.last_cmd = CMD_NONE;
515         /* create top window */
516         screen.top_window.rows = 2;
517         screen.top_window.cols = screen.cols;
518         screen.top_window.w = newwin(screen.top_window.rows,
519                                       screen.top_window.cols,
520                                       0, 0);
521         leaveok(screen.top_window.w, TRUE);
522         keypad(screen.top_window.w, TRUE);
524         /* create main window */
525         screen.main_window.rows = screen.rows-4;
526         screen.main_window.cols = screen.cols;
527         screen.main_window.w = newwin(screen.main_window.rows,
528                                        screen.main_window.cols,
529                                        2,
530                                        0);
532         //  leaveok(screen.main_window.w, TRUE); temporary disabled
533         keypad(screen.main_window.w, TRUE);
535         /* create progress window */
536         screen.progress_window.rows = 1;
537         screen.progress_window.cols = screen.cols;
538         screen.progress_window.w = newwin(screen.progress_window.rows,
539                                            screen.progress_window.cols,
540                                            screen.rows-2,
541                                            0);
542         leaveok(screen.progress_window.w, TRUE);
544         /* create status window */
545         screen.status_window.rows = 1;
546         screen.status_window.cols = screen.cols;
547         screen.status_window.w = newwin(screen.status_window.rows,
548                                          screen.status_window.cols,
549                                          screen.rows-1,
550                                          0);
552         leaveok(screen.status_window.w, FALSE);
553         keypad(screen.status_window.w, TRUE);
555 #ifdef ENABLE_COLORS
556         if (options.enable_colors) {
557                 /* set background attributes */
558                 wbkgd(stdscr, COLOR_PAIR(COLOR_LIST));
559                 wbkgd(screen.main_window.w,     COLOR_PAIR(COLOR_LIST));
560                 wbkgd(screen.top_window.w,      COLOR_PAIR(COLOR_TITLE));
561                 wbkgd(screen.progress_window.w, COLOR_PAIR(COLOR_PROGRESSBAR));
562                 wbkgd(screen.status_window.w,   COLOR_PAIR(COLOR_STATUS));
563                 colors_use(screen.progress_window.w, COLOR_PROGRESSBAR);
564         }
565 #endif
567         refresh();
569         /* initialize screens */
570         screen_list_init(screen.main_window.w,
571                          screen.main_window.cols, screen.main_window.rows);
573         if (mode_fn->open != NULL)
574                 mode_fn->open(c);
577 void
578 screen_paint(mpdclient_t *c)
580         const char *title = NULL;
582         if (mode_fn->get_title != NULL)
583                 title = mode_fn->get_title(screen.buf, screen.buf_size);
585         /* paint the title/header window */
586         if( title )
587                 paint_top_window(title, c, 1);
588         else
589                 paint_top_window("", c, 1);
591         /* paint the main window */
592         wclear(screen.main_window.w);
593         if (mode_fn->paint != NULL)
594                 mode_fn->paint();
596         paint_progress_window(c);
597         paint_status_window(c);
598         wmove(screen.main_window.w, 0, 0);
599         wnoutrefresh(screen.main_window.w);
601         /* tell curses to update */
602         doupdate();
605 void
606 screen_update(mpdclient_t *c)
608 #ifndef NCMPC_MINI
609         static int repeat = -1;
610         static int random_enabled = -1;
611         static int crossfade = -1;
612         static int dbupdate = -1;
614         /* print a message if mpd status has changed */
615         if (c->status != NULL) {
616                 if (repeat < 0) {
617                         repeat = c->status->repeat;
618                         random_enabled = c->status->random;
619                         crossfade = c->status->crossfade;
620                         dbupdate = c->status->updatingDb;
621                 }
623                 if (repeat != c->status->repeat)
624                         screen_status_printf(c->status->repeat ?
625                                              _("Repeat is on") :
626                                              _("Repeat is off"));
628                 if (random_enabled != c->status->random)
629                         screen_status_printf(c->status->random ?
630                                              _("Random is on") :
631                                              _("Random is off"));
633                 if (crossfade != c->status->crossfade)
634                         screen_status_printf(_("Crossfade %d seconds"), c->status->crossfade);
636                 if (dbupdate && dbupdate != c->status->updatingDb) {
637                         screen_status_printf(_("Database updated"));
638                         mpdclient_browse_callback(c, BROWSE_DB_UPDATED, NULL);
639                 }
641                 repeat = c->status->repeat;
642                 random_enabled = c->status->random;
643                 crossfade = c->status->crossfade;
644                 dbupdate = c->status->updatingDb;
645         }
647         /* update title/header window */
648         if (welcome && options.welcome_screen_list &&
649             screen.last_cmd==CMD_NONE &&
650             time(NULL)-screen.start_timestamp <= SCREEN_WELCOME_TIME)
651                 paint_top_window("", c, 0);
652         else
653 #endif
654         if (mode_fn->get_title != NULL) {
655                 paint_top_window(mode_fn->get_title(screen.buf,screen.buf_size), c, 0);
656 #ifndef NCMPC_MINI
657                 welcome = FALSE;
658 #endif
659         } else
660                 paint_top_window("", c, 0);
662         /* update the main window */
663         if (mode_fn->update != NULL)
664                 mode_fn->update(c);
666         /* update progress window */
667         paint_progress_window(c);
669         /* update status window */
670         paint_status_window(c);
672         /* move the cursor to the origin */
673         wmove(screen.main_window.w, 0, 0);
674         wnoutrefresh(screen.main_window.w);
676         /* tell curses to update */
677         doupdate();
680 void
681 screen_idle(mpdclient_t *c)
683         if (c->song && seek_id == c->song->id &&
684             (screen.last_cmd == CMD_SEEK_FORWARD ||
685              screen.last_cmd == CMD_SEEK_BACKWARD))
686                 mpdclient_cmd_seek(c, seek_id, seek_target_time);
688         screen.last_cmd = CMD_NONE;
689         seek_id = -1;
692 #ifdef HAVE_GETMOUSE
693 int
694 screen_get_mouse_event(mpdclient_t *c, unsigned long *bstate, int *row)
696         MEVENT event;
698         /* retrieve the mouse event from ncurses */
699         getmouse(&event);
700         /* calculate the selected row in the list window */
701         *row = event.y - screen.top_window.rows;
702         /* copy button state bits */
703         *bstate = event.bstate;
704         /* if button 2 was pressed switch screen */
705         if (event.bstate & BUTTON2_CLICKED) {
706                 screen_cmd(c, CMD_SCREEN_NEXT);
707                 return 1;
708         }
710         return 0;
712 #endif
714 static int
715 screen_client_cmd(mpdclient_t *c, command_t cmd)
717         if (c->connection == NULL || c->status == NULL)
718                 return 0;
720         switch(cmd) {
721                 /*
722         case CMD_PLAY:
723                 mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
724                 break;
725                 */
726         case CMD_PAUSE:
727                 mpdclient_cmd_pause(c, !IS_PAUSED(c->status->state));
728                 break;
729         case CMD_STOP:
730                 mpdclient_cmd_stop(c);
731                 break;
732         case CMD_CROP:
733                 mpdclient_cmd_crop(c);
734                 break;
735         case CMD_SEEK_FORWARD:
736                 if (!IS_STOPPED(c->status->state)) {
737                         if (c->song && seek_id != c->song->id) {
738                                 seek_id = c->song->id;
739                                 seek_target_time = c->status->elapsedTime;
740                         }
741                         seek_target_time+=options.seek_time;
742                         if (seek_target_time < c->status->totalTime)
743                                 break;
744                         seek_target_time = c->status->totalTime;
745                         /* seek_target_time=0; */
746                 }
747                 break;
748                 /* fall through... */
749         case CMD_TRACK_NEXT:
750                 if (!IS_STOPPED(c->status->state))
751                         mpdclient_cmd_next(c);
752                 break;
753         case CMD_SEEK_BACKWARD:
754                 if (!IS_STOPPED(c->status->state)) {
755                         if (seek_id != c->song->id) {
756                                 seek_id = c->song->id;
757                                 seek_target_time = c->status->elapsedTime;
758                         }
759                         seek_target_time-=options.seek_time;
760                         if (seek_target_time < 0)
761                                 seek_target_time=0;
762                 }
763                 break;
764         case CMD_TRACK_PREVIOUS:
765                 if (!IS_STOPPED(c->status->state))
766                         mpdclient_cmd_prev(c);
767                 break;
768         case CMD_SHUFFLE:
769                 if (mpdclient_cmd_shuffle(c) == 0)
770                         screen_status_message(_("Shuffled playlist"));
771                 break;
772         case CMD_CLEAR:
773                 if (mpdclient_cmd_clear(c) == 0)
774                         screen_status_message(_("Cleared playlist"));
775                 break;
776         case CMD_REPEAT:
777                 mpdclient_cmd_repeat(c, !c->status->repeat);
778                 break;
779         case CMD_RANDOM:
780                 mpdclient_cmd_random(c, !c->status->random);
781                 break;
782         case CMD_CROSSFADE:
783                 if (c->status->crossfade)
784                         mpdclient_cmd_crossfade(c, 0);
785                 else
786                         mpdclient_cmd_crossfade(c, options.crossfade_time);
787                 break;
788         case CMD_DB_UPDATE:
789                 if (!c->status->updatingDb) {
790                         if( mpdclient_cmd_db_update(c,NULL)==0 )
791                                 screen_status_printf(_("Database update started"));
792                 } else
793                         screen_status_printf(_("Database update running..."));
794                 break;
795         case CMD_VOLUME_UP:
796                 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
797                         mpdclient_cmd_volume(c, ++c->status->volume);
798                 break;
799         case CMD_VOLUME_DOWN:
800                 if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
801                         mpdclient_cmd_volume(c, --c->status->volume);
802                 break;
804         default:
805                 return 0;
806         }
808         return 1;
811 void
812 screen_cmd(mpdclient_t *c, command_t cmd)
814         screen.last_cmd = cmd;
815 #ifndef NCMPC_MINI
816         welcome = FALSE;
817 #endif
819         if (mode_fn->cmd != NULL && mode_fn->cmd(c, cmd))
820                 return;
822         if (screen_client_cmd(c, cmd))
823                 return;
825         switch(cmd) {
826         case CMD_TOGGLE_FIND_WRAP:
827                 options.find_wrap = !options.find_wrap;
828                 screen_status_printf(options.find_wrap ?
829                                      _("Find mode: Wrapped") :
830                                      _("Find mode: Normal"));
831                 break;
832         case CMD_TOGGLE_AUTOCENTER:
833                 options.auto_center = !options.auto_center;
834                 screen_status_printf(options.auto_center ?
835                                      _("Auto center mode: On") :
836                                      _("Auto center mode: Off"));
837                 break;
838         case CMD_SCREEN_UPDATE:
839                 screen_paint(c);
840                 break;
841         case CMD_SCREEN_PREVIOUS:
842                 screen_next_mode(c, -1);
843                 break;
844         case CMD_SCREEN_NEXT:
845                 screen_next_mode(c, 1);
846                 break;
847         case CMD_SCREEN_PLAY:
848                 screen_switch(&screen_playlist, c);
849                 break;
850         case CMD_SCREEN_FILE:
851                 screen_switch(&screen_browse, c);
852                 break;
853 #ifdef ENABLE_HELP_SCREEN
854         case CMD_SCREEN_HELP:
855                 screen_switch(&screen_help, c);
856                 break;
857 #endif
858 #ifdef ENABLE_SEARCH_SCREEN
859         case CMD_SCREEN_SEARCH:
860                 screen_switch(&screen_search, c);
861                 break;
862 #endif
863 #ifdef ENABLE_ARTIST_SCREEN
864         case CMD_SCREEN_ARTIST:
865                 screen_switch(&screen_artist, c);
866                 break;
867 #endif
868 #ifdef ENABLE_SONG_SCREEN
869         case CMD_SCREEN_SONG:
870                 screen_switch(&screen_song, c);
871                 break;
872 #endif
873 #ifdef ENABLE_KEYDEF_SCREEN
874         case CMD_SCREEN_KEYDEF:
875                 screen_switch(&screen_keydef, c);
876                 break;
877 #endif
878 #ifdef ENABLE_LYRICS_SCREEN
879         case CMD_SCREEN_LYRICS:
880                 screen_switch(&screen_lyrics, c);
881                 break;
882 #endif
883 #ifdef ENABLE_OUTPUTS_SCREEN
884         case CMD_SCREEN_OUTPUTS:
885                 screen_switch(&screen_outputs, c);
886                 break;
887         case CMD_SCREEN_SWAP:
888                 screen_swap(c, NULL);
889                 break;
890 #endif
892         default:
893                 break;
894         }