fixed path to external icons
[shermanaquarium] / sherman-aquarium / shermans / clock.c
1
2
3 /* Different kind of displaying the time. */
4
5
6 #include <string.h>
7 #include <stdio.h>
8 #include <math.h>
9 #include <time.h>
10 #include <gai/gai.h>
11
12
13
14 #include "aquarium.h"
15 #include "clock.h"
16 #include "draw.h"
17
18 /* This is for the Fuzzy clock */
19 #define FUZZY_IMAGES 18
20 #define TWENTY 12
21 #define QUARTER 13
22 #define HALF 14
23 #define OCLOCK 15
24 #define PAST 16
25 #define TO 17
26
27 static SA_Image *fuzzy_clock_data=NULL;
28
29
30 /* This is for the digital clock*/
31 #define DIGITAL_IMAGES 10
32 #define COLON 10
33 static SA_Image dig, colon;
34
35
36 /* This is for the analog clock */
37 static int old_sec, oldxmax, oldymax;;
38 static int sec_x,sec_y,min_x,min_y,hour_x,hour_y;
39 static unsigned int analog_final_colour_hour;
40 static unsigned int analog_final_colour_min;
41 static unsigned int analog_final_colour_sec;
42
43
44 /* Save settings lives inside this struct */
45 static Clock_settings clock_settings;
46 static AquariumData *ad;
47
48
49 static int what_is_init;
50
51 /* This returns the clock settings structure. */
52 Clock_settings *clock_get_settings_ptr(void)
53 {
54     return &clock_settings;
55 }
56
57
58
59
60 void clock_exit_digital(void)
61 {
62
63     if(dig.pixbuf!=NULL)
64         g_object_unref(dig.pixbuf);
65     if(colon.pixbuf!=NULL)
66         g_object_unref(colon.pixbuf);
67
68     memset(&dig,0,sizeof(SA_Image));
69     memset(&colon,0,sizeof(SA_Image));
70
71 }
72 void clock_exit_analog(void)
73 {
74     /* Nothing to do here */
75 }
76
77 void clock_exit_fuzzy(void)
78 {
79     int i;
80
81     for(i=0;;i++){
82         if(fuzzy_clock_data[i].image==NULL) break;
83         g_object_unref(fuzzy_clock_data[i].pixbuf);
84     }
85     
86     g_free(fuzzy_clock_data);
87     fuzzy_clock_data=NULL;
88 }
89
90
91 void clock_exit(void)
92 {
93     if(what_is_init == CLOCK_DIGITAL)
94         clock_exit_digital();
95     if(what_is_init == CLOCK_ANALOG)
96         clock_exit_analog();
97     if(what_is_init == CLOCK_FUZZY)
98         clock_exit_fuzzy();
99 }
100
101
102
103
104 void clock_init_digital(void)
105 {
106
107
108     what_is_init = CLOCK_DIGITAL;
109
110     if(dig.image!=NULL)
111         clock_exit_digital();
112
113     if(clock_settings.digital_fontsize == CLOCK_LARGE_FONT){
114         load_image("clock/digital/bigfigures.png", &dig, DIGITAL_IMAGES);
115         load_image("clock/digital/bigcolon.png",&colon,1);
116     }
117     else{
118         load_image("clock/digital/smallfigures.png", &dig, DIGITAL_IMAGES);
119         load_image("clock/digital/smallcolon.png", &colon,1);
120     }
121     
122
123     change_colour_to(clock_settings.digital_colour.r,
124                      clock_settings.digital_colour.g,
125                      clock_settings.digital_colour.b,
126                      dig.image,dig.pixbuf, FALSE);
127     change_colour_to(clock_settings.digital_colour.r,
128                      clock_settings.digital_colour.g,
129                      clock_settings.digital_colour.b,
130                      colon.image,colon.pixbuf, FALSE);
131
132 }
133
134 void clock_init_fuzzy(void)
135 {
136     int i;
137     char *fuzzy_image_names[] ={
138         "clock/fuzzy/One.png",
139         "clock/fuzzy/Two.png",
140         "clock/fuzzy/Three.png",
141         "clock/fuzzy/Four.png",
142         "clock/fuzzy/Five.png",
143         "clock/fuzzy/Six.png",
144         "clock/fuzzy/Seven.png",
145         "clock/fuzzy/Eight.png",
146         "clock/fuzzy/Nine.png",
147         "clock/fuzzy/Ten.png",
148         "clock/fuzzy/Eleven.png",
149         "clock/fuzzy/Twelve.png",
150         "clock/fuzzy/Twenty.png",
151         "clock/fuzzy/Quarter.png",
152         "clock/fuzzy/Half.png",
153         "clock/fuzzy/Oclock.png",
154         "clock/fuzzy/Past.png",
155         "clock/fuzzy/To.png",
156         NULL
157     };
158
159
160     what_is_init = CLOCK_FUZZY;
161
162     /* Should be possible to call this init more than once */
163     if(fuzzy_clock_data!=NULL)
164         clock_exit_fuzzy();
165
166     fuzzy_clock_data = g_malloc0(sizeof(SA_Image)*FUZZY_IMAGES);
167
168     for(i=0;;i++){
169         if(fuzzy_image_names[i]==NULL) break;
170
171         load_image(fuzzy_image_names[i], &fuzzy_clock_data[i],1);
172         change_colour_to(clock_settings.fuzzy_colour.r,
173                          clock_settings.fuzzy_colour.g,
174                          clock_settings.fuzzy_colour.b,
175                          fuzzy_clock_data[i].image,fuzzy_clock_data[i].pixbuf, FALSE);
176         
177     }
178
179 }
180
181 void clock_init_analog(void)
182 {
183
184     what_is_init = CLOCK_ANALOG;
185
186
187     /* Setting up colours */
188     analog_final_colour_hour = 
189         (((unsigned int)clock_settings.analog_colour_hour.r)<<16) +
190         (((unsigned int)clock_settings.analog_colour_hour.g)<<8) +
191         (unsigned int)clock_settings.analog_colour_hour.b;
192
193     analog_final_colour_min = 
194         (((unsigned int)clock_settings.analog_colour_min.r)<<16) +
195         (((unsigned int)clock_settings.analog_colour_min.g)<<8) +
196         (unsigned int)clock_settings.analog_colour_min.b;
197
198     if(clock_settings.analog_seconds)
199         analog_final_colour_sec = 
200             (((unsigned int)clock_settings.analog_colour_sec.r)<<16) +
201             (((unsigned int)clock_settings.analog_colour_sec.g)<<8) +
202             (unsigned int)clock_settings.analog_colour_sec.b;
203
204     old_sec=oldxmax=oldymax=-1;
205 }
206
207
208 /* Loads graphics - Can be called upon a restart or changed settings. */
209
210 void clock_init(void)
211 {
212
213     ad = aquarium_get_settings_ptr();
214
215     if (clock_settings.type == CLOCK_OFF)
216         return;
217
218     if(clock_settings.type == CLOCK_DIGITAL)
219         clock_init_digital();
220
221     if(clock_settings.type == CLOCK_ANALOG)
222         clock_init_analog();
223
224     if(clock_settings.type == CLOCK_FUZZY)
225         clock_init_fuzzy();
226
227 }
228
229
230
231
232 void clock_update_fuzzy(int hour, int min, int sec)
233 {
234     int i,x=4,y=4;
235     int to_or_past, ptr2img[5], num_ptr;
236     int largest_one=-1;
237
238     /* Convert min to closes 5 min */
239     min=((int)((min*2+5)/10)*5);
240
241     if(min>30){
242         min=60-min;
243         to_or_past=TO;
244         hour++;
245     }
246     else
247         to_or_past=PAST;
248
249
250     /* Convert from 24 format to 12 hour format.*/
251     if(hour>12) hour-=12;
252
253     /* X minutes past zero doesnt exist */
254     if(hour==0) hour=12;
255
256     /* Most have tree lines */
257     num_ptr = 3;
258     ptr2img[1]=to_or_past;
259     ptr2img[2]=hour-1;
260
261     switch(min){
262     case 0:
263         num_ptr = 2;
264         ptr2img[0]=hour-1;
265         ptr2img[1]=OCLOCK;
266         break;
267     case 5:
268         ptr2img[0]=4;   /* Five */
269         break;
270     case 10:
271         ptr2img[0]=9;   /* Ten */
272         break;
273     case 15:
274         ptr2img[0]=QUARTER;
275         break;
276     case 20:
277         ptr2img[0]=TWENTY;
278         break;
279     case 25:
280         num_ptr = 4;
281         ptr2img[0]=TWENTY;
282         ptr2img[1]=4;
283         ptr2img[2]=to_or_past;
284         ptr2img[3]=hour-1;
285         break;
286     case 30:
287         ptr2img[0]=HALF;
288         break;
289
290     default:
291         printf("I don't understand this kind of time.sorry\n");
292     }
293
294     /* Assume the images have about the same height */
295
296     if(clock_settings.vert == TOP)
297         y=2;
298     else if(clock_settings.vert == CENTER)
299         y=(ad->ymax - num_ptr*(fuzzy_clock_data[0].height+2))/2;
300     else if(clock_settings.vert == BOTTOM)
301         y=ad->ymax - num_ptr*(fuzzy_clock_data[0].height+2)-2;
302
303
304     /* Find the widest one */
305     for(i=0;i<num_ptr;i++){
306         if(largest_one < fuzzy_clock_data[ptr2img[i]].width)
307             largest_one = fuzzy_clock_data[ptr2img[i]].width;
308     }
309     
310
311     for(i=0;i<num_ptr;i++){
312             
313         if(clock_settings.horz == LEFT)
314             x = 2+(largest_one - fuzzy_clock_data[ptr2img[i]].width)/2;
315         else if (clock_settings.horz == CENTER)
316             x=(ad->xmax-fuzzy_clock_data[ptr2img[i]].width)/2;
317         else if (clock_settings.horz == RIGHT)
318             x=(ad->xmax-fuzzy_clock_data[ptr2img[i]].width - 
319                (largest_one - fuzzy_clock_data[ptr2img[i]].width)/2-2);
320
321         draw_pic_alpha(fuzzy_clock_data[ptr2img[i]].image,
322                        fuzzy_clock_data[ptr2img[i]].width,
323                        fuzzy_clock_data[ptr2img[i]].height,
324                        x,y,0,(int)clock_settings.fuzzy_colour.alpha);
325         y+=fuzzy_clock_data[ptr2img[i]].height+2;
326     }
327
328
329 }
330
331 /* Analoge clock */
332
333 void clock_update_analog(int hour, int min, int sec)
334 {
335     int size_l_x,size_r_x,size_b_y, size_t_y;
336     int center_x=0, center_y=0;
337     int curr_x, curr_y;
338
339
340     if(clock_settings.horz == RIGHT){
341         if (ad->xmax < ad->ymax) center_x = ad->xmax/2;
342         else center_x=ad->xmax-ad->ymax/2;
343     }
344     else if(clock_settings.horz == CENTER)
345         center_x = ad->xmax/2;
346
347     else if(clock_settings.horz == LEFT){
348         if (ad->xmax < ad->ymax) center_x = ad->xmax/2;
349         else center_x=ad->ymax/2;
350     }
351
352     if(clock_settings.vert == TOP){
353         if (ad->xmax > ad->ymax) center_y = ad->ymax/2;
354         else center_y=ad->xmax/2;
355     }
356     else if(clock_settings.vert == CENTER)
357         center_y=ad->ymax/2;
358
359     else if(clock_settings.vert == BOTTOM){
360         if (ad->xmax > ad->ymax) center_y = ad->ymax/2;
361         else center_y=ad->ymax-ad->xmax/2;
362     }
363
364
365
366
367     /* Check if we shall keep the clock circular or not.*/
368     if(clock_settings.analog_keep_circular){
369         if(ad->xmax > ad->ymax)
370             size_l_x=size_r_x=size_t_y=size_b_y=center_y; //ad->ymax;
371         else
372             size_l_x=size_r_x=size_t_y=size_b_y=center_x ;//ad->xmax;
373     }
374     else{
375         size_r_x = ad->xmax - center_x;
376         size_l_x = center_x;
377         size_t_y = center_y;
378         size_b_y = ad->ymax - center_y;
379     }
380  
381
382
383     /* Only calculate new placement when it is nessecary, not each frame */
384
385     if(clock_settings.analog_seconds){
386         if(old_sec!=sec || oldxmax!=ad->xmax || oldymax!=ad->ymax){
387             old_sec=sec;
388
389             if(sec>30) curr_x = size_l_x;
390             else curr_x = size_r_x;
391             if(sec <15 || sec >45) curr_y = size_t_y;
392             else curr_y=size_b_y;
393             
394             sec_x=(int)(((float)curr_x*0.9)*cos((2*M_PI*(float)sec)/60.0-M_PI/2));
395             sec_y=(int)(((float)curr_y*0.9)*sin((2*M_PI*(float)sec)/60.0-M_PI/2));
396         }
397     }
398
399     if(sec==0 || oldxmax!=ad->xmax || oldymax!=ad->ymax){
400
401         if(min>30) curr_x = size_l_x;
402         else curr_x = size_r_x;
403         if(min <15 || min >45) curr_y = size_t_y;
404         else curr_y=size_b_y;
405
406         min_x=(int)(((float)curr_x*0.74)*cos((2*M_PI*(float)min)/60.0-M_PI/2));
407         min_y=(int)(((float)curr_y*0.74)*sin((2*M_PI*(float)min)/60.0-M_PI/2));
408
409         if(hour>6) curr_x = size_l_x;
410         else curr_x = size_r_x;
411         if(sec <3 || sec >9) curr_y = size_t_y;
412         else curr_y=size_b_y;
413
414         hour_x=(int)(((float)curr_x*0.58)*cos(2*M_PI*((float)hour+(float)min/60.0)/12.0-M_PI/2));
415         hour_y=(int)(((float)curr_y*0.58)*sin(2*M_PI*((float)hour+(float)min/60.0)/12.0-M_PI/2));
416     }
417
418     oldxmax=ad->xmax;
419     oldymax=ad->ymax;
420    
421     anti_line(center_x,center_y,
422               center_x+hour_x,
423               center_y+hour_y,
424               1,analog_final_colour_hour,1);
425
426     anti_line(center_x,center_y,
427               center_x+min_x,
428               center_y+min_y,
429               1,analog_final_colour_min,1);
430     
431     if(clock_settings.analog_seconds){
432         anti_line(center_x,center_y,
433                   center_x+sec_x,
434                   center_y+sec_y,
435                   1,analog_final_colour_sec,1);
436     }
437
438 }
439
440 void clock_update_digital(int hour, int min, int sec)
441 {
442     int sum_width, list[10], list_max,i;
443     int x=0,y=0;
444
445     list[0]=hour/10;
446     list[1]=hour%10;
447     list[2]=COLON;
448     list[3]=min/10;
449     list[4]=min%10;
450     list_max=5;
451
452
453
454     if(clock_settings.digital_seconds) {
455         list[5]=COLON;
456         list[6]=sec/10;
457         list[7]=sec%10;
458         list_max=8;
459         sum_width = 2*colon.width + 6*dig.width;
460     }
461     else {
462         sum_width = colon.width + 4*dig.width;
463     }
464
465
466
467     if(clock_settings.horz == LEFT)
468         x = 2;
469     else if(clock_settings.horz == CENTER)
470         x = (ad->xmax - sum_width)/2;
471     else if(clock_settings.horz == RIGHT)
472         x = ad->xmax - sum_width - 2;
473
474     if(clock_settings.vert == TOP)
475         y = 2;
476     else if(clock_settings.vert == CENTER)
477         y = (ad->ymax - dig.height)/2;
478     else if(clock_settings.vert == BOTTOM)
479         y = ad->ymax - dig.height - 2;
480
481
482     /*Digital Clock*/
483
484     for(i=0;i<list_max;i++){
485         if(list[i]==COLON){
486             if(clock_settings.digital_blinking && (sec%2)){
487                 x+=colon.width;
488                 continue;
489             }
490             draw_pic_alpha(colon.image, colon.width, colon.height, x, y,
491                            0, (int)clock_settings.digital_colour.alpha);
492                 x+=colon.width;
493         }
494         else{
495             draw_pic_alpha(dig.image, dig.width, dig.height, x, y,
496                            list[i], (int)clock_settings.digital_colour.alpha);
497             x+=dig.width;
498         }
499     }   
500
501 }
502
503
504
505 /* Shall be called both before and after fish are drawn */
506 void clock_update(int beforeorafter)
507 {
508     time_t now;
509     struct tm *mt;
510
511     if (clock_settings.type == CLOCK_OFF)
512         return;
513
514     if(beforeorafter==clock_settings.draw){
515
516         now = time(NULL);
517         mt = localtime(&now);
518
519
520         if(clock_settings.type == CLOCK_DIGITAL)
521             clock_update_digital(mt->tm_hour,mt->tm_min,mt->tm_sec);
522         if(clock_settings.type == CLOCK_ANALOG)
523             clock_update_analog(mt->tm_hour,mt->tm_min,mt->tm_sec);
524         if(clock_settings.type == CLOCK_FUZZY)
525             clock_update_fuzzy(mt->tm_hour,mt->tm_min,mt->tm_sec);
526     }
527 }
528
529
530
531