57778b8baaae2942d663dc43b9db923401d79cb6
[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/8) + 4;
70   width  = BAR_IMG_WIDTH - 8; 
71   height = BAR_IMG_WIDTH - 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;
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       fprintf(stderr, "Usage: %s [-n|--no-console-switch]\n", argv[0]);
197       exit(-1);
198     }
199
200   tmpdir = getenv("TMPDIR");
201
202   if (!tmpdir)
203     tmpdir = "/tmp";
204
205   chdir(tmpdir);
206
207   if (mkfifo(PSPLASH_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP))
208     {
209       if (errno!=EEXIST) 
210         {
211           perror("mkfifo");
212           exit(-1);
213         }
214     }
215
216   pipe_fd = open (PSPLASH_FIFO,O_RDONLY|O_NONBLOCK);
217   
218   if (pipe_fd==-1) 
219     {
220       perror("pipe open");
221       exit(-2);
222     }
223
224   if (!disable_console_switch)
225     psplash_console_switch ();
226
227   if ((fb = psplash_fb_new()) == NULL)
228     exit(-1);
229
230   psplash_fb_draw_rect (fb, 0, 0, fb->width, fb->height, 0xec, 0xec, 0xe1);
231
232   psplash_fb_draw_image (fb, 
233                          (fb->width  - HAND_IMG_WIDTH)/2, 
234                          (fb->height - HAND_IMG_HEIGHT)/4, 
235                          HAND_IMG_WIDTH,
236                          HAND_IMG_HEIGHT,
237                          HAND_IMG_BYTES_PER_PIXEL,
238                          HAND_IMG_RLE_PIXEL_DATA);
239
240   psplash_fb_draw_image (fb, 
241                          (fb->width  - BAR_IMG_WIDTH)/2, 
242                          fb->height - (fb->height/8), 
243                          BAR_IMG_WIDTH,
244                          BAR_IMG_HEIGHT,
245                          BAR_IMG_BYTES_PER_PIXEL,
246                          BAR_IMG_RLE_PIXEL_DATA);
247
248
249   psplash_draw_progress (fb, 0);
250
251   psplash_draw_msg (fb, MSG);
252
253   psplash_main (fb, pipe_fd, 0);
254
255   if (!disable_console_switch)
256     psplash_console_reset ();
257
258   psplash_fb_destroy (fb);
259
260   return 0;
261 }