#! /usr/bin/perl -w use Getopt::Long; use Pod::Usage; my $help = 0; my $usage = 0; my $dryrun = 0; my $verbose = 0; my $path = ''; my $annex = ''; my $home = $ENV{'HOME'}; sub main() { checkargs(); if (!$path) { $path = $home . '/.xbmc/userdata/Database'; } print("# checking XBMC directory '$path'\n") if ($verbose); $dbpath = finddb($path); if (!$dbpath) { pod2usage("$0: can't find a XBMC database in '$path'."); } print("# using database '$dbpath'\n") if ($verbose); checkdb(); } # list videos database, find the latest one # modified version of # http://stackoverflow.com/questions/4651092/getting-the-list-of-files-sorted-by-modification-date-in-perl sub finddb($) { my $path = shift(@_); opendir my($dirh), $path or die "can't opendir $path: $!"; my @flist = sort { -M $a <=> -M $b } # Sort by modification time map { "$path/$_" } # We need full paths for sorting grep { /^MyVideos.*\.db$/ } readdir $dirh; closedir $dirh; if ($#flist > 0) { return $flist[0]; } else { return 0; } } sub checkargs() { pod2usage(1) if $help; pod2usage(-exitval => 0, -verbose => 2) if $usage; GetOptions('h|?' => \$help, 'help|usage' => \$usage, # we want to operate on relative links, so set this to # the common annex to the git annex repo 'annex=s' => \$annex, 'path=s' => \$path, 'home=s' => \$home, 'dryrun|n' => \$dryrun, 'verbose|v' => \$verbose, ) or die("Error parsing commandline\n"); } sub checkdb() { my @lines = `echo 'SELECT playCount, path.strPath, files.strFileName FROM movie JOIN files ON files.idFile=movie.idFile JOIN path ON path.idPath=files.idPath;' | sqlite3 $dbpath`; print "# finding files...\n" if $verbose; for (@lines) { my ($count, $dir, $file) = split /\|/; chomp $file; # empty or non-numeric count is zero if ($count !~ /[0-9]/) { $count = 0; } print "# $dir/$file\n" if $verbose; if ($file =~ s#stack://##) { for (split /,/, $file) { s/$annex//; s/^ //; s/ $//; my @cmd = (qw(git annex metadata --set), "playCount=$count", $_); if ($dryrun) { print join(' ', @cmd) . "\n"; } else { system(@cmd); } } } else { $dir =~ s/$annex//; my @cmd = (qw(git annex metadata --set), "playCount=$count", "$dir$file"); if ($dryrun) { print join(' ', @cmd) . "\n"; } else { system(@cmd); } } } } main(); __END__ =encoding utf8 =head1 NAME git-annex-xbmc-playcount - register XBMC playcounts as git-annex metadata =head1 SYNOPSIS git-annex-xbmc-playcount [--path .xbmc/userdata/Database] Options: -h short usage --help complete help --dryrun, -n do nothing and show the commands that would be ran --annex path to the git-annex repo --home the home directory where the .xbmc directory is located --path the location of the Database directory of XBMC, overrides --home --verbose show interaction details with the database =head1 DESCRIPTION This program will look into the XBMC database for the "playcount" field to register that number as metadata in the git-annex repository. =head1 OPTIONS =over 8 =item B<--dryrun> Do nothing but show all the steps that would be ran. The output can be piped through a POSIX shell after inspection. B<-n> is an alias of this command. Example: git-annex-xbmc-playcount -n | tee runme # inspect the output sh < runme =item B<--annex> This option allows the user to specify the root of the git-annex repository, which is then stripped off the paths found in the XBMC database. =item B<--home> Home of the user running XBMC. If not specified, defaults to the $HOME environment variables. The script will look into B<$home/.xbmc/userdata/Database> for a file matching B<^MyVideos.*\.db$> and will fail if none is found. =item B<--path> Manually specify the path to B<.xbmc/userdata/Database>. This overrides B<--home>. Note that this doesn't point directly to the database itself, because there are usually many database files and we want to automatically find the latest. This may be a stupid limitation. =item B<--verbose> Show more information about path discovery. Doesn't obstruct B<--dryrun> output because lines are prefixed with C<#>. =back =head1 EXAMPLES You have a git annex in B and XBMC is ran as the B