#if BTTV


// Source and Documentation:
// http://www.exploits.org/v4l/    -> The v4l mailing list archives
// http://www.linuxhq.com/kernel/v2.2/doc/video4linux/API.html.html

// TCap v0.1
// (C) Thomas Hargrove
// http://toonarchive.com/tcap

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>
//#include <vga.h>
//#include <vgagl.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <errno.h>
#include <time.h>

#include "iter.h"
#include "series.h"
#include "utils.h"
#include "data.h"
#include "data.videodev.h"   /**original file: videodev.h**/


// Only 640x480 and 320x240 work here
//const int 	mywidth = 64;
//const int 	myheight = 48;

static struct	video_capability  capability;
static int 	fd = -1;
static struct 	video_mbuf gb_buffers = { 2*0x151000, 0, {0,0x151000 }};
static char 	*map = NULL;
static struct 	video_mmap my_buf;

//GraphicsContext *physicalscreen;
//GraphicsContext *virtualscreen;
clock_t		cstart=0;
clock_t		clast=0;
float		fps;
int		frame_count=0;

// ------------------------------------------------------------
// This function copies the image from the capture card (tmap)
// and draws each pixel on the off screen buffer.  Then it
// copies the off screen buffer to the actual screen.
// ------------------------------------------------------------
// This function is quite slow, so if you need a higher fps
// just optimize this routine
// ------------------------------------------------------------
/*
**************************************************************

Modified the above comment to cop it to a file

*************************************************************
*/


void copytofile(char* tmap) {

/*   int x,y;
   unsigned char r,g,b;
   for(y=0; y<myheight; y++) {
	for(x=0; x<mywidth; x++) {
		r = *(tmap+2);
		g = *(tmap+1);
		b = *tmap;
		gl_setpixelrgb(x, y, r, g, b); 
		tmap+=3;
	}
   }
   gl_printf(10,5,"TCap v0.1");
   gl_printf(10,15,"Tom Hargrove");

   gl_printf(10,25,"Fps %0.1f", fps);
   if ( ((cstart=clock())-clast) / CLOCKS_PER_SEC > 1) {
	fps = (float) frame_count / ((float) (cstart-clast) / CLOCKS_PER_SEC);
	frame_count=0;
	clast=cstart;
   }
   frame_count++;

   gl_copyscreen(physicalscreen);	// This copies the image to the screen!
*/
/*
FILE *fp;
int x,y;
unsigned char r,g,b;

int maxr = 0, maxg = 0, maxb = 0;

  fp = fopen ("image2.pnm", "w");
  fprintf (fp, "P6\n");
  fprintf (fp, "%d %d\n", mywidth, myheight);
  fprintf (fp, "255\n");

  for(y=0; y<myheight; y++) {
	for(x=0; x<mywidth; x++) {
		r = *(tmap+2);
		g = *(tmap+1);
		b = *tmap;
                maxr = r > maxr ? r : maxr;
                maxg = g > maxg ? g : maxg;
                maxb = b > maxb ? b : maxb;
		fprintf (fp, "%c%c%c", r, g, b);
		tmap+=3;
	}
   }

  fclose (fp);

   frame_count++;

  fprintf (stderr, "maxr=%d  maxg=%d  maxb=%d  frame=%d\n",
                    maxr, maxg, maxb, frame_count);
*/
}


/******************************** bttv_image *********************************/
/* Fille d->Bilder, similar to import_images, but as functon pointer.        */
/* q[0][0] = -1 init, else refresh; reads 2 frames but discards 1st => fresh */
/* q[1][0] = d->Br_b[bild_nr]                                                */
/* q[1][1] = d->Ho_a[bild_nr]                                                */

