2 #include <clutter-gst/clutter-gst.h>
3 #include "clutter-video-player.h"
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
14 G_DEFINE_TYPE (ClutterVideoPlayer, clutter_video_player, CLUTTER_TYPE_GROUP);
16 #define CLUTTER_VIDEO_PLAYER_GET_PRIVATE(obj) \
17 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_VIDEO_PLAYER, ClutterVideoPlayerPrivate))
19 struct _ClutterVideoPlayerPrivate
21 ClutterActor * vtexture;
23 ClutterActor * control;
24 ClutterActor * control_play;
25 ClutterActor * control_pause;
36 toggle_pause_state (ClutterVideoPlayer *player);
39 input_cb (ClutterStage * stage, ClutterEvent * event, gpointer data);
42 autostop_playback (gpointer data)
44 ClutterVideoPlayer * player = data;
45 ClutterVideoPlayerPrivate * priv = player->priv;
47 clutter_actor_show (priv->vtexture);
49 toggle_pause_state (player);
50 clutter_media_set_position (CLUTTER_MEDIA (priv->vtexture), 0);
55 eos_cb (ClutterMedia * media, gpointer data)
57 ClutterVideoPlayer * player = data;
59 if (!player->priv->paused)
60 toggle_pause_state (player);
62 clutter_media_set_position (media, 0);
66 pixbuf_from_data (const guchar * data, gint length)
69 GdkPixbufLoader * ldr = gdk_pixbuf_loader_new_with_type ("png", NULL);
73 g_warning ("Could not create loader");
77 if (!gdk_pixbuf_loader_write (ldr, data, length, NULL))
79 g_warning ("Failed to write to loader.");
83 pixbuf = gdk_pixbuf_loader_get_pixbuf (ldr);
89 size_change (ClutterTexture *texture,
94 ClutterVideoPlayer *player = data;
95 gint h = player->priv->width * height / width;
97 clutter_actor_set_size (CLUTTER_ACTOR (player), player->priv->width, h);
101 construct_controls (ClutterVideoPlayer *player)
103 ClutterVideoPlayerPrivate *priv = player->priv;
106 priv->vtexture = clutter_gst_video_texture_new ();
108 if (priv->vtexture == NULL)
109 g_error("failed to create vtexture");
111 /* Dont let the underlying pixbuf dictate size */
112 g_object_set (G_OBJECT(priv->vtexture), "sync-size", FALSE, NULL);
114 g_signal_connect (CLUTTER_TEXTURE(priv->vtexture),
116 G_CALLBACK (size_change), player);
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);
124 priv->control = clutter_group_new ();
126 pixb = pixbuf_from_data (&play_png[0], sizeof (play_png));
129 g_error("Unable to load play button image");
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);
135 pixb = pixbuf_from_data (&pause_png[0], sizeof (pause_png));
138 g_error("Unable to load pause button image");
140 priv->control_pause = clutter_texture_new_from_pixbuf (pixb);
141 clutter_actor_set_size (priv->control_pause, CTRL_SIZE, CTRL_SIZE);
143 clutter_group_add_many (CLUTTER_GROUP (priv->control),
148 clutter_actor_set_opacity (priv->control, 0xee);
150 clutter_actor_set_position (priv->control_play, 0, 0);
151 clutter_actor_set_position (priv->control_pause, 0, 0);
153 clutter_group_add_many (CLUTTER_GROUP (player),
154 priv->vtexture, priv->control, NULL);
156 g_signal_connect (clutter_stage_get_default(), "event",
157 G_CALLBACK (input_cb),
168 clutter_video_player_set_property (GObject *object,
173 ClutterVideoPlayer *player;
174 ClutterVideoPlayerPrivate *priv;
176 player = CLUTTER_VIDEO_PLAYER(object);
183 priv->uri = g_strdup (g_value_get_string (value));
186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
192 clutter_video_player_get_property (GObject *object,
197 ClutterVideoPlayer *player;
198 ClutterVideoPlayerPrivate *priv;
200 player = CLUTTER_VIDEO_PLAYER(object);
206 g_value_set_string (value, priv->uri);
209 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
215 clutter_video_player_constructor (GType gtype,
217 GObjectConstructParam *params)
219 GObjectClass * parent_class;
222 parent_class = G_OBJECT_CLASS (clutter_video_player_parent_class);
223 retval = parent_class->constructor (gtype, n_params, params);
225 construct_controls (CLUTTER_VIDEO_PLAYER (retval));
231 clutter_video_player_finalize (GObject *object)
233 ClutterVideoPlayer *player = CLUTTER_VIDEO_PLAYER (object);
235 g_free (player->priv->uri);
237 G_OBJECT_CLASS (clutter_video_player_parent_class)->finalize (object);
241 clutter_video_player_request_coords (ClutterActor *self,
242 ClutterActorBox *box)
244 ClutterVideoPlayer * player = CLUTTER_VIDEO_PLAYER (self);
245 ClutterVideoPlayerPrivate *priv = player->priv;
246 ClutterActorBox cbox;
250 cbox.x2 = box->x2 - box->x1;
251 cbox.y2 = box->y2 - box->y1;
253 priv->width = CLUTTER_FIXED_INT (cbox.x2);
254 priv->height = CLUTTER_FIXED_INT (cbox.y2);
256 g_debug ("coords request %d x %d",
257 CLUTTER_FIXED_INT (cbox.x2),
258 CLUTTER_FIXED_INT (cbox.y2));
260 clutter_actor_request_coords (priv->vtexture, &cbox);
262 clutter_actor_set_position (priv->control, 0, 0);
264 CLUTTER_ACTOR_CLASS (clutter_video_player_parent_class)->request_coords (self, box);
266 g_object_notify (G_OBJECT (self), "height");
267 g_object_notify (G_OBJECT (self), "width");
269 clutter_actor_set_position (priv->control,
270 (clutter_actor_get_width (priv->vtexture) -
272 clutter_actor_get_height (priv->vtexture) -
273 (CTRL_SIZE + CTRL_SIZE/2));
275 clutter_actor_show (priv->control);
276 clutter_actor_queue_redraw (priv->vtexture);
280 clutter_video_player_class_init (ClutterVideoPlayerClass *klass)
282 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
283 ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
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;
290 actor_class->request_coords = clutter_video_player_request_coords;
292 g_object_class_install_property (gobject_class,
294 g_param_spec_string ("uri",
299 CLUTTER_PARAM_READWRITE));
301 g_type_class_add_private (gobject_class, sizeof (ClutterVideoPlayerPrivate));
305 clutter_video_player_init (ClutterVideoPlayer *self)
307 ClutterVideoPlayerPrivate *priv;
309 self->priv = priv = CLUTTER_VIDEO_PLAYER_GET_PRIVATE (self);
315 clutter_video_player_new (const gchar * uri)
317 return g_object_new (CLUTTER_TYPE_VIDEO_PLAYER, "uri", uri, NULL);
321 toggle_pause_state (ClutterVideoPlayer *player)
323 if (player->priv->paused)
325 clutter_media_set_playing (CLUTTER_MEDIA(player->priv->vtexture),
327 player->priv->paused = FALSE;
328 clutter_actor_hide (player->priv->control_play);
329 clutter_actor_show (player->priv->control_pause);
333 clutter_media_set_playing (CLUTTER_MEDIA(player->priv->vtexture),
335 player->priv->paused = TRUE;
336 clutter_actor_hide (player->priv->control_pause);
337 clutter_actor_show (player->priv->control_play);
342 input_cb (ClutterStage *stage,
346 ClutterVideoPlayer *player = (ClutterVideoPlayer*)user_data;
347 ClutterVideoPlayerPrivate *priv = player->priv;
351 case CLUTTER_BUTTON_PRESS:
354 ClutterButtonEvent *bev = (ClutterButtonEvent *) event;
357 = clutter_stage_get_actor_at_pos
358 (CLUTTER_STAGE(clutter_stage_get_default()),
361 printf("got actor %p at pos %ix%i\n", actor, bev->x, bev->y);
363 if (actor == priv->control_pause || actor == priv->control_play)
365 toggle_pause_state (player);