2008-05-27 Robert Bragg <bob@o-hand.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, barwidth;
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   if (value > 0)
74     {
75       barwidth = (CLAMP(value,0,100) * width) / 100;
76       psplash_fb_draw_rect (fb, x + barwidth, y, 
77                         width - barwidth, height,
78                         0xec, 0xec, 0xe1);
79       psplash_fb_draw_rect (fb, x, y, barwidth,
80                             height, 0x6d, 0x6d, 0x70);
81     }
82   else
83     {
84       barwidth = (CLAMP(-value,0,100) * width) / 100;
85       psplash_fb_draw_rect (fb, x, y, 
86                         width - barwidth, height,
87                         0xec, 0xec, 0xe1);
88       psplash_fb_draw_rect (fb, x + width - barwidth,
89                             y, barwidth, height,
90                             0x6d, 0x6d, 0x70);
91     }
92
93   DBG("value: %i, width: %i, barwidth :%i\n", value, 
94                 width, barwidth);
95 }
96
97 static int 
98 parse_command (PSplashFB *fb, char *string, int length) 
99 {
100   char *command;
101   int   parsed=0;
102
103   parsed = strlen(string)+1;
104
105   DBG("got cmd %s", string);
106         
107   if (strcmp(string,"QUIT") == 0)
108     return 1;
109
110   command = strtok(string," ");
111
112   if (!strcmp(command,"PROGRESS")) 
113     {
114       psplash_draw_progress (fb, atoi(strtok(NULL,"\0")));
115     } 
116   else if (!strcmp(command,"MSG")) 
117     {
118       psplash_draw_msg (fb, strtok(NULL,"\0"));
119     } 
120   else if (!strcmp(command,"QUIT")) 
121     {
122       return 1;
123     }
124
125   return 0;
126 }
127
128 void 
129 psplash_main (PSplashFB *fb, int pipe_fd, int timeout) 
130 {
131   int            err;
132   ssize_t        length = 0;
133   fd_set         descriptors;
134   struct timeval tv;
135   char          *end;
136   char           command[2048];
137
138   tv.tv_sec = timeout;
139   tv.tv_usec = 0;
140
141   FD_ZERO(&descriptors);
142   FD_SET(pipe_fd, &descriptors);
143
144   end = command;
145
146   while (1) 
147     {
148       if (timeout != 0) 
149         err = select(pipe_fd+1, &descriptors, NULL, NULL, &tv);
150       else
151         err = select(pipe_fd+1, &descriptors, NULL, NULL, NULL);
152       
153       if (err <= 0) 
154         {
155           /*
156           if (errno == EINTR)
157             continue;
158           */
159           return;
160         }
161       
162       length += read (pipe_fd, end, sizeof(command) - (end - command));
163
164       if (length == 0) 
165         {
166           /* Reopen to see if there's anything more for us */
167           close(pipe_fd);
168           pipe_fd = open(PSPLASH_FIFO,O_RDONLY|O_NONBLOCK);
169           goto out;
170         }
171       
172       if (command[length-1] == '\0') 
173         {
174           if (parse_command(fb, command, strlen(command))) 
175             return;
176           length = 0;
177         } 
178     out:
179       end = &command[length];
180     
181       tv.tv_sec = timeout;
182       tv.tv_usec = 0;
183       
184       FD_ZERO(&descriptors);
185       FD_SET(pipe_fd,&descriptors);
186     }
187
188   return;
189 }
190
191 int 
192 main (int argc, char** argv) 
193 {
194   char      *tmpdir;
195   int        pipe_fd, i = 0, angle = 0;
196   PSplashFB *fb;
197   bool       disable_console_switch = FALSE;
198   
199   signal(SIGHUP, psplash_exit);
200   signal(SIGINT, psplash_exit);
201   signal(SIGQUIT, psplash_exit);
202
203   while (++i < argc)
204     {
205       if (!strcmp(argv[i],"-n") || !strcmp(argv[i],"--no-console-switch"))
206         {
207           disable_console_switch = TRUE;
208           continue;
209         }
210
211       if (!strcmp(argv[i],"-a") || !strcmp(argv[i],"--angle"))
212         {
213           if (++i > argc) goto fail;
214           angle = atoi(argv[i]);
215           continue;
216         }
217       
218     fail:
219       fprintf(stderr, 
220               "Usage: %s [-n|--no-console-switch][-a|--angle <0|90|180|270>]\n", 
221               argv[0]);
222       exit(-1);
223     }
224
225   tmpdir = getenv("TMPDIR");
226
227   if (!tmpdir)
228     tmpdir = "/tmp";
229
230   chdir(tmpdir);
231
232   if (mkfifo(PSPLASH_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP))
233     {
234       if (errno!=EEXIST) 
235         {
236           perror("mkfifo");
237           exit(-1);
238         }
239     }
240
241   pipe_fd = open (PSPLASH_FIFO,O_RDONLY|O_NONBLOCK);
242   
243   if (pipe_fd==-1) 
244     {
245       perror("pipe open");
246       exit(-2);
247     }
248
249   if (!disable_console_switch)
250     psplash_console_switch ();
251
252   if ((fb = psplash_fb_new(angle)) == NULL)
253     exit(-1);
254
255   /* Clear the background with #ecece1 */
256   psplash_fb_draw_rect (fb, 0, 0, fb->width, fb->height, 0xec, 0xec, 0xe1);
257
258   /* Draw the OH logo  */
259   psplash_fb_draw_image (fb, 
260                          (fb->width  - HAND_IMG_WIDTH)/2, 
261                          (fb->height - HAND_IMG_HEIGHT)/2, 
262                          HAND_IMG_WIDTH,
263                          HAND_IMG_HEIGHT,
264                          HAND_IMG_BYTES_PER_PIXEL,
265                          HAND_IMG_RLE_PIXEL_DATA);
266
267   /* Draw progress bar border */
268   psplash_fb_draw_image (fb, 
269                          (fb->width  - BAR_IMG_WIDTH)/2, 
270                          fb->height - (fb->height/6), 
271                          BAR_IMG_WIDTH,
272                          BAR_IMG_HEIGHT,
273                          BAR_IMG_BYTES_PER_PIXEL,
274                          BAR_IMG_RLE_PIXEL_DATA);
275
276   psplash_draw_progress (fb, 0);
277
278   psplash_draw_msg (fb, MSG);
279
280   psplash_main (fb, pipe_fd, 0);
281
282   if (!disable_console_switch)
283     psplash_console_reset ();
284
285   psplash_fb_destroy (fb);
286
287   return 0;
288 }