#include #include #include #include #include #include #include #include void (*original_paint) (ClutterActor * actor) = 0; typedef struct _Cover { ClutterActor * texture; gboolean showing; } Cover; typedef struct _App { ClutterActor * stage; GList * album_list; gchar * base_directory; gint dimy; gint dimx; gint screenw; gint screenh; gint artw; gint arth; gint posx; gint posy; } App; static void paint_album (ClutterActor * actor) { glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); original_paint(actor); glDisable(GL_CULL_FACE); } static void rotate_finished(ClutterActor * actor, gpointer data) { clutter_actor_hide(actor); } static gboolean start_rotate(gpointer data) { App * app = (App *) data; ClutterEffectTemplate * effect = clutter_effect_template_new_for_duration(1000, CLUTTER_ALPHA_SINE_INC); Cover *cov1, *cov2; if (g_list_length(app->album_list) < (app->dimx * app->dimy)) return TRUE; cov1 = g_list_nth_data(app->album_list, random() % g_list_length(app->album_list)); cov2 = g_list_nth_data(app->album_list, random() % g_list_length(app->album_list)); while (!cov1->showing) cov1 = g_list_nth_data(app->album_list, random() % g_list_length(app->album_list)); while (cov2->showing) cov2 = g_list_nth_data(app->album_list, random() % g_list_length(app->album_list)); clutter_actor_show(cov2->texture); clutter_actor_set_rotation(cov1->texture, CLUTTER_Y_AXIS, 0, 0, 0, 0); clutter_actor_set_rotation(cov2->texture, CLUTTER_Y_AXIS, 180, 0, 0, 0); clutter_actor_set_position(cov2->texture, clutter_actor_get_x(cov1->texture), clutter_actor_get_y(cov1->texture)); clutter_effect_rotate(effect,cov1->texture, CLUTTER_Y_AXIS, 180, clutter_actor_get_width(cov1->texture)/2, clutter_actor_get_height(cov1->texture)/2, 0, CLUTTER_ROTATE_CW, 0, 0); clutter_effect_rotate(effect,cov2->texture, CLUTTER_Y_AXIS, 360, clutter_actor_get_width(cov2->texture)/2, clutter_actor_get_height(cov2->texture)/2, 0, CLUTTER_ROTATE_CW, 0, 0); g_object_unref(effect); cov1->showing = 0; cov2->showing = 1; return TRUE; } static gboolean supported_img(const gchar * name) { GdkPixbufFormat * fmt = gdk_pixbuf_get_file_info (name, NULL, NULL); if (fmt) return (gdk_pixbuf_format_is_disabled (fmt) != TRUE); return FALSE; } static void load_image(App * app, const gchar * name) { Cover * cov = g_new0(Cover, 1); GdkPixbuf * pixbuf; pixbuf = gdk_pixbuf_new_from_file(name, NULL); app->album_list = g_list_append(app->album_list, cov); cov->texture = clutter_texture_new_from_pixbuf(pixbuf); if (!original_paint) { original_paint = CLUTTER_ACTOR_GET_CLASS(cov->texture)->paint; CLUTTER_ACTOR_GET_CLASS(cov->texture)->paint = paint_album; } clutter_container_add_actor(CLUTTER_CONTAINER(app->stage), cov->texture); clutter_actor_set_size(cov->texture, app->artw, app->arth); clutter_actor_show(cov->texture); if ((app->posx < app->dimx) && (app->posy < app->dimy)) { ClutterEffectTemplate * effect = clutter_effect_template_new_for_duration(500, CLUTTER_ALPHA_EXP_INC); cov->showing = 1; clutter_actor_set_opacity(cov->texture, 0x00); clutter_actor_set_x(cov->texture, app->artw*app->posx); clutter_actor_set_y(cov->texture, app->arth*app->posy); clutter_effect_fade(effect, cov->texture, 255, 0, 0); g_object_unref(effect); } else { clutter_actor_hide(cov->texture); cov->showing = 0; } app->posx++; if (app->posx > app->dimx) { app->posx = 0; app->posy++; } g_object_unref(pixbuf); } static void load_directory(App * app, const gchar * name) { GDir * dir; struct stat sbuf; const gchar * fname; dir = g_dir_open(name, 0, NULL); if (!dir) return; g_chdir(name); while ((fname = g_dir_read_name(dir))) { while (g_main_context_pending (NULL)) g_main_context_iteration(NULL, FALSE); if (supported_img(fname)) load_image(app, fname); if (g_stat(fname, &sbuf) > -1 && S_ISDIR(sbuf.st_mode)) load_directory(app, fname); } g_chdir(".."); g_dir_close(dir); } static gboolean load_images(gpointer data) { App * app = (App *)data; clutter_actor_get_size(app->stage, &(app->screenw), &(app->screenh)); app->dimx = app->dimy * (app->screenw / (float)app->screenh); app->artw = floor(app->screenw / (float)app->dimx); app->arth = floor(app->screenh / (float)app->dimy); g_timeout_add(5000, start_rotate, app); load_directory(app, app->base_directory); return FALSE; } int main (int argc, char ** argv) { GtkWidget *window; GtkWidget *clutter; App * app; ClutterColor color = {0x0,0x0,0x0,0xff}; gint artX, artY, screenX, screenY; gtk_init(&argc, &argv); gtk_clutter_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); clutter = gtk_clutter_embed_new(); gtk_window_fullscreen(GTK_WINDOW(window)); gtk_container_add(GTK_CONTAINER(window),clutter); gtk_widget_show_all(window); app = g_new0(App,1); app->stage = gtk_clutter_embed_get_stage(GTK_CLUTTER_EMBED(clutter)); app->dimy = 4; // FIXME app->base_directory = *(argv+1); app->posx = app->posy = 0; clutter_stage_fullscreen(CLUTTER_STAGE(app->stage)); clutter_stage_set_color(CLUTTER_STAGE(app->stage), &color); g_timeout_add(100, load_images, app); clutter_actor_show_all(app->stage); gtk_main(); }