root/trunk/references/Shepherd/Configure.pm @ 1168

Revision 1168, 38.6 kB (checked in by max, 5 years ago)

Attempt to fix HD issue with ABC & SBS... but I don't really know what I'm doing

Line 
1#!/usr/bin/perl -w
2
3package Shepherd::Configure;
4
5my $version = '0.10';
6
7use strict;
8no strict 'refs';
9
10use XMLTV;
11
12my %REGIONS = 
13    (
14        63 => "NSW: Broken Hill",       66 => "NSW: Central Coast",     67 => "NSW: Griffith",
15        69 => "NSW: Tamworth",  71 => "NSW: Wollongong",        73 => "NSW: Sydney",
16        74 => "NT: Darwin",     75 => "QLD: Brisbane",  78 => "QLD: Gold Coast",
17        79 => "QLD: Cairns",    81 => "SA: Adelaide",   82 => "SA: Renmark",
18        83 => "SA: Riverland",  85 => "SA: South East SA",      86 => "SA: Spencer Gulf",
19        88 => "TAS: Tasmania",  90 => "VIC: Ballarat",  93 => "VIC: Geelong",
20        94 => "VIC: Melbourne", 95 => "VIC: Mildura/Sunraysia", 98 => "VIC: Gippsland",
21        101 => "WA: Perth",     102 => "WA: Regional",  106 => "NSW: Remote and Central",
22        107 => "SA: Remote and Central",        108 => "NT: Remote and Central",        114 => "QLD: Remote and Central",
23        126 => "ACT: Canberra", 184 => "NSW: Newcastle",        253 => "QLD: Mackay",
24        254 => "QLD: Rockhampton",      255 => "QLD: Sunshine Coast",   256 => "QLD: Toowoomba",
25        257 => "QLD: Townsville",       258 => "QLD: Wide Bay", 259 => "NSW: Far South Coast",
26        261 => "NSW: Lismore/Coffs Harbour",    262 => "NSW: Orange/Dubbo",     263 => "NSW: Taree/Port Macquarie",
27        264 => "NSW: Wagga Wagga",      266 => "VIC: Bendigo",  267 => "VIC: Shepparton",
28        268 => "VIC: Albury/Wodonga"
29    );
30
31# -----------------------------------------
32# Subs: Configuration
33# -----------------------------------------
34
35sub configure
36{
37    if ($::opt->{configure} ne '1')
38    {
39        my $proggy = $::opt->{configure};
40        print "\nAttempting to configure \"$proggy\".\n";
41
42        unless ($::components->{$proggy})
43        {
44            print "Unknown component: \"$proggy\".\n";
45            exit 0;
46        }
47
48        my $progtype = $::components->{$proggy}->{type};
49        unless ($progtype eq 'grabber' or $progtype eq 'postprocessor'
50                or $progtype eq 'reconciler')
51        {
52            print "Cannot configure $progtype components.\n";
53            exit 0;
54        }
55
56        &::call_prog($proggy, query_filename($proggy, $progtype) . " ". query_config($proggy, 'option_config'));
57
58        exit 0;
59    }
60    print "\nConfiguring.\n\n" .
61          "Step 1: Region Selection\n\nSelect your region:\n";
62    foreach (sort { $REGIONS{$a} cmp $REGIONS{$b} } keys %REGIONS)
63    {
64        printf(" (%3d) %s\n", $_, $REGIONS{$_});
65    }
66    $::region = &XMLTV::Ask::ask_choice("Enter region code:", ($::region || "94"),
67                         keys %REGIONS);
68
69    print "\nStep 2: Channel Selection\n\n";
70
71    print "Shepherd offers two methods of channel selection: Guided and Advanced.\n".
72          "Guided is easier; Advanced allows manual entering of XMLTV IDs.\n\n";
73
74    my $guided = &XMLTV::Ask::ask_boolean("Would you like Guided channel selection?", 1);
75
76    my $mchans = &configure_channels_guided if ($guided);
77    &configure_channels_advanced unless ($mchans);
78
79    print "\nStep 3: Transitioning\n\n".
80          "Would you like to transition seamlessly from your current grabber?\n\n".
81          "Different data sources can have different names for the same show. For\n".
82          "example, one grabber might call a show \"Spicks & Specks\" while another\n".
83          "calls it \"Spicks and Specks\". These differences can make MythTV think\n".
84          "they're actually different shows.\n\n".
85          ucfirst($::progname) . " is able to merge these differences so that it always\n".
86          "presents shows with a consistent name, no matter where it actually sourced\n".
87          "show data from. If you'd like, it can also rename shows so they're consistent\n".
88          "with whichever grabber you've been using until now.\n\n".
89          "The advantage of this is that you should get a smoother transition to\n".
90          ucfirst($::progname) . ", with no shows changing names and no need to re-create\n".
91          "any recording rules. The main disadvantage is that if your previous grabber\n".
92          "used an inferior data source -- i.e. it sometimes has typos or less\n".
93          "informative program names -- then you'll continue to see these.\n\n".
94          "If you were using one of the following grabbers previously AND you want\n".
95          ucfirst($::progname) . " to use that grabber's program names, select it here.\n\n";
96
97    my $def = "Do not transition; just use best quality titles";
98    my %transition = (  "ltd (aka tv_grab_au, versions 1,30, 1.40 or 1.41)" => 'yahoo7widget',
99                        "OzTivo" => 'oztivo',
100                        "Rex" => 'rex');
101    my $defaulttrans = $def;
102    foreach my $key (keys %transition) {
103        $defaulttrans = $key if ((defined $::pref_title_source) && ($transition{$key} eq $::pref_title_source));
104    }
105    my $pref = &XMLTV::Ask::ask_choice("Transition from grabber?", $defaulttrans,
106                          $def, keys %transition);
107    $::pref_title_source = $transition{$pref};
108   
109    print "\n";
110    &::show_channels if (!$mchans);
111    &::show_mythtv_mappings($::debug, $mchans) if ($mchans);
112
113    my $str = "Create configuration file";
114    $str .= " and update MythTV" if ($mchans);
115    unless(&XMLTV::Ask::ask_boolean("\n$str?", 1))
116    {
117        print "Aborting configuration.\n";
118        exit 0;
119    }
120
121    &::write_config_file;
122    &::write_channels_file;
123    &update_mythtv_channels($mchans) if ($mchans);
124
125    print "\nMythTV Integration\n\n".
126          "If you run MythTV, Shepherd can register itself as the default grabber\n".
127          "and set your system to run it regularly to ensure up-to-date guide data.\n".
128          "This is generally easier than doing it yourself.\n\n";
129   
130    if (&XMLTV::Ask::ask_boolean("Would you like Shepherd to auto-configure MythTV?", 1))
131    {
132        &configure_mythtv;
133    }
134
135    print "Checking if any components require configuration.\n\n";
136    &::check;
137
138    print "Finished configuring.\n\n";
139
140    &::status;
141
142    print "\nShepherd is installed into $::CWD.\n\n";
143
144    if (&XMLTV::Ask::ask_boolean("\nShepherd can (optionally) install channel icons.\nDo you wish to do this now?")) {
145        &set_icons;
146    }
147
148    print "\nIf you wish to add/change channel icons in future, you can call Shepherd with:\n".
149          "    $::CWD/$::progname --set-icons\n\n";
150
151    print "Done.\n";
152    exit 0;
153}
154
155sub configure_channels_guided
156{
157    my $mythids = &::retrieve_mythtv_channels;
158    unless ($mythids)
159    {
160        print "\nUnable to retrieve list of MythTV channels.\n" .
161              "Guided channel selection is not available, now using Advanced.\n";
162        return undef;
163    }
164       
165    print "\n* Guided Channel Selection *\n";
166
167    print "\nHigh Definition TV (HDTV)\n".
168          "Most Australian TV networks broadcast at least some\n".
169          "programmes in HDTV each week, but for the most part\n".
170          "either upsample SD to HD or play a rolling demonstration\n".
171          "HD clip when they don't have the programme in HD format.\n\n".
172          "If you have a HDTV capable system and are interested in\n".
173          "having Shepherd's postprocessors populate HDTV content\n".
174          "then Shepherd will need to know the XMLTV IDs for the HD\n".
175          "channels also.  HD related SD channels are required.\n",
176          "The 7HD, Nine HD and TEN HD channels are populated\n",
177          "with programs from the first related SD channel.\n",
178          "$::wiki/FAQ#MyhighdefinitionHDchannelsaremissingprograms\n\n";
179    my $want_hdtv = &XMLTV::Ask::ask_boolean("Do you have High-Definition (HDTV)?");
180
181    my (@channellist, @hd_channellist, @paytv_channellist);
182
183    @channellist = sort &::read_official_channels($::region);
184    $::channels = { };
185    $::opt_channels = { };
186    foreach (@channellist)
187    {
188        $::channels->{$_} = undef;
189    }
190
191    if ($want_hdtv)
192    {
193        @hd_channellist = grep(!/ABC2|ABC1|SBS News|31/i, @channellist);
194
195        #limit to ones in $channels (don't know so can't) and if 7HD remove 7HD and first 7 (don't know so do anyway)
196        foreach my $hdchannel (keys %$::hd_to_sds) {
197                @hd_channellist = grep(!/^$hdchannel$/i, @hd_channellist);
198                my $oldlength = scalar @hd_channellist;
199                foreach my $sdchannel (@{$::hd_to_sds->{$hdchannel}}) {
200                        @hd_channellist = grep(!/^$sdchannel$/i, @hd_channellist);
201                        if ($oldlength != scalar @hd_channellist) { # removed first
202                                print "'$hdchannel' is going to be populated from '$sdchannel'\n";
203                                last;
204                        }
205                }
206        }
207
208        foreach (@hd_channellist)
209        {
210            $_.='HD';
211            $::opt_channels->{$_} = undef;
212        }
213    }
214
215    my $want_paytv = &XMLTV::Ask::ask_boolean("\nDo you have PayTV?");
216    if ($want_paytv)
217    {
218        $want_paytv = &XMLTV::Ask::ask_choice("Which PayTV provider do you have?", 
219                                 $::want_paytv_channels || "Foxtel", 
220                                 ("Foxtel", "SelecTV"));
221        $::want_paytv_channels = $want_paytv;
222        @paytv_channellist = &::read_official_channels($want_paytv);
223        foreach (@paytv_channellist)
224        {
225            $::opt_channels->{$_} = undef;
226        }
227    }
228    else
229    {
230        $::want_paytv_channels = undef;
231    }
232
233    my @sdchannels = (@channellist, @hd_channellist);
234    my @allchannels = (@sdchannels, @paytv_channellist);
235    my @paytvchannels = ((undef) x scalar(@sdchannels), (@paytv_channellist));
236
237    printf "\nYour MythTV has %d channels. Shepherd offers %d channels of guide\n".
238           "data for %s (%d free-to-air, %d HDTV, %d Pay-TV).\n\n".
239           "Please associate each MythTV channel with a Shepherd guide data\n".
240           "channel.\n\n",
241           scalar(keys %$mythids),
242           scalar(@allchannels),
243           $REGIONS{$::region},
244           scalar(@channellist), 
245           scalar(@hd_channellist), 
246           scalar(@paytv_channellist);
247   
248    my $display_mode = 0;
249    foreach my $ch (sort keys %$mythids)
250    {
251        my @table = $display_mode ? @paytvchannels : @sdchannels;
252        if ($want_paytv)
253        {
254            push @table, ($display_mode ? 'f:(Free to Air channel)' : 'p:(Pay TV channel)' );
255        }
256
257        &guided_configure_table(@table);
258
259        my $mch = $mythids->{$ch};
260        my $longname = $mch->{name};
261        $longname .= " ($mch->{callsign})" if ($mch->{callsign} and lc($mch->{callsign}) ne lc($longname));
262
263        my $channum = $mch->{channum} || '-';
264        printf "MythTV channel %s: %s ? ",
265               $channum,
266               $longname;
267        my $inp = <STDIN>;
268        chomp $inp;
269        if ($inp eq '?')
270        {
271            # TODO: &guided_configure_help;
272            redo;
273        }
274        elsif ($inp eq 'f')
275        {
276            $display_mode = 0;
277            redo;
278        }
279        elsif ($inp eq 'p')
280        {
281            $display_mode = 1;
282            redo;
283        }
284        elsif ($inp =~ /\d+/)
285        {
286            my $xmltvid = '';
287            if ($inp == 0)
288            {
289                print "$ch -> (no guide data)\n";
290            }
291            else
292            {
293                $inp--;
294                my $target = $allchannels[$inp];
295                unless ($target)
296                {
297                    print "Unknown #: $inp\n";
298                    redo;
299                }
300                $xmltvid = lc "$target.shepherd.au";
301                $xmltvid =~ s/ //g;
302                if ($inp < @channellist)
303                {
304                    $::channels->{$target} = $xmltvid;
305                }
306                else
307                {
308                    $::opt_channels->{$target} = $xmltvid;
309                }
310                print "$ch -> $allchannels[$inp].\n";
311            }
312            $mythids->{$ch}->{xmltvid} = $xmltvid;
313
314        }
315        else
316        {
317            print "Unknown selection. Please try again.\n";
318            redo;
319        }
320    }
321
322    foreach (keys %$::opt_channels)
323    {
324        if (defined $::opt_channels->{$_} && $_ =~ /HD$/) {
325            my $sd = $_;
326            $sd =~ s/HD$//;
327            if (!defined $::channels->{$sd}) {
328                print "No corresponding SD channel for a HD channel.  '$_' needs '$sd'.  Please try again.\n";
329                exit;
330            }
331        }
332    }
333
334    foreach (keys %$::channels)
335    {
336        delete $::channels->{$_} unless defined $::channels->{$_};
337    }
338    foreach (keys %$::opt_channels)
339    {
340        delete $::opt_channels->{$_} unless defined $::opt_channels->{$_};
341    }
342
343    &::show_mythtv_mappings($::debug, $mythids);
344
345    print "\nIf you proceed to the end of configuration, Shepherd will\n" .
346          "write these channel mappings to MythTV.\n\n";
347
348    exit unless (&XMLTV::Ask::ask_boolean("Is this table correct? ", 1));
349
350    return $mythids;
351}
352
353sub guided_configure_table
354{
355    my @chs;
356    my $skip = 0;
357    foreach (@_)
358    {
359        if (defined $_)
360        {
361            push @chs, $_;
362        }
363        else
364        {
365            $skip++;
366        }
367    }
368
369    @chs = ('(no guide)', @chs);
370
371    my $half = int(scalar(@chs) / 2);
372    $half++ if (scalar(@chs) % 2);
373   
374    my $i = 0;
375    my $n;
376    my $str = '';
377    while ($i < $half)
378    {
379        $n = $i;
380        $n += $skip if ($n);
381        my $selection = &guided_configure_table_entry($chs[$i], $n);
382        $selection .= &guided_configure_table_entry($chs[$i+$half], $n+$half) if ($i + $half < @chs);
383        $str .= "$selection\n";
384        $i++;
385    }
386    print "Guide data sources:\n$str";
387}
388
389sub guided_configure_table_entry
390{
391    my ($entry, $num) = @_;
392    if ($entry =~ /^(\w):(.*)/)
393    {
394        $num = $1;
395        $entry = $2;
396    }
397    return sprintf "(%2s) %-30s", $num, $entry;
398}
399
400sub configure_channels_advanced
401{
402    my @channellist = &::read_official_channels($::region);
403   
404    $::channels = channel_selection("Free to Air", ".free.au", $::channels, @channellist);
405    &::check_channel_xmltvids;
406
407    my $old_opt_channels = $::opt_channels;
408    print "\nHigh Definition TV (HDTV)\n".
409          "Most Australian TV networks broadcast at least some\n".
410          "programmes in HDTV each week, but for the most part\n".
411          "either upsample SD to HD or play a rolling demonstration\n".
412          "HD clip when they don't have the programme in HD format.\n\n".
413          "If you have a HDTV capable system and are interested in\n".
414          "having Shepherd's postprocessors populate HDTV content\n".
415          "then Shepherd will need to know the XMLTV IDs for the HD\n".
416          "channels also.  HD related SD channels are required.\n",
417          "The 7HD, Nine HD and TEN HD channels are populated\n",
418          "with programs from the first related SD channel.\n",
419          "$::wiki/FAQ#MyhighdefinitionHDchannelsaremissingprograms\n";
420    if (&XMLTV::Ask::ask_boolean("\nDo you wish to include HDTV channels?")) 
421    {
422        #limit to ones in $channels and if 7HD remove 7HD and first 7
423        my @hd_channellist = grep(!/ABC2|SBS News|31/i, keys %$::channels);
424
425        foreach my $hdchannel (keys %$::hd_to_sds) {
426                my $oldlength = scalar @hd_channellist;
427                @hd_channellist = grep(!/^$hdchannel$/i, @hd_channellist);
428                next if ($oldlength == scalar @hd_channellist); # didn't remove
429                $oldlength = scalar @hd_channellist;
430                foreach my $sdchannel (@{$::hd_to_sds->{$hdchannel}}) {
431                        @hd_channellist = grep(!/^$sdchannel$/i, @hd_channellist);
432                        if ($oldlength != scalar @hd_channellist) { # removed first
433                                print "'$hdchannel' is going to be populated from '$sdchannel'\n";
434                                last;
435                        }
436                }
437        }
438
439        foreach (@hd_channellist)
440        {
441            $_ .= "HD";
442        }
443
444        $::opt_channels = channel_selection("HDTV", ".hd.free.au", $old_opt_channels, @hd_channellist);
445        &::check_channel_xmltvids;
446    }
447    else
448    {
449        $::opt_channels = { };
450    }
451
452    if (&XMLTV::Ask::ask_boolean("\nDo you wish to include PayTV (e.g. Foxtel, SelecTV) channels?", defined $::want_paytv_channels))
453    {
454        $::want_paytv_channels = &XMLTV::Ask::ask_choice("Which PayTV provider?", $::want_paytv_channels || "Foxtel", ("Foxtel", "SelecTV"));
455        my @paytv_channellist = &::read_official_channels($::want_paytv_channels);
456        my $paytv = channel_selection("Pay TV", ".paytv.au", $old_opt_channels, @paytv_channellist);
457        if (keys %$paytv) {
458            $::opt_channels = { %$::opt_channels, %$paytv };
459        } else {
460            $::want_paytv_channels = undef;
461        }
462        &::check_channel_xmltvids;
463    }
464    else
465    {
466        $::want_paytv_channels = undef;
467    }
468}
469
470# Sourced from YourTV
471sub fetch_regions
472{
473    my ($reg, $shh) = @_;
474
475    &::log("Fetching free-to-air region information...\n") unless ($shh);
476
477    # Download list
478    my $ua = LWP::UserAgent->new();
479    $ua->env_proxy;
480    $ua->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322');
481    $ua->cookie_jar({});
482    $ua->get('http://www.yourtv.com.au');
483    my $response = $ua->get('http://www.yourtv.com.au/?');
484
485    my $page = $response->content;
486    die "Unable to download region list page" if ($response->is_error());
487
488    die "Unable to parse region list" if (!($page =~ /<select[^>]*fta_region_id[^>]*>(.*?)<\/select>/is));
489    my $regions = $1;
490
491    my %regions;
492    while ($regions =~ /value.*?(\d+).*?>(.*?)(<|$)/sg) {
493        my ($num, $name) = ($1, $2);
494        $name =~ s/^\s+//s;
495        $name =~ s/\s+$//s;
496        $name =~ s/\s+/ /gs;
497        $name =~ s/ -/:/;
498
499        $regions{$num} = $name;
500        #printf "Downloaded %d %s\n", $num, $name;
501    }
502
503    my %REGIONSLOCAL = %REGIONS;
504    my %regionslocal = %regions;
505    foreach my $num (keys %regionslocal) {
506        #printf "Checking %d %s\n", $num, $regions{$num};
507        if (!defined($REGIONSLOCAL{$num}) || $REGIONS{$num} ne $regions{$num}) {
508                #printf "Missing %d %s\n", $num, $regions{$num};
509        } else {
510                delete $REGIONSLOCAL{$num};
511                delete $regionslocal{$num};
512        }
513    }
514
515    if ((scalar(keys %REGIONSLOCAL) != 0) || (scalar(keys %regionslocal) != 0)) {
516        print "old regions not matched:\n";
517        foreach (sort { $REGIONSLOCAL{$a} cmp $REGIONSLOCAL{$b} } keys %REGIONSLOCAL) {
518                printf(" %3d %s\n", $_, $REGIONSLOCAL{$_});
519        }
520        print "new regions not matched:\n";
521        foreach (sort { $regionslocal{$a} cmp $regionslocal{$b} } keys %regionslocal) {
522                printf(" %3d %s\n", $_, $regionslocal{$_});
523        }
524        print "new region list:\n";
525        my $count = 0;
526        print "\tmy %REGIONS = (";
527        foreach (sort { $a <=> $b } keys %regions) {
528                if ($count%3 == 0) {
529                        print"\n\t\t";
530                } else {
531                        print"\t";
532                }
533                printf('%d => "%s",', $_, $regions{$_});
534                $count+=1;
535        }
536        print ");\n";
537    }
538}
539
540# Sourced from YourTV
541sub fetch_channels
542{
543    my ($reg, $shh) = @_;
544
545    &::log("Fetching free-to-air channel information...\n") unless ($shh);
546
547    # Download list
548    my $ua = LWP::UserAgent->new();
549    $ua->env_proxy;
550    $ua->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322');
551    $ua->cookie_jar({});
552    $ua->get('http://www.yourtv.com.au');
553    my $response = $ua->get('http://www.yourtv.com.au/profile/ajax.cfm?action=channels&region_id='.$reg);
554
555    my $page = $response->content;
556    die "Unable to download channel list" if ($response->is_error());
557
558    # Rules for Station Names:
559    # Station names are comprised of the channel name (eg "Seven") and an
560    # optional regional qualifier in brackets (eg "(Cairns/Rockhampton)").
561    # Station names shall not contain a regional qualifer unless
562    # necessary to distinguish between identical channel names in
563    # the same region; in this case, a regional qualifier shall always
564    # be included. In the absence of anything better, the region name
565    # (eg "NSW: Regional NSW") is used as the regional qualifier.
566    my (@channellist, $clist, $cn, $rq);
567    while ($page =~ /<label for="venue_id.*?>(.*?)<\/label>/sg)
568    {
569        my $channel = $1;
570        $channel =~ s/\s{2,}//g;
571        if ($channel =~ /(.*) (\(.*\))/)
572        {
573            ($cn, $rq) = ($1, $2);
574        }
575        else
576        {
577            $cn = $channel;
578            $rq = '';
579        }
580        # Is there already a channel with this name?
581        if ($clist->{$cn})
582        {
583            # Set regional qualifier for existing station if not already set
584            if (@{$clist->{$cn}} == 1 and $clist->{$cn}[0] eq '')
585            {
586                $clist->{$cn} = [ "(".$REGIONS{$reg}.")" ];
587            }
588            $rq = $REGIONS{$reg} if ($rq eq '');
589            die "Bad channel list in region $reg!" if (grep($rq eq $_, @{$clist->{$cn}}));
590            push @{$clist->{$cn}}, $rq; 
591        }
592        else
593        {
594            $clist->{$cn} = [ $rq ];
595        }
596    }
597    foreach $cn (keys %$clist)
598    {
599        if (@{$clist->{$cn}} == 1)
600        {
601            push @channellist, $cn;
602        }
603        else
604        {
605            foreach $rq (@{$clist->{$cn}})
606            {
607                push @channellist, "$cn $rq";
608            }
609        }
610    }
611    return @channellist;
612}
613
614sub fetch_channels_foxtel
615{
616    my $shh = shift;
617    &::log("Fetching PayTV channel information...\n") unless ($shh);
618
619    my $ua = LWP::UserAgent->new();
620    $ua->env_proxy;
621    $ua->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322');
622    $ua->cookie_jar({});
623    my $response = $ua->get('http://www.foxtel.com.au/channel/lineup.html');
624
625    my $page = $response->content;
626    die "Unable to download channel list" if ($response->is_error());
627
628    my @channellist;
629    while ($page =~ /<option value="\/channel\/.*?>(.*?)<\/option>/sg)
630    {
631        my $ch = $1;
632        $ch =~ s/[ \t()\[\]\+\.\-]//g;  # remove special chars
633        $ch =~ s/(&amp;|&)/and/g;       # &amp; to and
634        $ch =~ s|[/,].*||;              # and deleting after / or ,
635
636        push @channellist,$ch;
637    }
638
639    return @channellist;
640}
641
642sub fetch_channels_selectv
643{
644    my $shh = shift;
645    &::log("Fetching PayTV channel information...\n") unless ($shh);
646
647    my $ua = LWP::UserAgent->new();
648    $ua->env_proxy;
649    $ua->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322');
650    $ua->cookie_jar({});
651    my $response = $ua->get('http://www.selectv.com/go/tv-guide');
652
653    my $page = $response->content;
654    die "Unable to download channel list" if ($response->is_error());
655
656    my @channellist;
657    while ($page =~ /<option value=".*?">(.*?)<\/option>/sg)
658    {
659        my $ch = $1;
660        $ch =~ s/[ \t()\[\]\+\.\-]//g;  # remove special chars
661        $ch =~ s/(&amp;|&)/and/g;       # &amp; to and
662        $ch =~ s|[/,].*||;              # and deleting after / or ,
663
664        # also in selectv_website
665        my %SelecTV_to_Foxtel = (
666                "AnimalPlanet" => "AnimalPlanet",
667                "AntennaGreek" => "AntennaGreek",               # SelecTV only
668                "BBCWorld" => "BBCWorldNews",
669                "CartoonNetwork" => "CartoonNetwork",
670                "CNNI" => "CNN",                                # rename
671                "DiscoveryScience" => "DiscoveryScience",
672                "DiscoveryHomeandHealth" => "DiscoveryHealth",  # rename
673                "DiscoveryTravelandLiving" => "DiscoveryTravel",# rename
674                "DiscoveryRealTime" => "DiscoveryRealTime",     # SelecTV and OzTivo
675                "E!Entertainment" => "E!Entertainment",
676                "ERTGreek" => "ERTGreek",                       # SelecTV only
677                "Eurosport" => "Eurosport",                     # SelecTV and OzTivo
678                "FashionTV" => "FashionTV",
679                "MovieExtra" => "MOVIEEXTRA",                   # rename
680                "MovieGreats" => "MOVIEGREATS",                 # rename
681                "MovieOne" => "MOVIEONE",                       # rename
682                "MovieTwo" => "MOVIETWO",                       # rename
683                "MTV" => "MTV",
684                "NatGeoAdventure" => "NatGeoAdventure",
685                "NationalGeographic" => "NationalGeographic",
686                "Ovation" => "Ovation",
687                "SkyRacing" => "SkyRacing",
688                "TurnerClassicMovies" => "TCM",                 # rename
689                "TVChileSpanish" => "TVChileSpanish",           # SelecTV and OzTivo
690                "TVE" => "TVE",                                 # SelecTV and OzTivo
691                "VH1" => "VH1",
692        );
693        print " Unknown channel: $ch\n" if !exists($SelecTV_to_Foxtel{$ch});
694        $ch = $SelecTV_to_Foxtel{$ch} if $SelecTV_to_Foxtel{$ch};
695
696        push @channellist,$ch;
697    }
698
699    return @channellist;
700}
701
702# Channel Selection (advanced/manual entering of XMLTV IDs)
703#
704# We try to help users match XMLTV IDs to their MythTV installation.
705# We also try to make all the defaults match what they selected last
706# time, if they're re-running configure.
707sub channel_selection
708{
709    my ($type, $default_tail, $old_channels, @channellist) = @_;
710
711    my $mythids = &::retrieve_mythtv_channels;
712
713    print "\nYour region has " . scalar(@channellist) . " $type channels:\n " .
714          join(', ', @channellist) . ".\n\n";
715
716    my $newchannels = {};
717    my $line;
718    my $c = 1;
719    print "\nEach channel you want guide data for needs a unique XMLTV ID. You can type\n".
720          "in an ID of your choice, or press ENTER to accept the suggested [default],\n".
721          "or type in \"n\" to skip this channel.\n\n".
722          "Please don't subscribe to unneeded channels.\n\n".
723          "$type Channels:\n";
724    foreach my $ch (@channellist)
725    {
726        my $default;
727        my $status = "new";
728
729        # Ideally, keep what they assigned last time.
730        if ($old_channels->{$ch})
731        {
732            $status = "previously configured";
733            $default = $old_channels->{$ch};
734        }
735        # If it looks like a channel in MythTV, suggest that.
736        elsif ($mythids->{$ch})
737        {
738            $default = $mythids->{$ch}->{xmltvid};
739        }
740        # Otherwise make up a name
741        else
742        {
743            $default = lc($ch);          # make a default id by lower-casing
744            $default =~ s/[ \t()]//g;   # removing whitespace and parens
745            $default =~ s|[/,].*||;     # and deleting after / or ,
746            $default .= $default_tail;  # and tack on something like ".free.au".
747        }
748
749        printf "(%2d/%2d) \"%s\" (%s)\n", $c, scalar(@channellist), $ch, $status;
750
751        # Notify user if we found a matching MythTV channel
752        if ($mythids->{$ch})
753        {
754            my $channum = $mythids->{$ch}->{channum} || '-';
755            printf "        Looks like MythTV channel #%s: \"%s\" (%s)\n",
756                   $channum,
757                   $mythids->{$ch}->{name},
758                   $mythids->{$ch}->{callsign};
759            if ($default ne $mythids->{$ch}->{xmltvid})
760            {
761                printf "        Current ID is \"%s\" but MythTV Ch #%s is \"%s\"\n",
762                    $default, $channum, $mythids->{$ch}->{xmltvid};
763            }
764        }
765
766        # Don't subscribe by default when user has configured previously
767        # and ignored this channel, or if it's a FTA Channel 31 variant.
768        if (($status eq 'new' and keys %$old_channels)
769                or
770            ($type eq 'Free to Air' and $ch =~ /31/))
771        {       
772            print "        If subscribing, suggest \"$default\".\n";
773            $default = "";
774        }
775
776        $line = &XMLTV::Ask::ask("        [$default] ? ");
777        $line =~ s/\s//g;
778
779        # Some users think they can enter 'y' to accept default
780        if (lc($line) eq 'y' or lc($line) eq 'yes')
781        {
782            if ($default)
783            {
784                $newchannels->{$ch} = $default;
785            }
786            else
787            {
788                print "No default value: please enter an XMLTV ID of your choice.\n";
789                redo;
790            }
791        }
792        elsif ($line ne 'n' and ($line =~ /\w/ or $default))
793        {
794            $newchannels->{$ch} = $line || $default;
795        }
796
797        # Check XMLTV ID is unique
798        foreach (keys %$newchannels)
799        {
800            next if ($_ eq $ch);
801            if ($newchannels->{$_} and $newchannels->{$ch} and $newchannels->{$_} eq $newchannels->{$ch})
802            {
803                print "ERROR: You have entered identical XMLTV IDs for $ch and $_ (\"$newchannels->{$_}\"). Exiting.\n";
804                exit;
805            }
806        }
807        $c++;
808    }
809    printf "\nYou are subscribing to %d %s channels:\n",
810           scalar(keys %$newchannels), $type;
811    print "* $_ -> $newchannels->{$_}\n" for sort keys %$newchannels;
812
813    my @not = grep (!$newchannels->{$_}, @channellist);
814    printf "\nYou are not subscribing to %d other channel%s: %s.\n",
815           scalar(@not), (@not > 1 ? 's' :''), join(', ', @not)
816           if (@not);
817   return $newchannels;
818}
819
820sub update_mythtv_channels
821{
822    my $mchans = shift;
823    eval
824    {
825        use lib 'references';
826        require Shepherd::MythTV;
827
828        my $dbh = &Shepherd::MythTV::open_connection;
829        exit unless ($dbh);
830        my $sth = $dbh->prepare("UPDATE channel SET xmltvid = ? WHERE name = ? AND channum = ? ");
831        foreach (keys %$mchans)
832        {
833            my $mch = $mchans->{$_};
834            $sth->execute($mch->{xmltvid}, $mch->{name}, $mch->{channum});
835        }
836        &Shepherd::MythTV::close_connection;
837        &::log("Successfully updated MythTV channels.\n");
838    };
839    if ($@)
840    {
841        &::log("Error trying to access MythTV database: $@\n");
842        return undef;
843    }
844}
845
846# ------------------------------
847# -   List Channel Names       -
848# ------------------------------
849#
850# This does a web lookup rather than reading the official
851# channels_list reference.
852sub list_chan_names
853{
854    printf "Select your region:\n";
855    printf(" (%3d) %s\n", 0, 'All regions (including PayTV and does regions check)');
856
857    foreach (sort { $REGIONS{$a} cmp $REGIONS{$b} } keys %REGIONS) {
858        printf(" (%3d) %s\n", $_, $REGIONS{$_});
859    }
860    my $reg = &XMLTV::Ask::ask_choice("Enter region code:", ($::region || "94"),
861                         '0', keys %REGIONS);
862
863    if (!$reg)
864    {
865        &fetch_regions;
866
867        print "\nListing channels for all regions:\n";
868
869        my @rchans = &fetch_channels_foxtel;
870        printf "\nFoxtel:%s\n", join (',', @rchans);
871        list_chan_names_diff("Foxtel", @rchans);
872        print "\n Use to update channel_list and foxtel_swf.conf (remove ACC from foxtel_swf.conf and check mapping to foxtel in oztivo)\n";
873        print " Remove from above Channel7Adelaide,Channel7Brisbane,Channel7Melbourne,Channel7Perth,Channel7Sydney\n\n";
874
875        @rchans = &fetch_channels_selectv;
876        printf "\nSelecTV:%s\n", join (',', @rchans);
877        list_chan_names_diff("SelecTV", @rchans);
878        print "\n Use to update channel_list and selectv_website.conf (check mapping to foxtel in shepherd and selectv_website, and check oztivo mapping)\n\n";
879
880        my $channel_support_exceptions = '';
881        foreach my $id (sort { scalar($a) <=> scalar($b) } keys %REGIONS)
882        {
883            my @rchans = fetch_channels($id, 1);
884            printf "%s:%s\n", $id, join(',', @rchans);
885            my $cse = list_chan_names_diff($id, @rchans);
886            $channel_support_exceptions = "$channel_support_exceptions $cse"
887                    if $cse;
888            sleep 1;
889        }
890
891        print "\n\'channel_support_exceptions\' => \'$channel_support_exceptions\',\n";
892
893        return;
894    }
895
896    printf "\nChannels for region %d (%s) are as follows:\n\t%s\n\n",
897                $reg, $REGIONS{$reg}, join("\n\t",fetch_channels($reg));
898}
899
900sub list_chan_names_diff
901{
902    my $id = shift;
903    my @rchans = @_;
904
905    my @ochans = &::read_official_channels($id);
906    my $line = '';
907    my $channel_support_exceptions = '';
908
909    my $count = scalar(@rchans);
910    foreach my $chan (@ochans) {
911        @rchans = grep($chan ne $_, @rchans);
912        if ($count == scalar(@rchans)) { # didn't find
913            $line = "$line-$chan,";
914            $chan =~ s/ /_/g;
915            if ($channel_support_exceptions) {
916                $channel_support_exceptions = "$channel_support_exceptions,$chan";
917            } else {
918                $channel_support_exceptions = "$chan";
919            }
920        } else {
921            $count = scalar(@rchans);
922        }
923    }
924    foreach my $chan (@rchans) { # didn't remove
925        $line = "$line+$chan,";
926    }
927    if ($line) {
928        print " difference: $line\n";
929    }
930
931    $channel_support_exceptions = "$id:-$channel_support_exceptions"
932            if $channel_support_exceptions;
933
934    return $channel_support_exceptions;
935}
936
937# ------------------------------
938# -   MythTV Integration       -
939# ------------------------------
940#
941#
942
943sub configure_mythtv
944{
945    &::log("\nConfiguring MythTV...\n\n" .
946           "This will:\n".
947           "1. Create a symbolic link to Shepherd from tv_grab_au\n".
948           "2. Register Shepherd with MythTV as the default grabber\n".
949           "3. Turn off MythTV-driven scheduling of guide data updates\n".
950           "4. Create a cron job to periodically run Shepherd.\n\n");
951
952    # Check existence of symlink
953
954    my $me = "$::CWD/applications/shepherd/shepherd";
955
956    &::log("Setting up symlink...\n");
957
958    my $mapped = 0;
959    my $symlink;
960    my @delete_me;
961    foreach my $path (split/:/, $ENV{PATH})
962    {
963        my $tv_grab_au = "$path/tv_grab_au";
964
965        # Figure out an appropriate symlink.
966        # (We'll use /usr/bin/tv_grab_au, but only if
967        # /usr/bin/ is in PATH.)
968        $symlink = $tv_grab_au unless ($symlink && $symlink eq '/usr/bin/tv_grab_au');
969
970        if (-e $tv_grab_au)
971        {
972            if (-l $tv_grab_au)
973            {
974                my $link = readlink($tv_grab_au);
975                if ($link and $link eq $me)
976                {
977                    &::log("Symlink $tv_grab_au is correctly mapped to $me.\n");
978                    $mapped = $tv_grab_au;
979                    last;
980                }
981            }
982            push @delete_me, $tv_grab_au;
983        }
984    }
985
986    &::log("\n");
987
988    if (!$mapped or @delete_me)
989    {
990        if (@delete_me)
991        {
992            &::log("\nShepherd would like to DELETE the following file(s):\n\n");
993            system ("ls -l --color @delete_me");
994            &::log("\n");
995        }
996        if (!$mapped)
997        {
998            &::log("Shepherd would like to CREATE the following symlink:\n\n".
999                " $symlink -> $me\n\n");
1000        }
1001
1002        my $response = &XMLTV::Ask::ask_boolean(
1003            ucfirst(
1004                ($mapped ? '' : ( 'create symlink ' . (@delete_me ? 'and ' : ''))) .
1005                (@delete_me ? 'delete ' . scalar(@delete_me) . ' file(s)' : '')) .
1006            '?', 1);
1007        unless ($response)
1008        {
1009            &::log("Aborting.\n");
1010            return;
1011        }
1012
1013        system("sudo rm @delete_me") if (@delete_me);
1014        system("sudo ln -s $me $symlink") unless ($mapped);
1015    }
1016
1017    &::log("Symlink established:\n");
1018    system("ls -l --color `which tv_grab_au`");
1019    &::log("\n");
1020
1021    # 2. Insert 'tv_grab_au' into mythconverg -> videosource
1022
1023    &::log("Registering Shepherd as tv_grab_au with MythTV.\n\n");
1024
1025    # No eval because I want to bomb out if this fails:
1026    # no point creating cron jobs if they won't work.
1027    use lib 'references';
1028    require Shepherd::MythTV;
1029
1030    my $dbh = &Shepherd::MythTV::open_connection();
1031    return unless ($dbh);
1032    $dbh->do("UPDATE videosource SET xmltvgrabber='tv_grab_au'") 
1033        || die "Error updating MythTV database: ".$dbh->errstr;
1034
1035    &::log("Ok. Turning off MythTV-scheduled guide data updates...\n");
1036    $dbh->do("UPDATE settings SET data='0' WHERE value='MythFillEnabled'")
1037        || &::log("Warning: Unable to check/update MythFillEnabled setting: ".$dbh->errstr.".\n");
1038
1039    &Shepherd::MythTV::close_connection;
1040
1041    &::log("MythTV database updated.\n\n");
1042
1043    # 3. Create cron job
1044
1045    &::log("Creating cron job...\n\n");
1046    my $oldcronfile = "$::CWD/cron.bak";
1047
1048    my $cmd = "crontab -l > $oldcronfile";
1049
1050    # Response codes: 0==success, 1==empty cron, other==failure
1051    my $response = (system($cmd) >> 8);
1052    my $no_permission = 1 if ($response > 1);
1053
1054    # Some systems (Gentoo) only allow root to run crontab
1055    if ($no_permission)
1056    {
1057        &::log("Error code $response from crontab command; trying again with root permission...\n");
1058        $cmd = "sudo crontab -u `whoami` -l > $oldcronfile";
1059        $response = (system($cmd) >> 8);
1060        if ($response > 1)
1061        {
1062            &::log("Error code $response from crontab. Aborting.\n");
1063            return;
1064        }
1065        &::log("OK: seemed to work.\n\n");
1066    }
1067
1068    my $newcron = '';
1069    my $oldcron = '';
1070    if (open (OLDCRON, $oldcronfile))
1071    {
1072        while (my $line = <OLDCRON>)
1073        {
1074            $oldcron .= $line;
1075            $newcron .= $line unless ($line =~ /mythfilldatabase/);
1076        }
1077        close OLDCRON;
1078    }
1079
1080    my $minute = ((localtime)[1] + 2) % 60;
1081    my $job = "$minute * * * * nice mythfilldatabase --graboptions '--daily'\n";
1082
1083    $newcron .= $job;
1084
1085    my $newcronfile = "$::CWD/cron.new";
1086    open (NEWCRON, ">$newcronfile")
1087        or die "Unable to open $newcronfile: $!";
1088    print NEWCRON $newcron;
1089    close NEWCRON;
1090
1091    if ($response)
1092    {
1093        &::log("Shepherd believes you currently have no crontab, and would\n".
1094            "like to set your crontab to:\n");
1095    }
1096    else
1097    {
1098        &::log("Shepherd would like to replace this:\n\n$oldcron\n" .
1099            "... with this:\n");
1100    }
1101    &::log("\n$newcron\n");
1102    unless (&XMLTV::Ask::ask_boolean("Set your crontab as displayed above?", 1))
1103    {
1104        &::log("Aborting.\n");
1105        return;
1106    }
1107
1108    $cmd = "crontab $newcronfile";
1109    $cmd = "sudo $cmd -u `whoami`" if ($no_permission);
1110    system($cmd) and &::log("Failed?\n");
1111
1112    &::log("Done.\n");
1113
1114    if (&XMLTV::Ask::ask_boolean("Would you like to see your symlink " .
1115            "and cron job?", 1))
1116    {
1117        my $cmd = "ls -l --color `which tv_grab_au`";
1118        &::log("\n" . '$ ' . $cmd . "\n");
1119        system($cmd);
1120
1121        $cmd = "crontab -l";
1122        $cmd = "sudo $cmd -u `whoami`" if ($no_permission);
1123        &::log("\n" . '$ ' . $cmd . "\n");
1124        system($cmd);
1125    }
1126
1127    &::log("\nSuccessfully configured MythTV.\n\n".
1128           "Your system will run mythfilldatabase on the $minute" . 
1129           "th minute of every hour,\n" .
1130           "which will trigger Shepherd (as tv_grab_au) with the --daily option.\n");
1131}
1132
1133
1134# ------------------------------
1135# -   Icons                    -
1136# ------------------------------
1137
1138sub set_icons
1139{
1140    print "\n\nPopulating Channel Icons.\n\n";
1141
1142    eval
1143    {
1144        use lib 'references';
1145        require Shepherd::MythTV;
1146
1147        my $dbh = &Shepherd::MythTV::open_connection;
1148        exit unless ($dbh);
1149
1150        -d "$::CWD/icons" or mkdir "$::CWD/icons" or die "Cannot create directory $::CWD/icons: $!";
1151
1152        # fetch icon styles
1153        print "Contacted database.\n\nFetching icon styles ... ";
1154        my $icon_styles = &::fetch_file('http://www.whuffy.com/shepherd/logo_list.txt');
1155        exit 1 unless ($icon_styles);
1156
1157        print "Done\n\n".
1158              "There are (typically) multiple themes available for each channel.\n".
1159              "For each channel you will be asked which theme graphic you'd like for\n".
1160              "each channel icon\n".
1161              "Aesthetically, you probably want all channel graphics sourced from a single\n".
1162              "theme, but you can choose individual graphics for each if you choose.\n\n".
1163              "The following themes are available. Please browse the URL of each theme\n".
1164              "to see if you like the general style:\n\n".
1165              " Theme Name       Theme Description              Theme Preview URL\n".
1166              " ---------------- ------------------------------ ------------------------------\n";
1167
1168        my $t;
1169
1170        foreach my $line (split/\n/,$icon_styles) {
1171            if ($line =~ /^THEME\t(.*)\t(.*)\t(.*)$/) {
1172                my ($theme_name, $theme_desc, $theme_preview_url) = ($1, $2, $3, $4);
1173                printf " %-16s %-30s %s\n",$theme_name,$theme_desc,$theme_preview_url;
1174            } elsif ($line =~ /^ICON\t(.*)\t(.*)\t(.*)$/) {
1175                my ($ch, $ch_theme, $url) = ($1, $2, $3);
1176                my $themename = "$ch_theme [$url]";
1177                $t->{ch}->{$ch}->{themes}->{$themename}->{url} = $url;
1178
1179                $t->{ch}->{$ch}->{themes}->{$themename}->{fname} = $ch_theme."_".$ch;
1180                if ($url =~ /\/([a-zA-Z0-9\.\_]+)$/) {
1181                    $t->{ch}->{$ch}->{themes}->{$themename}->{fname} = $ch_theme."_".$1;
1182                }
1183
1184                $t->{ch}->{$ch}->{first_theme} = $themename if (!defined $t->{ch}->{$ch}->{first_theme});
1185                $t->{ch}->{$ch}->{count}++;
1186            }
1187        }
1188
1189        print "\nFor each channel, choose the icon theme you would like to use:\n";
1190        foreach my $ch (sort keys %{($t->{ch})}) {
1191            next if ((!defined $::channels->{$ch}) && (!defined $::opt_channels->{$ch}));
1192            my $xmlid = $::channels->{$ch};
1193            $xmlid = $::opt_channels->{$ch} if (defined $::opt_channels->{$ch});
1194
1195            printf "\n\n$ch: [%s]\n",$xmlid;
1196
1197            # verify that channel is in database
1198            my ($chan_id,$curr_icon) = $dbh->selectrow_array("SELECT chanid,icon FROM channel WHERE xmltvid LIKE '".$xmlid."'");
1199            if (!$chan_id) {
1200                print "  Skipped - not in channels database.\n";
1201                next;
1202            } else {
1203                print "Icon currently set to: $curr_icon\n";
1204            }
1205
1206            # let user choose the icon theme they want. if there is only one choice, choose it for them
1207            my $chosen_theme = "";
1208            if (($t->{ch}->{$ch}->{count} == 1) && ($curr_icon eq "none")) {
1209                $chosen_theme = $t->{ch}->{$ch}->{first_theme};
1210                print "Only one theme and icon not currently set, using: $chosen_theme\n";
1211            } else {
1212                $chosen_theme = &XMLTV::Ask::ask_choice("Choose theme:",
1213                    ($curr_icon eq "none" ? $t->{ch}->{$ch}->{first_theme} : "current icon ($curr_icon)"),
1214                    "current icon ($curr_icon)", "none",
1215                    sort keys %{($t->{ch}->{$ch}->{themes})});
1216            }
1217
1218            if (($chosen_theme ne "") && ($chosen_theme !~ /^current/)) {
1219                my $fname;
1220                if ($chosen_theme eq "none") {
1221                    $fname = "none";
1222                } else {
1223                    # always re-fetch icons even if we already had them.
1224                    # this simplifies the case if a download was corrupt.
1225                    my $url = $t->{ch}->{$ch}->{themes}->{$chosen_theme}->{url};
1226                    $fname = "$::CWD/icons/".$t->{ch}->{$ch}->{themes}->{$chosen_theme}->{fname};
1227
1228                    print "Fetching $url .. ";
1229                    if (!(&::fetch_file($url, $fname, 1))) {
1230                        print "Failed.\n";
1231                        next;
1232                    }
1233                    print "done.\n";
1234                }
1235
1236                # update database
1237                print "Updating database to $fname .. ";
1238                $dbh->do("UPDATE channel SET icon='".$fname."' WHERE chanid LIKE $chan_id") ||
1239                die "could not update database channel icon: ".$dbh->errstr;
1240                print "done.\n";
1241            }
1242        }
1243
1244        print "\n\nAll done.\n".
1245              "You will need to restart both mythbackend and mythfrontend for any icon changes to appear.\n\n";
1246
1247        &Shepherd::MythTV::close_connection;
1248        &::log("Successfully set MythTV icons.\n");
1249    };
1250    if ($@)
1251    {
1252        &::log("Error trying to access MythTV database: $@\n");
1253        return undef;
1254    }
1255}
1256
1257
1258
12591;
Note: See TracBrowser for help on using the browser.