/**
  \class CVideoDeviceInput
  
  Every video device has one or more inputs (called channels in the
  Video4Linux API). Each input refers to one of the physical inputs
  on the card/chip, like Tuner, Composite, S-video, etc. This class represents
  such an input.
  
  In addition, each input can have 0 or more tuners attached to it (to keep
  matters simple...). A tuner does the actual frequency and norm setting, 
  and is represented by a \ref CVideoDeviceTuner class.
*/

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

#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>

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

/** 
  \brief Constructor
  
  In the constructor the channel information is queried and stored. It
  will also create any Tuner objects that may be needed.
*/

CVideoDeviceInput::CVideoDeviceInput(CVideoDevice *video, int channel)
{
   struct video_channel vchan;
   char buf[33];

   pVideo = video;
   Channel = channel;
   
   Type = Unknown;
   flags = 0;
   CurrentTuner = -1;

   Tuners.setAutoDelete(TRUE);
   // Query data 
   vchan.channel = Channel;
   if (ioctl(pVideo->CamFD, VIDIOCGCHAN, &vchan) == 0) {
     strncpy(buf, vchan.name, 32);
     buf[32] = '\0';
     Name = buf;

     if (vchan.flags & VIDEO_VC_TUNER) {
       Tuners.resize(vchan.tuners);
       for (int i = 0; i < vchan.tuners; i++)
          Tuners.insert(i, new CVideoDeviceTuner(pVideo, i));
     }
     else
       Tuners.resize(0);
     switch(vchan.type) {
       case VIDEO_TYPE_TV:     Type = TV;     break;
       case VIDEO_TYPE_CAMERA: Type = Camera; break;
     }
     flags = vchan.flags;
   }
   else
     qWarning("CVideoDeviceInput: Warning: no channel info available.");
}  

/**
  \brief Return channel number.
*/
int CVideoDeviceInput::GetNumber() const
{
   return Channel;
}

/**
  \brief Return symbolic name for input.
*/
QString CVideoDeviceInput::GetName() const
{
   return Name;
}

/**
  \brief Returns whether this input has audio settings associated with it.
*/
bool CVideoDeviceInput::HasAudio() const
{
   if (flags & VIDEO_VC_AUDIO)
     return TRUE;
   return FALSE;
}

/**
  \brief Return type for this input.
  
  Returns a value from the \ref InputTypes enum, either TV or Camera
*/  
int CVideoDeviceInput::GetType() const
{
   return Type;
}

/**
  \brief Return number of tuners.

  Most inputs don't have a tuner, or at most 1. Multiple tuners could
  be used for multi-norm cards (each norm having a separate tuner), but
  this hasn't happened sofar.
*/
int CVideoDeviceInput::GetTuners() const
{
   return Tuners.count();
}

/**
  \brief Get a Tuner object
  \param number The desired input (0 to GetTuners() - 1); -1 for default (current) one
*/
CVideoDeviceTuner *CVideoDeviceInput::GetTuner(int number) const
{
   if (number == -1) {
     if (CurrentTuner < 0)
       return NULL;
     else
       return Tuners.at((uint) CurrentTuner);
   }
   else
     return Tuners.at((uint) number);
}

/**
  \brief Return current tuner number
  \return Tuner number, or -1 if the current tuner is unknown
  
  Since there is no way to query the current selected tuner from the device,
  this function returns -1 until a tuner has been selected.
*/
int CVideoDeviceInput::GetCurrentTuner() const
{
   return CurrentTuner;
}


bool CVideoDeviceInput::SelectTuner(int number)
{
   struct video_tuner v;
   
   v.tuner = number;
   if (ioctl(pVideo->CamFD, VIDIOCGTUNER, &v) < 0)
     return FALSE;
   if (ioctl(pVideo->CamFD, VIDIOCSTUNER, &v) < 0)
     return FALSE;
   CurrentTuner = number;
   return FALSE;
}



/**
  \brief Make this input the current one.
  
*/
bool CVideoDeviceInput::Select()
{
   if (pVideo)
     return pVideo->SelectVideoInput(Channel);
   return FALSE;
}
