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