/* -*- 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.
 */

/*
 * $Id$
 */

/*
 * $Log$
 * Revision 1.16  2005/05/16 16:00:56  deva
 *
 * Lots of stuff!
 *
 * Revision 1.15  2005/05/07 10:25:34  deva
 *
 * Removed ffmpeg code from img_encoder and corrected decoding errors in mov_encoder
 *
 * Revision 1.14  2005/05/03 08:31:59  deva
 * Removed the error object, and replaced it with a more generic info object.
 *
 * Revision 1.13  2005/05/02 14:06:55  deva
 * Added unfreeze to decoder (called from camera).
 *
 * Revision 1.12  2005/05/02 10:35:23  deva
 * Fixed wrongly showed snapshot thumbnails.
 *
 * Revision 1.11  2005/05/02 09:58:43  deva
 *
 * Fixed initial values of the stae bools.
 *
 * Revision 1.10  2005/05/02 09:50:22  deva
 * Rewrote freeze, shoot and record flags, from encoder to frame.
 *
 * Revision 1.9  2005/05/01 11:25:56  deva
 * Added code to read screenshot from frame queue, decode it to rgb and put it into a qimage.
 *
 * Revision 1.8  2005/05/01 09:56:26  deva
 * Added Id and Log tags to all files
 */

#include <config.h>
#ifdef USE_GUI

#include "camera.h"

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

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

  pthread_mutex_init (&mutex, NULL);
  //mutex = PTHREAD_MUTEX_INITIALIZER;
  /*  
	AVFormatContext *ifmtctx;
	AVFormatContext *ofmtctx;
  */
  running = 1;

  //	av_register_all();

	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);
  /*
  if(errorstatus->hasError()) {
    errorstatus->pushError("Camera initialization failed (decoder).");
    return;
  }
  */
	encoder = new Encoder(info,
                        ip, port,
                        &encode_sem,
                        encode_queue,
                        &mutex,
                        &running);
  /*
  if(errorstatus->hasError()) {
    errorstatus->pushError("Camera initialization failed (encoder).");
    return;
  }
  */
	player = new Player(info,
                      &running,
                      &player_sem,
                      player_queue,
                      &mutex);
  /*
  if(errorstatus->hasError()) {
    errorstatus->pushError("Camera initialization failed (player).");
    return;
  }
  */

  pthread_create (&decodetid, NULL, thread_run, decoder);
  /*
  if(errorstatus->hasError()) {
    errorstatus->pushError("Camera initialization failed (decoder thread).");
    return;
  }
  */
  pthread_create (&encodetid, NULL, thread_run, encoder);
  /*
  if(errorstatus->hasError()) {
    errorstatus->pushError("Camera initialization failed (encoder thread).");
    return;
  }
  */
  pthread_create (&playertid, NULL, thread_run, player);
  /*
  if(errorstatus->hasError()) {
    errorstatus->pushError("Camera initialization failed (player thread).");
    return;
  }
  */
  initialized = true;
}

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

	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();
    //    encoder->freeze();
    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();
}

#endif/* USE_GUI */