NAME
Linux::DVB::DVBT - Perl extension for DVB terrestrial recording, epg, and scanning
SYNOPSIS
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) ;
# show the logical channel numbers
my $tuning_href = $dvb->get_tuning_info() ;
my $channels_aref = $dvb->get_channel_list() ;
print "Chans\n" ;
foreach my $ch_href (@$channels_aref)
{
my $chan = $ch_href->{'channel'} ;
printf "%3d : %-40s %5d-%5d $ch_href->{type}\n",
$ch_href->{'channel_num'},
$chan,
$tuning_href->{'pr'}{$chan}{'tsid'},
$tuning_href->{'pr'}{$chan}{'pnr'} ;
}
DESCRIPTION
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)
- dvbt-devices
-
Shows information about fited DVB-T tuners
- dvbt-scan
-
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
- dvbt-epg
-
When run, this grabs the latest EPG information and updates a MySql database:
$ dvbt-epg
- dvbt-record
-
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)
- dvbt-ffrec
-
Similar to dvbt-record, but pipes the transport stream into ffmpeg and uses that to transcode the data directly into an MPEG file (without saving the transport stream file).
Specify the channel, the duration, and the output filename to record a channel:
$ dvbt-ffrec "bbc1" spooks.mpeg 1:00
Note that the duration can be specified as an integer (number of minutes), or in HH:MM format (for hours and minutes)
- dvbt-devices
-
Displays the list of currently fitted DVB-T tuners.
- dvbt-chans
-
Use to display the current list of tuned channels. Shows them in logical channel number order.
Logical Channel Numbers (LCNs)
I've finally worked out how to gather the logical channel number information for all of the channels. The scan() method now stores the LCN information into the config files, and makes the list of channels available through the "get_channel_list()" method. So you can now get the channel number you see (and enter) on any standard freeview TV or PVR.
This is of most interest if you want to use the "epg()" method to gather data to create a TV guide. Generally, you'd like the channel listings to be sorted in the order to which we've all become used to through TV viewing (i.e. it helps to have BBC1 appear before channel 4!).
HISTORY
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.
FIELDS
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
- adapter_num - DVB adapter number
-
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.
- frontend_num - DVB frontend number
-
A single adapter may have multiple frontends. If so then use this field to select the frontend within the selected adapter.
- frontend_name - Device path for frontend (set multiplex)
-
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
- demux_name - Device path for demux (select channel within multiplex)
-
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
- dvr_name - Device path for dvr (video record access)
-
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
- debug - Set debug level
-
Set this to the required debug level. Higher values give more verbose information.
- devices - Fitted DVBT adapter list
-
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)
- merge - Merge scan results
-
Set this flag before running the scan() method. When set, the scan will merge the new results with any previous scan results (read from the config files)
By default this flag is cleared (so each scan will start from fresh).
- frontend_params - Last used frontend settings
-
This is a HASH ref containing the parameters used in the last call to set_frontend(%params) (either externally or internally by this module).
- config_path - Search path for configuration files
-
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).
- tuning - Channel tuning information
-
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.
- errmode - Set error handling mode
-
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")
- errors - List of errors
-
This is an ARRAY ref containing a list of any errors that have occurred. Each error is stored as a text string.
CONSTRUCTOR
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.
CLASS METHODS
Use as Linux::DVB::DVBT->method()
debug([$level])
-
Set new debug level. Returns setting.
dvb_debug([$level])
-
Set new debug level for dvb XS code
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)
OBJECT DATA METHODS
set(%args)
-
Set one or more settable parameter.
The %args are specified as a hash, for example
set('frequency' => 578000)
The full list of possible arguments are as described in the "FIELDS" section
OBJECT METHODS
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)
-
Object internal method
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)
Returns 0 if ok; error code otherwise
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).
(If you don't know what these parameters should be set to, then I recommend you just use the select_channel($channel_name) method)
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
NOTE: Frequency files are provided by the 'dvb' rpm package available for most distros
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", 'lcn' => 301 }, .... }, '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()
-
Object internal method
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()
-
Object internal method
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; otherwise returns undef. The array is sorted by logical channel number and contains HASHes of the form:
{ 'channel' => channel name (e.g. "BBC THREE") 'channel_num' => the logical channel number (e.g. 7) 'type' => radio or tv channel ('radio' or 'tv') }
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.
ACKNOWLEDGEMENTS
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.
AUTHOR
Steve Price
Please report bugs using http://rt.cpan.org.
FUTURE
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)
COPYRIGHT AND LICENSE
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.