Skip to content

Commit

Permalink
major reimplementation
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrjones committed Apr 29, 2012
1 parent f2c3cb1 commit 1b7389e
Show file tree
Hide file tree
Showing 38 changed files with 1,554 additions and 561 deletions.
6 changes: 5 additions & 1 deletion README.markdown
Expand Up @@ -9,4 +9,8 @@ INSTALL
------- -------


curl -L http://cpanmin.us | perl - --sudo App::cpanminus curl -L http://cpanmin.us | perl - --sudo App::cpanminus
cpanm App::MP4Meta cpanm App::MP4Meta

TODO
----
Move from IMDB::Film to WebService::IMDB
1 change: 0 additions & 1 deletion dist.ini
Expand Up @@ -2,6 +2,5 @@ name = App-MP4Meta
author = Andrew Jones <andrew@arjones.co.uk> author = Andrew Jones <andrew@arjones.co.uk>
license = Perl_5 license = Perl_5
copyright_holder = Andrew Jones copyright_holder = Andrew Jones
copyright_year = 2011


[@ARJONES] [@ARJONES]
127 changes: 28 additions & 99 deletions lib/App/MP4Meta/Base.pm
Expand Up @@ -6,11 +6,8 @@ package App::MP4Meta::Base;


# ABSTRACT: Base class. Contains common functionality. # ABSTRACT: Base class. Contains common functionality.


use File::Temp '0.22', (); use Module::Load ();
use File::Copy; use Try::Tiny;
use IMDB::Film '0.50';
require LWP::UserAgent;

use AtomicParsley::Command; use AtomicParsley::Command;


sub new { sub new {
Expand All @@ -21,22 +18,34 @@ sub new {
# the path to AtomicParsley # the path to AtomicParsley
$self->{'ap'} = AtomicParsley::Command->new( { ap => $args->{'ap'} } ); $self->{'ap'} = AtomicParsley::Command->new( { ap => $args->{'ap'} } );


# LWP::UserAgent
$self->{'ua'} = LWP::UserAgent->new;

# if true, replace file # if true, replace file
$self->{'noreplace'} = $args->{'noreplace'}; $self->{'noreplace'} = $args->{'noreplace'};


# stores tmp files which we clean up later # if true, print verbosely
$self->{'tmp_files'} = (); $self->{'verbose'} = $args->{'verbose'};


# cache for IMDB objects # internet sources
$self->{'imdb_cache'} = {}; $self->{'sources'} = $args->{'sources'};


# cache for cover images # common attributes for a media file
$self->{'cover_img_cache'} = {}; $self->{'genre'} = $args->{'genre'};
$self->{'title'} = $args->{'title'};
$self->{'coverfile'} = $args->{'coverfile'};


bless( $self, $class ); bless( $self, $class );

# create sources now so they are in scope for as long as we are
$self->{'sources_objects'} = [];
for my $source ( @{ $self->{'sources'} } ) {
try {
push( @{ $self->{'sources_objects'} },
$self->_new_source($source) );
}
catch {
say STDERR "could not load source: $_";
};
}

return $self; return $self;
} }


Expand All @@ -57,70 +66,6 @@ sub _write_tags {
return; return;
} }


# Make a query to imdb
# Returns undef if we couldn't find the query.
# Returns an IMDB::Film object.
sub _query_imdb {
my ( $self, $title, $year ) = @_;

# first, check the cache
my $key = $title;
$key .= $year if $year;
if ( defined $self->{'imdb_cache'}->{$key} ) {
return $self->{'imdb_cache'}->{$key};
}

my $imdb = IMDB::Film->new( crit => $title, year => $year );

if ( $imdb->status ) {

# cache IMDB object for future queries
$self->{'imdb_cache'}->{$key} = $imdb;

return $imdb;
}
return;
}

