Linux::DVB::DVBT - Perl extension for DVB terrestrial recording, epg, and scanning
use Linux::DVB::DVBT; # get list of installed adapters my @devices = Linux::DVB::DVBT->device_list() ; foreach (@devices) { printf "%s : adapter number: %d, frontend number: %d\n", $_->{name}, $_->{adapter_num}, $_->{frontend_num} ; } # Create a dvb object using the first dvb adapter in the list my $dvb = Linux::DVB::DVBT->new() ; # .. or specify the device numbers my $dvb = Linux::DVB::DVBT->new( 'adapter_num' => 2, 'frontend_num' => 1, ) ; # Scan for channels $dvb->scan_from_file('/usr/share/dvb/dvb-t/uk-Oxford') ; # Set channel $dvb->select_channel("BBC ONE") ; # Get EPG data my ($epg_href, $dates_href) = $dvb->epg() ; # Record 30 minute program (after setting channel using select_channel method) $dvb->record('test.ts', 30*60) ;
Linux::DVB::DVBT is a package that provides an object interface to any installed Freeview tuner cards fitted to a Linux PC. The package supports initial set up (i.e. frequency scanning), searching for the latest electronic program guide (EPG), and selectign a channel for recording the video to disk.
Example scripts have been provided in the package which illustrate the expected use of the package (and are useable programs in themeselves)
Shows information about fited DVB-T tuners
Run this by providing the frequency file (usually stored in /usr/share/dvb/dvb-t). If run as root, this will set up the configuration files for all users. For example:
$ dvbt-scan /usr/share/dvb/dvb-t/uk-Oxford
NOTE: Frequency files are provided by the 'dvb' rpm package available for most distros
When run, this grabs the latest EPG information and updates a MySql database:
$ dvbt-epg
Specify the channel, the duration, and the output filename to record a channel:
$ dvbt-record "bbc1" spooks.ts 1:00
Note that the duration can be specified as an integer (number of minutes), or in HH:MM format (for hours and minutes)
I started this package after being lent a Hauppauge WinTV-Nova-T usb tuner (thanks Tim!) and trying to do some command line recording. After I'd failed to get most applications to even talk to the tuner I discovered xawtv (http://linux.bytesex.org/xawtv/), started looking at it's source code and started reading the DVB-T standards.
This package is the result of various experminets and is being used for my web TV listing and program record scheduling software.
All of the object fields are accessed via an accessor method of the same name as the field, or by using the set method where the field name and value are passed as key/value pairs in a HASH
Number of the DVBT adapter. When multiple DVBT adapters are fitted to a machine, they will be numbered from 0 onwards. Use this field to select the adapter.
A single adapter may have multiple frontends. If so then use this field to select the frontend within the selected adapter.
Once the DVBT adapter has been selected, read this field to get the device path for the frontend. It will be of the form: /dev/dvb/adapter0/frontend0
Once the DVBT adapter has been selected, read this field to get the device path for the demux. It will be of the form: /dev/dvb/adapter0/demux0
Once the DVBT adapter has been selected, read this field to get the device path for the dvr. It will be of the form: /dev/dvb/adapter0/dvr0
Set this to the required debug level. Higher values give more verbose information.
Read this ARRAY ref to get the list of fitted DVBT adapters. This is equivalent to running the "device_list()" class method (see "device_list()" for array format)
Use this field to specify your preferred channel numbering.
You provide an ARRAY ref where the array contains HASHes of the form:
{ 'channel' => <channel name> 'channel_num' => <channel number> }
For example, you'd probably want 'BBC ONE' to have the channel number 1.
NOTE: When I've worked out how the logical channel numbering information is transmitted, then I'll automatically fill this in from the scan.
This is a HASH ref containing the parameters used in the last call to set_frontend(%params) (either externally or internally by this module).
Set to ':' separated list of directories. When the module wants to either read or write configuration settings (for channel frequencies etc) then it uses this field to determine where to read/write those files from.
By default this is set to:
/etc/dvb:~/.tv
Which means that the files are read from /etc/dvb if it has been created (by root); or alternatively it uses ~/.tv (which also happens to be where xawtv stores it's files). Similarly, when writing files these directories are searched until a writeable area is found (so a user won't be able to write into /etc/dvb).
Use this field to read back the tuning parameters HASH ref as scanned or read from the configuration files (see "scan()" method for format)
This field is only used internally by the object but can be used for debug/information.
Set this field to either 'die' (the default) or 'return' and when an error occurs, the error mode action will be taken.
If the mode is set to 'die' then the application will terminate after printing all of the errors stored in the errors list (see "errors" field). When the mode is set to 'return' then the object method returns control back to the calling application with a non-zero status. It is the application's responsibility to handle the errors (stored in "errors")
This is an ARRAY ref containing a list of any errors that have occurred. Each error is stored as a text string.
new([%args])
Create a new object.
The %args are specified as they would be in the set method, for example:
'adapter_num' => 0
The full list of possible arguments are as described in the "FIELDS" section
hwinit()
Object internal method
Initialise the hardware (create dvb structure). Called once and sets the adpater & frontend number for this object.
If no adapter number has been specified yet then use the first device in the list.
Use as Linux::DVB::DVBT->method()
debug([$level])
Set new debug level. Returns setting.
verbose([$level])
Set new verbosity level. Returns setting.
device_list()
Return list of available hardware as an array of hashes. Each hash entry is of the form:
{ 'device' => device name (e.g. '/dev/dvb/adapter0') 'name' => Manufacturer name 'adpater_num' => Adapter number 'frontend_num' => Frontend number 'flags' => Adapter capability flags }
Note that this information is also available via the object instance using the 'devices' method, but this returns an ARRAY REF (rather than an ARRAY)
set(%args)
Set one or more settable parameter.
The %args are specified as a hash, for example
set('frequency' => 578000)
select_channel($channel_name)
Tune the frontend & the demux based on $channel_name.
This method uses a "fuzzy" search to match the specified channel name with the name broadcast by the network. The case of the name is not important, and neither is whitespace. The search also checks for both numeric and name instances of a number (e.g. "1" and "one").
For example, the following are all equivalent and match with the broadcast channel name "BBC ONE":
bbc1 BbC One b b c 1
Returns 0 if ok; error code otherwise
log_error($error_message)
Add the error message to the error log. Get the log as an ARRAY ref via the 'errors()' method
handle_error($error_message)
Add the error message to the error log and then handle the error depending on the setting of the 'errmode' field.
Get the log as an ARRAY ref via the 'errors()' method.
set_frontend(%params)
Tune the frontend to the specified frequency etc. HASH %params contains:
'frequency' 'inversion' 'bandwidth' 'code_rate_high' 'code_rate_low' 'modulation' 'transmission' 'guard_interval' 'hierarchy' 'timeout'
(If you don't know what these parameters should be set to, then I recommend you just use the select_channel($channel_name) method)
set_demux($video_pid, $audio_pid, $teletext_pid)
Selects a particular video/audio stream (and optional teletext stream) and sets the demultiplexer to those streams (ready for recording).
Returns 0 for success; error code otherwise.
epg()
Gathers the EPG information into a HASH using the previously tuned frontend and returns the EPG info. If the frontend is not yet tuned then the method attempts to use the tuning information (either from a previous scan or from reading the config files) to set up the frontend.
Note that you can safely run this method while recording; the EPG scan does not affect the demux or the frontend (once it has been set)
Returns an array:
[0] = EPG HASH [1] = Dates HASH
EPG HASH format is:
$channel_name => $pid => { 'pid' => program unique id 'channel' => channel name 'date' => date 'start' => start time 'end' => end time 'duration' => duration 'title' => title string 'text' => synopsis string 'etext' => extra text (not usually used) 'genre' => genre string 'repeat' => repeat count 'episode' => episode number 'num_episodes' => number of episodes }
i.e. The information is keyed on channel name and program id (pid)
The genre string is formatted as:
"Major category|genre/genre..."
For example:
"Film|movie/drama (general)"
This allows for a simple regexp to extract the information (e.g. in a TV listings application you may want to only use the major category in the main view, then show the extra genre information in a more detailed view)
Dates HASH format is:
$channel_name => { 'start_date' => date of first program for this channel 'start' => start time of first program for this channel 'end_date' => date of last program for this channel 'end' => end time of last program for this channel }
i.e. The information is keyed on channel name
The dates HASH is created so that an existing EPG database can be updated by removing existing information for a channel between the indicated dates.
scan_from_file($freq_file)
Reads the DVBT frequency file (usually stored in /usr/share/dvb/dvb-t) and uses the contents to set the frontend to the initial frequency. Then starts a channel scan using that tuning.
$freq_file must be the full path to the file. The file contents should be something like:
# Oxford # T freq bw fec_hi fec_lo mod transmission-mode guard-interval hierarchy T 578000000 8MHz 2/3 NONE QAM64 2k 1/32 NONE
Returns the discovered channel information as a HASH (see "scan()")
scan()
Starts a channel scan using previously set tuning. On successful completion of a scan, saves the results into the configuration files.
Returns the discovered channel information as a HASH:
'pr' => { $channel_name => { 'audio' => "407", 'audio_details' => "eng:407 und:408", 'ca' => "0", 'name' => "301", 'net' => "BBC", 'pnr' => "19456", 'running' => "4", 'teletext' => "0", 'tsid' => "16384", 'type' => "1", 'video' => "203", }, .... }, 'ts' => { $tsid => { 'bandwidth' => "8", 'code_rate_high' => "23", 'code_rate_low' => "12", 'frequency' => "713833330", 'guard_interval' => "32", 'hierarchy' => "0", 'modulation' => "64", 'net' => "Oxford/Bexley", 'transmission' => "2", }, ... }
Normally this information is only used internally.
get_tuning_info()
Check to see if 'tuning' information has been set. If not, attempts to read from the config search path.
Returns a HASH ref of tuning information (see "scan()" method for format); otherwise returns undef
get_channel_list()
Checks to see if 'channel_list' information has been set. If not, attempts to create a list based on the scan information.
NOTE that the created list will be the best attempt at ordering the channels based on the TSID & PNR which won't be pretty, but it'll be better than nothing!
Returns an ARRAY ref of channel_list information (see 'channel_list' field for format); otherwise returns undef
TODO: In a later release I'll work out how to use the logical channel number broadcast on the NIT
record($file, $duration)
Streams the selected channel information (see "select_channel($channel_name)") into the file $file for $duration.
The duration may be specified either as an integer number of minutes, or in HH:MM format (for hours & minutes), or in HH:MM:SS format (for hours, minutes, seconds).
Note that (if possible) the method creates the directory path to the file if it doersn't already exist.
Gerd Knorr for writing xawtv (see http://linux.bytesex.org/xawtv/)
Some of the C code used in this module is used directly from Gerd's libng. All other files are entirely written by me, or drastically modified from Gerd's original to (a) make the code more 'Perl friendly', (b) to reduce the amount of code compiled into the library to just those functions required by this module.
Steve Price
Please report bugs using http://rt.cpan.org.
Subsequent releases will include:
Support for event-driven applications (e.g. POE). I need to re-write some of the C to allow for event-driven hooks (and special select calls)
Extraction of channel numbering from broadcast. I want to work out how to decode the LCN.
Copyright (C) 2008 by Steve Price
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.
To install Linux::DVB::DVBT, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Linux::DVB::DVBT
CPAN shell
perl -MCPAN -e shell install Linux::DVB::DVBT
For more information on module installation, please visit the detailed CPAN module installation guide.