mysql_selector.c: whitespace cleanup
[paraslash.git] / sdl_gui.c
1 /*
2  * Copyright (C) 2003-2006 Andre Noll <maan@systemlinux.org>
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  *
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */
18
19 /** \file sdl_gui.c SDL-based interface for paraslash */
20
21 #include "para.h"
22 #include "string.h"
23
24
25 #include <SDL/SDL.h>
26 #include "SFont.h"
27
28 #include <SDL/SDL_image.h>
29 #include <SDL/SDL_events.h>
30 #include <SDL/SDL_keyboard.h>
31 #include <SDL/SDL_keysym.h>
32 #include <sys/time.h> /* timeval, needed for select */
33
34 #include "sdl_gui.cmdline.h"
35
36 #define FRAME_RED 100
37 #define FRAME_GREEN 200
38 #define FRAME_BLUE 200
39
40 SDL_Surface *screen;
41 static int width = 0;
42 static int height = 0;
43
44 extern const char *status_item_list[NUM_STAT_ITEMS];
45 struct gengetopt_args_info args_info;
46
47 #define FRAME_WIDTH 10
48 #define FONT_HEIGHT 36
49
50 #define INPUT_WIDTH width - 2 * FRAME_WIDTH
51 #define INPUT_X FRAME_WIDTH
52 #define INPUT_HEIGHT (args_info.interactive_flag? FONT_HEIGHT : 0)
53 #define INPUT_Y height - FRAME_WIDTH - INPUT_HEIGHT
54
55 #define OUTPUT_WIDTH width - 2 * FRAME_WIDTH
56 #define OUTPUT_X FRAME_WIDTH
57 #define OUTPUT_Y FRAME_WIDTH
58 #define OUTPUT_HEIGHT (height - INPUT_HEIGHT - 2 * FRAME_WIDTH)
59
60 #define NUM_LINES (height - 2 * FRAME_WIDTH - INPUT_HEIGHT) / FONT_HEIGHT
61
62 #define M_YELLOW 0
63 #define N_YELLOW 1
64
65 #define LEFT 1
66 #define RIGHT 2
67 #define CENTER 3
68
69
70 struct stat_item{
71         char *name;
72         char *prefix;
73         char *postfix;
74         char *content;
75         unsigned x;
76         unsigned y;
77         unsigned w;
78         unsigned h;
79         Uint8 r;
80         Uint8 g;
81         Uint8 b;
82         int font;
83         int align;
84 };
85
86 struct font {
87         char name[MAXLINE];
88         SFont_FontInfo fontinfo;
89 };
90
91 struct font fonts[] = {
92         {
93                 .name = "24P_Arial_Metallic_Yellow.png",
94                 .fontinfo = {NULL, {0}, 0}
95         },
96         {
97                 .name = "24P_Arial_NeonYellow.png",
98                 .fontinfo = {NULL, {0}, 0}
99         },
100         {
101                 .name = "24P_Copperplate_Blue.png",
102                 .fontinfo = {NULL, {0}, 0}
103         },
104         {
105                 .name = "",
106                 .fontinfo = {NULL, {0}, 0}
107         }
108 };
109
110
111 #define PIC_WIDTH width * 3 / 10
112 #define PIC_HEIGHT height / 3
113
114 #define INPUT_FONT 0
115 #define OUTPUT_FONT 1
116 #define MSG_FONT 2
117
118
119 static struct stat_item stat_items[NUM_STAT_ITEMS];
120
121 void para_log(__unused int ll, __unused char* fmt,...) /* no logging */
122 {
123 }
124
125 static void init_stat_items(void)
126 {
127         int i;
128         struct stat_item *s = stat_items;
129
130         for (i = 0; i < NUM_STAT_ITEMS; i++) {
131                 s[i].w = 0;
132                 s[i].content = NULL;
133         }
134
135
136         s[SI_STATUS_BAR].prefix = "";
137         s[SI_STATUS_BAR].postfix = "";
138         s[SI_STATUS_BAR].content = "";
139         s[SI_STATUS_BAR].x = 0;
140         s[SI_STATUS_BAR].y = 10;
141         s[SI_STATUS_BAR].w = 100;
142         s[SI_STATUS_BAR].h = FONT_HEIGHT;
143         s[SI_STATUS_BAR].r = 0;
144         s[SI_STATUS_BAR].g = 0;
145         s[SI_STATUS_BAR].b = 0;
146         s[SI_STATUS_BAR].font = M_YELLOW;
147         s[SI_STATUS_BAR].align = CENTER;
148
149         s[SI_PLAY_TIME].prefix = "";
150         s[SI_PLAY_TIME].postfix = "";
151         s[SI_PLAY_TIME].content = "";
152         s[SI_PLAY_TIME].x = 35;
153         s[SI_PLAY_TIME].y = 20;
154         s[SI_PLAY_TIME].w = 65;
155         s[SI_PLAY_TIME].h = FONT_HEIGHT;
156         s[SI_PLAY_TIME].r = 0;
157         s[SI_PLAY_TIME].g = 0;
158         s[SI_PLAY_TIME].b = 0;
159         s[SI_PLAY_TIME].font = M_YELLOW;
160         s[SI_PLAY_TIME].align = CENTER;
161
162         s[SI_STATUS].prefix = "";
163         s[SI_STATUS].postfix = "";
164         s[SI_STATUS].content = "";
165         s[SI_STATUS].x = 35;
166         s[SI_STATUS].y = 28;
167         s[SI_STATUS].w = 12;
168         s[SI_STATUS].h = FONT_HEIGHT;
169         s[SI_STATUS].r = 0;
170         s[SI_STATUS].g = 0;
171         s[SI_STATUS].b = 0;
172         s[SI_STATUS].font = N_YELLOW;
173         s[SI_STATUS].align = LEFT;
174
175         s[SI_STATUS_FLAGS].prefix = " (";
176         s[SI_STATUS_FLAGS].postfix = ")";
177         s[SI_STATUS_FLAGS].content = "";
178         s[SI_STATUS_FLAGS].x = 47;
179         s[SI_STATUS_FLAGS].y = 28;
180         s[SI_STATUS_FLAGS].w = 15;
181         s[SI_STATUS_FLAGS].h = FONT_HEIGHT;
182         s[SI_STATUS_FLAGS].r = 0;
183         s[SI_STATUS_FLAGS].g = 0;
184         s[SI_STATUS_FLAGS].b = 0;
185         s[SI_STATUS_FLAGS].font = N_YELLOW;
186         s[SI_STATUS_FLAGS].align = CENTER;
187
188         s[SI_NUM_PLAYED].prefix = "#";
189         s[SI_NUM_PLAYED].postfix = "";
190         s[SI_NUM_PLAYED].content = "0";
191         s[SI_NUM_PLAYED].x = 62;
192         s[SI_NUM_PLAYED].y = 28;
193         s[SI_NUM_PLAYED].w = 13;
194         s[SI_NUM_PLAYED].h = FONT_HEIGHT;
195         s[SI_NUM_PLAYED].r = 0;
196         s[SI_NUM_PLAYED].g = 0;
197         s[SI_NUM_PLAYED].b = 0;
198         s[SI_NUM_PLAYED].font = N_YELLOW;
199         s[SI_NUM_PLAYED].align = CENTER;
200
201         s[SI_UPTIME].prefix = "Up: ";
202         s[SI_UPTIME].postfix = "";
203         s[SI_UPTIME].content = "";
204         s[SI_UPTIME].x = 75;
205         s[SI_UPTIME].y = 28;
206         s[SI_UPTIME].w = 25;
207         s[SI_UPTIME].h = FONT_HEIGHT;
208         s[SI_UPTIME].r = 0;
209         s[SI_UPTIME].g = 0;
210         s[SI_UPTIME].b = 0;
211         s[SI_UPTIME].font = N_YELLOW;
212         s[SI_UPTIME].align = RIGHT;
213
214         s[SI_SELECTOR].prefix = "selector: ";
215         s[SI_SELECTOR].postfix = "";
216         s[SI_SELECTOR].content = "no content yet";
217         s[SI_SELECTOR].x = 35;
218         s[SI_SELECTOR].y = 48;
219         s[SI_SELECTOR].w = 35;
220         s[SI_SELECTOR].h = FONT_HEIGHT;
221         s[SI_SELECTOR].r = 0;
222         s[SI_SELECTOR].g = 0;
223         s[SI_SELECTOR].b = 0;
224         s[SI_SELECTOR].font = N_YELLOW;
225         s[SI_SELECTOR].align = LEFT;
226
227         s[SI_FORMAT].prefix = "Format: ";
228         s[SI_FORMAT].postfix = "";
229         s[SI_FORMAT].content = "";
230         s[SI_FORMAT].x = 70;
231         s[SI_FORMAT].y = 48;
232         s[SI_FORMAT].w = 30;
233         s[SI_FORMAT].h = FONT_HEIGHT;
234         s[SI_FORMAT].r = 0;
235         s[SI_FORMAT].g = 0;
236         s[SI_FORMAT].b = 0;
237         s[SI_FORMAT].font = N_YELLOW;
238         s[SI_FORMAT].align = RIGHT;
239
240         s[SI_MTIME].prefix = "MTime: ";
241         s[SI_MTIME].postfix = "";
242         s[SI_MTIME].content = "";
243         s[SI_MTIME].x = 35;
244         s[SI_MTIME].y = 35;
245         s[SI_MTIME].w = 65;
246         s[SI_MTIME].h = FONT_HEIGHT;
247         s[SI_MTIME].r = 0;
248         s[SI_MTIME].g = 0;
249         s[SI_MTIME].b = 0;
250         s[SI_MTIME].font = N_YELLOW;
251         s[SI_MTIME].align = LEFT;
252
253         s[SI_FILE_SIZE].prefix = "Size: ";
254         s[SI_FILE_SIZE].postfix = "kb";
255         s[SI_FILE_SIZE].content = "";
256         s[SI_FILE_SIZE].x = 35;
257         s[SI_FILE_SIZE].y = 42;
258         s[SI_FILE_SIZE].w = 20;
259         s[SI_FILE_SIZE].h = FONT_HEIGHT;
260         s[SI_FILE_SIZE].r = 0;
261         s[SI_FILE_SIZE].g = 0;
262         s[SI_FILE_SIZE].b = 0;
263         s[SI_FILE_SIZE].font = N_YELLOW;
264         s[SI_FILE_SIZE].align = LEFT;
265
266         s[SI_AUDIO_INFO1].prefix = "";
267         s[SI_AUDIO_INFO1].postfix = "";
268         s[SI_AUDIO_INFO1].content = "";
269         s[SI_AUDIO_INFO1].x = 0;
270         s[SI_AUDIO_INFO1].y = 60;
271         s[SI_AUDIO_INFO1].w = 100;
272         s[SI_AUDIO_INFO1].h = FONT_HEIGHT;
273         s[SI_AUDIO_INFO1].r = 0;
274         s[SI_AUDIO_INFO1].g = 0;
275         s[SI_AUDIO_INFO1].b = 0;
276         s[SI_AUDIO_INFO1].font = N_YELLOW;
277         s[SI_AUDIO_INFO1].align = CENTER;
278
279         s[SI_AUDIO_INFO2].prefix = "";
280         s[SI_AUDIO_INFO2].postfix = "";
281         s[SI_AUDIO_INFO2].content = "";
282         s[SI_AUDIO_INFO2].x = 0;
283         s[SI_AUDIO_INFO2].y = 65;
284         s[SI_AUDIO_INFO2].w = 100;
285         s[SI_AUDIO_INFO2].h = FONT_HEIGHT;
286         s[SI_AUDIO_INFO2].r = 0;
287         s[SI_AUDIO_INFO2].g = 0;
288         s[SI_AUDIO_INFO2].b = 0;
289         s[SI_AUDIO_INFO2].font = N_YELLOW;
290         s[SI_AUDIO_INFO2].align = CENTER;
291
292         s[SI_AUDIO_INFO3].prefix = "";
293         s[SI_AUDIO_INFO3].postfix = "";
294         s[SI_AUDIO_INFO3].content = "";
295         s[SI_AUDIO_INFO3].x = 0;
296         s[SI_AUDIO_INFO3].y = 70;
297         s[SI_AUDIO_INFO3].w = 100;
298         s[SI_AUDIO_INFO3].h = FONT_HEIGHT;
299         s[SI_AUDIO_INFO3].r = 0;
300         s[SI_AUDIO_INFO3].g = 0;
301         s[SI_AUDIO_INFO3].b = 0;
302         s[SI_AUDIO_INFO3].font = N_YELLOW;
303         s[SI_AUDIO_INFO3].align = CENTER;
304
305         s[SI_DBINFO1].name = "dbinfo1:";
306         s[SI_DBINFO1].prefix = "";
307         s[SI_DBINFO1].postfix = "";
308         s[SI_DBINFO1].content = "";
309         s[SI_DBINFO1].x = 0;
310         s[SI_DBINFO1].y = 83;
311         s[SI_DBINFO1].w = 100;
312         s[SI_DBINFO1].h = FONT_HEIGHT;
313         s[SI_DBINFO1].r = 0;
314         s[SI_DBINFO1].g = 0;
315         s[SI_DBINFO1].b = 0;
316         s[SI_DBINFO1].font = N_YELLOW;
317         s[SI_DBINFO1].align = CENTER;
318
319         s[SI_DBINFO2].prefix = "";
320         s[SI_DBINFO2].postfix = "";
321         s[SI_DBINFO2].content = "";
322         s[SI_DBINFO2].x = 0;
323         s[SI_DBINFO2].y = 88;
324         s[SI_DBINFO2].w = 100;
325         s[SI_DBINFO2].h = FONT_HEIGHT;
326         s[SI_DBINFO2].r = 0;
327         s[SI_DBINFO2].g = 0;
328         s[SI_DBINFO2].b = 0;
329         s[SI_DBINFO2].font = N_YELLOW;
330         s[SI_DBINFO2].align = CENTER;
331
332         s[SI_DBINFO3].name = "dbinfo3:";
333         s[SI_DBINFO3].prefix = "";
334         s[SI_DBINFO3].postfix = "";
335         s[SI_DBINFO3].content = "";
336         s[SI_DBINFO3].x = 0;
337         s[SI_DBINFO3].y = 93;
338         s[SI_DBINFO3].w = 100;
339         s[SI_DBINFO3].h = FONT_HEIGHT;
340         s[SI_DBINFO3].r = 0;
341         s[SI_DBINFO3].g = 0;
342         s[SI_DBINFO3].b = 0;
343         s[SI_DBINFO3].font = N_YELLOW;
344         s[SI_DBINFO3].align = CENTER;
345 }
346
347 /*
348  * init SDL libary and set window title
349  */
350 static void init_SDL(void)
351 {
352         if (SDL_Init(SDL_INIT_VIDEO) == -1) {
353                 fprintf(stderr,
354                         "Couldn't initialize SDL: %s\n", SDL_GetError());
355                 exit(1);
356         }
357         /* Clean up on exit */
358         atexit(SDL_Quit);
359         /* Initialize the display */
360         if (args_info.fullscreen_flag)
361                 screen = SDL_SetVideoMode(width, height, 0, SDL_FULLSCREEN);
362         else
363                 screen = SDL_SetVideoMode(width, height, 0, 0);
364         if (!screen) {
365                 fprintf(stderr, "Couldn't set video mode: %s\n",
366                         SDL_GetError());
367                 exit(1);
368         }
369         SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
370         SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE);
371         SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE);
372         /* Set the window manager title bar */
373         SDL_WM_SetCaption("The Gui of death that makes you blind (paraslash "
374                 VERSION ")", "SFont");
375 }
376
377 /*
378  * draw rectangular frame of width FRAME_WIDTH
379  */
380 static void draw_frame(Uint8 r, Uint8 g, Uint8 b) {
381         SDL_Rect rect;
382
383         rect.x = 0;
384         rect.y = 0;
385         rect.w = width;
386         rect.h = FRAME_WIDTH;
387         SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
388         SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h);
389
390         rect.x = 0;
391         rect.y = height - FRAME_WIDTH;
392         rect.w = width;
393         rect.h = FRAME_WIDTH;
394         SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
395         SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h);
396
397         rect.x = 0;
398         rect.y = FRAME_WIDTH;
399         rect.w = FRAME_WIDTH;
400         rect.h = height -  2 * FRAME_WIDTH;
401         SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
402         SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h);
403
404         rect.x = width - FRAME_WIDTH;
405         rect.y = FRAME_WIDTH;
406         rect.w = FRAME_WIDTH;
407         rect.h = height -  2 * FRAME_WIDTH;
408         SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
409         SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h);
410 }
411
412 /*
413  * fill input rect with color
414  */
415 static void fill_input_rect(void)
416 {
417         SDL_Rect rect;
418
419         rect.x = INPUT_X;
420         rect.y = INPUT_Y;
421         rect.w = INPUT_WIDTH;
422         rect.h = INPUT_HEIGHT;
423         SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 10, 150, 10));
424 }
425
426 /*
427  * fill output rect with color
428  */
429 static void fill_output_rect(void)
430 {
431         SDL_Rect rect;
432
433         rect.x = OUTPUT_X;
434         rect.y = OUTPUT_Y;
435         rect.w = OUTPUT_WIDTH;
436         rect.h = OUTPUT_HEIGHT;
437         SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));
438 }
439
440 /*
441  * convert tab to space
442  */
443 static void tab2space(char *text)
444 {
445         char *p = text;
446         while (*p) {
447                 if (*p == '\t')
448                         *p = ' ';
449                 p++;
450         }
451 }
452
453 static void print_msg(char *msg)
454 {
455         SFont_FontInfo *font = &(fonts[MSG_FONT].fontinfo);
456         char *buf = strdup(msg);
457         int len = strlen(buf);
458
459         if (!buf)
460                 return;
461         while (TextWidth2(font, buf) > INPUT_WIDTH && len > 0) {
462                 *(buf + len) = '\0';
463                 len--;
464         }
465         fill_input_rect();
466         PutString2(screen, font, INPUT_X, INPUT_Y, buf);
467         free(buf);
468 }
469
470 static void update_all(void)
471 {
472         SDL_UpdateRect(screen, 0, 0, 0, 0);
473 }
474
475 static void update_input(void)
476 {
477         SDL_UpdateRect(screen, INPUT_X, INPUT_Y, INPUT_WIDTH, INPUT_HEIGHT);
478
479 }
480
481 /*
482  * wait for key, ignore all other events, return 0 if there is no key event
483  * pending. Otherwise return keysym of key
484  */
485 SDLKey get_key(void)
486 {
487         SDL_Event event;
488
489         while (SDL_PollEvent(&event) > 0) {
490                 if(event.type != SDL_KEYDOWN)
491                         continue;
492 //              printf("Key pressed, scancode: 0x%x\n",
493 //                      event.key.keysym.scancode);
494                 return event.key.keysym.sym;
495         }
496         return 0;
497 }
498
499 /*
500  * print message, wait for key (blocking), return 1 for 'q', 0 else
501  */
502 static SDLKey hit_key(char *msg)
503 {
504         SDLKey sym;
505
506         print_msg(msg);
507         update_input();
508         while (!(sym = get_key()))
509                 ;
510         fill_input_rect();
511         update_input();
512         if (sym == SDLK_q)
513                 return 1;
514         else
515                 return 0;
516 }
517
518 /*
519  * read paraslash command from input, execute it and print results
520  */
521 static int command_handler(void)
522 {
523         FILE *pipe;
524         unsigned count = 0;
525         char text[MAXLINE]="";
526         char buf[MAXLINE]="";
527         SFont_FontInfo *font = &fonts[OUTPUT_FONT].fontinfo;
528
529 //      printf("string input\n");
530         SFont_Input2(screen, &fonts[INPUT_FONT].fontinfo,
531                 INPUT_X, INPUT_Y - 5, INPUT_WIDTH, text);
532         if (!strlen(text))
533                 return 1;
534         if (!strcmp(text, "exit") || !strcmp(text, "quit"))
535                 return 0;
536         if (text[0] == '!') {
537                 if (text[1] == '\0')
538                         return 1;
539                 pipe = popen(text + 1, "r");
540         } else {
541                 sprintf(buf, BINDIR "/para_client %s 2>&1", text);
542                 pipe = popen(buf, "r");
543         }
544         if (!pipe)
545                 return 0;
546         fill_output_rect();
547         while(fgets(text, MAXLINE - 1, pipe)) {
548                 int len;
549
550                 tab2space(text);
551                 len = strlen(text);
552         //      printf("string: %s\n", dest);
553                 while (TextWidth2(font, text) > width - 2 * FRAME_WIDTH &&
554                                 len > 0) {
555                         text[len] = '\0';
556                         len--;
557                 }
558                 PutString2(screen, font, OUTPUT_X,
559                         OUTPUT_Y + count * FONT_HEIGHT, text);
560                 count++;
561                 if (count >= NUM_LINES) {
562                         update_all();
563                         if (hit_key("Hit any key to continue, q to return"))
564                                 goto out;
565                         count = 0;
566                         fill_output_rect();
567                 }
568         }
569         update_all();
570         hit_key("Hit any key to return");
571 out:    fill_output_rect();
572         pclose(pipe);
573         return 1;
574 }
575
576
577 /*
578  * Add prefix and postfix to string, delete characters from the end
579  * if its length exceeds the max length defined in stat_items[item]
580  */
581 char *transform_string(int item)
582 {
583         struct stat_item s = stat_items[item];
584         size_t len;
585         char *ret;
586         unsigned pixels = s.w * (width - 2 * FRAME_WIDTH) / 100;
587         SFont_FontInfo *font = &(fonts[s.font].fontinfo);
588
589         ret = make_message("%s%s%s", s.prefix, s.content, s.postfix);
590         len = strlen(ret);
591         while (TextWidth2(font, ret) > pixels && len > 0) {
592                 *(ret + len) = '\0';
593                 len--;
594         }
595         return ret;
596 }
597
598 SDL_Surface *load_jpg(void)
599 {
600         SDL_RWops *rwop;
601         int fds[3] = {0, 1, 0};
602         pid_t pid;
603         FILE *pipe;
604
605         if (para_exec_cmdline_pid(&pid, args_info.pic_cmd_arg, fds) < 0)
606                 return NULL;
607         pipe = fdopen(fds[1], "r");
608         if (!pipe)
609                 return NULL;
610         if (!(rwop = SDL_RWFromFP(pipe, 0)))
611                 return NULL;
612         return IMG_LoadJPG_RW(rwop);
613 }
614
615 void update_pic(void)
616 {
617         SDL_Surface *img;
618         SDL_Rect src_pic_rect = {
619                 .x = 0,
620                 .y = 0,
621                 .w = PIC_WIDTH,
622                 .h = PIC_HEIGHT,
623         };
624         SDL_Rect dest_pic_rect = {
625                 .x = FRAME_WIDTH,
626                 .y = OUTPUT_HEIGHT / 5,
627                 .w = PIC_WIDTH,
628                 .h = PIC_HEIGHT,
629         };
630
631         if (!screen)
632                 return;
633
634         if (!(img = load_jpg()))
635                 return;
636         SDL_FillRect(screen, &dest_pic_rect, SDL_MapRGB(screen->format,
637                 0, 0, 0));
638         SDL_BlitSurface(img, &src_pic_rect, screen, &dest_pic_rect);
639         SDL_Flip(screen);
640         SDL_FreeSurface(img);
641 }
642
643 /*
644  * update status item number i.
645  */
646 static void do_update(int i)
647 {
648         static int last_played = -1;
649         SDL_Rect rect;
650         char *buf;
651         SFont_FontInfo *font = &(fonts[stat_items[i].font].fontinfo);
652         if (!stat_items[i].w)
653                 return;
654
655         rect.x = stat_items[i].x * (width - FRAME_WIDTH * 2) / 100
656                 + FRAME_WIDTH;
657         rect.y = stat_items[i].y * (height - 2 * FRAME_WIDTH - INPUT_HEIGHT)
658                 / 100;
659         rect.w = stat_items[i].w * (width - 2 * FRAME_WIDTH) / 100;
660         rect.h = stat_items[i].h;
661         buf = transform_string(i);
662         SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format,
663                 stat_items[i].r, stat_items[i].g, stat_items[i].b));
664         switch(stat_items[i].align) {
665         case CENTER:
666                 PutString2(screen, font,
667                         rect.x + (rect.w - TextWidth2(font, buf)) / 2,
668                         rect.y, buf);
669                 break;
670         case LEFT:
671                 PutString2(screen, font, rect.x, rect.y, buf);
672                 break;
673         case RIGHT:
674                 PutString2(screen, font, rect.x + (rect.w -
675                         TextWidth2(font, buf)), rect.y, buf);
676                 break;
677         }
678         free(buf);
679         SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h);
680         if (i == SI_NUM_PLAYED && atoi(stat_items[i].content) != last_played) {
681                 update_pic();
682                 last_played = atoi(stat_items[i].content);
683         };
684 }
685
686 /*
687  * Check if buf is a known status line. If so call do_update and return 1.
688  * Return 0 otherwise.
689  */
690 void update_status(char *buf)
691 {
692         int i;
693
694         i = stat_line_valid(buf);
695         if (i < 0)
696                 return;
697         //free(stat_items[i].content);
698         stat_items[i].content = para_strdup(buf +
699                 strlen(status_item_list[i]) + 1);
700         do_update(i);
701 }
702
703 /*
704  * Read stat line from pipe if pipe is ready, call update_status to
705  * display information.
706  */
707 static int draw_status(int pipe)
708 {
709         fd_set rfds;
710         int ret;
711         struct timeval tv;
712
713         tv.tv_sec = 0;
714         tv.tv_usec = 3000000;
715         FD_ZERO(&rfds);
716         FD_SET(pipe, &rfds);
717         ret = select(pipe + 1, &rfds, NULL, NULL, &tv);
718 //      printf("select returned %d\n", ret);
719         if (ret <= 0)
720                 return 0;
721         if (read_audiod_pipe(pipe, update_status) > 0)
722                 return 1;
723 //      clear_all_items();
724         free(stat_items[SI_STATUS_BAR].content);
725         stat_items[SI_STATUS_BAR].content =
726                 para_strdup("audiod not running!?\n");
727         update_all();
728         sleep(1);
729         return -1;
730 }
731
732 static void clean_exit(int ret)
733 {
734         SDL_Quit();
735         exit(ret);
736 }
737
738 static void print_help(void)
739 {
740         print_msg("Hit q to quit, any other key to enter command mode");
741 }
742
743 static int configfile_exists(void)
744 {
745         if (!args_info.config_file_given) {
746                 char *home = para_homedir();
747                 args_info.config_file_arg = make_message(
748                         "%s/.paraslash/sdl_gui.conf", home);
749                 free(home);
750         }
751         return file_exists(args_info.config_file_arg);
752 }
753
754 /*
755  * MAIN
756  */
757 int main(int argc, char *argv[])
758 {
759         int i, ret, pipe;
760         SDLKey sym;
761
762         cmdline_parser(argc, argv, &args_info);
763         ret = configfile_exists();
764 //      printf("w=%i,h=%i,ret=%i, cf=%s\n", width, height, ret, args_info.config_file_arg);
765
766         if (!ret && args_info.config_file_given) {
767                 fprintf(stderr, "Can't read config file %s\n",
768                         args_info.config_file_arg);
769                 exit(EXIT_FAILURE);
770         }
771         if (ret)
772                 cmdline_parser_configfile(args_info.config_file_arg,
773                         &args_info, 0, 0, 0);
774         signal(SIGCHLD, SIG_IGN);
775         width = args_info.width_arg;
776         height = args_info.height_arg;
777 //      printf("w=%i,h=%i,ret=%i, cf=%s\n", width, height, ret, args_info.config_file_arg);
778         init_stat_items();
779         pipe = para_open_audiod_pipe(args_info.stat_cmd_arg);
780         init_SDL();
781         for (i = 0; fonts[i].name[0]; i++) {
782                 char buf[MAXLINE];
783                 sprintf(buf, "%s/%s", FONTDIR, fonts[i].name);
784                 /* Load the font - You don't have to use the IMGlib for this */
785                 fonts[i].fontinfo.Surface = IMG_Load(buf);
786                 /* Prepare the font for use */
787                 InitFont2(&fonts[i].fontinfo);
788         }
789         draw_frame(FRAME_RED, FRAME_GREEN, FRAME_BLUE);
790         if (args_info.interactive_flag) {
791                 print_help();
792                 update_input();
793         }
794         for (;;) {
795                 ret = draw_status(pipe);
796                 if (ret < 0) {
797                         close(pipe);
798                         pipe = -1;
799                 }
800                 if (SDL_QuitRequested())
801                         clean_exit(0);
802                 while ((sym = get_key())) {
803                         if (!args_info.interactive_flag)
804                                 clean_exit(0);
805                         if (sym == SDLK_q)
806                                 clean_exit(0);
807                         if (       sym == SDLK_LSHIFT
808                                 || sym == SDLK_RSHIFT
809                                 || sym == SDLK_LMETA
810                                 || sym == SDLK_RMETA
811                                 || sym == SDLK_RCTRL
812                                 || sym == SDLK_LCTRL
813                                 || sym == SDLK_MODE
814                                 || sym == SDLK_CAPSLOCK
815                                 || sym == SDLK_LALT
816                                 || sym == SDLK_RALT
817                                 || sym == SDLK_RSUPER
818                                 || sym == SDLK_LSUPER
819                                 || sym == SDLK_COMPOSE
820                                 )
821                                 continue;
822                         if (pipe < 0) {
823 //                              printf("closing pipe\n");
824                                 kill(0, SIGINT);
825                                 close(pipe);
826 //                              printf("pipe closed\n");
827                         }
828                         fill_input_rect();
829                         update_input();
830                         if (!command_handler())
831                                 clean_exit(0);
832                         fill_output_rect();
833                         print_help();
834                         update_pic();
835                         SDL_UpdateRect(screen, 0, 0, 0, 0);
836                         pipe = para_open_audiod_pipe(args_info.stat_cmd_arg);
837                         break;
838                 }
839         }
840 }