File:Xmbc inotify.pl

From RARForge
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Xmbc_inotify.pl(file size: 8 KB, MIME type: application/x-perl)

Warning: This file type may contain malicious code. By executing it, your system may be compromised.

<source lang=perl>

  1. !/usr/bin/perl -w

use strict; use Linux::Inotify2; use Path::Class; use Number::Bytes::Human; use File::stat; use Data::Dumper;

    1. JSON rpc call

use LWP::UserAgent; use HTTP::Request; use JSON::PP;

my $debug=1; ## just more verbose


  1. Define required credentials.

my $jsonUser = "xbmc"; my $jsonPass = "<YOU XBMC password>"; my $jsonHost = "localhost:8080";

my $wait=60; ## how many seconds to wait after proccessing an event. This will allow us to group events/updates. (60 seconds default)

    1. only update xbmc / notify on these extentions

my @video_files = qw(avi mkv mpg mpeg mp4 mov wmv flv m1v m2v mpe);

    1. watched dirs - recursive

my @dirs = ("/Videos/", "/OtherVideoDir/",

   );
    1. This requires the script from prowl app
    2. url: http://prowlapp.com/static/prowl.pl

my $prowl = {'enabled' => '0', 'script' => '/usr/local/bin/prowl.pl', 'api_key' => 'FIXME', 'app_name' => 'XBMC Inotify', };

                                                                                                              1. Configuration DONE #######################################################

my @files; my $inotify = Linux::Inotify2->new

   or die "unable to create new inotify object: $!";

my $host=`hostname`; ## maybe used for later my $pid=$$;

    1. on start - lets scan the library

&jsonXBMC('VideoLibrary.Scan'); &notifyProwl('Initializing','program startup');


    1. setup initial watch dirs

my $dirs =0; my $update_xbmc=0; my $clean_xbmc=0; my @start_list; ## used for notifications my @finish_list; ## used for notifications my @remove_list; ## used for notifications

    1. Intialize watched dirs - INIT

