// GUI app sonic-snap
// by Bram Stolk

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include "sonixcam.h"

static int width=352;
static int height=288;

static SonixCam *cam=0;

static bool opt_normalize=true;
static bool opt_autogain=false;
static bool opt_compression=false;
static int  opt_count=1;
static int  opt_skip=1;
static float opt_gain=-1;
static char *opt_device="/dev/video0";
static char *opt_prefix="sonicsnap";


static void adjust_gain(void)
{
  float gc = cam->AnalyzeGainChange(0.00025);
  float gain = cam->GetGain();
  gain += gc;
  if (gain>1.0) gain=1.0;
  if (gain<0.0) gain=0.0;
  cam->SetGain(gain);
}


static void save_ppm(char *fname)
{
  assert(fname);
  int sz=width*height*3;
  unsigned char *img = new unsigned char[sz];
  memcpy(img, cam->GetImage(), sz);
  FILE *f=fopen(fname,"wb");
  if (!f)
  {
    fprintf(stderr, "Cannot open file %s for writing", fname);
    delete [] img;
    return;
  }
  fprintf(f,"P6 %d %d %d\n", width, height, 255);
  int rv=fwrite(img, sz, 1, f);
  assert(rv==1);
  fclose(f);
  delete [] img;
}


static void single_shot(void)
{
  static int shotnr=0;
  static int savenr=0;
  while (1)
  {
    if (cam->Sustain())
    { 
      if (opt_autogain)
        adjust_gain();
      shotnr++;
      if ((shotnr % opt_skip) == 0)
      {
        char fname[128];
        sprintf(fname, "%s%04d.ppm", opt_prefix, savenr);
        save_ppm(fname);
        savenr++;
        return;
      }
    }
    else
    {
      usleep(5000);
    }
  }
}



static bool parse_opt(char *o)
{
  if (!strncmp(o, "normalize=", 10))
  {
    opt_normalize = atoi(o+10);
    return true;
  }

  if (!strncmp(o, "autogain=", 9))
  {
    opt_autogain = atoi(o+9);
    return true;
  }

  if (!strncmp(o, "compression=", 12))
  {
    opt_compression = atoi(o+12);
    return true;
  }

  if (!strncmp(o, "count=", 6))
  {
    opt_count = atoi(o+6);
    return true;
  }

  if (!strncmp(o, "skip=", 5))
  {
    opt_skip = atoi(o+5);
    return true;
  }

  if (!strncmp(o, "gain=", 5))
  {
    opt_gain = atof(o+5);
    return true;
  }

  if (!strncmp(o, "prefix=", 7))
  {
    opt_prefix = o+7;
    return true;
  }

  if (!strncmp(o, "device=", 7))
  {
    opt_device = o+7;
    return true;
  }

  return false;
}


static void usage(char *progname)
{
  fprintf
  (
    stderr,
    "Usage: %s gain=0.5 normalize=1 autogain=0 compression=1 count=1 skip=1 prefix=sonicsnap device=/dev/video0\n",
    progname
  );
}



int main(int argc, char *argv[])
{
  int i;
  for (i=1; i<argc; i++)
  {
    if (!parse_opt(argv[i]))
    {
      usage(argv[0]);
      exit(1);
    }
  }

  cam = new SonixCam(opt_device, width, height);

  cam->SetCompression(opt_compression);
  cam->DoNormalize(opt_normalize);
  cam->DoAutoGain(opt_autogain);
  if (opt_gain!=-1)
    cam->SetGain(opt_gain);

  cam->StartCapture();
  cam->Sustain();
  bool gotfirst=false;
  while (!gotfirst)
    gotfirst=cam->Sustain();
  for (i=0; i<opt_count; i++)
  {
    single_shot();
  }
  cam->StopCapture();

  delete cam;
}

