#include #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 = ( (gint)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