# Gets the cover image and stores in a tmp file
sub _get_cover_image {
my ( $self, $url ) = @_;

return unless $url;

if ( $url =~ m/\.(jpg|png)$/ ) {
my $suffix = $1;

# first, check the cache
if ( defined $self->{'cover_img_cache'}->{$url} ) {
return $self->{'cover_img_cache'}->{$url};
}

# get the image
my $response = $self->{ua}->get($url);
if ( !$response->is_success ) {
return;
}

# create a temp file
my $tmp = $self->_get_tempfile($suffix);

# write img to temp file
binmode $tmp;
print $tmp $response->decoded_content;

# cache temp file for future queries
$self->{'cover_img_cache'}->{$url} = $tmp->filename;

return $tmp->filename;
}
else {

# can't use cover
return;
}
}

# Converts 'THE_OFFICE' to 'The Office' # Converts 'THE_OFFICE' to 'The Office'
sub _clean_title { sub _clean_title {
my ( $self, $title ) = @_; my ( $self, $title ) = @_;
Expand All @@ -133,27 +78,11 @@ sub _clean_title {
return $title; return $title;
} }


# Returns a File::Temp object sub _new_source {
sub _get_tempfile { my ( $self, $source ) = @_;
my ( $self, $suffix ) = @_; my $module = 'App::MP4Meta::Source::' . $source;

Module::Load::load($module);
$suffix = $suffix // 'tmp'; return $module->new;

my $tmp = File::Temp->new( UNLINK => 0, SUFFIX => ".$suffix" );

# save the tmp file for later
push @{ $self->{tmp_files} }, $tmp->filename;

return $tmp;
}

sub DESTROY {
my $self = shift;

# remove all tmp files
for my $f ( @{ $self->{tmp_files} } ) {
unlink $f;
}
} }


1; 1;
Expand Down
38 changes: 35 additions & 3 deletions lib/App/MP4Meta/Command/film.pm
Expand Up @@ -8,6 +8,8 @@ package App::MP4Meta::Command::film;


use App::MP4Meta -command; use App::MP4Meta -command;


use Try::Tiny;

=head1 SYNOPSIS =head1 SYNOPSIS
mp4meta film PULP_FICTION.mp4 "The Truman Show.m4v" mp4meta film PULP_FICTION.mp4 "The Truman Show.m4v"
Expand All @@ -30,7 +32,16 @@ sub abstract {


sub opt_spec { sub opt_spec {
return ( return (
[ "genre=s", "The genre of the TV Show" ],
[ "coverfile=s", "The location of the cover image" ],
[ "sources=s@", "The sources to search", { default => [qw/IMDB/] } ],
[ "title=s", "The title of the Film" ],
[ "noreplace", "Don't replace the file - creates a temp file instead" ], [ "noreplace", "Don't replace the file - creates a temp file instead" ],
[ "verbose", "Print verbosely" ],
[
"withoutany",
"Continue to process even if we can not find any information on the internet"
],
); );
} }


Expand All @@ -57,12 +68,33 @@ sub execute {
my ( $self, $opt, $args ) = @_; my ( $self, $opt, $args ) = @_;


require App::MP4Meta::Film; require App::MP4Meta::Film;
my $film = App::MP4Meta::Film->new( { noreplace => $opt->{noreplace}, } ); my $film = App::MP4Meta::Film->new(
{
noreplace => $opt->{noreplace},
genre => $opt->{genre},
sources => $opt->{sources},
title => $opt->{title},
coverfile => $opt->{coverfile},
verbose => $opt->{verbose},
continue_without_any => $opt->{withoutany},
}
);


for my $file (@$args) { for my $file (@$args) {
my $error = $film->apply_meta($file); say "processing $file" if $opt->{verbose};
say $error if $error; my $error;
try {
$error = $film->apply_meta($file);
}
catch {
$error = "Error applying meta to $file: $_";
}
finally {
say $error if $error;
};
} }

say 'done' if $opt->{verbose};
} }


1; 1;
56 changes: 44 additions & 12 deletions lib/App/MP4Meta/Command/tv.pm
Expand Up @@ -8,17 +8,23 @@ package App::MP4Meta::Command::tv;


use App::MP4Meta -command; use App::MP4Meta -command;


use Try::Tiny;

