2006-12-22 Matthew Allum <mallum@openedhand.com>
[profile/ivi/psplash.git] / psplash.c
1 /* 
2  *  pslash - a lightweight framebuffer splashscreen for embedded devices. 
3  *
4  *  Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
5  *
6  *  Parts of this file ( fifo handling ) based on 'usplash' copyright 
7  *  Matthew Garret.
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2, or (at your option)
12  *  any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  */
20
21 #include "psplash.h"
22 #include "psplash-hand-img.h"
23 #include "psplash-bar-img.h"
24 #include "radeon-font.h"
25
26 #define MSG ""
27
28 void
29 psplash_exit (int signum)
30 {
31   DBG("mark");
32
33   psplash_console_reset ();
34 }
35
36 void
37 psplash_draw_msg (PSplashFB *fb, const char *msg)
38 {
39   int w, h;
40
41   psplash_fb_text_size (fb, &w, &h, &radeon_font, msg);
42
43   DBG("displaying '%s' %ix%i\n", msg, w, h);
44
45   /* Clear */
46
47   psplash_fb_draw_rect (fb, 
48                         0, 
49                         fb->height - (fb->height/6) - h, 
50                         fb->width,
51                         h,
52                         0xec, 0xec, 0xe1);
53
54   psplash_fb_draw_text (fb,
55                         (fb->width-w)/2, 
56                         fb->height - (fb->height/6) - h,
57                         0x6d, 0x6d, 0x70,
58                         &radeon_font,
59                         msg);
60 }
61
62 void
63 psplash_draw_progress (PSplashFB *fb, int value)
64 {
65   int x, y, width, height;
66
67   /* 4 pix border */
68   x      = ((fb->width  - BAR_IMG_WIDTH)/2) + 4 ;
69   y      = fb->height - (fb->height/6) + 4;
70   width  = BAR_IMG_WIDTH - 8; 
71   height = BAR_IMG_HEIGHT - 8;
72
73   value = CLAMP(value,0,100);
74
75   DBG("total w: %i, val :%i, w: %i", 
76       width, value, (value * width) / 100);
77
78   psplash_fb_draw_rect (fb, x, y, 
79                         (value * width) / 100, 
80                         height, 0x6d, 0x6d, 0x70);
81 }
82
83 static int 
84 parse_command (PSplashFB *fb, char *string, int length) 
85 {
86   char *command;
87   int   parsed=0;
88
89   parsed = strlen(string)+1;
90
91   DBG("got cmd %s", string);
92         
93   if (strcmp(string,"QUIT") == 0)
94     return 1;
95
96   command = strtok(string," ");
97
98   if (!strcmp(command,"PROGRESS")) 
99     {
100       psplash_draw_progress (fb, atoi(strtok(NULL,"\0")));
101     } 
102   else if (!strcmp(command,"MSG")) 
103     {
104       psplash_draw_msg (fb, strtok(NULL,"\0"));
105     } 
106   else if (!strcmp(command,"QUIT")) 
107     {
108       return 1;
109     }
110
111   return 0;
112 }
113
114 void 
115 psplash_main (PSplashFB *fb, int pipe_fd, int timeout) 
116 {
117   int            err;
118   ssize_t        length = 0;
119   fd_set         descriptors;
120   struct timeval tv;
121   char          *end;
122   char           command[2048];
123
124   tv.tv_sec = timeout;
125   tv.tv_usec = 0;
126
127   FD_ZERO(&descriptors);
128   FD_SET(pipe_fd, &descriptors);
129
130   end = command;
131
132   while (1) 
133     {
134       if (timeout != 0) 
135         err = select(pipe_fd+1, &descriptors, NULL, NULL, &tv);
136       else
137         err = select(pipe_fd+1, &descriptors, NULL, NULL, NULL);
138       
139       if (err <= 0) 
140         {
141           /*
142           if (errno == EINTR)
143             continue;
144           */
145           return;
146         }
147       
148       length += read (pipe_fd, end, sizeof(command) - (end - command));
149
150       if (length == 0) 
151         {
152           /* Reopen to see if there's anything more for us */
153           close(pipe_fd);
154           pipe_fd = open(PSPLASH_FIFO,O_RDONLY|O_NONBLOCK);
155           goto out;
156         }
157       
158       if (command[length-1] == '\0') 
159         {
160           if (parse_command(fb, command, strlen(command))) 
161             return;
162           length = 0;
163         } 
164     out:
165       end = &command[length];
166     
167       tv.tv_sec = timeout;
168       tv.tv_usec = 0;
169       
170       FD_ZERO(&descriptors);
171       FD_SET(pipe_fd,&descriptors);
172     }
173
174   return;
175 }
176
177 int 
178 main (int argc, char** argv) 
179 {
180   char      *tmpdir;
181   int        pipe_fd, i = 0, angle = 0;
182   PSplashFB *fb;
183   bool       disable_console_switch = FALSE;
184   
185   signal(SIGHUP, psplash_exit);
186   signal(SIGINT, psplash_exit);
187   signal(SIGQUIT, psplash_exit);
188
189   while (++i < argc)
190     {
191       if (!strcmp(argv[i],"-n") || !strcmp(argv[i],"--no-console-switch"))
192         {
193           disable_console_switch = TRUE;
194           continue;
195         }
196
197       if (!strcmp(argv[i],"-a") || !strcmp(argv[i],"--angle"))
198         {
199           if (++i > argc) goto fail;
200           angle = atoi(argv[i]);
201           continue;
202         }
203       
204     fail:
205       fprintf(stderr, 
206               "Usage: %s [-n|--no-console-switch] [-a|--angle <0|90|180|270>]\n", 
207               argv[0]);
208       exit(-1);
209     }
210
211   tmpdir = getenv("TMPDIR");
212
213   if (!tmpdir)
214     tmpdir = "/tmp";
215
216   chdir(tmpdir);
217
218   if (mkfifo(PSPLASH_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP))
219     {
220       if (errno!=EEXIST) 
221         {
222           perror("mkfifo");
223           exit(-1);
224         }
225     }
226
227   pipe_fd = open (PSPLASH_FIFO,O_RDONLY|O_NONBLOCK);
228   
229   if (pipe_fd==-1) 
230     {
231       perror("pipe open");
232       exit(-2);
233     }
234
235   if (!disable_console_switch)
236     psplash_console_switch ();
237
238   if ((fb = psplash_fb_new(angle)) == NULL)
239     exit(-1);
240
241   /* Clear the background with #ecece1 */
242   psplash_fb_draw_rect (fb, 0, 0, fb->width, fb->height, 0xec, 0xec, 0xe1);
243
244   /* Draw the OH logo  */
245   psplash_fb_draw_image (fb, 
246                          (fb->width  - HAND_IMG_WIDTH)/2, 
247                          (fb->height - HAND_IMG_HEIGHT)/2, 
248                          HAND_IMG_WIDTH,
249                          HAND_IMG_HEIGHT,
250                          HAND_IMG_BYTES_PER_PIXEL,
251                          HAND_IMG_RLE_PIXEL_DATA);
252
253   /* Draw progress bar border */
254   psplash_fb_draw_image (fb, 
255                          (fb->width  - BAR_IMG_WIDTH)/2, 
256                          fb->height - (fb->height/6), 
257                          BAR_IMG_WIDTH,
258                          BAR_IMG_HEIGHT,
259                          BAR_IMG_BYTES_PER_PIXEL,
260                          BAR_IMG_RLE_PIXEL_DATA);
261
262   psplash_draw_progress (fb, 0);
263
264   psplash_draw_msg (fb, MSG);
265
266   psplash_main (fb, pipe_fd, 0);
267
268   if (!disable_console_switch)
269     psplash_console_reset ();
270
271   psplash_fb_destroy (fb);
272
273   return 0;
274 }