added into billboard info about missed calls, sms, chat, mail from notifications...
[livewp] / applet / src / livewp-actor.c
1 /*vim: set sw=4 ts=4 et: */
2 /*
3  * This file is part of Live Wallpaper (livewp)
4  * 
5  * Copyright (C) 2010 Vlad Vasiliev
6  * Copyright (C) 2010 Tanya Makova
7  *       for the code
8  * 
9  * This software is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  * 
14  * This software is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  * 
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this software; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23 */
24 /*******************************************************************************/
25 #include "livewp-actor.h"
26
27 Actor* 
28 init_object(AWallpaperPlugin *desktop_plugin, 
29             gchar * name, 
30             gchar * filename, 
31             gint x, 
32             gint y, 
33             gint z, 
34             gint width, 
35             gint height, 
36             gboolean visible, 
37             gboolean load_image,
38             gint scale, 
39             gint opacity, 
40             void (*pfunc_change)(Actor*),
41             void (*pfunc_probability)(Actor*),
42             GPtrArray *child
43            )
44 {
45     Actor *actor = NULL;
46     actor = g_new0(Actor, 1);
47     actor->x = x;
48     actor->y = y;
49     actor->z = z;
50     actor->width = width;
51     actor->height = height;
52     actor->visible = visible;
53     actor->scale = scale;
54     actor->opacity = opacity;
55     actor->filename = g_strdup(filename);
56     actor->name = g_strdup(name);
57     actor->func_change = (gpointer)pfunc_change; 
58     actor->func_probability = (gpointer)pfunc_probability;
59     actor->child = child;
60     if (load_image)
61         create_hildon_actor(actor, desktop_plugin);
62     else 
63          actor->widget = NULL;
64     actor->time_start_animation = 0;
65     actor->duration_animation = 0;
66     return actor;
67 }
68
69 void 
70 destroy_actor(Actor *actor)
71 {
72     if (actor){
73         if (actor->child){
74             g_ptr_array_free(actor->child, TRUE);
75         }
76         if (actor->filename)
77             g_free(actor->filename);
78         if (actor->name)
79             g_free(actor->name);
80         gtk_widget_destroy(actor->widget);
81         //actor->widget = NULL;
82         g_free(actor);
83     }
84 }
85 static gint 
86 path_line(gint x0, gint x1, double t)
87 {
88     // уравниение прямой
89     return ((x1 - x0) * t + x0);
90 }
91 void
92 set_actor_scale(Actor *actor, double scalex, double scaley)
93 {
94     hildon_animation_actor_set_scale(
95             HILDON_ANIMATION_ACTOR(actor->widget), 
96             scalex, 
97             scaley
98     );
99
100 }
101
102 void 
103 set_actor_visible(Actor *actor, gboolean visible)
104 {
105     hildon_animation_actor_set_show(HILDON_ANIMATION_ACTOR(actor->widget), visible);
106 }
107
108 void
109 set_actor_position(Actor *actor, gint x, gint y, gint z, AWallpaperPlugin *desktop_plugin)
110 {
111     hildon_animation_actor_set_position_full(HILDON_ANIMATION_ACTOR (actor->widget), 
112                                              x-desktop_plugin->priv->xapplet, 
113                                              y-desktop_plugin->priv->yapplet, 
114                                              z);
115 }
116
117 int
118 func_callback(void *user_data, int argc, char **argv, char **azColName)
119 {
120     fprintf(stderr, "callback\n");
121     int i;
122     GtkTreeIter iter;
123     GtkListStore *list = GTK_LIST_STORE(user_data);
124     gtk_list_store_append(list, &iter);
125     for(i = 0; i < argc; i++){
126         fprintf(stderr, "argc=%d, argv=%s, colname=%s\n", argc, argv, azColName[i]);
127         //if(!strcmp(azColName[i], "count"))
128             gtk_list_store_set(list, &iter, 0, atoi(argv[i]), -1);
129     }
130     return 0;
131 }
132 int get_notify_count(gchar *notify_type)
133 {
134     sqlite3 *db = NULL;
135     sqlite3 *res = NULL;
136     gint rc = 0, result = 0;
137     gchar sql[1024];
138
139     rc = sqlite3_open("/home/user/.config/hildon-desktop/notifications.db", &db);
140     if (rc){
141         fprintf(stderr, "error open db %d %s\n", rc, sqlite3_errmsg(db));
142     }else {
143         snprintf(sql, sizeof(sql)-1, "select count(id) from notifications where icon_name='general_%s'", notify_type);
144         rc = sqlite3_prepare(db, sql, sizeof(sql)-1, &res, NULL);
145         if (rc != SQLITE_OK){
146             fprintf(stderr, "error prepare %d %s\n", rc, sql);
147         }
148         if (sqlite3_step(res) != SQLITE_ROW){
149             fprintf(stderr, "not sqlite_row\n");
150         }
151         result = sqlite3_column_int(res, 0);
152         //fprintf(stderr, "count missing calls = %d\n", call_count);
153         sqlite3_finalize(res);
154
155         sqlite3_close(db);
156     }
157     return result;
158 }
159
160 void 
161 change_billboard(Actor * actor, AWallpaperPlugin *desktop_plugin)
162 {
163     GtkWidget *label;
164     gchar *message;
165     PangoFontDescription *pfd = NULL;
166     
167     //fprintf(stderr, "change billboard\n");
168     
169     label = actor->image;
170     message = g_markup_printf_escaped("<span bgcolor=\"%s\" foreground=\"%s\">%s: %d \n%s: %d \n%s: %d \n%s: %d</span>", "#FFFFFF", "#000000", 
171                                       _("Missed calls"),
172                                       get_notify_count("missed"), 
173                                       _("Missed sms"),
174                                       get_notify_count("sms"), 
175                                       _("Missed chat"),
176                                       get_notify_count("chat"), 
177                                       _("Missed mail"),
178                                       get_notify_count("mail"));
179     gtk_label_set_markup(GTK_LABEL(label), message);
180     g_free(message);
181     pfd = pango_font_description_from_string("Sans 14");
182     gtk_widget_modify_font(GTK_WIDGET(label), NULL);
183     gtk_widget_modify_font(GTK_WIDGET(label), pfd);
184     pango_font_description_free(pfd);
185     actor->time_start_animation = time(NULL) + 20;    
186 }
187
188
189 void 
190 change_billboard1(Actor * actor, AWallpaperPlugin *desktop_plugin)
191 {
192     GtkWidget *label;
193     sqlite3 *db = NULL;
194     sqlite3_stmt *res = NULL;
195     gchar *errMsg = NULL, *message;
196     gchar sql[1024];
197     gint call_count=0, sms_count=0, rc=0;
198     GtkListStore *list = NULL;
199     PangoFontDescription *pfd = NULL;
200     
201     rc = sqlite3_open("/home/user/.rtcom-eventlogger/el.db", &db);
202     if (rc){
203         fprintf(stderr, "error open db %d %s\n", rc, sqlite3_errmsg(db));
204     }else {
205         snprintf(sql, sizeof(sql)-1, "select count(id) from Events where event_type_id=%d", 3);
206 #if 0
207         gtk_list_store_new(1, G_TYPE_INT);
208         rc = sqlite3_exec(db, sql, func_callback, (void*)list, &errMsg);
209         if (rc != SQLITE_OK){
210             fprintf(stderr, "error %s\n", errMsg);
211
212         }
213         fprintf(stderr, "after exec sql=%s rc= %d err=%d \n", sql, rc, errMsg);
214 #endif
215 //#if 0
216         rc = sqlite3_prepare(db, sql, sizeof(sql)-1, &res, NULL);
217         if (rc != SQLITE_OK){
218             fprintf(stderr, "error prepare %d %s\n", rc, sql);
219         }
220         if (sqlite3_step(res) != SQLITE_ROW){
221             fprintf(stderr, "not sqlite_row\n");
222         }
223         call_count = sqlite3_column_int(res, 0);
224         //fprintf(stderr, "count missing calls = %d\n", call_count);
225         sqlite3_finalize(res);
226
227         snprintf(sql, sizeof(sql)-1, "select count(id) from Events where event_type_id=%d and is_read=%d", 7, 0);
228         rc = sqlite3_prepare(db, sql, sizeof(sql)-1, &res, NULL);
229         if (rc != SQLITE_OK){
230             fprintf(stderr, "error prepare %d %s\n", rc, sql);
231         }
232         if (sqlite3_step(res) != SQLITE_ROW){
233             fprintf(stderr, "not sqlite_row\n");
234         }
235         sms_count = sqlite3_column_int(res, 0);
236         //fprintf(stderr, "count sms = %d\n", sms_count);
237         sqlite3_finalize(res);
238
239 //#endif
240         sqlite3_close(db);
241     }
242     label = actor->image;
243     message = g_markup_printf_escaped("<span bgcolor=\"%s\" foreground=\"%s\">Missed calls: %d Unread sms: %d</span>", "#FFFFFF", "#000000", call_count, sms_count);
244     gtk_label_set_markup(GTK_LABEL(label), message);
245     g_free(message);
246     pfd = pango_font_description_from_string("Sans 14");
247     gtk_widget_modify_font(GTK_WIDGET(label), NULL);
248     gtk_widget_modify_font(GTK_WIDGET(label), pfd);
249     pango_font_description_free(pfd);
250     actor->time_start_animation = time(NULL) + 20;    
251 }
252
253
254 void 
255 change_moon(Actor * actor, AWallpaperPlugin *desktop_plugin)
256 {
257     gint phase;
258     char *newfile;
259     gint x0 = 150,
260          x1 = 650, 
261          x, y;
262     struct timeval tvb;     
263     suseconds_t ms;
264     long sec;
265     double t;
266 #if 0
267     gint y0, y1, x2, y2;
268     double a, b, c;
269     a = (double)(y2 - (double)(x2*(y1-y0) + x1*y0 - x0*y1)/(x1-x0))/(x2*(x2-x0-x1)+x0*x1);
270     b = (double)(y1-y0)/(x1-x0) - (double)a*(x0+x1);
271     c = (double)(x1*y0 - x0*y1)/(x1-x0) + (double)a*x0*x1;
272     fprintf(stderr, "a=%f, b=%f, c=%f\n", a, b, c);
273 #endif
274     gettimeofday(&tvb, NULL);
275     
276     ms = tvb.tv_usec;
277     sec = tvb.tv_sec;
278
279     if (actor){
280         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT){
281             if (!actor->visible){
282                 actor->visible = TRUE;
283                 phase = get_moon_phase();
284                 newfile = g_strdup_printf( "%s%d.png", actor->name, phase);
285                 if (actor->filename)
286                     g_free(actor->filename);
287                 actor->filename = newfile;
288                 actor->time_start_animation = sec - fast_rnd(60 * 60);
289                 actor->duration_animation = 1 * 60 * 60;
290                 create_hildon_actor(actor, desktop_plugin);
291
292             }
293             t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
294             if (t <= 1)
295                 x = path_line(x0, x1, t);
296             else 
297                 x = path_line(x1, x0, t-1);
298             y = 0.001920*x*x - 1.536*x + 337.2;
299             //y = a*x*x + b*x + c;
300
301             set_actor_position(actor, x, y, actor->z, desktop_plugin);
302
303             if (t>=2){
304                 actor->time_start_animation = sec;
305             }
306
307          }else if (actor->visible){
308             actor->visible = FALSE;
309             fprintf(stderr, "destroy moon \n");
310             destroy_hildon_actor(actor);
311             actor->time_start_animation = 0;
312         } 
313     }
314     
315 }
316
317 void 
318 change_sun(Actor * actor, AWallpaperPlugin *desktop_plugin)
319 {
320     double alt, azm;
321     gint x, y;
322
323     //fprintf(stderr, "change sun\n");
324     if (actor){
325         if (desktop_plugin->priv->scene->daytime != TIME_NIGHT){
326             if (!actor->visible){
327                 actor->visible = TRUE;
328                 create_hildon_actor(actor, desktop_plugin);
329             }
330             get_sun_pos(&alt, &azm);
331             get_sun_screen_pos(alt, azm, &x, &y);
332             actor->x = x;
333             actor->y = y;
334             set_actor_position(actor, x, y, actor->z, desktop_plugin);
335             actor->time_start_animation = time(NULL) + 60;
336          }else if (actor->visible){
337             actor->visible = FALSE;
338             destroy_hildon_actor(actor);
339             actor->time_start_animation = 0;
340         } 
341     }
342     
343 }
344
345 void 
346 change_tram(Actor * actor, AWallpaperPlugin *desktop_plugin)
347 {
348     gint x0 = -300, y0 = 225, scale0 = 100,
349          x1 = 800, y1 = 162, scale1 = 130, 
350          x, y, scale;
351     struct timeval tvb;     
352     suseconds_t ms;
353     long sec;
354     double t;
355
356     //fprintf(stderr, "change tram\n");
357     gettimeofday(&tvb, NULL);
358     
359     ms = tvb.tv_usec;
360     sec = tvb.tv_sec;
361     
362     if (!actor->visible){
363         actor->visible = TRUE;
364         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT){
365             if (actor->filename)
366                 g_free(actor->filename);
367             actor->filename = g_strdup("tram_dark.png");
368         } else{
369             if (actor->filename)
370                 g_free(actor->filename);
371             actor->filename = g_strdup("tram.png");
372         }
373         create_hildon_actor(actor, desktop_plugin);
374     }
375     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
376     x = path_line(x0, x1, t);
377     y = path_line(y0, y1, t);
378     scale = path_line(scale0, scale1, t);
379     set_actor_position(actor, x, y, actor->z, desktop_plugin);
380     set_actor_scale(actor, (double)scale/100, (double)scale/100);
381     if (t >= 1){
382         /* stop animation */
383         actor->visible = FALSE;
384         destroy_hildon_actor(actor);
385         actor->time_start_animation = sec + fast_rnd(60);
386     }
387 }
388
389 void
390 change_plane1(Actor *actor, AWallpaperPlugin *desktop_plugin)
391 {
392     gint x0 = 620, y0 = 233,
393          x1 = 79, y1 = -146, 
394          x, y;
395     struct timeval tvb;     
396     suseconds_t ms;
397     long sec;
398     double t;
399
400     gettimeofday(&tvb, NULL);
401     
402     ms = tvb.tv_usec;
403     sec = tvb.tv_sec;
404 //    fprintf(stderr, "1 %f - %d\n", sec+(double)ms/100000, now);
405    
406     if (desktop_plugin->priv->scene->daytime != TIME_NIGHT){
407         if (actor->time_start_animation == 0){
408             actor->time_start_animation = sec + fast_rnd(180);
409             return;
410         }
411     }
412     if (!actor->visible){
413         actor->visible = TRUE;
414         create_hildon_actor(actor, desktop_plugin);
415     }
416     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
417     x = path_line(x0, x1, t);
418     y = path_line(y0, y1, t);
419     //scale = path_line(scale0, scale1, t);
420     set_actor_position(actor, x, y, actor->z, desktop_plugin);
421     if (t >= 1){
422         /* stop animation */
423         actor->visible = FALSE;
424         destroy_hildon_actor(actor);
425         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT) 
426             actor->time_start_animation = 0;
427         else 
428             actor->time_start_animation = sec + fast_rnd(180);
429     }
430
431 }
432
433 void
434 change_plane2(Actor *actor, AWallpaperPlugin *desktop_plugin)
435 {
436     gint x0 = -actor->width, y0 = 45,
437          x1 = 800, y1 = 20, 
438          x, y;
439     struct timeval tvb;     
440     suseconds_t ms;
441     long sec;
442     double t;
443
444     gettimeofday(&tvb, NULL);
445     
446     ms = tvb.tv_usec;
447     sec = tvb.tv_sec;
448 //    fprintf(stderr, "1 %f - %d\n", sec+(double)ms/100000, now);
449     if (desktop_plugin->priv->scene->daytime != TIME_NIGHT){
450         if (actor->time_start_animation == 0){
451             actor->time_start_animation = sec + fast_rnd(180);
452             return;
453         }
454     }
455     if (!actor->visible){
456         actor->visible = TRUE;
457         create_hildon_actor(actor, desktop_plugin);
458     }
459
460     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
461     x = path_line(x0, x1, t);
462     y = path_line(y0, y1, t);
463     //scale = path_line(scale0, scale1, t);
464     set_actor_position(actor, x, y, actor->z, desktop_plugin);
465     if (t >= 1){
466         /* stop animation */
467         actor->visible = FALSE;
468         destroy_hildon_actor(actor);
469         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT) 
470             actor->time_start_animation = 0;
471         else 
472             actor->time_start_animation = sec + fast_rnd(180);
473     }
474
475 }
476
477 void
478 change_cloud(Actor *actor, AWallpaperPlugin *desktop_plugin)
479 {
480     gint x0, y0 = 300, scale0 = 100,
481          x1, y1 = -actor->height, scale1 = 150, 
482          x, y, scale;
483     struct timeval tvb;     
484     suseconds_t ms;
485     long sec;
486     double t;
487     gchar *newfile;
488
489     //fprintf(stderr, "change cloud\n");
490     gettimeofday(&tvb, NULL);
491     
492     ms = tvb.tv_usec;
493     sec = tvb.tv_sec;
494    
495     if (!actor->visible){
496         actor->visible = TRUE;
497         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT){
498             newfile = g_strdup_printf("%s_dark.png", actor->name);
499         }else{
500             newfile = g_strdup_printf("%s.png", actor->name);
501         } 
502         if (actor->filename)
503             g_free(actor->filename);
504         actor->filename = newfile;
505          
506         create_hildon_actor(actor, desktop_plugin);
507     }
508     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
509     
510     if (desktop_plugin->priv->scene->wind_orientation == 1){
511         x0 = -actor->width;
512         x1 = 800;
513     }
514     else {
515         x0 = 800;
516         x1 = -actor->width;
517     }
518
519     x = path_line(x0, x1, t);    
520     y = -desktop_plugin->priv->scene->wind_angle * (x - x0) + actor->y;
521     scale = path_line(scale0, scale1, (double)(y - y0)/(y1 - y0));
522
523     set_actor_position(actor, x, y, actor->z, desktop_plugin);
524     set_actor_scale(actor, (double)scale/100, (double)scale/100);
525     if ((y < y1 || y > y0) || t >= 1){
526         /* stop animation */
527         actor->visible = FALSE;
528         destroy_hildon_actor(actor);
529         actor->time_start_animation = sec + fast_rnd(300);
530         actor->y = fast_rnd(300);
531     }
532
533 }
534
535 void
536 change_wind(Actor *actor, AWallpaperPlugin *desktop_plugin)
537 {
538     desktop_plugin->priv->scene->wind_orientation = fast_rnd(2);
539     if (desktop_plugin->priv->scene->wind_orientation == 0) desktop_plugin->priv->scene->wind_orientation = -1;
540     desktop_plugin->priv->scene->wind_angle = (double)(fast_rnd(200) - 100) / 100;
541     actor->time_start_animation = time(NULL) + (fast_rnd(10) + 10) * 60;
542     //fprintf(stderr, "change wind orient = %d angle = %f after = %d\n", scene.wind_orientation, scene.wind_angle, actor->time_start_animation-time(NULL));
543 }
544
545 void 
546 change_window1(Actor * actor, AWallpaperPlugin *desktop_plugin)
547 {
548     gint now = time(NULL);
549     if (desktop_plugin->priv->scene->daytime == TIME_DAY){
550         if (actor->widget){
551             actor->visible = FALSE;
552             destroy_hildon_actor(actor);
553         }
554         actor->time_start_animation = 0;
555         return;
556     }else {
557         if (!actor->widget)
558             create_hildon_actor(actor, desktop_plugin);
559         if (actor->time_start_animation == 0){
560             actor->time_start_animation = now + fast_rnd(30);
561             return;
562         }
563     }
564
565     if (!actor->visible)
566         actor->visible = TRUE;
567     else 
568         actor->visible = FALSE;
569     set_actor_visible(actor, actor->visible);
570     actor->time_start_animation = now + fast_rnd(60) + 10;
571
572 }
573
574 void 
575 change_signal(Actor * actor, AWallpaperPlugin *desktop_plugin)
576 {
577     gint now = time(NULL);
578     Actor *a;
579     a = g_ptr_array_index(actor->child, 0);
580     if (a->visible)
581         a->visible = FALSE;
582     else 
583         a->visible = TRUE;
584     set_actor_visible(a, a->visible);
585     
586     a = g_ptr_array_index(actor->child, 1);
587     if (a->visible)
588         a->visible = FALSE;
589     else 
590         a->visible = TRUE;
591     set_actor_visible(a, a->visible);
592
593     actor->time_start_animation = now + fast_rnd(30) + 10;
594 }
595
596 void
597 change_layer(Actor * actor, AWallpaperPlugin *desktop_plugin)
598 {
599     gint y, speed1 = 8, speed2 = 16;
600     Actor *a;
601
602     if (!desktop_plugin->priv->rich_animation) return;
603
604     a = g_ptr_array_index(actor->child, 0);
605     y = a->y + speed1;
606     if (y > 480) y = -480;
607     set_actor_position(a, a->x, y, a->z, desktop_plugin);
608     a->y = y;
609     
610     a = g_ptr_array_index(actor->child, 1);
611     y = a->y + speed1;
612     if (y > 480) y = -480;
613     set_actor_position(a, a->x, y, a->z, desktop_plugin);
614     a->y = y;
615
616     a = g_ptr_array_index(actor->child, 2);
617     y = a->y + speed2;
618     if (y > 480) y = -480;
619     set_actor_position(a, a->x, y, a->z, desktop_plugin);
620     a->y = y;
621
622     a = g_ptr_array_index(actor->child, 3);
623     y = a->y + speed2;
624     if (y > 480) y = -480;
625     set_actor_position(a, a->x, y, a->z, desktop_plugin);
626     a->y = y;
627 }
628
629 void 
630 change_static_actor(Actor * actor, AWallpaperPlugin *desktop_plugin)
631 {
632     gchar *newfile;
633     newfile = g_strdup_printf("%s%d.png", actor->name, desktop_plugin->priv->scene->daytime); 
634     if (actor->filename)
635             g_free(actor->filename);
636     actor->filename = newfile;
637     change_hildon_actor(actor, desktop_plugin);
638 }
639
640 void 
641 change_static_actor_with_corner(Actor * actor, AWallpaperPlugin *desktop_plugin)
642 {
643     gchar buffer[2048];
644
645     if (desktop_plugin->priv->right_corner)
646         gtk_widget_destroy(desktop_plugin->priv->right_corner);
647     snprintf(buffer, sizeof(buffer) - 1, "%s/%s/town%i_right_corner.png", \
648                                   THEME_PATH, desktop_plugin->priv->theme, desktop_plugin->priv->scene->daytime);
649     desktop_plugin->priv->right_corner = gtk_image_new_from_file (buffer);
650     if (desktop_plugin->priv->right_corner){
651         gtk_fixed_put(GTK_FIXED(desktop_plugin->priv->main_widget), desktop_plugin->priv->right_corner, 0, 0);
652         gtk_widget_show (desktop_plugin->priv->right_corner);
653     }
654     change_static_actor(actor, desktop_plugin);
655
656 }