Upcoming Parse.pl

From MythTV Official Wiki
Jump to: navigation, search

Author Christopher Neufeld
Description This script provides an example of how one can use perl to parse the XML data available on the service port of the backend. This particular example returns the number of seconds before the start time of the next scheduled recording, and the channel number next to be tuned on a particular encoder.
Supports Version25.png  Version26.png 


Background

MythTV versions 0.25 and later support an informational data channel in the Services API. See that page for more information. A correctly formulated HTTP request will return an XML data block that can be parsed by appropriate scripts.

In my particular setup, I have a set-top box that can, in rare cases, take many minutes to tune a channel, so I'd like to tune that encoder as far ahead of time as possible. I also have an automated procedure to power-cycle my Hauppauge HD-PVR after every recording, but I want to skip doing that if another recording is scheduled to begin shortly, on any encoder. Pursuant to this, the following script returns two numbers on a line. The first is the number of seconds until the start time of the next scheduled recording on any encoder (note that this does not account for any user-configured preroll, which can be used to start recordings a certain number of seconds early). The second is the channel number of the next recording scheduled to be made on encoder #1, which is my HD-PVR encoder. Since I never use live TV on my MythTV box, the backend always knows what recording will be made next.

Determining the XML data structure

Before we can write the script, we have to know how the data will be returned from the API. One could look through the source code and documentation, but it's actually quite easy to dump the format to the screen, and design one's script based simply on that. The following script dumps out the data from the DVR_Service#GetUpcomingList service.

#!/usr/bin/perl

use LWP::Simple;
use XML::Simple;
use Data::Dumper;


$backend = 'mythtv.i.cneufeld.ca';

# Retrieve the next 10 recordings from the backend
$xmlstring = get "http://${backend}:6544/Dvr/GetUpcomingList?Count=10" || die "Unable to contact backend.";


$xml = new XML::Simple;
$parsedxml = $xml->XMLin($xmlstring);
print Dumper($parsedxml);

The output of this script is actually quite long, and I won't reproduce it here, but a sample is reproduced at DVR_Service#GetUpcomingList. Looking at the data output by the perl script, you can see that the upcoming recordings are in an array under ->{Programs}->{Program}.

The upcoming_parse.pl script

Here is the script that I use. It retrieves and parses the upcoming recording data, retrieves the current time and the time of the next recording, loops over upcoming recordings to find the next one scheduled on the HD-PVR, and finally prints out the number of seconds to the next recording, and the next channel to be tuned on the HD-PVR.

#!/usr/bin/perl

# Here's a helpful little script for my HD-PVR troubles.  It queries
# the backend, and returns one line with two numbers on it:
#
# The first is the number of seconds before the next scheduled
# recording is to start (on any encoder).  The second is the channel
# number of the next HD-PVR recording, or 1 if there are no HD-PVR
# recordings among the next 10 scheduled.

use strict;

use LWP::Simple;
use XML::Simple;
use Date::Manip::Date;

my $nextchan = 1;  # default if no HD-PVR recordings are upcoming

# Local network settings
my $hdpvr_encoder = 1;
my $backend = 'mythtv.i.cneufeld.ca';

# Retrieve the next 10 recordings from the backend
my $xmlstring = get "http://${backend}:6544/Dvr/GetUpcomingList?Count=10" || die "Unable to contact backend.";

# Parse the recording data
my $xml = new XML::Simple;
my $parsedxml = $xml->XMLin($xmlstring);

# When is now?
my $rightnow = new Date::Manip::Date;
$rightnow->parse("now");

# When is the first recording in the upcoming list?
my $nextstart = new Date::Manip::Date;
$nextstart->parse(@{$parsedxml->{Programs}->{Program}}[0]->{StartTime});

# Find the next recording that will occur on the HD-PVR, and record
# its channel number
foreach my $entry (@{$parsedxml->{Programs}->{Program}})
{
    if ( $entry->{Recording}->{EncoderId} == $hdpvr_encoder ) {
	$nextchan = $entry->{Channel}->{ChanNum};
	last;
    }
}

# Dump the results
print $nextstart->secs_since_1970_GMT() - $rightnow->secs_since_1970_GMT(), "   ", $nextchan, "\n";