Hi, I have a working xmltv setup here. It required some hacking into the downloader code for Israel. First of all, you should use tvtime which has xmltv support. Second, you need the tv_grab_il script attached. Third, you'll need a cron job something like this (here I download twice per week):
20 6 * * 0,3 cp /home/alon/media/TV/listings.xml /home/alon/media/TV/listings.xml.old && /usr/local/bin/tv_grab_il | tv_sort > /home/alon/media/TV/listings.xml Fourth, you need to configure tvtime to use your XMLTV file and correctly modify the ~/.tvtime/stationlist.xml file with XMLTV ids (I'm attaching my file). Good luck! On Mon, 5 Feb 2007, Amichai Rotman wrote: > Hi all, > > I would like to set up Freevo on my Ubuntu 6.10 box and make use of the TV > guide feature. I understand it uses XMLTV to get the TV guide (like the EPG > on digital broadcast) but I don't know how to set it up. > > I tried to follow the instructions but it is very unfriendly and confusing. > > Any of you know of an existing guide / HOWTO or did it him/her self? > > Thanks! > > -- This message was sent by Alon Altman ([EMAIL PROTECTED]) ICQ:1366540 GPG public key at http://8ln.org/pubkey.txt Key fingerprint = A670 6C81 19D3 3773 3627 DE14 B44A 50A3 FE06 7F24 -------------------------------------------------------------------------- -=[ Random Fortune ]=- Any philosophy that can be put "in a nutshell" belongs there. -- Sydney J. Harris -- Attached file included as plaintext by Listar -- -- File: tv_grab_il #!/usr/bin/perl -w =pod =head1 NAME tv_grab_il - Grab TV listings for Israel. =head1 SYNOPSIS tv_grab_il --help tv_grab_il [--config-file FILE] --configure tv_grab_il [--config-file FILE] [--output FILE] [--days N] [--offset N] [--quiet] =head1 DESCRIPTION Outputs TV listings for channels available in Israel (free to air, cable and satellite). The data is obtained from parsing web pages from the Israeli portal walla (from tv.walla.co.il). First run B<tv_grab_il --configure> to decide which channels to download. There is a long list. You may want to select none when it asks you for which channels and manually edit the configuration file to uncomment the channels you wish to tape. Then run B<tv_grab_il> with no arguments to output the listing in XML format to the standard output. To view the hebrew, you will need to set your terminal to have a unicode font that supports hebrew. B<--configure> Prompt for which channels, and write the configuration file. B<--config-file FILE> Set the name of the configuration file, the default is B<~/.xmltv/tv_grab_il.conf>. This is the file written by B<--configure> and read when grabbing. B<--output FILE> write to FILE rather than standard output. B<--days N> grab N days. The default is 7 (there does not seem to be more information than this anyway on the server in general). B<--offset N> start N days in the future. The default is to start from today. B<--quiet> suppress the progress messages normally written to standard error. =head1 SEE ALSO L<xmltv(5)>. =head1 AUTHOR Written by Jason Friedman, [EMAIL PROTECTED] This program is based on tv_grab_sn, written by Stefan G:orling, [EMAIL PROTECTED] and maintained by Staffan Malmgren, [EMAIL PROTECTED] Patched by Alon Altman. Last updated: 5 February, 2007. =head1 BUGS The summer time routine uses the European summer time start and stop dates which are different to those used in Israel. The correct times can be found at http://www.greenwichmeantime.com/local/asia/il.htm?israel+jerusalem+tel_aviv =cut use strict; #binmode(STDOUT,":utf8"); #binmode(STDERR,":utf8"); use HTML::TreeBuilder; use Date::Manip; use Getopt::Long; use Locale::Hebrew; use Encode; use XMLTV; use XMLTV::Memoize; use XMLTV::Ask; use XMLTV::TZ qw(parse_local_date); use XMLTV::DST qw(utc_offset); use XMLTV::Config_file; use XMLTV::Get_nice; use XMLTV::Mode; use XMLTV::Usage <<END $0: get Israeli television listings in XMLTV format To configure: $0 --configure [--config-file FILE] To grab listings: $0 [--config-file FILE] [--output FILE] [--days N] [--offset N] [--quiet] END ; # Use Term::ProgressBar if installed. use constant Have_bar => eval { require Term::ProgressBar; 1 }; # Memoize some date parsing routines, if possible. FIXME move to # XMLTV::Memoize. # eval { require Memoize }; unless ($@) { foreach (qw(utc_offset ParseDate UnixDate dc fetch_data)) { Memoize::memoize($_) or warn "cannot memoize $_"; } } sub xhead(); sub configure(); sub get_channels(); sub fetch_data ($$); sub get_display_name ($); sub process_file( $$$$$ ); sub read_config_file( $ ); sub dc ( $$ ); sub reencode ( $ ); # The base timezone ("winter time") and "summer time" for Israel is # equivalent however the switchover dates are different (see BUGS) my $BASE_TZ = "EET"; my $PAGE_ENCODING = "Windows-1255"; my $DOMAIN = 'tv.walla.co.il'; XMLTV::Memoize::check_argv('XMLTV::Get_nice::get_nice_aux'); my ($opt_days, $opt_help, $opt_output, $opt_offset,$opt_configure, $opt_config_file, $opt_quiet); $XMLTV::Get_nice::Delay=1; $opt_days = 7; # default $opt_quiet = 0; # default $opt_offset = 0; #default GetOptions('days=i' => \$opt_days, 'offset=i' => \$opt_offset, 'help' => \$opt_help, 'configure' => \$opt_configure, 'config-file=s' => \$opt_config_file, 'output=s' => \$opt_output, 'quiet' => \$opt_quiet ) or usage(0); die 'number of days must not be negative' if (defined $opt_days && $opt_days < 0); usage(1) if $opt_help; my $mode = XMLTV::Mode::mode('grab', # default $opt_configure => 'configure', ); # MAIN ROUTINE my $now = dc(parse_local_date('now'),"$opt_offset days"); $now = substr($now,0,8); # Find the config file my $config_file = XMLTV::Config_file::filename($opt_config_file, 'tv_grab_il', $opt_quiet); if ($mode eq 'configure') { configure(); exit(); } my %w_args; if (defined $opt_output) { my $fh = new IO::File(">$opt_output"); $w_args{OUTPUT} = $fh; } $w_args{encoding} = 'utf-8'; # GRABBING DATA: my (%channels,$channel,@dates,$date,$i); %channels = read_config_file($config_file); my $writer = new XMLTV::Writer(%w_args); $writer->start(xhead); my @to_get; my $bar = new Term::ProgressBar('getting channel info', scalar keys %channels) if Have_bar && not $opt_quiet; foreach my $channel (keys %channels) { my $ch_xid = "$channel.$DOMAIN"; # fetch today's data to get the channel name # (Hopefully memoize should prevent the data being fetched twice) my $data = fetch_data(UnixDate($now,'%Y-%m-%d'),$channel); my $display_name = ($channel == 14 ? 'national geographic' : get_display_name($data)); $writer->write_channel({ id => $ch_xid, 'display-name' => [[ reencode($display_name),"he_IL.UTF8" ]] }); update $bar if Have_bar && not $opt_quiet; } my $day = $now; for (my $i = 0 ;$i < $opt_days; $i++) { if ($i > 0 ) { $day = dc($day, '+ 1 day'); } push @to_get, [ UnixDate($day,'%Y-%m-%d'), "$_.$DOMAIN", $_ , ($i==0)] #push @to_get, [ $day, "$_.$DOMAIN", $_ , ($i==0)] foreach keys %channels; } my $today = UnixDate($now, '%Y-%m-%d'); $bar = new Term::ProgressBar('getting listings', scalar @to_get) if Have_bar && not $opt_quiet; foreach (@to_get) { my ($day, $ch_xid, $ch_did,$isfirstday) = @$_; my $data = fetch_data($day,$ch_did); process_file($writer,$data,$day,$ch_xid,$isfirstday); update $bar if Have_bar && not $opt_quiet; } $writer->end(); exit(); ####################################################################### sub get_display_name ( $ ) { my($data) = @_; my $tree = HTML::TreeBuilder->new_from_content($data); my @first_list = $tree->look_down( '_tag','td', sub { (defined($_[0]->attr('class')) && $_[0]->attr('class') =~ /^w5b$/) } ); die "Cannot find channel name" if (scalar(@first_list)==0); my $channel_name = $first_list[0]->as_text; $channel_name =~ s/ *[^ ]* *//; $channel_name =~ s/^ *//; $channel_name =~ s/ *$//; $channel_name = Locale::Hebrew::hebrewflip($channel_name); return $channel_name; } ####################################################################### sub process_file( $$$$$ ) { my($writer,$data,$date,$channel) = @_; my @genrenames = ("family","movie","music","sport","news","latenight","youth"); # print "$data\n"; my $tree = HTML::TreeBuilder->new_from_content($data); my @show_details = $tree->look_down( '_tag','a', sub { $_[0]->attr('href') =~ /\?w=\/[0-9]+\/[0-9]+\/[0-9]{4}-[0-9][0-9]-[0-9][0-9]\/1$/ } ); my $detail; my (@starttimes, @endtimes, @prognames, @genres); foreach $detail (@show_details) { my $progname = $detail->as_text; my $starttime = $detail->parent->parent->content->[4]->content->[0]->as_text; my $genre_string = $detail->parent->parent->content->[3]->content->[0]->attr('src'); $genre_string =~ /genre\/(.*)\.gif/; push @starttimes, $starttime; # push @prognames, reencode(Locale::Hebrew::hebrewflip($progname)); push @prognames, reencode($progname); push @genres, $genrenames[$1-1]; } if (not @starttimes) { warn "nothing found for date $date, channel $channel\n"; return; } my ($i); my $prevhour=0; for $i (1 ... scalar @starttimes) { my $time=$starttimes[$i-1]; $time =~ /(\d+):\d+/o; my $hour= $1; if ($hour<$prevhour) { $date = UnixDate(dc($date, '+ 1 day'), '%Y-%m-%d'); } $prevhour=$hour; my (%program); $program{title} = [[$prognames[$i-1],"he_IL.UTF8"]]; $program{start} = utc_offset("$date $starttimes[$i-1]",$BASE_TZ); $program{channel} = $channel; $program{category} = [[$genres[$i-1], "en"]]; $writer->write_programme(\%program); } } ####################################################################### # fetch the web page # Parameters: # date # channel number (on web page) # directory for caching data sub fetch_data ( $$ ) { my($date,$channel) = @_; my $data; my $url = "http://$DOMAIN/?w=/$channel//$date/1"; my $shortdate = $date; $shortdate =~ s/-//g; $data = get_nice($url); if (not defined $data) { die "Could not download web page $url. Check internet settings\n"; } return $data; } ############################################################################## sub read_config_file( $ ) { my ($config_file) = @_; my (@config_lines,%channels,$ch_did);#,$ch_name); @config_lines = XMLTV::Config_file::read_lines($config_file); foreach (@config_lines) { # get rid of comments, space next if not defined; if (/^channel:?\s+(\d+)/) { $ch_did = $1; $channels{$ch_did} = 1; } elsif (/^$/) {; # ignore empty lines } else { warn "$config_file:$.: bad line\n"; } } die "No channels specified, run me with --configure\n" if not %channels; return %channels; } ############################################################################## # Wrapper for DateCalc(). sub dc( $$ ) { my $err; my $r = DateCalc(@_, \$err); die "DateCalc() failed with $err" if $err; die 'DateCalc() returned undef' if not defined $r; return $r; } ############################################################################## sub xhead() { return { 'source-info-url' => "http://$DOMAIN/", 'source-data-url' => "http://$DOMAIN", 'generator-info-name' => 'XMLTV', 'generator-info-url' => 'http://membled.com/work/apps/xmltv/', }; } ############################################################################# sub configure() { XMLTV::Config_file::check_no_overwrite($config_file); # FIXME commonize this configuration stuff within the XMLTV project. open(CONF, ">$config_file") or die "cannot write to $config_file: $!"; my $bar = new Term::ProgressBar('getting channel list', 1) if Have_bar && not $opt_quiet; my ($chsptr) = get_channels(); update $bar if Have_bar && not $opt_quiet; my @chs = @$chsptr; my @names = map {$_->{'display-name'}->[0]->[0] } @chs; #filteredchs; my @qs = map { "add channel $_?" } @names; my @want = ask_many_boolean(1, @qs); foreach (@chs) { my $w = shift @want; warn("cannot read input, stopping channel questions"), last if not defined $w; # No need to print to user - XMLTV::Ask is verbose enough. # Print a config line, but comment it out if channel not wanted. print CONF '#' if not $w; my $name = shift @names; print CONF "channel $_->{id}\n"; } close CONF or warn "cannot close $config_file: $!"; say "All done, run with no arguments to grab listings.\n"; } ############################################################################ # get the channels for Israel and their categories sub get_channels() { my ($channelspage,$location,@r); $location = "http://$DOMAIN/?w=/4"; $channelspage = get_nice($location); if (not defined $channelspage) { die "cannot get $channelspage"; } my $tree = HTML::TreeBuilder->new_from_content($channelspage); my @channel_list = $tree->look_down( '_tag','a', sub { $_[0]->attr('href') =~ /\?w=\/[0-9]*\/\/[0-9]{4}-[0-9][0-9]-[0-9][0-9]\/1$/ } ); my ($current_table,$channel_name,$channel_number,$channel_element,$channel_content,$channel_type); my (%types,%contents); foreach $channel_element (@channel_list) { # ignore links to images if (defined($channel_element->look_down('_tag','img'))) { next; }; $channel_content = $channel_element->as_text; $channel_name = $channel_element->as_text; $channel_element->starttag() =~ /w=\/([0-9]*)/; $channel_number = $1; push @r, {'display-name' => [[ $channel_name, "he_IL.UTF8"]], 'id' => $channel_number }; } # Now that we're done with it, we must destroy it. $tree = $tree->delete; return ([EMAIL PROTECTED]); } ############################################################################ # reencode a string sub reencode( $ ) { my ($thestring) = @_; return (encode_utf8(decode($PAGE_ENCODING,$thestring))); } -- Binary/unsupported file stripped by Listar -- -- Type: APPLICATION/xml -- File: stationlist.xml ================================================================= To unsubscribe, send mail to [EMAIL PROTECTED] with the word "unsubscribe" in the message body, e.g., run the command echo unsubscribe | mail [EMAIL PROTECTED]