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