Ticket #5371: mythical.pl

File mythical.pl, 4.6 KB (added by daveg at dgnode dot screaming dot net, 17 years ago)

Perl script

Line 
1#!/usr/bin/perl -w
2# Name: mythical
3# Version: 0.1
4# Release: 1
5# Summary: Generate an iCalendar file of upcoming MythTV recordings
6# License: GPL - use at your own risk etc.
7# Copyright: (C) 2008 - David Greenhouse <daveg at dgnode dot screaming dot net>
8# Description:
9# Similar to mythtv/contrib/misc_status_info/myth_upcoming_recordings.pl
10# but generates an iCalendar (RFC2445) file for use with desktop calendar
11# applications such as KOrganizer.
12# Why?
13# The information is already available within MythTV frontend and MythWeb but is
14# a natural fit for a desktop calendar application. With the data in iCalendar (RFC2445)
15# format it becomes very portable either by direct access or via synchronisation such
16# as SyncML. May even get my Palm to run as a IR remote and synchronise the recording
17# schedule via OBEX!
18# Usage:
19# # MythTV class gripes about UPnP missing so redirect stderr if run by cron etc.
20# mythical.pl 2>/dev/null >~/mythical.ics
21# TODO:
22# UTF-8.
23# Run-time options.
24# Timezones.
25# Testing for daylight saving etc.
26# Suggestions?
27# Further Development?
28# Could be merged with 'myth_upcoming_recordings.pl'.
29# Functionality could be included in MythWeb to provide a live webCal interface.
30# Use Data::iCal (not in Fedora 8 yet).
31# Suggestions?
32# Revision History:
33# * 2008-05-16 0.1-1 David Greenhouse <daveg at dgnode dot screaming dot net>
34# - Initial creation.
35
36use strict;
37use warnings;
38use MythTV;
39
40#program version
41my $VERSION="0.1";
42
43# Connect to the MythTV backend
44my $myth = new MythTV();
45# Get a list of upcoming recordings
46my %rows = $myth->backend_rows('QUERY_GETALLPENDING', 2);
47my $row;
48my $show;
49# iCalendar wrapper
50format_value('BEGIN', 'VCALENDAR');
51format_value('VERSION', '2.0');
52format_value('PROGID', "-//MythTV Recording Schedule//NONSGML mythical $VERSION//EN");
53# Content
54foreach $row (@{$rows{'rows'}}) {
55 $show = new MythTV::Program(@$row);
56 # Selection criteria...
57 if (include_this($show)) {
58 format_event($show);
59 }
60}
61format_value('END', 'VCALENDAR');
62
63# Test to include the given programme or not.
64# May need some more work, run-time options etc.
65sub include_this {
66 my $prog = shift;
67 return $prog->{'recstatus'} == $MythTV::recstatus_willrecord;
68}
69
70# Output an iCalendar entry for the given programme.
71sub format_event {
72 my $prog = shift;
73 format_value('BEGIN', 'VEVENT');
74 format_value('DTSTAMP', format_date(time()));
75 format_value('UID', format_uid($prog));
76 format_value('DTSTART', format_date($prog->{'starttime'}));
77 format_value('DTEND', format_date($prog->{'endtime'}));
78 format_value('LAST-MODIFIED', format_date($prog->{'lastmodified'}));
79 if ($prog->{'subtitle'} ne 'Untitled') {
80 format_value('SUMMARY', $prog->{'title'} . ' - "' . $prog->{'subtitle'} . '"');
81 } else {
82 format_value('SUMMARY', $prog->{'title'});
83 }
84 format_value('DESCRIPTION', $prog->{'description'});
85 format_value('LOCATION', $prog->{'channel'}{'name'});
86 format_value('CATEGORIES', $prog->{'category'});
87 format_value('TRANSP', $prog->{'recstatus'} == $MythTV::recstatus_willrecord ? 'OPAQUE' : 'TRANSPARENT');
88 format_value('STATUS', $prog->{'recstatus'} == $MythTV::recstatus_willrecord ? 'CONFIRMED' : 'TENTATIVE');
89 format_value('PRIORITY', format_priority($prog));
90 format_value('X-MYTHTV-RECSTATUS', $MythTV::RecStatus_Types{$prog->{'recstatus'}});
91 format_value('END', 'VEVENT');
92}
93
94# Format an entry line with the given tag and value.
95# Escapes and wraps, terminate with CR-NL.
96sub format_value {
97 my $tag = shift;
98 my $value = shift;
99 # Escapes
100 $value =~ s/;/\\;/g;
101 $value =~ s/,/\\,/g;
102 $value =~ s/"/\\"/g;
103 # Wrap at col 76
104 my $text = $tag . ":" . $value;
105 while (length($text) > 76) {
106 print substr($text, 0, 76) . "\r\n";
107 $text = ' ' . substr($text, 76);
108 }
109 if ($text ne ' ') {
110 print $text . "\r\n";
111 }
112}
113
114# Format a date/time value as an iCalendar Date/Time
115sub format_date {
116 my $localtime = shift;
117 my ($ts,$tm,$th,$dd,$dm,$dy) = localtime($localtime);
118 # YYYYMMDDThhmmss
119 return sprintf "%4.4d%2.2d%2.2dT%2.2d%2.2d%2.2d", $dy + 1900, $dm + 1, $dd, $th, $tm, $ts;
120}
121
122# Generate a unique identifier for the given programme.
123# chanid_starttime@hostname
124sub format_uid {
125 my $prog = shift;
126 my ($ts,$tm,$th,$dd,$dm,$dy) = localtime($prog->{'starttime'});
127 return sprintf "%4.4s_%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d@%s", $prog->{'chanid'}, $dy + 1900, $dm + 1, $dd, $th, $tm, $ts, $prog->{'hostname'};
128}
129
130# Simple classification of recording priority in to three levels.
131sub format_priority {
132 my $prog = shift;
133 my $pri = $prog->{'recpriority'};
134 if ($pri < 0) {
135 return 'LOW';
136 } elsif ($pri > 0) {
137 return 'HIGH';
138 }
139 return 'MEDIUM';
140}