#!/usr/local/bin/perl
# search for EyeTV recordings
# pudge@pobox.com, http://dev.macperl.org/
# Wed Nov 13 11:43:21 2002
# This program is free and open software. You may use, modify,
# distribute, and sell this program (and any modified variants) in any
# way you wish, provided you do not restrict others from doing the same.
use strict;
use warnings;
no warnings 'uninitialized';
# all modules on the CPAN or included with perl
use Date::Format;
use Date::Parse;
use File::Basename;
use File::Glob ':glob';
use File::Spec::Functions;
use Getopt::Std;
use Mac::Files;
use Mac::Memory;
use Mac::PropertyList 'parse_plist';
use Text::Autoformat;
my $PROGNAME = basename($0);
my %opts;
usage('Options used incorrectly') unless getopts('d:t:t2:phfluq:', \%opts);
usage() if $opts{'h'};
my $match = shift @ARGV;
my $eyetvdir = $opts{'d'};
if (!$eyetvdir) {
# find proper file from preferences, it's a Base64'd alias,
# so get the data, stick it in a handle, and resolve it
my $prefs = catfile(
FindFolder(kOnSystemDisk, kPreferencesFolderType),
'com.elgato.eyetv.plist'
);
my $data = get_plist($prefs);
my $handle = new Handle $data->{'value'}{'archive folder'}{value};
$eyetvdir = catdir(scalar ResolveAlias($handle), 'EyeTV Archive');
}
opendir my $dh, $eyetvdir or die "Can't open $eyetvdir: $!";
my %matches;
for my $dir (grep { /^[0-9a-f]{16}/ } readdir $dh) {
next if $dir eq ('f' x 16) && !$opts{'f'};
my %files = map { ($_, 1) } glob( catfile($eyetvdir, $dir, '*.eyetv[pr]') );
my @files = grep { /r$/ } keys %files;
my @pfiles = grep { /p$/ } keys %files;
push @files, @pfiles if $opts{'p'} || $opts{'t'} == 1;
my $pdata = get_plist($pfiles[0]);
for my $file (@files) {
my $nfile = catfile($dir, basename($file, '\.*'));
my $data = get_plist($file);
# sometimes the title or description is not
# properly filled in, find it in the 'p' file
for (qw(description)) {
$data->{value}{$_}{value} ||= $pdata->{value}{$_}{value};
}
# ... but if both titles are defined, the r one is probably
# the episode title, so combine them
if (!$data->{value}{title}{value}) {
$data->{value}{title}{value} = $pdata->{value}{title}{value};
} elsif ($data->{value}{title}{value} && $data->{value}{title}{value}) {
$data->{value}{title}{value} = $pdata->{value}{title}{value}
. ' - ' . $data->{value}{title}{value};
}
if ($match) {
$matches{$nfile} = $data if
grep { /\Q$match\E/i }
map { $data->{value}{$_}{value} }
qw(title description);
} else {
$matches{$nfile} = $data;
}
# unfinished code: grep by time
if ($opts{t}) {
my($t1, $t2);
if ($opts{t} == 1) { $t1 = time() }
else { $t1 = str2time($opts{t}) }
if ($opts{t2} == 1) { $t2 = time() }
else { $t2 = str2time($opts{t2}) }
for my $file (keys %matches) {
delete $matches{$file} if
get_date($matches{$file}{value}) < $t1;
}
}
}
}
unless ($opts{'q'}) {
print "TV recordings in directory '$eyetvdir':\n";
print keys %matches ? "\n" : "No matches found.\n";
}
my %playlists;
for my $file (sort {
$matches{$a}{value}{start}{value}
cmp
$matches{$b}{value}{start}{value}
} keys %matches) {
my $info = $matches{$file}{value};
my $description = $info->{description}{value} || '';
$description &&= autoformat(
$description,
{ left => 5, right => 74, all => 1 }
);
if (!$opts{'q'}) {
if ($opts{'u'}) {
$file =~ s/eyetvr/mpg/;
$file = "http://mp3.pudge.net:8080/private/eyetv/$file";
} elsif ($opts{'l'}) {
$file =~ s/eyetvr/mpg/;
$file = catfile($eyetvdir, $file);
}
}
my @values = (
$info->{title}{value},
$file,
scalar localtime get_date($info),
$info->{duration}{value}/3600,
$description
);
if ($opts{'q'}) {
push @{$playlists{ $info->{title}{value} }}, \@values;
} else {
printf <<'EOT', @values;
%s
%s
%s (%.2f hours)
%s
EOT
}
}
if ($opts{'q'}) {
opendir my $dh, $opts{'q'} or die $!;
for my $file (readdir $dh) {
if ($file =~ /^EyeTV: /) {
unlink catfile($opts{'q'}, $file);
}
}
for my $title (keys %playlists) {
my $file = catfile($opts{'q'}, "EyeTV: $title.bqp");
open my $fh, '>', $file or die $!;
for my $program (@{$playlists{$title}}) {
$program->[1] =~ s/eyetvr$/mpg/;
printf $fh <<'EOT', @{$program}[1, 2];
EyeTV/%s
%s
EOT
}
}
}
sub get_plist {
my($file) = @_;
open my $fh, '<', $file or die "Can't open '$file': $!";
my $data = do { local $/; <$fh> };
# flatten
$data =~ s{ [^<]+\s+ }{}sgx;
$data =~ s{ (?!\n) }{}sgx;
return Mac::PropertyList::parse_plist($data);
}
sub get_date {
my($info) = @_;
my $date = $info->{start}{value};
$date =~ s/T/ /;
$date =~ s/Z/ GMT/;
return str2time($date);
}
sub usage {
print "*** $_[0]\n" if $_[0];
print <