rendered paste body#include <clutter/clutter.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter-gtk/gtk-clutter-embed.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <math.h>
#include <gtk/gtk.h>
#include <GL/gl.h>
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();
}