fixed memory leak
[livewp] / applet / src / livewp-home-widget.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-common.h" 
26 #include "livewp-home-widget.h"
27 #include <gconf/gconf-client.h>
28 #include "livewp-rules.h"
29 #include "livewp-scene.h"
30 #include <sys/time.h>
31 #include <stdlib.h>
32
33 #define GCONF_KEY_POSITION "/apps/osso/hildon-desktop/applets/livewp-home-widget.desktop-%i/position"
34 #define GCONF_KEY_MODIFIED "/apps/osso/hildon-desktop/applets/livewp-home-widget.desktop-%i/modified"
35 #define GCONF_KEY_VIEW     "/apps/osso/hildon-desktop/applets/livewp-home-widget.desktop-%i/view"
36
37 HD_DEFINE_PLUGIN_MODULE (AWallpaperPlugin, animation_wallpaper_plugin, HD_TYPE_HOME_PLUGIN_ITEM)
38 #define Animation_Wallpaper_HOME_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE (obj,\
39                                                           Animation_Wallpaper_TYPE_HOME_PLUGIN,\
40                                                           Animation_WallpaperPrivate))
41 static void
42 lw_applet_realize (GtkWidget *widget)
43 {
44     GdkScreen *screen;
45     gchar * strid; 
46     gint id; 
47     AWallpaperPlugin *desktop_plugin = widget;
48
49     fprintf(stderr,"ddddddddddddd %s\n", hd_plugin_item_get_plugin_id (HD_PLUGIN_ITEM (widget)));
50     strid = g_strdup(hd_plugin_item_get_plugin_id (HD_PLUGIN_ITEM (widget)));
51     id = strid[strlen(strid)-1] - '0';
52     desktop_plugin->priv->view = id + 1;
53     g_free(strid); 
54     init_scene_theme(desktop_plugin);
55         
56     desktop_plugin->priv->long_timer = g_timeout_add(LONG_TIMER, (GtkFunction)long_timeout, desktop_plugin);
57
58     screen = gtk_widget_get_screen (widget);
59     gtk_widget_set_colormap (widget,
60                                 gdk_screen_get_rgba_colormap (screen));
61     gtk_widget_set_app_paintable (widget,
62                                 TRUE);
63     GTK_WIDGET_CLASS (animation_wallpaper_plugin_parent_class)->realize (widget);
64 }
65
66
67 static gboolean
68 lw_applet_expose_event(GtkWidget      *widget,
69                                         GdkEventExpose *event)
70 {
71   cairo_t *cr;
72
73   /* Create cairo context */
74   cr = gdk_cairo_create (GDK_DRAWABLE (widget->window));
75   gdk_cairo_region (cr, event->region);
76   cairo_clip (cr);
77
78   /* Draw alpha background */
79   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
80   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
81   cairo_paint (cr);
82
83   /* Free context */
84   cairo_destroy (cr);
85
86   return GTK_WIDGET_CLASS (animation_wallpaper_plugin_parent_class)->expose_event (widget,
87                                                                                   event);
88 }
89
90 static gboolean
91 expose_event (GtkWidget *widget,GdkEventExpose *event,
92      gpointer data)
93 {
94     cairo_t *cr;
95     GdkPixbuf *pixbuf = (GdkPixbuf *) data;
96         
97     cr = gdk_cairo_create(widget->window);
98     if (cr){
99         gdk_cairo_region(cr, event->region);
100         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
101         gdk_cairo_set_source_pixbuf(cr, pixbuf, 0.0, 0.0);
102         cairo_paint(cr);
103         cairo_destroy(cr);
104     }
105     return TRUE;
106 }
107
108 static void
109 realize (GtkWidget *widget)
110 {
111     GdkScreen *screen;
112     screen = gtk_widget_get_screen (widget);
113     gtk_widget_set_colormap (widget, gdk_screen_get_rgba_colormap (screen));
114 }
115 /* Set position of widget on desktop */
116 static void
117 init_applet_position(gint *xapplet, gint *yapplet)
118 {
119   GSList *position = NULL;
120   gchar *position_key;
121   gchar *modified_key;
122   gchar *modified;
123   GError *error = NULL;
124   gint i;
125   GConfClient   *gconf_client = gconf_client_get_default ();
126   for (i=0;i<4;i++){
127       position_key = g_strdup_printf (GCONF_KEY_POSITION, i);
128       position = gconf_client_get_list (gconf_client,
129                                         position_key,
130                                         GCONF_VALUE_INT,
131                                         NULL);
132       if (position && position->data && position->next->data){
133         *xapplet = GPOINTER_TO_INT (position->data);
134         *yapplet = GPOINTER_TO_INT (position->next->data);
135       }else{
136         position = g_slist_prepend (g_slist_prepend (NULL,
137                                           GINT_TO_POINTER (Ystartposition)),
138                               GINT_TO_POINTER (Xstartposition));
139         gconf_client_set_list (gconf_client,
140                                    position_key,
141                                    GCONF_VALUE_INT,
142                                position,
143                        &error);
144         *xapplet = Xstartposition;
145         *yapplet = Ystartposition;
146       }
147       g_free (position_key);
148       modified = g_strdup_printf ("%i", 0);
149       modified_key = g_strdup_printf (GCONF_KEY_MODIFIED, i);
150       gconf_client_set_string (gconf_client,
151                                modified_key,
152                                modified,
153                                &error);
154       g_free(modified);
155       g_free(modified_key);
156       modified_key = g_strdup_printf (GCONF_KEY_VIEW, i);
157       gconf_client_set_int (gconf_client,
158                                modified_key,
159                                (i+1),
160                                &error);
161       g_free(modified_key);
162
163   }
164   gconf_client_clear_cache(gconf_client);
165   g_object_unref(gconf_client);
166 }
167 #if 0
168 void
169 actor_set_position_full(GtkWidget *actor, gint x, gint y, gint z)
170 {
171 /*  fprintf(stderr, "actor_set_position_full z=%d\n", z); */
172     hildon_animation_actor_set_position_full (HILDON_ANIMATION_ACTOR (actor),x-0, y-0, z);
173 }
174 #endif
175
176 void
177 destroy_hildon_actor(Actor *actor)
178 {
179     //fprintf(stderr, "destroy_hildon_actor %s\n",actor->name);
180     gtk_widget_destroy(actor->widget);
181     actor->widget = NULL;
182 }
183
184 void
185 create_hildon_actor_text(Actor *actor, AWallpaperPlugin *desktop_plugin) 
186 {
187   GtkWidget *ha = NULL;
188   GdkPixbuf *pixbuf = NULL;
189   GtkWidget *image = NULL;
190   GtkWidget *label = NULL;
191
192   ha = hildon_animation_actor_new();
193   label = gtk_label_new(NULL);  
194
195   if (label){
196     //g_signal_connect(G_OBJECT(label), "expose_event", G_CALLBACK(expose_event), NULL);
197
198     gtk_container_add (GTK_CONTAINER (ha), label);
199   }  
200   realize(ha);
201   gtk_widget_show(label);
202   gtk_widget_show_all(ha);
203   
204   /* TO DO check it */
205   /*  gdk_flush (); */
206
207   //g_object_set_data(G_OBJECT(ha), "image", image);
208   actor->image = label;
209   hildon_animation_actor_set_parent (HILDON_ANIMATION_ACTOR (ha), GTK_WINDOW(desktop_plugin));
210   actor->widget = ha;
211   set_actor_position(actor, actor->x, actor->y, actor->z, desktop_plugin);
212   set_actor_scale(actor, (double)actor->scale/100, (double)actor->scale/100);
213   set_actor_visible(actor, actor->visible);
214 }
215
216
217
218 void
219 create_hildon_actor(Actor *actor, AWallpaperPlugin *desktop_plugin) 
220 {
221   GtkWidget *ha = NULL;
222   GdkPixbuf *pixbuf = NULL;
223   GtkWidget *image = NULL;
224   gchar     *str = NULL;
225
226   ha = hildon_animation_actor_new();
227   str = g_strdup_printf( "%s/%s/%s", THEME_PATH, 
228                         desktop_plugin->priv->theme, actor->filename);
229   pixbuf = gdk_pixbuf_new_from_file_at_size (str, 
230                                              actor->width, 
231                                              actor->height, 
232                                              NULL);
233   /*fprintf(stderr, "create_hildon_actor %s %s\n", actor->name, str);*/
234   if (str)
235       g_free(str);
236   if (pixbuf){
237       image = gtk_image_new_from_pixbuf (pixbuf);
238       g_object_unref(G_OBJECT(pixbuf));
239   }
240   if (image){
241     g_signal_connect(G_OBJECT(image), "expose_event",
242                            G_CALLBACK(expose_event), pixbuf);
243     gtk_container_add (GTK_CONTAINER (ha), image);
244   }  
245   realize(ha);
246   gtk_widget_show_all(ha);
247   
248   /* TO DO check it */
249   /*  gdk_flush (); */
250
251   //g_object_set_data(G_OBJECT(ha), "image", image);
252   actor->image = image;
253   hildon_animation_actor_set_parent (HILDON_ANIMATION_ACTOR (ha), GTK_WINDOW(desktop_plugin));
254
255   actor->widget = ha;
256   set_actor_position(actor, actor->x, actor->y, actor->z, desktop_plugin);
257   set_actor_scale(actor, (double)actor->scale/100, (double)actor->scale/100);
258   set_actor_visible(actor, actor->visible);
259 }
260
261
262 void
263 change_hildon_actor(Actor *actor, AWallpaperPlugin *desktop_plugin)
264 {
265     GtkWidget *image = NULL;
266     GdkPixbuf *pixbuf = NULL;
267     gchar     *str = NULL;
268
269     str = g_strdup_printf( "%s/%s/%s", THEME_PATH, 
270                             desktop_plugin->priv->theme, actor->filename);
271  
272     pixbuf = gdk_pixbuf_new_from_file_at_size (str, 
273                                                actor->width, 
274                                                actor->height, 
275                                                NULL);
276     if(str)
277         g_free(str);
278     if (pixbuf){
279         image = gtk_image_new_from_pixbuf (pixbuf);
280         g_object_unref(G_OBJECT(pixbuf));
281     }
282     if (image){ 
283         g_signal_connect(G_OBJECT(image), "expose_event",
284                                        G_CALLBACK(expose_event), pixbuf);
285         //if (g_object_get_data(G_OBJECT(actor->widget), "image")){
286         if (actor->image){
287             gtk_container_remove(GTK_CONTAINER(actor->widget), actor->image);  
288         }
289         //g_object_set_data(G_OBJECT(actor->widget), "image", image);
290         actor->image = image;
291         gtk_container_add (GTK_CONTAINER (actor->widget), image);
292         realize(actor->widget);
293         gtk_widget_show_all(actor->widget);
294         /* TO DO check it */
295        /*  gdk_flush (); */
296
297
298     }
299
300 }
301
302
303 static gboolean
304 short_timeout (AWallpaperPlugin *desktop_plugin)
305 {
306     //gint daytime = get_daytime();
307     GSList * tmp;
308     void (*pfunc)(gpointer, gpointer);
309     time_t now;
310     Actor *actor;
311     gboolean stop_flag = TRUE;
312
313 if (!desktop_plugin->priv->visible || !desktop_plugin->priv->rich_animation){
314         desktop_plugin->priv->short_timer = 0;
315         return FALSE;
316     }
317
318     now = time(NULL);
319     //scene.daytime = daytime;
320     /* fprintf(stderr, "Short timer %d\n", now); */
321     tmp = desktop_plugin->priv->scene->actors;
322     while (tmp != NULL){
323            actor = tmp->data;
324            if (now >= actor->time_start_animation  
325                && actor->time_start_animation > 0
326                /* && now - actor->time_start_animation <= actor->duration_animation*/){
327                 pfunc = actor->func_change;
328                 if (pfunc){ 
329                     (*pfunc)(actor, desktop_plugin);
330                     stop_flag = FALSE;
331                 }
332             }
333             tmp = g_slist_next(tmp);
334     }
335     if (stop_flag){
336          desktop_plugin->priv->short_timer = 0;
337          return FALSE;
338     }else
339          return TRUE; /* keep running this event */
340 }
341
342 void
343 run_long_timeout(AWallpaperPlugin *desktop_plugin)
344 {
345
346     gint daytime = get_daytime();
347     GSList * tmp;
348     void (*pfunc)(gpointer, gpointer);
349     time_t now;
350     Actor *actor;
351
352     if (!desktop_plugin->priv->scene)
353         return;
354     //fprintf(stderr, "!!!run long timeout short_timer=%d\n", desktop_plugin->priv->short_timer);
355     if (desktop_plugin->priv->scene->daytime != daytime){
356         desktop_plugin->priv->scene->daytime = daytime;
357         tmp = desktop_plugin->priv->scene->actors;
358         while (tmp != NULL){
359             //change_actor(tmp->data);
360             pfunc =((Actor*)tmp->data)->func_change;
361             if (pfunc){
362                 (*pfunc)(tmp->data, desktop_plugin);
363             }
364             tmp = g_slist_next(tmp);
365         }
366     }
367    
368     now = time(NULL);
369     //fprintf(stderr, "Now  %d\n", now);
370     tmp = desktop_plugin->priv->scene->actors;
371     while (tmp != NULL){
372         actor = tmp->data;
373         if (now >= actor->time_start_animation  
374             && actor->time_start_animation > 0
375             && desktop_plugin->priv->short_timer == 0){
376             /* fprintf(stderr, "start short timer act = %s %d\n", actor->name, now); */
377             if (desktop_plugin->priv->rich_animation){
378                 actor->time_start_animation = now;
379                 desktop_plugin->priv->short_timer = g_timeout_add(SHORT_TIMER, (GtkFunction)short_timeout, desktop_plugin);
380             }
381             else {
382                 (*actor->func_change)(actor, desktop_plugin);
383             }
384         }
385         tmp = g_slist_next(tmp);
386     }
387  
388 }
389
390 static gboolean
391 long_timeout (AWallpaperPlugin *desktop_plugin)
392 {
393     /* fprintf(stderr, "long_timeout %i\n", desktop_plugin->priv->long_timer); */
394     if (desktop_plugin->priv->long_timer == 0 )
395         return FALSE;
396     if (!desktop_plugin->priv->visible){
397         if(desktop_plugin->priv->short_timer != 0){
398             g_source_remove(desktop_plugin->priv->short_timer);
399             desktop_plugin->priv->short_timer = 0;
400         }
401         desktop_plugin->priv->long_timer = 0;
402         return FALSE;
403     }
404   
405
406     run_long_timeout(desktop_plugin);
407     return TRUE; /* keep running this event */
408 }
409
410 static void
411 desktop_plugin_visible_notify (GObject    *object,
412                                           GParamSpec *spec,
413                                           AWallpaperPlugin *desktop_plugin)
414 {
415     gboolean visible;
416     g_object_get (object, "is-on-current-desktop", &visible, NULL);
417     /* fprintf (stderr, "is-on-current-desktop changed. visible: %u", visible); */
418     if (visible){
419         desktop_plugin->priv->visible = TRUE;
420         if (desktop_plugin->priv->long_timer == 0 ){
421             desktop_plugin->priv->long_timer = g_timeout_add(LONG_TIMER, (GtkFunction)long_timeout, desktop_plugin);
422             run_long_timeout(desktop_plugin);
423         }
424     }else{
425         desktop_plugin->priv->visible = FALSE;
426         if (desktop_plugin->priv->long_timer != 0 ){
427             g_source_remove(desktop_plugin->priv->long_timer);
428             desktop_plugin->priv->long_timer = 0;
429         }
430     }
431 }
432 gboolean
433 rich_animation_press(GtkWidget *widget, GdkEvent *event,
434                                             gpointer user_data){
435     fprintf(stderr,"gggggggggggggggggggg2222\n");
436     return FALSE;
437 }    
438 static void
439 animation_wallpaper_plugin_init (AWallpaperPlugin *desktop_plugin)
440 {
441     GtkWidget *rich_animation;
442     gchar           buffer[2048];
443     gchar str[128];
444
445     //fprintf(stderr, "!!!!!!!plugin init \n");
446     Animation_WallpaperPrivate *priv =  Animation_Wallpaper_HOME_PLUGIN_GET_PRIVATE (desktop_plugin);
447     desktop_plugin->priv =  Animation_Wallpaper_HOME_PLUGIN_GET_PRIVATE (desktop_plugin);
448     priv->osso = osso_initialize(PACKAGE, VERSION, TRUE, NULL);
449
450     /* Load config */
451     read_config(priv);
452     /* Initialize DBUS */
453     livewp_initialize_dbus(priv);
454
455     priv->desktop_plugin = desktop_plugin;
456     priv->visible = TRUE;
457     priv->short_timer = 0;
458     priv->xapplet = 0;
459     priv->yapplet = 0;
460     priv->scene = NULL;
461 //    priv->theme = g_strdup("Modern");
462 //#if 0 
463     priv->hash_scene_func = g_hash_table_new(g_str_hash, g_str_equal);
464     
465     g_hash_table_insert(priv->hash_scene_func, g_strdup("Berlin"), (gpointer)&init_scene_Berlin);
466     g_hash_table_insert(priv->hash_scene_func, g_strdup("Modern"), (gpointer)&init_scene_Modern);
467     g_hash_table_insert(priv->hash_scene_func, g_strdup("Matrix"), (gpointer)&init_scene_Matrix);
468 //#endif
469     //priv->theme = g_strdup("Modern");
470     desktop_plugin->priv->main_widget = gtk_fixed_new();
471
472     gtk_widget_set_size_request(desktop_plugin->priv->main_widget, 100, 32);
473     desktop_plugin->priv->right_corner = NULL;
474     snprintf(buffer, sizeof(buffer) - 1, "%s/%s/%s", THEME_PATH, desktop_plugin->priv->theme, "town0_right_corner.png");
475     desktop_plugin->priv->right_corner = gtk_image_new_from_file (buffer);
476     if (desktop_plugin->priv->right_corner){
477         gtk_fixed_put(GTK_FIXED(desktop_plugin->priv->main_widget), desktop_plugin->priv->right_corner, 0, 0);
478         gtk_widget_show (desktop_plugin->priv->right_corner);
479     }
480     /* Create rich animation event */
481     rich_animation = gtk_event_box_new();
482     if(rich_animation){
483         gtk_widget_set_events(rich_animation, GDK_BUTTON_PRESS_MASK);
484         gtk_event_box_set_visible_window(GTK_EVENT_BOX(rich_animation), FALSE);
485         gtk_widget_set_size_request(rich_animation, 100, 32);
486         gtk_widget_show (rich_animation);
487         g_signal_connect(rich_animation, "button-press-event", G_CALLBACK(rich_animation_press), desktop_plugin);
488         gtk_fixed_put(GTK_FIXED(desktop_plugin->priv->main_widget), rich_animation, 0, 0);
489     }
490 #if 0
491     GtkWidget *label = gtk_label_new ("1111ddddddddd");
492     gtk_widget_set_size_request(label, 95, 30);
493     gtk_widget_show (label);
494     gtk_container_add (GTK_CONTAINER (desktop_plugin), label);
495 #endif
496     hd_home_plugin_item_set_settings (HD_HOME_PLUGIN_ITEM (desktop_plugin), TRUE);
497     g_signal_connect (desktop_plugin, "show-settings",
498                              G_CALLBACK (show_settings), priv);
499     gtk_widget_show (desktop_plugin->priv->main_widget);
500     gtk_container_add (GTK_CONTAINER (desktop_plugin), desktop_plugin->priv->main_widget);
501     init_applet_position(&(priv->xapplet), &(priv->yapplet));
502
503     
504     //fprintf(stderr, "!!!theme = %s\n", priv->theme);
505     //snprintf(str, sizeof(str) - 1, "%s", "init_scene2");
506     //fprintf(stderr, " str = %s\n", str);
507     priv->scene = NULL;
508 #if 0
509     if (!strcmp(priv->theme,"Modern"))
510         init_scene_Modern(desktop_plugin);
511     else if (!strcmp(priv->theme,"Berlin")) 
512         init_scene_Berlin(desktop_plugin);
513     else if (!strcmp(priv->theme, "Matrix"))
514         init_scene_Matrix(desktop_plugin);
515 #endif
516 //    init_scene_theme(desktop_plugin);
517         
518 //    priv->long_timer = g_timeout_add(LONG_TIMER, (GtkFunction)long_timeout, desktop_plugin);
519     /* TODO Move scene to priv */
520     //scene.timer_type = LONG_TIMER_TYPE;
521     g_signal_connect (desktop_plugin, "notify::is-on-current-desktop",
522                    G_CALLBACK (desktop_plugin_visible_notify), desktop_plugin);
523
524    
525     //sleep(2);
526 }
527
528 static void
529 lw_applet_finalize (GObject *object)
530 {
531 fprintf(stderr,"lw_applet_finalize\n");
532 /*
533      AWallpaperPlugin *desktop_plugin = Animation_Wallpaper_HOME_PLUGIN (object);
534      Animation_WallpaperPrivate *priv = desktop_plugin->priv;
535      
536      if (priv){
537              livewp_deinitialize_dbus(priv);
538              fprintf(stderr,"finalaze %i\n", priv->long_timer);
539              if (priv->long_timer){
540                 g_source_remove(priv->long_timer);
541                 priv->long_timer = 0;
542              }
543              if (priv->short_timer){
544                 g_source_remove(priv->short_timer);
545                 priv->short_timer = 0;
546              }
547
548              destroy_scene(desktop_plugin);
549      }
550 */
551 }
552
553 static void
554 desktop_widget_finalize (GObject *object)
555 {
556      AWallpaperPlugin *desktop_plugin = Animation_Wallpaper_HOME_PLUGIN (object);
557      Animation_WallpaperPrivate *priv = desktop_plugin->priv;
558      
559      if (priv){
560              livewp_deinitialize_dbus(priv);
561              fprintf(stderr,"finalaze %i\n", priv->long_timer);
562              if (priv->long_timer){
563                 g_source_remove(priv->long_timer);
564                 priv->long_timer = 0;
565              }
566              if (priv->short_timer){
567                 g_source_remove(priv->short_timer);
568                 priv->short_timer = 0;
569              }
570
571              destroy_scene(desktop_plugin);
572      }
573       /* Call the base class's implementation: */
574       G_OBJECT_CLASS (animation_wallpaper_plugin_parent_class)->finalize (object);
575 }
576
577 static void
578 animation_wallpaper_plugin_class_init (AWallpaperPluginClass *klass) {
579
580     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
581     GtkObjectClass *gobject_class = GTK_OBJECT_CLASS (klass);
582     GObjectClass *object_class = G_OBJECT_CLASS (klass);
583
584     /* gobject */
585     gobject_class->destroy = (gpointer)lw_applet_finalize;
586     object_class->finalize = desktop_widget_finalize;
587     widget_class->realize = lw_applet_realize;
588     widget_class->expose_event = lw_applet_expose_event;
589
590     g_type_class_add_private (klass, sizeof (Animation_WallpaperPrivate));
591
592 }
593
594 static void
595 animation_wallpaper_plugin_class_finalize (AWallpaperPluginClass *class) {
596 }
597
598 Animation_WallpaperPrivate*
599 animation_wallpaper_plugin_new (void)
600 {
601   return g_object_new (Animation_Wallpaper_TYPE_HOME_PLUGIN , NULL);
602 }
603