package A2B::Tool; use A2B::Table::Element; use A2B; use Cwd; use strict; use vars qw(@ISA); @ISA = qw(A2B::Table::Element); use overload '""' => \&as_string; sub as_string { my ($self, $details) = @_; my $options = $details; my $all_args = $details >= 2; my $cmd; if ($options) { $cmd = $self->command_line; if (!$all_args) { my %already; $cmd = join ' ', $self->tool, grep { !$already{$_}++ } $cmd =~ /(\${.*?})/g; } } else { $cmd = $self->tool; } return $cmd; }; # logic: special options that could not simply be represented in the tools file sub logic { my ($self, $command, $ext) = @_; my $tool = $self->tool; # warn "logic: $tool $ext $command\n"; if ($tool eq "mplayer" || $tool eq "mencoder") { if ($ext eq "mov" || $ext eq "mp4" || $ext eq "3gp") { $command =~ s/\b$tool\b/$tool -demuxer mov/g; } } return $command; } sub find_files { my ($self, $type) = @_; if ($type eq "inode/directory") { my @dirs = `find . -maxdepth 1 -mindepth 1 -type d`; chomp for @dirs; if (@dirs == 1) { return map {"$_/"} @dirs; } else { return "./"; } } my @files = `find -L -type f | sort`; # XXX may be a bad thing, to use find - e.g. speed, portability # die "cant use `find'" unless @files; for (@files) { chomp; s|^\./||; } return @files; } sub command_line { my ($self) = @_; my $tool = $self->tool; my $command = $self->invoke; unless ($command =~ s/\$t\b/$tool/g) { $command = "$tool $command"; } my $nopts = $ENV{$tool."_nopts"}; if ($nopts) { if (!A2B->quiet && !A2B->a2b->{using_already}{"${tool}_nopts"}++) { warn "using ${tool}_nopts $nopts\n"; } for my $nopt (split /\s{2,}/, $nopts) { $command =~ s/\b\Q$nopt\E\b//g; } } $command = join " ", map { if (/^\w[\w-]*$/) { my $opts = $ENV{$_."_opts"}; if ($opts && !A2B->quiet && !A2B->a2b->{using_already}{"${tool}_opts"}++) { warn "using $tool ${_}_opts = $opts\n"; } $opts ? "$_ $opts" : $_; } else { $_ } } split /\s+/, $command; return $command; } sub convert { my ($self, @from_files) = @_; # we assume that we are in a safe, preferably empty box to do all this! my @files_before = $self->find_files(""); my $tool = $self->tool; my $command = $self->command_line; $command =~ /(\$i|\@i|\@,i)\b/ or die "database invalid for $tool: invoke field has no \$i, \@i or \@,i"; my $dir = getcwd; my $i = 1; $command =~ s{(^|\s)a2b(\s)}{my $x = "$1a2b -D=$i$2"; ++$i; $x}ge; my $extension = $self->to->extension; my $a2b = A2B->a2b; my $type = $a2b->identify_by_content_first($from_files[0]); my $ext = $a2b->type($type)->extension; $command =~ s/\$ix\b/$ext/g; $command =~ s/\$ox\b/$extension/g; $command = $self->logic($command, $ext); if ($command =~ /(\@i|\@,i)\b/) { my $out_file = "output.$extension"; -e $out_file and die "target `$out_file' already exists\n"; $command =~ s/\@i\b/join " ", map {"\Q$_\E"} @from_files/eg; $command =~ s/\@,i\b/join ",", map {"\Q$_\E"} @from_files/eg; $command =~ s/\$i\b/"\Q$from_files[0]\E"/eg; $command =~ s/\$o\b/"\Q$out_file\E"/eg; $self->do_command($command) or warn "command failed"; } else { for my $file (@from_files) { my $com = $command; $com =~ s/\$i\b/\Q$file\E/g; if ($com =~ /\$o\b/) { (my $out_file = $file) =~ s/(?:\.[^\.]*)?$/.$extension/; if ($out_file =~ m{://}) { $out_file =~ s{.*/}{}; if ($out_file =~ m{^\.} or $out_file eq "") { $out_file = "a2b-out$out_file"; } } -e $out_file and die "target `$out_file' already exists\n"; $com =~ s/\$o\b/\Q$out_file\E/g; } $self->do_command($com) or warn "command failed"; } } my @files = $self->find_files($self->to->type); my %files_before = map {$_, 1} @files_before; my @new_files; for (@files) { push @new_files, $_ unless $files_before{$_}; } return @new_files; } sub do_command { my ($self, $command) = @_; if (A2B->quiet <= 1) { print "$command\n"; } if (A2B->quiet) { $command = "exec >/dev/null 2>&1; $command"; } return not system "$command"; } 1