/* ex: set tabstop=4 expandtab: */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
#include <GL/glx.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include "textureMovie.h"

extern "C" void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);

#define MAX_TEX_WIDTH 512
#define MAX_TEX_HEIGHT 512

struct _frame
    {
    GLint format;
    GLint xdim, ydim;
    GLint size;
    void * image;
    };


textureMovie::textureMovie(char * filename,float fps)
    {
    glGenTextures(1,&texid_);
    currentFrame_ = -1;
    fps_ = fps;
    startTime_ = -1;
    readCtexFrames(filename);
    glBindTexture(GL_TEXTURE_2D, texid_);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
    glBindTexture(GL_TEXTURE_2D,0);
    }


void textureMovie::readCtexFrames(char * filename)
    {
    int maxFrames = 1000, fd;
    struct { GLint format, xdim, ydim, size; } header;
    data_ = (struct _frame **) malloc(maxFrames * sizeof(struct _frame *));
    fd = open(filename,0);
    if (fd < 0)
        {
        perror(filename);
        exit(1);
        }
    numFrames_ = 0;
    while (1)
        {
        if (read(fd,&header,sizeof(header)) <= 0)
            break;
        if (numFrames_ == maxFrames)
            {
            maxFrames *= 2;
            data_ = (struct _frame **) realloc(data_,
                                           maxFrames * sizeof(struct _frame *));
            }
        data_[numFrames_] = (struct _frame *) malloc(sizeof(struct _frame));
        data_[numFrames_]->format = header.format;
        data_[numFrames_]->xdim = header.xdim;
        data_[numFrames_]->ydim = header.ydim;
        data_[numFrames_]->size = header.size;
        data_[numFrames_]->image = malloc(header.size);
        if (read(fd, data_[numFrames_]->image, header.size) <= 0)
            break;
        numFrames_++;
        }
    close(fd);
    }


static void printGLError(void)
    {
    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
        printf("textureMovie: GL error '%s'\n",gluErrorString(err));
    }


void textureMovie::update(float t)
    {
    if (startTime_ < 0)
        startTime_ = t;
    int newframe = ((int)((t-startTime_)*fps_+0.5)) % numFrames_;
    if (newframe != currentFrame_)
        {
        currentFrame_ = newframe;
        struct _frame * frame = data_[currentFrame_];
        glBindTexture(GL_TEXTURE_2D, texid_);
        glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, frame->format,
                      frame->xdim, frame->ydim, 0, frame->size,
                      frame->image);
        glBindTexture(GL_TEXTURE_2D, 0);
        }
    printGLError();
    }


void textureMovie::bind(void)
    {
    glBindTexture(GL_TEXTURE_2D, texid_);
    }
