Code

Addded support for the mpd update command (CMD_DB_UPDATE)
[ncmpc.git] / src / screen.c
1 /* 
2  * (c) 2004 by Kalle Wallin (kaw@linux.se)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  *
17  */
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <time.h>
24 //#include <signal.h>
25 #include <locale.h>
26 #include <glib.h>
27 #include <ncurses.h>
29 #include "config.h"
30 #include "libmpdclient.h"
31 #include "mpc.h"
32 #include "command.h"
33 #include "options.h"
34 #include "colors.h"
35 #include "screen.h"
36 #include "screen_play.h"
37 #include "screen_file.h"
38 #include "screen_help.h"
39 #include "screen_search.h"
40 #include "screen_utils.h"
42 #undef  ENABLE_STATUS_LINE_CLOCK
43 #define ENABLE_SCROLLING
45 #define DEFAULT_CROSSFADE_TIME 10
47 #define STATUS_MESSAGE_TIMEOUT 3
48 #define STATUS_LINE_MAX_SIZE   512
50 #ifdef ENABLE_KEYDEF_SCREEN
51 extern screen_functions_t *get_screen_keydef(void);
52 #endif
54 static screen_t *screen = NULL;
55 static screen_functions_t *mode_fn = NULL;
57 static void
58 switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c)
59 {
60   if( new_mode == screen->mode )
61     return;
63   /* close the old mode */
64   if( mode_fn && mode_fn->close )
65     mode_fn->close();
67   /* get functions for the new mode */
68   switch(new_mode)
69     {
70     case SCREEN_PLAY_WINDOW:
71       mode_fn = get_screen_playlist();
72       break;
73     case SCREEN_FILE_WINDOW:
74       mode_fn = get_screen_file();
75       break;
76     case SCREEN_HELP_WINDOW:
77       mode_fn = get_screen_help();
78       break;
79 #ifdef ENABLE_KEYDEF_SCREEN
80     case SCREEN_KEYDEF_WINDOW:
81       mode_fn = get_screen_keydef();
82       break;
83 #endif
84     default:
85       break;
86     }
88  screen->mode = new_mode;
89  screen->painted = 0;
91  /* open the new mode */
92  if( mode_fn && mode_fn->open )
93    mode_fn->open(screen, c);
95 }
97 static void
98 paint_top_window(char *header, mpd_client_t *c, int clear)
99 {
100   char flags[4];
101   static int prev_volume = -1;
102   static int prev_header_len = -1;
103   WINDOW *w = screen->top_window.w;
105   if(prev_header_len!=strlen(header))
106     {
107       prev_header_len = strlen(header);
108       clear = 1;
109     }
111   if(clear)
112     {
113       wmove(w, 0, 0);
114       wclrtoeol(w);
115     }
117   if(prev_volume!=c->status->volume || clear)
118     {
119       char buf[32];
121       if( header[0] )
122         {
123           colors_use(w, COLOR_TITLE_BOLD);
124           mvwaddstr(w, 0, 0, header);
125         }
126       else
127         {
128           colors_use(w, COLOR_TITLE_BOLD);
129           waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE));
130           colors_use(w, COLOR_TITLE);
131           waddstr(w, ":Help  ");
132           colors_use(w, COLOR_TITLE_BOLD);
133           waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE));
134           colors_use(w, COLOR_TITLE);
135           waddstr(w, ":Playlist  ");
136           colors_use(w, COLOR_TITLE_BOLD);
137           waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE));
138           colors_use(w, COLOR_TITLE);
139           waddstr(w, ":Browse");
140         }
141       if( c->status->volume==MPD_STATUS_NO_VOLUME )
142         {
143           snprintf(buf, 32, "Volume n/a ");
144         }
145       else
146         {
147           snprintf(buf, 32, " Volume %d%%", c->status->volume); 
148         }
149       colors_use(w, COLOR_TITLE);
150       mvwaddstr(w, 0, screen->top_window.cols-strlen(buf), buf);
152       flags[0] = 0;
153       if( c->status->repeat )
154         strcat(flags, "r");
155       if( c->status->random )
156         strcat(flags, "z");
157       if( c->status->crossfade )
158         strcat(flags, "x");
159       if( c->status->updatingDb )
160         strcat(flags, "U");
161       colors_use(w, COLOR_LINE);
162       mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols);
163       if( flags[0] )
164         {
165           wmove(w,1,screen->top_window.cols-strlen(flags)-3);
166           waddch(w, '[');
167           colors_use(w, COLOR_LINE_BOLD);
168           waddstr(w, flags);
169           colors_use(w, COLOR_LINE);
170           waddch(w, ']');
171         }
172       wnoutrefresh(w);
173     }
176 static void
177 paint_progress_window(mpd_client_t *c)
179   double p;
180   int width;
181   int elapsedTime = c->status->elapsedTime;
183   if( c->status==NULL || IS_STOPPED(c->status->state) )
184     {
185       mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE, 
186                screen->progress_window.cols);
187       wnoutrefresh(screen->progress_window.w);
188       return;
189     }
191   if( c->seek_song_id == c->song_id )
192     elapsedTime = c->seek_target_time;
194   p = ((double) elapsedTime) / ((double) c->status->totalTime);
195   
196   width = (int) (p * (double) screen->progress_window.cols);
197   mvwhline(screen->progress_window.w, 
198            0, 0,
199            ACS_HLINE, 
200            screen->progress_window.cols);
201   whline(screen->progress_window.w, '=', width-1);
202   mvwaddch(screen->progress_window.w, 0, width-1, 'O');
203   wnoutrefresh(screen->progress_window.w);
206 #ifdef ENABLE_SCROLLING
207 static char *
208 scroll_string(char *str, char *sep, int width)
210   static int offset = 0;
211   static time_t t = 0;
212   char *tmp, *buf;
213   size_t len;
215   if( offset==0 )
216     {
217       offset++;
218       return g_strdup(str);
219     }
220  
221   /* create a buffer containing the string and the separator */
222   tmp = g_malloc(strlen(str)+strlen(sep)+1);
223   strcpy(tmp, str);
224   strcat(tmp, sep);
225   len = strlen(tmp);
227   if( offset >= len )
228    offset = 0;
229   
230   /* create the new scrolled string */
231   buf = g_malloc(width+1);
232   strncpy(buf, tmp+offset, width);
233   if( strlen(buf) < width )
234     strncat(buf, tmp, width-strlen(buf));
236   if( time(NULL)-t >= 1 )
237     {
238       t = time(NULL);
239       offset++;
240     }
241   g_free(tmp);
242   return buf;
244 #endif
246 static void 
247 paint_status_window(mpd_client_t *c)
249   WINDOW *w = screen->status_window.w;
250   mpd_Status *status = c->status;
251   mpd_Song *song   = c->song;
252   int elapsedTime = c->status->elapsedTime;
253   int x = 0;
255   if( time(NULL) - screen->status_timestamp <= STATUS_MESSAGE_TIMEOUT )
256     return;
257   
258   
259   wmove(w, 0, 0);
260   wclrtoeol(w);
261   colors_use(w, COLOR_STATUS_BOLD);
262   
263   switch(status->state)
264     {
265     case MPD_STATUS_STATE_STOP:
266       waddstr(w, "Stopped! ");
267       break;
268     case MPD_STATUS_STATE_PLAY:
269       waddstr(w, "Playing:");
270       break;
271     case MPD_STATUS_STATE_PAUSE:
272       waddstr(w, "[Paused]");
273       break;
274     default:
275       break;
276     }
277   x += 9;
279   /* create time string */
280   memset(screen->buf, 0, screen->buf_size);
281   if( IS_PLAYING(status->state) || IS_PAUSED(status->state) )
282     {
283       if( status->totalTime > 0 )
284         {
285           if( c->seek_song_id == c->song_id )
286             elapsedTime = c->seek_target_time;
287           snprintf(screen->buf, screen->buf_size, 
288                    " [%i:%02i/%i:%02i]",
289                    elapsedTime/60, elapsedTime%60,
290                    status->totalTime/60,   status->totalTime%60 );
291         }
292       else
293         {
294           snprintf(screen->buf, screen->buf_size,  " [%d kbps]", status->bitRate );
295         }
296     }
297   else
298     {
299       time_t timep;
301       time(&timep);
302       /* Note: setlocale(LC_TIME,"") should be used first */
303       //strftime(screen->buf, screen->buf_size, "%X ",  localtime(&timep));
304       strftime(screen->buf, screen->buf_size, " %k:%M",  localtime(&timep));
305     }
307   /* display song */
308   if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) &&  song )
309     {
310       char *songname = mpc_get_song_name(song);
311       int width = COLS-x-strlen(screen->buf);
313       colors_use(w, COLOR_STATUS);
314 #ifdef ENABLE_SCROLLING
315       if( strlen(songname) > width )
316         {
317           char *tmp = scroll_string(songname, " *** ", width);
318           strcpy(songname, tmp);
319           g_free(tmp);
320         }
321 #endif
322       mvwaddnstr(w, 0, x, songname, width);
323     } 
325   /* distplay time string */
326   if( screen->buf[0] )
327     {
328       x = screen->status_window.cols - strlen(screen->buf);
329       colors_use(w, COLOR_STATUS_TIME);
330       mvwaddstr(w, 0, x, screen->buf);
331     }
333 #ifdef ENABLE_STATUS_LINE_CLOCK
334   else if( c->status->state == MPD_STATUS_STATE_STOP )
335     {
336       time_t timep;
338       /* Note: setlocale(LC_TIME,"") should be used first */
339       time(&timep);
340       strftime(screen->buf, screen->buf_size, "%X ",  localtime(&timep));
341       x = screen->status_window.cols - strlen(screen->buf) ;
342       colors_use(w, COLOR_STATUS_TIME);
343       mvwaddstr(w, 0, x, screen->buf);
344     }
345 #endif
347   wnoutrefresh(w);
352 int
353 screen_exit(void)
355   endwin();
356   if( screen )
357     {
358       GList *list = g_list_first(screen->screen_list);
360       /* close and exit all screens (playlist,browse,help...) */
361       while( list )
362         {
363           screen_functions_t *mode_fn = list->data;
365           if( mode_fn && mode_fn->close )
366             mode_fn->close();
367           if( mode_fn && mode_fn->exit )
368             mode_fn->exit();
369           list->data = NULL;
370           list=list->next;
371         }
372       g_list_free(screen->screen_list);
374       g_free(screen->buf);
375       g_free(screen->findbuf);
376       g_free(screen);
377       screen = NULL;
378     }
379   return 0;
382 void
383 screen_resize(void)
385   GList *list;
387 #ifdef DEBUG
388   fprintf(stderr, "Resize rows %d->%d, cols %d->%d\n",
389           screen->rows, LINES,
390           screen->cols, COLS);
391 #endif
392       
393   if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
394     {
395       screen_exit();
396       fprintf(stderr, "Error: Screen to small!\n");
397       exit(EXIT_FAILURE);
398     }
400   resizeterm(LINES, COLS);
402   screen->cols = COLS;
403   screen->rows = LINES;
405   /* top window */
406   screen->top_window.cols = screen->cols;
407   wresize(screen->top_window.w, 2, screen->cols);
409   /* main window */
410   screen->main_window.cols = screen->cols;
411   screen->main_window.rows = screen->rows-4;
412   wresize(screen->main_window.w, screen->main_window.rows, screen->cols);
413   wclear(screen->main_window.w);
415   /* progress window */
416   screen->progress_window.cols = screen->cols;
417   wresize(screen->progress_window.w, 1, screen->cols);
418   mvwin(screen->progress_window.w, screen->rows-2, 0);
420   /* status window */
421   screen->status_window.cols = screen->cols;
422   wresize(screen->status_window.w, 1, screen->cols);
423   mvwin(screen->status_window.w, screen->rows-1, 0);
425   screen->buf_size = screen->cols;
426   g_free(screen->buf);
427   screen->buf = g_malloc(screen->cols);
429   list = g_list_first(screen->screen_list);
430   while( list )
431     {
432       screen_functions_t *mode_fn = list->data;
434       if( mode_fn && mode_fn->resize )
435         mode_fn->resize(screen->main_window.cols, screen->main_window.rows);
437       list=list->next;
438     }
440   /* ? - without this the cursor becomes visible with aterm & Eterm */
441   curs_set(1);
442   curs_set(0);     
444   screen->painted = 0;
447 void 
448 screen_status_message(char *msg)
450   WINDOW *w = screen->status_window.w;
452   wmove(w, 0, 0);
453   wclrtoeol(w);
454   colors_use(w, COLOR_STATUS_ALERT);
455   waddstr(w, msg);
456   wnoutrefresh(w);
457   screen->status_timestamp = time(NULL);
460 void 
461 screen_status_printf(char *format, ...)
463   char buffer[STATUS_LINE_MAX_SIZE];
464   va_list ap;
465   
466   va_start(ap,format);
467   vsnprintf(buffer,sizeof(buffer),format,ap);
468   va_end(ap);
469   screen_status_message(buffer);
472 int
473 screen_init(void)
475   GList *list;
477   /* initialize the curses library */
478   initscr();
479   /* initialize color support */
480   colors_start();
481   /* tell curses not to do NL->CR/NL on output */
482   nonl();          
483   /* take input chars one at a time, no wait for \n */  
484   cbreak();       
485   /* don't echo input */
486   noecho();    
487   /* set cursor invisible */     
488   curs_set(0);     
489   /* return from getch() without blocking */
490   //  nodelay(stdscr, TRUE); 
491   keypad(stdscr, TRUE);  
492   timeout(SCREEN_TIMEOUT);
494   if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
495     {
496       fprintf(stderr, "Error: Screen to small!\n");
497       exit(EXIT_FAILURE);
498     }
500   screen = g_malloc(sizeof(screen_t));
501   memset(screen, 0, sizeof(screen_t));
502   screen->mode = SCREEN_PLAY_WINDOW;
503   screen->cols = COLS;
504   screen->rows = LINES;
505   screen->buf  = g_malloc(screen->cols);
506   screen->buf_size = screen->cols;
507   screen->findbuf = NULL;
508   screen->painted = 0;
509   screen->start_timestamp = time(NULL);
510   screen->input_timestamp = time(NULL);
511   screen->last_cmd = CMD_NONE;
513   /* create top window */
514   screen->top_window.rows = 2;
515   screen->top_window.cols = screen->cols;
516   screen->top_window.w = newwin(screen->top_window.rows, 
517                                   screen->top_window.cols,
518                                   0, 0);
519   leaveok(screen->top_window.w, TRUE);
520   keypad(screen->top_window.w, TRUE);  
522   /* create main window */
523   screen->main_window.rows = screen->rows-4;
524   screen->main_window.cols = screen->cols;
525   screen->main_window.w = newwin(screen->main_window.rows, 
526                                  screen->main_window.cols,
527                                  2, 
528                                  0);
530   //  leaveok(screen->main_window.w, TRUE); temporary disabled
531   keypad(screen->main_window.w, TRUE);  
533   /* create progress window */
534   screen->progress_window.rows = 1;
535   screen->progress_window.cols = screen->cols;
536   screen->progress_window.w = newwin(screen->progress_window.rows, 
537                                      screen->progress_window.cols,
538                                      screen->rows-2, 
539                                      0);
540   leaveok(screen->progress_window.w, TRUE);
541   
542   /* create status window */
543   screen->status_window.rows = 1;
544   screen->status_window.cols = screen->cols;
545   screen->status_window.w = newwin(screen->status_window.rows, 
546                                    screen->status_window.cols,
547                                    screen->rows-1, 
548                                    0);
550   leaveok(screen->status_window.w, FALSE);
551   keypad(screen->status_window.w, TRUE);  
553   if( options.enable_colors )
554     {
555       /* set background attributes */
556       wbkgd(stdscr, COLOR_PAIR(COLOR_LIST)); 
557       wbkgd(screen->main_window.w,     COLOR_PAIR(COLOR_LIST));
558       wbkgd(screen->top_window.w,      COLOR_PAIR(COLOR_TITLE));
559       wbkgd(screen->progress_window.w, COLOR_PAIR(COLOR_PROGRESSBAR));
560       wbkgd(screen->status_window.w,   COLOR_PAIR(COLOR_STATUS));
561       colors_use(screen->progress_window.w, COLOR_PROGRESSBAR);
562     }
564   /* initialize screens */
565   screen->screen_list = NULL;
566   screen->screen_list = g_list_append(screen->screen_list, 
567                                       (gpointer) get_screen_playlist());
568   screen->screen_list = g_list_append(screen->screen_list, 
569                                       (gpointer) get_screen_file());
570   screen->screen_list = g_list_append(screen->screen_list, 
571                                       (gpointer) get_screen_help());
572 #ifdef ENABLE_KEYDEF_SCREEN
573   screen->screen_list = g_list_append(screen->screen_list, 
574                                       (gpointer) get_screen_keydef());
575 #endif
577   list = screen->screen_list;
578   while( list )
579     {
580       screen_functions_t *fn = list->data;
581       
582       if( fn && fn->init )
583         fn->init(screen->main_window.w, 
584                  screen->main_window.cols,
585                  screen->main_window.rows);
586       
587       list = list->next;
588     }
590   mode_fn = get_screen_playlist();
592   return 0;
595 void 
596 screen_paint(mpd_client_t *c)
598   /* paint the title/header window */
599   if( mode_fn && mode_fn->get_title )
600     paint_top_window(mode_fn->get_title(), c, 1);
601   else
602     paint_top_window("", c, 1);
604   /* paint the main window */
605   if( mode_fn && mode_fn->paint )
606     mode_fn->paint(screen, c);
607   
608   paint_progress_window(c);
609   paint_status_window(c);
610   screen->painted = 1;
611   wmove(screen->main_window.w, 0, 0);  
612   wnoutrefresh(screen->main_window.w);
614   /* tell curses to update */
615   doupdate();
618 void 
619 screen_update(mpd_client_t *c)
621   static int repeat = -1;
622   static int random = -1;
623   static int crossfade = -1;
624   static int dbupdate = -1;
625   static int welcome = 1;
626   list_window_t *lw = NULL;
628   if( !screen->painted )
629     return screen_paint(c);
631   /* print a message if mpd status has changed */
632   if( repeat<0 )
633     {
634       repeat = c->status->repeat;
635       random = c->status->random;
636       crossfade = c->status->crossfade;
637       dbupdate = c->status->updatingDb;
638     }
639   if( repeat != c->status->repeat )
640     screen_status_printf("Repeat is %s", 
641                          c->status->repeat  ? "On" : "Off");
642   if( random != c->status->random )
643     screen_status_printf("Random is %s", 
644                          c->status->random ? "On" : "Off");
645   if( crossfade != c->status->crossfade )
646     screen_status_printf("Crossfade %d seconds", c->status->crossfade);
647   if( dbupdate && dbupdate != c->status->updatingDb )
648     screen_status_printf("Database updated!");
650   repeat = c->status->repeat;
651   random = c->status->random;
652   crossfade = c->status->crossfade;
653   dbupdate = c->status->updatingDb;
655   /* update title/header window */
656   if( welcome && screen->last_cmd==CMD_NONE &&
657       time(NULL)-screen->start_timestamp <= SCREEN_WELCOME_TIME)
658     paint_top_window("", c, 0);
659   else if( mode_fn && mode_fn->get_title )
660     {
661       paint_top_window(mode_fn->get_title(), c, 0);
662       welcome = 0;
663     }
664   else
665     paint_top_window("", c, 0);
667   /* update the main window */
668   if( mode_fn && mode_fn->paint )
669     mode_fn->update(screen, c);
671   if( mode_fn && mode_fn->get_lw )
672     lw = mode_fn->get_lw();
674   /* update progress window */
675   paint_progress_window(c);
677   /* update status window */
678   paint_status_window(c);
680   /* move the cursor to the selected row in the main window */
681   if( lw )
682     wmove(screen->main_window.w, LW_ROW(lw), 0);   
683   else
684     wmove(screen->main_window.w, 0, 0);   
685   wnoutrefresh(screen->main_window.w);
687   /* tell curses to update */
688   doupdate();
691 void
692 screen_idle(mpd_client_t *c)
694   if( c->seek_song_id ==  c->song_id &&
695       (screen->last_cmd == CMD_SEEK_FORWARD || 
696        screen->last_cmd == CMD_SEEK_BACKWARD) )
697     {
698       mpd_sendSeekCommand(c->connection, 
699                           c->seek_song_id, 
700                           c->seek_target_time);
701       mpd_finishCommand(c->connection);
702     }
704   screen->last_cmd = CMD_NONE;
705   c->seek_song_id = -1;
708 void 
709 screen_cmd(mpd_client_t *c, command_t cmd)
711   int n = 0;
712   screen_mode_t new_mode = screen->mode;
714   screen->input_timestamp = time(NULL);
715   screen->last_cmd = cmd;
717   if( mode_fn && mode_fn->cmd && mode_fn->cmd(screen, c, cmd) )
718     return;
720   switch(cmd)
721     {
722     case CMD_PLAY:
723       mpd_sendPlayCommand(c->connection, play_get_selected());
724       mpd_finishCommand(c->connection);
725       break;
726     case CMD_PAUSE:
727       mpd_sendPauseCommand(c->connection);
728       mpd_finishCommand(c->connection);
729       break;
730     case CMD_STOP:
731       mpd_sendStopCommand(c->connection);
732       mpd_finishCommand(c->connection);
733       break;
734     case CMD_SEEK_FORWARD:
735       if( !IS_STOPPED(c->status->state) )
736         {
737           if( c->seek_song_id != c->song_id )
738             {
739               c->seek_song_id = c->song_id;
740               c->seek_target_time = c->status->elapsedTime;
741             }
742           c->seek_target_time++;
743           if( c->seek_target_time < c->status->totalTime )
744             break;
745           c->seek_target_time=0;
746         }
747       /* fall through... */
748     case CMD_TRACK_NEXT:
749       if( !IS_STOPPED(c->status->state) )
750         {
751           mpd_sendNextCommand(c->connection);
752           mpd_finishCommand(c->connection);
753         }
754       break;
755     case CMD_SEEK_BACKWARD:
756       if( !IS_STOPPED(c->status->state) )
757         {
758           if( c->seek_song_id != c->song_id )
759             {
760               c->seek_song_id = c->song_id;
761               c->seek_target_time = c->status->elapsedTime;
762             }
763           c->seek_target_time--;
764           if( c->seek_target_time < 0 )
765             c->seek_target_time=0;
766         }
767       break;
768     case CMD_TRACK_PREVIOUS:
769       if( !IS_STOPPED(c->status->state) )
770         {
771           mpd_sendPrevCommand(c->connection);
772           mpd_finishCommand(c->connection);
773         }
774       break;   
775     case CMD_SHUFFLE:
776       mpd_sendShuffleCommand(c->connection);
777       mpd_finishCommand(c->connection);
778       screen_status_message("Shuffled playlist!");
779       break;
780     case CMD_CLEAR:
781       mpd_sendClearCommand(c->connection);
782       mpd_finishCommand(c->connection);
783       file_clear_highlights(c);
784       screen_status_message("Cleared playlist!");
785       break;
786     case CMD_REPEAT:
787       n = !c->status->repeat;
788       mpd_sendRepeatCommand(c->connection, n);
789       mpd_finishCommand(c->connection);
790       break;
791     case CMD_RANDOM:
792       n = !c->status->random;
793       mpd_sendRandomCommand(c->connection, n);
794       mpd_finishCommand(c->connection);
795       break;
796     case CMD_CROSSFADE:
797       if( c->status->crossfade )
798         n = 0;
799       else
800         n = DEFAULT_CROSSFADE_TIME;
801       mpd_sendCrossfadeCommand(c->connection, n);
802       mpd_finishCommand(c->connection);
803       break;
804     case CMD_DB_UPDATE:
805       if( !c->status->updatingDb )
806         {
807           mpd_sendUpdateCommand(c->connection);
808           n = mpd_getUpdateId(c->connection);
809           mpd_finishCommand(c->connection);
810           if( !mpc_error(c) )
811             screen_status_printf("Database update started [%d]", n);
812         }
813       else
814         screen_status_printf("Database update running...");
815       break;
816     case CMD_VOLUME_UP:
817       if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
818         {
819           c->status->volume=c->status->volume+1;
820           mpd_sendSetvolCommand(c->connection, c->status->volume  );
821           mpd_finishCommand(c->connection);
822         }
823       break;
824     case CMD_VOLUME_DOWN:
825       if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
826         {
827           c->status->volume=c->status->volume-1;
828           mpd_sendSetvolCommand(c->connection, c->status->volume  );
829           mpd_finishCommand(c->connection);
830         }
831       break;
832     case CMD_TOGGLE_FIND_WRAP:
833       options.find_wrap = !options.find_wrap;
834       screen_status_printf("Find mode: %s", 
835                            options.find_wrap ? "Wrapped" : "Normal");
836       break;
837     case CMD_TOGGLE_AUTOCENTER:
838       options.auto_center = !options.auto_center;
839       screen_status_printf("Auto center mode: %s", 
840                            options.auto_center ? "On" : "Off");
841       break;
842     case CMD_SCREEN_PREVIOUS:
843       if( screen->mode > SCREEN_PLAY_WINDOW )
844         new_mode = screen->mode - 1;
845       else
846         new_mode = SCREEN_HELP_WINDOW-1;
847       switch_screen_mode(new_mode, c);
848       break;
849     case CMD_SCREEN_NEXT:
850       new_mode = screen->mode + 1;
851       if( new_mode >= SCREEN_HELP_WINDOW )
852         new_mode = SCREEN_PLAY_WINDOW;
853       switch_screen_mode(new_mode, c);
854       break;
855     case CMD_SCREEN_PLAY:
856       switch_screen_mode(SCREEN_PLAY_WINDOW, c);
857       break;
858     case CMD_SCREEN_FILE:
859       switch_screen_mode(SCREEN_FILE_WINDOW, c);
860       break;
861     case CMD_SCREEN_SEARCH:
862       switch_screen_mode(SCREEN_SEARCH_WINDOW, c);
863       break;
864     case CMD_SCREEN_HELP:
865       switch_screen_mode(SCREEN_HELP_WINDOW, c);
866       break;
867 #ifdef ENABLE_KEYDEF_SCREEN 
868     case CMD_SCREEN_KEYDEF:
869       switch_screen_mode(SCREEN_KEYDEF_WINDOW, c);
870       break;
871 #endif
872     case CMD_QUIT:
873       exit(EXIT_SUCCESS);
874     default:
875       break;
876     }