void bttv_image (AGENT *z, COMMAND *cmd, DATA *d, int begin, int end) {

   char *my_video_dev = "/dev/video0";
   const int bild_nr = 0;
   unsigned char r,g,b;
   int i, refresh;

   /**initialize**/
   if  (cmd->quantum[0][0] == -1) {

       // ----------------------------------------------------------------------
       // Get the v4l capture set up
       // ----------------------------------------------------------------------
       if  (-1 == (fd = open(my_video_dev, O_RDWR))) {
           printf("Error opening device: %s\n", my_video_dev);
           exit (1);
       }

       if  (-1 == ioctl(fd,VIDIOCGCAP,&capability)) {
           printf("Error: ioctl(fd,VIDIOCGCAP,&capability)\n");
           exit (1);
       }

       /*Set the close-on-exec flag as specified by FD_CLOEXEC*/
       fcntl(fd,F_SETFD,FD_CLOEXEC);

       if  (-1 == ioctl(fd,VIDIOCGMBUF,&gb_buffers)) {
           printf("Error: Error getting buffers, I think\n");
           exit (1);
       }

       map = mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); 
       if  (map == NULL) {
           printf("Error: Mmap returned NULL\n");
           exit (1);
       }

       // Set up out capture to use the correct resolution
       my_buf.width = cmd->quantum[1][0];
       my_buf.height = cmd->quantum[1][1];
       my_buf.format = VIDEO_PALETTE_RGB24;


      d->anzahl = 1;

      /** get memory for image information **/
      if  ((d->Br_b = (int *)malloc (d->anzahl * sizeof (int))) == NULL)
          fprintf (stderr, "\nallocation failure for d->Br_b\n");
      if  ((d->Ho_a = (int *)malloc (d->anzahl * sizeof (int))) == NULL)
         fprintf (stderr, "\nallocation failure for d->Ho_a\n");
      if  ((d->Bild_grau = (int *)malloc (d->anzahl * sizeof (int))) == NULL)
          fprintf (stderr, "\nallocation failure for d->Bild_grau\n");
      if  ((d->Bild_max = (double *)malloc(d->anzahl * sizeof (double))) == NULL)
          fprintf (stderr, "\nallocation failure for d->Bild_\n");
      if  ((d->Bild_min = (double *)malloc(d->anzahl * sizeof (double))) == NULL)
          fprintf (stderr, "\nallocation failure for d->Bild_\n");
      if  ((d->Bild_mindiff = (double *)malloc (d->anzahl * sizeof (double)))
           == NULL)  fprintf (stderr, "\nallocation failure for d->Bild_\n");
      /** get memory for our pointers to pictures **/
      if  ((d->Bilder = (double **)malloc(d->anzahl*sizeof(double *))) == NULL)
          fprintf (stderr, "\nout of memory\n");

      /**(from importP5_img)**/
      d->Br_b[bild_nr]      = cmd->quantum[1][0];
      d->Ho_a[bild_nr]      = cmd->quantum[1][1];
      d->Bild_grau[bild_nr] = 255;
      d->Bilder[bild_nr]    = d_vector (d->Br_b[bild_nr] * d->Ho_a[bild_nr] * 3);
      d->Bild_min[bild_nr]  = 0.0;
      d->Bild_max[bild_nr]  = 255.0;
      d->Bild_mindiff[bild_nr] = 0.0;
   }

   // Tell the capture card to fill frame 0
/*
   my_buf.frame = 0;
   if (-1 == ioctl(fd, VIDIOCMCAPTURE, &my_buf)) { 
	printf("Error: Grabber chip can't sync (no station tuned in?)\n"); 
	goto err;
   }
*/   

   // --------------------------------------------------------------------------
   // This is the infinate loop
   // We basically:
   //	capture frame 1
   //   sync frame 0
   //   process frame 0
   //	capture frame 0 
   //   sync frame 1
   //   process frame 1
   // For more information, read the programming how-to that came with xawtv
   // --------------------------------------------------------------------------

   /**do the whole thing 2ce so that the newest frame will be taken**/
   for (refresh = 0; refresh < 2; ++refresh) {

       my_buf.frame = 0; /**changed this from 1 !!**/
       if  (-1 == ioctl(fd, VIDIOCMCAPTURE, &my_buf)) {
           printf("Error: Grabber chip can't sync (no station tuned in?)\n"); 
           printf("my_buf.width=%d my_buf.height=%d ... too small?\n", my_buf.width, my_buf.height); 
           exit (1);
       }
 
       my_buf.frame = 0;
       if  (-1 == ioctl(fd, VIDIOCSYNC, &my_buf.frame)) {
            printf("Error on sync!\n"); 
            exit (1);
       }

       for (i = 0; i < d->Br_b[bild_nr] * d->Ho_a[bild_nr] * 3; i += 3) {
           r = *(map + i + 2);
           g = *(map + i + 1);
           b = *(map + i);
           d->Bilder[bild_nr][i]   = (double)(r);
           d->Bilder[bild_nr][i+1] = (double)(g);
           d->Bilder[bild_nr][i+2] = (double)(b);
       }
   }

/*
	my_buf.frame = 0;
	if (-1 == ioctl(fd, VIDIOCMCAPTURE, &my_buf)) {
		printf("Error: Grabber chip can't sync (no station tuned in?)\n"); 
		goto err;
	}

	my_buf.frame = 1;
	if (-1 == ioctl(fd, VIDIOCSYNC, &my_buf.frame)) {
		printf("Error on sync!\n"); 
		goto err;
	}

	copytofile(map + gb_buffers.offsets[1]);
*/

   // Return screen to text mode.
   //vga_setmode(TEXT);
}


#endif