foreach my $drop_dir(@dirs) {

   &log("Processing subdirs for: $drop_dir\n",1);
   my $dir = dir($drop_dir);
   my $c = 0;
   $dir->traverse(sub{

my ($child, $cont, $indent) = @_; if ($child->is_dir) { $dirs++; &log("subdir: $child",1); $inotify->watch("$child", IN_CLOSE_WRITE | IN_CREATE | IN_MOVED_TO | IN_DELETE , \&MyWatch);

## in_modify if too verbose.. it grabs any changes to file before final close ## IN_CLOSE_WRITE == after a file is written too/closed ## IN_CREATE == new directories/files ## IN_MOVED_TO == moved directory/files (to watch dirs only) } $cont->($c + 1); }); }

    1. log/notify status of watched dirs

my $init_s = "Watching $dirs directories"; &log($init_s,1); &notifyProwl('Initialized',$init_s);

    1. LOOP to keep watching dirs/files

while (1) {

   $inotify->poll;
   my $had_event = 0;
   ## notify on sync start and finish
   if (@start_list)  {  

my $info = join(', ', @start_list); my $title = 'rSync Started'; &notifyProwl($title,$info); ## notify XBMC my %params = ( "title" => $title, "message" => $info, "displaytime" => 10000, ); &jsonXBMC('GUI.ShowNotification',\%params); @start_list = ();

   }
   if (@finish_list) {  

my $info = join(', ', @finish_list); my $title = 'rSync Finished'; &notifyProwl($title,$info); ## notify XBMC my %params = ( "title" => $title, "message" => $info, "displaytime" => 10000, ); &jsonXBMC('GUI.ShowNotification',\%params); @finish_list = ();

   }
   if (@remove_list)  { 

&notifyProwl('Removed',join(', ', @remove_list)); @remove_list = ();

   }


   if ($update_xbmc) {

$had_event = 1; $update_xbmc = 0; &log("Updating XBMC library"); &jsonXBMC('VideoLibrary.Scan');

   }
   if ($clean_xbmc) {

$had_event = 1; $clean_xbmc = 0; &log("Cleaning XBMC library"); &jsonXBMC('VideoLibrary.Clean');

   }
   if ($had_event) {

&log("Sleeping '$wait' seconds before processing any new events"); sleep($wait); &log("I\'m awake again - ready to process any new events");

   }

}


sub MyWatch() {

   #$inotify->watch("$child",  IN_CLOSE_WRITE | IN_MOVED_TO , sub {
   my $event = shift;
   my $name = $event->fullname;		
   my $file_name = $event->name;		
   ## continue on..
   my $log = 'unknown';
   if ($event->IN_IGNORED) {

$event->w->cancel; ## cancel watch

#$update_xbmc = 1; frodo doesn't work well yet with deleting after update.. so enableing clean again $log = "DIR $name removed -- cancelling watch"; foreach my $ext (@video_files) { $clean_xbmc = 1; ## only clean if we care if ($name =~ /\.$ext/i) { push (@remove_list,$name); } } #&notifyProwl('removed',$log); ## remove watch - if directory

   } elsif ( $event->IN_DELETE) {

## this is a file - so nothign really to do other than notify $log = "FILE: $name removed"; ## group deletes together -- otherwise.. flurry of prowl notify foreach my $ext (@video_files) { $log = "FILE: VIDEO $name removed - will notify prowl"; $clean_xbmc = 1; if ($name =~ /\.$ext/i) { push (@remove_list,$name); } }

   } else {		

if (-d $name) { $inotify->watch($name, IN_CLOSE_WRITE | IN_CREATE | IN_MOVED_TO , \&MyWatch); $log = "DIR: $name created -- adding to watchlist"; &notifyProwl('new',$log); } elsif (-f $name && $event->IN_CREATE) { ## file is created, but has not finished writing - do not update xbmc ### this is where we would notify on start sync -- only notify on files we watch $log = "$name is FILE -- in_create called.. waiting for IN_CLOSE_WRITE to process"; foreach my $ext (@video_files) { ## push new files to start_list (sync started notifications) if ($file_name =~ /\.$ext/i) { push (@start_list,$name); } } } else { $log = "$name is IN_CLOSE_WRITE" if $event->IN_CLOSE_WRITE; $log = "$name is IN_CREATE" if $event->IN_CREATE; $log = "$name is IN_MOVED_TO" if $event->IN_MOVED_TO; $log = "events for $name have been lost\n" if $event->IN_Q_OVERFLOW; if ($file_name =~ /^\..*\.\w{5}$/) { &log("$file_name must be rsync - skip it"); } else { ## only update video files foreach my $ext (@video_files) { ## push new files to finish_list (sync finished notifications) if ($file_name =~ /\.$ext$/i) { ## SIZE OF FILE my $human = Number::Bytes::Human->new(); my $size = stat($name)->size; my $hsize = $human->format($size); push (@finish_list,"[$hsize] $name"); &log("$name $ext is video file -- update xbmc"); $update_xbmc = 1; ## new videos - set update xbmc } } if (!$update_xbmc) {&log("$file_name is NOT a video file -- skipping update xbmc"); } } }

   }
   &log($log);

}


sub log() {

   my $msg = shift;
   my $print= shift;
   if ($debug || $print) {

print localtime . ": $msg\n";

   }
   system("logger  -t $0\[$pid\] \"$msg\"");

}


sub jsonXBMC() {

   my $method = shift;
   my $tmp = shift;
   my %params;
   if ($tmp) {

%params = %$tmp;

   }
   # Construct JSON RPC URL.
   my $jsonUrl = sprintf("http://%s:%s@%s/jsonrpc",

$jsonUser, $jsonPass, $jsonHost,);

   my %hash = ("jsonrpc" => "2.0",

"method" => "$method", "params" => \%params, "id" => $method, );

   #my $json = encode_json \%hash;
   my $js = JSON::PP->new;
   $js->canonical(1);
   my $json = $js->encode(\%hash);
   
   # Setup a new HTTP Request object.
   my $http = HTTP::Request->new('POST', $jsonUrl);
   
   $http->header('Content-Type' => 'application/json');
   $http->content($json);
   
   # Fire off the request.
   my $ua  = LWP::UserAgent->new;
   my $res = $ua->request($http);
   
   # Return the HTTP status and exit.
   my $result = sprintf("XBMC JSON-RPC $method: host:$jsonHost, user:$jsonUser, pass:<hidden>, Result: %s\n", $res->status_line);
   &log($result);
   if ($res->status_line !~ /200\s+OK/i) {

&notifyProwl('XBMC JSON: ' . $method,$res->status_line);

   }

}


sub notifyProwl() {

   if (defined($prowl->{enabled}) && $prowl->{enabled} == 1) {

my ($event,$msg) = @_; my $cmd = sprintf("perl %s -apikey='%s' -application='%s' -event='%s' -notification='%s'",$prowl->{script}, $prowl->{api_key}, $prowl->{app_name}, $event, $msg); my $res = `$cmd`; &log("Notify Prowl Event: $cmd\n"); &log("Notify: Prowl Result: $res\n");

   }

}

</source>

File history

Click on a date/time to view the file as it appeared at that time.

Date/TimeDimensionsUserComment
current23:38, 19 April 2013 (8 KB)Robertr (talk | contribs)

The following page uses this file: