#include "def.h"
/* for TRUE,FALSE etc */

#include <stdio.h> 
/* for perror() */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/* for open(), close() */

#include <sys/ioctl.h>
/* for ioctl() */

#include <sys/mman.h>
/* for mmap */

#include <linux/videodev.h>
/* for all video-specifics */

#include "bitmap_24bitRGB.h"



#define WIDTH 640
#define HEIGHT 480
#define CAMERA_DEVICE "/dev/video0"

int fd; 
unsigned char *frameBuffer;

struct video_mbuf memoryBufferInfo;
struct video_mmap memoryMapInfo;

int grapperInit() {
  struct video_channel vchannel;
  
  fd=open( CAMERA_DEVICE , O_RDWR); 
  if( fd <= 0) {
    return FALSE;
  }

  /* Get memory buffer information */
  if(ioctl(fd, VIDIOCGMBUF, &memoryBufferInfo) < 0) {
    close(fd);
    return FALSE;
  }
  
  /* map buffer */
  frameBuffer = 
    mmap(0, memoryBufferInfo.size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  if ( (int)frameBuffer < 0) {
    close(fd);
    return FALSE;
  }

  /* set channels */
  vchannel.channel=1; // Channel 1 is of type Composite1 
  vchannel.norm=1;    // Why ? I dont know

  if(ioctl(fd, VIDIOCSCHAN, &vchannel) < 0)  {
    munmap(frameBuffer, memoryBufferInfo.size);
    close(fd);
    return FALSE;
  }
  
     
  /* set grab parameters */
  memoryMapInfo.frame  = 0;
  memoryMapInfo.height = HEIGHT;
  memoryMapInfo.width  = WIDTH;
  memoryMapInfo.format = VIDEO_PALETTE_RGB24;

  return TRUE;
}


int grapperSync() {
  if( ioctl(fd, VIDIOCSYNC, &(memoryMapInfo.frame) ) < 0) {
    perror("VIDIOCSYNC");
    return FALSE;
  }
  return TRUE;
}


int grapperCapture() {
  if( ioctl(fd, VIDIOCMCAPTURE, &memoryMapInfo) < 0) {
    perror("VIDIOCMCAPTURE");
    return FALSE;
  }
  return TRUE;
}

void grapperRelease() {
  munmap(frameBuffer, memoryBufferInfo.size);
  close(fd);
}

int copyGrapToBitmap(Bitmap_24bitRGB *bitmap) {
  int size=0;
  if(WIDTH*HEIGHT < (bitmap->width * bitmap->height) ) 
    size = 3*WIDTH*HEIGHT;
  else
    size = 3* ( bitmap->width * bitmap->height);

  memcpy(bitmap->image, frameBuffer, size);
  return TRUE;
}
