summaryrefslogtreecommitdiffstats
path: root/hacks/glx/carousel.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/glx/carousel.c')
-rw-r--r--hacks/glx/carousel.c958
1 files changed, 0 insertions, 958 deletions
diff --git a/hacks/glx/carousel.c b/hacks/glx/carousel.c
deleted file mode 100644
index ec207a4..0000000
--- a/hacks/glx/carousel.c
+++ /dev/null
@@ -1,958 +0,0 @@
-/* carousel, Copyright (c) 2005-2018 Jamie Zawinski <jwz@jwz.org>
- * Loads a sequence of images and rotates them around.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation. No representations are made about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * Created: 21-Feb-2005
- */
-
-#define DEF_FONT \
- "OCR A Std 48, Lucida Console 48, Monaco 48, Courier 48, monospace 48"
-#define DEF_TITLE_FONT "sans-serif bold 48"
-
-#define DEFAULTS "*count: 7 \n" \
- "*delay: 10000 \n" \
- "*wireframe: False \n" \
- "*showFPS: False \n" \
- "*fpsSolid: True \n" \
- "*useSHM: True \n" \
- "*font: " DEF_FONT "\n" \
- "*titleFont: " DEF_TITLE_FONT "\n" \
- "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \
- "*grabDesktopImages: False \n" \
- "*chooseRandomImages: True \n"
-
-# define release_carousel 0
-# include "xlockmore.h"
-
-#ifdef USE_GL
-
-# define DEF_SPEED "1.0"
-# define DEF_DURATION "20"
-# define DEF_TITLES "True"
-# define DEF_ZOOM "True"
-# define DEF_TILT "XY"
-# define DEF_MIPMAP "True"
-# define DEF_DEBUG "False"
-
-#include "rotator.h"
-#include "gltrackball.h"
-#include "grab-ximage.h"
-#include "texfont.h"
-
-# ifndef HAVE_JWXYZ
-# include <X11/Intrinsic.h> /* for XrmDatabase in -debug mode */
-# endif
-
-/* Should be in <GL/glext.h> */
-# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
-# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
-# endif
-# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
-# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
-# endif
-
-typedef struct {
- double x, y, w, h;
-} rect;
-
-typedef enum { EARLY, NORMAL, LOADING, OUT, IN, DEAD } fade_mode;
-static int fade_ticks = 60;
-
-typedef struct {
- char *title; /* the filename of this image */
- int w, h; /* size in pixels of the image */
- int tw, th; /* size in pixels of the texture */
- XRectangle geom; /* where in the image the bits are */
- GLuint texid;
-} image;
-
-typedef struct {
- ModeInfo *mi;
- image current, loading;
- GLfloat r, theta; /* radius and rotation on the tube */
- rotator *rot; /* for zoomery */
- Bool from_top_p; /* whether this image drops in or rises up */
- time_t expires; /* when this image should be replaced */
- fade_mode mode; /* in/out animation state */
- int mode_tick;
- Bool loaded_p; /* whether background load is done */
-} image_frame;
-
-
-typedef struct {
- GLXContext *glx_context;
- GLfloat anisotropic;
- rotator *rot;
- trackball_state *trackball;
- Bool button_down_p;
- time_t button_down_time;
-
- int nframes; /* how many frames are loaded */
- int frames_size;
- image_frame **frames; /* pointers to the frames */
-
- Bool awaiting_first_images_p;
- int loads_in_progress;
-
- texture_font_data *texfont, *titlefont;
-
- fade_mode mode;
- int mode_tick;
-
- int loading_sw, loading_sh;
-
- time_t last_time, now;
- int draw_tick;
-
-} carousel_state;
-
-static carousel_state *sss = NULL;
-
-
-/* Command-line arguments
- */
-static GLfloat speed; /* animation speed scale factor */
-static int duration; /* reload images after this long */
-static Bool mipmap_p; /* Use mipmaps instead of single textures. */
-static Bool titles_p; /* Display image titles. */
-static Bool zoom_p; /* Throb the images in and out as they spin. */
-static char *tilt_str;
-static Bool tilt_x_p; /* Tilt axis towards the viewer */
-static Bool tilt_y_p; /* Tilt axis side to side */
-static Bool debug_p; /* Be loud and do weird things. */
-
-
-static XrmOptionDescRec opts[] = {
- {"-zoom", ".zoom", XrmoptionNoArg, "True" },
- {"-no-zoom", ".zoom", XrmoptionNoArg, "False" },
- {"-tilt", ".tilt", XrmoptionSepArg, 0 },
- {"-no-tilt", ".tilt", XrmoptionNoArg, "" },
- {"-titles", ".titles", XrmoptionNoArg, "True" },
- {"-no-titles", ".titles", XrmoptionNoArg, "False" },
- {"-mipmaps", ".mipmap", XrmoptionNoArg, "True" },
- {"-no-mipmaps", ".mipmap", XrmoptionNoArg, "False" },
- {"-duration", ".duration", XrmoptionSepArg, 0 },
- {"-debug", ".debug", XrmoptionNoArg, "True" },
- {"-font", ".font", XrmoptionSepArg, 0 },
- {"-speed", ".speed", XrmoptionSepArg, 0 },
-};
-
-static argtype vars[] = {
- { &mipmap_p, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool},
- { &debug_p, "debug", "Debug", DEF_DEBUG, t_Bool},
- { &titles_p, "titles", "Titles", DEF_TITLES, t_Bool},
- { &zoom_p, "zoom", "Zoom", DEF_ZOOM, t_Bool},
- { &tilt_str, "tilt", "Tilt", DEF_TILT, t_String},
- { &speed, "speed", "Speed", DEF_SPEED, t_Float},
- { &duration, "duration", "Duration", DEF_DURATION, t_Int},
-};
-
-ENTRYPOINT ModeSpecOpt carousel_opts = {countof(opts), opts, countof(vars), vars, NULL};
-
-
-/* Allocates a frame structure and stores it in the list.
- */
-static image_frame *
-alloc_frame (ModeInfo *mi)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- image_frame *frame = (image_frame *) calloc (1, sizeof (*frame));
-
- frame->mi = mi;
- frame->mode = EARLY;
- frame->rot = make_rotator (0, 0, 0, 0, 0.04 * frand(1.0) * speed, False);
-
- glGenTextures (1, &frame->current.texid);
- glGenTextures (1, &frame->loading.texid);
- if (frame->current.texid <= 0) abort();
- if (frame->loading.texid <= 0) abort();
-
- if (ss->frames_size <= ss->nframes)
- {
- ss->frames_size = (ss->frames_size * 1.2) + ss->nframes;
- ss->frames = (image_frame **)
- realloc (ss->frames, ss->frames_size * sizeof(*ss->frames));
- if (! ss->frames)
- {
- fprintf (stderr, "%s: out of memory (%d images)\n",
- progname, ss->frames_size);
- exit (1);
- }
- }
-
- ss->frames[ss->nframes++] = frame;
-
- return frame;
-}
-
-
-static void image_loaded_cb (const char *filename, XRectangle *geom,
- int image_width, int image_height,
- int texture_width, int texture_height,
- void *closure);
-
-
-/* Load a new file into the given image struct.
- */
-static void
-load_image (ModeInfo *mi, image_frame *frame)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- int wire = MI_IS_WIREFRAME(mi);
-
- if (debug_p && !wire && frame->current.w != 0)
- fprintf (stderr, "%s: dropped %4d x %-4d %4d x %-4d \"%s\"\n",
- progname,
- frame->current.geom.width,
- frame->current.geom.height,
- frame->current.tw, frame->current.th,
- (frame->current.title ? frame->current.title : "(null)"));
-
- switch (frame->mode)
- {
- case EARLY: break;
- case NORMAL: frame->mode = LOADING; break;
- default: abort();
- }
-
- ss->loads_in_progress++;
-
- if (wire)
- image_loaded_cb (0, 0, 0, 0, 0, 0, frame);
- else
- {
- int w = (MI_WIDTH(mi) / 2) - 1;
- int h = (MI_HEIGHT(mi) / 2) - 1;
- if (w <= 10) w = 10;
- if (h <= 10) h = 10;
-
- if (w > h * 5) { /* tiny window: use 16:9 boxes */
- h = w * 9/16;
- }
-
- load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, w, h,
- mipmap_p, frame->loading.texid,
- image_loaded_cb, frame);
- }
-}
-
-
-/* Callback that tells us that the texture has been loaded.
- */
-static void
-image_loaded_cb (const char *filename, XRectangle *geom,
- int image_width, int image_height,
- int texture_width, int texture_height,
- void *closure)
-{
- image_frame *frame = (image_frame *) closure;
- ModeInfo *mi = frame->mi;
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- int wire = MI_IS_WIREFRAME(mi);
-
- if (wire)
- {
- frame->loading.w = MI_WIDTH (mi) * (0.5 + frand (1.0));
- frame->loading.h = MI_HEIGHT (mi);
- frame->loading.geom.width = frame->loading.w;
- frame->loading.geom.height = frame->loading.h;
- goto DONE;
- }
-
- if (image_width == 0 || image_height == 0)
- exit (1);
-
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
-
- if (ss->anisotropic >= 1.0)
- glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- ss->anisotropic);
-
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- frame->loading.w = image_width;
- frame->loading.h = image_height;
- frame->loading.tw = texture_width;
- frame->loading.th = texture_height;
- frame->loading.geom = *geom;
-
- if (frame->loading.title)
- free (frame->loading.title);
- frame->loading.title = (filename ? strdup (filename) : 0);
-
- /* xscreensaver-getimage returns paths relative to the image directory
- now, so leave the sub-directory part in. Unless it's an absolute path.
- */
- if (frame->loading.title && frame->loading.title[0] == '/')
- { /* strip filename to part after last /. */
- char *s = strrchr (frame->loading.title, '/');
- if (s) strcpy (frame->loading.title, s+1);
- }
-
- if (debug_p)
- fprintf (stderr, "%s: loaded %4d x %-4d %4d x %-4d \"%s\"\n",
- progname,
- frame->loading.geom.width,
- frame->loading.geom.height,
- frame->loading.tw, frame->loading.th,
- (frame->loading.title ? frame->loading.title : "(null)"));
-
- DONE:
-
- frame->loaded_p = True;
-
- if (ss->loads_in_progress <= 0) abort();
- ss->loads_in_progress--;
-
- /* This image expires N seconds after it finished loading. */
- frame->expires = time((time_t *) 0) + (duration * MI_COUNT(mi));
-
- switch (frame->mode)
- {
- case EARLY: /* part of the initial batch of images */
- {
- image swap = frame->current;
- frame->current = frame->loading;
- frame->loading = swap;
- }
- break;
- case LOADING: /* start dropping the old image out */
- {
- frame->mode = OUT;
- frame->mode_tick = fade_ticks / speed;
- frame->from_top_p = random() & 1;
- }
- break;
- default:
- abort();
- }
-}
-
-
-static void loading_msg (ModeInfo *mi, int n);
-
-static Bool
-load_initial_images (ModeInfo *mi)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- int i;
- Bool all_loaded_p = True;
- for (i = 0; i < ss->nframes; i++)
- if (! ss->frames[i]->loaded_p)
- all_loaded_p = False;
-
- if (all_loaded_p)
- {
- if (ss->nframes < MI_COUNT (mi))
- {
- /* The frames currently on the list are fully loaded.
- Start the next one loading. (We run the image loader
- asynchronously, but we load them one at a time.)
- */
- load_image (mi, alloc_frame (mi));
- }
- else
- {
- /* The first batch of images are now all loaded!
- Stagger the expire times so that they don't all drop out at once.
- */
- time_t now = time((time_t *) 0);
- int i;
-
- for (i = 0; i < ss->nframes; i++)
- {
- image_frame *frame = ss->frames[i];
- frame->r = 1.0;
- frame->theta = i * 360.0 / ss->nframes;
- frame->expires = now + (duration * (i + 1));
- frame->mode = NORMAL;
- }
-
- /* Instead of always going clockwise, shuffle the expire times
- of the frames so that they drop out in a random order.
- */
- for (i = 0; i < ss->nframes; i++)
- {
- image_frame *frame1 = ss->frames[i];
- image_frame *frame2 = ss->frames[random() % ss->nframes];
- time_t swap = frame1->expires;
- frame1->expires = frame2->expires;
- frame2->expires = swap;
- }
-
- ss->awaiting_first_images_p = False;
- }
- }
-
- loading_msg (mi, ss->nframes-1);
-
- return !ss->awaiting_first_images_p;
-}
-
-
-ENTRYPOINT void
-reshape_carousel (ModeInfo *mi, int width, int height)
-{
- GLfloat h = (GLfloat) height / (GLfloat) width;
- int y = 0;
-
- if (width > height * 5) { /* tiny window: show middle */
- height = width * 9/16;
- y = -height/2;
- h = height / (GLfloat) width;
- }
-
- glViewport (0, y, (GLint) width, (GLint) height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective (60.0, 1/h, 1.0, 8.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt( 0.0, 0.0, 2.6,
- 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0);
-
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-
-ENTRYPOINT Bool
-carousel_handle_event (ModeInfo *mi, XEvent *event)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
-
- if (event->xany.type == ButtonPress &&
- event->xbutton.button == Button1)
- {
- if (! ss->button_down_p)
- ss->button_down_time = time((time_t *) 0);
- }
- else if (event->xany.type == ButtonRelease &&
- event->xbutton.button == Button1)
- {
- if (ss->button_down_p)
- {
- /* Add the time the mouse was held to the expire times of all
- frames, so that mouse-dragging doesn't count against
- image expiration.
- */
- int secs = time((time_t *) 0) - ss->button_down_time;
- int i;
- for (i = 0; i < ss->nframes; i++)
- ss->frames[i]->expires += secs;
- }
- }
-
- if (gltrackball_event_handler (event, ss->trackball,
- MI_WIDTH (mi), MI_HEIGHT (mi),
- &ss->button_down_p))
- return True;
- else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
- {
- int i = random() % ss->nframes;
- ss->frames[i]->expires = 0;
- return True;
- }
-
- return False;
-}
-
-
-/* Kludge to add "-v" to invocation of "xscreensaver-getimage" in -debug mode
- */
-static void
-hack_resources (Display *dpy)
-{
-# ifndef HAVE_JWXYZ
- char *res = "desktopGrabber";
- char *val = get_string_resource (dpy, res, "DesktopGrabber");
- char buf1[255];
- char buf2[255];
- XrmValue value;
- XrmDatabase db = XtDatabase (dpy);
- sprintf (buf1, "%.100s.%.100s", progname, res);
- sprintf (buf2, "%.200s -v", val);
- value.addr = buf2;
- value.size = strlen(buf2);
- XrmPutResource (&db, buf1, "String", &value);
- free (val);
-# endif /* !HAVE_JWXYZ */
-}
-
-
-static void
-loading_msg (ModeInfo *mi, int n)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- int wire = MI_IS_WIREFRAME(mi);
- char text[100];
-
- if (wire) return;
-
- if (n == 0)
- sprintf (text, "Loading images...");
- else
- sprintf (text, "Loading images... (%d%%)",
- (int) (n * 100 / MI_COUNT(mi)));
-
- if (ss->loading_sw == 0)
- {
- /* only do this once, so that the string doesn't move. */
- XCharStruct e;
- texture_string_metrics (ss->titlefont, text, &e, 0, 0);
- ss->loading_sw = e.width;
- ss->loading_sh = e.ascent + e.descent;
- }
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
-/*
- {
- double rot = current_device_rotation();
- glRotatef(rot, 0, 0, 1);
- if ((rot > 45 && rot < 135) ||
- (rot < -45 && rot > -135))
- {
- GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi);
- glScalef (s, 1/s, 1);
- }
- }
-*/
-
- {
- GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi)
- ? (MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi))
- : 1);
- glRotatef (current_device_rotation(), 0, 0, 1);
- glScalef (s, s, s);
- }
-
- glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1);
- glTranslatef ((MI_WIDTH(mi) - ss->loading_sw) / 2,
- (MI_HEIGHT(mi) - ss->loading_sh) / 2,
- 0);
- glColor3f (1, 1, 0);
- glEnable (GL_TEXTURE_2D);
- glDisable (GL_DEPTH_TEST);
-# ifndef HAVE_ANDROID /* Doesn't work -- photo displays as static */
- print_texture_string (ss->titlefont, text);
-# endif
- glEnable (GL_DEPTH_TEST);
- glPopMatrix();
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
-
- glMatrixMode(GL_MODELVIEW);
-
- glFinish();
- glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi));
-}
-
-
-ENTRYPOINT void
-init_carousel (ModeInfo *mi)
-{
- int screen = MI_SCREEN(mi);
- carousel_state *ss;
- int wire = MI_IS_WIREFRAME(mi);
-
- MI_INIT (mi, sss);
- ss = &sss[screen];
-
- if ((ss->glx_context = init_GL(mi)) != NULL) {
- reshape_carousel (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
- clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */
- } else {
- MI_CLEARWINDOW(mi);
- }
-
- if (!tilt_str || !*tilt_str)
- ;
- else if (!strcasecmp (tilt_str, "0"))
- ;
- else if (!strcasecmp (tilt_str, "X"))
- tilt_x_p = 1;
- else if (!strcasecmp (tilt_str, "Y"))
- tilt_y_p = 1;
- else if (!strcasecmp (tilt_str, "XY"))
- tilt_x_p = tilt_y_p = 1;
- else
- {
- fprintf (stderr, "%s: tilt must be 'X', 'Y', 'XY' or '', not '%s'\n",
- progname, tilt_str);
- exit (1);
- }
-
- {
- double spin_speed = speed * 0.2; /* rotation of tube around axis */
- double spin_accel = speed * 0.1;
- double wander_speed = speed * 0.001; /* tilting of axis */
-
- spin_speed *= 0.9 + frand(0.2);
- wander_speed *= 0.9 + frand(0.2);
-
- ss->rot = make_rotator (spin_speed, spin_speed, spin_speed,
- spin_accel, wander_speed, True);
-
- ss->trackball = gltrackball_init (False);
- }
-
- if (strstr ((char *) glGetString(GL_EXTENSIONS),
- "GL_EXT_texture_filter_anisotropic"))
- glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ss->anisotropic);
- else
- ss->anisotropic = 0.0;
-
- glDisable (GL_LIGHTING);
- glEnable (GL_DEPTH_TEST);
- glDisable (GL_CULL_FACE);
-
- if (! wire)
- {
- glShadeModel (GL_SMOOTH);
- glEnable (GL_LINE_SMOOTH);
- /* This gives us a transparent diagonal slice through each image! */
- /* glEnable (GL_POLYGON_SMOOTH); */
- glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
- glEnable (GL_BLEND);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_ALPHA_TEST);
-
- glEnable (GL_POLYGON_OFFSET_FILL);
- glPolygonOffset (1.0, 1.0);
-
- }
-
- ss->texfont = load_texture_font (MI_DISPLAY(mi), "font");
- ss->titlefont = load_texture_font (MI_DISPLAY(mi), "titleFont");
-
- if (debug_p)
- hack_resources (MI_DISPLAY (mi));
-
- ss->nframes = 0;
- ss->frames_size = 10;
- ss->frames = (image_frame **)
- calloc (1, ss->frames_size * sizeof(*ss->frames));
-
- ss->mode = IN;
- ss->mode_tick = fade_ticks / speed;
-
- ss->awaiting_first_images_p = True;
-}
-
-
-static void
-draw_frame (ModeInfo *mi, image_frame *frame, time_t now, Bool body_p)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- int wire = MI_IS_WIREFRAME(mi);
-
- GLfloat texw = frame->current.geom.width / (GLfloat) frame->current.tw;
- GLfloat texh = frame->current.geom.height / (GLfloat) frame->current.th;
- GLfloat texx1 = frame->current.geom.x / (GLfloat) frame->current.tw;
- GLfloat texy1 = frame->current.geom.y / (GLfloat) frame->current.th;
- GLfloat texx2 = texx1 + texw;
- GLfloat texy2 = texy1 + texh;
- GLfloat aspect = ((GLfloat) frame->current.geom.height /
- (GLfloat) frame->current.geom.width);
-
- glBindTexture (GL_TEXTURE_2D, frame->current.texid);
-
- glPushMatrix();
-
- /* Position this image on the wheel.
- */
- glRotatef (frame->theta, 0, 1, 0);
- glTranslatef (0, 0, frame->r);
-
- /* Scale down the image so that all N frames fit on the wheel
- without bumping in to each other.
- */
- {
- GLfloat t, s;
- switch (ss->nframes)
- {
- case 1: t = -1.0; s = 1.7; break;
- case 2: t = -0.8; s = 1.6; break;
- case 3: t = -0.4; s = 1.5; break;
- case 4: t = -0.2; s = 1.3; break;
- default: t = 0.0; s = 6.0 / ss->nframes; break;
- }
- glTranslatef (0, 0, t);
- glScalef (s, s, s);
- }
-
- /* Center this image on the wheel plane.
- */
- glTranslatef (-0.5, -(aspect/2), 0);
-
- /* Move as per the "zoom in and out" setting.
- */
- if (zoom_p)
- {
- double x, y, z;
- /* Only use the Z component of the rotator for in/out position. */
- get_position (frame->rot, &x, &y, &z, !ss->button_down_p);
- glTranslatef (0, 0, z/2);
- }
-
- /* Compute the "drop in and out" state.
- */
- switch (frame->mode)
- {
- case EARLY:
- abort();
- break;
- case NORMAL:
- if (!ss->button_down_p &&
- now >= frame->expires &&
- ss->loads_in_progress == 0) /* only load one at a time */
- load_image (mi, frame);
- break;
- case LOADING:
- break;
- case OUT:
- if (--frame->mode_tick <= 0) {
- image swap = frame->current;
- frame->current = frame->loading;
- frame->loading = swap;
-
- frame->mode = IN;
- frame->mode_tick = fade_ticks / speed;
- }
- break;
- case IN:
- if (--frame->mode_tick <= 0)
- frame->mode = NORMAL;
- break;
- default:
- abort();
- }
-
- /* Now translate for current in/out state.
- */
- if (frame->mode == OUT || frame->mode == IN)
- {
- GLfloat t = (frame->mode == OUT
- ? frame->mode_tick / (fade_ticks / speed)
- : (((fade_ticks / speed) - frame->mode_tick + 1) /
- (fade_ticks / speed)));
- t = 5 * (1 - t);
- if (frame->from_top_p) t = -t;
- glTranslatef (0, t, 0);
- }
-
- if (body_p) /* Draw the image quad. */
- {
- if (! wire)
- {
- glColor3f (1, 1, 1);
- glNormal3f (0, 0, 1);
- glEnable (GL_TEXTURE_2D);
- glBegin (GL_QUADS);
- glNormal3f (0, 0, 1);
- glTexCoord2f (texx1, texy2); glVertex3f (0, 0, 0);
- glTexCoord2f (texx2, texy2); glVertex3f (1, 0, 0);
- glTexCoord2f (texx2, texy1); glVertex3f (1, aspect, 0);
- glTexCoord2f (texx1, texy1); glVertex3f (0, aspect, 0);
- glEnd();
- }
-
- /* Draw a box around it.
- */
- glLineWidth (2.0);
- glColor3f (0.5, 0.5, 0.5);
- glDisable (GL_TEXTURE_2D);
- glBegin (GL_LINE_LOOP);
- glVertex3f (0, 0, 0);
- glVertex3f (1, 0, 0);
- glVertex3f (1, aspect, 0);
- glVertex3f (0, aspect, 0);
- glEnd();
-
- }
- else if (frame->current.title && *frame->current.title)
- { /* Draw a title under the image. */
- XCharStruct e;
- int sw, sh;
- GLfloat scale = 0.05;
- char *title = frame->current.title ? frame->current.title : "(untitled)";
- texture_string_metrics (ss->texfont, title, &e, 0, 0);
- sw = e.width;
- sh = e.ascent + e.descent;
-
- glTranslatef (0, -scale, 0);
-
- scale /= sh;
- glScalef (scale, scale, scale);
-
- glTranslatef (((1/scale) - sw) / 2, 0, 0);
- glColor3f (1, 1, 1);
-
- if (!wire)
- {
- glEnable (GL_TEXTURE_2D);
-# ifndef HAVE_ANDROID /* Doesn't work -- photo displays as static */
- print_texture_string (ss->texfont, title);
-# endif
- }
- else
- {
- glBegin (GL_LINE_LOOP);
- glVertex3f (0, 0, 0);
- glVertex3f (sw, 0, 0);
- glVertex3f (sw, sh, 0);
- glVertex3f (0, sh, 0);
- glEnd();
- }
- }
-
- glPopMatrix();
-}
-
-
-ENTRYPOINT void
-draw_carousel (ModeInfo *mi)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- int i;
-
- if (!ss->glx_context)
- return;
-
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ss->glx_context);
-
- if (ss->awaiting_first_images_p)
- if (!load_initial_images (mi))
- return;
-
- /* Only check the wall clock every 10 frames */
- {
- if (ss->now == 0 || ss->draw_tick++ > 10)
- {
- ss->now = time((time_t *) 0);
- if (ss->last_time == 0) ss->last_time = ss->now;
- ss->draw_tick = 0;
- }
- }
-
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix();
-
- glRotatef(current_device_rotation(), 0, 0, 1);
-
-
- /* Run the startup "un-shrink" animation.
- */
- switch (ss->mode)
- {
- case IN:
- if (--ss->mode_tick <= 0)
- {
- ss->mode = NORMAL;
- ss->last_time = time((time_t *) 0);
- }
- break;
- case NORMAL:
- break;
- default:
- abort();
- }
-
-
- /* Scale as per the startup "un-shrink" animation.
- */
- if (ss->mode != NORMAL)
- {
- GLfloat s = (ss->mode == OUT
- ? ss->mode_tick / (fade_ticks / speed)
- : (((fade_ticks / speed) - ss->mode_tick + 1) /
- (fade_ticks / speed)));
- glScalef (s, s, s);
- }
-
- /* Rotate and tilt as per the user, and the motion modeller.
- */
- {
- double x, y, z;
- gltrackball_rotate (ss->trackball);
-
- /* Tilt the tube up or down by up to 30 degrees */
- get_position (ss->rot, &x, &y, &z, !ss->button_down_p);
- if (tilt_x_p)
- glRotatef (15 - (x * 30), 1, 0, 0);
- if (tilt_y_p)
- glRotatef (7 - (y * 14), 0, 0, 1);
-
- /* Only use the Y component of the rotator. */
- get_rotation (ss->rot, &x, &y, &z, !ss->button_down_p);
- glRotatef (y * 360, 0, 1, 0);
- }
-
- /* First draw each image, then draw the titles. GL insists that you
- draw back-to-front in order to make alpha blending work properly,
- so we need to draw all of the 100% opaque images before drawing
- any of the not-100%-opaque titles.
- */
- for (i = 0; i < ss->nframes; i++)
- draw_frame (mi, ss->frames[i], ss->now, True);
- if (titles_p)
- for (i = 0; i < ss->nframes; i++)
- draw_frame (mi, ss->frames[i], ss->now, False);
-
- glPopMatrix();
-
- if (mi->fps_p) do_fps (mi);
- glFinish();
- glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi));
-}
-
-
-ENTRYPOINT void
-free_carousel (ModeInfo *mi)
-{
- carousel_state *ss = &sss[MI_SCREEN(mi)];
- int i;
- if (!ss->glx_context) return;
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ss->glx_context);
- if (ss->rot) free_rotator (ss->rot);
- if (ss->trackball) gltrackball_free (ss->trackball);
- if (ss->texfont) free_texture_font (ss->texfont);
- if (ss->titlefont) free_texture_font (ss->titlefont);
- for (i = 0; i < ss->nframes; i++) {
- if (ss->frames[i]->current.title) free (ss->frames[i]->current.title);
- if (ss->frames[i]->loading.title) free (ss->frames[i]->loading.title);
- if (ss->frames[i]->rot) free_rotator (ss->frames[i]->rot);
- if (ss->frames[i]->current.texid)
- glDeleteTextures (1, &ss->frames[i]->current.texid);
- if (ss->frames[i]->loading.texid)
- glDeleteTextures (1, &ss->frames[i]->loading.texid);
- }
-}
-
-XSCREENSAVER_MODULE ("Carousel", carousel)
-
-#endif /* USE_GL */