File: VideoDeviceTuner.cc

package info (click to toggle)
camstream 0.27%2Bdfsg-3
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 12,320 kB
  • ctags: 5,393
  • sloc: cpp: 17,031; sh: 8,154; asm: 455; ansic: 440; makefile: 343
file content (176 lines) | stat: -rw-r--r-- 4,347 bytes parent folder | download | duplicates (2)
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);
     }
   }
}