App-MP4Meta

 view release on metacpan or  search on metacpan

lib/App/MP4Meta/Base.pm  view on Meta::CPAN

use 5.010;
use strict;
use warnings;

package App::MP4Meta::Base;
{
  $App::MP4Meta::Base::VERSION = '1.153340';
}

# ABSTRACT: Base class. Contains common functionality.

use Module::Load ();
use Try::Tiny;
use AtomicParsley::Command;

sub new {
    my $class = shift;
    my $args  = shift;
    my $self  = {};

    # file suffixes we support
    my @suffixes = qw/mp4 m4a m4p m4v m4b/;
    $self->{suffixes} = \@suffixes;

    # the path to AtomicParsley
    $self->{'ap'} = AtomicParsley::Command->new( { ap => $args->{'ap'} } );

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

    # if true, add to itunes
    $self->{'itunes'} = $args->{'itunes'};

    # if true, print verbosely
    $self->{'verbose'} = $args->{'verbose'};

    # internet sources
    $self->{'sources'} = $args->{'sources'};

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

    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;
}

# Calls AtomicParsley and writes the tags to the file
sub _write_tags {
    my ( $self, $path, $tags ) = @_;

    my $tempfile = $self->{ap}->write_tags( $path, $tags, !$self->{noreplace} );

    if ( !$self->{ap}->{success} ) {
        return $self->{ap}->{'stdout_buf'}[0] // $self->{ap}->{'full_buf'}[0];
    }

    if ( !$tempfile ) {
        return "Error writing to file";
    }

    return;
}

sub _strip_suffix {
    my ( $self, $file ) = @_;

    my $regex = sprintf( '\.(%s)$', join( '|', @{ $self->{suffixes} } ) );
    $file =~ s/$regex//;

    return $file;
}

# Converts 'THE_OFFICE' to 'The Office'
sub _clean_title {
    my ( $self, $title ) = @_;

    $title =~ s/(-|_)/ /g;
    $title =~ s/(?<=\w)\.(?=\w)/ /g;
    $title = lc($title);
    $title = join ' ', map( { ucfirst() } split /\s/, $title );

    return $title;
}

# adds file to itunes
sub _add_to_itunes {
    my ( $self, $path ) = @_;

    return unless $self->{'itunes'};

    unless ( $^O eq 'darwin' ) {
        say STDERR 'can only add to iTunes on Mac OSX';
        return 1;
    }

    $path =~ s!/!:!g;

    my $cmd = sprintf(
"osascript -e 'tell application \"iTunes\" to add file \"%s\" to playlist \"Library\" of source \"Library\"'",
        $path );

    my $result = `$cmd`;
    if ($?) {
        say STDERR "error adding to iTunes: $result";
        return 1;
    }
    if ( $self->{'verbose'} and $result ) {
        say $result;
    }

    return;
}

# load a module as a new source
sub _new_source {
    my ( $self, $source ) = @_;
    my $module = 'App::MP4Meta::Source::' . $source;
    Module::Load::load($module);
    return $module->new;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

App::MP4Meta::Base - Base class. Contains common functionality.

=head1 VERSION

version 1.153340

=head1 SYNOPSIS

  my $base = App::MP4Meta::Base->new( ap => 'path/to/ap' );

=head1 METHODS

=head2 new( %args )

Create new object. Takes the following arguments:

=over 4

=item *

ap - Path to the AtomicParsley command. Optional.

=item *

noreplace - If true, do not replace file, but save to temp instead

=item *

verbose - If true, print verbosely

=item *

sources - A list of sources to load

=item *

genre - Define a genre for the media file



( run in 2.058 seconds using v1.01-cache-2.11-cpan-d7a12ab2c7f )