/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            camera.cc
 *
 *  Fri Oct 29 12:46:38 CEST 2004
 *  Copyright  2004 Bent Bisballe
 *  deva@aasimon.org
 ****************************************************************************/

/*
 *    This file is part of MIaV.
 *
 *    MIaV 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.
 *
 *    MIaV is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MIaV; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include <config.h>
#ifdef USE_GUI

#include "camera.h"

Camera::Camera(Info *ginfo)
{
  info = ginfo;
}

void Camera::connect(const char *ip, const int port, int width, int height)
{
  initialized = false;

  pthread_mutex_init (&mutex, NULL);
  //mutex = PTHREAD_MUTEX_INITIALIZER;

  running = 1;

	encode_queue = new Queue<Frame>(); // infinite size
	player_queue = new Queue<Frame>(1); // fixed size of 1

	sem_init(&encode_sem, 0, 0);
	sem_init(&player_sem, 0, 0);

	decoder = new Decoder(info,
                        &encode_sem,
                        &player_sem,
                        encode_queue,
                        player_queue,
                        &mutex,
                        &running);

	encoder = new Encoder(info,
                        ip, port,
                        &encode_sem,
                        encode_queue,
                        &mutex,
                        &running);

	player = new Player(info,
                      width, height,
                      &running,
                      &player_sem,
                      player_queue,
                      &mutex);

  decoder->run();
  encoder->run();
  player->run();

  initialized = true;
}

Camera::~Camera()
{
  // Signal to the threads to stop
  running = 0;

  /* // FIXME: Add some way to stop a thread object
	pthread_join(decodetid, NULL);
	pthread_join(playertid, NULL);
  pthread_join(encodetid, NULL);
  */

	delete decoder;
	delete encoder;
	delete player;

	sem_destroy(&encode_sem);
	sem_destroy(&player_sem);

	delete player_queue;
	delete encode_queue;
}

void Camera::setCpr(char *newcpr)
{
  
  if(initialized) encoder->setCpr(newcpr);
  else info->error("Camera not initialized.");

}


void Camera::start()
{
  if(initialized) {
    encoder->start();
    decoder->start();
  } else {
    info->error("Camera not initialized.");
  }
}

void Camera::stop(n_savestate save)
{
  if(initialized) {
    decoder->stop(save);
    encoder->stop(save);
  } else {
    info->error("Camera not initialized.");
  }
}

void Camera::freeze()
{
  if(initialized) {
    player->stop();
    decoder->freeze();
  } else {
    info->error("Camera not initialized.");
  }
}

void Camera::unfreeze()
{
  if(initialized) {
    player->start();
    decoder->unfreeze();
  } else {
    info->error("Camera not initialized.");
  }
}

void Camera::snapshot(unsigned char *rgb)
{
  if(initialized) {
    decoder->shoot(rgb);
    encoder->shoot();
  } else {
    info->error("Camera not initialized.");
  }
}

int Camera::getQueueLength()
{
  return encode_queue->length();
}

void Camera::resize(int w, int h)
{
  player->resize(w,h);
}

#endif/* USE_GUI */