Make sure that all timeouts in HildonBanner are removed
[hildon] / examples / hildon-remote-texture-example.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <glib.h>
4 #include <gtk/gtk.h>
5 #include <sys/types.h>
6 #include <sys/shm.h>
7 #include <string.h>
8 #include <math.h>
9 #include <hildon/hildon.h>
10 #include <hildon/hildon-remote-texture.h>
11
12 #define W 800
13 #define H 480
14
15 /* Press and drag to pan around, or tap to move between zoom levels.
16  * A file must be specified on the command-line, and it must be > 640x480.
17  *
18  * This file will be loaded and placed into a shared memory area, which will
19  * be read by hildon-desktop.
20  * An area 640x480 in the top-left corner will be updated with an animation
21  * to show how to modify the area. */
22
23 #define DO_ANIM 1 /* whether to animate the area defined below */
24
25 #define ANIM_X 0
26 #define ANIM_Y 0
27 #define ANIM_WIDTH 640
28 #define ANIM_HEIGHT 480
29 #define ANIM_FRAMES 64
30
31 /* this could come from ftol, but we hardcode it for this example */
32 static key_t shm_key = 0xCAFEBEEF;
33
34 static gint  bpp, width, height;
35 static guchar *shm = 0; /* shared mem area */
36 static int anim_frame = 0;
37
38 static double scale = 1;
39 static double scale_smooth = 1;
40 static double x = 0;
41 static double y = 0;
42 static double x_inc = 0;
43 static double y_inc = 0;
44 static double cursor_move = 0;
45
46 static int last_x, last_y, pressed = 0;
47
48 static void timeout_cb (void *obj)
49 {
50     HildonRemoteTexture *actor = HILDON_REMOTE_TEXTURE (obj);
51
52     if (shm && DO_ANIM) {
53       gint x,y;
54
55       for (y=0;y<ANIM_HEIGHT;y++)
56         {
57           guchar *anim = &shm[(width*(y+ANIM_Y) + ANIM_X)*bpp];
58           for (x=0;x<ANIM_WIDTH;x++)
59             {
60               *anim = ((x+anim_frame)&(ANIM_FRAMES-1)) * 256 / ANIM_FRAMES;
61               anim += bpp;
62             }
63         }
64
65       hildon_remote_texture_update_area(actor,
66           ANIM_X, ANIM_Y, ANIM_WIDTH, ANIM_HEIGHT);
67       anim_frame++;
68     }
69
70     if (!pressed)
71       {
72         if (fabs(x_inc)>0.01 || fabs(y_inc)>0.01)
73           {
74             x += x_inc;
75             y += y_inc;
76             x_inc = x_inc * 0.8;
77             y_inc = y_inc * 0.8;
78             hildon_remote_texture_set_offset (actor, x, y);
79           }
80
81         if (fabs(scale - scale_smooth)>0.01)
82           {
83             scale_smooth = scale_smooth*0.9 + scale*0.1;
84             hildon_remote_texture_set_scale (actor, scale_smooth, scale_smooth);
85           }
86       }
87
88 }
89
90 static void press_cb (GtkWidget *widget,
91                GdkEventButton *event, gpointer data)
92 {
93   pressed = TRUE;
94   last_x = event->x;
95   last_y = event->y;
96   cursor_move = 0;
97 }
98
99 static void release_cb (GtkWidget *widget,
100                GdkEventButton *event, gpointer obj)
101 {
102   pressed = FALSE;
103   last_x = event->x;
104   last_y = event->y;
105
106   if (cursor_move < 40)
107     {
108       scale = scale * 1.5;
109       if (scale>8) scale=0.125;
110       /* scale smooth will actually do the update */
111     }
112 }
113
114 static void motion_cb (GtkWidget *widget,
115                 GdkEventMotion *event, gpointer data)
116 {
117   HildonRemoteTexture *actor = HILDON_REMOTE_TEXTURE(data);
118
119   if (pressed)
120     {
121       x_inc = event->x - last_x;
122       y_inc = event->y - last_y;
123       cursor_move += fabs(x_inc) + fabs(y_inc);
124
125       x_inc /= scale;
126       y_inc /= scale;
127
128       x += x_inc;
129       y += y_inc;
130       hildon_remote_texture_set_offset (actor, x, y);
131     }
132
133   last_x = event->x;
134   last_y = event->y;
135 }
136
137 int
138 main (int argc, char **argv)
139 {
140     gtk_init (&argc, &argv);
141
142     GdkPixbuf        *pixbuf;
143     GError           *error = 0;
144     guchar           *gpixels;
145
146     if (argc!=2)
147       {
148         printf("USAGE: hildon-remote-texture-example image.png\n");
149         printf("NB. Image should be 640x480 in size or greater\n");
150         return EXIT_FAILURE;
151       }
152
153     g_debug("Loading Image %s...", argv[1]);
154     pixbuf          = gdk_pixbuf_new_from_file (argv[1], &error);
155     width           = gdk_pixbuf_get_width (pixbuf);
156     height          = gdk_pixbuf_get_height (pixbuf);
157     bpp             = gdk_pixbuf_get_n_channels (pixbuf); /* assume 8 bit */
158     gpixels         = gdk_pixbuf_get_pixels (pixbuf);
159     g_debug("Creating Shared Memory");
160     size_t shm_size = width*height*bpp;
161     int shmid;
162
163     /*
164      * Create the segment, attach it to our data space, and copy in the
165      * texture we loaded
166      */
167     if ((shmid = shmget(shm_key, shm_size, IPC_CREAT | 0666)) < 0) {
168         perror("shmget");
169         exit(1);
170     }
171
172     if ((shm = shmat(shmid, NULL, 0)) == (guchar *) -1) {
173         perror("shmat");
174         exit(1);
175     }
176
177     memcpy(shm, gpixels, shm_size);
178     g_debug("Done.");
179
180     /* Craete the program with the remote texture */
181     HildonProgram *program = hildon_program_get_instance ();
182     HildonWindow *window = HILDON_WINDOW(
183         hildon_window_new());
184     hildon_program_add_window (program, window);
185     gtk_widget_show (GTK_WIDGET(window));
186
187     HildonRemoteTexture *actor = HILDON_REMOTE_TEXTURE
188         (hildon_remote_texture_new ());
189
190     g_set_application_name ("Animation");
191
192     g_signal_connect (G_OBJECT (window),
193                       "delete_event",
194                       G_CALLBACK (gtk_main_quit), NULL);
195     g_signal_connect (G_OBJECT (window),
196                               "button-press-event",
197                               G_CALLBACK (press_cb),
198                               actor);
199     g_signal_connect (G_OBJECT (window),
200                                   "button-release-event",
201                                   G_CALLBACK (release_cb),
202                                   actor);
203     g_signal_connect (G_OBJECT (window),
204                       "motion-notify-event",
205                       G_CALLBACK (motion_cb),
206                       actor);
207     gtk_widget_add_events (GTK_WIDGET(window),
208                            GDK_BUTTON_PRESS_MASK|
209                            GDK_BUTTON_MOTION_MASK|
210                            GDK_BUTTON_RELEASE_MASK);
211
212
213     gtk_widget_show_all (GTK_WIDGET (actor));
214     gdk_flush ();
215
216     /* vital: add this remote texture to a proper window */
217     hildon_remote_texture_set_parent(actor, GTK_WINDOW(window));
218     /* Set the actual data we'll be displaying, via the shm key */
219     hildon_remote_texture_set_image(actor, shm_key, width, height, bpp);
220     /* Set the actual position on the screen */
221     hildon_remote_texture_set_position (actor, 0, 56, W, H-56);
222     hildon_remote_texture_set_show (actor, 1);
223
224     g_timeout_add (25, (GSourceFunc)timeout_cb, actor);
225
226     printf ("going to gtk_main ()\n");
227     gtk_main ();
228     return 0;
229 }