1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
/**
\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 "VideoDeviceLinux.h"
/**
\brief Constructor
\param _video Master VideoDevice object
\param _tuner Tuner number (should rarely be > 0)
*/
CVideoDeviceTuner::CVideoDeviceTuner(CVideoDeviceLinux *_video, int _tuner)
{
struct video_tuner vtun;
pVideo = _video;
Tuner = _tuner;
FreqLow = 0;
FreqHigh = 0;
FreqStep = 1;
Flags = 0;
memset(&vtun, 0, sizeof(vtun));
vtun.tuner = Tuner;
if (ioctl(pVideo->GetDescriptor(), 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->GetDescriptor(), VIDIOCGFREQ, &ufreq) < 0)
return -1.0;
return ufreq * FreqStep;
}
/**
\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;
}
TVChannel::TunerNorms CVideoDeviceTuner::GetNorm() const
{
return TVChannel::TunerNorms_MAX;
}
/**
\brief Will trigger this Tuner
*/
bool CVideoDeviceTuner::Select()
{
struct video_tuner v;
v.tuner = Tuner;
if (ioctl(pVideo->GetDescriptor(), VIDIOCGTUNER, &v) < 0)
return false;
if (ioctl(pVideo->GetDescriptor(), VIDIOCSTUNER, &v) < 0)
return false;
emit Selected(Tuner);
return true;
}
// public slots
/**
\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->GetDescriptor(), VIDIOCSFREQ, &ufreq) < 0)
return false;
return true;
}
/**
\brief Set television norm for this tuner
A 'norm' is a combination of horizontal and vertical resolution, and color
coding information; the most common are PAL (with small variations), NTSC and
SECAM. Strictly speaking, the resolution and color coding mechanics are separated;
but often they are not. As a counter-example, in Brazil they use NTSC resolution
and PAL color coding.
*/
void CVideoDeviceTuner::SetNorm(TVChannel::TunerNorms norm)
{
qDebug("<> CVideoDeviceTuner::SetNorm(%d)", norm);
if (norm < TVChannel::TunerNorms_MAX && HasNorm())
{
struct video_tuner v;
v.tuner = Tuner;
if (ioctl(pVideo->GetDescriptor(), VIDIOCGTUNER, &v) < 0)
return;
switch (norm)
{
case TVChannel::PAL_BG:
case TVChannel::PAL_NC:
case TVChannel::PAL_M:
case TVChannel::PAL_N:
v.mode = VIDEO_MODE_PAL;
break;
case TVChannel::NTSC:
case TVChannel::NTSC_JAPAN:
v.mode = VIDEO_MODE_NTSC;
break;
case TVChannel::SECAM:
v.mode= VIDEO_MODE_SECAM;
break;
}
if (ioctl(pVideo->GetDescriptor(), VIDIOCSTUNER, &v) < 0)
{
qWarning("CVideoDeviceTuner::SetNorm() Failed to set norm %d.", norm);
}
}
}
|