<br />On Wednesday, November 6, 2013 15:17 CET, Roald <roalda@gmail.com> wrote:<br /> <blockquote>On Wed, Nov 6, 2013 at 8:42 AM, Marius Schrecker<br />wrote:<br /><br />> Hi,<br />> I live in Norway and receive channel listings from a mixture of two<br />> xmltv sources which I have configured in a combined xmltv file.<br />><br />> Hi, what are these two xmltv sources? tv_grab_no_gfeed seems to be dead<br />now, so I am not sure where to get listings from.<br /><br />--<br />Regards Roald Amundsen</blockquote><br />Here are the grabber lines from my .xmltv file: <br />grabber=/usr/bin/tv_grab_no_gfeed;root-url=http://data.epg.no/xmltv/channels.xml.gz<br />grabber=/usr/bin/tv_grab_la;root-url=http://xmltv.tvtab.la/xmltv/channels.xml<br /><br />But the latter is a modified grabber script:<br /><br />#!/usr/bin/perl -w<br /><br />eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'<br /> if 0; # not running under some shell
<br /><br />=pod<br /><br />=head1 NAME<br /><br />tv_grab_la - Grab TV listings for Scandinavia through "Joakim Nylen" server.<br /><br />=head1 SYNOPSIS<br /><br />tv_grab_la --help<br /><br />tv_grab_la --configure [--config-file FILE] [--gui OPTION]<br /><br />tv_grab_la [--config-file FILE] <br /> [--days N] [--offset N]<br /> [--output FILE] [--quiet] [--debug]<br /><br />tv_grab_la --list-channels [--config-file FILE]<br /> [--output FILE] [--quiet] [--debug]<br /> <br /> <br />=head1 DESCRIPTION<br /><br />Output TV and listings in XMLTV format for many stations<br />available in Scandinavia. <br /><br />First you must run B<tv_grab_la --configur
e> to choose which stations<br />you want to receive.<br /><br />Then running B<tv_grab_la> with no arguments will get a listings for<br />the stations you chose for five days including today.<br /><br />=head1 OPTIONS<br /><br />B<--configure> Prompt for which stations to download and write the<br />configuration file.<br /><br />B<--config-file FILE> Set the name of the configuration file, the<br />default is B<~/.xmltv/tv_grab_la.conf>. This is the file written by<br />B<--configure> and read when grabbing.<br /><br />B<--gui OPTION> Use this option to enable a graphical interface to be used.<br />OPTION may be 'Tk', or left blank for the best available choice.<br />Additional allowed values of OPTION are 'Term' for normal terminal output<br />(default) and 'TermNoProgressBar' to disable the use of Term::ProgressBar.<br /><br />B<--output FILE> When grabbing, write output to FILE rather than<br />s
tandard output.<br /><br />B<--days N> When grabbing, grab N days rather than 5.<br /><br />B<--offset N> Start grabbing at today + N days. N may be negative.<br /><br />B<--quiet> Suppress the progress-bar normally shown on standard error.<br /><br />B<--debug> Provide more information on progress to stderr to help in<br />debugging.<br /><br />B<--list-channels> Output a list of all channels that data is available<br /> for. The list is in xmltv-format.<br /><br />B<--version> Show the version of the grabber.<br /><br />B<--help> Print a help message and exit.<br /><br />=head1 ERROR HANDLING<br /><br />If the grabber fails to download data for some channel on a specific day, <br />it will print an errormessage to STDERR and then continue with the other<br />channels and days. The grabber will exit with a status code of 1 to indicate
<br />that the data is incomplete. <br /><br />=head1 ENVIRONMENT VARIABLES<br /><br />The environment variable HOME can be set to change where configuration<br />files are stored. All configuration is stored in $HOME/.xmltv/. On Windows,<br />it might be necessary to set HOME to a path without spaces in it.<br /><br />=head1 SUPPORTED CHANNELS<br /><br />For information on supported channels, see http://xmltv.tvtab.la/<br /><br />=head1 AUTHOR<br /><br />Mattias Holmlund, mattias -at- holmlund -dot- se. This documentation<br />and parts of the code copied from tv_grab_uk by<br />Ed Avis, ed -at- membled -dot- com.<br /><br />=head1 BUGS<br /><br />=cut<br /><br />use strict;<br /><br />use XMLTV;<br />use XMLTV::ProgressBar;<br />use XMLTV::Options qw/ParseOptions/;<br />use XMLTV::Configure::Writer;<br /><br />use XML::LibXML;<br />use Date::Manip;<br />use Compress::Zlib;<br />use File::Path;<br />use File::Basename;<br />use IO::Scalar;<br />use LWP;<br /><br
/>my $ua;<br />$ua = LWP::UserAgent->new();<br />$ua->agent("xmltv/$XMLTV::VERSION");<br />$ua->env_proxy();<br /><br />use HTTP::Cache::Transparent;<br /><br /># Although we use HTTP::Cache::Transparent, this undocumented --cache<br /># option for debugging is still useful since it will _always_ use a<br /># cached copy of a page, without contacting the server at all.<br />#<br />use XMLTV::Memoize; XMLTV::Memoize::check_argv('getuncompressed');<br /><br />sub t;<br /><br />my $default_root_url = 'http://xmltv.tvtab.la/xmltv/channels.xml.gz';<br />my $default_cachedir = get_default_cachedir();<br /><br />my( $opt, $conf ) = ParseOptions( { <br /> grabber_name => "tv_grab_la",<br /> capabilities => [qw/baseline manualconfig tkconfig apiconfig cache/],<br /> stage_sub => \&config_stage,<br /> listchannels_sub => \&list_channels,<br /> load_old
_config_sub => \&load_old_config,<br /> version => '$Id: tv_grab_se_swedb.in,v 1.8 2010/10/01 17:49:30 dekarl Exp $',<br /> description => "Scandinavia - (Nylen)",<br /><br />} );<br /><br />if (not defined( $conf->{cachedir} )) {<br /> print STDERR "No cachedir defined in configfile " . <br /> $opt->{'config-file'} . "\n" .<br /> "Please run the grabber with --configure.\n";<br /> exit 1;<br />}<br /><br />if (not defined( $conf->{'root-url'} )) {<br /> print STDERR "No root-url defined in configfile " .<br /> $opt->{'config-file'} . "\n" .<br /> &quo
t;Please run the grabber with --configure.\n";<br /> exit 1;<br />}<br /><br />if (not defined( $conf->{'channel'} )) {<br /> print STDERR "No channels selected in configfile " .<br /> $opt->{'config-file'} . "\n" .<br /> "Please run the grabber with --configure.\n";<br /> exit 1;<br />}<br /><br />init_cachedir( $conf->{cachedir}->[0] );<br />HTTP::Cache::Transparent::init( { <br /> BasePath => $conf->{cachedir}->[0],<br /> NoUpdate => 15*60,<br /> Verbose => $opt->{debug},<br /> } );<br /><br />binmode (STDOUT);<br /><br />my($xmldecl, $channels) = load_channels( $conf->{'root-url'}->[0] );<br /><br />my( $odoc, $root );<br />my $warnings = 0;<br /><br />write_heade
r( $xmldecl );<br /><br />write_channel_list( $conf->{channel} );<br /><br />my $now = ParseDate( 'now' );<br />my $date =$now;<br />$date = DateCalc( $now, "+$opt->{offset} days" ) <br /> if( $opt->{offset} );<br /><br />my $bar = undef;<br />$bar = new XMLTV::ProgressBar( {<br /> name => 'downloading listings',<br /> count => $opt->{days} * @{$conf->{channel}},<br /> }) if (not $opt->{quiet}) && (not $opt->{debug});<br /><br />for( my $i=0; $i < $opt->{days}; $i++ )<br />{<br /> t "Date: $date";<br /> foreach my $channel_id (@{$conf->{channel}})<br /> {<br /> # We have already warned the user if the channel doesn't exist.<br /> if( exists $channels->{$channel_id} )<br /> {<br /> &
nbsp; t " $channel_id";<br /> my( $channel_name, $url ) = @{$channels->{$channel_id}};<br /> print_data( $url, $channel_id, $date )<br /> or warning( "Failed to download data for $channel_id on " . <br /> UnixDate( $date, "%Y-%m-%d" ) . "." );<br /> }<br /> $bar->update() if defined( $bar );<br /> }<br /> $date = DateCalc( $date, "+1 days" );<br />}<br /><br />$bar->finish() if defined $bar;<br /><br />write_footer();<br /><br /># Signal that something went wrong if there were warnings.<br />exit(1) if $warnings;<br /><br /># All data fetched ok.<br />t "Exiting without warnings.";<br />e
xit(0);<br /><br />sub t<br />{<br /> my( $message ) = @_;<br /> print STDERR $message . "\n" if $opt->{debug};<br />}<br /><br />sub warning<br />{<br /> my( $message ) = @_;<br /> print STDERR $message . "\n";<br /> $warnings++;<br />}<br /><br />sub list_channels<br />{<br /> my( $conf, $opt ) = @_;<br /><br /> ( $xmldecl, $channels ) = load_channels( $conf->{'root-url'}->[0] );<br /> <br /> my $result="";<br /> my $fh = new IO::Scalar \$result;<br /> my $oldfh = select( $fh );<br /> write_header( $xmldecl );<br /> write_channel_list( [sort keys %{$channels}] );<br /> write_footer();<br /> select( $oldfh );<br /> $fh->close();<br /><br /> return $result;<br />}<br /><br />sub config_stage<br />{<br />
my( $stage, $conf ) = @_;<br /><br /> die "Unknown stage $stage" if $stage ne "start";<br /><br /> my $result;<br /> my $writer = new XMLTV::Configure::Writer( OUTPUT => \$result,<br /> encoding => 'iso-8859-1' );<br /> $writer->start( { grabber => 'tv_grab_la' } );<br /> $writer->write_string( {<br /> id => 'root-url', <br /> title => [ [ 'Root URL for grabbing data', 'en' ] ],<br /> description => [ <br /> [ 'The file at this URL describes which channels are available and ' .<br />  
;'where data can be found for them. ', 'en' ] ],<br /> default => $default_root_url,<br /> } );<br /> $writer->write_string( {<br /> id => 'cachedir', <br /> title => [ [ 'Directory to store the cache in', 'en' ] ],<br /> description => [ <br /> [ 'tv_grab_la uses a cache with files that it has already '. <br /> 'downloaded. Please specify where the cache shall be stored. ', <br /> 'en' ] ],<br /> default => $default_cachedir,<br /> } );<br /><br /> $writer->end( 'select-channels' );<br /><br /> return $result;<br />}<br /><br />#<br /># Load a
configuration file in the old format.<br />#<br /><br />sub load_old_config<br />{<br /> my( $config_file ) = @_;<br /><br /> my @lines = XMLTV::Config_file::read_lines( $config_file );<br /> <br /> my $conf = {};<br /> $conf->{cachedir}->[0] = $default_cachedir;<br /> $conf->{'root-url'}->[0] = $default_root_url;<br /> $conf->{channel} = [];<br /><br /> foreach my $line (@lines)<br /> {<br /> next unless defined $line;<br /><br /> my( $command, $param ) = split( /\s+/, $line, 2 );<br /> $param =~ tr/\n\r//d;<br /> $param =~ s/\s+$//;<br /><br /> if ( $command =~ /^\s*root-url\s*$/) {<br /> $conf->{'root-url'}->[0] = $param;<br /> &n
bsp; } elsif ( $command =~ /^\s*channel\s*$/) {<br /> push @{$conf->{channel}}, $param;<br /> } elsif ( $command eq 'cache-dir' ) {<br /> $conf->{'cachedir'}->[0] = $param;<br /> } else {<br /> die "Unknown command $command in config-file $config_file"<br /> }<br /> }<br /><br /> return $conf;<br />}<br /><br />sub get_default_cachedir<br />{<br /> my $winhome = $ENV{HOMEDRIVE} . $ENV{HOMEPATH} <br /> if defined( $ENV{HOMEDRIVE} ) <br /> and defined( $ENV{HOMEPATH} ); <br /> <br /> my $home = $ENV{HOME} || $winhome || ".";<br /> return "$home/.xmltv/cache";<br />}<br /><br
/>sub init_cachedir<br />{<br /> my( $path ) = @_;<br /> if( not -d $path )<br /> {<br /> mkpath( $path ) or die "Failed to create cache-directory $path: $@";<br /> }<br />}<br /><br />sub load_channels<br />{<br /> my( $url ) = @_;<br /> <br /> my %channels;<br /><br /> my $xmldata = getuncompressed( $url );<br /><br /> defined( $xmldata ) or die "Failed to fetch $url";<br /><br /> my $xml = XML::LibXML->new;<br /> <br /> my $doc = $xml->parse_string($xmldata);<br /><br /> my $xmldecl = "<?xml version='" . $doc->version() . "' " . <br /> "encoding='" . $doc->encoding() . "'?>\n";<br /><br /> my $ns = $doc->find( "//channel&quo
t; );<br /><br /> foreach my $node ($ns->get_nodelist)<br /> {<br /> my $id = $node->findvalue( '@id' );<br /> my $name = $node->findvalue( 'display-name[1]' );<br /> my $url = $node->findvalue( 'base-url' );<br /> my $urlns = $node->find( './base-url' );<br /> foreach my $urlnode ($urlns->get_nodelist)<br /> {<br /> $node->removeChild( $urlnode );<br /> }<br /> $channels{$id} = [ $name, $url, $node->toString(0, 1) ];<br /> }<br /><br /> return ($xmldecl, \%channels);<br />}<br /><br />sub print_data<br />{<br /> my( $rooturl, $channel_id, $date ) = @_;<br /> <br /> my $url
= $rooturl . $channel_id . "_" . UnixDate( $date, "%Y-%m-%d" ) . <br /> ".xml.gz";<br /><br /> my $xmldata = getuncompressed( $url );<br /><br /> defined $xmldata or return 0;<br /><br /> my $in = new IO::Scalar \$xmldata;<br /> while( my $line = $in->getline() )<br /> {<br /> last if $line =~ /<tv/;<br /> }<br /><br /> while( my $line = $in->getline() )<br /> {<br /> last if $line =~ /<\/tv>/;<br /> print $line;<br /> }<br /><br /> return 1;<br />}<br /><br />sub write_header<br />{<br /> my( $xmldecl ) = @_;<br /><br /> # Use the same xml declaration as the one in<br /> # channels.xml<br /> print $xmldecl;<br /> print '&l
t;!DOCTYPE tv SYSTEM "xmltv.dtd">' . "\n";<br /> print "<tv>\n";<br />}<br /><br />sub write_channel_list<br />{<br /> my( $channel_list ) = @_;<br /><br /> # Write list of channels.<br /> t 'Writing list of channels.';<br /><br /> foreach my $channel_id (@{$channel_list})<br /> {<br /> if( not exists $channels->{$channel_id} )<br /> {<br /> print STDERR "Unknown channel $channel_id." .<br /> " See http://xmltv.tvtab.la/" . <br /> " for a list of available channels or run" . <br /> " tv_grab_la --configure to reconfigure.\n";<br /> &nb
sp; next;<br /> }<br /> <br /> my( $channel_name, $url, $def ) = @{$channels->{$channel_id}};<br /> print " $def\n";<br /> }<br />}<br /><br />sub write_footer<br />{<br /> print "</tv>\n";<br />}<br /><br />sub getuncompressed {<br /> my( $url ) = @_;<br /><br /> my $response = $ua->get($url);<br /><br /> return undef<br /> unless $response->is_success;<br /><br /> my $compressed = $response->content<br /> or return undef;<br /><br /> # Since LWP 5.827, the result from get() is already<br /> # uncompressed.<br /><br /> my $uncompressed;<br /><br /> eval {<br /> $uncompressed = Compress::Zlib::m
emGunzip( \$compressed );<br /> };<br /><br /> $uncompressed = $compressed if not defined $uncompressed;<br /><br /> return $uncompressed;<br />}<br /><br />### Setup indentation in Emacs<br />## Local Variables:<br />## perl-indent-level: 4<br />## perl-continued-statement-offset: 4<br />## perl-continued-brace-offset: 0<br />## perl-brace-offset: -4<br />## perl-brace-imaginary-offset: 0<br />## perl-label-offset: -2<br />## cperl-indent-level: 4<br />## cperl-brace-offset: 0<br />## cperl-continued-brace-offset: 0<br />## cperl-label-offset: -2<br />## cperl-extra-newline-before-brace: t<br />## cperl-merge-trailing-else: nil<br />## cperl-continued-statement-offset: 2<br />## End:<br /><br /><br />