/**
  \class CVideoDeviceTuner
  \brief Tuner on V4L device
  
  This class sets the frequency and norm on the TV or radio tuner on a
  TV/radio card. The frequency is represented as a float number in Hz.

  There are three basic TV systems on this planet: PAL, NTSC and SECAM.
  There are also small variations in these systems, called <i>norms</i>.
  There are norms like PAL-B, -D, -G, -H, -I, M, -N, -MC; NTSC has two
  versions, `plain' NTSC (as used in the USA) and NTSC-Japan. SECAM seems
  to have only one norm. In practice, these norms are all the same when
  viewing a broadcast; as far as I know the main differences lie in the
  assignment of the hidden line numbers to services like TeleText, Closed
  Captioning, etc.
*/  

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/ioctl.h>

#include "VideoDeviceInput.h"
#include "VideoDeviceTuner.h"
#include "VideoDevice.h"

/**
  \brief Constructor
  \param _video Master VideoDevice object
  \param _tuner Tuner number (should rarely be > 0)
*/
CVideoDeviceTuner::CVideoDeviceTuner(CVideoDevice *_video, int _tuner)
{
   struct video_tuner vtun;
   
   pVideo = _video;
   Tuner = _tuner;

   FreqLow = 0;
   FreqHigh = 0;
   FreqStep = 1;

   memset(&vtun, 0, sizeof(vtun));
   vtun.tuner = Tuner;
   if (ioctl(pVideo->CamFD, VIDIOCGTUNER, &vtun) < 0)
     return;
   Name = vtun.name;
   Flags = vtun.flags;
   if (Flags & VIDEO_TUNER_LOW)
     FreqStep = 1.0e3 / 16;
   else
     FreqStep = 1.0e6 / 16;
   FreqLow  = vtun.rangelow * FreqStep;
   FreqHigh = vtun.rangehigh * FreqStep;
}


const QString CVideoDeviceTuner::GetName()
{
   return Name;
}

float CVideoDeviceTuner::GetLowestFrequency() const
{
   return FreqLow;
}

float CVideoDeviceTuner::GetHighestFrequency() const
{
   return FreqHigh;
}

/**
  \brief Return frequency of tuner, in Hz
  \return -1.0 in case of failure
*/
float CVideoDeviceTuner::GetFrequency() const
{
   if (ioctl(pVideo->CamFD, VIDIOCGFREQ, &ufreq) < 0)
     return -1.0;
   return ufreq * FreqStep;
}

/**
  \brief Set frequency
  \param freq Desired frequency, in Hz
  \return FALSE if device refused the frequency or was not able to, TRUE with success
*/  
bool CVideoDeviceTuner::SetFrequency(float freq)
{
   ufreq = (ulong)(freq / FreqStep);
   if (ioctl(pVideo->CamFD, VIDIOCSFREQ, &ufreq) < 0)
     return FALSE;
   return TRUE;
}

/**
  \brief Returns whether this input can have its norm set.
*/
bool CVideoDeviceTuner::HasNorm() const
{
   if (Flags & (VIDEO_TUNER_NORM | VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC | VIDEO_TUNER_SECAM))
     return TRUE;
   return FALSE;
}

void CVideoDeviceTuner::SetNorm(int norm)
{
   if (norm < MAX)
     Norm = norm;
}

int CVideoDeviceTuner::GetNorm() const
{
   return Norm;
}   
