<br />On Wednesday, November 6, 2013 15:17 CET, Roald &lt;roalda@gmail.com&gt; wrote:<br />&nbsp;<blockquote>On Wed, Nov 6, 2013 at 8:42 AM, Marius Schrecker<br />wrote:<br /><br />&gt; Hi,<br />&gt; I live in Norway and receive channel listings from a mixture of two<br />&gt; xmltv sources which I have configured in a combined xmltv file.<br />&gt;<br />&gt; 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:&nbsp;<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 &#39;exec /usr/bin/perl -w -S $0 ${1+&quot;$@&quot;}&#39;<br />&nbsp; &nbsp; 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 &quot;Joakim Nylen&quot; 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]&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[--days N] [--offset N]<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[--output FILE] [--quiet] [--debug]<br /><br />tv_grab_la --list-channels [--config-file FILE]<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[--output FILE] [--quiet] [--debug]<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<br />=head1 DESCRIPTION<br /><br />Output TV and listings in XMLTV format for many stations<br />available in Scandinavia.&nbsp;<br /><br />First you must run B&lt;tv_grab_la --configur
 e&gt; to choose which stations<br />you want to receive.<br /><br />Then running B&lt;tv_grab_la&gt; 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&lt;--configure&gt; Prompt for which stations to download and write the<br />configuration file.<br /><br />B&lt;--config-file FILE&gt; Set the name of the configuration file, the<br />default is B&lt;~/.xmltv/tv_grab_la.conf&gt;. &nbsp;This is the file written by<br />B&lt;--configure&gt; and read when grabbing.<br /><br />B&lt;--gui OPTION&gt; Use this option to enable a graphical interface to be used.<br />OPTION may be &#39;Tk&#39;, or left blank for the best available choice.<br />Additional allowed values of OPTION are &#39;Term&#39; for normal terminal output<br />(default) and &#39;TermNoProgressBar&#39; to disable the use of Term::ProgressBar.<br /><br />B&lt;--output FILE&gt; When grabbing, write output to FILE rather than<br />s
 tandard output.<br /><br />B&lt;--days N&gt; When grabbing, grab N days rather than 5.<br /><br />B&lt;--offset N&gt; Start grabbing at today + N days. &nbsp;N may be negative.<br /><br />B&lt;--quiet&gt; Suppress the progress-bar normally shown on standard error.<br /><br />B&lt;--debug&gt; Provide more information on progress to stderr to help in<br />debugging.<br /><br />B&lt;--list-channels&gt; &nbsp; &nbsp;Output a list of all channels that data is available<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for. The list is in xmltv-format.<br /><br />B&lt;--version&gt; Show the version of the grabber.<br /><br />B&lt;--help&gt; 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,&nbsp;<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
 &nbsp;<br />that the data is incomplete.&nbsp;<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-&gt;new();<br />$ua-&gt;agent(&quot;xmltv/$XMLTV::VERSION&quot;);<br />$ua-&gt;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(&#39;getuncompressed&#39;);<br /><br />sub t;<br /><br />my $default_root_url = &#39;http://xmltv.tvtab.la/xmltv/channels.xml.gz&#39;;<br />my $default_cachedir = get_default_cachedir();<br /><br />my( $opt, $conf ) = ParseOptions( {&nbsp;<br />&nbsp; &nbsp; grabber_name =&gt; &quot;tv_grab_la&quot;,<br />&nbsp; &nbsp; capabilities =&gt; [qw/baseline manualconfig tkconfig apiconfig cache/],<br />&nbsp; &nbsp; stage_sub =&gt; \&amp;config_stage,<br />&nbsp; &nbsp; listchannels_sub =&gt; \&amp;list_channels,<br />&nbsp; &nbsp; load_old
 _config_sub =&gt; \&amp;load_old_config,<br />&nbsp; &nbsp; version =&gt; &#39;$Id: tv_grab_se_swedb.in,v 1.8 2010/10/01 17:49:30 dekarl Exp $&#39;,<br />&nbsp; &nbsp; description =&gt; &quot;Scandinavia - (Nylen)&quot;,<br /><br />} );<br /><br />if (not defined( $conf-&gt;{cachedir} )) {<br />&nbsp; &nbsp; print STDERR &quot;No cachedir defined in configfile &quot; .&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$opt-&gt;{&#39;config-file&#39;} . &quot;\n&quot; .<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;Please run the grabber with --configure.\n&quot;;<br />&nbsp; &nbsp; exit 1;<br />}<br /><br />if (not defined( $conf-&gt;{&#39;root-url&#39;} )) {<br />&nbsp; &nbsp; print STDERR &quot;No root-url defined in configfile &quot; .<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$opt-&gt;{&#39;config-file&#39;} . &quot;\n&quot; .<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quo
 t;Please run the grabber with --configure.\n&quot;;<br />&nbsp; &nbsp; exit 1;<br />}<br /><br />if (not defined( $conf-&gt;{&#39;channel&#39;} )) {<br />&nbsp; &nbsp; print STDERR &quot;No channels selected in configfile &quot; .<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$opt-&gt;{&#39;config-file&#39;} . &quot;\n&quot; .<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;Please run the grabber with --configure.\n&quot;;<br />&nbsp; &nbsp; exit 1;<br />}<br /><br />init_cachedir( $conf-&gt;{cachedir}-&gt;[0] );<br />HTTP::Cache::Transparent::init( {&nbsp;<br />&nbsp; &nbsp; BasePath =&gt; $conf-&gt;{cachedir}-&gt;[0],<br />&nbsp; &nbsp; NoUpdate =&gt; 15*60,<br />&nbsp; &nbsp; Verbose =&gt; $opt-&gt;{debug},<br />&nbsp; &nbsp; } );<br /><br />binmode (STDOUT);<br /><br />my($xmldecl, $channels) = load_channels( $conf-&gt;{&#39;root-url&#39;}-&gt;[0] );<br /><br />my( $odoc, $root );<br />my $warnings = 0;<br /><br />write_heade
 r( $xmldecl );<br /><br />write_channel_list( $conf-&gt;{channel} );<br /><br />my $now = ParseDate( &#39;now&#39; );<br />my $date =$now;<br />$date = DateCalc( $now, &quot;+$opt-&gt;{offset} days&quot; )&nbsp;<br />&nbsp; &nbsp; if( $opt-&gt;{offset} );<br /><br />my $bar = undef;<br />$bar = new XMLTV::ProgressBar( {<br />&nbsp; &nbsp; name =&gt; &#39;downloading listings&#39;,<br />&nbsp; &nbsp; count =&gt; $opt-&gt;{days} * @{$conf-&gt;{channel}},<br />&nbsp; &nbsp; }) if (not $opt-&gt;{quiet}) &amp;&amp; (not $opt-&gt;{debug});<br /><br />for( my $i=0; $i &lt; $opt-&gt;{days}; $i++ )<br />{<br />&nbsp; &nbsp; t &quot;Date: $date&quot;;<br />&nbsp; &nbsp; foreach my $channel_id (@{$conf-&gt;{channel}})<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; # We have already warned the user if the channel doesn&#39;t exist.<br />&nbsp; &nbsp; &nbsp; &nbsp; if( exists $channels-&gt;{$channel_id} )<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &
 nbsp; t &quot; &nbsp;$channel_id&quot;;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my( $channel_name, $url ) = @{$channels-&gt;{$channel_id}};<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print_data( $url, $channel_id, $date )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; or warning( &quot;Failed to download data for $channel_id on &quot; .&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UnixDate( $date, &quot;%Y-%m-%d&quot; ) . &quot;.&quot; );<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; $bar-&gt;update() if defined( $bar );<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; $date = DateCalc( $date, &quot;+1 days&quot; );<br />}<br /><br />$bar-&gt;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 &quot;Exiting without warnings.&quot;;<br />e
 xit(0);<br /><br />sub t<br />{<br />&nbsp; &nbsp; my( $message ) = @_;<br />&nbsp; &nbsp; print STDERR $message . &quot;\n&quot; if $opt-&gt;{debug};<br />}<br /><br />sub warning<br />{<br />&nbsp; &nbsp; my( $message ) = @_;<br />&nbsp; &nbsp; print STDERR $message . &quot;\n&quot;;<br />&nbsp; &nbsp; $warnings++;<br />}<br /><br />sub list_channels<br />{<br />&nbsp; &nbsp; my( $conf, $opt ) = @_;<br /><br />&nbsp; &nbsp; ( $xmldecl, $channels ) = load_channels( $conf-&gt;{&#39;root-url&#39;}-&gt;[0] );<br />&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; my $result=&quot;&quot;;<br />&nbsp; &nbsp; my $fh = new IO::Scalar \$result;<br />&nbsp; &nbsp; my $oldfh = select( $fh );<br />&nbsp; &nbsp; write_header( $xmldecl );<br />&nbsp; &nbsp; write_channel_list( [sort keys %{$channels}] );<br />&nbsp; &nbsp; write_footer();<br />&nbsp; &nbsp; select( $oldfh );<br />&nbsp; &nbsp; $fh-&gt;close();<br /><br />&nbsp; &nbsp; return $result;<br />}<br /><br />sub config_stage<br />{<br />
 &nbsp; &nbsp; my( $stage, $conf ) = @_;<br /><br />&nbsp; &nbsp; die &quot;Unknown stage $stage&quot; if $stage ne &quot;start&quot;;<br /><br />&nbsp; &nbsp; my $result;<br />&nbsp; &nbsp; my $writer = new XMLTV::Configure::Writer( OUTPUT =&gt; \$result,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;encoding =&gt; &#39;iso-8859-1&#39; );<br />&nbsp; &nbsp; $writer-&gt;start( { grabber =&gt; &#39;tv_grab_la&#39; } );<br />&nbsp; &nbsp; $writer-&gt;write_string( {<br />&nbsp; &nbsp; &nbsp; &nbsp; id =&gt; &#39;root-url&#39;,&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; title =&gt; [ [ &#39;Root URL for grabbing data&#39;, &#39;en&#39; ] ],<br />&nbsp; &nbsp; &nbsp; &nbsp; description =&gt; [&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[ &#39;The file at this URL describes which channels are available and &#39; .<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp
 ;&#39;where data can be found for them. &#39;, &#39;en&#39; ] ],<br />&nbsp; &nbsp; &nbsp; &nbsp; default =&gt; $default_root_url,<br />&nbsp; &nbsp; &nbsp;} );<br />&nbsp; &nbsp; $writer-&gt;write_string( {<br />&nbsp; &nbsp; &nbsp; &nbsp; id =&gt; &#39;cachedir&#39;,&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; title =&gt; [ [ &#39;Directory to store the cache in&#39;, &#39;en&#39; ] ],<br />&nbsp; &nbsp; &nbsp; &nbsp; description =&gt; [&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[ &#39;tv_grab_la uses a cache with files that it has already &#39;.&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39;downloaded. Please specify where the cache shall be stored. &#39;,&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39;en&#39; ] ],<br />&nbsp; &nbsp; &nbsp; &nbsp; default =&gt; $default_cachedir,<br />&nbsp; &nbsp; &nbsp;} );<br /><br />&nbsp; &nbsp; $writer-&gt;end( &#39;select-channels&#39; );<br /><br />&nbsp; &nbsp; return $result;<br />}<br /><br />#<br /># Load a 
 configuration file in the old format.<br />#<br /><br />sub load_old_config<br />{<br />&nbsp; &nbsp; my( $config_file ) = @_;<br /><br />&nbsp; &nbsp; my @lines = XMLTV::Config_file::read_lines( $config_file );<br />&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; my $conf = {};<br />&nbsp; &nbsp; $conf-&gt;{cachedir}-&gt;[0] = $default_cachedir;<br />&nbsp; &nbsp; $conf-&gt;{&#39;root-url&#39;}-&gt;[0] = $default_root_url;<br />&nbsp; &nbsp; $conf-&gt;{channel} = [];<br /><br />&nbsp; &nbsp; foreach my $line (@lines)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; next unless defined $line;<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; my( $command, $param ) = split( /\s+/, $line, 2 );<br />&nbsp; &nbsp; &nbsp; &nbsp; $param =~ tr/\n\r//d;<br />&nbsp; &nbsp; &nbsp; &nbsp; $param =~ s/\s+$//;<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; if ( $command =~ /^\s*root-url\s*$/) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $conf-&gt;{&#39;root-url&#39;}-&gt;[0] = $param;<br />&nbsp; &nbsp; &n
 bsp; &nbsp; } elsif &nbsp;( $command =~ /^\s*channel\s*$/) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push @{$conf-&gt;{channel}}, $param;<br />&nbsp; &nbsp; &nbsp; &nbsp; } elsif ( $command eq &#39;cache-dir&#39; ) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $conf-&gt;{&#39;cachedir&#39;}-&gt;[0] = $param;<br />&nbsp; &nbsp; &nbsp; &nbsp; } else {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; die &quot;Unknown command $command in config-file $config_file&quot;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; return $conf;<br />}<br /><br />sub get_default_cachedir<br />{<br />&nbsp; &nbsp; my $winhome = $ENV{HOMEDRIVE} . $ENV{HOMEPATH}&nbsp;<br />&nbsp; &nbsp; if defined( $ENV{HOMEDRIVE} )&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; and defined( $ENV{HOMEPATH} );&nbsp;<br />&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; my $home = $ENV{HOME} || $winhome || &quot;.&quot;;<br />&nbsp; &nbsp; return &quot;$home/.xmltv/cache&quot;;<br />}<br /><br
  />sub init_cachedir<br />{<br />&nbsp; &nbsp; my( $path ) = @_;<br />&nbsp; &nbsp; if( not -d $path )<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; mkpath( $path ) or die &quot;Failed to create cache-directory $path: $@&quot;;<br />&nbsp; &nbsp; }<br />}<br /><br />sub load_channels<br />{<br />&nbsp; &nbsp; my( $url ) = @_;<br />&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; my %channels;<br /><br />&nbsp; &nbsp; my $xmldata = getuncompressed( $url );<br /><br />&nbsp; &nbsp; defined( $xmldata ) or die &quot;Failed to fetch $url&quot;;<br /><br />&nbsp; &nbsp; my $xml = XML::LibXML-&gt;new;<br />&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; my $doc = $xml-&gt;parse_string($xmldata);<br /><br />&nbsp; &nbsp; my $xmldecl = &quot;&lt;?xml version=&#39;&quot; . $doc-&gt;version() . &quot;&#39; &quot; .&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &quot;encoding=&#39;&quot; . $doc-&gt;encoding() . &quot;&#39;?&gt;\n&quot;;<br /><br />&nbsp; &nbsp; my $ns = $doc-&gt;find( &quot;//channel&quo
 t; );<br /><br />&nbsp; &nbsp; foreach my $node ($ns-&gt;get_nodelist)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; my $id = $node-&gt;findvalue( &#39;@id&#39; );<br />&nbsp; &nbsp; &nbsp; &nbsp; my $name = $node-&gt;findvalue( &#39;display-name[1]&#39; );<br />&nbsp; &nbsp; &nbsp; &nbsp; my $url = $node-&gt;findvalue( &#39;base-url&#39; );<br />&nbsp; &nbsp; &nbsp; &nbsp; my $urlns = $node-&gt;find( &#39;./base-url&#39; );<br />&nbsp; &nbsp; &nbsp; &nbsp; foreach my $urlnode ($urlns-&gt;get_nodelist)<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $node-&gt;removeChild( $urlnode );<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; $channels{$id} = [ $name, $url, $node-&gt;toString(0, 1) ];<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; return ($xmldecl, \%channels);<br />}<br /><br />sub print_data<br />{<br />&nbsp; &nbsp; my( $rooturl, $channel_id, $date ) = @_;<br />&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; my $url
  = $rooturl . $channel_id . &quot;_&quot; . UnixDate( $date, &quot;%Y-%m-%d&quot; ) .&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &quot;.xml.gz&quot;;<br /><br />&nbsp; &nbsp; my $xmldata = getuncompressed( $url );<br /><br />&nbsp; &nbsp; defined $xmldata or return 0;<br /><br />&nbsp; &nbsp; my $in = new IO::Scalar \$xmldata;<br />&nbsp; &nbsp; while( my $line = $in-&gt;getline() )<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; last if $line =~ /&lt;tv/;<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; while( my $line = $in-&gt;getline() )<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; last if $line =~ /&lt;\/tv&gt;/;<br />&nbsp; &nbsp; &nbsp; &nbsp; print $line;<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; return 1;<br />}<br /><br />sub write_header<br />{<br />&nbsp; &nbsp; my( $xmldecl ) = @_;<br /><br />&nbsp; &nbsp; # Use the same xml declaration as the one in<br />&nbsp; &nbsp; # channels.xml<br />&nbsp; &nbsp; print $xmldecl;<br />&nbsp; &nbsp; print &#39;&l
 t;!DOCTYPE tv SYSTEM &quot;xmltv.dtd&quot;&gt;&#39; . &quot;\n&quot;;<br />&nbsp; &nbsp; print &quot;&lt;tv&gt;\n&quot;;<br />}<br /><br />sub write_channel_list<br />{<br />&nbsp; &nbsp; my( $channel_list ) = @_;<br /><br />&nbsp; &nbsp; # Write list of channels.<br />&nbsp; &nbsp; t &#39;Writing list of channels.&#39;;<br /><br />&nbsp; &nbsp; foreach my $channel_id (@{$channel_list})<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; if( not exists $channels-&gt;{$channel_id} )<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print STDERR &quot;Unknown channel $channel_id.&quot; .<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot; See http://xmltv.tvtab.la/&quot; .&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot; for a list of available channels or run&quot; .&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot; tv_grab_la --configure to reconfigure.\n&quot;;<br />&nbsp; &nb
 sp; &nbsp; &nbsp; &nbsp; &nbsp; next;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; my( $channel_name, $url, $def ) = @{$channels-&gt;{$channel_id}};<br />&nbsp; &nbsp; &nbsp; &nbsp; print &quot; &nbsp;$def\n&quot;;<br />&nbsp; &nbsp; }<br />}<br /><br />sub write_footer<br />{<br />&nbsp; &nbsp; print &quot;&lt;/tv&gt;\n&quot;;<br />}<br /><br />sub getuncompressed {<br />&nbsp; &nbsp; my( $url ) = @_;<br /><br />&nbsp; &nbsp; my $response = $ua-&gt;get($url);<br /><br />&nbsp; &nbsp; return undef<br />&nbsp; &nbsp; &nbsp; &nbsp; unless $response-&gt;is_success;<br /><br />&nbsp; &nbsp; my $compressed = $response-&gt;content<br />&nbsp; &nbsp; &nbsp; &nbsp; or return undef;<br /><br />&nbsp; &nbsp; # Since LWP 5.827, the result from get() is already<br />&nbsp; &nbsp; # uncompressed.<br /><br />&nbsp; &nbsp; my $uncompressed;<br /><br />&nbsp; &nbsp; eval {<br />&nbsp;&nbsp; &nbsp;$uncompressed = Compress::Zlib::m
 emGunzip( \$compressed );<br />&nbsp; &nbsp; };<br /><br />&nbsp; &nbsp; $uncompressed = $compressed if not defined $uncompressed;<br /><br />&nbsp; &nbsp; 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 />&nbsp;