| 505 | | if (defined $plugin_data->{$plugin}->{xmltv}) { |
| 506 | | $plugin_data->{$plugin}->{valid} = 1; |
| 507 | | |
| 508 | | my $xmltv = $plugin_data->{$plugin}->{xmltv}; |
| 509 | | my ($encoding, $credits, $chan, $progs) = @$xmltv; |
| 510 | | $plugin_data->{$plugin}->{total_duration} = 0; |
| 511 | | $plugin_data->{$plugin}->{programmes} = 0; |
| 512 | | |
| 513 | | my $strptime = new DateTime::Format::Strptime( pattern => "%Y%m%d%H%M %z"); |
| 514 | | my $alt_strptime = new DateTime::Format::Strptime( pattern => "%Y%m%d%H%M"); # alternate format 1: oztivo doesn't seem to output timezone |
| 515 | | my $seen_channels_with_data = 0; |
| 516 | | |
| 517 | | # iterate thru channels |
| 518 | | foreach my $ch (sort keys %{$channels}) { |
| 519 | | my $seen_progs_on_this_channel = 0; |
| 520 | | |
| 521 | | # iterate thru programmes per channel |
| 522 | | foreach my $prog (@$progs) { |
| 523 | | next if ($prog->{channel} ne $channels->{$ch}); |
| 524 | | |
| 525 | | my $t1 = $strptime->parse_datetime($prog->{start}); |
| 526 | | $t1 = $alt_strptime->parse_datetime($prog->{start}) if (!$t1); |
| 527 | | |
| 528 | | my $t2 = $strptime->parse_datetime($prog->{stop}); |
| 529 | | $t2 = $alt_strptime->parse_datetime($prog->{stop}) if (!$t2); |
| 530 | | |
| 531 | | next if (!$t1 || !$t2); # if we can't parse stop/start then clearly THIS data is bunk! |
| 532 | | |
| 533 | | # store t1 and t2 times in the xmltv data for later on (shh.. ton't tell anyone..) |
| 534 | | $prog->{start_epoch} = $t1->epoch; |
| 535 | | $prog->{stop_epoch} = $t2->epoch; |
| 536 | | |
| 537 | | # store plugin-specific stats |
| 538 | | $plugin_data->{$plugin}->{programmes}++; |
| 539 | | $plugin_data->{$plugin}->{total_duration} += ($t2->epoch - $t1->epoch); |
| 540 | | $seen_progs_on_this_channel++; |
| 541 | | $plugin_data->{$plugin}->{earliest_data_seen} = $t1->epoch if (!defined $plugin_data->{$plugin}->{earliest_data_seen}); |
| 542 | | $plugin_data->{$plugin}->{earliest_data_seen} = $t1->epoch if ($t1->epoch < $plugin_data->{$plugin}->{earliest_data_seen}); |
| 543 | | $plugin_data->{$plugin}->{latest_data_seen} = $t2->epoch if (!defined $plugin_data->{$plugin}->{latest_data_seen}); |
| 544 | | $plugin_data->{$plugin}->{latest_data_seen} = $t2->epoch if ($t2->epoch > $plugin_data->{$plugin}->{latest_data_seen}); |
| 545 | | |
| 546 | | # store channel-specific stats |
| 547 | | $channel_data->{$ch}->{programmes}++; |
| 548 | | $channel_data->{$ch}->{total_duration} += ($t2->epoch - $t1->epoch); |
| 549 | | |
| 550 | | # store timeslot info |
| 551 | | next if ($t1->epoch > $endtime); # programme starts after timeslots we are interested .. nice that we have it ... but we really don't care about it! |
| 552 | | next if ($t2->epoch < $starttime); # programme ends before timeslots we are interested .. nice that we have it ... but we really don't care about it! |
| 553 | | my $start_slotnum; |
| 554 | | if ($t1->epoch >= $starttime) { |
| 555 | | $start_slotnum = int(($t1->epoch - $starttime) / $timeslot_size); |
| 556 | | } else { |
| 557 | | $start_slotnum = 0; |
| 558 | | } |
| 559 | | my $end_slotnum; |
| 560 | | if ($t2->epoch < $endtime) { |
| 561 | | $end_slotnum = int(($t2->epoch - $starttime) / $timeslot_size); |
| 562 | | } else { |
| 563 | | $end_slotnum = ($num_timeslots-1); |
| 564 | | } |
| 565 | | |
| 566 | | # add this programme into the global timeslots table for this channel |
| 567 | | foreach my $slotnum ($start_slotnum..$end_slotnum) { |
| 568 | | $channel_data->{$ch}->{timeslots}[$slotnum]++; |
| 569 | | } |
| | 506 | if (!($this_plugin->{xmltv})) { |
| | 507 | printf "WARNING: Plugin %s didn't seem to return any valid XMLTV!\n",$plugin; |
| | 508 | return; |
| | 509 | } |
| | 510 | |
| | 511 | $this_plugin->{valid} = 1; |
| | 512 | |
| | 513 | my $xmltv = $this_plugin->{xmltv}; |
| | 514 | my ($encoding, $credits, $chan, $progs) = @$xmltv; |
| | 515 | $this_plugin->{total_duration} = 0; |
| | 516 | $this_plugin->{programmes} = 0; |
| | 517 | $this_plugin->{progs_with_invalid_date} = 0; # explicitly track unparsable dates |
| | 518 | $this_plugin->{progs_with_unknown_channel} = 0; # explicitly track unknown channels |
| | 519 | |
| | 520 | my $strptime = new DateTime::Format::Strptime( pattern => "%Y%m%d%H%M %z"); |
| | 521 | my $alt_strptime = new DateTime::Format::Strptime( pattern => "%Y%m%d%H%M"); # alternate format 1: oztivo doesn't seem to output timezone |
| | 522 | my $seen_channels_with_data = 0; |
| | 523 | |
| | 524 | # |
| | 525 | # first iterate through all programmes and see if there are any channels we don't know about |
| | 526 | # |
| | 527 | my %chan_xml_list; |
| | 528 | foreach my $ch (sort keys %{$channels}) { |
| | 529 | $chan_xml_list{($channels->{$ch})} = 1; |
| | 530 | } |
| | 531 | foreach my $prog (@$progs) { |
| | 532 | if (!defined $chan_xml_list{($prog->{channel})}) { |
| | 533 | $this_plugin->{progs_with_unknown_channel}++; |
| | 534 | printf " - WARNING: plugin '%s' returned data for unknown channel '%s': ignored.\n",$plugin,$prog->{channel}; |
| | 535 | $chan_xml_list{($prog->{channel})} = 1; # so we warn only once |
| | 536 | } |
| | 537 | } |
| | 538 | |
| | 539 | # iterate thru channels |
| | 540 | foreach my $ch (sort keys %{$channels}) { |
| | 541 | my $seen_progs_on_this_channel = 0; |
| | 542 | |
| | 543 | # iterate thru programmes per channel |
| | 544 | foreach my $prog (@$progs) { |
| | 545 | next if ($prog->{channel} ne $channels->{$ch}); |
| | 546 | |
| | 547 | my $t1 = $strptime->parse_datetime($prog->{start}); |
| | 548 | my $t2 = $strptime->parse_datetime($prog->{stop}); |
| | 549 | $t1 = $alt_strptime->parse_datetime($prog->{start}) if (!$t1); |
| | 550 | $t2 = $alt_strptime->parse_datetime($prog->{stop}) if (!$t2); |
| | 551 | |
| | 552 | if (!$t1 || !$t2) { |
| | 553 | printf " - WARNING: plugin '%s' returned programme data with invalid timestamp format: \"%s\": can't parse.\n", |
| | 554 | $plugin,(!$t1 ? $prog->{start} : $prog->{stop}) if (!$this_plugin->{progs_with_invalid_date}); |
| | 555 | $this_plugin->{progs_with_invalid_date}++; |
| | 556 | next; |
| 572 | | $seen_channels_with_data++ if ($seen_progs_on_this_channel > 0); |
| 573 | | } |
| 574 | | |
| 575 | | # print some stats about what we saw! |
| 576 | | printf "SHEPHERD: %s '%s' returned data for %d channels, %d programmes, %dd%02dh%02dm%02ds duration, %s%s\n", |
| 577 | | ucfirst($plugintype), $plugin, $seen_channels_with_data, $plugin_data->{$plugin}->{programmes}, |
| 578 | | int($plugin_data->{$plugin}->{total_duration} / 86400), # days |
| 579 | | int(($plugin_data->{$plugin}->{total_duration} % 86400) / 3600), # hours |
| 580 | | int(($plugin_data->{$plugin}->{total_duration} % 3600) / 60), # mins |
| 581 | | int($plugin_data->{$plugin}->{total_duration} % 60), # sec |
| 582 | | (defined $plugin_data->{$plugin}->{earliest_data_seen} ? (strftime "%a %e %b %H:%M - ", localtime($plugin_data->{$plugin}->{earliest_data_seen})) : 'no data'), |
| 583 | | (defined $plugin_data->{$plugin}->{latest_data_seen} ? (strftime "%a %e %b %H:%M", localtime($plugin_data->{$plugin}->{latest_data_seen})) : ''); |
| 584 | | $plugin_data->{$plugin}->{laststatus} = sprintf "%dch/%dpr/%dhrs %s-%s", |
| 585 | | $seen_channels_with_data, $plugin_data->{$plugin}->{programmes}, |
| 586 | | int($plugin_data->{$plugin}->{total_duration} / 3600), |
| 587 | | (defined $plugin_data->{$plugin}->{earliest_data_seen} ? (strftime "%a%d%b%H:%M", localtime($plugin_data->{$plugin}->{earliest_data_seen})) : 'no'), |
| 588 | | (defined $plugin_data->{$plugin}->{latest_data_seen} ? (strftime "%a%d%b%H:%M", localtime($plugin_data->{$plugin}->{latest_data_seen})) : 'data'); |
| 589 | | |
| 590 | | } else { |
| 591 | | printf "WARNING: Plugin %s didn't seem to return any valid XMLTV!\n",$plugin; |
| 592 | | delete $plugin_data->{$plugin}->{valid}; |
| 593 | | } |
| | 559 | # store t1 and t2 times in the xmltv data for later on (shh.. ton't tell anyone..) |
| | 560 | $prog->{start_epoch} = $t1->epoch; |
| | 561 | $prog->{stop_epoch} = $t2->epoch; |
| | 562 | |
| | 563 | # store plugin-specific stats |
| | 564 | $this_plugin->{programmes}++; |
| | 565 | $this_plugin->{total_duration} += ($t2->epoch - $t1->epoch); |
| | 566 | $seen_progs_on_this_channel++; |
| | 567 | $this_plugin->{earliest_data_seen} = $t1->epoch if (!defined $this_plugin->{earliest_data_seen}); |
| | 568 | $this_plugin->{earliest_data_seen} = $t1->epoch if ($t1->epoch < $this_plugin->{earliest_data_seen}); |
| | 569 | $this_plugin->{latest_data_seen} = $t2->epoch if (!defined $this_plugin->{latest_data_seen}); |
| | 570 | $this_plugin->{latest_data_seen} = $t2->epoch if ($t2->epoch > $this_plugin->{latest_data_seen}); |
| | 571 | |
| | 572 | # store channel-specific stats |
| | 573 | $channel_data->{$ch}->{programmes}++; |
| | 574 | $channel_data->{$ch}->{total_duration} += ($t2->epoch - $t1->epoch); |
| | 575 | |
| | 576 | # store timeslot info |
| | 577 | next if ($t1->epoch > $endtime); # programme starts after timeslots we are interested .. nice that we have it ... but we really don't care about it! |
| | 578 | next if ($t2->epoch < $starttime); # programme ends before timeslots we are interested .. nice that we have it ... but we really don't care about it! |
| | 579 | my $start_slotnum; |
| | 580 | if ($t1->epoch >= $starttime) { |
| | 581 | $start_slotnum = int(($t1->epoch - $starttime) / $timeslot_size); |
| | 582 | } else { |
| | 583 | $start_slotnum = 0; |
| | 584 | } |
| | 585 | my $end_slotnum; |
| | 586 | if ($t2->epoch < $endtime) { |
| | 587 | $end_slotnum = int(($t2->epoch - $starttime) / $timeslot_size); |
| | 588 | } else { |
| | 589 | $end_slotnum = ($num_timeslots-1); |
| | 590 | } |
| | 591 | |
| | 592 | # add this programme into the global timeslots table for this channel |
| | 593 | foreach my $slotnum ($start_slotnum..$end_slotnum) { |
| | 594 | $channel_data->{$ch}->{timeslots}[$slotnum]++; |
| | 595 | } |
| | 596 | } |
| | 597 | |
| | 598 | $seen_channels_with_data++ if ($seen_progs_on_this_channel > 0); |
| | 599 | } |
| | 600 | |
| | 601 | # print some stats about what we saw! |
| | 602 | printf "SHEPHERD: %s '%s' returned data for %d channels, %d programmes, %dd%02dh%02dm%02ds duration, %s%s\n", |
| | 603 | ucfirst($plugintype), $plugin, $seen_channels_with_data, $this_plugin->{programmes}, |
| | 604 | int($this_plugin->{total_duration} / 86400), # days |
| | 605 | int(($this_plugin->{total_duration} % 86400) / 3600), # hours |
| | 606 | int(($this_plugin->{total_duration} % 3600) / 60), # mins |
| | 607 | int($this_plugin->{total_duration} % 60), # sec |
| | 608 | (defined $this_plugin->{earliest_data_seen} ? (strftime "%a %e %b %H:%M - ", localtime($this_plugin->{earliest_data_seen})) : 'no data'), |
| | 609 | (defined $this_plugin->{latest_data_seen} ? (strftime "%a %e %b %H:%M", localtime($this_plugin->{latest_data_seen})) : ''); |
| | 610 | $this_plugin->{laststatus} = sprintf "%dch/%dpr/%dhrs %s-%s", |
| | 611 | $seen_channels_with_data, $this_plugin->{programmes}, |
| | 612 | int($this_plugin->{total_duration} / 3600), |
| | 613 | (defined $this_plugin->{earliest_data_seen} ? (strftime "%a%d%b%H:%M", localtime($this_plugin->{earliest_data_seen})) : 'no'), |
| | 614 | (defined $this_plugin->{latest_data_seen} ? (strftime "%a%d%b%H:%M", localtime($this_plugin->{latest_data_seen})) : 'data'); |
| | 615 | |
| | 616 | $plugin_data->{$plugin} = $this_plugin; |