Initial Import
[profile/ivi/clutter-toys.git] / attic / table / clutter-video-player.c
1
2 #include <clutter-gst/clutter-gst.h>
3 #include "clutter-video-player.h"
4 #include "play_png.h"
5 #include "pause_png.h"
6
7 #define CTRL_SIZE 10
8
9 #ifndef CLUTTER_PARAM_READWRITE
10 #define CLUTTER_PARAM_READWRITE \
11         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |G_PARAM_STATIC_BLURB
12 #endif
13
14 G_DEFINE_TYPE (ClutterVideoPlayer, clutter_video_player, CLUTTER_TYPE_GROUP);
15
16 #define CLUTTER_VIDEO_PLAYER_GET_PRIVATE(obj) \
17 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_VIDEO_PLAYER, ClutterVideoPlayerPrivate))
18
19 struct _ClutterVideoPlayerPrivate
20 {
21   ClutterActor    * vtexture;
22
23   ClutterActor    * control;
24   ClutterActor    * control_play;
25   ClutterActor    * control_pause;
26   
27   gboolean          paused;
28
29   gint              width;
30   gint              height;
31   
32   gchar           * uri;
33 };
34
35 static void
36 toggle_pause_state (ClutterVideoPlayer *player);
37
38 static void 
39 input_cb (ClutterStage * stage, ClutterEvent * event, gpointer data);
40
41 static gboolean
42 autostop_playback (gpointer data)
43 {
44   ClutterVideoPlayer        * player = data;
45   ClutterVideoPlayerPrivate * priv = player->priv;
46
47   clutter_actor_show (priv->vtexture);
48
49   toggle_pause_state (player);
50   clutter_media_set_position (CLUTTER_MEDIA (priv->vtexture), 0);
51   return FALSE;
52 }
53
54 static void
55 eos_cb (ClutterMedia * media, gpointer data)
56 {
57   ClutterVideoPlayer * player = data;
58
59   if (!player->priv->paused)
60     toggle_pause_state (player);
61
62   clutter_media_set_position (media, 0);
63 }
64
65 static GdkPixbuf *
66 pixbuf_from_data (const guchar * data, gint length)
67 {
68   GdkPixbuf *pixbuf;
69   GdkPixbufLoader * ldr = gdk_pixbuf_loader_new_with_type ("png", NULL);
70
71   if (!ldr)
72     {
73       g_warning ("Could not create loader");
74       return NULL;
75     }
76   
77   if (!gdk_pixbuf_loader_write (ldr, data, length, NULL))
78     {
79       g_warning ("Failed to write to loader.");
80       return NULL;
81     }
82   
83   pixbuf = gdk_pixbuf_loader_get_pixbuf (ldr);
84
85   return pixbuf;
86 }
87
88 void
89 size_change (ClutterTexture *texture, 
90              gint            width,
91              gint            height,
92              gpointer        data)
93 {
94   ClutterVideoPlayer *player = data;
95   gint h = player->priv->width * height / width;
96   
97   clutter_actor_set_size (CLUTTER_ACTOR (player), player->priv->width, h);
98 }
99
100 static void
101 construct_controls (ClutterVideoPlayer *player)
102 {
103   ClutterVideoPlayerPrivate *priv = player->priv;
104   GdkPixbuf           *pixb;
105
106   priv->vtexture = clutter_gst_video_texture_new ();
107
108   if (priv->vtexture == NULL)
109     g_error("failed to create vtexture");
110   
111   /* Dont let the underlying pixbuf dictate size */
112   g_object_set (G_OBJECT(priv->vtexture), "sync-size", FALSE, NULL);
113
114   g_signal_connect (CLUTTER_TEXTURE(priv->vtexture), 
115                     "size-change",
116                     G_CALLBACK (size_change), player);
117   
118   clutter_media_set_filename(CLUTTER_MEDIA(priv->vtexture), priv->uri);
119   clutter_media_set_playing (CLUTTER_MEDIA(priv->vtexture), TRUE);
120   priv->paused = FALSE;
121   g_signal_connect (priv->vtexture, "eos", G_CALLBACK (eos_cb), player);
122   g_timeout_add (100, autostop_playback, player);
123   
124   priv->control = clutter_group_new ();
125   
126   pixb = pixbuf_from_data (&play_png[0], sizeof (play_png));
127
128   if (pixb == NULL)
129     g_error("Unable to load play button image");
130
131   priv->control_play = clutter_texture_new_from_pixbuf (pixb);
132   clutter_actor_set_size (priv->control_play, CTRL_SIZE, CTRL_SIZE);
133   clutter_actor_show (priv->control_play);
134   
135   pixb = pixbuf_from_data (&pause_png[0], sizeof (pause_png));
136
137   if (pixb == NULL)
138     g_error("Unable to load pause button image");
139
140   priv->control_pause = clutter_texture_new_from_pixbuf (pixb);
141   clutter_actor_set_size (priv->control_pause, CTRL_SIZE, CTRL_SIZE);
142   
143   clutter_group_add_many (CLUTTER_GROUP (priv->control), 
144                           priv->control_play, 
145                           priv->control_pause,
146                           NULL);
147
148   clutter_actor_set_opacity (priv->control, 0xee);
149
150   clutter_actor_set_position (priv->control_play, 0, 0);
151   clutter_actor_set_position (priv->control_pause, 0, 0);
152
153   clutter_group_add_many (CLUTTER_GROUP (player), 
154                           priv->vtexture, priv->control, NULL);
155
156   g_signal_connect (clutter_stage_get_default(), "event",
157                     G_CALLBACK (input_cb), 
158                     player);
159 }
160
161 enum
162 {
163   PROP_0,
164   PROP_URI,
165 };
166
167 static void 
168 clutter_video_player_set_property (GObject      *object, 
169                                   guint         prop_id,
170                                   const GValue *value, 
171                                   GParamSpec   *pspec)
172 {
173   ClutterVideoPlayer        *player;
174   ClutterVideoPlayerPrivate *priv;
175
176   player = CLUTTER_VIDEO_PLAYER(object);
177   priv = player->priv;
178
179   switch (prop_id) 
180     {
181     case PROP_URI:
182       g_free (priv->uri);
183       priv->uri = g_strdup (g_value_get_string (value));
184       break;
185     default:
186       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187       break;
188     }
189 }
190
191 static void 
192 clutter_video_player_get_property (GObject    *object, 
193                                    guint       prop_id,
194                                    GValue     *value, 
195                                    GParamSpec *pspec)
196 {
197   ClutterVideoPlayer        *player;
198   ClutterVideoPlayerPrivate *priv;
199
200   player = CLUTTER_VIDEO_PLAYER(object);
201   priv = player->priv;
202
203   switch (prop_id) 
204     {
205     case PROP_URI:
206       g_value_set_string (value, priv->uri);
207       break;
208     default:
209       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
210       break;
211     }
212 }
213
214 static GObject *
215 clutter_video_player_constructor (GType                  gtype,
216                                   guint                  n_params,
217                                   GObjectConstructParam *params)
218 {
219   GObjectClass       * parent_class;
220   GObject            * retval;
221
222   parent_class = G_OBJECT_CLASS (clutter_video_player_parent_class);
223   retval = parent_class->constructor (gtype, n_params, params);
224
225   construct_controls (CLUTTER_VIDEO_PLAYER (retval));
226   
227   return retval;
228 }
229
230 static void 
231 clutter_video_player_finalize (GObject *object)
232 {
233   ClutterVideoPlayer *player = CLUTTER_VIDEO_PLAYER (object);
234
235   g_free (player->priv->uri);
236   
237   G_OBJECT_CLASS (clutter_video_player_parent_class)->finalize (object);
238 }
239
240 static void
241 clutter_video_player_request_coords (ClutterActor        *self,
242                                      ClutterActorBox     *box)
243 {
244   ClutterVideoPlayer * player = CLUTTER_VIDEO_PLAYER (self);
245   ClutterVideoPlayerPrivate *priv = player->priv;
246   ClutterActorBox cbox;
247
248   cbox.x1 = 0;
249   cbox.y1 = 0;
250   cbox.x2 = box->x2 - box->x1;
251   cbox.y2 = box->y2 - box->y1;
252
253   priv->width  = CLUTTER_FIXED_INT (cbox.x2);
254   priv->height = CLUTTER_FIXED_INT (cbox.y2);
255
256   g_debug ("coords request %d x %d",
257            CLUTTER_FIXED_INT (cbox.x2),
258            CLUTTER_FIXED_INT (cbox.y2));
259   
260   clutter_actor_request_coords (priv->vtexture, &cbox);
261
262   clutter_actor_set_position (priv->control, 0, 0);
263   
264   CLUTTER_ACTOR_CLASS (clutter_video_player_parent_class)->request_coords (self, box);
265
266   g_object_notify (G_OBJECT (self), "height");
267   g_object_notify (G_OBJECT (self), "width");
268   
269   clutter_actor_set_position (priv->control,
270                               (clutter_actor_get_width (priv->vtexture) -
271                                CTRL_SIZE) / 2,
272                               clutter_actor_get_height (priv->vtexture) -
273                               (CTRL_SIZE + CTRL_SIZE/2));
274   
275   clutter_actor_show (priv->control);
276   clutter_actor_queue_redraw (priv->vtexture);
277 }
278
279 static void
280 clutter_video_player_class_init (ClutterVideoPlayerClass *klass)
281 {
282   GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
283   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
284
285   gobject_class->constructor  = clutter_video_player_constructor;
286   gobject_class->set_property = clutter_video_player_set_property;
287   gobject_class->get_property = clutter_video_player_get_property;
288   gobject_class->finalize     = clutter_video_player_finalize;
289
290   actor_class->request_coords  = clutter_video_player_request_coords;
291
292   g_object_class_install_property (gobject_class,
293                                    PROP_URI,
294                                    g_param_spec_string ("uri",
295                                                         "uri",
296                                                         "uri",
297                                                         "test.avi",
298                                                         G_PARAM_CONSTRUCT |
299                                                         CLUTTER_PARAM_READWRITE));
300    
301   g_type_class_add_private (gobject_class, sizeof (ClutterVideoPlayerPrivate));
302 }
303
304 static void
305 clutter_video_player_init (ClutterVideoPlayer *self)
306 {
307   ClutterVideoPlayerPrivate *priv;
308
309   self->priv = priv = CLUTTER_VIDEO_PLAYER_GET_PRIVATE (self);
310
311   priv->paused = TRUE;
312 }
313
314 ClutterActor *
315 clutter_video_player_new (const gchar * uri)
316 {
317   return g_object_new (CLUTTER_TYPE_VIDEO_PLAYER, "uri", uri, NULL);
318 }
319
320 static void
321 toggle_pause_state (ClutterVideoPlayer *player)
322 {
323   if (player->priv->paused)
324     {
325       clutter_media_set_playing (CLUTTER_MEDIA(player->priv->vtexture), 
326                                  TRUE);
327       player->priv->paused = FALSE;
328       clutter_actor_hide (player->priv->control_play);
329       clutter_actor_show (player->priv->control_pause);
330     }
331   else
332     {
333       clutter_media_set_playing (CLUTTER_MEDIA(player->priv->vtexture), 
334                                      FALSE);
335       player->priv->paused = TRUE;
336       clutter_actor_hide (player->priv->control_pause);
337       clutter_actor_show (player->priv->control_play);
338     }
339 }
340
341 static void 
342 input_cb (ClutterStage *stage, 
343           ClutterEvent *event,
344           gpointer      user_data)
345 {
346   ClutterVideoPlayer *player = (ClutterVideoPlayer*)user_data;
347   ClutterVideoPlayerPrivate *priv = player->priv;
348   
349   switch (event->type)
350     {
351     case CLUTTER_BUTTON_PRESS:
352         {
353           ClutterActor       *actor;
354           ClutterButtonEvent *bev = (ClutterButtonEvent *) event;
355
356           actor 
357             = clutter_stage_get_actor_at_pos 
358                                  (CLUTTER_STAGE(clutter_stage_get_default()),
359                                   bev->x, bev->y);
360
361           printf("got actor %p at pos %ix%i\n", actor, bev->x, bev->y);
362
363           if (actor == priv->control_pause || actor == priv->control_play)
364             {
365               toggle_pause_state (player);
366               return;
367             }
368
369         }
370       break;
371     default:
372       break;
373     }
374 }