+++ /dev/null
-#include <clutter/clutter.h>
-
-ClutterActor *rect; /* um... */
-
-
-void input_cb (ClutterStage *stage,
- ClutterEvent *event,
- gpointer user_data)
-{
- ClutterVideoTexture *vtex = CLUTTER_VIDEO_TEXTURE(user_data);
- static gint paused = 0;
-
- if (event->type == CLUTTER_KEY_RELEASE)
- {
- if (paused)
- {
- clutter_media_set_playing (CLUTTER_MEDIA(vtex), TRUE);
- paused = 0;
- }
- else
- {
- clutter_media_set_playing (CLUTTER_MEDIA(vtex), FALSE);
- paused = 1;
- }
- }
-}
-
-void
-size_change (ClutterTexture *texture,
- gint width,
- gint height,
- gpointer user_data)
-{
- ClutterActor *stage;
- ClutterGeometry stage_geom;
- gint vid_width, vid_height, new_y, new_height;
-
- stage = clutter_stage_get_default ();
-
- clutter_actor_get_geometry (stage, &stage_geom);
-
- clutter_texture_get_base_size (texture, &vid_width, &vid_height);
-
- printf("*** vid : %ix%i stage %ix%i ***\n",
- vid_width, vid_height, stage_geom.width, stage_geom.height);
-
-
- new_height = ( vid_height * stage_geom.width ) / vid_width;
- new_y = (stage_geom.height - new_height) / 2;
-
- clutter_actor_set_position (CLUTTER_ACTOR (texture), 0, new_y);
-
- clutter_actor_set_size (CLUTTER_ACTOR (texture),
- stage_geom.width,
- new_height);
-
- // clutter_actor_set_opacity (CLUTTER_ACTOR (texture), 50);
-
- printf("*** Pos set to +%i+%i , %ix%i ***\n",
- 0, new_y, stage_geom.width, new_height);
-}
-
-void
-tick (GObject *object,
- GParamSpec *pspec,
- ClutterLabel *label)
-{
- ClutterVideoTexture *vtex;
- gint w, h, position, duration;
- gchar buf[256];
-
- vtex = CLUTTER_VIDEO_TEXTURE(object);
-
- position = clutter_media_get_position (CLUTTER_MEDIA(vtex));
- duration = clutter_media_get_duration (CLUTTER_MEDIA(vtex));
-
- g_snprintf(buf, 256, "%i / %i", position, duration);
-
- clutter_label_set_text (label, buf);
-
- clutter_texture_get_base_size (CLUTTER_TEXTURE(label), &w, &h);
- clutter_actor_set_size(rect, w+10, h+10);
-}
-
-int
-main (int argc, char *argv[])
-{
- ClutterActor *label, *vtexture, *ctexture;
- ClutterActor *stage;
- ClutterColor rect_color = { 0xde, 0xde, 0xdf, 0xaa };
- ClutterColor stage_color = { 0x00, 0x00, 0x00, 0x00 };
- GError *err = NULL;
-
- if (argc < 2)
- g_error("%s <video file>", argv[0]);
-
- clutter_init (&argc, &argv);
-
- vtexture = clutter_video_texture_new ();
-
- clutter_media_set_filename(CLUTTER_MEDIA(vtexture), argv[1]);
-
- stage = clutter_stage_get_default ();
-
- /* Broken..
- g_object_set(vtexture, "repeat-x", TRUE, NULL);
- g_object_set(vtexture, "repeat-y", TRUE, NULL);
- */
-
- if (vtexture == NULL || err != NULL)
- {
- g_error("failed to create vtexture, err: %s", err->message);
- }
-
- label = clutter_label_new_with_text ("Sans Bold 24", "Loading...");
-
- clutter_actor_set_position(label, 10, 10);
-
- rect = clutter_rectangle_new_with_color (&rect_color);
- clutter_actor_set_size(rect, 0, 0);
- clutter_actor_set_position(rect, 5, 5);
-
- ctexture = clutter_clone_texture_new (CLUTTER_TEXTURE(vtexture));
- clutter_actor_set_opacity (CLUTTER_ACTOR (ctexture), 100);
-
- clutter_actor_set_size (ctexture, 640, 50);
- clutter_actor_set_position (ctexture, 0, 430);
-
- clutter_group_add_many (CLUTTER_GROUP (stage),
- vtexture, rect, label, ctexture, NULL);
-
- clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
-
- g_signal_connect (stage, "input-event",
- G_CALLBACK (input_cb),
- vtexture);
-
- clutter_group_show_all (CLUTTER_GROUP (stage));
-
- clutter_media_set_playing (CLUTTER_MEDIA(vtexture), TRUE);
-
- g_signal_connect (CLUTTER_MEDIA(vtexture),
- "notify::position",
- G_CALLBACK (tick),
- label);
-
- g_object_set (G_OBJECT(vtexture), "sync-size", FALSE, NULL);
-
- g_signal_connect (CLUTTER_TEXTURE(vtexture),
- "size-change",
- G_CALLBACK (size_change), NULL);
-
- clutter_main();
-
- g_object_unref (stage);
-
- return 0;
-}
--- /dev/null
+#include <clutter/clutter.h>
+
+#define SEEK_H 20
+#define SEEK_W 690
+
+typedef struct VideoApp
+{
+ ClutterActor *vtexture;
+
+ ClutterActor *control, *control_bg, *control_play, *control_pause,
+ *control_seek1, *control_seek2, *control_seekbar, *control_label;
+ gboolean controls_showing, paused;
+ guint controls_timeout;
+ ClutterTimeline *controls_tl, *effect1_tl;
+}
+VideoApp;
+
+static void
+show_controls (VideoApp *app, gboolean vis);
+
+void
+control_tl_cb (ClutterTimeline *timeline,
+ gint frame_num,
+ VideoApp *app)
+{
+ guint8 opacity;
+
+ clutter_group_show_all (CLUTTER_GROUP (app->control));
+ clutter_actor_hide (app->paused ? app->control_pause : app->control_play);
+ clutter_actor_show (app->paused ? app->control_play : app->control_pause);
+
+ opacity = ( frame_num * 0xde ) / clutter_timeline_get_n_frames(timeline);
+
+ if (!app->controls_showing)
+ opacity = 0xde - opacity;
+
+ clutter_actor_set_opacity (app->control, opacity);
+}
+
+void
+control_tl_complete_cb (ClutterTimeline *timeline,
+ VideoApp *app)
+{
+ if (!app->controls_showing)
+ clutter_group_hide_all (CLUTTER_GROUP (app->control));
+
+ app->controls_timeout = 0;
+}
+
+static gboolean
+controls_timeout_cb (VideoApp *app)
+{
+ show_controls (app, FALSE);
+ return FALSE;
+}
+
+static void
+show_controls (VideoApp *app, gboolean vis)
+{
+ if (clutter_timeline_is_playing (app->controls_tl))
+ return;
+
+ if (vis == TRUE && app->controls_showing == FALSE)
+ {
+ app->controls_showing = TRUE;
+ clutter_timeline_start (app->controls_tl);
+
+ app->controls_timeout = g_timeout_add (5 * 1000,
+ (GSourceFunc)controls_timeout_cb,
+ app);
+ return;
+ }
+
+ if (vis == TRUE && app->controls_showing == TRUE)
+ {
+ if (app->controls_timeout)
+ {
+ g_source_remove (app->controls_timeout);
+
+ app->controls_timeout
+ = g_timeout_add (5 * 1000,
+ (GSourceFunc)controls_timeout_cb,
+ app);
+ }
+ return;
+ }
+
+ if (vis == FALSE && app->controls_showing == TRUE)
+ {
+ app->controls_showing = FALSE;
+ clutter_timeline_start (app->controls_tl);
+ return;
+ }
+}
+
+void
+toggle_pause_state (VideoApp *app)
+{
+ if (app->paused)
+ {
+ clutter_media_set_playing (CLUTTER_MEDIA(app->vtexture),
+ TRUE);
+ app->paused = FALSE;
+ clutter_actor_hide (app->control_play);
+ clutter_actor_show (app->control_pause);
+ }
+ else
+ {
+ clutter_media_set_playing (CLUTTER_MEDIA(app->vtexture),
+ FALSE);
+ app->paused = TRUE;
+ clutter_actor_hide (app->control_pause);
+ clutter_actor_show (app->control_play);
+ }
+}
+
+void
+input_cb (ClutterStage *stage,
+ ClutterEvent *event,
+ gpointer user_data)
+{
+ VideoApp *app = (VideoApp*)user_data;
+
+ switch (event->type)
+ {
+ case CLUTTER_MOTION:
+ show_controls (app, TRUE);
+ break;
+ case CLUTTER_BUTTON_PRESS:
+ if (app->controls_showing)
+ {
+ ClutterActor *actor;
+ ClutterButtonEvent *bev = (ClutterButtonEvent *) event;
+
+ actor
+ = clutter_stage_get_actor_at_pos
+ (CLUTTER_STAGE(clutter_stage_get_default()),
+ bev->x, bev->y);
+
+ if (actor == app->control_pause || actor == app->control_play)
+ {
+ toggle_pause_state (app);
+ return;
+ }
+
+ if (actor == app->control_seek1
+ || actor == app->control_seek2
+ || actor == app->control_seekbar)
+ {
+ gint x, y, dist, pos;
+
+ clutter_actor_get_abs_position (app->control_seekbar, &x, &y);
+
+ dist = bev->x - x;
+
+ CLAMP(dist, 0, SEEK_W);
+
+ pos = (dist * clutter_media_get_duration
+ (CLUTTER_MEDIA(app->vtexture))) / SEEK_W;
+
+ clutter_media_set_position (CLUTTER_MEDIA(app->vtexture),
+ pos);
+ }
+ }
+ break;
+ case CLUTTER_KEY_RELEASE:
+ {
+ ClutterKeyEvent* kev = (ClutterKeyEvent *) event;
+
+ switch (clutter_key_event_symbol (kev))
+ {
+ case CLUTTER_q:
+ case CLUTTER_Escape:
+ clutter_main_quit ();
+ break;
+ case CLUTTER_e:
+ if (!clutter_timeline_is_playing (app->effect1_tl))
+ clutter_timeline_start (app->effect1_tl);
+ break;
+ default:
+ toggle_pause_state (app);
+ break;
+ }
+ }
+ default:
+ break;
+ }
+}
+
+void
+size_change (ClutterTexture *texture,
+ gint width,
+ gint height,
+ gpointer user_data)
+{
+ ClutterActor *stage;
+ ClutterGeometry stage_geom;
+ gint vid_width, vid_height, new_y, new_height;
+
+ clutter_texture_get_base_size (texture, &vid_width, &vid_height);
+
+ new_height = ( vid_height * CLUTTER_STAGE_WIDTH() ) / vid_width;
+ new_y = ( CLUTTER_STAGE_HEIGHT() - new_height) / 2;
+
+ clutter_actor_set_position (CLUTTER_ACTOR (texture), 0, new_y);
+
+ clutter_actor_set_size (CLUTTER_ACTOR (texture),
+ CLUTTER_STAGE_WIDTH(),
+ new_height);
+}
+
+void
+tick (GObject *object,
+ GParamSpec *pspec,
+ VideoApp *app)
+{
+ ClutterVideoTexture *vtex;
+ gint w, h, position, duration, seek_w;
+ gchar buf[256];
+
+ vtex = CLUTTER_VIDEO_TEXTURE(object);
+
+ position = clutter_media_get_position (CLUTTER_MEDIA(vtex));
+ duration = clutter_media_get_duration (CLUTTER_MEDIA(vtex));
+
+ if (duration == 0 || position == 0)
+ return;
+
+ clutter_actor_set_size (app->control_seekbar,
+ (position * SEEK_W) / duration,
+ SEEK_H);
+}
+
+int
+effect1_tl_cb (ClutterTimeline *timeline,
+ gint frame_num,
+ VideoApp *app)
+{
+ clutter_actor_rotate_y (app->vtexture,
+ frame_num * 12,
+ CLUTTER_STAGE_WIDTH()/2,
+ 0);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ VideoApp *app = NULL;
+ ClutterActor *stage;
+ ClutterColor stage_color = { 0x00, 0x00, 0x00, 0x00 };
+ ClutterColor control_color1 = { 73, 74, 77, 0xee };
+ ClutterColor control_color2 = { 0xcc, 0xcc, 0xcc, 0xff };
+ GdkPixbuf *pixb;
+ gint x,y;
+
+ if (argc < 2)
+ g_error("%s <video file>", argv[0]);
+
+ clutter_init (&argc, &argv);
+
+ stage = clutter_stage_get_default ();
+ g_object_set (stage, "fullscreen", TRUE, NULL);
+ clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
+
+ app = g_new0(VideoApp, 1);
+
+ app->vtexture = clutter_video_texture_new ();
+
+ if (app->vtexture == NULL)
+ {
+ g_error("failed to create vtexture");
+ }
+
+ /* Dont let the underlying pixbuf dictate size */
+ g_object_set (G_OBJECT(app->vtexture), "sync-size", FALSE, NULL);
+
+ /* Handle it ourselves so can scale up for fullscreen better */
+ g_signal_connect (CLUTTER_TEXTURE(app->vtexture),
+ "size-change",
+ G_CALLBACK (size_change), NULL);
+
+ /* Load up out video texture */
+ clutter_media_set_filename(CLUTTER_MEDIA(app->vtexture), argv[1]);
+
+ /* Create the control UI */
+ app->control = clutter_group_new ();
+
+ pixb = gdk_pixbuf_new_from_file ("vid-panel.png", NULL);
+
+ if (pixb == NULL)
+ g_error("Unable to load vid-panel.png");
+
+ app->control_bg = clutter_texture_new_from_pixbuf (pixb);
+
+ pixb = gdk_pixbuf_new_from_file("media-actions-start.png", NULL);
+
+ if (pixb == NULL)
+ g_error("Unable to load media-actions-start.png");
+
+ app->control_play = clutter_texture_new_from_pixbuf (pixb);
+
+ pixb = gdk_pixbuf_new_from_file("media-actions-pause.png", NULL);
+
+ if (pixb == NULL)
+ g_error("Unable to load media-actions-pause.png");
+
+ app->control_pause = clutter_texture_new_from_pixbuf (pixb);
+
+ app->control_seek1 = clutter_rectangle_new_with_color (&control_color1);
+ app->control_seek2 = clutter_rectangle_new_with_color (&control_color2);
+ app->control_seekbar = clutter_rectangle_new_with_color (&control_color1);
+ clutter_actor_set_opacity (app->control_seekbar, 0x99);
+
+ app->control_label
+ = clutter_label_new_with_text("Sans Bold 24",
+ g_path_get_basename(argv[1]));
+ clutter_label_set_color (CLUTTER_LABEL(app->control_label), &control_color1);
+
+ clutter_group_add_many (CLUTTER_GROUP (app->control),
+ app->control_bg,
+ app->control_play,
+ app->control_pause,
+ app->control_seek1,
+ app->control_seek2,
+ app->control_seekbar,
+ app->control_label,
+ NULL);
+
+ x = (CLUTTER_STAGE_WIDTH() - clutter_actor_get_width(app->control))/2;
+ y = CLUTTER_STAGE_HEIGHT() - (CLUTTER_STAGE_HEIGHT()/3);
+
+ clutter_actor_set_position (app->control, x, y);
+ clutter_actor_set_opacity (app->control, 0xee);
+
+ clutter_actor_set_position (app->control_play, 30, 30);
+ clutter_actor_set_position (app->control_pause, 30, 30);
+
+ clutter_actor_set_size (app->control_seek1, SEEK_W+10, SEEK_H+10);
+ clutter_actor_set_position (app->control_seek1, 200, 100);
+ clutter_actor_set_size (app->control_seek2, SEEK_W, SEEK_H);
+ clutter_actor_set_position (app->control_seek2, 205, 105);
+ clutter_actor_set_size (app->control_seekbar, 0, SEEK_H);
+ clutter_actor_set_position (app->control_seekbar, 205, 105);
+
+ clutter_actor_set_position (app->control_label, 200, 40);
+
+ /* Add control UI to stage */
+ clutter_group_add_many (CLUTTER_GROUP (stage),
+ app->vtexture, app->control, NULL);
+
+ /* hook up a time line for fading controls */
+ app->controls_tl = clutter_timeline_new (10, 30);
+ g_signal_connect (app->controls_tl, "new-frame",
+ G_CALLBACK (control_tl_cb), app);
+ g_signal_connect (app->controls_tl, "completed",
+ G_CALLBACK (control_tl_complete_cb), app);
+
+
+ app->effect1_tl = clutter_timeline_new (30, 90);
+ g_signal_connect (app->effect1_tl, "new-frame",
+ G_CALLBACK (effect1_tl_cb), app);
+
+ /* Hook up other events */
+ g_signal_connect (stage, "input-event",
+ G_CALLBACK (input_cb),
+ app);
+
+ g_signal_connect (CLUTTER_MEDIA(app->vtexture),
+ "notify::position",
+ G_CALLBACK (tick),
+ app);
+
+ clutter_media_set_playing (CLUTTER_MEDIA(app->vtexture), TRUE);
+
+ clutter_group_show_all (CLUTTER_GROUP (stage));
+
+ clutter_main();
+
+ g_object_unref (stage);
+
+ return 0;
+}