#use Term::ProgressBar::Simple;

=head1 SYNOPSIS =head1 SYNOPSIS
mp4meta tv THE_MIGHTY_BOOSH_S1E1.m4v THE_MIGHTY_BOOSH_S1E2.m4v mp4meta tv THE_MIGHTY_BOOSH_S1E1.m4v THE_MIGHTY_BOOSH_S1E2.m4v
mp4meta film --noreplace 24.S01E01.m4v mp4meta tv --noreplace 24.S01E01.m4v
=head1 DESCRIPTION
This command applies metadata to one or more TV Series. It parses the filename in order to get the shows title and its season and episode number. This command applies metadata to one or more TV Series. It parses the filename in order to get the shows title and its season and episode number.
It gets the TV Series metadata by querying the IMDB. It then uses AtomicParsley to apply the metadata to the file. It gets the TV Series metadata by querying various sources (see below). It then uses AtomicParsley to apply the metadata to the file.
If it can not find the TV Series on the IMDB, by default it will not apply any metadata. If you wan't it to apply what it can, pass the C<--withoutimdb> option. If it can not find the TV Series on any of the sources, by default it will not apply any metadata. If you wan't it to apply what it can, pass the C<--withoutany> option.
By default, it will apply the metadata to the existing file. If you want it to write to a temporary file and leave the existing file untouched, provide the C<--noreplace> option. By default, it will apply the metadata to the existing file. If you want it to write to a temporary file and leave the existing file untouched, provide the C<--noreplace> option.
Expand All @@ -34,10 +40,19 @@ sub opt_spec {
return ( return (
[ "genre=s", "The genre of the TV Show" ], [ "genre=s", "The genre of the TV Show" ],
[ "coverfile=s", "The location of the cover image" ], [ "coverfile=s", "The location of the cover image" ],
[ "title=s", "The title of the TV Show" ], [
"sources=s@",
"The sources to search",
{ default => [qw/TVDB IMDB/] }
],
[ "title=s", "The title of the TV Show" ],
[ "series=s", "The series number" ],
[ "episode=s", "The episode number" ],
[ "noreplace", "Don't replace the file - creates a temp file instead" ], [ "noreplace", "Don't replace the file - creates a temp file instead" ],
[ "verbose", "Print verbosely" ],
[ [
"withoutimdb", "Continue to process even if we can not find on IMDB" "withoutany",
"Continue to process even if we can not find any information on the internet"
], ],
); );
} }
Expand All @@ -48,6 +63,8 @@ sub validate_args {
# we need at least one file to work with # we need at least one file to work with
$self->usage_error("too few arguments") unless @$args; $self->usage_error("too few arguments") unless @$args;


# TODO: check we have a source

# check each file # check each file
for my $f (@$args) { for my $f (@$args) {
unless ( -e $f ) { unless ( -e $f ) {
Expand All @@ -67,18 +84,33 @@ sub execute {
require App::MP4Meta::TV; require App::MP4Meta::TV;
my $tv = App::MP4Meta::TV->new( my $tv = App::MP4Meta::TV->new(
{ {
noreplace => $opt->{noreplace}, noreplace => $opt->{noreplace},
genre => $opt->{genre}, genre => $opt->{genre},
title => $opt->{title}, sources => $opt->{sources},
coverfile => $opt->{coverfile}, title => $opt->{title},
without_imdb => $opt->{withoutimdb}, coverfile => $opt->{coverfile},
verbose => $opt->{verbose},
continue_without_any => $opt->{withoutany},
} }
); );


say sprintf( 'processing %d files', scalar @$args ) if $opt->{verbose};

for my $file (@$args) { for my $file (@$args) {
my $error = $tv->apply_meta($file); say "processing $file" if $opt->{verbose};
say $error if $error; my $error;
try {
$error = $tv->apply_meta($file);
}
catch {
$error = "Error applying meta to $file: $_";
}
finally {
say $error if $error;
};
} }

say 'done' if $opt->{verbose};
} }


1; 1;

0 comments on commit 1b7389e

Please sign in to comment.