1 |
=head1 NAME |
2 |
|
3 |
Linux::DVB - interface to (some parts of) the Linux DVB API |
4 |
|
5 |
=head1 SYNOPSIS |
6 |
|
7 |
use Linux::DVB; |
8 |
|
9 |
=head1 DESCRIPTION |
10 |
|
11 |
This module provides an interface to the Linux DVB API. It is a straightforward |
12 |
translation of the C API. You should read the Linux DVB API description to make |
13 |
any sense of this module. It can be found here: |
14 |
|
15 |
http://www.linuxtv.org/docs/dvbapi/dvbapi.html |
16 |
|
17 |
All constants from F<frontend.h> and F<demux.h> are exported by their C |
18 |
name and by default. |
19 |
|
20 |
Noteworthy differences to the C API: unions and sub-structs are usually |
21 |
translated into flat perl hashes, i.e C<struct.u.qam.symbol_rate> |
22 |
becomes C<< $struct->{symbol_rate} >>. |
23 |
|
24 |
Noteworthy limitations of this module include: no way to set the |
25 |
frequency or diseqc. No interface to the video, audio and net devices. |
26 |
If you need this functionality bug the author. |
27 |
|
28 |
=cut |
29 |
|
30 |
package Linux::DVB; |
31 |
|
32 |
use Fcntl (); |
33 |
|
34 |
BEGIN { |
35 |
$VERSION = '0.2'; |
36 |
@ISA = qw(Exporter); |
37 |
|
38 |
require XSLoader; |
39 |
XSLoader::load __PACKAGE__, $VERSION; |
40 |
|
41 |
require Exporter; |
42 |
|
43 |
my %consts = &_consts; |
44 |
my $consts; |
45 |
while (my ($k, $v) = each %consts) { |
46 |
push @EXPORT, $k; |
47 |
$consts .= "sub $k(){$v}\n"; |
48 |
} |
49 |
eval $consts; |
50 |
} |
51 |
|
52 |
sub new { |
53 |
my ($class, $path, $mode) = @_; |
54 |
|
55 |
my $self = bless { path => $path, mode => $mode }, $class; |
56 |
sysopen $self->{fh}, $path, $mode | &Fcntl::O_NONBLOCK |
57 |
or die "$path: $!"; |
58 |
$self->{fd} = fileno $self->{fh}; |
59 |
|
60 |
$self; |
61 |
} |
62 |
|
63 |
sub fh { $_[0]{fh} } |
64 |
sub fd { $_[0]{fd} } |
65 |
|
66 |
sub blocking { |
67 |
fcntl $_[0]{fh}, &Fcntl::F_SETFL, $_[1] ? 0 : &Fcntl::O_NONBLOCK; |
68 |
} |
69 |
|
70 |
package Linux::DVB::Frontend; |
71 |
|
72 |
@ISA = qw(Linux::DVB); |
73 |
|
74 |
=head1 Linux::DVB::Frontend CLASS |
75 |
|
76 |
=head2 SYNOPSIS |
77 |
|
78 |
my $fe = new Linux::DVB::Frontend $path, $writable; |
79 |
|
80 |
my $fe = new Linux::DVB::Frontend |
81 |
"/dev/dvb/adapter0/frontend0", 1; |
82 |
|
83 |
$fe->fh; # filehandle |
84 |
$fe->fd; # fileno |
85 |
$fe->blocking (0); # or 1 |
86 |
|
87 |
$fe->{name} |
88 |
$fe->{type} |
89 |
$fe->frontend_info->{name} |
90 |
|
91 |
$fe->status & FE_HAS_LOCK |
92 |
print $fe->ber, $fe->snr, $fe->signal_strength, $fe->uncorrected; |
93 |
|
94 |
my $tune = $fe->parameters; |
95 |
$tune->{frequency}; |
96 |
$tune->{symbol_rate}; |
97 |
|
98 |
=cut |
99 |
|
100 |
sub new { |
101 |
my ($class, $path, $mode) = @_; |
102 |
my $self = $class->SUPER::new ($path, $mode ? &Fcntl::O_RDWR : &Fcntl::O_RDONLY); |
103 |
|
104 |
%$self = ( %$self, %{ $self->frontend_info } ); |
105 |
|
106 |
$self; |
107 |
} |
108 |
|
109 |
sub frontend_info { _frontend_info ($_[0]{fd}) } |
110 |
sub status { _read_status ($_[0]{fd}) } |
111 |
sub ber { _read_ber ($_[0]{fd}) } |
112 |
sub snr { _snr ($_[0]{fd}) } |
113 |
sub signal_strength { _signal_strength ($_[0]{fd}) } |
114 |
sub uncorrected { _uncorrected ($_[0]{fd}) } |
115 |
|
116 |
=item $fe->set (parameter => value, ...) |
117 |
|
118 |
Sets frontend parameters. All values are stuffed into the |
119 |
C<dvb_frontend_parameters> structure without conversion and passed to |
120 |
FE_SET_FRONTEND. |
121 |
|
122 |
Returns true on success. |
123 |
|
124 |
All modes: |
125 |
|
126 |
frequency => |
127 |
inversion => |
128 |
|
129 |
QPSK frontends: |
130 |
|
131 |
symbol_rate => |
132 |
fec_inner => |
133 |
|
134 |
QAM frontends: |
135 |
|
136 |
symbol_rate => |
137 |
fec_inner => |
138 |
modulation => |
139 |
|
140 |
QFDM frontends: |
141 |
|
142 |
bandwidth => |
143 |
code_rate_HP => |
144 |
code_rate_LP => |
145 |
constellation => |
146 |
transmission_mode => |
147 |
|
148 |
=cut |
149 |
|
150 |
sub set { |
151 |
my ($self) = shift; |
152 |
_set $self->{fd}, { @_ }, $self->{type} |
153 |
} |
154 |
|
155 |
=item $fe->parameters |
156 |
|
157 |
Calls FE_GET_FRONTEND and returns a hash reference that contains the same keys |
158 |
as given to the C<set> method. |
159 |
|
160 |
Example: |
161 |
|
162 |
Data::Dumper::Dumper $fe->get |
163 |
|
164 |
{ |
165 |
frequency => 426000000, # 426 Mhz |
166 |
inversion => 0, # INVERSION_OFF |
167 |
symbol_rate => 6900000, # 6.9 MB/s |
168 |
fec_inner => 0, # FEC_NONE |
169 |
modulation => 3, # QAM_64 |
170 |
} |
171 |
|
172 |
=cut |
173 |
|
174 |
sub parameters { _get ($_[0]{fd}, $_[0]{type}) } |
175 |
sub get { _get ($_[0]{fd}, $_[0]{type}) } # unannounced alias |
176 |
sub event { _event ($_[0]{fd}, $_[0]{type}) } |
177 |
|
178 |
package Linux::DVB::Demux; |
179 |
|
180 |
@ISA = qw(Linux::DVB); |
181 |
|
182 |
=head1 Linux::DVB::Demux CLASS |
183 |
|
184 |
=head2 SYNOPSIS |
185 |
|
186 |
my $dmx = new Linux::DVB::Demux |
187 |
"/dev/dvb/adapter0/demux0"; |
188 |
|
189 |
$fe->fh; # filehandle |
190 |
$fe->fd; # fileno |
191 |
$fe->blocking (1); # non-blocking is default |
192 |
|
193 |
$dmx->buffer (16384); |
194 |
$dmx->sct_filter ($pid, "filter", "mask", $timeout=0, $flags=DMX_CHECK_CRC); |
195 |
$dmx->pes_filter ($pid, $input, $output, $type, $flags=0); |
196 |
$dmx->start; |
197 |
$dmx->stop; |
198 |
|
199 |
=cut |
200 |
|
201 |
sub new { |
202 |
my ($class, $path) = @_; |
203 |
my $self = $class->SUPER::new ($path, &Fcntl::O_RDWR); |
204 |
|
205 |
$self; |
206 |
} |
207 |
|
208 |
sub start { _start ($_[0]{fd}) } |
209 |
sub stop { _stop ($_[0]{fd}) } |
210 |
|
211 |
sub sct_filter { _filter ($_[0]{fd}, @_[1, 2, 3, 4, 5]) } |
212 |
sub pes_filter { _pes_filter ($_[0]{fd}, @_[1, 2, 3, 4, 5]) } |
213 |
sub buffer { _buffer ($_[0]{fd}, $_[1]) } |
214 |
|
215 |
package Linux::DVB::Decode; |
216 |
|
217 |
use Encode; |
218 |
|
219 |
sub text($) { |
220 |
for ($_[0]) { |
221 |
s/^([\x01-\x0b])// and $_ = decode sprintf ("iso-8859-%d", 4 + ord $1), $_; |
222 |
# 10 - pardon you??? |
223 |
s/^\x11// and $_ = decode "utf16-be", $_; |
224 |
# 12 ksc5601, DB |
225 |
# 13 db2312, DB |
226 |
# 14 big5(?), DB |
227 |
s/\x8a/\n/g; |
228 |
#s/([\x00-\x09\x0b-\x1f\x80-\x9f])/sprintf "{%02x}", ord $1/ge; |
229 |
s/([\x00-\x09\x0b-\x1f\x80-\x9f])//ge; |
230 |
} |
231 |
} |
232 |
|
233 |
1; |
234 |
|
235 |
=head1 AUTHOR |
236 |
|
237 |
Marc Lehmann <schmorp@schmorp.de> |
238 |
http://home.schmorp.de/ |
239 |
|
240 |
=cut |
241 |
|