/*
 * Analogue TV Player plugin for VDR
 *
 * Copyright (C) 2003, 2005 Andreas Kool <akool@gmx.de>
 *
 * This code is distributed under the terms and conditions of the
 * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
 *
 * Version: $Id: encoder.c,v 1.41 2005/01/09 18:16:08 akool Exp $
 * Release: $Name:  $
 *
 */

#include <signal.h>
#include <errno.h>
#include <cstring>

#include "encoder.h"
#include "memcpy.h"
#include <unistd.h>

#include "i18n.h"
#include <stdint.h>
#include "player-analogtv.h"

#if 0
#include <vdr/device.h>

class cAnalogtvPlayer : public cPlayer, cThread {
public:
  cAnalogtvPlayer(void);
  virtual ~cAnalogtvPlayer();
};

cAnalogtvPlayer::cAnalogtvPlayer(void) :
   cPlayer(pmExtern_THIS_SHOULD_BE_AVOIDED)
{
  d(1, "pmExtern_THIS_SHOULD_BE_AVOIDED");
}

cAnalogtvPlayer::~cAnalogtvPlayer()
{
  d(1, "~pmExtern_THIS_SHOULD_BE_AVOIDED");
}
#endif

cEncoder::cEncoder()
{
  d(3, "cEncoder::cEncoder()");

  ReaderLoopRunning = 1;

  Start();

  EncoderRunning = 1;
}

cEncoder::~cEncoder()
{
  register int cc = 0;

  d(3, "cEncoder::~cEncoder()");

  ReaderLoopRunning = 0;

  if (s.mpeg_encoder != PVRPES) {
    cc = kill(pid, SIGINT);

    d(2, "kill(%d)=%d, %d:%s", pid, cc, errno, errno ? strerror(errno) : "");
  }

  Cancel(2);

#if 0
  cAnalogtvPlayer *off = new cAnalogtvPlayer();
  delete off;
#endif

  // FIXME: cDevice::PrimaryDevice()->Clear();

  EncoderRunning = 0;
}

static void LoadProfile(int profile)
{
  if (profile == AUTO)
    profile = isPVR ? PVR : MEDIUM;

  switch (profile) {
    case FASTEST : s.image_size = 0;       // 352x288
                   s.clipping = 1;
                   s.video_bit_rate = 23;  // 2,3 MBit
                   s.audio_bit_rate = 80;  // 80 KBit
                   s.audio_mode = 3;       // Mono
                   s.gop = 1;              // "I"
                   s.filter = 0;           // YUV 4:2:0 fastest
                   s.motion[0] =
                   s.motion[1] = 0;        // Motion compensation disabled
                   *extraOpts = 0;
                   break;

    case MEDIUM  : s.image_size = 0;       // 352x288
                   s.clipping = 1;
                   s.video_bit_rate = 50;  // 2,3 MBit
                   s.audio_bit_rate = 80;  // 80 KBit
                   s.audio_mode = 0;       // Stereo
                   s.gop = 0;              // "IBBPBBPBBPBBP"
                   s.filter = 7;           // YUV 4:2:0 fastest
                   s.motion[0] =
                   s.motion[1] = 0;        // Motion compensation disabled
                   *extraOpts = 0;
                   break;

    case BEST    : s.image_size = 5;       // 720x576
                   s.clipping = 0;
                   s.video_bit_rate = 80;  // 8 MBit
                   s.audio_bit_rate = 160; // 160 KBit
                   s.audio_mode = 0;       // Stereo
                   s.gop = 0;              // "IBBPBBPBBPBBP"
                   s.filter = 7;           // YUV 4:2:0 v-decimation
                   s.motion[0] = 8;
                   s.motion[1] = 64;       // Motion compensation range 8-64
                   *extraOpts = 0;
                   break;

    case SMALL   : s.image_size = 0;       // 352x288
                   s.clipping = 1;
                   s.video_bit_rate = 20;  // 2 MBit
                   s.audio_bit_rate = 48;  // 48 KBit
                   s.audio_mode = 3;       // Mono
                   s.gop = 0;              // "IBBPBBPBBPBBP"
                   s.filter = 0;           // YUV 4:2:0 fastest
                   s.motion[0] = 8;
                   s.motion[1] = 64;       // Motion compensation range 8-64
                   sprintf(extraOpts, " -f3.125 -S32"); // 3.125 frames/second (25/8), sampling rate 32 kHz
                   break;
    
    case PVR     : s.image_size = 2;       // 720x576
                   s.video_bit_rate = 15;  // 1,5 .. 2,25 MBit
                   s.audio_bit_rate = 192; // 192 KBit
                   break;
  }
}

void cEncoder::Action(void)
{
  register int cc = 0, retries = 4;

  d(3, "cEncoder::Action()");

  if (isPVR || !audio_free()) {

    // Unter V4L2 erkennt nxtvepg _nicht_, daß der Encoder "/dev/video"
    // benötigt, und darf _auf_keinen_Fall_ laufen :-(

    if ((v4l == 2) && !isPVR) {
      cc = SystemExec("killall -q nxtvepg");
        
      if (!cc) {
        d(1, "nxtvepg killed");
         nxtvepg_killed = 1;
      }
    }

    if (analogModule) // use the "ANALOG" module of the Siemens DVB-C
      videosource = 1;

    if (s.profile)
      LoadProfile(s.profile);

retry:
    if (s.mpeg_encoder == PVRPES) {
      d(1, "readPVR(Apid=%d, Vpid=%d)", Apid, Vpid);
      cc = readPVR(Apid, Vpid);
    }
    else {
      d(1, "runEncoder(Apid=%d, Vpid=%d)", Apid, Vpid);
      cc = runEncoder(Apid, Vpid);
    }

    switch (cc) {
      case  0 : if (!isPVR)
                  Assign(1); // remember settings of _this_ encoder instance
                d(0, "%s stopped.", (s.mpeg_encoder == PVRPES) ? "PVR reader" : "encoder");
                break;

      case -1 : d(0, "%s failed!%s", 
                  (s.mpeg_encoder == PVRPES) ? "PVR reader" : "encoder", 
                  (--retries > 0) ? " - retrying" : "");
        
                if ((retries > 0) && (s.mpeg_encoder == PVRPES)) {
      		  (void)tune(frequency, freqOffset);
                  goto retry;
                }
    		// AnalogtvDevice->StopEncoder(); FIXME
                break;

      case -2 : d(0, "open error!");
    		// AnalogtvDevice->StopEncoder(); FIXME
                break; 
    }
  }
  else
    d(0, "Can't open \"%s\", %d:%s", s.audio_device, errno, strerror(errno));
}
