Projects
Multimedia
pacpl
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 7
View file
pacpl.changes
Changed
@@ -1,4 +1,25 @@ ------------------------------------------------------------------- +Tue Oct 9 21:49:13 UTC 2018 - aloisio@gmx.com + +- Update to version 6.1.0 + * fixed kdialog ouput directory space issue + thanks to Jeremy Rehbaum (JRehbaum@juno.com) + * incorporated patches from Paulo Marcel Coelho Aragão + + fix blank WMA tags + + fix decoder not working for WMA + + fix overwrite check to act more appropriately + + fix DEFOPTS = 0 to work as intended + + added alac-decoder support for .mp4 files + + added .gitignore + + fixed handling of m4a (AAC) codec handling + * incoporated patches from Reuben Thomas (rrt@sc3d.org) + + fix installaton under different prefix and/or DESTDIR + + fix hardwired pathes in pacpl + * note: with above patches pacpl is now pacpl.in which will + be renamed after configure + * updated Makefile.am to remove pacpl with "make distclean" + +------------------------------------------------------------------- Sat Mar 10 19:22:40 UTC 2018 - aloisio@gmx.com - Update to version 5.1.0 (see ChangeLog)
View file
pacpl.spec
Changed
@@ -18,7 +18,7 @@ Name: pacpl -Version: 5.1.0 +Version: 6.1.0 Release: 0 Summary: A tool to convert audio files between many different types License: GPL-3.0 @@ -115,6 +115,7 @@ sed -e '/^Icon/cIcon=%{name}' -e '/^Exec/cExec=PACPL-Konvert' \ -i plugins/kde/pacpl.desktop sed -e '/EXTRA/d' -i Makefile.in +cp ChangeLog.txt ChangeLog %build %configure
View file
pacpl-5.1.0.tar.gz/ChangeLog
Deleted
@@ -1,259 +0,0 @@ -================= -**** 5.1.0 **** -================= - -* updated version to 5.1.0 - -+ added patches directory. below updates and incorporations are included. - -% incorporated the following patches Matteo Cypriani (mcy@lm7.fr) - - typos - - configure exit - - enforce outdir when preserve is utilized - - multiple input source decode - -* updated README.module documentation thanks to Cristian Greco <cristian.debian@gmail.com> - -================= -**** 5.0.2 **** -================ - -%fixed regex to detect directory names with spaces thanks to Dmitry Klimov - -================= -**** 5.0.1 **** -================= - -01-04-2014 - -* updated ogg vorbis & spx tags to use TRACKNUMBER instead of TRACK - -% fixed coverting to "wma, ra, & mmf" thanks to bug report by Timothy E. Harris -% fixed missing semicolon bug in nemo/nautilus/thunar script -% fixed overwrite message to show output file, not source. -% fixed Thunar PACPL-Konvert script thanks to Timothy E. Harris - -- removed support for .src and .ram extenions (no longer supported) - -================= -**** 5.0.0 **** -================= - -11-1-2013 - -** 5.0.0 Official Stable Release ** - -* minor code optimizations/changes -* updated README program description - -% fixed amr encoding -% fixed mmf, ra, wma, other codecs supported by ffmpeg - -+ added a few obscure audio formats supported by sox/sndfile-convert including: - rf64 (sndfile) 8svx amb dat dvms f32 f64 fssd gsrt hcom txw vms - -10-12-2013 - -% fixed encoding to .mp4/.m4a using ffmpeg/avconv -% fixed configure error when enabling nemo - -- removed use of Ogg::Vorbis::Header. tag writing for oga and ogg - is now done via vorbiscomment (part of vorbis-tools) - -+ added oga extension for ogg vorbis audio -+ added ogv audio extract support -+ added webm audio extract support - -* updated oga/ogg tag reading to use Audio::Scan - -10-10-2013 - -% changed the kde plugin to popup a combobox for selecting the - output format to keep things somewhat consistent with the rest of - the platforms. - -% flip-flopped on the use 5.18.0 statement. seems other (*buntu*) - distros consider that release "experimental". worked around it - with a simple: - - no if $ >= 5.018, warnings => "experimental::smartmatch"; - -% re-wrote preserve directory function. it actually works again... - -+ added parallel processing. about time we put those cores to use! -+ added use of Parallel::ForkManager module you can install it via: - 1) perl -MCPAN -e 'install Parallel::ForkManager' - 2) sudo apt-get install libparallel-forkmanager-perl - -+ added option -j,--jobs option to specify concurrent jobs to process -+ added JOBS varible in pacpl.conf. default is set to 4 -+ added jobs description to locale files (need translations!) - -+ added support for the Thunar file manager (tested under Xbuntu 13.04) - see plugins/gnome/thunar/INSTALL for more information - -10-1-2013 - -+ added the use 5.18.0; requriement to pacpl. to those - using earlier versions, you can remove this line but YMMV. - -% fixed configure script to work properly when different - gui dialog / file managers are installed - -- removed support for lpac/pac (obsolete) -- removed support for gogo (obsolete) - -9-30-2013 - -+ added GNOMEDIR variable to the Makefile in case your gnome - installation is not located in the default /usr directory - -* updated directory structure for plugins -* updated configure script to use the following: - - --enable-kde (for the KDE service menu) - --enable-nautilus (for the nautilus script) - --enable-nemo (for the nemo action script) - - the kde and nautilus/nemo options cannot be used together. - you can however use both nemo and nautilus (assuming you have - both installed) - - by default none of the options are enabled - -- removed install.sh & README for nemo script directory - -9-24-2013 - -# bumped version to 5.0.0. with the amount of time - passed since the last release and all the feature - additons/changes I feel its warranted: For now - we're still in the nightly/pre-release testing stage - -+ GNOME Support Added: - -Note: Tested and tailored for 13.04 Unity, it will however - work on earlier versions and other debian based distros - using the Gnome desktop which have zenity & notify-send - installed - -+ added PACPL-Convert (Nautilus/Nemo) script - -+ added support for running the script through Nemo on Linux Mint - or other distributions that use that file manager - tested on Linux Mint 15 "Olivia" Cinnamon (64-bit) - -- removed use of Audio::WMA -- removed use of MP4::Info -- removed use of Audio::Musepack -- removed use of Audio::APETags - - the above four modules have been replaced by Audio::Scan for - reading the tags from the various formats including flac. - -+ added use of perl module Audio::Scan -+ added support for reading .ape tags -+ added support for TAK audio format (decode only) -+ added cdparanoia to mod-install-ubuntu.sh as part of the basic tools -+ added new string to .po files (gui_outdir) - **translators needed** - -% fixed changed FLAC tag DESCRIPTION to COMMENT -% fixed FLAC upper/lower case issue by reading tags with Audio::Scan -% fixed cd ripping - $out_dir should be $outdir in order run correctly -% fixed encoding to .mp4 & .m4a. Had same issue as Musepack files. - -* updated configure for gnome & kde - neither is installed by default. - you will need to --enable-kde or --enable-gnome if you would like to - have eiher of the plugins installed. - -* updated extra/mod-install*.sh to reflect module changes -* updated %run (put all codedcs in alphabetical order) a little house cleaning.. -* updated default bitrate in pacpl.conf to 192kbps for formats that support it -* updated pacpl.conf - changed default disc device to /dev/dvd - & modified all lang/*.po files to reflect change. - -- removed RAM from codecs.conf (has no encoder) - -9-21-2013 - -+ added --enable-kde (adds Konqueror/Dolphin pacpl.desktop) -+ added --enable-gnome (nautilus script in the works) ***not included...yet*** - -+ added support for amr audio format -+ added support for 3gp audio format -+ added support for 3g2 audio format - -= Note: The above three formats only work if your version of ffmpeg/avconv supports them. - see extra/ffmpeg-conf.sh / extra/libav-conf.sh (requires libopencore-amr) - -% fixed spacing error in codecs.conf for DTS - -- removed --enable-konqueror & --enable-dolphin options - -9-18-2013 - -+ added ffmpeg-conf.sh and libav-conf.sh to extra/ dir. - this shows what libs and options are needed for full support for pacpl -+ added support for libav (avconv) encoder/decoder - ffmpeg fork -+ added ffmpeg/avconv support to various formats as available encoder/decoder -+ added support for adts audio format - -% fixed mpc tagging using the new SV7/SV8 releases. (options have to come BEFORE - the input and output file) -% fixed all ffmpeg encode instances to apply $eopts (user options) when - --defopts=0 to the output file as opposed to the input. - -* updated codecs.conf to include new formats that can be configured -* updated extra/README.extra -* update Makefile.am - * use wildcard * for LANG_MODS instead of listing them individually - * remove -t flag for $(INSTALL_DATA) - -9-14-2013 - -* updated extra/mod-install.sh (removed Switch module) -* updated extra/mod-install-kubuntu.sh (renamed to mod-install-ubuntu.sh) - - removed liboggvorbis-perl - + added various required modules/libs for Ogg::Vorbis::Header - + added section to install basic encoders/decoders - + added section to fix apt repository /var/lib/apt/lists - to be able to install restricted-extras package. - = tested in both Ubuntu & Kubuntu 13.04 - - Note: When running the script choose the default yes for all prompts - -9-12-2013 - -+ added support for lowercase tags when writing/reading flac metadata -+ added git repository (https://github.com/vorzox/pacpl) -+ added support for dcaenc (dts) encoder (requires multi-channel wav as input) -+ added support for dts (default encoder/decoder=ffmpeg) - -9-10-2013 - -+ added support for mp3HD audio format -+ added support for aften ac3 encoder -+ added support for twolame mp2 encoder -+ added support for opus audio format -+ added support for off (OptimumFrog - Float) audio format -+ added support for TwinVQ (vqf) audio format (decode only) -+ added Greek/Hellenic translation thanks to Evangelos Apostolakos -+ added required module CDDB (this goes along with CDDB_get) - -- removed amarok support -- removed pacpl gui KMDR -- removed support for d3lphin (obsolete) -- removed --enable-all configuration option (obsolete) -- removed deprecated use of Switch in favor of given-when-default - -* updated README to include new/updated URLs for applications -* updated website pacpl.sourceforge.net (vorzox.wix.com/pacpl) -* update Makefile.am and configure.ac to comply with current standards -* updated slack-desc: changes layout and includes new formats - -% fixed ffmpeg ac3 encoding. specified bitrate was in bits not kilobits -% fixed ffmpeg tag handling...again...thanks to Dave Allen Barker Jr. -% fixed pacpl.desktop to include missing formats -% fixed return 1 when encoding fails -% fixed added MP3::Tag->config(write_v24 => 'YES') to allow updating & - modifying of newer ID3v2 tags.
View file
pacpl-5.1.0.tar.gz/pacpl
Deleted
@@ -1,4034 +0,0 @@ -#!/usr/bin/perl -# -# Perl Audio Converter -# -# Copyright (C) 2005-2017 Philip Lyons (vorzox@gmail.com) -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -use strict; -use warnings; -use Getopt::Long; -use File::Basename; -use File::Find; -use File::Spec::Functions qw(rel2abs); -use Parallel::ForkManager; - -use feature qw(switch say); - -no if $ >= 5.018, warnings => "experimental::smartmatch"; - -# Tagging modules -use MP3::Tag; -use Audio::FLAC::Header; -use Audio::Scan; - -# CDDB module -use CDDB_get qw(get_cddb); - -# non-encoder/decoder related options -my -( - $to, - $recursive, - $preserve, - $rip, - $help, - $longhelp, - $verbose, - $verinfo, - $dryrun, - $delete, - $keep, - $overwrite, - $formats, - $topdir, - $only, - $first_run, - - @file, - @dir, - - %run, - %lang, -); - -my $silent = "> /dev/null 2>&1"; - -# tagging options -my -( - $title, - $track, - $artist, - $album, - $comment, - $year, - $genre, - $taginfo, -); - -# name, version & icon information -my $name = "Perl Audio Converter"; -my $version = "5.1.0"; -my $icon_path = "/etc/pacpl/pacpl.png"; - -# If these options are toggled, messages/errors will be displayed -# via kdialog or zenity/notify-send (depending on environment) -my ($gui, $kde, $gnome); - -# Debugging (for developer use only) -my $debug = 0; - -# default configuration. -my %config = ( - - IMPORTM => 0, - JOBS => 4, - - DEFOPTS => 1, - EOPTS => '', - DOPTS => '', - NOPTS => '', - - BITRATE => 128, - FREQ => 44100, - CHANNELS => 2, - EFFECT => '', - FCOMP => 2, - PCOMP => 3, - ACOMP => 3000, - OGGQUAL => 3, - SPXQUAL => 8, - AACQUAL => 100, - MPCQUAL => 'radio', - OFMODE => 'normal', - OFOPT => 'fast', - BRATIO => 2, - BQUANL => 1.0, - BPSIZE => 128, - - USE_CDDB => 1, - CDDB_HOST => 'freedb.freedb.org', - CDDB_PORT => 8880, - CDDB_MODE => 'cddb', - CDDB_INPUT => 1, - DEVICE => '/dev/dvd', - NSCHEME => '%ar - %ti', - - ZEN_DIR => 1, - ZEN_OPTS => 1, - KDE_DIR => 1, - KDE_OPTS => 1, - - ); - -# location of configuration file -my $conf_path = "/etc/pacpl"; -my $po_dir = "/usr/share/pacpl/locale"; -my $mod_dir = "$conf_path/modules"; - -my $conf_file; - -# load the appropriate locale file -load_lang(); - -# try to load configuration file in this order... -my @conf_locations = ( - "$ENV{HOME}/.pacplrc", # Local - "$conf_path/pacpl.conf", # Global - "$ENV{PWD}/pacpl.conf", # Current Directory - ); - -# try to load conf file from one of the above locations -foreach my $i (@conf_locations) { - if (not $conf_file and -e $i) { - $conf_file = $i; - say "$lang{debug} $lang{loaded_config} $conf_file" if $debug == 1; - } -} - -say "$lang{no_config}" if not $conf_file; - -# open config file. -if ($conf_file and -e $conf_file) { - - open(CONF, "$conf_file") or die "$lang{opening_file} $conf_file - $!\n"; - - my @conf_opts = <CONF>; - @conf_opts = grep(!/^#|^$/, @conf_opts); - - close(CONF); - - # now read config file options and change default values accordingly. - foreach (@conf_opts) { - chomp; - my ($k, $v) = split(/\s*=\s*/); - $config{$k} = $v if exists($config{$k}) and $v; - say "$lang{debug} $k = $v" if $debug == 1 and exists($config{$k}); - } -} - -my $codecs_conf = "$conf_path/codecs.conf"; - -# set default encoders/decoders -sub load_codecs { - - open(CODECS, "$codecs_conf") or die "$lang{opening_file} $codecs_conf - $!\n"; - - my @codecs = <CODECS>; - @codecs = grep(!/^$|^#/, @codecs); - @codecs = grep(s/^\s*|\s*$//, @codecs); - - close(CODECS); - - foreach (@codecs) { - - chomp; - my ($k, $v) = split(/\s*=\s*/); - my ($e, $d) = split(/,/, $v); - - $k =~ tr/A-Z/a-z/; - - $run{$k}{DEFAULT_ENCODER} = $e if (exists($run{$k}{DEFAULT_ENCODER})); - $run{$k}{DEFAULT_DECODER} = $d if (exists($run{$k}{DEFAULT_DECODER})); - } -} - -# load po file and store in %lang hash -sub load_lang { - - my $po = "$po_dir/$ENV{LANG}.po"; - $po =~ s/\.UTF-8//i if $po =~ /UTF-8/i; - $po =~ s/\.utf8//i if $po =~ /utf8/i; - $po =~ s/_\w+// if not -e $po; - $po = "$po_dir/en_US.po" if not -e $po; - - open(LANG, "< $po") or die "error: could not open - $po\n$!\n"; - - my @data = <LANG>; - @data = grep(!/^#|^$/, @data); - - close(LANG); - - foreach (@data) { - chomp; - s/=/__EQ__/; - my ($k, $v) = split(/\s*__EQ__\s*/, $_); - $lang{$k} = $v; - } - -} - -my $banner = 1; - -# print error messages -sub perror { - my ($key, $msg) = @_; - say "$name - $version\n"; - say "$lang{error}: $lang{$key} $msg" . "\n"; - system("kdialog --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $kde; - system("zenity --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $gnome; - die "$lang{seek_help}\n"; -} - -# print notices/warnings -sub pnotice { - - my ($key, $msg, $nm) = @_; - - say "$name - $version\n" if $banner == 1; - print "$lang{$key} $msg"; - say '' if $nm == 1; - say "\n" if $nm == 2; - - $banner = 0; -} - -# defaults for user variables. -my $outfile; -my $outdir; -my $defopts = $config{DEFOPTS}; -my $eopts = $config{EOPTS}; -my $dopts = $config{DOPTS}; -my $nopts = $config{NOPTS}; -my $normalize = $config{NOPTS}; -my $bitrate = $config{BITRATE}; -my $freq = $config{FREQ}; -my $channels = $config{CHANNELS}; -my $effect = $config{EFFECT}; -my $fcomp = $config{FCOMP}; -my $acomp = $config{ACOMP}; -my $oggqual = $config{OGGQUAL}; -my $spxqual = $config{SPXQUAL}; -my $aacqual = $config{AACQUAL}; -my $mpcqual = $config{MPCQUAL}; -my $ofmode = $config{OFMODE}; -my $ofopt = $config{OFOPT}; -my $bratio = $config{BRATIO}; -my $bquanl = $config{BQUANL}; -my $bpsize = $config{BPSIZE}; - -my $cdinfo; -my $nocddb; -my $noinput; -my $device = $config{DEVICE}; -my $nscheme = $config{NSCHEME}; -my $my_encoder; -my $my_decoder; -my $encoder; -my $decoder; - -my $jobs = $config{JOBS}; - -# command line options -GetOptions -( - 't|to=s' => \$to, - 'r|recursive' => \$recursive, - 'p|preserve' => \$preserve, - 'h|help' => \$help, - 'l|longhelp' => \$longhelp, - 'v|verbose' => \$verbose, - 'f|formats' => \$formats, - 'o|only=s' => \$only, - 'k|keep' => \$keep, - 'j|jobs=n' => \$jobs, - - 'taginfo' => \$taginfo, - - 'version' => \$verinfo, - 'dryrun' => \$dryrun, - 'delete' => \$delete, - 'overwrite' => \$overwrite, - 'normalize' => \$normalize, - 'encoder=s' => \$my_encoder, - 'decoder=s' => \$my_decoder, - - 'title=s' => \$title, - 'track=n' => \$track, - 'artist=s' => \$artist, - 'album=s' => \$album, - 'comment=s' => \$comment, - 'year=n' => \$year, - 'genre=s' => \$genre, - - 'gui' => \$gui, - 'kde' => \$kde, - 'gnome' => \$gnome, - - 'eopts=s' => \$eopts, - 'dopts=s' => \$dopts, - 'defopts=n' => \$defopts, - 'nopts=s' => \$nopts, - 'outfile=s' => \$outfile, - 'outdir=s' => \$outdir, - - 'bitrate=n' => \$bitrate, - 'freq=n' => \$freq, - 'channels=n' => \$channels, - 'effect=s' => \$effect, - 'fcomp=n' => \$fcomp, - 'acomp=n' => \$acomp, - 'oggqual=n' => \$oggqual, - 'spxqual=n' => \$spxqual, - 'aacqual=n' => \$aacqual, - 'mpcqual=s' => \$mpcqual, - 'ofmode=s' => \$ofmode, - 'ofopt=s' => \$ofopt, - 'bratio=n' => \$bratio, - 'bquanl=n' => \$bquanl, - 'bpsize=n' => \$bpsize, - - 'rip=s' => \$rip, - 'nocddb' => \$nocddb, - 'noinput' => \$noinput, - 'device=s' => \$device, - 'nscheme=s' => \$nscheme, - 'cdinfo' => \$cdinfo, -); - -if (defined($preserve) && !defined($outdir)) { - die "You must specify --outdir when you use --preserve option. See man page.\n"; -} - -$silent = '' if $verbose; - -my $opts; -my $total_converted = 0; -my $total_failed = 0; - -# Initialize the fork manager with a count set through pacpl.conf or via the command line -my $pm = Parallel::ForkManager->new($jobs); - -# conversion options. when adding a new format, -# wild card %i = input file and %o = output file -%run = ( - - '3g2' => { - - DEFAULT_ENCODER => 'ffmpeg', - DEFAULT_DECODER => 'ffmpeg', - - ENCODER => { - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = "-ar 8000 -ac 1" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { NONE => 0, }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ar 8000 -ac 1" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { NONE => 0, }, - }, - - }, - - DECODER => { - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "-y -i %o $dopts %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "-y -i %o %dopts %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - - }, - - '3gp' => { - - DEFAULT_ENCODER => 'ffmpeg', - DEFAULT_DECODER => 'ffmpeg', - - ENCODER => { - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = "-ar 8000 -ac 1" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { NONE => 0, }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ar 8000 -ac 1" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { NONE => 0, }, - }, - - }, - - DECODER => { - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "-y -i %o $dopts %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "-y -i %o %dopts %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - - }, - - aac => { - - DEFAULT_ENCODER => "faac", - DEFAULT_DECODER => "faad", - - ENCODER => { - faac => { - NAME => "faac", - ESTR => sub { - $opts = "-q $aacqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i -o %o" - }, - PROMPT => { AACQUAL => 1 }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 1, - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - faad => { - NAME => "faad", - DSTR => sub { "$dopts -o %i %o" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - ac3 => { - - DEFAULT_ENCODER => "ffmpeg", - DEFAULT_DECODER => "ffmpeg", - - ENCODER => { - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => "avconv", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - aften => { - NAME => "aften", - ESTR => sub { - $opts = "-v 1 -q $bitrate -2" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - - PROMPT => { - BITRATE => 1, - }, - }, - - }, - - DECODER => { - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => "avconv", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - adts => { - - DEFAULT_ENCODER => 'ffmpeg', - DEFAULT_DECODER => 'ffmpeg', - - ENCODER => { - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $opts $eopts -strict -2 %o" - }, - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $opts $eopts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - ffmpeg => { - NAME => 'ffmpeg', - DSTR => "$dopts -y -i %i %o", - }, - - avconv => { - NAME => 'avconv', - DSTR => "$dopts -y -i %i %o", - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - ape => { - - DEFAULT_ENCODER => "mac", - DEFAULT_DECODER => "mac", - - ENCODER => { - mac => { - NAME => "mac", - ESTR => sub { - $opts = "-c$acomp" if $defopts == 1; - $opts = '' if $defopts == 0; - "%i %o $opts $eopts" - }, - - PROMPT => { ACOMP => 1 }, - }, - }, - - DECODER => { - mac => { - NAME => "mac", - DSTR => sub { "%i %o -d $dopts" }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "-y -i %i %dopts %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "-y -i %i $dopts %o" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 0, - MODULE => "Audio::Scan", - }, - }, - - amr => { - - DEFAULT_ENCODER => "ffmpeg", - DEFAULT_DECODER => "ffmpeg", - - ENCODER => { - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ar 8000 -ac 1" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { NONE => 0, }, - }, - - avconv => { - NAME => "avconv", - ESTR => sub { - $opts = "-ar 8000 -ac 1" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { NONE => 0, }, - }, - - }, - - DECODER => { - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "-y -i %i $dopts %o" }, - }, - - avconv => { - NAME => 'ffmpeg', - DSTR => sub { "-y -i %i %dopts %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - - }, - - bonk => { - - DEFAULT_ENCODER => "bonk", - DEFAULT_DECODER => "bonk", - - ENCODER => { - bonk => { - NAME => "bonk", - ESTR => sub { - $opts = "-q $bquanl -b $bratio -s $bpsize" if $defopts == 1; - $opts = '' if $defopts == 0; - "encode $eopts $opts %i -o %o" - }, - - PROMPT => { - BQUANL => 1, - BRATIO => 1, - BPSIZE => 1, - }, - }, - }, - - DECODER => { - bonk => { - NAME => "bonk", - DSTR => sub { "decode %i -o %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - dts => { - - DEFAULT_ENCODER => 'ffmpeg', - DEFAULT_DECODER => 'ffmpeg', - - ENCODER => { - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = '' if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $opts $eopts -strict -2 -codec:a libfaac %o" - }, - - PROMPT => { NONE => 0, }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = '' if $defopts == 1 or $defopts == 0; - "-y -i %i $opts $eopts -codec:a libfaac %o", - }, - PROMPT => { NONE => 0, }, - }, - - dcaenc => { - NAME => 'dcaenc', - ESTR => sub { - $opts = "$bitrate" if $defopts == 0; - $opts = '' if $defopts == 1; - "%i %o $opts" - }, - - PROMPT => { NONE => 0, }, - }, - }, - - DECODER => { - ffmpeg => { - NAME => 'ffmpeg', - DSTR => "$dopts -y -i %i %o", - }, - - avconv => { - NAME => 'avconv', - DSTR => "$dopts -y -i %i %o", - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - flac => { - - DEFAULT_ENCODER => "flac", - DEFAULT_DECODER => "flac", - - ENCODER => { - flac => { - NAME => "flac", - ESTR => sub { - $opts = "-$fcomp" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts -f $opts %i -o %o" - }, - PROMPT => { FCOMP => 1 }, - }, - - flake => { - NAME => "flake", - ESTR => sub { - $opts = "-$fcomp" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i -o %o" - }, - PROMPT => { FCOMP => 1 }, - }, - - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 1; - "-y -i %i $eopts $opts %o" - }, - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - flac => { - NAME => "flac", - DSTR => sub { "$dopts -f -d %i -o %o" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "Audio::FLAC::Header", - }, - }, - - fla => { - - DEFAULT_ENCODER => "flac", - DEFAULT_DECODER => "flac", - - ENCODER => { - flac => { - NAME => "flac", - ESTR => sub { - $opts = "-$fcomp" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts -f $opts %i -o %o" - }, - PROMPT => { FCOMP => 1 }, - }, - }, - - DECODER => { - flac => { - NAME => "flac", - DSTR => sub { "$dopts -f -d %i -o %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "Audio::FLAC::Header", - }, - }, - - la => { - - DEFAULT_ENCODER => "la", - DEFAULT_DECODER => "la", - - ENCODER => { - la => { - NAME => "la", - ESTR => sub { "-overwrite $eopts %i %o" }, - PROMPT => { NONE => 0, }, - }, - }, - - DECODER => { - la => { - NAME => "la", - ESTR => sub { "-console $dopts %i > %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - mp2 => { - - DEFAULT_ENCODER => "ffmpeg", - DEFAULT_DECODER => "ffmpeg", - - ENCODER => { - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - toolame => { - NAME => 'toolame', - ESTR => sub { - $opts = "-b $bitrate" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - - PROMPT => { - BITRATE => 1, - }, - }, - - twolame => { - NAME => 'twolame', - ESTR => sub { - $opts = "-b $bitrate -s $freq" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - }, - }, - - sox => { - NAME => 'sox', - ESTR => sub { - $opts = "-c $channels -r $bitrate" if $defopts == 1; - $opts = '' if $defopts == 0; - "%i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - - ffmpeg => { - NAME => 'ffmpeg', - DSTR => "$dopts -y -i %i %o", - }, - - avconv => { - NAME => 'avconv', - DSTR => "%dopts -y -i %i %o", - }, - - mplayer => { - NAME => 'mplayer', - DSTR => "-vc null -vo null -ao pcm:file=%o %i", - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - mp3 => { - - DEFAULT_ENCODER => "lame", - DEFAULT_DECODER => "lame", - - ENCODER => { - lame => { - NAME => "lame", - ESTR => sub { - $opts = "--resample $freq -b $bitrate -h" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - }, - }, - - bladeenc => { - NAME => "bladeenc", - ESTR => sub { - $opts = "-br $bitrate" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - PROMPT => { BITRATE => 1 }, - }, - - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts -y -i %i $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - sox => { - NAME => "sox", - ESTR => sub { - $opts = "-r $freq -c $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "%i $eopts $opts %o" - }, - - PROMPT => { - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - lame => { - NAME => "lame", - DSTR => sub { "$dopts --decode %i %o" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %O" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - - sox => { - NAME => "sox", - DSTR => sub { "%i $dopts %o" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "MP3::Tag", - }, - }, - - mp3hd => { - - DEFAULT_ENCODER => "mp3hdEncoder", - DEFAULT_DECODER => "mp3hdDecoder", - - ENCODER => { - mp3hdEncoder => { - NAME => "mp3hdEncoder", - ESTR => sub { - $opts = "-br $bitrate" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts -if %i -of %o" - }, - PROMPT => { BITRATE => 1 }, - }, - }, - - DECODER => { - mp3hdDecoder => { - NAME => "mp3hdDecoder", - DSTR => sub { "$dopts -if %i -of %o" }, - }, - }, - - TAGS => { - WRITE => 1, - READ => 1, - MODULE => "MP3::Tag", - }, - }, - - mp4 => { - - DEFAULT_ENCODER => "faac", - DEFAULT_DECODER => "faad", - - ENCODER => { - - faac => { - NAME => "faac", - ESTR => sub { - $opts = "-q $aacqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts -w $opts %i -o %o" - }, - PROMPT => { AACQUAL => 1 }, - }, - - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PRIMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - - faad => { - NAME => "faad", - DSTR => sub { "$dopts -o %o %i" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "Audio::Scan", - }, - }, - - m4a => { - - DEFAULT_ENCODER => "faac", - DEFAULT_DECODER => "faad", - - ENCODER => { - - faac => { - NAME => "faac", - ESTR => sub { - $opts = "-q $aacqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts -w $opts %i -o %o" - }, - PROMPT => { AACQUAL => 1 }, - }, - - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts -y -i %i $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - - faad => { - NAME => "faad", - DSTR => sub { "$dopts -o %o %i" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - - }, - - ESTR => sub { "$eopts -w -q $aacqual %i -o %o" }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "Audio::Scan", - }, - }, - - m4b => { - - DEFAULT_ENCODER => undef, - DEFAULT_DECODER => "faad", - - DECODER => { - faad => { - NAME => "faad", - DSTR => sub { "$dopts -o %o %i" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 1, - MODULE => undef, - }, - }, - - mpc => { - - DEFAULT_ENCODER => "mpcenc", - DEFAULT_DECODER => "mpcdec", - - ENCODER => { - - mpcenc => { - NAME => "mpcenc", - ESTR => sub { - $opts = "--$mpcqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts --overwrite $opts %i %o" - }, - PROMPT => { MPCQUAL => 1 }, - }, - }, - - DECODER => { - - mpcdec => { - NAME => "mpcdec", - DSTR => sub { "$dopts %i %o" }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "Audio::Scan", - }, - - PROMPT => { - MPCQUAL => 1, - }, - }, - - mpp => { - - DEFAULT_ENCODER => "mpcenc", - DEFAULT_DECODER => "mpcdec", - - ENCODER => { - - mpcenc => { - NAME => "mpcenc", - ESTR => sub { - $opts = "--$mpcqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts --overwrite $opts %i %o" - }, - PROMPT => { MPCQUAL => 1 }, - }, - }, - - DECODER => { - - mpcdec => { - NAME => "mpcdec", - DSTR => sub { "$dopts %i %o" }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "Audio::Scan", - }, - }, - - off => { - DEFAULT_ENCODER => 'off', - DEFAULT_DECODER => 'off', - - ENCODER => { - off => { - NAME => 'off', - ESTR => sub { - $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts --overwrite $opts %i --output %o" - }, - - PROMPT => { - OFMODE => 1, - OFOPT => 1, - }, - }, - }, - - DECODER => { - off => { - NAME => 'off', - DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - ofr => { - - DEFAULT_ENCODER => "ofr", - DEFAULT_DECODER => "ofr", - - ENCODER => { - ofr => { - NAME => "ofr", - ESTR => sub { - $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts --overwrite $opts %i --output %o" - }, - - PROMPT => { - OFMODE => 1, - OFOPT => 1, - }, - }, - }, - - DECODER => { - ofr => { - NAME => "ofr", - DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - ofs => { - - DEFAULT_ENCODER => "ofs", - DEFAULT_DECODER => "ofs", - - ENCODER => { - ofs => { - NAME => "ofs", - ESTR => sub { - $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts --overwrite $opts %i --output %o" - }, - - PROMPT => { - OFMODE => 1, - OFOPT => 1, - }, - }, - }, - - DECODER => { - ofs => { - NAME => "ofs", - DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - - oga => { - DEFAULT_ENCODER => 'oggenc', - DEFAULT_DECODER => 'oggdec', - - ENCODER => { - oggenc => { - NAME => 'oggenc', - ESTR => sub { - $opts = "--resample $freq -q $oggqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - PROMPT => { - FREQ => 1, - OGGQUAL => 1, - }, - }, - - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - sox => { - NAME => "sox", - ESTR => sub { - $opts = "-r $freq -c $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "%i $eopts $opts %o" - }, - - PROMPT => { - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - oggdec => { - NAME => "oggdec", - DSTR => sub { "$dopts %i --output %o" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - - sox => { - NAME => "sox", - DSTR => sub { "%i $dopts %o" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "vorbiscomment", - }, - }, - - ogg => { - - DEFAULT_ENCODER => "oggenc", - DEFAULT_DECODER => "oggdec", - - ENCODER => { - oggenc => { - NAME => "oggenc", - ESTR => sub { - $opts = "--resample $freq -q $oggqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i -o %o" - }, - - PROMPT => { - FREQ => 1, - OGGQUAL => 1, - }, - }, - - ffmpeg => { - NAME => "ffmpeg", - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - FREQ => 1, - CHANNELS => 1, - }, - }, - - sox => { - NAME => "sox", - ESTR => sub { - $opts = "-r $freq -c $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "%i $eopts $opts %o" - }, - - PROMPT => { - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - oggdec => { - NAME => "oggdec", - DSTR => sub { "$dopts %i --output %o" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - - sox => { - NAME => "sox", - DSTR => sub { "%i $dopts %o" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "vorbiscomment", - }, - }, - - opus => { - - DEFAULT_ENCODER => "opusenc", - DEFAULT_DECODER => "opusdec", - - ENCODER => { - opusenc => { - NAME => 'opusenc', - ESTR => sub { - $opts = "--bitrate $bitrate" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - PROMTP => { - BITRATE => 1, - }, - }, - }, - - DECODER => { - opusdec => { - NAME => 'opusdec', - DSTR => sub { "--force-wav %i %o" }, - PROMPT => { NONE => 0 }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - raw => { - - DEFAULT_ENCODER => "sox", - DEFAULT_DECODER => "sox", - - ENCODER => { - sox => { - NAME => 'sox', - ESTR => sub { - $opts = "-r $freq -c $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "%i $opts $eopts %o $effect" - }, - - PROMPT => { - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - sox => { - NAME => 'sox', - DSTR => sub { "-w -s -r $freq -c $channels $dopts %i %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - rm => { - - DEFAULT_ENCODER => 'ffmpeg', - DEFAULT_DECODER => 'ffmpeg', - - ENCODER => { - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = "-ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - FREQ => 1, - CHANNELS => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "-ar $freq -ac $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - FREQ => 1, - CHANNELS => 1, - }, - }, - }, - - DECODER => { - mplayer => { - NAME => 'mplayer', - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - shn => { - - DEFAULT_ENCODER => "shorten", - DEFAULT_DECODER => "shorten", - - ENCODER => { - shorten => { - NAME => "shorten", - ESTR => sub { - $opts = "-c $channels" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - PROMPT => { CHANNELS => 1 }, - }, - }, - - DECODER => { - shorten => { - NAME => "shorten", - DSTR => sub { "-x %i %o" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - spx => { - - DEFAULT_ENCODER => "speexenc", - DEFAULT_DECODER => "speexdec", - - ENCODER => { - speexenc => { - NAME => "speexenc", - ESTR => sub { - $opts = "--quality $spxqual" if $defopts == 1; - $opts = '' if $defopts == 0; - "$eopts $opts %i %o" - }, - PROMPT => { SPXQUAL => 1 }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { - $opts = "--bitrate $bitrate.k" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i %i $eopts $opts %o" - }, - - PROMPT => { - BITRATE => 1, - }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { - $opts = "--bitrate $bitrate.k" if $defopts == 1; - $opts = '' if $defopts == 0; - "-y -i $eopts $opts %o" - }, - PROMPT => { - BITRATE => 1, - }, - }, - }, - - DECODER => { - speexdec => { - NAME => "speexdec", - DSTR => sub { "$dopts %i %o" }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => undef, - }, - }, - - tta => { - - DEFAULT_ENCODER => "ttaenc", - DEFAULT_DECODER => "ttaenc", - - ENCODER => { - ttaenc => { - NAME => "ttaenc", - ESTR => sub { "$eopts -e %i -o %o" }, - PROMPT => { NONE => 0, }, - }, - }, - - DECODER => { - ttaenc => { - NAME => "ttaenc", - DSTR => sub { "$dopts -d %i -o %o" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - wav => { - - DEFAULT_ENCODER => "mv", - DEFAULT_DECODER => "cp", - - ENCODER => { - mv => { - NAME => "mv", - ESTR => sub { "%i %o" }, - PROMPT => { NONE => 0, }, - }, - }, - - DECODER => { - cp => { - NAME => "cp", - DSTR => sub { "%i %o" }, - } - }, - - TAGS => { - READ => 0, - WRITE => 0, - MODULE => undef, - }, - }, - - wv => { - - DEFAULT_ENCODER => "wavpack", - DEFAULT_DECODER => "wvunpack", - - ENCODER => { - wavpack => { - NAME => "wavpack", - ESTR => sub { "$eopts -h -y %i -o %o" }, - PROMPT => { NONE => 0, }, - }, - - ffmpeg => { - NAME => 'ffmpeg', - ESTR => sub { "-y -i %i $eopts %o" }, - PROMPT => { NONE => 0, }, - }, - - avconv => { - NAME => 'avconv', - ESTR => sub { "-y -i %i $eopts %o" }, - PROMPT => { NONE => 0, }, - }, - }, - - DECODER => { - wvunpack => { - NAME => "wvunpack", - DSTR => sub { "$dopts -y %i -o %o" }, - }, - - ffmpeg => { - NAME => "ffmpeg", - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - avconv => { - NAME => 'avconv', - DSTR => sub { "$dopts -y -i %i %o" }, - }, - - mplayer => { - NAME => "mplayer", - DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, - }, - }, - - TAGS => { - READ => 1, - WRITE => 1, - MODULE => "Audio::Scan", - }, - }, -); - -# supported ffmpeg/avconv formats (decode only) -my @ffmpeg_codecs = ( "mmf", "ra", "wma" ); -my @ffmpeg_forks = ( "avconv", "ffmpeg" ); - -foreach my $fork (@ffmpeg_forks) { - - foreach my $codec (@ffmpeg_codecs) { - - $run{$codec}{DEFAULT_ENCODER} = $fork; - $run{$codec}{DEFAULT_DECODER} = $fork; - $run{$codec}{ENCODER}{$fork}{NAME} = $fork; - $run{$codec}{DECODER}{$fork}{NAME} = $fork; - $run{$codec}{DECODER}{$fork}{DSTR} = sub {"-y %i $dopts %o"}; - $run{$codec}{ENCODER}{$fork}{ESTR} = sub {"-y -i %i $eopts -ab $bitrate.k -ar $freq -ac $channels %o"}; - $run{$codec}{TAGS}{READ} = 0; - $run{$codec}{TAGS}{WRITE} = 0; - $run{$codec}{TAGS}{MODULE} = undef; - } - -} - -# support reading of WMA tags via Audio::Scan -$run{wma}{TAGS}{READ} = 1; -$run{wma}{TAGS}{MODULE} = "Audio::Scan"; - -# supported video to audio types -my @movie_codecs = ( - "rv", "asf", "avi", "divx", - "mkv", "mpg", "mpeg", "mov", - "ogm", "qt", "vcd", "vob", - "wmv", "flv", "svcd", "m4v", - "nsv", "nuv", "psp", "smk", - "ogv", "webm", - - # decode only audio formats - "vqf", "tak", - ); - -foreach (@movie_codecs) { - $run{$_}{DEFAULT_ENCODER} = undef; - $run{$_}{DEFAULT_DECODER} = "ffmpeg"; - $run{$_}{DECODER}{mplayer}{NAME} = "mplayer"; - $run{$_}{DECODER}{ffmpeg}{NAME} = "ffmpeg"; - $run{$_}{DECODER}{mplayer}{DSTR} = sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }; - $run{$_}{DECODER}{ffmpeg}{DSTR} = sub { "$dopts -i %i %o"; }; - $run{$_}{TAGS}{READ} = 0; - $run{$_}{TAGS}{WRITE} = 0; - $run{$_}{TAGS}{MODULE} = undef; -} - -# supported sndfile-convert formats -my @sndfile = ( - "pvf", "caf", "sf", "paf", "fap", "sd2", - "mat4", "mat5", "mat", "ircam", "w64", "nist", - "rf64", - ); - -foreach (@sndfile) { - - $run{$_}{DEFAULT_ENCODER} = "sndfile-convert"; - $run{$_}{DEFAULT_DECODER} = "sndfile-convert"; - $run{$_}{ENCODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; - $run{$_}{DECODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; - $run{$_}{ENCODER}{"sndfile-convert"}{ESTR} = sub { "$eopts %i %o" }; - $run{$_}{DECODER}{"sndfile-convert"}{DSTR} = sub { "$dopts %i %o" }; - $run{$_}{TAGS}{READ} = 0; - $run{$_}{TAGS}{WRITE} = 0; - $run{$_}{TAGS}{MODULE} = undef; -} - -# supported sox formats -my @sox_codecs = ( - "aiff", "aif", "au", "snd", "voc", - "smp", "avr", "cdr", "8svx", "amb", - "dat", "dvms", "f32", "f64", "fssd", - "gsrt", "hcom", "txw", "vms", "al", - "sou", "ima", "prc", "cvu", - "maud", - ); - -foreach (@sox_codecs) { - - $run{$_}{DEFAULT_ENCODER} = "sox"; - $run{$_}{DEFAULT_DECODER} = "sox"; - $run{$_}{ENCODER}{sox}{NAME} = "sox"; - $run{$_}{DECODER}{sox}{NAME} = "sox"; - $run{$_}{ENCODER}{sox}{ESTR} = sub { "%i -r $freq -c $channels $eopts %o $effect" }; - $run{$_}{DECODER}{sox}{DSTR} = sub { "%i $dopts %o" }; - $run{$_}{TAGS}{READ} = 0; - $run{$_}{TAGS}{WRITE} = 0; - $run{$_}{TAGS}{MODULE} = undef; - - $run{$_}{ENCODER}{sox}{PROMPT}{FREQ} = 1; - $run{$_}{ENCODER}{sox}{PROMPT}{CHANNELS} = 1; - -} - -# load codecs.conf file -load_codecs() if -e $codecs_conf; - -my $out_name = $outfile; -my $out_dir = $outdir; -my $first_message = 1; -my %files; -my $number = 0; - -# process all files and directories -sub proc_input { - - $to =~ tr/A-Z/a-z/; - - perror("bad_input","") unless(exists($run{$to})); - - proc_preserve_dir($dir0) if @dir and $preserve; # process recursive directory preservation (sends to proc_files - proc_dirs() if @dir and not $preserve; # process directories including recursively (sends to proc_files) - proc_files() if @file; # process all files - fork_files(); # start the conversion process. -} - -# process all files (all roads lead to rome) -sub proc_files { - - if (@file) { - - foreach my $i (sort(@file)) { - - my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); - - $ext =~ s/^\.//; - $dir = rel2abs($dir); - $outdir = $dir if not defined($out_dir) and not $preserve; - $outdir = $out_dir if $preserve; - - my $if = $ext; - $if =~ tr/A-Z/a-z/; - - $only =~ tr/A-Z/a-z/ if $only; - - next if $only and $if ne $only; - - $encoder = $my_encoder if defined($my_encoder); - $decoder = $my_decoder if defined($my_decoder); - - $encoder = $run{$to}{DEFAULT_ENCODER} if not $my_encoder; - $decoder = $run{$if}{DEFAULT_DECODER} if not $my_decoder; - - if (-e "$file.$to" and not $overwrite) { - pnotice("overwrite","$file.$to",1); - $total_failed++; - next; - } - - if (check_input($file,$dir,$if) == 0) { - - pnotice("unk_encoder","$file.$ext",1), next unless(exists($run{$to}{ENCODER}{$encoder})); - pnotice("unk_decoder","$file.$ext",1), next unless(exists($run{$if}{DECODER}{$decoder})); - - get_visual_opts($to,$outdir) if $gui and not defined($first_run); - - $first_run = 1; - - perror("multi_out","") if (defined($out_name) and $#file gt 0 or defined($out_name) and @dir); - perror("no_outdir","") if (not -e $outdir and not -d $outdir); - - $outfile = "$file" if not $out_name; - - if ($keep and $if eq $to) { - system("cp -v \"$dir/$file.$ext\" \"$outdir/$outfile.$ext\"") if $outdir ne $dir and not -e "$outdir/$outfile.$ext"; - next if $outdir eq $dir; - } - - else { - $files{"FILE$number"}{FILE} = "$dir/$file"; - $files{"FILE$number"}{OUTF} = "$outdir/$outfile"; - $files{"FILE$number"}{EXT} = "$ext"; - $files{"FILE$number"}{NAME} = "$file"; - $files{"FILE$number"}{OUTD} = "$outfile"; - $files{"FILE$number"}{DECODER} = "$decoder"; - - $number++; - } - - } - } - } - undef(@file); -} - -# process directories and push all to @file arrary -sub proc_dirs { - - if (@dir) { - - my @tmp_dir = @dir; - undef(@dir); - $topdir = $tmp_dir0; - - if (not $recursive) { - - undef(@file); - - foreach my $d (@tmp_dir) { - - opendir(DIR, "$d") or perror("opening_dir","$d: $!"); - my @dir_files = readdir(DIR); - closedir(DIR); - perror("empty_dir","$d") if $#dir_files <= 1; - - foreach my $f (@dir_files) { - - if (not -d $f and not -d "$d/$f") { - push(@file, "$d/$f"); - undef($out_name); - } - } - } - - proc_files(); - return 0; - - } - - elsif ($recursive) { - - if (not $preserve) { - - undef(@file); - - foreach my $r (@tmp_dir) { - - $r = rel2abs($r); - - find ( sub { - my $rfile = $File::Find::name; - push(@file, $rfile) if not -d $rfile; - }, $r - ); - } - - proc_files(); - return 0; - - } - } - - } -} - -# preserve directory structuer (revised 10-7-2013) -my $out_dir_original = rel2abs($outdir) if $outdir and -d $outdir; - -sub proc_preserve_dir { - -$topdir = rel2abs($dir0); - -perror("no_outdir","") if not defined($out_dir_original); -perror("no_outdir","") if not -d $out_dir_original; - -undef(@file); # clear the array before we begin. - -find ( sub { - my $val = $File::Find::name; - $val =~ s/(\$)/\\\$/g; - - if ($val ne $topdir) { - - $val =~ s/$topdir\///; - - # create mirrored directories in output directory - if (not -f fileparse("$topdir/$val") and not -d "$out_dir_original/$val") { - say "creating directory $out_dir_original/$val" if not -f "$topdir/$val" and $verbose; - mkdir("$out_dir_original/$val", 0755) if not -f "$topdir/$val"; - } - - # this will list all files in their original directories - if (-f "$topdir/$val") { - say "$lang{debug} pushing to \@file: $topdir/$val" if $debug == 1; - push(@file, "$topdir/$val"); - } - - # set $out_dir to the - $out_dir = "$out_dir_original/" . dirname($val) if -f "$topdir/$val"; - - # send file, and output dir to proc_files(); - proc_files(); - } - - }, $topdir - ); -} - -# convert input to destination format -sub convert { - - my ($inf, $outf, $infmt, $iname, $oname, $dec) = @_; - - my $if = $infmt; - $if =~ tr/A-Z/a-z/; - - clear_tag_hash() if not $rip; - - # catch ^C. will have to be pressed repeatedly to exit the process. - $SIG{INT} = sub { - unlink("$outf.$$.wav"); - kill 9, $$; - }; - - # check to see if encoder/decoder exists. if not, see if we have one - # that supports the desired input/output formats. - $decoder = $dec; - check_encoder(); - check_decoder($infmt); - - my $decode_string = $run{$if}{DECODER}{$decoder}{DSTR}->(); - $decode_string =~ s/%i/\"$inf.$infmt\"/; - $decode_string =~ s/%o/\"$outf.$$.wav\"/; - $decode_string =~ s/(\$|\\)/\\$1/g; - - pnotice("debug","\n$run{$if}{DECODER}{$decoder}{NAME} $decode_string", 2) if $dryrun; - - # decode input file to temporary wav - system("$run{$if}{DECODER}{$decoder}{NAME} $decode_string $silent") if not $dryrun; - - # remove temporary wav file and die if decode fails - if ($? > 0) { - unlink("$outf.$$.wav") if -e "$outf.$$.wav"; - say ""; - $banner = 0; - pnotice("decode_failed","$inf.$infmt: try with --verbose",1); - return 1; - } - - # normalize wav file before encoding to output format - perror("no_app","normalize") if $normalize and not `which normalize 2>/dev/null`; - system("normalize $nopts \"$outf.$$.wav\"") if $normalize; - - # copy meta-data from input file to %tag_name - read_tags("$inf.$infmt", "$if") if $run{$if}{TAGS}{READ} == 1 and not $dryrun; - - my $tag_opts = format_tags($to); # tag options for mp4/m4a/m4b/mpc/mpp/bonk/spx/wv - - my $encode_string = $run{$to}{ENCODER}{$encoder}{ESTR}->(); - $encode_string =~ s/%i/$tag_opts \"$outf.$$.wav\"/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "faac" or $encoder eq "mpcenc"; - $encode_string =~ s/%i/\"$outf.$$.wav\" $tag_opts/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "ffmpeg" or $encoder eq "avconv"; - $encode_string =~ s/%i/\"$outf.$$.wav\"/ if $to !~ /mpc|mpp|mp4|m4a/; - $encode_string =~ s/%o/$tag_opts \"$outf.$to\"/ if $tag_opts ne " " and $to !~ /mpc|mpp|mp4|m4a/; - $encode_string =~ s/%o/\"$outf.$to\"/ if $tag_opts eq " " or $to =~ /mpc|mpp|mp4|m4a/; - $encode_string =~ s/(\$|\\)/\\$1/g; - - # read tag options from command line if present - get_user_tags(); - - pnotice("debug","\n$run{$to}{ENCODER}{$encoder}{NAME} $encode_string", 2) if $dryrun; - - # encode temporary WAV to desired output format. - system("$run{$to}{ENCODER}{$encoder}{NAME} $encode_string $silent") if not $dryrun; - - # remove partially encoded output file and temporary wav if encoding fails - if ($? > 0) { - unlink("$outf.$to") if -e "$outf.$to"; - unlink("$outf.$$.wav") if -e "$outf.$$.wav"; - say ""; - $banner = 0; - pnotice("encode_failed","$outf.$to: $?",1); - return 1; - } - - # write meta-data to output file from %tag_name hash - write_tags("$outf.$to", "$to") if $run{$to}{TAGS}{WRITE} == 1 and $tag_opts eq " " and not $dryrun; - - unlink("$outf.$$.wav") if not $dryrun; - unlink("$inf.$infmt") if $delete and not $dryrun; - - pnotice("removed_tmp","$outf.$$.wav","2") if $verbose; - pnotice("removed_src","$inf.$infmt", "2") if $delete and $verbose; -} - -$pm->run_on_finish -( sub { - my $pid = shift; - my $exit_code = shift; - my $ident = shift; - - if (-e "$ident.$to") { - $total_converted++; - } - say "$lang{debug} PID: $pid EXIT_CODE: $exit_code IDENTITY: \"$ident.$to\"" if $debug == 1; - } -); - -# convert all files that have been placed in the %files hash through various procs* -sub fork_files { - - say "\n$name - $version\n" if not $gui and $banner == 1; - - foreach (sort(keys(%files))) - { - $pm->start($files{$_}{OUTF}) and next; - my $msg = "$lang{converting}" . " " . basename($files{$_}{FILE}) . ".$files{$_}{EXT} -> $to"; - say "$msg" if not $gui; - system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$msg\" 10 &") if $gui and $kde; - system("notify-send \"$name\" \"$msg\" -t 35 -i $icon_path &") if $gui and $gnome; - convert("$files{$_}{FILE}","$files{$_}{OUTF}","$files{$_}{EXT}","$files{$_}{NAME}","$files{$_}{OUTD}","$files{$_}{DECODER}"); - $pm->finish; - } - - $pm->wait_all_children; - $total_failed = $number - $total_converted if $total_converted < $number; - - my $finished_msg = "\n$lang{total_converted} $total_converted, $lang{failed} $total_failed\n"; - - say "$finished_msg" if not $gui; - system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$finished_msg\" 10 &") if $gui and $kde; - system("notify-send \"$name\" \"$finished_msg\" -t 35 -i $icon_path &") if $gui and $gnome; - -} - -# if the default encoder does not exist, cycle through the supported -# encoders until we find one that does. -sub check_encoder { - - if (not `which $encoder 2>/dev/null`) { - my $first_encoder = $encoder; - foreach (keys %{$run{$to}{ENCODER}}) { $encoder = $_ and return if `which $_ 2>/dev/null`; } - perror("no_encode_app","$to") if $encoder eq $first_encoder; - } - - else { return 0; } -} - -# if the default decoder does not exist, cycle through the supported -# decoders until we find one that does. -sub check_decoder { - - my $from = shift; - - if (not `which $decoder 2>/dev/null`) { - my $first_decoder = $decoder; - foreach (keys %{$run{$from}{DECODER}}) { $decoder = $_ and return if `which $_ 2>/dev/null`; } - perror("no_decode_app","$from") if $decoder eq $first_decoder; - } - - else { return 0; } -} - -# make sure encoding/decoding is supported. -sub check_input { - - my $file = shift; - my $dir = shift; - my $ext = shift; - - perror("no_encoder","$to") unless(defined($run{$to}{ENCODER})); - - unless(defined($run{$ext}{DECODER})) { - pnotice("no_decoder","$ext",2) if $verbose or not $only; - $total_failed++; - return 1; - } - - return 0; -} - -######################################## -# GUI options for KDE & Gnome Plugins # -######################################## - -my $kdialog = "kdialog --title \"$name\""; -my $zenity = "zenity --title \"$name\" --list --radiolist --width 100 --height 300 --column '' --column "; - -sub get_visual_opts { - - my ($to_fmt,$od) = @_; - - # escape illegal characters in output directory name - $od =~ s/('|\(|\)|"|\\)/\\$1/g; - - $outdir = `kdialog --getexistingdirectory $od` if $config{KDE_DIR} == 1 and $kde; - $outdir = `zenity --title \"$lang{gui_outdir}\" --file-selection --directory --filename=\`pwd\`` if $config{ZEN_DIR} == 1 and $gnome; - - chomp($outdir); - $out_dir = $outdir; - exit(1) if not $outdir; - - if ($config{KDE_OPTS} == 1 or $config{ZEN_OPTS} == 1) { - foreach (keys %{$run{$to_fmt}{ENCODER}{$encoder}{PROMPT}}) { - prompt_user($_); - } - } -} - -sub prompt_user { - - my $opt = shift; - - given ($opt) { - - when (/^BITRATE/) { - $bitrate = `$kdialog --default $bitrate --combobox \"$lang{gui_bitrate}\" 56 112 128 160 192 256 320` if $kde; - $bitrate = `$zenity \"$lang{gui_bitrate}\" FALSE 56 FALSE 112 FALSE 128 FALSE 160 TRUE 192 FALSE 256 FALSE 320` if $gnome; - chomp($bitrate); - exit(1) if not $bitrate; - } - - when (/^FREQ/) { - $freq = `$kdialog --default $freq --combobox \"$lang{gui_freq}\" 32000 44100 48000` if $kde; - $freq = `$zenity \"$lang{gui_freq}\" FALSE 32000 TRUE 44100 FALSE 48000` if $gnome; - chomp($freq); - exit(1) if not $freq; - } - - when (/^CHANNELS/) { - $channels = `$kdialog --default $channels --combobox \"$lang{gui_chans}\" 1 2` if $kde; - $channels = `$zenity \"$lang{gui_chans}\" FALSE 1 TRUE 2` if $gnome; - chomp($channels); - exit(1) if not $channels; - } - - when (/^FCOMP/) { - $fcomp = `$kdialog --default $fcomp --combobox \"$lang{gui_fcomp}\" 0 1 2 3 4 5 6 7 8` if $kde; - $fcomp = `$zenity \"$lang{gui_fcomp}\" FALSE 0 FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8` if $gnome; - chomp($fcomp); - exit(1) if not $fcomp; - } - - when (/^ACOMP/) { - $acomp = `$kdialog --default $acomp --combobox \"$lang{gui_acomp}\" 1000 2000 3000 4000 5000` if $kde; - $acomp = `$zenity \"$lang{gui_acomp}\" FALSE 1000 FALSE 2000 TRUE 3000 FALSE 4000 FALSE 5000` if $gnome; - chomp($acomp); - exit(1) if not $acomp; - } - - when (/^OGGQUAL/) { - $oggqual = `$kdialog --default $oggqual --combobox \"$lang{gui_oggqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; - $oggqual = `$zenity \"$lang{gui_oggqual}\" FALSE 0 FALSE 1 FALSE 2 TRUE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8 FALSE 9 FALSE 10` if $gnome; - chomp($oggqual); - exit(1) if not $oggqual; - } - - when (/^SPXQUAL/) { - $spxqual = `$kdialog --default $spxqual --combobox \"$lang{gui_spxqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; - $spxqual = `$zenity \"$lang{gui_spxqual}\" FALSE 0 FALSE 1 FALSE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 TRUE 8 FALSE 9 FALSE 10` if $gnome; - chomp($spxqual); - exit(1) if not $spxqual; - } - - when (/^AACQUAL/) { - $aacqual = `$kdialog --default $aacqual --combobox \"$lang{gui_aacqual}\" 100 200 300 400 500` if $kde; - $aacqual = `$zenity \"$lang{gui_aacqual}\" TRUE 100 FALSE 200 FALSE 300 FALSE 400 FALSE 500` if $gnome; - chomp($aacqual); - exit(1) if not $aacqual; - } - - when (/^MPCQUAL/) { - $mpcqual = `$kdialog --default $mpcqual --combobox \"$lang{gui_mpcqual}\" thumb radio standard xtreme insane braindead` if $kde; - $mpcqual = `$zenity \"$lang{gui_mpcqual}\" FALSE thumb TRUE radio FALSE standard FALSE xtreme FALSE insane FALSE braindead` if $gnome; - chomp($mpcqual); - exit(1) if not $mpcqual; - } - - when (/^OFMODE/ ) { - $ofmode = `$kdialog --default $ofmode --combobox \"$lang{gui_ofmode}\" fast normal high extra best highnew extranew bestnew` if $kde; - $ofmode = `$zenity \"$lang{gui_ofmode}\" FALSE fast TRUE normal FALSE high FALSE extra FALSE best FALSE highnew FALSE extranew FALSE bestnew` if $gnome; - chomp($ofmode); - exit(1) if not $ofmode; - } - - when (/^OFOPT/) { - $ofopt = `$kdialog --default $ofopt --combobox \"$lang{gui_ofopt}\" none fast normal high best` if $kde; - $ofopt = `$zenity \"$lang{gui_ofopt}\" FALSE none TRUE fast FALSE normal FALSE high FALSE best` if $gnome; - chomp($ofopt); - exit(1) if not $ofopt; - } - - when (/^BRATIO/) { - $bratio = `$kdialog --default $bratio --combobox \"$lang{gui_bratio}\" 1 2 3 4 5` if $kde; - $bratio = `$zenity \"$lang{gui_bratio}\" FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5` if $gnome; - chomp($bratio); - exit(1) if not $bratio; - } - - when (/^BQUANL/) { - $bquanl = `$kdialog --default $bquanl --combobox \"$lang{gui_bquanl}\" 1.00 1.25 1.50 1.75 2.00` if $kde; - $bquanl = `$zenity \"$lang{gui_bquanl}\" TRUE 1.00 FALSE 1.25 FALSE 1.50 FALSE 1.75 FALSE 2.00` if $gnome; - chomp($bquanl); - exit(1) if not $bquanl; - } - - when (/^BPSIZE/) { - $bpsize = `$kdialog --default $bpsize --combobox \"$lang{gui_bpsize}\" 10 128` if $kde; - $bpsize = `$zenity \"$lang{gui_bpsize}\" FALSE 10 TRUE 128` if $gnome; - chomp($bpsize); - exit(1) if not $bpsize; - } - - default { return 0; } - } - -} - -# all copied tags will be stored here for furture use -my %tag_name = -( - title => undef, - track => undef, - artist => undef, - album => undef, - comment => undef, - year => undef, - genre => undef, -); - -# override tags read from input file if any of the tagging -# options are specified by the user during conversion. -sub get_user_tags -{ - $tag_name{title} = $title if $title; - $tag_name{track} = $track if $track; - $tag_name{artist} = $artist if $artist; - $tag_name{album} = $album if $album; - $tag_name{comment} = $comment if $comment; - $tag_name{year} = $year if $year; - $tag_name{genre} = $genre if $genre; -} - -# the formats MP4/M4A/M4B/MPC/MPP/WV/BONK have no tag writing module. -# tags therefore have to be written during encode via various -# command line args. -sub format_tags { - - my $type = shift; - - given ($type) { - - when (/^mp4$|^m4a$|^m4b$/) { - - if ($run{$to}{ENCODER}{$encoder}{NAME} eq "ffmpeg" or $run{$to}{ENCODER}{$encoder}{NAME} eq "avconv") { - - $tag_name{track} = 0 if not $tag_name{track}; - $tag_name{year} = 0 if not $tag_name{year}; - - return "-metadata TITLE=\"$tag_name{title}\" -metadata TRACK=\"$tag_name{track}\" -metadata ARTIST=\"$tag_name{artist}\" -metadata ALBUM=\"$tag_name{album}\" -metadata COMMENT=\"$tag_name{comment}\" -metadata YEAR=\"$tag_name{year}\" -metadata GENRE=\"$tag_name{genre}\""; - - } else { - - return "--title \"$tag_name{title}\" --track \"$tag_name{track}\" --artist \"$tag_name{artist}\" --album \"$tag_name{album}\" --comment \"$tag_name{comment}\" --year \"$tag_name{year}\" --genre \"$tag_name{genre}\""; - - } - } - - when (/^mpc$|^mpp$/) { return "--artist \"$tag_name{artist}\" --title \"$tag_name{title}\" --album \"$tag_name{album}\" --track \"$tag_name{track}\" --genre \"$tag_name{genre}\" --year \"$tag_name{year}\" --comment \"$tag_name{comment}\""; } - when (/^wv$/) { return "-w \"Title=$tag_name{title}\" -w \"Track=$tag_name{track}\" -w \"Artist=$tag_name{artist}\" -w \"Album=$tag_name{album}\" -w \"Comment=$tag_name{comment}\" -w \"Year=$tag_name{year}\" -w \"Genre=$tag_name{genre}\""; } - when (/^bonk$/) { return "-t \"$tag_name{title}\" -a \"$tag_name{artist}\" -c \"$tag_name{comment}\""; } - when (/^spx$/) { return "--author \"$tag_name{artist}\" --title \"$tag_name{title}\" --comment \"year=$tag_name{year}\" --comment \"tracknumber=$tag_name{track}\" --comment \"album=$tag_name{album}\" --comment \"genre=$tag_name{genre}\" --comment \"comment=$tag_name{comment}\""; } - - default { return " "; } - } -} - -# meta-data is read based on input file extension. -# all tags which are present will be copied to -# the %tag_name hash. -sub read_tags { - - my $in_file = shift; - my $in_format = shift; - - my $tag_module = $run{$in_format}{TAGS}{MODULE}; - - given ($in_format) { - - when (/^mp3$|^mp3hd$/) { - my $mp3tag = $tag_module->new($in_file); - my @tags = $mp3tag->autoinfo(); - - $tag_name{title} = "$tags0" if $tags0; - $tag_name{track} = "$tags1" if $tags1; - $tag_name{artist} = "$tags2" if $tags2; - $tag_name{album} = "$tags3" if $tags3; - $tag_name{comment} = "$tags4" if $tags4; - $tag_name{year} = "$tags5" if $tags5; - $tag_name{genre} = "$tags6" if $tags6; - - return 0; - } - - when (/^ogg$|^oga$/) { - my $ogg_tag = Audio::Scan->scan_tags($in_file)->{tags}; - - $tag_name{title} = $ogg_tag->{TITLE} if $ogg_tag->{TITLE}; - $tag_name{track} = $ogg_tag->{TRACKNUMBER} if $ogg_tag->{TRACKNUMBER}; - $tag_name{artist} = $ogg_tag->{ARTIST} if $ogg_tag->{ARTIST}; - $tag_name{album} = $ogg_tag->{ALBUM} if $ogg_tag->{ALBUM}; - $tag_name{comment} = $ogg_tag->{COMMENT} if $ogg_tag->{COMMENT}; - $tag_name{year} = $ogg_tag->{YEAR} if $ogg_tag->{YEAR}; - $tag_name{genre} = $ogg_tag->{GENRE} if $ogg_tag->{GENRE}; - - return 0; - } - - when (/^spx$/) { - my $pid = open(SPX, "speexdec \"$in_file\" tmp1-$$.wav 2>&1 |") or perror("opening_file","$in_file"); - my @data = <SPX>; - @data = grep(!/^$|^#/, @data); - - close(SPX); - - foreach (@data) { - - next unless /=/; - chomp; - - my ($k, $v) = split /=/; - $k =~ tr/A-Z/a-z/; - $tag_name{$k} = $v if exists($tag_name{$k}); - $tag_name{artist} = $v if $k =~ /^author/i; - $tag_name{track} = $v if $k =~ /^tracknumber/i; - } - - unlink("tmp-$$.wav"); - return 0; - } - - when (/^flac$|^fla$/) { - my $flac_tag = Audio::Scan->scan_tags($in_file)->{tags}; - - $tag_name{title} = $flac_tag->{TITLE} if $flac_tag->{TITLE}; - $tag_name{track} = $flac_tag->{TRACKNUMBER} if $flac_tag->{TRACKNUMBER}; - $tag_name{artist} = $flac_tag->{ARTIST} if $flac_tag->{ARTIST}; - $tag_name{album} = $flac_tag->{ALBUM} if $flac_tag->{ALBUM}; - $tag_name{comment} = $flac_tag->{COMMENT} if $flac_tag->{COMMENT}; - $tag_name{year} = $flac_tag->{DATE} if $flac_tag->{DATE}; - $tag_name{genre} = $flac_tag->{GENRE} if $flac_tag->{GENRE}; - - return 0; - } - - when (/^mp4$|^m4a$|^m4b$/) { - my $mp4_tag = $tag_module->scan_tags($in_file)->{tags}; - - $tag_name{title} = $mp4_tag->{NAM} if $mp4_tag->{NAM}; - $tag_name{track} = $mp4_tag->{TRKN} if $mp4_tag->{TRKN}; - $tag_name{artist} = $mp4_tag->{ART} if $mp4_tag->{ART}; - $tag_name{album} = $mp4_tag->{ALB} if $mp4_tag->{ALB}; - $tag_name{comment} = $mp4_tag->{CMT} if $mp4_tag->{CMT}; - $tag_name{year} = $mp4_tag->{DAY} if $mp4_tag->{DAY}; - $tag_name{genre} = $mp4_tag->{GNRE} if $mp4_tag->{GNRE}; - - return 0; - } - -when (/^ape$|^mpc$|^mpp$|^wv$/) { - my $audio_tag = $tag_module->scan_tags($in_file)->{tags}; - - $tag_name{title} = $audio_tag->{TITLE} if $audio_tag->{TITLE}; - $tag_name{track} = $audio_tag->{TRACK} if $audio_tag->{TRACK}; - $tag_name{artist} = $audio_tag->{ARTIST} if $audio_tag->{ARTIST}; - $tag_name{album} = $audio_tag->{ALBUM} if $audio_tag->{ALBUM}; - $tag_name{comment} = $audio_tag->{COMMENT} if $audio_tag->{COMMENT}; - $tag_name{year} = $audio_tag->{YEAR} if $audio_tag->{YEAR}; - $tag_name{genre} = $audio_tag->{GENRE} if $audio_tag->{GENRE}; - - return 0; - } - - when (/^wma$/) { - my $wma_tag = $tag_module->scan_tags($in_file)->{tags}; - - $tag_name{title} = $wma_tag->{TITLE} if $wma_tag->{TITLE}; - $tag_name{track} = $wma_tag->{TRACKNUMBER} if $wma_tag->{TRACKNUMBER}; - $tag_name{artist} = $wma_tag->{AUTHOR} if $wma_tag->{AUTHOR}; - $tag_name{album} = $wma_tag->{ALBUMTITLE} if $wma_tag->{ALBUMTITLE}; - $tag_name{comment} = $wma_tag->{DESCRIPTION} if $wma_tag->{DESCRIPTION}; - $tag_name{year} = $wma_tag->{YEAR} if $wma_tag->{YEAR}; - $tag_name{genre} = $wma_tag->{GENRE} if $wma_tag->{GENRE}; - - return 0; - } - - default { return 1; } - } -} - -# write meta-data stored in %tag_name to output file. -sub write_tags { - - my $out_file = shift; - my $out_format = shift; - - my $tag_m; - - given ($out_format) { - - when (/^mp3$|^mp3hd$/) { - $tag_m = MP3::Tag->config(write_v24 => 'YES'); - $tag_m = MP3::Tag->new("$out_file"); - - # ID3v2 Tags - unless(exists($tag_m->{ID3v2})) { $tag_m->new_tag("ID3v2"); } - - $tag_m->{ID3v2}->add_frame("TIT2", "$tag_name{title}") if defined($tag_name{title}); - $tag_m->{ID3v2}->add_frame("TRCK", "$tag_name{track}") if defined($tag_name{track}); - $tag_m->{ID3v2}->add_frame("TPE1", "$tag_name{artist}") if defined($tag_name{artist}); - $tag_m->{ID3v2}->add_frame("TALB", "$tag_name{album}") if defined($tag_name{album}); - $tag_m->{ID3v2}->comment("$tag_name{comment}") if defined($tag_name{comment}); - $tag_m->{ID3v2}->add_frame("TYER", "$tag_name{year}") if defined($tag_name{year}); - $tag_m->{ID3v2}->add_frame("TCON", "$tag_name{genre}") if defined($tag_name{genre}); - - $tag_m->{ID3v2}->write_tag; - - # ID3v1 Tags - unless(exists($tag_m->{ID3v1})) { $tag_m->new_tag("ID3v1"); } - - $tag_m->{ID3v1}->title("$tag_name{title}") if defined($tag_name{title}); - $tag_m->{ID3v1}->track("$tag_name{track}") if defined($tag_name{track}); - $tag_m->{ID3v1}->artist("$tag_name{artist}") if defined($tag_name{artist}); - $tag_m->{ID3v1}->album("$tag_name{album}") if defined($tag_name{album}); - $tag_m->{ID3v1}->comment("$tag_name{comment}") if defined($tag_name{comment}); - $tag_m->{ID3v1}->year("$tag_name{year}") if defined($tag_name{year}); - $tag_m->{ID3v1}->genre("$tag_name{genre}") if defined($tag_name{genre}); - - $tag_m->{ID3v1}->write_tag; - - return 0; - - } - - when (/^ogg$|^oga$/) { - $tag_m = ''; - - $tag_m = "$tag_m -t \"TITLE=$tag_name{title}\"" if $tag_name{title}; - $tag_m = "$tag_m -t \"TRACKNUMBER=$tag_name{track}\"" if $tag_name{track}; - $tag_m = "$tag_m -t \"ARTIST=$tag_name{artist}\"" if $tag_name{artist}; - $tag_m = "$tag_m -t \"ALBUM=$tag_name{album}\"" if $tag_name{album}; - $tag_m = "$tag_m -t \"COMMENT=$tag_name{comment}\"" if $tag_name{comment}; - $tag_m = "$tag_m -t \"YEAR=$tag_name{year}\"" if $tag_name{year}; - $tag_m = "$tag_m -t \"GENRE=$tag_name{genre}\"" if $tag_name{genre}; - - system("vorbiscomment -w $tag_m \"$out_file\"") if $tag_m ne ''; - - return 0; - } - - when (/^fla$|^flac$/) { - $tag_m = Audio::FLAC::Header->new("$out_file"); - my $tag_i = $tag_m->tags(); - - $tag_i->{TITLE} = "$tag_name{title}" if $tag_name{title}; - $tag_i->{TRACKNUMBER} = "$tag_name{track}" if $tag_name{track}; - $tag_i->{ARTIST} = "$tag_name{artist}" if $tag_name{artist}; - $tag_i->{ALBUM} = "$tag_name{album}" if $tag_name{album}; - $tag_i->{COMMENT} = "$tag_name{comment}" if $tag_name{comment}; - $tag_i->{DATE} = "$tag_name{year}" if $tag_name{year}; - $tag_i->{GENRE} = "$tag_name{genre}" if $tag_name{genre}; - - $tag_m->write(); - - return 0; - } - - default { perror("no_write_tag","$out_file"); } - } - -} - -# this is necessary when converting multiple files. -# it prevents old tags from the previous file being -# copied over to the next file in line. -sub clear_tag_hash { - foreach (keys(%tag_name)) { - $tag_name{$_} = ''; - } -} - -# display meta-data for selected file(s) -sub show_taginfo { - - perror("no_input","") if $#file < 0; - - foreach my $i (@file) { - - my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); - - $ext =~ s/^\.//; - - my $from = $ext; - $from =~ tr/A-Z/a-z/; - - if ($run{$from}{TAGS}{READ} == 1) { - - clear_tag_hash(); - read_tags("$dir/$file.$ext","$from"); - - say ''; - - pnotice("tag_info","$file.$ext",2); - - say " Artist: $tag_name{artist}"; - say " Title: $tag_name{title}"; - say " Album: $tag_name{album}"; - say " Track: $tag_name{track}"; - say "Comment: $tag_name{comment}"; - say " Year: $tag_name{year}"; - say " Genre: $tag_name{genre}"; - - say ''; - - } else { pnotice("no_read_tag","$file.$ext",2); } - } -} - -# write tags to file supplied by the user -sub write_user_tags { - - perror("no_input","") if $#file < 0; - - say ''; - say "$name - $version\n"; - - foreach (@file) { - - my ($file, $dir, $ext) = fileparse("$_", qr/\.^.*/); - - $ext =~ s/^\.//; - my $from = $ext; - $from =~ tr/A-Z/a-z/; - - if ($run{$from}{TAGS}{WRITE} == 1) { - - clear_tag_hash(); - read_tags("$dir/$file.$ext","$from"); - - $tag_name{title} = $title if $title; - $tag_name{track} = $track if $track; - $tag_name{artist} = $artist if $artist; - $tag_name{album} = $album if $album; - $tag_name{comment} = $comment if $comment; - $tag_name{year} = $year if $year; - $tag_name{genre} = $genre if $genre; - - write_tags("$dir/$file.$ext","$from"); - say "$lang{write_tag_i} $file.$ext"; - - } else { perror("no_write_tag","$file.$ext"); } - } - say ''; -} - -# print out list of supported encode & decode formats -sub show_formats { - -say "\n$name - $version\n"; -say "EXT E D ENCODER DECODER TAG-READ TAG-WRITE"; -say "----------------------------------------------------------------------"; - -my $enc_count = 0; -my $dec_count = 0; - - foreach (sort(keys(%run))) { - - my $e = "N"; $e = "Y" if defined($run{$_}{DEFAULT_ENCODER}); - my $d = "N"; $d = "Y" if defined($run{$_}{DEFAULT_DECODER}); - my $r = "N"; $r = "Y" if $run{$_}{TAGS}{READ} == 1; - my $w = "N"; $w = "Y" if $run{$_}{TAGS}{WRITE} == 1; - - my $enc = ''; $enc = $run{$_}{DEFAULT_ENCODER} if defined($run{$_}{DEFAULT_ENCODER}); - my $dec = ''; $dec = $run{$_}{DEFAULT_DECODER} if defined($run{$_}{DEFAULT_DECODER}); - - printf("%-9s %-3s %-3s %-15s %-18s %-10s %s\n", $_, $e, $d, $enc, $dec, $r, $w); - - ++$enc_count if $enc ne ''; - ++$dec_count if $dec ne ''; - - } - - say "\n$lang{enc_fmts} $enc_count --- $lang{dec_fmts} $dec_count\n"; - -} - -# show encoders for output format -sub show_encoders { - say "\n$name - $version\n\n$lang{show_encoders}: $my_encoder\n"; - foreach (sort(keys %{$run{$my_encoder}{ENCODER}})) { - print "$_ -> "; - print "installed" if `which $_ 2>/dev/null`; - print "not found" if not `which $_ 2>/dev/null`; - print " (default)" if $_ eq $run{$my_encoder}{DEFAULT_ENCODER}; - say ''; - } - say ''; -} - -# show decoders for input format -sub show_decoders { - say "\n$name - $version\n\n$lang{show_decoders}: $my_decoder\n"; - foreach (sort(keys %{$run{$my_decoder}{DECODER}})) { - print "$_ -> "; - print "installed" if `which $_ 2>/dev/null`; - print " (default)" if $_ eq $run{$my_decoder}{DEFAULT_DECODER}; - say ''; - } - say ''; -} - -################# -# cd ripping... # -################# - -# get total number of tracks from cdparanoia query -sub get_total_tracks { - - open(CDINFO, "cdparanoia -Q 2>&1 |") or die "can't fork: $!\n"; - my @cdquery = <CDINFO>; - close(CDINFO); - - my $fmt_tracks = $cdquery-3; - $fmt_tracks =~ s/\s//g; - - my @ttracks = split(/\./, $fmt_tracks); - - return "$ttracks0"; - -} - -my (%cd, %ripconfig, @cdtrack, $track_total); - -# setup the cddb config -sub get_cddb_config { - - $config{USE_CDDB} = 0 && return if $nocddb; - - $config{CDDB_INPUT} = 0 if $noinput; - - $ripconfig{CDDB_HOST} = $config{CDDB_HOST}; - $ripconfig{CDDB_PORT} = $config{CDDB_PORT}; - $ripconfig{CDDB_MODE} = $config{CDDB_MODE}; - $ripconfig{DEVICE} = $device; - $ripconfig{CDDB_INPUT} = $config{CDDB_INPUT}; - - print $ripconfig{CDDB_HOST}; - - %cd = get_cddb(\%ripconfig); - - if (not $cd{title}) { - pnotice("no_cddb","",2); - $config{USE_CDDB} = 0; - } - else { - @cdtrack = @{$cd{track}}; - $track_total = $cd{tno}; - } - -} - -# check to see if a disc is present -sub query_disc { - system("cdparanoia -q -d $device -Q > /dev/null 2>&1"); - perror("no_disc","$device") if $? > 0; -} - -# set tag info from cddb -sub tag_track { - - my $tno = shift; - - $tag_name{artist} = $cd{artist} if $cd{artist}; - $tag_name{title} = $cdtrack$tno-1 if $cdtrack$tno-1; - $tag_name{genre} = $cd{cat} if $cd{cat}; - $tag_name{track} = $tno; - $tag_name{album} = $cd{title} if $cd{title}; - $tag_name{year} = $cd{year} if $cd{year}; - $tag_name{comment} = ''; - -} - -# process and convert ripped track -sub rip_cd { - - my ($on,$tno) = @_; - - $outdir = $ENV{HOME}; - $to =~ tr/A-Z/a-z/; - - get_visual_opts($to,$out_dir) if $gui and not defined($first_run); - $first_run = 1; - pnotice("ripping_track","$tno",2); - - $on =~ s/\//_/g; - - say "\ncdparanoia -d $device $tno $on.wav\n" if $dryrun; - system("cdparanoia -d $device $tno \"$on.wav\" >/dev/null 2>&1") if not $dryrun; - - if ($to !~ /wav/i) { - - push(@file, "$on.wav"); - tag_track($tno); - proc_input(); - clear_tag_hash(); - undef(@file); - unlink("$on.wav") if not $dryrun; - pnotice("removed_tmp","$on.wav",2) if $verbose; - - } -} - -# rip selected tracks or all from disc -sub proc_cd { - - perror("no_app","cdparanoia") if not `which cdparanoia 2>/dev/null`; - - query_disc(); - get_cddb_config(); - - my $total_tracks = get_total_tracks(); - - if ($rip eq "all") { - - if ($config{USE_CDDB} ne 1) { - - for(my $i=1;$i<=$total_tracks;$i++) { - rip_cd($i, $i); - } - - } elsif ($config{USE_CDDB} eq 1) { - - my $n = 1; - - foreach my $i (@cdtrack) { - - my $out_string = $nscheme; - - chomp($cdtrack$n-1); - - $out_string =~ s/%ar/$cd{artist}/; - $out_string =~ s/%ti/$cdtrack$n-1/; - $out_string =~ s/%tr/$n/; - $out_string =~ s/%ab/$cd{title}/; - $out_string =~ s/%yr/$cd{year}/; - - rip_cd($out_string, $n); - - ++$n; - } - } - - } else { - - my @tracks = split(/,/, $rip); - - foreach my $i (@tracks) { - - next if $i > $total_tracks or $i < 1; - - my $out_string = $nscheme; - - $out_string =~ s/%ar/$cd{artist}/; - $out_string =~ s/%ti/$cdtrack$i-1/; - $out_string =~ s/%tr/$i/; - $out_string =~ s/%ab/$cd{title}/; - $out_string =~ s/%yr/$cd{year}/; - - rip_cd($out_string, $i) if $config{USE_CDDB} == 1; - rip_cd($i, $i) if $config{USE_CDDB} == 0; - } - } -} - -# get/print cddb information from disc -sub cdinfo { - - query_disc(); - get_cddb_config(); - - say "$name - $version\n"; - - say "Artist = $cd{artist}"; - say "Album = $cd{title}"; - say "Genre = $cd{genre}"; - say "Tracks = $cd{tno}"; - say "Year = $cd{year}\n"; - - my $n = 1; - - foreach (@cdtrack) { - say "Track $n: $_"; - ++$n; - } - - exit(0); -} - -# version / license information -sub version { - -say " -$name - $version - -Copyright (C) 2005-2017 Philip Lyons - -This is free software. You may redistribute copies of it under the terms of -the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. -There is NO WARRANTY, to the extent permitted by law. -"; - -} - -# help & longhelp menu -sub help_menu { - -say "\n$name - $version"; - -say " --t, --to $lang{to} --r, --recursive $lang{recursive} --p, --preserve $lang{preserve} --f, --formats $lang{formats} --o, --only $lang{only} --k, --keep $lang{keep} --j, --jobs $lang{jobs} --h, --help $lang{help} --l, --longhelp $lang{longhelp} --v, --verbose $lang{verbose} -"; - -say "$lang{user_opts} - ---defopts $lang{defopts} ---eopts $lang{eopts} ---dopts $lang{dopts} ---nopts $lang{nopts} ---outfile $lang{outfile} ---outdir $lang{outdir} ---dryrun $lang{dryrun} ---overwrite $lang{overwrited} ---normalize $lang{normalize} ---delete $lang{delete} ---encoder $lang{encoder} ---decoder $lang{decoder} ---version $lang{version} - -$lang{enc_opts} - ---bitrate $lang{bitrate} ---freq $lang{freq} ---channels $lang{channels} ---effect $lang{effect} ---fcomp $lang{fcomp} ---acomp $lang{acomp} ---oggqual $lang{oggqual} ---spxqual $lang{spxqual} ---aacqual $lang{aacqual} ---mpcqual $lang{mpcqual} ---ofmode $lang{ofmode} ---ofopt $lang{ofopt} ---bratio $lang{bratio} ---bquanl $lang{bquanl} ---bpsize $lang{bpsize} - -$lang{tag_opts} - ---artist $lang{artist} ---title $lang{title} ---track $lang{track} ---year $lang{year} ---album $lang{album} ---genre $lang{genre} ---comment $lang{comment} ---taginfo $lang{taginfo} - -$lang{tag_usage} - -$lang{rip_opts} - ---rip $lang{rip} ---nocddb $lang{nocddb} ---noinput $lang{noinput} ---nscheme $lang{nscheme} ---cdinfo $lang{cdinfo} ---device $lang{device} - -$lang{rip_usage}" if $longhelp; - -say "\n$lang{usage}\n"; - -} - -sub load_module { - my ($file) = @_; - my $return; - unless($return = do $file) { - perror("opening_file","$file: $@ $!") if $@ or !defined($return) or not !$return; - } -} - -sub import_module { - my ($format_ref) = @_; - my $format_name=$format_ref->{NAME}; - $run{$format_name} = $format_ref; -} - -# load all user modules -sub load_user_modules { - my @imported_mods; - opendir(DIR, "$mod_dir") or perror("opening_dir","$mod_dir: $!"); - foreach (readdir(DIR)) { - load_module("$mod_dir/$_") if $_ !~ /^\./; - push(@imported_mods, $_) if $_ !~ /^\./; - } - closedir(DIR); - say "$lang{imported} @imported_mods"; -} - -# place files/directories in their respective arrays -if (@ARGV) { - foreach (@ARGV) { - if (-f $_) { push(@file,$_); print "$lang{debug} adding $_ to \@file\n" if $debug == 1; } - elsif (-d $_) { push(@dir, $_); print "$lang{debug} adding $_ to \@dir\n" if $debug == 1; } - else { perror("no_infile","$_"); } - } -} - -load_user_modules() if $config{IMPORTM} == 1; - -if ($to and @ARGV and not $rip) { proc_input(); } - -elsif ($to and $rip) { proc_cd(); } -elsif ($my_encoder and not $to) { show_encoders(); } -elsif ($my_decoder and not $to) { show_decoders(); } -elsif ($verinfo) { version(); } -elsif ($longhelp) { help_menu(); } -elsif ($formats) { show_formats(); } -elsif ($cdinfo) { cdinfo(); } -elsif ($taginfo and not $to) { show_taginfo(); } -elsif ($title or $track or $artist or $album or $comment or $year or $genre) { write_user_tags(); } - -else { help_menu(); } - -__END__ - -=head1 NAME - -pacpl - Perl Audio Converter, a multi purpose converter/ripper/tagger - -=head1 SYNOPSIS - -pacpl --to <format> <options> file(s)/directory(s) - -=head1 DESCRIPTION - -Perl Audio Converter - -A Linux CLI tool for converting multiple audio types from one format to another. - -It supports the following audio formats: - -======================================== - -3G2, 3GP, 8SVX, AAC, AC3, ADTS, AIFF, AL, AMB, AMR, APE, AU, -AVR, BONK, CAF, CDR, CVU, DAT, DTS, DVMS, F32, F64, FAP, FLA, -FLAC, FSSD, GSRT, HCOM, IMA, IRCAM, LA, MAT, MAUD, MAT4, MAT5, -M4A, MP2, MP3, MP4, MPC, MPP, NIST, OFF, OFR, OFS, OPUS, OGA, -OGG, PAF, PRC, PVF, RA, RAM, RAW, RF64, SD2, SF, SHN, SMP, SND, -SOU, SPX, SRN, TAK, TTA, TXW, VOC, VMS, VQF, W64, WAV, WMA, -and WV. - -It can also extract audio from the following video extensions: - -============================================================== - -RM, RV, ASF, DivX, MPG, MKV, MPEG, AVI, MOV, OGM, OGV, QT, VCD, -SVCD, M4V, NSV, NUV, PSP, SMK, VOB, FLV, WEBM and WMV. - -Parallel Processing, a CD ripping function with CDDB support, batch conversion, -tag preservation for most supported formats, independent tag reading & writing, -service menus for KDE Dolphin/Konqueror, GNOME Nautilus script, and action -scripts for Nemo/Thunar are also provided. - -=head1 OPTIONS - -B<-t, --to> I<format> - -set encode format for the input file(s) or directory(ies). you can see a -complete list of supported encode formats by using the B<--formats> option. - -B<-r, --recursive> - -recursively scan and convert input folder(s) to destination format. - -B<-p, --preserve> - -when recursively converting a directory, preserve the input folders directory -structure in the specified output directory. such as: - -pacpl --to ogg -r -p /home/mp3s --outdir /home/oggs - -in the example above, let's assume the directory structure was: - -=over 21 - -=item /home/mp3s/Alternative - -=item /home/mp3s/Alternative/New - -=item /home/mp3s/Rap - -=item /home/mp3s/Country - -=item /home/mp3s/Techno/ - -=back - -the output directory will now contain: - -=over 4 - -=item /home/oggs/Alternative - -=item /home/oggs/Alternative/New - -=item /home/oggs/Rap - -=item /home/oggs/Country - -=item /home/oggs/Techno - -=back - -with all files in each sub-folder converted to ogg. - -B<-o, --only> I<format> - -only convert files matching extension. this option is useful when you have -a directory or batch of files with mixed audio types and only need to -convert one specific type. - -B<-k, --keep> - -do not re-encode files with extensions matching the destination extension. -instead...copy them to the output folder, or skip to the next file. - -B<-j, --jobs> - -number of simultanious jobs to run at once. the default limit -is set to 4 in pacpl.conf. You can modify this value on the fly -using --jobs=<num> or set it perminately in the configuration file - -=over 4 - -=item B<-f, --formats> show a list of supported encode/decode formats. - -=item B<-h, --help> show the short help menu. - -=item B<-l, --longhelp> display the complete list of options. - -=item B<--version> show version and licensing information. - -=back - -=head1 USER OPTIONS - -B<--defopts> I<1/0> - -to turn off default encoder options use --defopts 0. this option gives you -more control when using the --eopts command. - -defopts is set to 1 by default. you can also toggle this option in -/etc/pacpl/pacpl.conf. - -B<--eopts> I<options> - -this option allows you to use encoder options not implemented by pacpl. -an example would be: - -pacpl --to mp4 --eopts="-c 44100 -I 1,2" YourFile.mp3 - -B<--dopts> I<options> - -this option allows you to use decoder options not implemented by pacpl. -an example would be: - -pacpl --to mpc --dopts="--start 60" YourFile.ogg - -B<--outfile> I<name> - -set the output file name to I<name>. - -B<--outdir> I<directory> - -place all encoded files in I<directory>. - -B<--dryrun> - -show what would be done without actually converting anything. this is a -good way to trouble shoot, or to see what would be done without actually -touching your files. - -B<--overwrite> - -replace the output file if it already exists. - -B<--normalize> - -adjusts volume levels of audio files. - -B<--nopts> I<options> - -this allows you to specify normalize options not implemented by pacpl - -B<--delete> - -remove source/input file after the conversion process has finished. - -B<--encoder> I<encoder> - -specify an alternate encoder for the selected output file(s) - -you can see a list of supported encoders by using the following: - -pacpl --encoder I<format> - -B<--decoder> I<decoder> - -specify an alternate decoder for the selected input file(s) - -you can see a list of supported decoders by using the following: - -pacpl --decoder I<format> - -B<-v, --verbose> - -show detailed information about the encoding process and what's actually -being done. - -=head1 ENCODER OPTIONS - -B<--bitrate> I<num> - -set the bitrate to I<num>. default is 128. this option does not apply -to all formats. - -B<--freq> I<num> - -set the frequency to I<num>. default is 44100. this option does not apply -to all formats. - -B<--channels> I<num> - -set the number of audio channels in the output file to I<num>. this option -does not apply to all formats. - -B<--effect> I<str> - -see B<sox>(1). this option only applies to the following: - -AIFF, AU, SND, RAW, VOC, SMP, AVR, and CDR - -B<--fcomp> I<num> - -set flac compression level to I<num>. fastest -0, highest -8, default -2 - -=over 4 - -=item 1 = fast - -=item 2 = simple - -=item 3 = medium (default) - -=item 4 = high - -=item 5 = extra high, - -=back - -B<--acomp> I<num> - -set ape compression level to I<num>. - -=over 4 - -=item 1000 = fast - -=item 2000 = normal - -=item 3000 = high (default) - -=item 4000 = extra high - -=item 5000 = insane - -=back - -B<--oggqual> I<num> - -set ogg quality level to I<num>. -1, very low and 10 very high, default 3 - -B<--spxqual> I<num> - -set speex quality level to I<num>. 0-10, default 8 (use --bitrate <num> when using ffmpeg/avconv as encoder) - -B<--aacqual> I<num> - -set aac, mp4, m4a, or m4b quality level to I<num>. default 300 - -B<--mpcqual> I<str> - -set mpc/mpp quality level to I<str>. - -=over 4 - -=item thumb low quality/internet, (typ. 58... 86 kbps) - -=item radio medium (MP3) quality, (typ. 112...152 kbps - default) - -=item standard high quality (dflt), (typ. 142...184 kbps) - -=item xtreme extreme high quality, (typ. 168...212 kbps) - -=back - -B<--ofmode> I<str> - -set off/ofr/ofs compression mode to I<str>. normal, extra, and extranew modes -are recommended for general use. available options are: - -=over 4 - -=item fast - -=item normal (default) - -=item high - -=item extra - -=item best - -=item highnew - -=item extranew - -=item bestnew - -=back - -B<--ofopt> I<str> - -set off/ofr/ofs optimization level to I<str>. - -specify the optimization level in the engine. In order to achieve -optimal compression at all sample types, sample rates, and audio -content, the core compression engine has the possibility to find the -optimal values for its parameters, at the cost of slightly increased -compression time only. The default recommended value is fast. -do not use normal (or even high or best) for this parameter unless -encoding time does not matter and you want to obtain the smallest -possible file for a given compression mode. The difference between -the optimize levels fast and best (which is up to three times slower -than fast) is very small, generally under 0.05%, but may be also -larger in some rare cases. Note that the none optimize level is -forced by the encoder to fast optimize level for the extra, best, -highnew, extranew, and bestnew modes. - -available options are: - -=over 4 - -=item none - -=item fast (default) - -=item normal - -=item high - -=item best - -=back - -B<--bratio> I<num> - -set bonk down sampling ratio. default 2 - -B<--bquanl> I<num> - -set bonk quantanization level. default 1.0 - -B<--bpsize> I<num> - -set bonk predictor size. default 128 - -=head1 TAGGING OPTIONS - -B<note:> - -tagging outside of the encoding process can only be performed on the -following audio types: - -=over 4 - -=item MP3 - -=item OGG - -=item FLA - -=item FLAC - -=back - -B<--artist> I<str> - -set artist information to I<str>. - -B<--title> I<str> - -set title information to I<str>. - -B<--track> I<num> - -set track information to I<num>. - -B<--year> I<num> - -set year/date information to I<num>. - -B<--album> I<str> - -set album information to I<str>. - -B<--genre> I<str> - -set genre information to I<str>. - -B<--comment> I<str> - -set comment information to I<str>. - -B<--taginfo> I<file> - -show tagging information for I<file>. multiple files can be specified -at once. - -=head1 RIPPING OPTIONS - -B<--rip> I<num/all> - -rip selected tracks separated by comma or all from current disc. - -=over 4 - -=item pacpl --rip all --to flac - -=item pacpl --rip 1,3,9,15 --to flac - -=back - -B<--nocddb> - -disable cddb. use this option if you do not want tagging based on cddb. - -B<--noinput> - -disable cddb interactivity. this is enabled by default. - -B<--nscheme> I<str> - -set naming scheme to I<str>. default is %ar - %ti - -available options are: - -=over 4 - -=item %ar = artist - -=item %ti = song title - -=item %tr = track - -=item %yr = year - -=item %ab = album - -=back - -B<eg:> --nscheme="(%tr)-%ti" - -B<--device> I<device> - -set device to I<device>. default is /dev/dvd - -B<--cdinfo> - -show cddb information for current disc. - -=head1 SEE ALSO - -=over 4 - -=item B<sox>(1) B<ffmpeg>(1) B<lame>(1) B<oggenc>(1) B<oggdec>(1) - -=item B<flac>(1) B<shorten>(1) B<faac>(1) B<faad>(1) B<mpcenc>(1) - -=item B<mpcdec>(1) B<mplayer>(1) B<speexenc>(1) B<speexdec>(1) - -=item B<sndfile-convert>(1) B<normalize>(1) B<cdparanoia>(1) - -=item B<opusenc>(1) B<opusdec>(1) B<wavpack>(1) B<ffmpeg>(1) - -=item B<mplayer>(1) B<avconv>(1) - -=back - -=head1 BUGS - -Report all bugs to Philip Lyons (vorzox@gmail.com) - -=head1 LICENSING - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -=head1 AUTHOR - -Copyright (C) 2005-2017 Philip Lyons (vorzox@gmail.com)
View file
pacpl-6.1.0.tar.gz/ChangeLog.txt
Added
@@ -0,0 +1,285 @@ +================= +**** 6.1.0 **** +================= + +* updated version to 6.1.0 + +% fixed kdialog ouput directory space issue + thanks to Jeremy Rehbaum (JRehbaum@juno.com) + +% incorporated patches from Paulo Marcel Coelho Aragão + - fix blank WMA tags + - fix decoder not working for WMA + - fix overwrite check to act more appropriately + - fix DEFOPTS = 0 to work as intended + + added alac-decoder support for .mp4 files + + added .gitignore + % fixed handling of m4a (AAC) codec handling + +% incoporated patches from Reuben Thomas (rrt@sc3d.org) + - fix installaton under different prefix and/or DESTDIR + - fix hardwired pathes in pacpl + +%note: with above patches pacpl is now pacpl.in which will be renamed after configure + +% updated Makefile.am to remove pacpl with "make distclean" + +================= +**** 5.1.0 **** +================= + +* updated version to 5.1.0 + ++ added patches directory. below updates and incorporations are included. + +% incorporated the following patches Matteo Cypriani (mcy@lm7.fr) + - typos + - configure exit + - enforce outdir when preserve is utilized + - multiple input source decode + +* updated README.module documentation thanks to Cristian Greco <cristian.debian@gmail.com> + +================= +**** 5.0.2 **** +================ + +%fixed regex to detect directory names with spaces thanks to Dmitry Klimov + +================= +**** 5.0.1 **** +================= + +01-04-2014 + +* updated ogg vorbis & spx tags to use TRACKNUMBER instead of TRACK + +% fixed coverting to "wma, ra, & mmf" thanks to bug report by Timothy E. Harris +% fixed missing semicolon bug in nemo/nautilus/thunar script +% fixed overwrite message to show output file, not source. +% fixed Thunar PACPL-Konvert script thanks to Timothy E. Harris + +- removed support for .src and .ram extenions (no longer supported) + +================= +**** 5.0.0 **** +================= + +11-1-2013 + +** 5.0.0 Official Stable Release ** + +* minor code optimizations/changes +* updated README program description + +% fixed amr encoding +% fixed mmf, ra, wma, other codecs supported by ffmpeg + ++ added a few obscure audio formats supported by sox/sndfile-convert including: + rf64 (sndfile) 8svx amb dat dvms f32 f64 fssd gsrt hcom txw vms + +10-12-2013 + +% fixed encoding to .mp4/.m4a using ffmpeg/avconv +% fixed configure error when enabling nemo + +- removed use of Ogg::Vorbis::Header. tag writing for oga and ogg + is now done via vorbiscomment (part of vorbis-tools) + ++ added oga extension for ogg vorbis audio ++ added ogv audio extract support ++ added webm audio extract support + +* updated oga/ogg tag reading to use Audio::Scan + +10-10-2013 + +% changed the kde plugin to popup a combobox for selecting the + output format to keep things somewhat consistent with the rest of + the platforms. + +% flip-flopped on the use 5.18.0 statement. seems other (*buntu*) + distros consider that release "experimental". worked around it + with a simple: + + no if $ >= 5.018, warnings => "experimental::smartmatch"; + +% re-wrote preserve directory function. it actually works again... + ++ added parallel processing. about time we put those cores to use! ++ added use of Parallel::ForkManager module you can install it via: + 1) perl -MCPAN -e 'install Parallel::ForkManager' + 2) sudo apt-get install libparallel-forkmanager-perl + ++ added option -j,--jobs option to specify concurrent jobs to process ++ added JOBS varible in pacpl.conf. default is set to 4 ++ added jobs description to locale files (need translations!) + ++ added support for the Thunar file manager (tested under Xbuntu 13.04) + see plugins/gnome/thunar/INSTALL for more information + +10-1-2013 + ++ added the use 5.18.0; requriement to pacpl. to those + using earlier versions, you can remove this line but YMMV. + +% fixed configure script to work properly when different + gui dialog / file managers are installed + +- removed support for lpac/pac (obsolete) +- removed support for gogo (obsolete) + +9-30-2013 + ++ added GNOMEDIR variable to the Makefile in case your gnome + installation is not located in the default /usr directory + +* updated directory structure for plugins +* updated configure script to use the following: + + --enable-kde (for the KDE service menu) + --enable-nautilus (for the nautilus script) + --enable-nemo (for the nemo action script) + + the kde and nautilus/nemo options cannot be used together. + you can however use both nemo and nautilus (assuming you have + both installed) + + by default none of the options are enabled + +- removed install.sh & README for nemo script directory + +9-24-2013 + +# bumped version to 5.0.0. with the amount of time + passed since the last release and all the feature + additons/changes I feel its warranted: For now + we're still in the nightly/pre-release testing stage + ++ GNOME Support Added: + +Note: Tested and tailored for 13.04 Unity, it will however + work on earlier versions and other debian based distros + using the Gnome desktop which have zenity & notify-send + installed + ++ added PACPL-Convert (Nautilus/Nemo) script + ++ added support for running the script through Nemo on Linux Mint + or other distributions that use that file manager + tested on Linux Mint 15 "Olivia" Cinnamon (64-bit) + +- removed use of Audio::WMA +- removed use of MP4::Info +- removed use of Audio::Musepack +- removed use of Audio::APETags + + the above four modules have been replaced by Audio::Scan for + reading the tags from the various formats including flac. + ++ added use of perl module Audio::Scan ++ added support for reading .ape tags ++ added support for TAK audio format (decode only) ++ added cdparanoia to mod-install-ubuntu.sh as part of the basic tools ++ added new string to .po files (gui_outdir) - **translators needed** + +% fixed changed FLAC tag DESCRIPTION to COMMENT +% fixed FLAC upper/lower case issue by reading tags with Audio::Scan +% fixed cd ripping - $out_dir should be $outdir in order run correctly +% fixed encoding to .mp4 & .m4a. Had same issue as Musepack files. + +* updated configure for gnome & kde - neither is installed by default. + you will need to --enable-kde or --enable-gnome if you would like to + have eiher of the plugins installed. + +* updated extra/mod-install*.sh to reflect module changes +* updated %run (put all codedcs in alphabetical order) a little house cleaning.. +* updated default bitrate in pacpl.conf to 192kbps for formats that support it +* updated pacpl.conf - changed default disc device to /dev/dvd + & modified all lang/*.po files to reflect change. + +- removed RAM from codecs.conf (has no encoder) + +9-21-2013 + ++ added --enable-kde (adds Konqueror/Dolphin pacpl.desktop) ++ added --enable-gnome (nautilus script in the works) ***not included...yet*** + ++ added support for amr audio format ++ added support for 3gp audio format ++ added support for 3g2 audio format + += Note: The above three formats only work if your version of ffmpeg/avconv supports them. + see extra/ffmpeg-conf.sh / extra/libav-conf.sh (requires libopencore-amr) + +% fixed spacing error in codecs.conf for DTS + +- removed --enable-konqueror & --enable-dolphin options + +9-18-2013 + ++ added ffmpeg-conf.sh and libav-conf.sh to extra/ dir. + this shows what libs and options are needed for full support for pacpl ++ added support for libav (avconv) encoder/decoder - ffmpeg fork ++ added ffmpeg/avconv support to various formats as available encoder/decoder ++ added support for adts audio format + +% fixed mpc tagging using the new SV7/SV8 releases. (options have to come BEFORE + the input and output file) +% fixed all ffmpeg encode instances to apply $eopts (user options) when + --defopts=0 to the output file as opposed to the input. + +* updated codecs.conf to include new formats that can be configured +* updated extra/README.extra +* update Makefile.am + * use wildcard * for LANG_MODS instead of listing them individually + * remove -t flag for $(INSTALL_DATA) + +9-14-2013 + +* updated extra/mod-install.sh (removed Switch module) +* updated extra/mod-install-kubuntu.sh (renamed to mod-install-ubuntu.sh) + - removed liboggvorbis-perl + + added various required modules/libs for Ogg::Vorbis::Header + + added section to install basic encoders/decoders + + added section to fix apt repository /var/lib/apt/lists + to be able to install restricted-extras package. + = tested in both Ubuntu & Kubuntu 13.04 + + Note: When running the script choose the default yes for all prompts + +9-12-2013 + ++ added support for lowercase tags when writing/reading flac metadata ++ added git repository (https://github.com/vorzox/pacpl) ++ added support for dcaenc (dts) encoder (requires multi-channel wav as input) ++ added support for dts (default encoder/decoder=ffmpeg) + +9-10-2013 + ++ added support for mp3HD audio format ++ added support for aften ac3 encoder ++ added support for twolame mp2 encoder ++ added support for opus audio format ++ added support for off (OptimumFrog - Float) audio format ++ added support for TwinVQ (vqf) audio format (decode only) ++ added Greek/Hellenic translation thanks to Evangelos Apostolakos ++ added required module CDDB (this goes along with CDDB_get) + +- removed amarok support +- removed pacpl gui KMDR +- removed support for d3lphin (obsolete) +- removed --enable-all configuration option (obsolete) +- removed deprecated use of Switch in favor of given-when-default + +* updated README to include new/updated URLs for applications +* updated website pacpl.sourceforge.net (vorzox.wix.com/pacpl) +* update Makefile.am and configure.ac to comply with current standards +* updated slack-desc: changes layout and includes new formats + +% fixed ffmpeg ac3 encoding. specified bitrate was in bits not kilobits +% fixed ffmpeg tag handling...again...thanks to Dave Allen Barker Jr. +% fixed pacpl.desktop to include missing formats +% fixed return 1 when encoding fails +% fixed added MP3::Tag->config(write_v24 => 'YES') to allow updating & + modifying of newer ID3v2 tags.
View file
pacpl-5.1.0.tar.gz/Makefile.am -> pacpl-6.1.0.tar.gz/Makefile.am
Changed
@@ -1,6 +1,6 @@ # Perl Audio Converter # -# Copyright (C) 2005-2014 Philip Lyons (vorzox@gmail.com) +# Copyright (C) 2005-2018 Philip Lyons (vorzox@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -65,30 +65,27 @@ SHELL = /bin/sh # -# Configured directories... -# - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -datarootdir = @datarootdir@ -includedir = @includedir@ -libdir = @libdir@ -mandir = @mandir@ -docdir = @docdir@ - -# # Configuration files directories and other # -CONF_DIR = $(DESTDIR)/etc/$(PACKAGE_NAME) -PO_DIR = $(DESTDIR)/usr/share/pacpl/locale +CONF_DIR = $(DESTDIR)$(sysconfdir)/$(PACKAGE_NAME) +PO_DIR = $(DESTDIR)$(pkgdatadir)/locale MOD_DIR = $(CONF_DIR)/modules DOC_DIR = $(DESTDIR)$(docdir) MAN_DIR = $(DESTDIR)$(mandir)/man1 EXTRA_DIR = $(CONF_DIR)/extra +edit = sed \ + -e 's|@pkgdatadir@|$(pkgdatadir)|g' \ + -e 's|@sysconfdir@|$(sysconfdir)|g' + all : pacpl.1.gz +pacpl: pacpl.in Makefile + rm -f $@ $@.tmp + $(edit) '$@.in' >$@.tmp + mv $@.tmp $@ + chmod +x $@ + pacpl.1.gz : pacpl $(POD2MAN) $< | $(GZIP) -9 > $@ touch $@ @@ -150,14 +147,15 @@ $(RM) config.log $(RM) config.status $(RM) Makefile + $(RM) pacpl find . -name '*~' -exec $(RM) '{}' \; uninstall: uninstall-plugins $(RM) $(DESTDIR)$(bindir)/pacpl $(RM) $(MAN_DIR)/pacpl.1.gz - $(RM) -r $(CONF_DIR) - $(RM) -r $(DOC_DIR) - $(RM) -r $(DESTDIR)/usr/share/pacpl + $(RM) -r $(CONF_DIR)/pacpl + $(RM) -r $(DOC_DIR)/pacpl + $(RM) -r $(DESTDIR)$(pkgdatadir) uninstall-plugins: if INSTALL_KDE @@ -173,4 +171,4 @@ $(RM) $(NEMO_INSTALL_DIR)/PACPL-Convert $(RM) $(NEMO_INSTALL_DIR)/pacpl.nemo_action $(RM) $(ICON_DIR)/pacpl.png -endif \ No newline at end of file +endif
View file
pacpl-5.1.0.tar.gz/Makefile.in -> pacpl-6.1.0.tar.gz/Makefile.in
Changed
@@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -16,7 +16,7 @@ # Perl Audio Converter # -# Copyright (C) 2005-2014 Philip Lyons (vorzox@gmail.com) +# Copyright (C) 2005-2018 Philip Lyons (vorzox@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -269,10 +269,6 @@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ - -# -# Configured directories... -# prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ @@ -311,12 +307,16 @@ # # Configuration files directories and other # -CONF_DIR = $(DESTDIR)/etc/$(PACKAGE_NAME) -PO_DIR = $(DESTDIR)/usr/share/pacpl/locale +CONF_DIR = $(DESTDIR)$(sysconfdir)/$(PACKAGE_NAME) +PO_DIR = $(DESTDIR)$(pkgdatadir)/locale MOD_DIR = $(CONF_DIR)/modules DOC_DIR = $(DESTDIR)$(docdir) MAN_DIR = $(DESTDIR)$(mandir)/man1 EXTRA_DIR = $(CONF_DIR)/extra +edit = sed \ + -e 's|@pkgdatadir@|$(pkgdatadir)|g' \ + -e 's|@sysconfdir@|$(sysconfdir)|g' + all: all-am .SUFFIXES: @@ -341,8 +341,8 @@ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -360,7 +360,10 @@ cscope cscopelist: -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/.^$$\\*/\\\\&/g'`; \ @@ -400,7 +403,7 @@ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -426,7 +429,7 @@ @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -444,7 +447,7 @@ distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -454,7 +457,7 @@ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac @@ -640,6 +643,12 @@ all : pacpl.1.gz +pacpl: pacpl.in Makefile + rm -f $@ $@.tmp + $(edit) '$@.in' >$@.tmp + mv $@.tmp $@ + chmod +x $@ + pacpl.1.gz : pacpl $(POD2MAN) $< | $(GZIP) -9 > $@ touch $@ @@ -691,14 +700,15 @@ $(RM) config.log $(RM) config.status $(RM) Makefile + $(RM) pacpl find . -name '*~' -exec $(RM) '{}' \; uninstall: uninstall-plugins $(RM) $(DESTDIR)$(bindir)/pacpl $(RM) $(MAN_DIR)/pacpl.1.gz - $(RM) -r $(CONF_DIR) - $(RM) -r $(DOC_DIR) - $(RM) -r $(DESTDIR)/usr/share/pacpl + $(RM) -r $(CONF_DIR)/pacpl + $(RM) -r $(DOC_DIR)/pacpl + $(RM) -r $(DESTDIR)$(pkgdatadir) uninstall-plugins: @INSTALL_KDE_TRUE@ $(RM) $(KDE_INSTALL_DIR)/pacpl.desktop
View file
pacpl-5.1.0.tar.gz/NEWS -> pacpl-6.1.0.tar.gz/NEWS
Changed
@@ -1,3 +0,0 @@ -01-03-2014 - Minor Bug Fix Release - -11-01-2013 - Official 5.0.0 Package Released \ No newline at end of file
View file
pacpl-5.1.0.tar.gz/TODO -> pacpl-6.1.0.tar.gz/TODO
Changed
@@ -1,2 +1,4 @@ -Modify to change pacpl.conf (sysconfdir) in configure -same for local man pages + +1: Fix erronous messages produced when ripping cd tracks +2: clean up code and comments througout +3: add missing iOS file format extensions
View file
pacpl-5.1.0.tar.gz/aclocal.m4 -> pacpl-6.1.0.tar.gz/aclocal.m4
Changed
@@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.16.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,7 +20,7 @@ If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.)) -# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# Copyright (C) 2002-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -32,10 +32,10 @@ # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN(AM_AUTOMAKE_VERSION, -am__api_version='1.15' +am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if($1, 1.15, , +m4_if($1, 1.16.1, , AC_FATAL(Do not call $0, use AM_INIT_AUTOMAKE($1).))dnl ) @@ -51,14 +51,14 @@ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN(AM_SET_CURRENT_AUTOMAKE_VERSION, -AM_AUTOMAKE_VERSION(1.15)dnl +AM_AUTOMAKE_VERSION(1.16.1)dnl m4_ifndef(AC_AUTOCONF_VERSION, m4_copy(m4_PACKAGE_VERSION, AC_AUTOCONF_VERSION))dnl _AM_AUTOCONF_VERSION(m4_defn(AC_AUTOCONF_VERSION))) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -110,7 +110,7 @@ # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -143,7 +143,7 @@ # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -230,8 +230,8 @@ AC_REQUIRE(AC_PROG_MKDIR_P)dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> -# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> AC_SUBST(mkdir_p, '$(MKDIR_P)') # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. @@ -298,7 +298,7 @@ Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: <http://www.gnu.org/software/coreutils/>. +that behaves properly: <https://www.gnu.org/software/coreutils/>. If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -340,7 +340,7 @@ done echo "timestamp for $_am_arg" >`AS_DIRNAME("$_am_arg")`/stamp-h$_am_stamp_count) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -361,7 +361,7 @@ fi AC_SUBST(install_sh)) -# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# Copyright (C) 2003-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -382,7 +382,7 @@ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -421,7 +421,7 @@ # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -452,7 +452,7 @@ # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -533,7 +533,7 @@ rm -f conftest.file ) -# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# Copyright (C) 2009-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -593,7 +593,7 @@ _AM_SUBST_NOTMAKE(AM_BACKSLASH)dnl ) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -621,7 +621,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST(INSTALL_STRIP_PROGRAM)) -# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# Copyright (C) 2006-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -640,7 +640,7 @@ # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# Copyright (C) 2004-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it,
View file
pacpl-5.1.0.tar.gz/codecs.conf -> pacpl-6.1.0.tar.gz/codecs.conf
Changed
@@ -48,11 +48,10 @@ FLA = flac,flac -# MP4 / M4A # +# MP4 # # E: faac, ffmpeg, avconv # E: faad, ffmpeg, avconv, mplayer -M4A = faac,faad MP4 = faac,faad # MP3 #
View file
pacpl-5.1.0.tar.gz/configure -> pacpl-6.1.0.tar.gz/configure
Changed
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for pacpl 5.1.0. +# Generated by GNU Autoconf 2.69 for pacpl 6.1.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -576,13 +576,13 @@ # Identity of this package. PACKAGE_NAME='pacpl' PACKAGE_TARNAME='pacpl' -PACKAGE_VERSION='5.1.0' -PACKAGE_STRING='pacpl 5.1.0' +PACKAGE_VERSION='6.1.0' +PACKAGE_STRING='pacpl 6.1.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_default_prefix=/usr -ac_unique_file="pacpl" +ac_unique_file="pacpl.in" ac_subst_vars='LTLIBOBJS LIBOBJS DESTDIR @@ -1260,7 +1260,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pacpl 5.1.0 to adapt to many kinds of systems. +\`configure' configures pacpl 6.1.0 to adapt to many kinds of systems. Usage: $0 OPTION... VAR=VALUE... @@ -1326,7 +1326,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pacpl 5.1.0:";; + short | recursive ) echo "Configuration of pacpl 6.1.0:";; esac cat <<\_ACEOF @@ -1411,7 +1411,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pacpl configure 5.1.0 +pacpl configure 6.1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1428,7 +1428,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pacpl $as_me 5.1.0, which was +It was created by pacpl $as_me 6.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -1777,7 +1777,7 @@ -am__api_version='1.15' +am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2292,7 +2292,7 @@ # Define the identity of the package. PACKAGE='pacpl' - VERSION='5.1.0' + VERSION='6.1.0' cat >>confdefs.h <<_ACEOF @@ -2322,8 +2322,8 @@ # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> -# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The @@ -2374,7 +2374,7 @@ Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: <http://www.gnu.org/software/coreutils/>. +that behaves properly: <https://www.gnu.org/software/coreutils/>. If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -4823,7 +4823,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pacpl $as_me 5.1.0, which was +This file was extended by pacpl $as_me 6.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4876,7 +4876,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/\\""\`\$/\\\\&/g'`" ac_cs_version="\\ -pacpl config.status 5.1.0 +pacpl config.status 6.1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\"
View file
pacpl-5.1.0.tar.gz/configure.ac -> pacpl-6.1.0.tar.gz/configure.ac
Changed
@@ -1,10 +1,10 @@ # Process this file with autoconf to produce a configure script. # -# Copyright (C) 2007-2017 Philip Lyons (vorzox@gmail.com) +# Copyright (C) 2007-2018 Philip Lyons (vorzox@gmail.com) AC_PACKAGE_NAME(Perl Audio Converter) -AC_PACKAGE_TARNAME(pacpl-5.1.0.tar.bz2) -AC_PACKAGE_VERSION(5.1.0) +AC_PACKAGE_TARNAME(pacpl-6.1.0.tar.bz2) +AC_PACKAGE_VERSION(6.1.0) AC_PACKAGE_BUGREPORT(vorzox@gmail.com) m4_include(aclocal/ax_prog_perl_modules.m4) @@ -12,7 +12,7 @@ AC_PROG_PERL_VERSION(5.18.1) AC_PREREQ(2.69) -AC_INIT(pacpl,5.1.0) +AC_INIT(pacpl,6.1.0) AM_INIT_AUTOMAKE @@ -22,7 +22,7 @@ AC_PREFIX_DEFAULT(/usr) AC_PREFIX_PROGRAM(pacpl) -AC_CONFIG_SRCDIR(pacpl) +AC_CONFIG_SRCDIR(pacpl.in) AC_PROG_INSTALL
View file
pacpl-5.1.0.tar.gz/pacpl.conf -> pacpl-6.1.0.tar.gz/pacpl.conf
Changed
@@ -31,7 +31,7 @@ ##################################### # Audio Bitrate # -# Default: 128 +# Default: 320 # voice = 56kbps/mono # fm/radio/tape = 112kbps # mp3 = 128kbps @@ -40,7 +40,7 @@ # studio = 256kbps # high = 320kbps # -BITRATE = 192 +BITRATE = 320 #################### # Sampling Frequency @@ -61,14 +61,14 @@ # levels such as 2.5 are permitted. Normal quality # range is 0 - 10. # -OGGQUAL = 3 +OGGQUAL = 10 ##################### # Speex quality level # # (0-10), default 8 # -SPXQUAL = 8 +SPXQUAL = 10 ######################## # FLAC compression level @@ -103,7 +103,7 @@ # insane extreme high quality, (typ. 232...268 kbps) # braindead extreme high quality, (typ. 232...278 kbps) # -MPCQUAL = radio +MPCQUAL = standard ########################## # OptimFrog (OFR/OFS) mode
View file
pacpl-6.1.0.tar.gz/pacpl.in
Added
@@ -0,0 +1,4075 @@ +#!/usr/bin/perl +# +# Perl Audio Converter +# +# Copyright (C) 2005-2018 Philip Lyons (vorzox@gmail.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +use strict; +use warnings; +use Getopt::Long; +use File::Basename; +use File::Find; +use File::Spec::Functions qw(rel2abs); +use Parallel::ForkManager; + +use feature qw(switch say); + +no if $ >= 5.018, warnings => "experimental::smartmatch"; + +# Tagging modules +use MP3::Tag; +use Audio::FLAC::Header; +use Audio::Scan; + +# CDDB module +use CDDB_get qw(get_cddb); + +# non-encoder/decoder related options +my +( + $to, + $recursive, + $preserve, + $rip, + $help, + $longhelp, + $verbose, + $verinfo, + $dryrun, + $delete, + $keep, + $overwrite, + $formats, + $topdir, + $only, + $first_run, + + @file, + @dir, + + %run, + %lang, +); + +my $silent = "> /dev/null 2>&1"; + +# tagging options +my +( + $title, + $track, + $artist, + $album, + $comment, + $year, + $genre, + $taginfo, +); + +# name and version +my $name = "Perl Audio Converter"; +my $version = "6.1.0"; + +# If these options are toggled, messages/errors will be displayed +# via kdialog or zenity/notify-send (depending on environment) +my ($gui, $kde, $gnome); + +# Debugging (for developer use only) +my $debug = 0; + +# default configuration. +my %config = ( + + IMPORTM => 0, + JOBS => 4, + + DEFOPTS => 1, + EOPTS => '', + DOPTS => '', + NOPTS => '', + + BITRATE => 128, + FREQ => 44100, + CHANNELS => 2, + EFFECT => '', + FCOMP => 2, + PCOMP => 3, + ACOMP => 3000, + OGGQUAL => 3, + SPXQUAL => 8, + AACQUAL => 100, + MPCQUAL => 'radio', + OFMODE => 'normal', + OFOPT => 'fast', + BRATIO => 2, + BQUANL => 1.0, + BPSIZE => 128, + + USE_CDDB => 1, + CDDB_HOST => 'freedb.freedb.org', + CDDB_PORT => 8880, + CDDB_MODE => 'cddb', + CDDB_INPUT => 1, + DEVICE => '/dev/dvd', + NSCHEME => '%ar - %ti', + + ZEN_DIR => 1, + ZEN_OPTS => 1, + KDE_DIR => 1, + KDE_OPTS => 1, + + ); + +# location of configuration file +my $conf_path = "@sysconfdir@/pacpl"; +my $po_dir = "@pkgdatadir@/locale"; +my $mod_dir = "$conf_path/modules"; + +my $conf_file; + +# Icon path +my $icon_path = "$conf_path/pacpl.png"; + +# load the appropriate locale file +load_lang(); + +# try to load configuration file in this order... +my @conf_locations = ( + "$ENV{HOME}/.pacplrc", # Local + "$conf_path/pacpl.conf", # Global + "$ENV{PWD}/pacpl.conf", # Current Directory + ); + +# try to load conf file from one of the above locations +foreach my $i (@conf_locations) { + if (not $conf_file and -e $i) { + $conf_file = $i; + say "$lang{debug} $lang{loaded_config} $conf_file" if $debug == 1; + } +} + +say "$lang{no_config}" if not $conf_file; + +# open config file. +if ($conf_file and -e $conf_file) { + + open(CONF, "$conf_file") or die "$lang{opening_file} $conf_file - $!\n"; + + my @conf_opts = <CONF>; + @conf_opts = grep(!/^#|^$/, @conf_opts); + + close(CONF); + + # now read config file options and change default values accordingly. + foreach (@conf_opts) { + chomp; + my ($k, $v) = split(/\s*=\s*/); + $config{$k} = $v if exists($config{$k}) and length($v); + say "$lang{debug} $k = $v" if $debug == 1 and exists($config{$k}); + } +} + +my $codecs_conf = "$conf_path/codecs.conf"; + +# set default encoders/decoders +sub load_codecs { + + open(CODECS, "$codecs_conf") or die "$lang{opening_file} $codecs_conf - $!\n"; + + my @codecs = <CODECS>; + @codecs = grep(!/^$|^#/, @codecs); + @codecs = grep(s/^\s*|\s*$//, @codecs); + + close(CODECS); + + foreach (@codecs) { + + chomp; + my ($k, $v) = split(/\s*=\s*/); + my ($e, $d) = split(/,/, $v); + + $k =~ tr/A-Z/a-z/; + + $run{$k}{DEFAULT_ENCODER} = $e if (exists($run{$k}{DEFAULT_ENCODER})); + $run{$k}{DEFAULT_DECODER} = $d if (exists($run{$k}{DEFAULT_DECODER})); + } +} + +# load po file and store in %lang hash +sub load_lang { + + my $po = "$po_dir/$ENV{LANG}.po"; + $po =~ s/\.UTF-8//i if $po =~ /UTF-8/i; + $po =~ s/\.utf8//i if $po =~ /utf8/i; + $po =~ s/_\w+// if not -e $po; + $po = "$po_dir/en_US.po" if not -e $po; + + open(LANG, "< $po") or die "error: could not open - $po\n$!\n"; + + my @data = <LANG>; + @data = grep(!/^#|^$/, @data); + + close(LANG); + + foreach (@data) { + chomp; + s/=/__EQ__/; + my ($k, $v) = split(/\s*__EQ__\s*/, $_); + $lang{$k} = $v; + } + +} + +my $banner = 1; + +# print error messages +sub perror { + my ($key, $msg) = @_; + say "$name - $version\n"; + say "$lang{error}: $lang{$key} $msg" . "\n"; + system("kdialog --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $kde; + system("zenity --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $gnome; + die "$lang{seek_help}\n"; +} + +# print notices/warnings +sub pnotice { + + my ($key, $msg, $nm) = @_; + + say "$name - $version\n" if $banner == 1; + print "$lang{$key} $msg"; + say '' if $nm == 1; + say "\n" if $nm == 2; + + $banner = 0; +} + +# defaults for user variables. +my $outfile; +my $outdir; +my $defopts = $config{DEFOPTS}; +my $eopts = $config{EOPTS}; +my $dopts = $config{DOPTS}; +my $nopts = $config{NOPTS}; +my $normalize = $config{NOPTS}; +my $bitrate = $config{BITRATE}; +my $freq = $config{FREQ}; +my $channels = $config{CHANNELS}; +my $effect = $config{EFFECT}; +my $fcomp = $config{FCOMP}; +my $acomp = $config{ACOMP}; +my $oggqual = $config{OGGQUAL}; +my $spxqual = $config{SPXQUAL}; +my $aacqual = $config{AACQUAL}; +my $mpcqual = $config{MPCQUAL}; +my $ofmode = $config{OFMODE}; +my $ofopt = $config{OFOPT}; +my $bratio = $config{BRATIO}; +my $bquanl = $config{BQUANL}; +my $bpsize = $config{BPSIZE}; + +my $cdinfo; +my $nocddb; +my $noinput; +my $device = $config{DEVICE}; +my $nscheme = $config{NSCHEME}; +my $my_encoder; +my $my_decoder; +my $encoder; +my $decoder; + +my $jobs = $config{JOBS}; + +# command line options +GetOptions +( + 't|to=s' => \$to, + 'r|recursive' => \$recursive, + 'p|preserve' => \$preserve, + 'h|help' => \$help, + 'l|longhelp' => \$longhelp, + 'v|verbose' => \$verbose, + 'f|formats' => \$formats, + 'o|only=s' => \$only, + 'k|keep' => \$keep, + 'j|jobs=n' => \$jobs, + + 'taginfo' => \$taginfo, + + 'version' => \$verinfo, + 'dryrun' => \$dryrun, + 'delete' => \$delete, + 'overwrite' => \$overwrite, + 'normalize' => \$normalize, + 'encoder=s' => \$my_encoder, + 'decoder=s' => \$my_decoder, + + 'title=s' => \$title, + 'track=n' => \$track, + 'artist=s' => \$artist, + 'album=s' => \$album, + 'comment=s' => \$comment, + 'year=n' => \$year, + 'genre=s' => \$genre, + + 'gui' => \$gui, + 'kde' => \$kde, + 'gnome' => \$gnome, + + 'eopts=s' => \$eopts, + 'dopts=s' => \$dopts, + 'defopts=n' => \$defopts, + 'nopts=s' => \$nopts, + 'outfile=s' => \$outfile, + 'outdir=s' => \$outdir, + + 'bitrate=n' => \$bitrate, + 'freq=n' => \$freq, + 'channels=n' => \$channels, + 'effect=s' => \$effect, + 'fcomp=n' => \$fcomp, + 'acomp=n' => \$acomp, + 'oggqual=n' => \$oggqual, + 'spxqual=n' => \$spxqual, + 'aacqual=n' => \$aacqual, + 'mpcqual=s' => \$mpcqual, + 'ofmode=s' => \$ofmode, + 'ofopt=s' => \$ofopt, + 'bratio=n' => \$bratio, + 'bquanl=n' => \$bquanl, + 'bpsize=n' => \$bpsize, + + 'rip=s' => \$rip, + 'nocddb' => \$nocddb, + 'noinput' => \$noinput, + 'device=s' => \$device, + 'nscheme=s' => \$nscheme, + 'cdinfo' => \$cdinfo, +); + +if (defined($preserve) && !defined($outdir)) { + die "You must specify --outdir when you use --preserve option. See man page.\n"; +} + +$silent = '' if $verbose; + +my $opts; +my $total_converted = 0; +my $total_failed = 0; + +# Initialize the fork manager with a count set through pacpl.conf or via the command line +my $pm = Parallel::ForkManager->new($jobs); + +# conversion options. when adding a new format, +# wild card %i = input file and %o = output file +%run = ( + + '3g2' => { + + DEFAULT_ENCODER => 'ffmpeg', + DEFAULT_DECODER => 'ffmpeg', + + ENCODER => { + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = "-ar 8000 -ac 1" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { NONE => 0, }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ar 8000 -ac 1" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { NONE => 0, }, + }, + + }, + + DECODER => { + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "-y -i %o $dopts %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "-y -i %o %dopts %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + + }, + + '3gp' => { + + DEFAULT_ENCODER => 'ffmpeg', + DEFAULT_DECODER => 'ffmpeg', + + ENCODER => { + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = "-ar 8000 -ac 1" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { NONE => 0, }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ar 8000 -ac 1" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { NONE => 0, }, + }, + + }, + + DECODER => { + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "-y -i %o $dopts %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "-y -i %o %dopts %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + + }, + + aac => { + + DEFAULT_ENCODER => "faac", + DEFAULT_DECODER => "faad", + + ENCODER => { + faac => { + NAME => "faac", + ESTR => sub { + $opts = "-q $aacqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i -o %o" + }, + PROMPT => { AACQUAL => 1 }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 1, + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + faad => { + NAME => "faad", + DSTR => sub { "$dopts -o %i %o" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + ac3 => { + + DEFAULT_ENCODER => "ffmpeg", + DEFAULT_DECODER => "ffmpeg", + + ENCODER => { + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => "avconv", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + aften => { + NAME => "aften", + ESTR => sub { + $opts = "-v 1 -q $bitrate -2" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + + PROMPT => { + BITRATE => 1, + }, + }, + + }, + + DECODER => { + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => "avconv", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + adts => { + + DEFAULT_ENCODER => 'ffmpeg', + DEFAULT_DECODER => 'ffmpeg', + + ENCODER => { + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $opts $eopts -strict -2 %o" + }, + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $opts $eopts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + ffmpeg => { + NAME => 'ffmpeg', + DSTR => "$dopts -y -i %i %o", + }, + + avconv => { + NAME => 'avconv', + DSTR => "$dopts -y -i %i %o", + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + ape => { + + DEFAULT_ENCODER => "mac", + DEFAULT_DECODER => "mac", + + ENCODER => { + mac => { + NAME => "mac", + ESTR => sub { + $opts = "-c$acomp" if $defopts == 1; + $opts = '' if $defopts == 0; + "%i %o $opts $eopts" + }, + + PROMPT => { ACOMP => 1 }, + }, + }, + + DECODER => { + mac => { + NAME => "mac", + DSTR => sub { "%i %o -d $dopts" }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "-y -i %i %dopts %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "-y -i %i $dopts %o" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 0, + MODULE => "Audio::Scan", + }, + }, + + amr => { + + DEFAULT_ENCODER => "ffmpeg", + DEFAULT_DECODER => "ffmpeg", + + ENCODER => { + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ar 8000 -ac 1" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { NONE => 0, }, + }, + + avconv => { + NAME => "avconv", + ESTR => sub { + $opts = "-ar 8000 -ac 1" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { NONE => 0, }, + }, + + }, + + DECODER => { + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "-y -i %i $dopts %o" }, + }, + + avconv => { + NAME => 'ffmpeg', + DSTR => sub { "-y -i %i %dopts %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + + }, + + bonk => { + + DEFAULT_ENCODER => "bonk", + DEFAULT_DECODER => "bonk", + + ENCODER => { + bonk => { + NAME => "bonk", + ESTR => sub { + $opts = "-q $bquanl -b $bratio -s $bpsize" if $defopts == 1; + $opts = '' if $defopts == 0; + "encode $eopts $opts %i -o %o" + }, + + PROMPT => { + BQUANL => 1, + BRATIO => 1, + BPSIZE => 1, + }, + }, + }, + + DECODER => { + bonk => { + NAME => "bonk", + DSTR => sub { "decode %i -o %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + dts => { + + DEFAULT_ENCODER => 'ffmpeg', + DEFAULT_DECODER => 'ffmpeg', + + ENCODER => { + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = '' if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $opts $eopts -strict -2 -codec:a libfaac %o" + }, + + PROMPT => { NONE => 0, }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = '' if $defopts == 1 or $defopts == 0; + "-y -i %i $opts $eopts -codec:a libfaac %o", + }, + PROMPT => { NONE => 0, }, + }, + + dcaenc => { + NAME => 'dcaenc', + ESTR => sub { + $opts = "$bitrate" if $defopts == 0; + $opts = '' if $defopts == 1; + "%i %o $opts" + }, + + PROMPT => { NONE => 0, }, + }, + }, + + DECODER => { + ffmpeg => { + NAME => 'ffmpeg', + DSTR => "$dopts -y -i %i %o", + }, + + avconv => { + NAME => 'avconv', + DSTR => "$dopts -y -i %i %o", + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + flac => { + + DEFAULT_ENCODER => "flac", + DEFAULT_DECODER => "flac", + + ENCODER => { + flac => { + NAME => "flac", + ESTR => sub { + $opts = "-$fcomp" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts -f $opts %i -o %o" + }, + PROMPT => { FCOMP => 1 }, + }, + + flake => { + NAME => "flake", + ESTR => sub { + $opts = "-$fcomp" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i -o %o" + }, + PROMPT => { FCOMP => 1 }, + }, + + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 1; + "-y -i %i $eopts $opts %o" + }, + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + flac => { + NAME => "flac", + DSTR => sub { "$dopts -f -d %i -o %o" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "Audio::FLAC::Header", + }, + }, + + fla => { + + DEFAULT_ENCODER => "flac", + DEFAULT_DECODER => "flac", + + ENCODER => { + flac => { + NAME => "flac", + ESTR => sub { + $opts = "-$fcomp" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts -f $opts %i -o %o" + }, + PROMPT => { FCOMP => 1 }, + }, + }, + + DECODER => { + flac => { + NAME => "flac", + DSTR => sub { "$dopts -f -d %i -o %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "Audio::FLAC::Header", + }, + }, + + la => { + + DEFAULT_ENCODER => "la", + DEFAULT_DECODER => "la", + + ENCODER => { + la => { + NAME => "la", + ESTR => sub { "-overwrite $eopts %i %o" }, + PROMPT => { NONE => 0, }, + }, + }, + + DECODER => { + la => { + NAME => "la", + ESTR => sub { "-console $dopts %i > %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + mp2 => { + + DEFAULT_ENCODER => "ffmpeg", + DEFAULT_DECODER => "ffmpeg", + + ENCODER => { + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + toolame => { + NAME => 'toolame', + ESTR => sub { + $opts = "-b $bitrate" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + + PROMPT => { + BITRATE => 1, + }, + }, + + twolame => { + NAME => 'twolame', + ESTR => sub { + $opts = "-b $bitrate -s $freq" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + }, + }, + + sox => { + NAME => 'sox', + ESTR => sub { + $opts = "-c $channels -r $bitrate" if $defopts == 1; + $opts = '' if $defopts == 0; + "%i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + + ffmpeg => { + NAME => 'ffmpeg', + DSTR => "$dopts -y -i %i %o", + }, + + avconv => { + NAME => 'avconv', + DSTR => "%dopts -y -i %i %o", + }, + + mplayer => { + NAME => 'mplayer', + DSTR => "-vc null -vo null -ao pcm:file=%o %i", + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + mp3 => { + + DEFAULT_ENCODER => "lame", + DEFAULT_DECODER => "lame", + + ENCODER => { + lame => { + NAME => "lame", + ESTR => sub { + $opts = "--resample $freq -b $bitrate -h" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + }, + }, + + bladeenc => { + NAME => "bladeenc", + ESTR => sub { + $opts = "-br $bitrate" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + PROMPT => { BITRATE => 1 }, + }, + + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts -y -i %i $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + sox => { + NAME => "sox", + ESTR => sub { + $opts = "-r $freq -c $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "%i $eopts $opts %o" + }, + + PROMPT => { + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + lame => { + NAME => "lame", + DSTR => sub { "$dopts --decode %i %o" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %O" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + + sox => { + NAME => "sox", + DSTR => sub { "%i $dopts %o" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "MP3::Tag", + }, + }, + + mp3hd => { + + DEFAULT_ENCODER => "mp3hdEncoder", + DEFAULT_DECODER => "mp3hdDecoder", + + ENCODER => { + mp3hdEncoder => { + NAME => "mp3hdEncoder", + ESTR => sub { + $opts = "-br $bitrate" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts -if %i -of %o" + }, + PROMPT => { BITRATE => 1 }, + }, + }, + + DECODER => { + mp3hdDecoder => { + NAME => "mp3hdDecoder", + DSTR => sub { "$dopts -if %i -of %o" }, + }, + }, + + TAGS => { + WRITE => 1, + READ => 1, + MODULE => "MP3::Tag", + }, + }, + + mp4 => { + + DEFAULT_ENCODER => "faac", + DEFAULT_DECODER => "faad", + + ENCODER => { + + faac => { + NAME => "faac", + ESTR => sub { + $opts = "-q $aacqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts -w $opts %i -o %o" + }, + PROMPT => { AACQUAL => 1 }, + }, + + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PRIMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + + faad => { + NAME => "faad", + DSTR => sub { "$dopts -o %o %i" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "Audio::Scan", + }, + }, + + # m4a container with AAC codec + mp4a => { + + DEFAULT_ENCODER => "faac", + DEFAULT_DECODER => "faad", + + ENCODER => { + + faac => { + NAME => "faac", + ESTR => sub { + $opts = "-q $aacqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts -w $opts %i -o %o" + }, + PROMPT => { AACQUAL => 1 }, + }, + + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts -y -i %i $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + + faad => { + NAME => "faad", + DSTR => sub { "$dopts -o %o %i" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + + }, + + ESTR => sub { "$eopts -w -q $aacqual %i -o %o" }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "Audio::Scan", + }, + }, + + # m4a container with ALAC codec + alac => { + + DEFAULT_ENCODER => undef, + DEFAULT_DECODER => "alac-decoder", + + DECODER => { + + 'alac-decoder' => { + NAME => "alac-decoder", + DSTR => sub { "$dopts -f %o %i" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + + }, + + TAGS => { + READ => 1, + WRITE => 0, + MODULE => "Audio::Scan", + }, + }, + + m4b => { + + DEFAULT_ENCODER => undef, + DEFAULT_DECODER => "faad", + + DECODER => { + faad => { + NAME => "faad", + DSTR => sub { "$dopts -o %o %i" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 1, + MODULE => undef, + }, + }, + + mpc => { + + DEFAULT_ENCODER => "mpcenc", + DEFAULT_DECODER => "mpcdec", + + ENCODER => { + + mpcenc => { + NAME => "mpcenc", + ESTR => sub { + $opts = "--$mpcqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts --overwrite $opts %i %o" + }, + PROMPT => { MPCQUAL => 1 }, + }, + }, + + DECODER => { + + mpcdec => { + NAME => "mpcdec", + DSTR => sub { "$dopts %i %o" }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "Audio::Scan", + }, + + PROMPT => { + MPCQUAL => 1, + }, + }, + + mpp => { + + DEFAULT_ENCODER => "mpcenc", + DEFAULT_DECODER => "mpcdec", + + ENCODER => { + + mpcenc => { + NAME => "mpcenc", + ESTR => sub { + $opts = "--$mpcqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts --overwrite $opts %i %o" + }, + PROMPT => { MPCQUAL => 1 }, + }, + }, + + DECODER => { + + mpcdec => { + NAME => "mpcdec", + DSTR => sub { "$dopts %i %o" }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "Audio::Scan", + }, + }, + + off => { + DEFAULT_ENCODER => 'off', + DEFAULT_DECODER => 'off', + + ENCODER => { + off => { + NAME => 'off', + ESTR => sub { + $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts --overwrite $opts %i --output %o" + }, + + PROMPT => { + OFMODE => 1, + OFOPT => 1, + }, + }, + }, + + DECODER => { + off => { + NAME => 'off', + DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + ofr => { + + DEFAULT_ENCODER => "ofr", + DEFAULT_DECODER => "ofr", + + ENCODER => { + ofr => { + NAME => "ofr", + ESTR => sub { + $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts --overwrite $opts %i --output %o" + }, + + PROMPT => { + OFMODE => 1, + OFOPT => 1, + }, + }, + }, + + DECODER => { + ofr => { + NAME => "ofr", + DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + ofs => { + + DEFAULT_ENCODER => "ofs", + DEFAULT_DECODER => "ofs", + + ENCODER => { + ofs => { + NAME => "ofs", + ESTR => sub { + $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts --overwrite $opts %i --output %o" + }, + + PROMPT => { + OFMODE => 1, + OFOPT => 1, + }, + }, + }, + + DECODER => { + ofs => { + NAME => "ofs", + DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + + oga => { + DEFAULT_ENCODER => 'oggenc', + DEFAULT_DECODER => 'oggdec', + + ENCODER => { + oggenc => { + NAME => 'oggenc', + ESTR => sub { + $opts = "--resample $freq -q $oggqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + PROMPT => { + FREQ => 1, + OGGQUAL => 1, + }, + }, + + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + sox => { + NAME => "sox", + ESTR => sub { + $opts = "-r $freq -c $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "%i $eopts $opts %o" + }, + + PROMPT => { + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + oggdec => { + NAME => "oggdec", + DSTR => sub { "$dopts %i --output %o" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + + sox => { + NAME => "sox", + DSTR => sub { "%i $dopts %o" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "vorbiscomment", + }, + }, + + ogg => { + + DEFAULT_ENCODER => "oggenc", + DEFAULT_DECODER => "oggdec", + + ENCODER => { + oggenc => { + NAME => "oggenc", + ESTR => sub { + $opts = "--resample $freq -q $oggqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i -o %o" + }, + + PROMPT => { + FREQ => 1, + OGGQUAL => 1, + }, + }, + + ffmpeg => { + NAME => "ffmpeg", + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + FREQ => 1, + CHANNELS => 1, + }, + }, + + sox => { + NAME => "sox", + ESTR => sub { + $opts = "-r $freq -c $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "%i $eopts $opts %o" + }, + + PROMPT => { + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + oggdec => { + NAME => "oggdec", + DSTR => sub { "$dopts %i --output %o" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + + sox => { + NAME => "sox", + DSTR => sub { "%i $dopts %o" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "vorbiscomment", + }, + }, + + opus => { + + DEFAULT_ENCODER => "opusenc", + DEFAULT_DECODER => "opusdec", + + ENCODER => { + opusenc => { + NAME => 'opusenc', + ESTR => sub { + $opts = "--bitrate $bitrate" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + PROMTP => { + BITRATE => 1, + }, + }, + }, + + DECODER => { + opusdec => { + NAME => 'opusdec', + DSTR => sub { "--force-wav %i %o" }, + PROMPT => { NONE => 0 }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + raw => { + + DEFAULT_ENCODER => "sox", + DEFAULT_DECODER => "sox", + + ENCODER => { + sox => { + NAME => 'sox', + ESTR => sub { + $opts = "-r $freq -c $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "%i $opts $eopts %o $effect" + }, + + PROMPT => { + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + sox => { + NAME => 'sox', + DSTR => sub { "-w -s -r $freq -c $channels $dopts %i %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + rm => { + + DEFAULT_ENCODER => 'ffmpeg', + DEFAULT_DECODER => 'ffmpeg', + + ENCODER => { + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = "-ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + FREQ => 1, + CHANNELS => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "-ar $freq -ac $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + FREQ => 1, + CHANNELS => 1, + }, + }, + }, + + DECODER => { + mplayer => { + NAME => 'mplayer', + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + shn => { + + DEFAULT_ENCODER => "shorten", + DEFAULT_DECODER => "shorten", + + ENCODER => { + shorten => { + NAME => "shorten", + ESTR => sub { + $opts = "-c $channels" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + PROMPT => { CHANNELS => 1 }, + }, + }, + + DECODER => { + shorten => { + NAME => "shorten", + DSTR => sub { "-x %i %o" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + spx => { + + DEFAULT_ENCODER => "speexenc", + DEFAULT_DECODER => "speexdec", + + ENCODER => { + speexenc => { + NAME => "speexenc", + ESTR => sub { + $opts = "--quality $spxqual" if $defopts == 1; + $opts = '' if $defopts == 0; + "$eopts $opts %i %o" + }, + PROMPT => { SPXQUAL => 1 }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { + $opts = "--bitrate $bitrate.k" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i %i $eopts $opts %o" + }, + + PROMPT => { + BITRATE => 1, + }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { + $opts = "--bitrate $bitrate.k" if $defopts == 1; + $opts = '' if $defopts == 0; + "-y -i $eopts $opts %o" + }, + PROMPT => { + BITRATE => 1, + }, + }, + }, + + DECODER => { + speexdec => { + NAME => "speexdec", + DSTR => sub { "$dopts %i %o" }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => undef, + }, + }, + + tta => { + + DEFAULT_ENCODER => "ttaenc", + DEFAULT_DECODER => "ttaenc", + + ENCODER => { + ttaenc => { + NAME => "ttaenc", + ESTR => sub { "$eopts -e %i -o %o" }, + PROMPT => { NONE => 0, }, + }, + }, + + DECODER => { + ttaenc => { + NAME => "ttaenc", + DSTR => sub { "$dopts -d %i -o %o" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + wav => { + + DEFAULT_ENCODER => "mv", + DEFAULT_DECODER => "cp", + + ENCODER => { + mv => { + NAME => "mv", + ESTR => sub { "%i %o" }, + PROMPT => { NONE => 0, }, + }, + }, + + DECODER => { + cp => { + NAME => "cp", + DSTR => sub { "%i %o" }, + } + }, + + TAGS => { + READ => 0, + WRITE => 0, + MODULE => undef, + }, + }, + + wv => { + + DEFAULT_ENCODER => "wavpack", + DEFAULT_DECODER => "wvunpack", + + ENCODER => { + wavpack => { + NAME => "wavpack", + ESTR => sub { "$eopts -h -y %i -o %o" }, + PROMPT => { NONE => 0, }, + }, + + ffmpeg => { + NAME => 'ffmpeg', + ESTR => sub { "-y -i %i $eopts %o" }, + PROMPT => { NONE => 0, }, + }, + + avconv => { + NAME => 'avconv', + ESTR => sub { "-y -i %i $eopts %o" }, + PROMPT => { NONE => 0, }, + }, + }, + + DECODER => { + wvunpack => { + NAME => "wvunpack", + DSTR => sub { "$dopts -y %i -o %o" }, + }, + + ffmpeg => { + NAME => "ffmpeg", + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + avconv => { + NAME => 'avconv', + DSTR => sub { "$dopts -y -i %i %o" }, + }, + + mplayer => { + NAME => "mplayer", + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + }, + + TAGS => { + READ => 1, + WRITE => 1, + MODULE => "Audio::Scan", + }, + }, +); + +# supported ffmpeg/avconv formats (decode only) +my @ffmpeg_codecs = ( "mmf", "ra", "wma" ); +my @ffmpeg_forks = ( "avconv", "ffmpeg" ); + +foreach my $fork (@ffmpeg_forks) { + + foreach my $codec (@ffmpeg_codecs) { + + $run{$codec}{DEFAULT_ENCODER} = $fork; + $run{$codec}{DEFAULT_DECODER} = $fork; + $run{$codec}{ENCODER}{$fork}{NAME} = $fork; + $run{$codec}{DECODER}{$fork}{NAME} = $fork; + $run{$codec}{DECODER}{$fork}{DSTR} = sub {"-y -i %i $dopts %o"}; + $run{$codec}{ENCODER}{$fork}{ESTR} = sub {"-y -i %i $eopts -ab $bitrate.k -ar $freq -ac $channels %o"}; + $run{$codec}{TAGS}{READ} = 0; + $run{$codec}{TAGS}{WRITE} = 0; + $run{$codec}{TAGS}{MODULE} = undef; + } + +} + +# support reading of WMA tags via Audio::Scan +$run{wma}{TAGS}{READ} = 1; +$run{wma}{TAGS}{MODULE} = "Audio::Scan"; + +# supported video to audio types +my @movie_codecs = ( + "rv", "asf", "avi", "divx", + "mkv", "mpg", "mpeg", "mov", + "ogm", "qt", "vcd", "vob", + "wmv", "flv", "svcd", "m4v", + "nsv", "nuv", "psp", "smk", + "ogv", "webm", + + # decode only audio formats + "vqf", "tak", + ); + +foreach (@movie_codecs) { + $run{$_}{DEFAULT_ENCODER} = undef; + $run{$_}{DEFAULT_DECODER} = "ffmpeg"; + $run{$_}{DECODER}{mplayer}{NAME} = "mplayer"; + $run{$_}{DECODER}{ffmpeg}{NAME} = "ffmpeg"; + $run{$_}{DECODER}{mplayer}{DSTR} = sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }; + $run{$_}{DECODER}{ffmpeg}{DSTR} = sub { "$dopts -i %i %o"; }; + $run{$_}{TAGS}{READ} = 0; + $run{$_}{TAGS}{WRITE} = 0; + $run{$_}{TAGS}{MODULE} = undef; +} + +# supported sndfile-convert formats +my @sndfile = ( + "pvf", "caf", "sf", "paf", "fap", "sd2", + "mat4", "mat5", "mat", "ircam", "w64", "nist", + "rf64", + ); + +foreach (@sndfile) { + + $run{$_}{DEFAULT_ENCODER} = "sndfile-convert"; + $run{$_}{DEFAULT_DECODER} = "sndfile-convert"; + $run{$_}{ENCODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; + $run{$_}{DECODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; + $run{$_}{ENCODER}{"sndfile-convert"}{ESTR} = sub { "$eopts %i %o" }; + $run{$_}{DECODER}{"sndfile-convert"}{DSTR} = sub { "$dopts %i %o" }; + $run{$_}{TAGS}{READ} = 0; + $run{$_}{TAGS}{WRITE} = 0; + $run{$_}{TAGS}{MODULE} = undef; +} + +# supported sox formats +my @sox_codecs = ( + "aiff", "aif", "au", "snd", "voc", + "smp", "avr", "cdr", "8svx", "amb", + "dat", "dvms", "f32", "f64", "fssd", + "gsrt", "hcom", "txw", "vms", "al", + "sou", "ima", "prc", "cvu", + "maud", + ); + +foreach (@sox_codecs) { + + $run{$_}{DEFAULT_ENCODER} = "sox"; + $run{$_}{DEFAULT_DECODER} = "sox"; + $run{$_}{ENCODER}{sox}{NAME} = "sox"; + $run{$_}{DECODER}{sox}{NAME} = "sox"; + $run{$_}{ENCODER}{sox}{ESTR} = sub { "%i -r $freq -c $channels $eopts %o $effect" }; + $run{$_}{DECODER}{sox}{DSTR} = sub { "%i $dopts %o" }; + $run{$_}{TAGS}{READ} = 0; + $run{$_}{TAGS}{WRITE} = 0; + $run{$_}{TAGS}{MODULE} = undef; + + $run{$_}{ENCODER}{sox}{PROMPT}{FREQ} = 1; + $run{$_}{ENCODER}{sox}{PROMPT}{CHANNELS} = 1; + +} + +# load codecs.conf file +load_codecs() if -e $codecs_conf; + +my $out_name = $outfile; +my $out_dir = $outdir; +my $first_message = 1; +my %files; +my $number = 0; + +# process all files and directories +sub proc_input { + + $to =~ tr/A-Z/a-z/; + + perror("bad_input","") unless(exists($run{$to})); + + proc_preserve_dir($dir0) if @dir and $preserve; # process recursive directory preservation (sends to proc_files + proc_dirs() if @dir and not $preserve; # process directories including recursively (sends to proc_files) + proc_files() if @file; # process all files + fork_files(); # start the conversion process. +} + +# process all files (all roads lead to rome) +sub proc_files { + + if (@file) { + + foreach my $i (sort(@file)) { + + my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); + + $ext =~ s/^\.//; + $dir = rel2abs($dir); + $outdir = $dir if not defined($out_dir) and not $preserve; + $outdir = $out_dir if $preserve; + + my $if = $ext; + $if =~ tr/A-Z/a-z/; + + $only =~ tr/A-Z/a-z/ if $only; + + next if $only and $if ne $only; + + $encoder = $my_encoder if defined($my_encoder); + $decoder = $my_decoder if defined($my_decoder); + + $encoder = $run{$to}{DEFAULT_ENCODER} if not $my_encoder; + my $codec = ( $if eq "m4a" ? Audio::Scan->scan_info($i)->{info}->{tracks}0->{encoding} : $if ); + $decoder = $run{$codec}{DEFAULT_DECODER} if not $my_decoder; + + if (-e "$dir/$file.$to" and not $overwrite) { + pnotice("overwrite","$file.$to",1); + $total_failed++; + next; + } + + if (check_input($file,$dir,$codec) == 0) { + + pnotice("unk_encoder","$file.$ext",1), next unless(exists($run{$to}{ENCODER}{$encoder})); + pnotice("unk_decoder","$file.$ext",1), next unless(exists($run{$codec}{DECODER}{$decoder})); + + get_visual_opts($to,$outdir) if $gui and not defined($first_run); + + $first_run = 1; + + perror("multi_out","") if (defined($out_name) and $#file gt 0 or defined($out_name) and @dir); + perror("no_outdir","") if (not -e $outdir and not -d $outdir); + + $outfile = "$file" if not $out_name; + + if ($keep and $if eq $to) { + system("cp -v \"$dir/$file.$ext\" \"$outdir/$outfile.$ext\"") if $outdir ne $dir and not -e "$outdir/$outfile.$ext"; + next if $outdir eq $dir; + } + + else { + $files{"FILE$number"}{FILE} = "$dir/$file"; + $files{"FILE$number"}{OUTF} = "$outdir/$outfile"; + $files{"FILE$number"}{EXT} = "$ext"; + $files{"FILE$number"}{CODEC} = "$codec"; + $files{"FILE$number"}{NAME} = "$file"; + $files{"FILE$number"}{OUTD} = "$outfile"; + $files{"FILE$number"}{DECODER} = "$decoder"; + + $number++; + } + + } + } + } + undef(@file); +} + +# process directories and push all to @file arrary +sub proc_dirs { + + if (@dir) { + + my @tmp_dir = @dir; + undef(@dir); + $topdir = $tmp_dir0; + + if (not $recursive) { + + undef(@file); + + foreach my $d (@tmp_dir) { + + opendir(DIR, "$d") or perror("opening_dir","$d: $!"); + my @dir_files = readdir(DIR); + closedir(DIR); + perror("empty_dir","$d") if $#dir_files <= 1; + + foreach my $f (@dir_files) { + + if (not -d $f and not -d "$d/$f") { + push(@file, "$d/$f"); + undef($out_name); + } + } + } + + proc_files(); + return 0; + + } + + elsif ($recursive) { + + if (not $preserve) { + + undef(@file); + + foreach my $r (@tmp_dir) { + + $r = rel2abs($r); + + find ( sub { + my $rfile = $File::Find::name; + push(@file, $rfile) if not -d $rfile; + }, $r + ); + } + + proc_files(); + return 0; + + } + } + + } +} + +# preserve directory structuer (revised 10-7-2013) +my $out_dir_original = rel2abs($outdir) if $outdir and -d $outdir; + +sub proc_preserve_dir { + +$topdir = rel2abs($dir0); + +perror("no_outdir","") if not defined($out_dir_original); +perror("no_outdir","") if not -d $out_dir_original; + +undef(@file); # clear the array before we begin. + +find ( sub { + my $val = $File::Find::name; + $val =~ s/(\$)/\\\$/g; + + if ($val ne $topdir) { + + $val =~ s/$topdir\///; + + # create mirrored directories in output directory + if (not -f fileparse("$topdir/$val") and not -d "$out_dir_original/$val") { + say "creating directory $out_dir_original/$val" if not -f "$topdir/$val" and $verbose; + mkdir("$out_dir_original/$val", 0755) if not -f "$topdir/$val"; + } + + # this will list all files in their original directories + if (-f "$topdir/$val") { + say "$lang{debug} pushing to \@file: $topdir/$val" if $debug == 1; + push(@file, "$topdir/$val"); + } + + # set $out_dir to the + $out_dir = "$out_dir_original/" . dirname($val) if -f "$topdir/$val"; + + # send file, and output dir to proc_files(); + proc_files(); + } + + }, $topdir + ); +} + +# convert input to destination format +sub convert { + + my ($inf, $outf, $infmt, $iname, $oname, $codec, $dec) = @_; + + my $if = $infmt; + $if =~ tr/A-Z/a-z/; + + clear_tag_hash() if not $rip; + + # catch ^C. will have to be pressed repeatedly to exit the process. + $SIG{INT} = sub { + unlink("$outf.$$.wav"); + kill 9, $$; + }; + + # check to see if encoder/decoder exists. if not, see if we have one + # that supports the desired input/output formats. + $decoder = $dec; + check_encoder(); + check_decoder($codec); + + my $decode_string = $run{$codec}{DECODER}{$decoder}{DSTR}->(); + $decode_string =~ s/%i/\"$inf.$infmt\"/; + $decode_string =~ s/%o/\"$outf.$$.wav\"/; + $decode_string =~ s/(\$|\\)/\\$1/g; + + pnotice("debug","\n$run{$codec}{DECODER}{$decoder}{NAME} $decode_string", 2) if $dryrun; + + # decode input file to temporary wav + system("$run{$codec}{DECODER}{$decoder}{NAME} $decode_string $silent") if not $dryrun; + + # remove temporary wav file and die if decode fails + if ($? > 0) { + unlink("$outf.$$.wav") if -e "$outf.$$.wav"; + say ""; + $banner = 0; + pnotice("decode_failed","$inf.$infmt: try with --verbose",1); + return 1; + } + + # normalize wav file before encoding to output format + perror("no_app","normalize") if $normalize and not `which normalize 2>/dev/null`; + system("normalize $nopts \"$outf.$$.wav\"") if $normalize; + + # copy meta-data from input file to %tag_name + read_tags("$inf.$infmt", "$codec") if $run{$codec}{TAGS}{READ} == 1 and not $dryrun; + + my $tag_opts = format_tags($to); # tag options for mp4/m4a/m4b/mpc/mpp/bonk/spx/wv + + my $encode_string = $run{$to}{ENCODER}{$encoder}{ESTR}->(); + $encode_string =~ s/%i/$tag_opts \"$outf.$$.wav\"/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "faac" or $encoder eq "mpcenc"; + $encode_string =~ s/%i/\"$outf.$$.wav\" $tag_opts/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "ffmpeg" or $encoder eq "avconv"; + $encode_string =~ s/%i/\"$outf.$$.wav\"/ if $to !~ /mpc|mpp|mp4|m4a/; + $encode_string =~ s/%o/$tag_opts \"$outf.$to\"/ if $tag_opts ne " " and $to !~ /mpc|mpp|mp4|m4a/; + $encode_string =~ s/%o/\"$outf.$to\"/ if $tag_opts eq " " or $to =~ /mpc|mpp|mp4|m4a/; + $encode_string =~ s/(\$|\\)/\\$1/g; + + # read tag options from command line if present + get_user_tags(); + + pnotice("debug","\n$run{$to}{ENCODER}{$encoder}{NAME} $encode_string", 2) if $dryrun; + + # encode temporary WAV to desired output format. + system("$run{$to}{ENCODER}{$encoder}{NAME} $encode_string $silent") if not $dryrun; + + # remove partially encoded output file and temporary wav if encoding fails + if ($? > 0) { + unlink("$outf.$to") if -e "$outf.$to"; + unlink("$outf.$$.wav") if -e "$outf.$$.wav"; + say ""; + $banner = 0; + pnotice("encode_failed","$outf.$to: $?",1); + return 1; + } + + # write meta-data to output file from %tag_name hash + write_tags("$outf.$to", "$to") if $run{$to}{TAGS}{WRITE} == 1 and $tag_opts eq " " and not $dryrun; + + unlink("$outf.$$.wav") if not $dryrun; + unlink("$inf.$infmt") if $delete and not $dryrun; + + pnotice("removed_tmp","$outf.$$.wav","2") if $verbose; + pnotice("removed_src","$inf.$infmt", "2") if $delete and $verbose; +} + +$pm->run_on_finish +( sub { + my $pid = shift; + my $exit_code = shift; + my $ident = shift; + + if (-e "$ident.$to") { + $total_converted++; + } + say "$lang{debug} PID: $pid EXIT_CODE: $exit_code IDENTITY: \"$ident.$to\"" if $debug == 1; + } +); + +# convert all files that have been placed in the %files hash through various procs* +sub fork_files { + + say "\n$name - $version\n" if not $gui and $banner == 1; + + foreach (sort(keys(%files))) + { + $pm->start($files{$_}{OUTF}) and next; + my $msg = "$lang{converting}" . " " . basename($files{$_}{FILE}) . ".$files{$_}{EXT} -> $to"; + say "$msg" if not $gui; + system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$msg\" 10 &") if $gui and $kde; + system("notify-send \"$name\" \"$msg\" -t 35 -i $icon_path &") if $gui and $gnome; + convert("$files{$_}{FILE}","$files{$_}{OUTF}","$files{$_}{EXT}","$files{$_}{NAME}","$files{$_}{OUTD}","$files{$_}{CODEC}","$files{$_}{DECODER}"); + $pm->finish; + } + + $pm->wait_all_children; + $total_failed = $number - $total_converted if $total_converted < $number; + + my $finished_msg = "\n$lang{total_converted} $total_converted, $lang{failed} $total_failed\n"; + + say "$finished_msg" if not $gui; + system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$finished_msg\" 10 &") if $gui and $kde; + system("notify-send \"$name\" \"$finished_msg\" -t 35 -i $icon_path &") if $gui and $gnome; + +} + +# if the default encoder does not exist, cycle through the supported +# encoders until we find one that does. +sub check_encoder { + + if (not `which $encoder 2>/dev/null`) { + my $first_encoder = $encoder; + foreach (keys %{$run{$to}{ENCODER}}) { $encoder = $_ and return if `which $_ 2>/dev/null`; } + perror("no_encode_app","$to") if $encoder eq $first_encoder; + } + + else { return 0; } +} + +# if the default decoder does not exist, cycle through the supported +# decoders until we find one that does. +sub check_decoder { + + my $from = shift; + + if (not `which $decoder 2>/dev/null`) { + my $first_decoder = $decoder; + foreach (keys %{$run{$from}{DECODER}}) { $decoder = $_ and return if `which $_ 2>/dev/null`; } + perror("no_decode_app","$from") if $decoder eq $first_decoder; + } + + else { return 0; } +} + +# make sure encoding/decoding is supported. +sub check_input { + + my $file = shift; + my $dir = shift; + my $codec = shift; + + perror("no_encoder","$to") unless(defined($run{$to}{ENCODER})); + + unless(defined($run{$codec}{DECODER})) { + pnotice("no_decoder","$codec",2) if $verbose or not $only; + $total_failed++; + return 1; + } + + return 0; +} + +######################################## +# GUI options for KDE & Gnome Plugins # +######################################## + +my $kdialog = "kdialog --title \"$name\""; +my $zenity = "zenity --title \"$name\" --list --radiolist --width 100 --height 300 --column '' --column "; + +sub get_visual_opts { + + my ($to_fmt,$od) = @_; + + # escape illegal characters in output directory name + $od =~ s/( |'|\(|\)|"|\\)/\\$1/g; + + $outdir = `kdialog --getexistingdirectory $od` if $config{KDE_DIR} == 1 and $kde; + $outdir = `zenity --title \"$lang{gui_outdir}\" --file-selection --directory --filename=\`pwd\`` if $config{ZEN_DIR} == 1 and $gnome; + + chomp($outdir); + $out_dir = $outdir; + exit(1) if not $outdir; + + if ($config{KDE_OPTS} == 1 or $config{ZEN_OPTS} == 1) { + foreach (keys %{$run{$to_fmt}{ENCODER}{$encoder}{PROMPT}}) { + prompt_user($_); + } + } +} + +sub prompt_user { + + my $opt = shift; + + given ($opt) { + + when (/^BITRATE/) { + $bitrate = `$kdialog --default $bitrate --combobox \"$lang{gui_bitrate}\" 56 112 128 160 192 256 320` if $kde; + $bitrate = `$zenity \"$lang{gui_bitrate}\" FALSE 56 FALSE 112 FALSE 128 FALSE 160 TRUE 192 FALSE 256 FALSE 320` if $gnome; + chomp($bitrate); + exit(1) if not $bitrate; + } + + when (/^FREQ/) { + $freq = `$kdialog --default $freq --combobox \"$lang{gui_freq}\" 32000 44100 48000` if $kde; + $freq = `$zenity \"$lang{gui_freq}\" FALSE 32000 TRUE 44100 FALSE 48000` if $gnome; + chomp($freq); + exit(1) if not $freq; + } + + when (/^CHANNELS/) { + $channels = `$kdialog --default $channels --combobox \"$lang{gui_chans}\" 1 2` if $kde; + $channels = `$zenity \"$lang{gui_chans}\" FALSE 1 TRUE 2` if $gnome; + chomp($channels); + exit(1) if not $channels; + } + + when (/^FCOMP/) { + $fcomp = `$kdialog --default $fcomp --combobox \"$lang{gui_fcomp}\" 0 1 2 3 4 5 6 7 8` if $kde; + $fcomp = `$zenity \"$lang{gui_fcomp}\" FALSE 0 FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8` if $gnome; + chomp($fcomp); + exit(1) if not $fcomp; + } + + when (/^ACOMP/) { + $acomp = `$kdialog --default $acomp --combobox \"$lang{gui_acomp}\" 1000 2000 3000 4000 5000` if $kde; + $acomp = `$zenity \"$lang{gui_acomp}\" FALSE 1000 FALSE 2000 TRUE 3000 FALSE 4000 FALSE 5000` if $gnome; + chomp($acomp); + exit(1) if not $acomp; + } + + when (/^OGGQUAL/) { + $oggqual = `$kdialog --default $oggqual --combobox \"$lang{gui_oggqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; + $oggqual = `$zenity \"$lang{gui_oggqual}\" FALSE 0 FALSE 1 FALSE 2 TRUE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8 FALSE 9 FALSE 10` if $gnome; + chomp($oggqual); + exit(1) if not $oggqual; + } + + when (/^SPXQUAL/) { + $spxqual = `$kdialog --default $spxqual --combobox \"$lang{gui_spxqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; + $spxqual = `$zenity \"$lang{gui_spxqual}\" FALSE 0 FALSE 1 FALSE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 TRUE 8 FALSE 9 FALSE 10` if $gnome; + chomp($spxqual); + exit(1) if not $spxqual; + } + + when (/^AACQUAL/) { + $aacqual = `$kdialog --default $aacqual --combobox \"$lang{gui_aacqual}\" 100 200 300 400 500` if $kde; + $aacqual = `$zenity \"$lang{gui_aacqual}\" TRUE 100 FALSE 200 FALSE 300 FALSE 400 FALSE 500` if $gnome; + chomp($aacqual); + exit(1) if not $aacqual; + } + + when (/^MPCQUAL/) { + $mpcqual = `$kdialog --default $mpcqual --combobox \"$lang{gui_mpcqual}\" thumb radio standard xtreme insane braindead` if $kde; + $mpcqual = `$zenity \"$lang{gui_mpcqual}\" FALSE thumb TRUE radio FALSE standard FALSE xtreme FALSE insane FALSE braindead` if $gnome; + chomp($mpcqual); + exit(1) if not $mpcqual; + } + + when (/^OFMODE/ ) { + $ofmode = `$kdialog --default $ofmode --combobox \"$lang{gui_ofmode}\" fast normal high extra best highnew extranew bestnew` if $kde; + $ofmode = `$zenity \"$lang{gui_ofmode}\" FALSE fast TRUE normal FALSE high FALSE extra FALSE best FALSE highnew FALSE extranew FALSE bestnew` if $gnome; + chomp($ofmode); + exit(1) if not $ofmode; + } + + when (/^OFOPT/) { + $ofopt = `$kdialog --default $ofopt --combobox \"$lang{gui_ofopt}\" none fast normal high best` if $kde; + $ofopt = `$zenity \"$lang{gui_ofopt}\" FALSE none TRUE fast FALSE normal FALSE high FALSE best` if $gnome; + chomp($ofopt); + exit(1) if not $ofopt; + } + + when (/^BRATIO/) { + $bratio = `$kdialog --default $bratio --combobox \"$lang{gui_bratio}\" 1 2 3 4 5` if $kde; + $bratio = `$zenity \"$lang{gui_bratio}\" FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5` if $gnome; + chomp($bratio); + exit(1) if not $bratio; + } + + when (/^BQUANL/) { + $bquanl = `$kdialog --default $bquanl --combobox \"$lang{gui_bquanl}\" 1.00 1.25 1.50 1.75 2.00` if $kde; + $bquanl = `$zenity \"$lang{gui_bquanl}\" TRUE 1.00 FALSE 1.25 FALSE 1.50 FALSE 1.75 FALSE 2.00` if $gnome; + chomp($bquanl); + exit(1) if not $bquanl; + } + + when (/^BPSIZE/) { + $bpsize = `$kdialog --default $bpsize --combobox \"$lang{gui_bpsize}\" 10 128` if $kde; + $bpsize = `$zenity \"$lang{gui_bpsize}\" FALSE 10 TRUE 128` if $gnome; + chomp($bpsize); + exit(1) if not $bpsize; + } + + default { return 0; } + } + +} + +# all copied tags will be stored here for furture use +my %tag_name = +( + title => undef, + track => undef, + artist => undef, + album => undef, + comment => undef, + year => undef, + genre => undef, +); + +# override tags read from input file if any of the tagging +# options are specified by the user during conversion. +sub get_user_tags +{ + $tag_name{title} = $title if $title; + $tag_name{track} = $track if $track; + $tag_name{artist} = $artist if $artist; + $tag_name{album} = $album if $album; + $tag_name{comment} = $comment if $comment; + $tag_name{year} = $year if $year; + $tag_name{genre} = $genre if $genre; +} + +# the formats MP4/M4A/M4B/MPC/MPP/WV/BONK have no tag writing module. +# tags therefore have to be written during encode via various +# command line args. +sub format_tags { + + my $type = shift; + + given ($type) { + + when (/^mp4$|^m4a$|^m4b$/) { + + if ($run{$to}{ENCODER}{$encoder}{NAME} eq "ffmpeg" or $run{$to}{ENCODER}{$encoder}{NAME} eq "avconv") { + + $tag_name{track} = 0 if not $tag_name{track}; + $tag_name{year} = 0 if not $tag_name{year}; + + return "-metadata TITLE=\"$tag_name{title}\" -metadata TRACK=\"$tag_name{track}\" -metadata ARTIST=\"$tag_name{artist}\" -metadata ALBUM=\"$tag_name{album}\" -metadata COMMENT=\"$tag_name{comment}\" -metadata YEAR=\"$tag_name{year}\" -metadata GENRE=\"$tag_name{genre}\""; + + } else { + + return "--title \"$tag_name{title}\" --track \"$tag_name{track}\" --artist \"$tag_name{artist}\" --album \"$tag_name{album}\" --comment \"$tag_name{comment}\" --year \"$tag_name{year}\" --genre \"$tag_name{genre}\""; + + } + } + + when (/^mpc$|^mpp$/) { return "--artist \"$tag_name{artist}\" --title \"$tag_name{title}\" --album \"$tag_name{album}\" --track \"$tag_name{track}\" --genre \"$tag_name{genre}\" --year \"$tag_name{year}\" --comment \"$tag_name{comment}\""; } + when (/^wv$/) { return "-w \"Title=$tag_name{title}\" -w \"Track=$tag_name{track}\" -w \"Artist=$tag_name{artist}\" -w \"Album=$tag_name{album}\" -w \"Comment=$tag_name{comment}\" -w \"Year=$tag_name{year}\" -w \"Genre=$tag_name{genre}\""; } + when (/^bonk$/) { return "-t \"$tag_name{title}\" -a \"$tag_name{artist}\" -c \"$tag_name{comment}\""; } + when (/^spx$/) { return "--author \"$tag_name{artist}\" --title \"$tag_name{title}\" --comment \"year=$tag_name{year}\" --comment \"tracknumber=$tag_name{track}\" --comment \"album=$tag_name{album}\" --comment \"genre=$tag_name{genre}\" --comment \"comment=$tag_name{comment}\""; } + + default { return " "; } + } +} + +# meta-data is read based on input file extension. +# all tags which are present will be copied to +# the %tag_name hash. +sub read_tags { + + my $in_file = shift; + my $in_format = shift; + + my $tag_module = $run{$in_format}{TAGS}{MODULE}; + + given ($in_format) { + + when (/^mp3$|^mp3hd$/) { + my $mp3tag = $tag_module->new($in_file); + my @tags = $mp3tag->autoinfo(); + + $tag_name{title} = "$tags0" if $tags0; + $tag_name{track} = "$tags1" if $tags1; + $tag_name{artist} = "$tags2" if $tags2; + $tag_name{album} = "$tags3" if $tags3; + $tag_name{comment} = "$tags4" if $tags4; + $tag_name{year} = "$tags5" if $tags5; + $tag_name{genre} = "$tags6" if $tags6; + + return 0; + } + + when (/^ogg$|^oga$/) { + my $ogg_tag = Audio::Scan->scan_tags($in_file)->{tags}; + + $tag_name{title} = $ogg_tag->{TITLE} if $ogg_tag->{TITLE}; + $tag_name{track} = $ogg_tag->{TRACKNUMBER} if $ogg_tag->{TRACKNUMBER}; + $tag_name{artist} = $ogg_tag->{ARTIST} if $ogg_tag->{ARTIST}; + $tag_name{album} = $ogg_tag->{ALBUM} if $ogg_tag->{ALBUM}; + $tag_name{comment} = $ogg_tag->{COMMENT} if $ogg_tag->{COMMENT}; + $tag_name{year} = $ogg_tag->{YEAR} if $ogg_tag->{YEAR}; + $tag_name{genre} = $ogg_tag->{GENRE} if $ogg_tag->{GENRE}; + + return 0; + } + + when (/^spx$/) { + my $pid = open(SPX, "speexdec \"$in_file\" tmp1-$$.wav 2>&1 |") or perror("opening_file","$in_file"); + my @data = <SPX>; + @data = grep(!/^$|^#/, @data); + + close(SPX); + + foreach (@data) { + + next unless /=/; + chomp; + + my ($k, $v) = split /=/; + $k =~ tr/A-Z/a-z/; + $tag_name{$k} = $v if exists($tag_name{$k}); + $tag_name{artist} = $v if $k =~ /^author/i; + $tag_name{track} = $v if $k =~ /^tracknumber/i; + } + + unlink("tmp-$$.wav"); + return 0; + } + + when (/^flac$|^fla$/) { + my $flac_tag = Audio::Scan->scan_tags($in_file)->{tags}; + + $tag_name{title} = $flac_tag->{TITLE} if $flac_tag->{TITLE}; + $tag_name{track} = $flac_tag->{TRACKNUMBER} if $flac_tag->{TRACKNUMBER}; + $tag_name{artist} = $flac_tag->{ARTIST} if $flac_tag->{ARTIST}; + $tag_name{album} = $flac_tag->{ALBUM} if $flac_tag->{ALBUM}; + $tag_name{comment} = $flac_tag->{COMMENT} if $flac_tag->{COMMENT}; + $tag_name{year} = $flac_tag->{DATE} if $flac_tag->{DATE}; + $tag_name{genre} = $flac_tag->{GENRE} if $flac_tag->{GENRE}; + + return 0; + } + + when (/^(mp4|m4b|alac|mp4a)$/) { + my $mp4_tag = $tag_module->scan_tags($in_file)->{tags}; + + $tag_name{title} = $mp4_tag->{NAM} if $mp4_tag->{NAM}; + $tag_name{track} = $mp4_tag->{TRKN} if $mp4_tag->{TRKN}; + $tag_name{artist} = $mp4_tag->{ART} if $mp4_tag->{ART}; + $tag_name{album} = $mp4_tag->{ALB} if $mp4_tag->{ALB}; + $tag_name{comment} = $mp4_tag->{CMT} if $mp4_tag->{CMT}; + $tag_name{year} = $mp4_tag->{DAY} if $mp4_tag->{DAY}; + $tag_name{genre} = $mp4_tag->{GNRE} if $mp4_tag->{GNRE}; + + return 0; + } + +when (/^ape$|^mpc$|^mpp$|^wv$/) { + my $audio_tag = $tag_module->scan_tags($in_file)->{tags}; + + $tag_name{title} = $audio_tag->{TITLE} if $audio_tag->{TITLE}; + $tag_name{track} = $audio_tag->{TRACK} if $audio_tag->{TRACK}; + $tag_name{artist} = $audio_tag->{ARTIST} if $audio_tag->{ARTIST}; + $tag_name{album} = $audio_tag->{ALBUM} if $audio_tag->{ALBUM}; + $tag_name{comment} = $audio_tag->{COMMENT} if $audio_tag->{COMMENT}; + $tag_name{year} = $audio_tag->{YEAR} if $audio_tag->{YEAR}; + $tag_name{genre} = $audio_tag->{GENRE} if $audio_tag->{GENRE}; + + return 0; + } + + when (/^wma$/) { + my $wma_tag = $tag_module->scan_tags($in_file)->{tags}; + + $tag_name{title} = $wma_tag->{Title} if $wma_tag->{Title}; + $tag_name{track} = $wma_tag->{'WM/TrackNumber'} if $wma_tag->{'WM/TrackNumber'}; + $tag_name{artist} = $wma_tag->{'WM/AlbumArtist'} if $wma_tag->{'WM/AlbumArtist'}; + $tag_name{album} = $wma_tag->{'WM/AlbumTitle'} if $wma_tag->{'WM/AlbumTitle'}; + $tag_name{comment} = $wma_tag->{'WM/Description'} if $wma_tag->{'WM/Description'}; + $tag_name{year} = $wma_tag->{'WM/Year'} if $wma_tag->{'WM/Year'}; + $tag_name{genre} = $wma_tag->{'WM/Genre'} if $wma_tag->{'WM/Genre'}; + + return 0; + } + + default { return 1; } + } +} + +# write meta-data stored in %tag_name to output file. +sub write_tags { + + my $out_file = shift; + my $out_format = shift; + + my $tag_m; + + given ($out_format) { + + when (/^mp3$|^mp3hd$/) { + $tag_m = MP3::Tag->new("$out_file"); + + # ID3v2 Tags + unless(exists($tag_m->{ID3v2})) { $tag_m->new_tag("ID3v2"); } + + $tag_m->{ID3v2}->add_frame("TIT2", "$tag_name{title}") if defined($tag_name{title}); + $tag_m->{ID3v2}->add_frame("TRCK", "$tag_name{track}") if defined($tag_name{track}); + $tag_m->{ID3v2}->add_frame("TPE1", "$tag_name{artist}") if defined($tag_name{artist}); + $tag_m->{ID3v2}->add_frame("TALB", "$tag_name{album}") if defined($tag_name{album}); + $tag_m->{ID3v2}->comment("$tag_name{comment}") if defined($tag_name{comment}); + $tag_m->{ID3v2}->add_frame("TYER", "$tag_name{year}") if defined($tag_name{year}); + $tag_m->{ID3v2}->add_frame("TCON", "$tag_name{genre}") if defined($tag_name{genre}); + + $tag_m->{ID3v2}->write_tag; + + # ID3v1 Tags + unless(exists($tag_m->{ID3v1})) { $tag_m->new_tag("ID3v1"); } + + $tag_m->{ID3v1}->title("$tag_name{title}") if defined($tag_name{title}); + $tag_m->{ID3v1}->track("$tag_name{track}") if defined($tag_name{track}); + $tag_m->{ID3v1}->artist("$tag_name{artist}") if defined($tag_name{artist}); + $tag_m->{ID3v1}->album("$tag_name{album}") if defined($tag_name{album}); + $tag_m->{ID3v1}->comment("$tag_name{comment}") if defined($tag_name{comment}); + $tag_m->{ID3v1}->year("$tag_name{year}") if defined($tag_name{year}); + $tag_m->{ID3v1}->genre("$tag_name{genre}") if defined($tag_name{genre}); + + $tag_m->{ID3v1}->write_tag; + + return 0; + + } + + when (/^ogg$|^oga$/) { + $tag_m = ''; + + $tag_m = "$tag_m -t \"TITLE=$tag_name{title}\"" if $tag_name{title}; + $tag_m = "$tag_m -t \"TRACKNUMBER=$tag_name{track}\"" if $tag_name{track}; + $tag_m = "$tag_m -t \"ARTIST=$tag_name{artist}\"" if $tag_name{artist}; + $tag_m = "$tag_m -t \"ALBUM=$tag_name{album}\"" if $tag_name{album}; + $tag_m = "$tag_m -t \"COMMENT=$tag_name{comment}\"" if $tag_name{comment}; + $tag_m = "$tag_m -t \"YEAR=$tag_name{year}\"" if $tag_name{year}; + $tag_m = "$tag_m -t \"GENRE=$tag_name{genre}\"" if $tag_name{genre}; + + system("vorbiscomment -w $tag_m \"$out_file\"") if $tag_m ne ''; + + return 0; + } + + when (/^fla$|^flac$/) { + $tag_m = Audio::FLAC::Header->new("$out_file"); + my $tag_i = $tag_m->tags(); + + $tag_i->{TITLE} = "$tag_name{title}" if $tag_name{title}; + $tag_i->{TRACKNUMBER} = "$tag_name{track}" if $tag_name{track}; + $tag_i->{ARTIST} = "$tag_name{artist}" if $tag_name{artist}; + $tag_i->{ALBUM} = "$tag_name{album}" if $tag_name{album}; + $tag_i->{COMMENT} = "$tag_name{comment}" if $tag_name{comment}; + $tag_i->{DATE} = "$tag_name{year}" if $tag_name{year}; + $tag_i->{GENRE} = "$tag_name{genre}" if $tag_name{genre}; + + $tag_m->write(); + + return 0; + } + + default { perror("no_write_tag","$out_file"); } + } + +} + +# this is necessary when converting multiple files. +# it prevents old tags from the previous file being +# copied over to the next file in line. +sub clear_tag_hash { + foreach (keys(%tag_name)) { + $tag_name{$_} = ''; + } +} + +# display meta-data for selected file(s) +sub show_taginfo { + + perror("no_input","") if $#file < 0; + + foreach my $i (@file) { + + my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); + + $ext =~ s/^\.//; + + my $from = $ext; + $from =~ tr/A-Z/a-z/; + + if ($run{$from}{TAGS}{READ} == 1) { + + clear_tag_hash(); + read_tags("$dir/$file.$ext","$from"); + + say ''; + + pnotice("tag_info","$file.$ext",2); + + say " Artist: $tag_name{artist}"; + say " Title: $tag_name{title}"; + say " Album: $tag_name{album}"; + say " Track: $tag_name{track}"; + say "Comment: $tag_name{comment}"; + say " Year: $tag_name{year}"; + say " Genre: $tag_name{genre}"; + + say ''; + + } else { pnotice("no_read_tag","$file.$ext",2); } + } +} + +# write tags to file supplied by the user +sub write_user_tags { + + perror("no_input","") if $#file < 0; + + say ''; + say "$name - $version\n"; + + foreach (@file) { + + my ($file, $dir, $ext) = fileparse("$_", qr/\.^.*/); + + $ext =~ s/^\.//; + my $from = $ext; + $from =~ tr/A-Z/a-z/; + + if ($run{$from}{TAGS}{WRITE} == 1) { + + clear_tag_hash(); + read_tags("$dir/$file.$ext","$from"); + + $tag_name{title} = $title if $title; + $tag_name{track} = $track if $track; + $tag_name{artist} = $artist if $artist; + $tag_name{album} = $album if $album; + $tag_name{comment} = $comment if $comment; + $tag_name{year} = $year if $year; + $tag_name{genre} = $genre if $genre; + + write_tags("$dir/$file.$ext","$from"); + say "$lang{write_tag_i} $file.$ext"; + + } else { perror("no_write_tag","$file.$ext"); } + } + say ''; +} + +# print out list of supported encode & decode formats +sub show_formats { + +say "\n$name - $version\n"; +say "EXT E D ENCODER DECODER TAG-READ TAG-WRITE"; +say "----------------------------------------------------------------------"; + +my $enc_count = 0; +my $dec_count = 0; + + foreach (sort(keys(%run))) { + + my $e = "N"; $e = "Y" if defined($run{$_}{DEFAULT_ENCODER}); + my $d = "N"; $d = "Y" if defined($run{$_}{DEFAULT_DECODER}); + my $r = "N"; $r = "Y" if $run{$_}{TAGS}{READ} == 1; + my $w = "N"; $w = "Y" if $run{$_}{TAGS}{WRITE} == 1; + + my $enc = ''; $enc = $run{$_}{DEFAULT_ENCODER} if defined($run{$_}{DEFAULT_ENCODER}); + my $dec = ''; $dec = $run{$_}{DEFAULT_DECODER} if defined($run{$_}{DEFAULT_DECODER}); + + printf("%-9s %-3s %-3s %-15s %-18s %-10s %s\n", $_, $e, $d, $enc, $dec, $r, $w); + + ++$enc_count if $enc ne ''; + ++$dec_count if $dec ne ''; + + } + + say "\n$lang{enc_fmts} $enc_count --- $lang{dec_fmts} $dec_count\n"; + +} + +# show encoders for output format +sub show_encoders { + say "\n$name - $version\n\n$lang{show_encoders}: $my_encoder\n"; + foreach (sort(keys %{$run{$my_encoder}{ENCODER}})) { + print "$_ -> "; + print "installed" if `which $_ 2>/dev/null`; + print "not found" if not `which $_ 2>/dev/null`; + print " (default)" if $_ eq $run{$my_encoder}{DEFAULT_ENCODER}; + say ''; + } + say ''; +} + +# show decoders for input format +sub show_decoders { + say "\n$name - $version\n\n$lang{show_decoders}: $my_decoder\n"; + foreach (sort(keys %{$run{$my_decoder}{DECODER}})) { + print "$_ -> "; + print "installed" if `which $_ 2>/dev/null`; + print " (default)" if $_ eq $run{$my_decoder}{DEFAULT_DECODER}; + say ''; + } + say ''; +} + +################# +# cd ripping... # +################# + +# get total number of tracks from cdparanoia query +sub get_total_tracks { + + open(CDINFO, "cdparanoia -Q 2>&1 |") or die "can't fork: $!\n"; + my @cdquery = <CDINFO>; + close(CDINFO); + + my $fmt_tracks = $cdquery-3; + $fmt_tracks =~ s/\s//g; + + my @ttracks = split(/\./, $fmt_tracks); + + return "$ttracks0"; + +} + +my (%cd, %ripconfig, @cdtrack, $track_total); + +# setup the cddb config +sub get_cddb_config { + + $config{USE_CDDB} = 0 && return if $nocddb; + + $config{CDDB_INPUT} = 0 if $noinput; + + $ripconfig{CDDB_HOST} = $config{CDDB_HOST}; + $ripconfig{CDDB_PORT} = $config{CDDB_PORT}; + $ripconfig{CDDB_MODE} = $config{CDDB_MODE}; + $ripconfig{DEVICE} = $device; + $ripconfig{CDDB_INPUT} = $config{CDDB_INPUT}; + + print $ripconfig{CDDB_HOST}; + + %cd = get_cddb(\%ripconfig); + + if (not $cd{title}) { + pnotice("no_cddb","",2); + $config{USE_CDDB} = 0; + } + else { + @cdtrack = @{$cd{track}}; + $track_total = $cd{tno}; + } + +} + +# check to see if a disc is present +sub query_disc { + system("cdparanoia -q -d $device -Q > /dev/null 2>&1"); + perror("no_disc","$device") if $? > 0; +} + +# set tag info from cddb +sub tag_track { + + my $tno = shift; + + $tag_name{artist} = $cd{artist} if $cd{artist}; + $tag_name{title} = $cdtrack$tno-1 if $cdtrack$tno-1; + $tag_name{genre} = $cd{cat} if $cd{cat}; + $tag_name{track} = $tno; + $tag_name{album} = $cd{title} if $cd{title}; + $tag_name{year} = $cd{year} if $cd{year}; + $tag_name{comment} = ''; + +} + +# process and convert ripped track +sub rip_cd { + + my ($on,$tno) = @_; + + $outdir = $ENV{HOME}; + $to =~ tr/A-Z/a-z/; + + get_visual_opts($to,$out_dir) if $gui and not defined($first_run); + $first_run = 1; + pnotice("ripping_track","$tno",2); + + $on =~ s/\//_/g; + + say "\ncdparanoia -d $device $tno $on.wav\n" if $dryrun; + system("cdparanoia -d $device $tno \"$on.wav\" >/dev/null 2>&1") if not $dryrun; + + if ($to !~ /wav/i) { + + push(@file, "$on.wav"); + tag_track($tno); + proc_input(); + clear_tag_hash(); + undef(@file); + unlink("$on.wav") if not $dryrun; + pnotice("removed_tmp","$on.wav",2) if $verbose; + + } +} + +# rip selected tracks or all from disc +sub proc_cd { + + perror("no_app","cdparanoia") if not `which cdparanoia 2>/dev/null`; + + query_disc(); + get_cddb_config(); + + my $total_tracks = get_total_tracks(); + + if ($rip eq "all") { + + if ($config{USE_CDDB} ne 1) { + + for(my $i=1;$i<=$total_tracks;$i++) { + rip_cd($i, $i); + } + + } elsif ($config{USE_CDDB} eq 1) { + + my $n = 1; + + foreach my $i (@cdtrack) { + + my $out_string = $nscheme; + + chomp($cdtrack$n-1); + + $out_string =~ s/%ar/$cd{artist}/; + $out_string =~ s/%ti/$cdtrack$n-1/; + $out_string =~ s/%tr/$n/; + $out_string =~ s/%ab/$cd{title}/; + $out_string =~ s/%yr/$cd{year}/; + + rip_cd($out_string, $n); + + ++$n; + } + } + + } else { + + my @tracks = split(/,/, $rip); + + foreach my $i (@tracks) { + + next if $i > $total_tracks or $i < 1; + + my $out_string = $nscheme; + + $out_string =~ s/%ar/$cd{artist}/; + $out_string =~ s/%ti/$cdtrack$i-1/; + $out_string =~ s/%tr/$i/; + $out_string =~ s/%ab/$cd{title}/; + $out_string =~ s/%yr/$cd{year}/; + + rip_cd($out_string, $i) if $config{USE_CDDB} == 1; + rip_cd($i, $i) if $config{USE_CDDB} == 0; + } + } +} + +# get/print cddb information from disc +sub cdinfo { + + query_disc(); + get_cddb_config(); + + say "$name - $version\n"; + + say "Artist = $cd{artist}"; + say "Album = $cd{title}"; + say "Genre = $cd{genre}"; + say "Tracks = $cd{tno}"; + say "Year = $cd{year}\n"; + + my $n = 1; + + foreach (@cdtrack) { + say "Track $n: $_"; + ++$n; + } + + exit(0); +} + +# version / license information +sub version { + +say " +$name - $version + +Copyright (C) 2005-2018 Philip Lyons + +This is free software. You may redistribute copies of it under the terms of +the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. +There is NO WARRANTY, to the extent permitted by law. +"; + +} + +# help & longhelp menu +sub help_menu { + +say "\n$name - $version"; + +say " +-t, --to $lang{to} +-r, --recursive $lang{recursive} +-p, --preserve $lang{preserve} +-f, --formats $lang{formats} +-o, --only $lang{only} +-k, --keep $lang{keep} +-j, --jobs $lang{jobs} +-h, --help $lang{help} +-l, --longhelp $lang{longhelp} +-v, --verbose $lang{verbose} +"; + +say "$lang{user_opts} + +--defopts $lang{defopts} +--eopts $lang{eopts} +--dopts $lang{dopts} +--nopts $lang{nopts} +--outfile $lang{outfile} +--outdir $lang{outdir} +--dryrun $lang{dryrun} +--overwrite $lang{overwrited} +--normalize $lang{normalize} +--delete $lang{delete} +--encoder $lang{encoder} +--decoder $lang{decoder} +--version $lang{version} + +$lang{enc_opts} + +--bitrate $lang{bitrate} +--freq $lang{freq} +--channels $lang{channels} +--effect $lang{effect} +--fcomp $lang{fcomp} +--acomp $lang{acomp} +--oggqual $lang{oggqual} +--spxqual $lang{spxqual} +--aacqual $lang{aacqual} +--mpcqual $lang{mpcqual} +--ofmode $lang{ofmode} +--ofopt $lang{ofopt} +--bratio $lang{bratio} +--bquanl $lang{bquanl} +--bpsize $lang{bpsize} + +$lang{tag_opts} + +--artist $lang{artist} +--title $lang{title} +--track $lang{track} +--year $lang{year} +--album $lang{album} +--genre $lang{genre} +--comment $lang{comment} +--taginfo $lang{taginfo} + +$lang{tag_usage} + +$lang{rip_opts} + +--rip $lang{rip} +--nocddb $lang{nocddb} +--noinput $lang{noinput} +--nscheme $lang{nscheme} +--cdinfo $lang{cdinfo} +--device $lang{device} + +$lang{rip_usage}" if $longhelp; + +say "\n$lang{usage}\n"; + +} + +sub load_module { + my ($file) = @_; + my $return; + unless($return = do $file) { + perror("opening_file","$file: $@ $!") if $@ or !defined($return) or not !$return; + } +} + +sub import_module { + my ($format_ref) = @_; + my $format_name=$format_ref->{NAME}; + $run{$format_name} = $format_ref; +} + +# load all user modules +sub load_user_modules { + my @imported_mods; + opendir(DIR, "$mod_dir") or perror("opening_dir","$mod_dir: $!"); + foreach (readdir(DIR)) { + load_module("$mod_dir/$_") if $_ !~ /^\./; + push(@imported_mods, $_) if $_ !~ /^\./; + } + closedir(DIR); + say "$lang{imported} @imported_mods"; +} + +# place files/directories in their respective arrays +if (@ARGV) { + foreach (@ARGV) { + if (-f $_) { push(@file,$_); print "$lang{debug} adding $_ to \@file\n" if $debug == 1; } + elsif (-d $_) { push(@dir, $_); print "$lang{debug} adding $_ to \@dir\n" if $debug == 1; } + else { perror("no_infile","$_"); } + } +} + +load_user_modules() if $config{IMPORTM} == 1; + +if ($to and @ARGV and not $rip) { proc_input(); } + +elsif ($to and $rip) { proc_cd(); } +elsif ($my_encoder and not $to) { show_encoders(); } +elsif ($my_decoder and not $to) { show_decoders(); } +elsif ($verinfo) { version(); } +elsif ($longhelp) { help_menu(); } +elsif ($formats) { show_formats(); } +elsif ($cdinfo) { cdinfo(); } +elsif ($taginfo and not $to) { show_taginfo(); } +elsif ($title or $track or $artist or $album or $comment or $year or $genre) { write_user_tags(); } + +else { help_menu(); } + +__END__ + +=head1 NAME + +pacpl - Perl Audio Converter, a multi purpose converter/ripper/tagger + +=head1 SYNOPSIS + +pacpl --to <format> <options> file(s)/directory(s) + +=head1 DESCRIPTION + +Perl Audio Converter + +A Linux CLI tool for converting multiple audio types from one format to another. + +It supports the following audio formats: + +======================================== + +3G2, 3GP, 8SVX, AAC, AC3, ADTS, AIFF, AL, AMB, AMR, APE, AU, +AVR, BONK, CAF, CDR, CVU, DAT, DTS, DVMS, F32, F64, FAP, FLA, +FLAC, FSSD, GSRT, HCOM, IMA, IRCAM, LA, MAT, MAUD, MAT4, MAT5, +M4A, MP2, MP3, MP4, MPC, MPP, NIST, OFF, OFR, OFS, OPUS, OGA, +OGG, PAF, PRC, PVF, RA, RAM, RAW, RF64, SD2, SF, SHN, SMP, SND, +SOU, SPX, SRN, TAK, TTA, TXW, VOC, VMS, VQF, W64, WAV, WMA, +and WV. + +It can also extract audio from the following video extensions: + +============================================================== + +RM, RV, ASF, DivX, MPG, MKV, MPEG, AVI, MOV, OGM, OGV, QT, VCD, +SVCD, M4V, NSV, NUV, PSP, SMK, VOB, FLV, WEBM and WMV. + +Parallel Processing, a CD ripping function with CDDB support, batch conversion, +tag preservation for most supported formats, independent tag reading & writing, +service menus for KDE Dolphin/Konqueror, GNOME Nautilus script, and action +scripts for Nemo/Thunar are also provided. + +=head1 OPTIONS + +B<-t, --to> I<format> + +set encode format for the input file(s) or directory(ies). you can see a +complete list of supported encode formats by using the B<--formats> option. + +B<-r, --recursive> + +recursively scan and convert input folder(s) to destination format. + +B<-p, --preserve> + +when recursively converting a directory, preserve the input folders directory +structure in the specified output directory. such as: + +pacpl --to ogg -r -p /home/mp3s --outdir /home/oggs + +in the example above, let's assume the directory structure was: + +=over 21 + +=item /home/mp3s/Alternative + +=item /home/mp3s/Alternative/New + +=item /home/mp3s/Rap + +=item /home/mp3s/Country + +=item /home/mp3s/Techno/ + +=back + +the output directory will now contain: + +=over 4 + +=item /home/oggs/Alternative + +=item /home/oggs/Alternative/New + +=item /home/oggs/Rap + +=item /home/oggs/Country + +=item /home/oggs/Techno + +=back + +with all files in each sub-folder converted to ogg. + +B<-o, --only> I<format> + +only convert files matching extension. this option is useful when you have +a directory or batch of files with mixed audio types and only need to +convert one specific type. + +B<-k, --keep> + +do not re-encode files with extensions matching the destination extension. +instead...copy them to the output folder, or skip to the next file. + +B<-j, --jobs> + +number of simultanious jobs to run at once. the default limit +is set to 4 in pacpl.conf. You can modify this value on the fly +using --jobs=<num> or set it perminately in the configuration file + +=over 4 + +=item B<-f, --formats> show a list of supported encode/decode formats. + +=item B<-h, --help> show the short help menu. + +=item B<-l, --longhelp> display the complete list of options. + +=item B<--version> show version and licensing information. + +=back + +=head1 USER OPTIONS + +B<--defopts> I<1/0> + +to turn off default encoder options use --defopts 0. this option gives you +more control when using the --eopts command. + +defopts is set to 1 by default. you can also toggle this option in +/etc/pacpl/pacpl.conf. + +B<--eopts> I<options> + +this option allows you to use encoder options not implemented by pacpl. +an example would be: + +pacpl --to mp4 --eopts="-c 44100 -I 1,2" YourFile.mp3 + +B<--dopts> I<options> + +this option allows you to use decoder options not implemented by pacpl. +an example would be: + +pacpl --to mpc --dopts="--start 60" YourFile.ogg + +B<--outfile> I<name> + +set the output file name to I<name>. + +B<--outdir> I<directory> + +place all encoded files in I<directory>. + +B<--dryrun> + +show what would be done without actually converting anything. this is a +good way to trouble shoot, or to see what would be done without actually +touching your files. + +B<--overwrite> + +replace the output file if it already exists. + +B<--normalize> + +adjusts volume levels of audio files. + +B<--nopts> I<options> + +this allows you to specify normalize options not implemented by pacpl + +B<--delete> + +remove source/input file after the conversion process has finished. + +B<--encoder> I<encoder> + +specify an alternate encoder for the selected output file(s) + +you can see a list of supported encoders by using the following: + +pacpl --encoder I<format> + +B<--decoder> I<decoder> + +specify an alternate decoder for the selected input file(s) + +you can see a list of supported decoders by using the following: + +pacpl --decoder I<format> + +B<-v, --verbose> + +show detailed information about the encoding process and what's actually +being done. + +=head1 ENCODER OPTIONS + +B<--bitrate> I<num> + +set the bitrate to I<num>. default is 128. this option does not apply +to all formats. + +B<--freq> I<num> + +set the frequency to I<num>. default is 44100. this option does not apply +to all formats. + +B<--channels> I<num> + +set the number of audio channels in the output file to I<num>. this option +does not apply to all formats. + +B<--effect> I<str> + +see B<sox>(1). this option only applies to the following: + +AIFF, AU, SND, RAW, VOC, SMP, AVR, and CDR + +B<--fcomp> I<num> + +set flac compression level to I<num>. fastest -0, highest -8, default -2 + +=over 4 + +=item 1 = fast + +=item 2 = simple + +=item 3 = medium (default) + +=item 4 = high + +=item 5 = extra high, + +=back + +B<--acomp> I<num> + +set ape compression level to I<num>. + +=over 4 + +=item 1000 = fast + +=item 2000 = normal + +=item 3000 = high (default) + +=item 4000 = extra high + +=item 5000 = insane + +=back + +B<--oggqual> I<num> + +set ogg quality level to I<num>. -1, very low and 10 very high, default 3 + +B<--spxqual> I<num> + +set speex quality level to I<num>. 0-10, default 8 (use --bitrate <num> when using ffmpeg/avconv as encoder) + +B<--aacqual> I<num> + +set aac, mp4, m4a, or m4b quality level to I<num>. default 300 + +B<--mpcqual> I<str> + +set mpc/mpp quality level to I<str>. + +=over 4 + +=item thumb low quality/internet, (typ. 58... 86 kbps) + +=item radio medium (MP3) quality, (typ. 112...152 kbps - default) + +=item standard high quality (dflt), (typ. 142...184 kbps) + +=item xtreme extreme high quality, (typ. 168...212 kbps) + +=back + +B<--ofmode> I<str> + +set off/ofr/ofs compression mode to I<str>. normal, extra, and extranew modes +are recommended for general use. available options are: + +=over 4 + +=item fast + +=item normal (default) + +=item high + +=item extra + +=item best + +=item highnew + +=item extranew + +=item bestnew + +=back + +B<--ofopt> I<str> + +set off/ofr/ofs optimization level to I<str>. + +specify the optimization level in the engine. In order to achieve +optimal compression at all sample types, sample rates, and audio +content, the core compression engine has the possibility to find the +optimal values for its parameters, at the cost of slightly increased +compression time only. The default recommended value is fast. +do not use normal (or even high or best) for this parameter unless +encoding time does not matter and you want to obtain the smallest +possible file for a given compression mode. The difference between +the optimize levels fast and best (which is up to three times slower +than fast) is very small, generally under 0.05%, but may be also +larger in some rare cases. Note that the none optimize level is +forced by the encoder to fast optimize level for the extra, best, +highnew, extranew, and bestnew modes. + +available options are: + +=over 4 + +=item none + +=item fast (default) + +=item normal + +=item high + +=item best + +=back + +B<--bratio> I<num> + +set bonk down sampling ratio. default 2 + +B<--bquanl> I<num> + +set bonk quantanization level. default 1.0 + +B<--bpsize> I<num> + +set bonk predictor size. default 128 + +=head1 TAGGING OPTIONS + +B<note:> + +tagging outside of the encoding process can only be performed on the +following audio types: + +=over 4 + +=item MP3 + +=item OGG + +=item FLA + +=item FLAC + +=back + +B<--artist> I<str> + +set artist information to I<str>. + +B<--title> I<str> + +set title information to I<str>. + +B<--track> I<num> + +set track information to I<num>. + +B<--year> I<num> + +set year/date information to I<num>. + +B<--album> I<str> + +set album information to I<str>. + +B<--genre> I<str> + +set genre information to I<str>. + +B<--comment> I<str> + +set comment information to I<str>. + +B<--taginfo> I<file> + +show tagging information for I<file>. multiple files can be specified +at once. + +=head1 RIPPING OPTIONS + +B<--rip> I<num/all> + +rip selected tracks separated by comma or all from current disc. + +=over 4 + +=item pacpl --rip all --to flac + +=item pacpl --rip 1,3,9,15 --to flac + +=back + +B<--nocddb> + +disable cddb. use this option if you do not want tagging based on cddb. + +B<--noinput> + +disable cddb interactivity. this is enabled by default. + +B<--nscheme> I<str> + +set naming scheme to I<str>. default is %ar - %ti + +available options are: + +=over 4 + +=item %ar = artist + +=item %ti = song title + +=item %tr = track + +=item %yr = year + +=item %ab = album + +=back + +B<eg:> --nscheme="(%tr)-%ti" + +B<--device> I<device> + +set device to I<device>. default is /dev/dvd + +B<--cdinfo> + +show cddb information for current disc. + +=head1 SEE ALSO + +=over 4 + +=item B<sox>(1) B<ffmpeg>(1) B<lame>(1) B<oggenc>(1) B<oggdec>(1) + +=item B<flac>(1) B<shorten>(1) B<faac>(1) B<faad>(1) B<mpcenc>(1) + +=item B<mpcdec>(1) B<mplayer>(1) B<speexenc>(1) B<speexdec>(1) + +=item B<sndfile-convert>(1) B<normalize>(1) B<cdparanoia>(1) + +=item B<opusenc>(1) B<opusdec>(1) B<wavpack>(1) B<ffmpeg>(1) + +=item B<mplayer>(1) B<avconv>(1) + +=back + +=head1 BUGS + +Report all bugs to Philip Lyons (vorzox@gmail.com) + +=head1 LICENSING + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +=head1 AUTHOR + +Copyright (C) 2005-2018 Philip Lyons (vorzox@gmail.com)
View file
pacpl-6.1.0.tar.gz/patches/0001-Choose-decoder-encoder-based-on-the-codec-and-not-th.patch
Added
@@ -0,0 +1,214 @@ +From 69ec774ea202d74f20891bf0e6adae89d1b61fb7 Mon Sep 17 00:00:00 2001 +From: marcelpaulo <marcelpaulo@gmail.com> +Date: Mon, 26 Mar 2018 15:56:19 -0300 +Subject: PATCH Choose decoder/encoder based on the codec and not the file + extension: for m4a files, get the codec with Audio::Scan; for the others, use + the extension as the codec + +--- + codecs.conf | 3 +-- + pacpl.in | 73 +++++++++++++++++++++++++++++++++++++++++++++---------------- + 2 files changed, 55 insertions(+), 21 deletions(-) + +diff --git a/codecs.conf b/codecs.conf +index dffc4ea..5d6b47d 100644 +--- a/codecs.conf ++++ b/codecs.conf +@@ -48,11 +48,10 @@ FLAC = flac,flac + + FLA = flac,flac + +-# MP4 / M4A # ++# MP4 # + # E: faac, ffmpeg, avconv + # E: faad, ffmpeg, avconv, mplayer + +-M4A = faac,faad + MP4 = faac,faad + + # MP3 # +diff --git a/pacpl.in b/pacpl.in +index 611bb2d..3267448 100644 +--- a/pacpl.in ++++ b/pacpl.in +@@ -81,7 +81,7 @@ my + + # name, version + my $name = "Perl Audio Converter"; +-my $version = "6.0"; ++my $version = "6.1"; + + # If these options are toggled, messages/errors will be displayed + # via kdialog or zenity/notify-send (depending on environment) +@@ -1333,7 +1333,8 @@ my $pm = Parallel::ForkManager->new($jobs); + }, + }, + +- m4a => { ++ # m4a container with AAC codec ++ mp4a => { + + DEFAULT_ENCODER => "faac", + DEFAULT_DECODER => "faad", +@@ -1403,18 +1404,50 @@ my $pm = Parallel::ForkManager->new($jobs); + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + ++ }, ++ ++ ESTR => sub { "$eopts -w -q $aacqual %i -o %o" }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::Scan", ++ }, ++ }, ++ ++ # m4a container with ALAC codec ++ alac => { ++ ++ DEFAULT_ENCODER => undef, ++ DEFAULT_DECODER => "alac-decoder", ++ ++ DECODER => { ++ + 'alac-decoder' => { + NAME => "alac-decoder", + DSTR => sub { "$dopts -f %o %i" }, + }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, + + }, + +- ESTR => sub { "$eopts -w -q $aacqual %i -o %o" }, +- + TAGS => { + READ => 1, +- WRITE => 1, ++ WRITE => 0, + MODULE => "Audio::Scan", + }, + }, +@@ -2347,7 +2380,8 @@ sub proc_files { + $decoder = $my_decoder if defined($my_decoder); + + $encoder = $run{$to}{DEFAULT_ENCODER} if not $my_encoder; +- $decoder = $run{$if}{DEFAULT_DECODER} if not $my_decoder; ++ my $codec = ( $if eq "m4a" ? Audio::Scan->scan_info($i)->{info}->{tracks}0->{encoding} : $if ); ++ $decoder = $run{$codec}{DEFAULT_DECODER} if not $my_decoder; + + if (-e "$dir/$file.$to" and not $overwrite) { + pnotice("overwrite","$file.$to",1); +@@ -2355,10 +2389,10 @@ sub proc_files { + next; + } + +- if (check_input($file,$dir,$if) == 0) { ++ if (check_input($file,$dir,$codec) == 0) { + + pnotice("unk_encoder","$file.$ext",1), next unless(exists($run{$to}{ENCODER}{$encoder})); +- pnotice("unk_decoder","$file.$ext",1), next unless(exists($run{$if}{DECODER}{$decoder})); ++ pnotice("unk_decoder","$file.$ext",1), next unless(exists($run{$codec}{DECODER}{$decoder})); + + get_visual_opts($to,$outdir) if $gui and not defined($first_run); + +@@ -2378,6 +2412,7 @@ sub proc_files { + $files{"FILE$number"}{FILE} = "$dir/$file"; + $files{"FILE$number"}{OUTF} = "$outdir/$outfile"; + $files{"FILE$number"}{EXT} = "$ext"; ++ $files{"FILE$number"}{CODEC} = "$codec"; + $files{"FILE$number"}{NAME} = "$file"; + $files{"FILE$number"}{OUTD} = "$outfile"; + $files{"FILE$number"}{DECODER} = "$decoder"; +@@ -2497,7 +2532,7 @@ find ( sub { + # convert input to destination format + sub convert { + +- my ($inf, $outf, $infmt, $iname, $oname, $dec) = @_; ++ my ($inf, $outf, $infmt, $iname, $oname, $codec, $dec) = @_; + + my $if = $infmt; + $if =~ tr/A-Z/a-z/; +@@ -2514,17 +2549,17 @@ sub convert { + # that supports the desired input/output formats. + $decoder = $dec; + check_encoder(); +- check_decoder($infmt); ++ check_decoder($codec); + +- my $decode_string = $run{$if}{DECODER}{$decoder}{DSTR}->(); ++ my $decode_string = $run{$codec}{DECODER}{$decoder}{DSTR}->(); + $decode_string =~ s/%i/\"$inf.$infmt\"/; + $decode_string =~ s/%o/\"$outf.$$.wav\"/; + $decode_string =~ s/(\$|\\)/\\$1/g; + +- pnotice("debug","\n$run{$if}{DECODER}{$decoder}{NAME} $decode_string", 2) if $dryrun; ++ pnotice("debug","\n$run{$codec}{DECODER}{$decoder}{NAME} $decode_string", 2) if $dryrun; + + # decode input file to temporary wav +- system("$run{$if}{DECODER}{$decoder}{NAME} $decode_string $silent") if not $dryrun; ++ system("$run{$codec}{DECODER}{$decoder}{NAME} $decode_string $silent") if not $dryrun; + + # remove temporary wav file and die if decode fails + if ($? > 0) { +@@ -2540,7 +2575,7 @@ sub convert { + system("normalize $nopts \"$outf.$$.wav\"") if $normalize; + + # copy meta-data from input file to %tag_name +- read_tags("$inf.$infmt", "$if") if $run{$if}{TAGS}{READ} == 1 and not $dryrun; ++ read_tags("$inf.$infmt", "$codec") if $run{$codec}{TAGS}{READ} == 1 and not $dryrun; + + my $tag_opts = format_tags($to); # tag options for mp4/m4a/m4b/mpc/mpp/bonk/spx/wv + +@@ -2605,7 +2640,7 @@ sub fork_files { + say "$msg" if not $gui; + system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$msg\" 10 &") if $gui and $kde; + system("notify-send \"$name\" \"$msg\" -t 35 -i $icon_path &") if $gui and $gnome; +- convert("$files{$_}{FILE}","$files{$_}{OUTF}","$files{$_}{EXT}","$files{$_}{NAME}","$files{$_}{OUTD}","$files{$_}{DECODER}"); ++ convert("$files{$_}{FILE}","$files{$_}{OUTF}","$files{$_}{EXT}","$files{$_}{NAME}","$files{$_}{OUTD}","$files{$_}{CODEC}","$files{$_}{DECODER}"); + $pm->finish; + } + +@@ -2653,12 +2688,12 @@ sub check_input { + + my $file = shift; + my $dir = shift; +- my $ext = shift; ++ my $codec = shift; + + perror("no_encoder","$to") unless(defined($run{$to}{ENCODER})); + +- unless(defined($run{$ext}{DECODER})) { +- pnotice("no_decoder","$ext",2) if $verbose or not $only; ++ unless(defined($run{$codec}{DECODER})) { ++ pnotice("no_decoder","$codec",2) if $verbose or not $only; + $total_failed++; + return 1; + } +@@ -2940,7 +2975,7 @@ sub read_tags { + return 0; + } + +- when (/^mp4$|^m4a$|^m4b$/) { ++ when (/^(mp4|m4b|alac|mp4a)$/) { + my $mp4_tag = $tag_module->scan_tags($in_file)->{tags}; + + $tag_name{title} = $mp4_tag->{NAM} if $mp4_tag->{NAM}; +-- +2.14.1 +
View file
pacpl-6.1.0.tar.gz/patches/0001-Fix-installation-under-different-prefix-and-or-DESTD.patch
Added
@@ -0,0 +1,104 @@ +From 3f7aa5a851ef842d1d38d0f37db7dc21e60df3b8 Mon Sep 17 00:00:00 2001 +From: Reuben Thomas <rrt@sc3d.org> +Date: Mon, 22 Jan 2018 13:11:43 +0000 +Subject: PATCH 1/2 Fix installation under different --prefix and/or DESTDIR + +Use DESTDIR consistently. + +Use sysconfdir and pkgdatadir to track user-configured prefix. + +Remove unnecessary re-definitions of automake variables from +Makefile.am. +--- + Makefile.am | 21 ++++----------------- + Makefile.in | 11 ++++------- + 2 files changed, 8 insertions(+), 24 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index f52a21e..d3506f1 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -65,23 +65,10 @@ RM = @RM@ -f + SHELL = /bin/sh + + # +-# Configured directories... +-# +- +-prefix = @prefix@ +-exec_prefix = @exec_prefix@ +-bindir = @bindir@ +-datarootdir = @datarootdir@ +-includedir = @includedir@ +-libdir = @libdir@ +-mandir = @mandir@ +-docdir = @docdir@ +- +-# + # Configuration files directories and other + # +-CONF_DIR = $(DESTDIR)/etc/$(PACKAGE_NAME) +-PO_DIR = $(DESTDIR)/usr/share/pacpl/locale ++CONF_DIR = $(DESTDIR)$(sysconfdir)/$(PACKAGE_NAME) ++PO_DIR = $(DESTDIR)$(pkgdatadir)/locale + MOD_DIR = $(CONF_DIR)/modules + DOC_DIR = $(DESTDIR)$(docdir) + MAN_DIR = $(DESTDIR)$(mandir)/man1 +@@ -157,7 +144,7 @@ uninstall: uninstall-plugins + $(RM) $(MAN_DIR)/pacpl.1.gz + $(RM) -r $(CONF_DIR) + $(RM) -r $(DOC_DIR) +- $(RM) -r $(DESTDIR)/usr/share/pacpl ++ $(RM) -r $(DESTDIR)$(pkgdatadir) + + uninstall-plugins: + if INSTALL_KDE +@@ -173,4 +160,4 @@ if INSTALL_NEMO + $(RM) $(NEMO_INSTALL_DIR)/PACPL-Convert + $(RM) $(NEMO_INSTALL_DIR)/pacpl.nemo_action + $(RM) $(ICON_DIR)/pacpl.png +-endif +\ No newline at end of file ++endif +diff --git a/Makefile.in b/Makefile.in +index 04dbeb4..ff102dc 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -269,13 +269,10 @@ mandir = @mandir@ + mkdir_p = @mkdir_p@ + oldincludedir = @oldincludedir@ + pdfdir = @pdfdir@ +- +-# +-# Configured directories... +-# + prefix = @prefix@ + program_transform_name = @program_transform_name@ + psdir = @psdir@ ++runstatedir = @runstatedir@ + sbindir = @sbindir@ + sharedstatedir = @sharedstatedir@ + srcdir = @srcdir@ +@@ -311,8 +308,8 @@ ICON_DIR = $(DESTDIR)$(GNOMEDIR)/share/icons + # + # Configuration files directories and other + # +-CONF_DIR = $(DESTDIR)/etc/$(PACKAGE_NAME) +-PO_DIR = $(DESTDIR)/usr/share/pacpl/locale ++CONF_DIR = $(DESTDIR)$(sysconfdir)/$(PACKAGE_NAME) ++PO_DIR = $(DESTDIR)$(pkgdatadir)/locale + MOD_DIR = $(CONF_DIR)/modules + DOC_DIR = $(DESTDIR)$(docdir) + MAN_DIR = $(DESTDIR)$(mandir)/man1 +@@ -698,7 +695,7 @@ uninstall: uninstall-plugins + $(RM) $(MAN_DIR)/pacpl.1.gz + $(RM) -r $(CONF_DIR) + $(RM) -r $(DOC_DIR) +- $(RM) -r $(DESTDIR)/usr/share/pacpl ++ $(RM) -r $(DESTDIR)$(pkgdatadir) + + uninstall-plugins: + @INSTALL_KDE_TRUE@ $(RM) $(KDE_INSTALL_DIR)/pacpl.desktop +-- +2.7.4 +
View file
pacpl-6.1.0.tar.gz/patches/0002-Fix-hardwired-installation-paths-in-pacpl.patch
Added
@@ -0,0 +1,8196 @@ +From c497331621c0a6c128169945f67b552e81ab539f Mon Sep 17 00:00:00 2001 +From: Reuben Thomas <rrt@sc3d.org> +Date: Mon, 22 Jan 2018 13:21:55 +0000 +Subject: PATCH 2/2 Fix hardwired installation paths in pacpl + +--- + Makefile.am | 10 + + configure | 16 +- + configure.ac | 2 +- + pacpl | 4034 ---------------------------------------------------------- + pacpl.in | 4034 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 4059 insertions(+), 4037 deletions(-) + delete mode 100755 pacpl + create mode 100755 pacpl.in + +diff --git a/Makefile.am b/Makefile.am +index d3506f1..ee5503b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -74,8 +74,18 @@ DOC_DIR = $(DESTDIR)$(docdir) + MAN_DIR = $(DESTDIR)$(mandir)/man1 + EXTRA_DIR = $(CONF_DIR)/extra + ++edit = sed \ ++ -e 's|@pkgdatadir@|$(pkgdatadir)|g' \ ++ -e 's|@sysconfdir@|$(sysconfdir)|g' ++ + all : pacpl.1.gz + ++pacpl: pacpl.in Makefile ++ rm -f $@ $@.tmp ++ $(edit) '$@.in' >$@.tmp ++ mv $@.tmp $@ ++ chmod +x $@ ++ + pacpl.1.gz : pacpl + $(POD2MAN) $< | $(GZIP) -9 > $@ + touch $@ +diff --git a/configure b/configure +index 49a871d..0423607 100755 +--- a/configure ++++ b/configure +@@ -582,7 +582,7 @@ PACKAGE_BUGREPORT='' + PACKAGE_URL='' + + ac_default_prefix=/usr +-ac_unique_file="pacpl" ++ac_unique_file="pacpl.in" + ac_subst_vars='LTLIBOBJS + LIBOBJS + DESTDIR +@@ -687,6 +687,7 @@ infodir + docdir + oldincludedir + includedir ++runstatedir + localstatedir + sharedstatedir + sysconfdir +@@ -758,6 +759,7 @@ datadir='${datarootdir}' + sysconfdir='${prefix}/etc' + sharedstatedir='${prefix}/com' + localstatedir='${prefix}/var' ++runstatedir='${localstatedir}/run' + includedir='${prefix}/include' + oldincludedir='/usr/include' + docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +@@ -1010,6 +1012,15 @@ do + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + ++ -runstatedir | --runstatedir | --runstatedi | --runstated \ ++ | --runstate | --runstat | --runsta | --runst | --runs \ ++ | --run | --ru | --r) ++ ac_prev=runstatedir ;; ++ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ ++ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ ++ | --run=* | --ru=* | --r=*) ++ runstatedir=$ac_optarg ;; ++ + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ +@@ -1147,7 +1158,7 @@ fi + for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ +- libdir localedir mandir ++ libdir localedir mandir runstatedir + do + eval ac_val=\$$ac_var + # Remove trailing slashes. +@@ -1300,6 +1311,7 @@ Fine tuning of the installation directories: + --sysconfdir=DIR read-only single-machine data PREFIX/etc + --sharedstatedir=DIR modifiable architecture-independent data PREFIX/com + --localstatedir=DIR modifiable single-machine data PREFIX/var ++ --runstatedir=DIR modifiable per-process data LOCALSTATEDIR/run + --libdir=DIR object code libraries EPREFIX/lib + --includedir=DIR C header files PREFIX/include + --oldincludedir=DIR C header files for non-gcc /usr/include +diff --git a/configure.ac b/configure.ac +index 281f31f..887f580 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -22,7 +22,7 @@ AC_SUBST(KDEDIR) + + AC_PREFIX_DEFAULT(/usr) + AC_PREFIX_PROGRAM(pacpl) +-AC_CONFIG_SRCDIR(pacpl) ++AC_CONFIG_SRCDIR(pacpl.in) + + AC_PROG_INSTALL + +diff --git a/pacpl b/pacpl +deleted file mode 100755 +index 2ad3b74..0000000 +--- a/pacpl ++++ /dev/null +@@ -1,4034 +0,0 @@ +-#!/usr/bin/perl +-# +-# Perl Audio Converter +-# +-# Copyright (C) 2005-2017 Philip Lyons (vorzox@gmail.com) +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 3 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program. If not, see <http://www.gnu.org/licenses/>. +- +-use strict; +-use warnings; +-use Getopt::Long; +-use File::Basename; +-use File::Find; +-use File::Spec::Functions qw(rel2abs); +-use Parallel::ForkManager; +- +-use feature qw(switch say); +- +-no if $ >= 5.018, warnings => "experimental::smartmatch"; +- +-# Tagging modules +-use MP3::Tag; +-use Audio::FLAC::Header; +-use Audio::Scan; +- +-# CDDB module +-use CDDB_get qw(get_cddb); +- +-# non-encoder/decoder related options +-my +-( +- $to, +- $recursive, +- $preserve, +- $rip, +- $help, +- $longhelp, +- $verbose, +- $verinfo, +- $dryrun, +- $delete, +- $keep, +- $overwrite, +- $formats, +- $topdir, +- $only, +- $first_run, +- +- @file, +- @dir, +- +- %run, +- %lang, +-); +- +-my $silent = "> /dev/null 2>&1"; +- +-# tagging options +-my +-( +- $title, +- $track, +- $artist, +- $album, +- $comment, +- $year, +- $genre, +- $taginfo, +-); +- +-# name, version & icon information +-my $name = "Perl Audio Converter"; +-my $version = "5.1.0"; +-my $icon_path = "/etc/pacpl/pacpl.png"; +- +-# If these options are toggled, messages/errors will be displayed +-# via kdialog or zenity/notify-send (depending on environment) +-my ($gui, $kde, $gnome); +- +-# Debugging (for developer use only) +-my $debug = 0; +- +-# default configuration. +-my %config = ( +- +- IMPORTM => 0, +- JOBS => 4, +- +- DEFOPTS => 1, +- EOPTS => '', +- DOPTS => '', +- NOPTS => '', +- +- BITRATE => 128, +- FREQ => 44100, +- CHANNELS => 2, +- EFFECT => '', +- FCOMP => 2, +- PCOMP => 3, +- ACOMP => 3000, +- OGGQUAL => 3, +- SPXQUAL => 8, +- AACQUAL => 100, +- MPCQUAL => 'radio', +- OFMODE => 'normal', +- OFOPT => 'fast', +- BRATIO => 2, +- BQUANL => 1.0, +- BPSIZE => 128, +- +- USE_CDDB => 1, +- CDDB_HOST => 'freedb.freedb.org', +- CDDB_PORT => 8880, +- CDDB_MODE => 'cddb', +- CDDB_INPUT => 1, +- DEVICE => '/dev/dvd', +- NSCHEME => '%ar - %ti', +- +- ZEN_DIR => 1, +- ZEN_OPTS => 1, +- KDE_DIR => 1, +- KDE_OPTS => 1, +- +- ); +- +-# location of configuration file +-my $conf_path = "/etc/pacpl"; +-my $po_dir = "/usr/share/pacpl/locale"; +-my $mod_dir = "$conf_path/modules"; +- +-my $conf_file; +- +-# load the appropriate locale file +-load_lang(); +- +-# try to load configuration file in this order... +-my @conf_locations = ( +- "$ENV{HOME}/.pacplrc", # Local +- "$conf_path/pacpl.conf", # Global +- "$ENV{PWD}/pacpl.conf", # Current Directory +- ); +- +-# try to load conf file from one of the above locations +-foreach my $i (@conf_locations) { +- if (not $conf_file and -e $i) { +- $conf_file = $i; +- say "$lang{debug} $lang{loaded_config} $conf_file" if $debug == 1; +- } +-} +- +-say "$lang{no_config}" if not $conf_file; +- +-# open config file. +-if ($conf_file and -e $conf_file) { +- +- open(CONF, "$conf_file") or die "$lang{opening_file} $conf_file - $!\n"; +- +- my @conf_opts = <CONF>; +- @conf_opts = grep(!/^#|^$/, @conf_opts); +- +- close(CONF); +- +- # now read config file options and change default values accordingly. +- foreach (@conf_opts) { +- chomp; +- my ($k, $v) = split(/\s*=\s*/); +- $config{$k} = $v if exists($config{$k}) and $v; +- say "$lang{debug} $k = $v" if $debug == 1 and exists($config{$k}); +- } +-} +- +-my $codecs_conf = "$conf_path/codecs.conf"; +- +-# set default encoders/decoders +-sub load_codecs { +- +- open(CODECS, "$codecs_conf") or die "$lang{opening_file} $codecs_conf - $!\n"; +- +- my @codecs = <CODECS>; +- @codecs = grep(!/^$|^#/, @codecs); +- @codecs = grep(s/^\s*|\s*$//, @codecs); +- +- close(CODECS); +- +- foreach (@codecs) { +- +- chomp; +- my ($k, $v) = split(/\s*=\s*/); +- my ($e, $d) = split(/,/, $v); +- +- $k =~ tr/A-Z/a-z/; +- +- $run{$k}{DEFAULT_ENCODER} = $e if (exists($run{$k}{DEFAULT_ENCODER})); +- $run{$k}{DEFAULT_DECODER} = $d if (exists($run{$k}{DEFAULT_DECODER})); +- } +-} +- +-# load po file and store in %lang hash +-sub load_lang { +- +- my $po = "$po_dir/$ENV{LANG}.po"; +- $po =~ s/\.UTF-8//i if $po =~ /UTF-8/i; +- $po =~ s/\.utf8//i if $po =~ /utf8/i; +- $po =~ s/_\w+// if not -e $po; +- $po = "$po_dir/en_US.po" if not -e $po; +- +- open(LANG, "< $po") or die "error: could not open - $po\n$!\n"; +- +- my @data = <LANG>; +- @data = grep(!/^#|^$/, @data); +- +- close(LANG); +- +- foreach (@data) { +- chomp; +- s/=/__EQ__/; +- my ($k, $v) = split(/\s*__EQ__\s*/, $_); +- $lang{$k} = $v; +- } +- +-} +- +-my $banner = 1; +- +-# print error messages +-sub perror { +- my ($key, $msg) = @_; +- say "$name - $version\n"; +- say "$lang{error}: $lang{$key} $msg" . "\n"; +- system("kdialog --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $kde; +- system("zenity --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $gnome; +- die "$lang{seek_help}\n"; +-} +- +-# print notices/warnings +-sub pnotice { +- +- my ($key, $msg, $nm) = @_; +- +- say "$name - $version\n" if $banner == 1; +- print "$lang{$key} $msg"; +- say '' if $nm == 1; +- say "\n" if $nm == 2; +- +- $banner = 0; +-} +- +-# defaults for user variables. +-my $outfile; +-my $outdir; +-my $defopts = $config{DEFOPTS}; +-my $eopts = $config{EOPTS}; +-my $dopts = $config{DOPTS}; +-my $nopts = $config{NOPTS}; +-my $normalize = $config{NOPTS}; +-my $bitrate = $config{BITRATE}; +-my $freq = $config{FREQ}; +-my $channels = $config{CHANNELS}; +-my $effect = $config{EFFECT}; +-my $fcomp = $config{FCOMP}; +-my $acomp = $config{ACOMP}; +-my $oggqual = $config{OGGQUAL}; +-my $spxqual = $config{SPXQUAL}; +-my $aacqual = $config{AACQUAL}; +-my $mpcqual = $config{MPCQUAL}; +-my $ofmode = $config{OFMODE}; +-my $ofopt = $config{OFOPT}; +-my $bratio = $config{BRATIO}; +-my $bquanl = $config{BQUANL}; +-my $bpsize = $config{BPSIZE}; +- +-my $cdinfo; +-my $nocddb; +-my $noinput; +-my $device = $config{DEVICE}; +-my $nscheme = $config{NSCHEME}; +-my $my_encoder; +-my $my_decoder; +-my $encoder; +-my $decoder; +- +-my $jobs = $config{JOBS}; +- +-# command line options +-GetOptions +-( +- 't|to=s' => \$to, +- 'r|recursive' => \$recursive, +- 'p|preserve' => \$preserve, +- 'h|help' => \$help, +- 'l|longhelp' => \$longhelp, +- 'v|verbose' => \$verbose, +- 'f|formats' => \$formats, +- 'o|only=s' => \$only, +- 'k|keep' => \$keep, +- 'j|jobs=n' => \$jobs, +- +- 'taginfo' => \$taginfo, +- +- 'version' => \$verinfo, +- 'dryrun' => \$dryrun, +- 'delete' => \$delete, +- 'overwrite' => \$overwrite, +- 'normalize' => \$normalize, +- 'encoder=s' => \$my_encoder, +- 'decoder=s' => \$my_decoder, +- +- 'title=s' => \$title, +- 'track=n' => \$track, +- 'artist=s' => \$artist, +- 'album=s' => \$album, +- 'comment=s' => \$comment, +- 'year=n' => \$year, +- 'genre=s' => \$genre, +- +- 'gui' => \$gui, +- 'kde' => \$kde, +- 'gnome' => \$gnome, +- +- 'eopts=s' => \$eopts, +- 'dopts=s' => \$dopts, +- 'defopts=n' => \$defopts, +- 'nopts=s' => \$nopts, +- 'outfile=s' => \$outfile, +- 'outdir=s' => \$outdir, +- +- 'bitrate=n' => \$bitrate, +- 'freq=n' => \$freq, +- 'channels=n' => \$channels, +- 'effect=s' => \$effect, +- 'fcomp=n' => \$fcomp, +- 'acomp=n' => \$acomp, +- 'oggqual=n' => \$oggqual, +- 'spxqual=n' => \$spxqual, +- 'aacqual=n' => \$aacqual, +- 'mpcqual=s' => \$mpcqual, +- 'ofmode=s' => \$ofmode, +- 'ofopt=s' => \$ofopt, +- 'bratio=n' => \$bratio, +- 'bquanl=n' => \$bquanl, +- 'bpsize=n' => \$bpsize, +- +- 'rip=s' => \$rip, +- 'nocddb' => \$nocddb, +- 'noinput' => \$noinput, +- 'device=s' => \$device, +- 'nscheme=s' => \$nscheme, +- 'cdinfo' => \$cdinfo, +-); +- +-if (defined($preserve) && !defined($outdir)) { +- die "You must specify --outdir when you use --preserve option. See man page.\n"; +-} +- +-$silent = '' if $verbose; +- +-my $opts; +-my $total_converted = 0; +-my $total_failed = 0; +- +-# Initialize the fork manager with a count set through pacpl.conf or via the command line +-my $pm = Parallel::ForkManager->new($jobs); +- +-# conversion options. when adding a new format, +-# wild card %i = input file and %o = output file +-%run = ( +- +- '3g2' => { +- +- DEFAULT_ENCODER => 'ffmpeg', +- DEFAULT_DECODER => 'ffmpeg', +- +- ENCODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = "-ar 8000 -ac 1" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ar 8000 -ac 1" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- +- }, +- +- DECODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "-y -i %o $dopts %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "-y -i %o %dopts %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- +- }, +- +- '3gp' => { +- +- DEFAULT_ENCODER => 'ffmpeg', +- DEFAULT_DECODER => 'ffmpeg', +- +- ENCODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = "-ar 8000 -ac 1" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ar 8000 -ac 1" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- +- }, +- +- DECODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "-y -i %o $dopts %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "-y -i %o %dopts %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- +- }, +- +- aac => { +- +- DEFAULT_ENCODER => "faac", +- DEFAULT_DECODER => "faad", +- +- ENCODER => { +- faac => { +- NAME => "faac", +- ESTR => sub { +- $opts = "-q $aacqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i -o %o" +- }, +- PROMPT => { AACQUAL => 1 }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 1, +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- faad => { +- NAME => "faad", +- DSTR => sub { "$dopts -o %i %o" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- ac3 => { +- +- DEFAULT_ENCODER => "ffmpeg", +- DEFAULT_DECODER => "ffmpeg", +- +- ENCODER => { +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => "avconv", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- aften => { +- NAME => "aften", +- ESTR => sub { +- $opts = "-v 1 -q $bitrate -2" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- }, +- }, +- +- }, +- +- DECODER => { +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => "avconv", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- adts => { +- +- DEFAULT_ENCODER => 'ffmpeg', +- DEFAULT_DECODER => 'ffmpeg', +- +- ENCODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $opts $eopts -strict -2 %o" +- }, +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $opts $eopts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => "$dopts -y -i %i %o", +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => "$dopts -y -i %i %o", +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- ape => { +- +- DEFAULT_ENCODER => "mac", +- DEFAULT_DECODER => "mac", +- +- ENCODER => { +- mac => { +- NAME => "mac", +- ESTR => sub { +- $opts = "-c$acomp" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "%i %o $opts $eopts" +- }, +- +- PROMPT => { ACOMP => 1 }, +- }, +- }, +- +- DECODER => { +- mac => { +- NAME => "mac", +- DSTR => sub { "%i %o -d $dopts" }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "-y -i %i %dopts %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "-y -i %i $dopts %o" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 0, +- MODULE => "Audio::Scan", +- }, +- }, +- +- amr => { +- +- DEFAULT_ENCODER => "ffmpeg", +- DEFAULT_DECODER => "ffmpeg", +- +- ENCODER => { +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ar 8000 -ac 1" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- +- avconv => { +- NAME => "avconv", +- ESTR => sub { +- $opts = "-ar 8000 -ac 1" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- +- }, +- +- DECODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "-y -i %i $dopts %o" }, +- }, +- +- avconv => { +- NAME => 'ffmpeg', +- DSTR => sub { "-y -i %i %dopts %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- +- }, +- +- bonk => { +- +- DEFAULT_ENCODER => "bonk", +- DEFAULT_DECODER => "bonk", +- +- ENCODER => { +- bonk => { +- NAME => "bonk", +- ESTR => sub { +- $opts = "-q $bquanl -b $bratio -s $bpsize" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "encode $eopts $opts %i -o %o" +- }, +- +- PROMPT => { +- BQUANL => 1, +- BRATIO => 1, +- BPSIZE => 1, +- }, +- }, +- }, +- +- DECODER => { +- bonk => { +- NAME => "bonk", +- DSTR => sub { "decode %i -o %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- dts => { +- +- DEFAULT_ENCODER => 'ffmpeg', +- DEFAULT_DECODER => 'ffmpeg', +- +- ENCODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = '' if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $opts $eopts -strict -2 -codec:a libfaac %o" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = '' if $defopts == 1 or $defopts == 0; +- "-y -i %i $opts $eopts -codec:a libfaac %o", +- }, +- PROMPT => { NONE => 0, }, +- }, +- +- dcaenc => { +- NAME => 'dcaenc', +- ESTR => sub { +- $opts = "$bitrate" if $defopts == 0; +- $opts = '' if $defopts == 1; +- "%i %o $opts" +- }, +- +- PROMPT => { NONE => 0, }, +- }, +- }, +- +- DECODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => "$dopts -y -i %i %o", +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => "$dopts -y -i %i %o", +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- flac => { +- +- DEFAULT_ENCODER => "flac", +- DEFAULT_DECODER => "flac", +- +- ENCODER => { +- flac => { +- NAME => "flac", +- ESTR => sub { +- $opts = "-$fcomp" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts -f $opts %i -o %o" +- }, +- PROMPT => { FCOMP => 1 }, +- }, +- +- flake => { +- NAME => "flake", +- ESTR => sub { +- $opts = "-$fcomp" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i -o %o" +- }, +- PROMPT => { FCOMP => 1 }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 1; +- "-y -i %i $eopts $opts %o" +- }, +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- flac => { +- NAME => "flac", +- DSTR => sub { "$dopts -f -d %i -o %o" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "Audio::FLAC::Header", +- }, +- }, +- +- fla => { +- +- DEFAULT_ENCODER => "flac", +- DEFAULT_DECODER => "flac", +- +- ENCODER => { +- flac => { +- NAME => "flac", +- ESTR => sub { +- $opts = "-$fcomp" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts -f $opts %i -o %o" +- }, +- PROMPT => { FCOMP => 1 }, +- }, +- }, +- +- DECODER => { +- flac => { +- NAME => "flac", +- DSTR => sub { "$dopts -f -d %i -o %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "Audio::FLAC::Header", +- }, +- }, +- +- la => { +- +- DEFAULT_ENCODER => "la", +- DEFAULT_DECODER => "la", +- +- ENCODER => { +- la => { +- NAME => "la", +- ESTR => sub { "-overwrite $eopts %i %o" }, +- PROMPT => { NONE => 0, }, +- }, +- }, +- +- DECODER => { +- la => { +- NAME => "la", +- ESTR => sub { "-console $dopts %i > %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- mp2 => { +- +- DEFAULT_ENCODER => "ffmpeg", +- DEFAULT_DECODER => "ffmpeg", +- +- ENCODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- toolame => { +- NAME => 'toolame', +- ESTR => sub { +- $opts = "-b $bitrate" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- }, +- }, +- +- twolame => { +- NAME => 'twolame', +- ESTR => sub { +- $opts = "-b $bitrate -s $freq" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- }, +- }, +- +- sox => { +- NAME => 'sox', +- ESTR => sub { +- $opts = "-c $channels -r $bitrate" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "%i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => "$dopts -y -i %i %o", +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => "%dopts -y -i %i %o", +- }, +- +- mplayer => { +- NAME => 'mplayer', +- DSTR => "-vc null -vo null -ao pcm:file=%o %i", +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- mp3 => { +- +- DEFAULT_ENCODER => "lame", +- DEFAULT_DECODER => "lame", +- +- ENCODER => { +- lame => { +- NAME => "lame", +- ESTR => sub { +- $opts = "--resample $freq -b $bitrate -h" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- }, +- }, +- +- bladeenc => { +- NAME => "bladeenc", +- ESTR => sub { +- $opts = "-br $bitrate" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- PROMPT => { BITRATE => 1 }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts -y -i %i $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- sox => { +- NAME => "sox", +- ESTR => sub { +- $opts = "-r $freq -c $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "%i $eopts $opts %o" +- }, +- +- PROMPT => { +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- lame => { +- NAME => "lame", +- DSTR => sub { "$dopts --decode %i %o" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %O" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- +- sox => { +- NAME => "sox", +- DSTR => sub { "%i $dopts %o" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "MP3::Tag", +- }, +- }, +- +- mp3hd => { +- +- DEFAULT_ENCODER => "mp3hdEncoder", +- DEFAULT_DECODER => "mp3hdDecoder", +- +- ENCODER => { +- mp3hdEncoder => { +- NAME => "mp3hdEncoder", +- ESTR => sub { +- $opts = "-br $bitrate" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts -if %i -of %o" +- }, +- PROMPT => { BITRATE => 1 }, +- }, +- }, +- +- DECODER => { +- mp3hdDecoder => { +- NAME => "mp3hdDecoder", +- DSTR => sub { "$dopts -if %i -of %o" }, +- }, +- }, +- +- TAGS => { +- WRITE => 1, +- READ => 1, +- MODULE => "MP3::Tag", +- }, +- }, +- +- mp4 => { +- +- DEFAULT_ENCODER => "faac", +- DEFAULT_DECODER => "faad", +- +- ENCODER => { +- +- faac => { +- NAME => "faac", +- ESTR => sub { +- $opts = "-q $aacqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts -w $opts %i -o %o" +- }, +- PROMPT => { AACQUAL => 1 }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PRIMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- +- faad => { +- NAME => "faad", +- DSTR => sub { "$dopts -o %o %i" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "Audio::Scan", +- }, +- }, +- +- m4a => { +- +- DEFAULT_ENCODER => "faac", +- DEFAULT_DECODER => "faad", +- +- ENCODER => { +- +- faac => { +- NAME => "faac", +- ESTR => sub { +- $opts = "-q $aacqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts -w $opts %i -o %o" +- }, +- PROMPT => { AACQUAL => 1 }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts -y -i %i $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- +- faad => { +- NAME => "faad", +- DSTR => sub { "$dopts -o %o %i" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- +- }, +- +- ESTR => sub { "$eopts -w -q $aacqual %i -o %o" }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "Audio::Scan", +- }, +- }, +- +- m4b => { +- +- DEFAULT_ENCODER => undef, +- DEFAULT_DECODER => "faad", +- +- DECODER => { +- faad => { +- NAME => "faad", +- DSTR => sub { "$dopts -o %o %i" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 1, +- MODULE => undef, +- }, +- }, +- +- mpc => { +- +- DEFAULT_ENCODER => "mpcenc", +- DEFAULT_DECODER => "mpcdec", +- +- ENCODER => { +- +- mpcenc => { +- NAME => "mpcenc", +- ESTR => sub { +- $opts = "--$mpcqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts --overwrite $opts %i %o" +- }, +- PROMPT => { MPCQUAL => 1 }, +- }, +- }, +- +- DECODER => { +- +- mpcdec => { +- NAME => "mpcdec", +- DSTR => sub { "$dopts %i %o" }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "Audio::Scan", +- }, +- +- PROMPT => { +- MPCQUAL => 1, +- }, +- }, +- +- mpp => { +- +- DEFAULT_ENCODER => "mpcenc", +- DEFAULT_DECODER => "mpcdec", +- +- ENCODER => { +- +- mpcenc => { +- NAME => "mpcenc", +- ESTR => sub { +- $opts = "--$mpcqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts --overwrite $opts %i %o" +- }, +- PROMPT => { MPCQUAL => 1 }, +- }, +- }, +- +- DECODER => { +- +- mpcdec => { +- NAME => "mpcdec", +- DSTR => sub { "$dopts %i %o" }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "Audio::Scan", +- }, +- }, +- +- off => { +- DEFAULT_ENCODER => 'off', +- DEFAULT_DECODER => 'off', +- +- ENCODER => { +- off => { +- NAME => 'off', +- ESTR => sub { +- $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts --overwrite $opts %i --output %o" +- }, +- +- PROMPT => { +- OFMODE => 1, +- OFOPT => 1, +- }, +- }, +- }, +- +- DECODER => { +- off => { +- NAME => 'off', +- DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- ofr => { +- +- DEFAULT_ENCODER => "ofr", +- DEFAULT_DECODER => "ofr", +- +- ENCODER => { +- ofr => { +- NAME => "ofr", +- ESTR => sub { +- $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts --overwrite $opts %i --output %o" +- }, +- +- PROMPT => { +- OFMODE => 1, +- OFOPT => 1, +- }, +- }, +- }, +- +- DECODER => { +- ofr => { +- NAME => "ofr", +- DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- ofs => { +- +- DEFAULT_ENCODER => "ofs", +- DEFAULT_DECODER => "ofs", +- +- ENCODER => { +- ofs => { +- NAME => "ofs", +- ESTR => sub { +- $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts --overwrite $opts %i --output %o" +- }, +- +- PROMPT => { +- OFMODE => 1, +- OFOPT => 1, +- }, +- }, +- }, +- +- DECODER => { +- ofs => { +- NAME => "ofs", +- DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- +- oga => { +- DEFAULT_ENCODER => 'oggenc', +- DEFAULT_DECODER => 'oggdec', +- +- ENCODER => { +- oggenc => { +- NAME => 'oggenc', +- ESTR => sub { +- $opts = "--resample $freq -q $oggqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- PROMPT => { +- FREQ => 1, +- OGGQUAL => 1, +- }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- sox => { +- NAME => "sox", +- ESTR => sub { +- $opts = "-r $freq -c $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "%i $eopts $opts %o" +- }, +- +- PROMPT => { +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- oggdec => { +- NAME => "oggdec", +- DSTR => sub { "$dopts %i --output %o" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- +- sox => { +- NAME => "sox", +- DSTR => sub { "%i $dopts %o" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "vorbiscomment", +- }, +- }, +- +- ogg => { +- +- DEFAULT_ENCODER => "oggenc", +- DEFAULT_DECODER => "oggdec", +- +- ENCODER => { +- oggenc => { +- NAME => "oggenc", +- ESTR => sub { +- $opts = "--resample $freq -q $oggqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i -o %o" +- }, +- +- PROMPT => { +- FREQ => 1, +- OGGQUAL => 1, +- }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- sox => { +- NAME => "sox", +- ESTR => sub { +- $opts = "-r $freq -c $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "%i $eopts $opts %o" +- }, +- +- PROMPT => { +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- oggdec => { +- NAME => "oggdec", +- DSTR => sub { "$dopts %i --output %o" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- +- sox => { +- NAME => "sox", +- DSTR => sub { "%i $dopts %o" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "vorbiscomment", +- }, +- }, +- +- opus => { +- +- DEFAULT_ENCODER => "opusenc", +- DEFAULT_DECODER => "opusdec", +- +- ENCODER => { +- opusenc => { +- NAME => 'opusenc', +- ESTR => sub { +- $opts = "--bitrate $bitrate" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- PROMTP => { +- BITRATE => 1, +- }, +- }, +- }, +- +- DECODER => { +- opusdec => { +- NAME => 'opusdec', +- DSTR => sub { "--force-wav %i %o" }, +- PROMPT => { NONE => 0 }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- raw => { +- +- DEFAULT_ENCODER => "sox", +- DEFAULT_DECODER => "sox", +- +- ENCODER => { +- sox => { +- NAME => 'sox', +- ESTR => sub { +- $opts = "-r $freq -c $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "%i $opts $eopts %o $effect" +- }, +- +- PROMPT => { +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- sox => { +- NAME => 'sox', +- DSTR => sub { "-w -s -r $freq -c $channels $dopts %i %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- rm => { +- +- DEFAULT_ENCODER => 'ffmpeg', +- DEFAULT_DECODER => 'ffmpeg', +- +- ENCODER => { +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = "-ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "-ar $freq -ac $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- FREQ => 1, +- CHANNELS => 1, +- }, +- }, +- }, +- +- DECODER => { +- mplayer => { +- NAME => 'mplayer', +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- shn => { +- +- DEFAULT_ENCODER => "shorten", +- DEFAULT_DECODER => "shorten", +- +- ENCODER => { +- shorten => { +- NAME => "shorten", +- ESTR => sub { +- $opts = "-c $channels" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- PROMPT => { CHANNELS => 1 }, +- }, +- }, +- +- DECODER => { +- shorten => { +- NAME => "shorten", +- DSTR => sub { "-x %i %o" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- spx => { +- +- DEFAULT_ENCODER => "speexenc", +- DEFAULT_DECODER => "speexdec", +- +- ENCODER => { +- speexenc => { +- NAME => "speexenc", +- ESTR => sub { +- $opts = "--quality $spxqual" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "$eopts $opts %i %o" +- }, +- PROMPT => { SPXQUAL => 1 }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { +- $opts = "--bitrate $bitrate.k" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i %i $eopts $opts %o" +- }, +- +- PROMPT => { +- BITRATE => 1, +- }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { +- $opts = "--bitrate $bitrate.k" if $defopts == 1; +- $opts = '' if $defopts == 0; +- "-y -i $eopts $opts %o" +- }, +- PROMPT => { +- BITRATE => 1, +- }, +- }, +- }, +- +- DECODER => { +- speexdec => { +- NAME => "speexdec", +- DSTR => sub { "$dopts %i %o" }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => undef, +- }, +- }, +- +- tta => { +- +- DEFAULT_ENCODER => "ttaenc", +- DEFAULT_DECODER => "ttaenc", +- +- ENCODER => { +- ttaenc => { +- NAME => "ttaenc", +- ESTR => sub { "$eopts -e %i -o %o" }, +- PROMPT => { NONE => 0, }, +- }, +- }, +- +- DECODER => { +- ttaenc => { +- NAME => "ttaenc", +- DSTR => sub { "$dopts -d %i -o %o" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- wav => { +- +- DEFAULT_ENCODER => "mv", +- DEFAULT_DECODER => "cp", +- +- ENCODER => { +- mv => { +- NAME => "mv", +- ESTR => sub { "%i %o" }, +- PROMPT => { NONE => 0, }, +- }, +- }, +- +- DECODER => { +- cp => { +- NAME => "cp", +- DSTR => sub { "%i %o" }, +- } +- }, +- +- TAGS => { +- READ => 0, +- WRITE => 0, +- MODULE => undef, +- }, +- }, +- +- wv => { +- +- DEFAULT_ENCODER => "wavpack", +- DEFAULT_DECODER => "wvunpack", +- +- ENCODER => { +- wavpack => { +- NAME => "wavpack", +- ESTR => sub { "$eopts -h -y %i -o %o" }, +- PROMPT => { NONE => 0, }, +- }, +- +- ffmpeg => { +- NAME => 'ffmpeg', +- ESTR => sub { "-y -i %i $eopts %o" }, +- PROMPT => { NONE => 0, }, +- }, +- +- avconv => { +- NAME => 'avconv', +- ESTR => sub { "-y -i %i $eopts %o" }, +- PROMPT => { NONE => 0, }, +- }, +- }, +- +- DECODER => { +- wvunpack => { +- NAME => "wvunpack", +- DSTR => sub { "$dopts -y %i -o %o" }, +- }, +- +- ffmpeg => { +- NAME => "ffmpeg", +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- avconv => { +- NAME => 'avconv', +- DSTR => sub { "$dopts -y -i %i %o" }, +- }, +- +- mplayer => { +- NAME => "mplayer", +- DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, +- }, +- }, +- +- TAGS => { +- READ => 1, +- WRITE => 1, +- MODULE => "Audio::Scan", +- }, +- }, +-); +- +-# supported ffmpeg/avconv formats (decode only) +-my @ffmpeg_codecs = ( "mmf", "ra", "wma" ); +-my @ffmpeg_forks = ( "avconv", "ffmpeg" ); +- +-foreach my $fork (@ffmpeg_forks) { +- +- foreach my $codec (@ffmpeg_codecs) { +- +- $run{$codec}{DEFAULT_ENCODER} = $fork; +- $run{$codec}{DEFAULT_DECODER} = $fork; +- $run{$codec}{ENCODER}{$fork}{NAME} = $fork; +- $run{$codec}{DECODER}{$fork}{NAME} = $fork; +- $run{$codec}{DECODER}{$fork}{DSTR} = sub {"-y %i $dopts %o"}; +- $run{$codec}{ENCODER}{$fork}{ESTR} = sub {"-y -i %i $eopts -ab $bitrate.k -ar $freq -ac $channels %o"}; +- $run{$codec}{TAGS}{READ} = 0; +- $run{$codec}{TAGS}{WRITE} = 0; +- $run{$codec}{TAGS}{MODULE} = undef; +- } +- +-} +- +-# support reading of WMA tags via Audio::Scan +-$run{wma}{TAGS}{READ} = 1; +-$run{wma}{TAGS}{MODULE} = "Audio::Scan"; +- +-# supported video to audio types +-my @movie_codecs = ( +- "rv", "asf", "avi", "divx", +- "mkv", "mpg", "mpeg", "mov", +- "ogm", "qt", "vcd", "vob", +- "wmv", "flv", "svcd", "m4v", +- "nsv", "nuv", "psp", "smk", +- "ogv", "webm", +- +- # decode only audio formats +- "vqf", "tak", +- ); +- +-foreach (@movie_codecs) { +- $run{$_}{DEFAULT_ENCODER} = undef; +- $run{$_}{DEFAULT_DECODER} = "ffmpeg"; +- $run{$_}{DECODER}{mplayer}{NAME} = "mplayer"; +- $run{$_}{DECODER}{ffmpeg}{NAME} = "ffmpeg"; +- $run{$_}{DECODER}{mplayer}{DSTR} = sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }; +- $run{$_}{DECODER}{ffmpeg}{DSTR} = sub { "$dopts -i %i %o"; }; +- $run{$_}{TAGS}{READ} = 0; +- $run{$_}{TAGS}{WRITE} = 0; +- $run{$_}{TAGS}{MODULE} = undef; +-} +- +-# supported sndfile-convert formats +-my @sndfile = ( +- "pvf", "caf", "sf", "paf", "fap", "sd2", +- "mat4", "mat5", "mat", "ircam", "w64", "nist", +- "rf64", +- ); +- +-foreach (@sndfile) { +- +- $run{$_}{DEFAULT_ENCODER} = "sndfile-convert"; +- $run{$_}{DEFAULT_DECODER} = "sndfile-convert"; +- $run{$_}{ENCODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; +- $run{$_}{DECODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; +- $run{$_}{ENCODER}{"sndfile-convert"}{ESTR} = sub { "$eopts %i %o" }; +- $run{$_}{DECODER}{"sndfile-convert"}{DSTR} = sub { "$dopts %i %o" }; +- $run{$_}{TAGS}{READ} = 0; +- $run{$_}{TAGS}{WRITE} = 0; +- $run{$_}{TAGS}{MODULE} = undef; +-} +- +-# supported sox formats +-my @sox_codecs = ( +- "aiff", "aif", "au", "snd", "voc", +- "smp", "avr", "cdr", "8svx", "amb", +- "dat", "dvms", "f32", "f64", "fssd", +- "gsrt", "hcom", "txw", "vms", "al", +- "sou", "ima", "prc", "cvu", +- "maud", +- ); +- +-foreach (@sox_codecs) { +- +- $run{$_}{DEFAULT_ENCODER} = "sox"; +- $run{$_}{DEFAULT_DECODER} = "sox"; +- $run{$_}{ENCODER}{sox}{NAME} = "sox"; +- $run{$_}{DECODER}{sox}{NAME} = "sox"; +- $run{$_}{ENCODER}{sox}{ESTR} = sub { "%i -r $freq -c $channels $eopts %o $effect" }; +- $run{$_}{DECODER}{sox}{DSTR} = sub { "%i $dopts %o" }; +- $run{$_}{TAGS}{READ} = 0; +- $run{$_}{TAGS}{WRITE} = 0; +- $run{$_}{TAGS}{MODULE} = undef; +- +- $run{$_}{ENCODER}{sox}{PROMPT}{FREQ} = 1; +- $run{$_}{ENCODER}{sox}{PROMPT}{CHANNELS} = 1; +- +-} +- +-# load codecs.conf file +-load_codecs() if -e $codecs_conf; +- +-my $out_name = $outfile; +-my $out_dir = $outdir; +-my $first_message = 1; +-my %files; +-my $number = 0; +- +-# process all files and directories +-sub proc_input { +- +- $to =~ tr/A-Z/a-z/; +- +- perror("bad_input","") unless(exists($run{$to})); +- +- proc_preserve_dir($dir0) if @dir and $preserve; # process recursive directory preservation (sends to proc_files +- proc_dirs() if @dir and not $preserve; # process directories including recursively (sends to proc_files) +- proc_files() if @file; # process all files +- fork_files(); # start the conversion process. +-} +- +-# process all files (all roads lead to rome) +-sub proc_files { +- +- if (@file) { +- +- foreach my $i (sort(@file)) { +- +- my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); +- +- $ext =~ s/^\.//; +- $dir = rel2abs($dir); +- $outdir = $dir if not defined($out_dir) and not $preserve; +- $outdir = $out_dir if $preserve; +- +- my $if = $ext; +- $if =~ tr/A-Z/a-z/; +- +- $only =~ tr/A-Z/a-z/ if $only; +- +- next if $only and $if ne $only; +- +- $encoder = $my_encoder if defined($my_encoder); +- $decoder = $my_decoder if defined($my_decoder); +- +- $encoder = $run{$to}{DEFAULT_ENCODER} if not $my_encoder; +- $decoder = $run{$if}{DEFAULT_DECODER} if not $my_decoder; +- +- if (-e "$file.$to" and not $overwrite) { +- pnotice("overwrite","$file.$to",1); +- $total_failed++; +- next; +- } +- +- if (check_input($file,$dir,$if) == 0) { +- +- pnotice("unk_encoder","$file.$ext",1), next unless(exists($run{$to}{ENCODER}{$encoder})); +- pnotice("unk_decoder","$file.$ext",1), next unless(exists($run{$if}{DECODER}{$decoder})); +- +- get_visual_opts($to,$outdir) if $gui and not defined($first_run); +- +- $first_run = 1; +- +- perror("multi_out","") if (defined($out_name) and $#file gt 0 or defined($out_name) and @dir); +- perror("no_outdir","") if (not -e $outdir and not -d $outdir); +- +- $outfile = "$file" if not $out_name; +- +- if ($keep and $if eq $to) { +- system("cp -v \"$dir/$file.$ext\" \"$outdir/$outfile.$ext\"") if $outdir ne $dir and not -e "$outdir/$outfile.$ext"; +- next if $outdir eq $dir; +- } +- +- else { +- $files{"FILE$number"}{FILE} = "$dir/$file"; +- $files{"FILE$number"}{OUTF} = "$outdir/$outfile"; +- $files{"FILE$number"}{EXT} = "$ext"; +- $files{"FILE$number"}{NAME} = "$file"; +- $files{"FILE$number"}{OUTD} = "$outfile"; +- $files{"FILE$number"}{DECODER} = "$decoder"; +- +- $number++; +- } +- +- } +- } +- } +- undef(@file); +-} +- +-# process directories and push all to @file arrary +-sub proc_dirs { +- +- if (@dir) { +- +- my @tmp_dir = @dir; +- undef(@dir); +- $topdir = $tmp_dir0; +- +- if (not $recursive) { +- +- undef(@file); +- +- foreach my $d (@tmp_dir) { +- +- opendir(DIR, "$d") or perror("opening_dir","$d: $!"); +- my @dir_files = readdir(DIR); +- closedir(DIR); +- perror("empty_dir","$d") if $#dir_files <= 1; +- +- foreach my $f (@dir_files) { +- +- if (not -d $f and not -d "$d/$f") { +- push(@file, "$d/$f"); +- undef($out_name); +- } +- } +- } +- +- proc_files(); +- return 0; +- +- } +- +- elsif ($recursive) { +- +- if (not $preserve) { +- +- undef(@file); +- +- foreach my $r (@tmp_dir) { +- +- $r = rel2abs($r); +- +- find ( sub { +- my $rfile = $File::Find::name; +- push(@file, $rfile) if not -d $rfile; +- }, $r +- ); +- } +- +- proc_files(); +- return 0; +- +- } +- } +- +- } +-} +- +-# preserve directory structuer (revised 10-7-2013) +-my $out_dir_original = rel2abs($outdir) if $outdir and -d $outdir; +- +-sub proc_preserve_dir { +- +-$topdir = rel2abs($dir0); +- +-perror("no_outdir","") if not defined($out_dir_original); +-perror("no_outdir","") if not -d $out_dir_original; +- +-undef(@file); # clear the array before we begin. +- +-find ( sub { +- my $val = $File::Find::name; +- $val =~ s/(\$)/\\\$/g; +- +- if ($val ne $topdir) { +- +- $val =~ s/$topdir\///; +- +- # create mirrored directories in output directory +- if (not -f fileparse("$topdir/$val") and not -d "$out_dir_original/$val") { +- say "creating directory $out_dir_original/$val" if not -f "$topdir/$val" and $verbose; +- mkdir("$out_dir_original/$val", 0755) if not -f "$topdir/$val"; +- } +- +- # this will list all files in their original directories +- if (-f "$topdir/$val") { +- say "$lang{debug} pushing to \@file: $topdir/$val" if $debug == 1; +- push(@file, "$topdir/$val"); +- } +- +- # set $out_dir to the +- $out_dir = "$out_dir_original/" . dirname($val) if -f "$topdir/$val"; +- +- # send file, and output dir to proc_files(); +- proc_files(); +- } +- +- }, $topdir +- ); +-} +- +-# convert input to destination format +-sub convert { +- +- my ($inf, $outf, $infmt, $iname, $oname, $dec) = @_; +- +- my $if = $infmt; +- $if =~ tr/A-Z/a-z/; +- +- clear_tag_hash() if not $rip; +- +- # catch ^C. will have to be pressed repeatedly to exit the process. +- $SIG{INT} = sub { +- unlink("$outf.$$.wav"); +- kill 9, $$; +- }; +- +- # check to see if encoder/decoder exists. if not, see if we have one +- # that supports the desired input/output formats. +- $decoder = $dec; +- check_encoder(); +- check_decoder($infmt); +- +- my $decode_string = $run{$if}{DECODER}{$decoder}{DSTR}->(); +- $decode_string =~ s/%i/\"$inf.$infmt\"/; +- $decode_string =~ s/%o/\"$outf.$$.wav\"/; +- $decode_string =~ s/(\$|\\)/\\$1/g; +- +- pnotice("debug","\n$run{$if}{DECODER}{$decoder}{NAME} $decode_string", 2) if $dryrun; +- +- # decode input file to temporary wav +- system("$run{$if}{DECODER}{$decoder}{NAME} $decode_string $silent") if not $dryrun; +- +- # remove temporary wav file and die if decode fails +- if ($? > 0) { +- unlink("$outf.$$.wav") if -e "$outf.$$.wav"; +- say ""; +- $banner = 0; +- pnotice("decode_failed","$inf.$infmt: try with --verbose",1); +- return 1; +- } +- +- # normalize wav file before encoding to output format +- perror("no_app","normalize") if $normalize and not `which normalize 2>/dev/null`; +- system("normalize $nopts \"$outf.$$.wav\"") if $normalize; +- +- # copy meta-data from input file to %tag_name +- read_tags("$inf.$infmt", "$if") if $run{$if}{TAGS}{READ} == 1 and not $dryrun; +- +- my $tag_opts = format_tags($to); # tag options for mp4/m4a/m4b/mpc/mpp/bonk/spx/wv +- +- my $encode_string = $run{$to}{ENCODER}{$encoder}{ESTR}->(); +- $encode_string =~ s/%i/$tag_opts \"$outf.$$.wav\"/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "faac" or $encoder eq "mpcenc"; +- $encode_string =~ s/%i/\"$outf.$$.wav\" $tag_opts/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "ffmpeg" or $encoder eq "avconv"; +- $encode_string =~ s/%i/\"$outf.$$.wav\"/ if $to !~ /mpc|mpp|mp4|m4a/; +- $encode_string =~ s/%o/$tag_opts \"$outf.$to\"/ if $tag_opts ne " " and $to !~ /mpc|mpp|mp4|m4a/; +- $encode_string =~ s/%o/\"$outf.$to\"/ if $tag_opts eq " " or $to =~ /mpc|mpp|mp4|m4a/; +- $encode_string =~ s/(\$|\\)/\\$1/g; +- +- # read tag options from command line if present +- get_user_tags(); +- +- pnotice("debug","\n$run{$to}{ENCODER}{$encoder}{NAME} $encode_string", 2) if $dryrun; +- +- # encode temporary WAV to desired output format. +- system("$run{$to}{ENCODER}{$encoder}{NAME} $encode_string $silent") if not $dryrun; +- +- # remove partially encoded output file and temporary wav if encoding fails +- if ($? > 0) { +- unlink("$outf.$to") if -e "$outf.$to"; +- unlink("$outf.$$.wav") if -e "$outf.$$.wav"; +- say ""; +- $banner = 0; +- pnotice("encode_failed","$outf.$to: $?",1); +- return 1; +- } +- +- # write meta-data to output file from %tag_name hash +- write_tags("$outf.$to", "$to") if $run{$to}{TAGS}{WRITE} == 1 and $tag_opts eq " " and not $dryrun; +- +- unlink("$outf.$$.wav") if not $dryrun; +- unlink("$inf.$infmt") if $delete and not $dryrun; +- +- pnotice("removed_tmp","$outf.$$.wav","2") if $verbose; +- pnotice("removed_src","$inf.$infmt", "2") if $delete and $verbose; +-} +- +-$pm->run_on_finish +-( sub { +- my $pid = shift; +- my $exit_code = shift; +- my $ident = shift; +- +- if (-e "$ident.$to") { +- $total_converted++; +- } +- say "$lang{debug} PID: $pid EXIT_CODE: $exit_code IDENTITY: \"$ident.$to\"" if $debug == 1; +- } +-); +- +-# convert all files that have been placed in the %files hash through various procs* +-sub fork_files { +- +- say "\n$name - $version\n" if not $gui and $banner == 1; +- +- foreach (sort(keys(%files))) +- { +- $pm->start($files{$_}{OUTF}) and next; +- my $msg = "$lang{converting}" . " " . basename($files{$_}{FILE}) . ".$files{$_}{EXT} -> $to"; +- say "$msg" if not $gui; +- system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$msg\" 10 &") if $gui and $kde; +- system("notify-send \"$name\" \"$msg\" -t 35 -i $icon_path &") if $gui and $gnome; +- convert("$files{$_}{FILE}","$files{$_}{OUTF}","$files{$_}{EXT}","$files{$_}{NAME}","$files{$_}{OUTD}","$files{$_}{DECODER}"); +- $pm->finish; +- } +- +- $pm->wait_all_children; +- $total_failed = $number - $total_converted if $total_converted < $number; +- +- my $finished_msg = "\n$lang{total_converted} $total_converted, $lang{failed} $total_failed\n"; +- +- say "$finished_msg" if not $gui; +- system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$finished_msg\" 10 &") if $gui and $kde; +- system("notify-send \"$name\" \"$finished_msg\" -t 35 -i $icon_path &") if $gui and $gnome; +- +-} +- +-# if the default encoder does not exist, cycle through the supported +-# encoders until we find one that does. +-sub check_encoder { +- +- if (not `which $encoder 2>/dev/null`) { +- my $first_encoder = $encoder; +- foreach (keys %{$run{$to}{ENCODER}}) { $encoder = $_ and return if `which $_ 2>/dev/null`; } +- perror("no_encode_app","$to") if $encoder eq $first_encoder; +- } +- +- else { return 0; } +-} +- +-# if the default decoder does not exist, cycle through the supported +-# decoders until we find one that does. +-sub check_decoder { +- +- my $from = shift; +- +- if (not `which $decoder 2>/dev/null`) { +- my $first_decoder = $decoder; +- foreach (keys %{$run{$from}{DECODER}}) { $decoder = $_ and return if `which $_ 2>/dev/null`; } +- perror("no_decode_app","$from") if $decoder eq $first_decoder; +- } +- +- else { return 0; } +-} +- +-# make sure encoding/decoding is supported. +-sub check_input { +- +- my $file = shift; +- my $dir = shift; +- my $ext = shift; +- +- perror("no_encoder","$to") unless(defined($run{$to}{ENCODER})); +- +- unless(defined($run{$ext}{DECODER})) { +- pnotice("no_decoder","$ext",2) if $verbose or not $only; +- $total_failed++; +- return 1; +- } +- +- return 0; +-} +- +-######################################## +-# GUI options for KDE & Gnome Plugins # +-######################################## +- +-my $kdialog = "kdialog --title \"$name\""; +-my $zenity = "zenity --title \"$name\" --list --radiolist --width 100 --height 300 --column '' --column "; +- +-sub get_visual_opts { +- +- my ($to_fmt,$od) = @_; +- +- # escape illegal characters in output directory name +- $od =~ s/('|\(|\)|"|\\)/\\$1/g; +- +- $outdir = `kdialog --getexistingdirectory $od` if $config{KDE_DIR} == 1 and $kde; +- $outdir = `zenity --title \"$lang{gui_outdir}\" --file-selection --directory --filename=\`pwd\`` if $config{ZEN_DIR} == 1 and $gnome; +- +- chomp($outdir); +- $out_dir = $outdir; +- exit(1) if not $outdir; +- +- if ($config{KDE_OPTS} == 1 or $config{ZEN_OPTS} == 1) { +- foreach (keys %{$run{$to_fmt}{ENCODER}{$encoder}{PROMPT}}) { +- prompt_user($_); +- } +- } +-} +- +-sub prompt_user { +- +- my $opt = shift; +- +- given ($opt) { +- +- when (/^BITRATE/) { +- $bitrate = `$kdialog --default $bitrate --combobox \"$lang{gui_bitrate}\" 56 112 128 160 192 256 320` if $kde; +- $bitrate = `$zenity \"$lang{gui_bitrate}\" FALSE 56 FALSE 112 FALSE 128 FALSE 160 TRUE 192 FALSE 256 FALSE 320` if $gnome; +- chomp($bitrate); +- exit(1) if not $bitrate; +- } +- +- when (/^FREQ/) { +- $freq = `$kdialog --default $freq --combobox \"$lang{gui_freq}\" 32000 44100 48000` if $kde; +- $freq = `$zenity \"$lang{gui_freq}\" FALSE 32000 TRUE 44100 FALSE 48000` if $gnome; +- chomp($freq); +- exit(1) if not $freq; +- } +- +- when (/^CHANNELS/) { +- $channels = `$kdialog --default $channels --combobox \"$lang{gui_chans}\" 1 2` if $kde; +- $channels = `$zenity \"$lang{gui_chans}\" FALSE 1 TRUE 2` if $gnome; +- chomp($channels); +- exit(1) if not $channels; +- } +- +- when (/^FCOMP/) { +- $fcomp = `$kdialog --default $fcomp --combobox \"$lang{gui_fcomp}\" 0 1 2 3 4 5 6 7 8` if $kde; +- $fcomp = `$zenity \"$lang{gui_fcomp}\" FALSE 0 FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8` if $gnome; +- chomp($fcomp); +- exit(1) if not $fcomp; +- } +- +- when (/^ACOMP/) { +- $acomp = `$kdialog --default $acomp --combobox \"$lang{gui_acomp}\" 1000 2000 3000 4000 5000` if $kde; +- $acomp = `$zenity \"$lang{gui_acomp}\" FALSE 1000 FALSE 2000 TRUE 3000 FALSE 4000 FALSE 5000` if $gnome; +- chomp($acomp); +- exit(1) if not $acomp; +- } +- +- when (/^OGGQUAL/) { +- $oggqual = `$kdialog --default $oggqual --combobox \"$lang{gui_oggqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; +- $oggqual = `$zenity \"$lang{gui_oggqual}\" FALSE 0 FALSE 1 FALSE 2 TRUE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8 FALSE 9 FALSE 10` if $gnome; +- chomp($oggqual); +- exit(1) if not $oggqual; +- } +- +- when (/^SPXQUAL/) { +- $spxqual = `$kdialog --default $spxqual --combobox \"$lang{gui_spxqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; +- $spxqual = `$zenity \"$lang{gui_spxqual}\" FALSE 0 FALSE 1 FALSE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 TRUE 8 FALSE 9 FALSE 10` if $gnome; +- chomp($spxqual); +- exit(1) if not $spxqual; +- } +- +- when (/^AACQUAL/) { +- $aacqual = `$kdialog --default $aacqual --combobox \"$lang{gui_aacqual}\" 100 200 300 400 500` if $kde; +- $aacqual = `$zenity \"$lang{gui_aacqual}\" TRUE 100 FALSE 200 FALSE 300 FALSE 400 FALSE 500` if $gnome; +- chomp($aacqual); +- exit(1) if not $aacqual; +- } +- +- when (/^MPCQUAL/) { +- $mpcqual = `$kdialog --default $mpcqual --combobox \"$lang{gui_mpcqual}\" thumb radio standard xtreme insane braindead` if $kde; +- $mpcqual = `$zenity \"$lang{gui_mpcqual}\" FALSE thumb TRUE radio FALSE standard FALSE xtreme FALSE insane FALSE braindead` if $gnome; +- chomp($mpcqual); +- exit(1) if not $mpcqual; +- } +- +- when (/^OFMODE/ ) { +- $ofmode = `$kdialog --default $ofmode --combobox \"$lang{gui_ofmode}\" fast normal high extra best highnew extranew bestnew` if $kde; +- $ofmode = `$zenity \"$lang{gui_ofmode}\" FALSE fast TRUE normal FALSE high FALSE extra FALSE best FALSE highnew FALSE extranew FALSE bestnew` if $gnome; +- chomp($ofmode); +- exit(1) if not $ofmode; +- } +- +- when (/^OFOPT/) { +- $ofopt = `$kdialog --default $ofopt --combobox \"$lang{gui_ofopt}\" none fast normal high best` if $kde; +- $ofopt = `$zenity \"$lang{gui_ofopt}\" FALSE none TRUE fast FALSE normal FALSE high FALSE best` if $gnome; +- chomp($ofopt); +- exit(1) if not $ofopt; +- } +- +- when (/^BRATIO/) { +- $bratio = `$kdialog --default $bratio --combobox \"$lang{gui_bratio}\" 1 2 3 4 5` if $kde; +- $bratio = `$zenity \"$lang{gui_bratio}\" FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5` if $gnome; +- chomp($bratio); +- exit(1) if not $bratio; +- } +- +- when (/^BQUANL/) { +- $bquanl = `$kdialog --default $bquanl --combobox \"$lang{gui_bquanl}\" 1.00 1.25 1.50 1.75 2.00` if $kde; +- $bquanl = `$zenity \"$lang{gui_bquanl}\" TRUE 1.00 FALSE 1.25 FALSE 1.50 FALSE 1.75 FALSE 2.00` if $gnome; +- chomp($bquanl); +- exit(1) if not $bquanl; +- } +- +- when (/^BPSIZE/) { +- $bpsize = `$kdialog --default $bpsize --combobox \"$lang{gui_bpsize}\" 10 128` if $kde; +- $bpsize = `$zenity \"$lang{gui_bpsize}\" FALSE 10 TRUE 128` if $gnome; +- chomp($bpsize); +- exit(1) if not $bpsize; +- } +- +- default { return 0; } +- } +- +-} +- +-# all copied tags will be stored here for furture use +-my %tag_name = +-( +- title => undef, +- track => undef, +- artist => undef, +- album => undef, +- comment => undef, +- year => undef, +- genre => undef, +-); +- +-# override tags read from input file if any of the tagging +-# options are specified by the user during conversion. +-sub get_user_tags +-{ +- $tag_name{title} = $title if $title; +- $tag_name{track} = $track if $track; +- $tag_name{artist} = $artist if $artist; +- $tag_name{album} = $album if $album; +- $tag_name{comment} = $comment if $comment; +- $tag_name{year} = $year if $year; +- $tag_name{genre} = $genre if $genre; +-} +- +-# the formats MP4/M4A/M4B/MPC/MPP/WV/BONK have no tag writing module. +-# tags therefore have to be written during encode via various +-# command line args. +-sub format_tags { +- +- my $type = shift; +- +- given ($type) { +- +- when (/^mp4$|^m4a$|^m4b$/) { +- +- if ($run{$to}{ENCODER}{$encoder}{NAME} eq "ffmpeg" or $run{$to}{ENCODER}{$encoder}{NAME} eq "avconv") { +- +- $tag_name{track} = 0 if not $tag_name{track}; +- $tag_name{year} = 0 if not $tag_name{year}; +- +- return "-metadata TITLE=\"$tag_name{title}\" -metadata TRACK=\"$tag_name{track}\" -metadata ARTIST=\"$tag_name{artist}\" -metadata ALBUM=\"$tag_name{album}\" -metadata COMMENT=\"$tag_name{comment}\" -metadata YEAR=\"$tag_name{year}\" -metadata GENRE=\"$tag_name{genre}\""; +- +- } else { +- +- return "--title \"$tag_name{title}\" --track \"$tag_name{track}\" --artist \"$tag_name{artist}\" --album \"$tag_name{album}\" --comment \"$tag_name{comment}\" --year \"$tag_name{year}\" --genre \"$tag_name{genre}\""; +- +- } +- } +- +- when (/^mpc$|^mpp$/) { return "--artist \"$tag_name{artist}\" --title \"$tag_name{title}\" --album \"$tag_name{album}\" --track \"$tag_name{track}\" --genre \"$tag_name{genre}\" --year \"$tag_name{year}\" --comment \"$tag_name{comment}\""; } +- when (/^wv$/) { return "-w \"Title=$tag_name{title}\" -w \"Track=$tag_name{track}\" -w \"Artist=$tag_name{artist}\" -w \"Album=$tag_name{album}\" -w \"Comment=$tag_name{comment}\" -w \"Year=$tag_name{year}\" -w \"Genre=$tag_name{genre}\""; } +- when (/^bonk$/) { return "-t \"$tag_name{title}\" -a \"$tag_name{artist}\" -c \"$tag_name{comment}\""; } +- when (/^spx$/) { return "--author \"$tag_name{artist}\" --title \"$tag_name{title}\" --comment \"year=$tag_name{year}\" --comment \"tracknumber=$tag_name{track}\" --comment \"album=$tag_name{album}\" --comment \"genre=$tag_name{genre}\" --comment \"comment=$tag_name{comment}\""; } +- +- default { return " "; } +- } +-} +- +-# meta-data is read based on input file extension. +-# all tags which are present will be copied to +-# the %tag_name hash. +-sub read_tags { +- +- my $in_file = shift; +- my $in_format = shift; +- +- my $tag_module = $run{$in_format}{TAGS}{MODULE}; +- +- given ($in_format) { +- +- when (/^mp3$|^mp3hd$/) { +- my $mp3tag = $tag_module->new($in_file); +- my @tags = $mp3tag->autoinfo(); +- +- $tag_name{title} = "$tags0" if $tags0; +- $tag_name{track} = "$tags1" if $tags1; +- $tag_name{artist} = "$tags2" if $tags2; +- $tag_name{album} = "$tags3" if $tags3; +- $tag_name{comment} = "$tags4" if $tags4; +- $tag_name{year} = "$tags5" if $tags5; +- $tag_name{genre} = "$tags6" if $tags6; +- +- return 0; +- } +- +- when (/^ogg$|^oga$/) { +- my $ogg_tag = Audio::Scan->scan_tags($in_file)->{tags}; +- +- $tag_name{title} = $ogg_tag->{TITLE} if $ogg_tag->{TITLE}; +- $tag_name{track} = $ogg_tag->{TRACKNUMBER} if $ogg_tag->{TRACKNUMBER}; +- $tag_name{artist} = $ogg_tag->{ARTIST} if $ogg_tag->{ARTIST}; +- $tag_name{album} = $ogg_tag->{ALBUM} if $ogg_tag->{ALBUM}; +- $tag_name{comment} = $ogg_tag->{COMMENT} if $ogg_tag->{COMMENT}; +- $tag_name{year} = $ogg_tag->{YEAR} if $ogg_tag->{YEAR}; +- $tag_name{genre} = $ogg_tag->{GENRE} if $ogg_tag->{GENRE}; +- +- return 0; +- } +- +- when (/^spx$/) { +- my $pid = open(SPX, "speexdec \"$in_file\" tmp1-$$.wav 2>&1 |") or perror("opening_file","$in_file"); +- my @data = <SPX>; +- @data = grep(!/^$|^#/, @data); +- +- close(SPX); +- +- foreach (@data) { +- +- next unless /=/; +- chomp; +- +- my ($k, $v) = split /=/; +- $k =~ tr/A-Z/a-z/; +- $tag_name{$k} = $v if exists($tag_name{$k}); +- $tag_name{artist} = $v if $k =~ /^author/i; +- $tag_name{track} = $v if $k =~ /^tracknumber/i; +- } +- +- unlink("tmp-$$.wav"); +- return 0; +- } +- +- when (/^flac$|^fla$/) { +- my $flac_tag = Audio::Scan->scan_tags($in_file)->{tags}; +- +- $tag_name{title} = $flac_tag->{TITLE} if $flac_tag->{TITLE}; +- $tag_name{track} = $flac_tag->{TRACKNUMBER} if $flac_tag->{TRACKNUMBER}; +- $tag_name{artist} = $flac_tag->{ARTIST} if $flac_tag->{ARTIST}; +- $tag_name{album} = $flac_tag->{ALBUM} if $flac_tag->{ALBUM}; +- $tag_name{comment} = $flac_tag->{COMMENT} if $flac_tag->{COMMENT}; +- $tag_name{year} = $flac_tag->{DATE} if $flac_tag->{DATE}; +- $tag_name{genre} = $flac_tag->{GENRE} if $flac_tag->{GENRE}; +- +- return 0; +- } +- +- when (/^mp4$|^m4a$|^m4b$/) { +- my $mp4_tag = $tag_module->scan_tags($in_file)->{tags}; +- +- $tag_name{title} = $mp4_tag->{NAM} if $mp4_tag->{NAM}; +- $tag_name{track} = $mp4_tag->{TRKN} if $mp4_tag->{TRKN}; +- $tag_name{artist} = $mp4_tag->{ART} if $mp4_tag->{ART}; +- $tag_name{album} = $mp4_tag->{ALB} if $mp4_tag->{ALB}; +- $tag_name{comment} = $mp4_tag->{CMT} if $mp4_tag->{CMT}; +- $tag_name{year} = $mp4_tag->{DAY} if $mp4_tag->{DAY}; +- $tag_name{genre} = $mp4_tag->{GNRE} if $mp4_tag->{GNRE}; +- +- return 0; +- } +- +-when (/^ape$|^mpc$|^mpp$|^wv$/) { +- my $audio_tag = $tag_module->scan_tags($in_file)->{tags}; +- +- $tag_name{title} = $audio_tag->{TITLE} if $audio_tag->{TITLE}; +- $tag_name{track} = $audio_tag->{TRACK} if $audio_tag->{TRACK}; +- $tag_name{artist} = $audio_tag->{ARTIST} if $audio_tag->{ARTIST}; +- $tag_name{album} = $audio_tag->{ALBUM} if $audio_tag->{ALBUM}; +- $tag_name{comment} = $audio_tag->{COMMENT} if $audio_tag->{COMMENT}; +- $tag_name{year} = $audio_tag->{YEAR} if $audio_tag->{YEAR}; +- $tag_name{genre} = $audio_tag->{GENRE} if $audio_tag->{GENRE}; +- +- return 0; +- } +- +- when (/^wma$/) { +- my $wma_tag = $tag_module->scan_tags($in_file)->{tags}; +- +- $tag_name{title} = $wma_tag->{TITLE} if $wma_tag->{TITLE}; +- $tag_name{track} = $wma_tag->{TRACKNUMBER} if $wma_tag->{TRACKNUMBER}; +- $tag_name{artist} = $wma_tag->{AUTHOR} if $wma_tag->{AUTHOR}; +- $tag_name{album} = $wma_tag->{ALBUMTITLE} if $wma_tag->{ALBUMTITLE}; +- $tag_name{comment} = $wma_tag->{DESCRIPTION} if $wma_tag->{DESCRIPTION}; +- $tag_name{year} = $wma_tag->{YEAR} if $wma_tag->{YEAR}; +- $tag_name{genre} = $wma_tag->{GENRE} if $wma_tag->{GENRE}; +- +- return 0; +- } +- +- default { return 1; } +- } +-} +- +-# write meta-data stored in %tag_name to output file. +-sub write_tags { +- +- my $out_file = shift; +- my $out_format = shift; +- +- my $tag_m; +- +- given ($out_format) { +- +- when (/^mp3$|^mp3hd$/) { +- $tag_m = MP3::Tag->config(write_v24 => 'YES'); +- $tag_m = MP3::Tag->new("$out_file"); +- +- # ID3v2 Tags +- unless(exists($tag_m->{ID3v2})) { $tag_m->new_tag("ID3v2"); } +- +- $tag_m->{ID3v2}->add_frame("TIT2", "$tag_name{title}") if defined($tag_name{title}); +- $tag_m->{ID3v2}->add_frame("TRCK", "$tag_name{track}") if defined($tag_name{track}); +- $tag_m->{ID3v2}->add_frame("TPE1", "$tag_name{artist}") if defined($tag_name{artist}); +- $tag_m->{ID3v2}->add_frame("TALB", "$tag_name{album}") if defined($tag_name{album}); +- $tag_m->{ID3v2}->comment("$tag_name{comment}") if defined($tag_name{comment}); +- $tag_m->{ID3v2}->add_frame("TYER", "$tag_name{year}") if defined($tag_name{year}); +- $tag_m->{ID3v2}->add_frame("TCON", "$tag_name{genre}") if defined($tag_name{genre}); +- +- $tag_m->{ID3v2}->write_tag; +- +- # ID3v1 Tags +- unless(exists($tag_m->{ID3v1})) { $tag_m->new_tag("ID3v1"); } +- +- $tag_m->{ID3v1}->title("$tag_name{title}") if defined($tag_name{title}); +- $tag_m->{ID3v1}->track("$tag_name{track}") if defined($tag_name{track}); +- $tag_m->{ID3v1}->artist("$tag_name{artist}") if defined($tag_name{artist}); +- $tag_m->{ID3v1}->album("$tag_name{album}") if defined($tag_name{album}); +- $tag_m->{ID3v1}->comment("$tag_name{comment}") if defined($tag_name{comment}); +- $tag_m->{ID3v1}->year("$tag_name{year}") if defined($tag_name{year}); +- $tag_m->{ID3v1}->genre("$tag_name{genre}") if defined($tag_name{genre}); +- +- $tag_m->{ID3v1}->write_tag; +- +- return 0; +- +- } +- +- when (/^ogg$|^oga$/) { +- $tag_m = ''; +- +- $tag_m = "$tag_m -t \"TITLE=$tag_name{title}\"" if $tag_name{title}; +- $tag_m = "$tag_m -t \"TRACKNUMBER=$tag_name{track}\"" if $tag_name{track}; +- $tag_m = "$tag_m -t \"ARTIST=$tag_name{artist}\"" if $tag_name{artist}; +- $tag_m = "$tag_m -t \"ALBUM=$tag_name{album}\"" if $tag_name{album}; +- $tag_m = "$tag_m -t \"COMMENT=$tag_name{comment}\"" if $tag_name{comment}; +- $tag_m = "$tag_m -t \"YEAR=$tag_name{year}\"" if $tag_name{year}; +- $tag_m = "$tag_m -t \"GENRE=$tag_name{genre}\"" if $tag_name{genre}; +- +- system("vorbiscomment -w $tag_m \"$out_file\"") if $tag_m ne ''; +- +- return 0; +- } +- +- when (/^fla$|^flac$/) { +- $tag_m = Audio::FLAC::Header->new("$out_file"); +- my $tag_i = $tag_m->tags(); +- +- $tag_i->{TITLE} = "$tag_name{title}" if $tag_name{title}; +- $tag_i->{TRACKNUMBER} = "$tag_name{track}" if $tag_name{track}; +- $tag_i->{ARTIST} = "$tag_name{artist}" if $tag_name{artist}; +- $tag_i->{ALBUM} = "$tag_name{album}" if $tag_name{album}; +- $tag_i->{COMMENT} = "$tag_name{comment}" if $tag_name{comment}; +- $tag_i->{DATE} = "$tag_name{year}" if $tag_name{year}; +- $tag_i->{GENRE} = "$tag_name{genre}" if $tag_name{genre}; +- +- $tag_m->write(); +- +- return 0; +- } +- +- default { perror("no_write_tag","$out_file"); } +- } +- +-} +- +-# this is necessary when converting multiple files. +-# it prevents old tags from the previous file being +-# copied over to the next file in line. +-sub clear_tag_hash { +- foreach (keys(%tag_name)) { +- $tag_name{$_} = ''; +- } +-} +- +-# display meta-data for selected file(s) +-sub show_taginfo { +- +- perror("no_input","") if $#file < 0; +- +- foreach my $i (@file) { +- +- my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); +- +- $ext =~ s/^\.//; +- +- my $from = $ext; +- $from =~ tr/A-Z/a-z/; +- +- if ($run{$from}{TAGS}{READ} == 1) { +- +- clear_tag_hash(); +- read_tags("$dir/$file.$ext","$from"); +- +- say ''; +- +- pnotice("tag_info","$file.$ext",2); +- +- say " Artist: $tag_name{artist}"; +- say " Title: $tag_name{title}"; +- say " Album: $tag_name{album}"; +- say " Track: $tag_name{track}"; +- say "Comment: $tag_name{comment}"; +- say " Year: $tag_name{year}"; +- say " Genre: $tag_name{genre}"; +- +- say ''; +- +- } else { pnotice("no_read_tag","$file.$ext",2); } +- } +-} +- +-# write tags to file supplied by the user +-sub write_user_tags { +- +- perror("no_input","") if $#file < 0; +- +- say ''; +- say "$name - $version\n"; +- +- foreach (@file) { +- +- my ($file, $dir, $ext) = fileparse("$_", qr/\.^.*/); +- +- $ext =~ s/^\.//; +- my $from = $ext; +- $from =~ tr/A-Z/a-z/; +- +- if ($run{$from}{TAGS}{WRITE} == 1) { +- +- clear_tag_hash(); +- read_tags("$dir/$file.$ext","$from"); +- +- $tag_name{title} = $title if $title; +- $tag_name{track} = $track if $track; +- $tag_name{artist} = $artist if $artist; +- $tag_name{album} = $album if $album; +- $tag_name{comment} = $comment if $comment; +- $tag_name{year} = $year if $year; +- $tag_name{genre} = $genre if $genre; +- +- write_tags("$dir/$file.$ext","$from"); +- say "$lang{write_tag_i} $file.$ext"; +- +- } else { perror("no_write_tag","$file.$ext"); } +- } +- say ''; +-} +- +-# print out list of supported encode & decode formats +-sub show_formats { +- +-say "\n$name - $version\n"; +-say "EXT E D ENCODER DECODER TAG-READ TAG-WRITE"; +-say "----------------------------------------------------------------------"; +- +-my $enc_count = 0; +-my $dec_count = 0; +- +- foreach (sort(keys(%run))) { +- +- my $e = "N"; $e = "Y" if defined($run{$_}{DEFAULT_ENCODER}); +- my $d = "N"; $d = "Y" if defined($run{$_}{DEFAULT_DECODER}); +- my $r = "N"; $r = "Y" if $run{$_}{TAGS}{READ} == 1; +- my $w = "N"; $w = "Y" if $run{$_}{TAGS}{WRITE} == 1; +- +- my $enc = ''; $enc = $run{$_}{DEFAULT_ENCODER} if defined($run{$_}{DEFAULT_ENCODER}); +- my $dec = ''; $dec = $run{$_}{DEFAULT_DECODER} if defined($run{$_}{DEFAULT_DECODER}); +- +- printf("%-9s %-3s %-3s %-15s %-18s %-10s %s\n", $_, $e, $d, $enc, $dec, $r, $w); +- +- ++$enc_count if $enc ne ''; +- ++$dec_count if $dec ne ''; +- +- } +- +- say "\n$lang{enc_fmts} $enc_count --- $lang{dec_fmts} $dec_count\n"; +- +-} +- +-# show encoders for output format +-sub show_encoders { +- say "\n$name - $version\n\n$lang{show_encoders}: $my_encoder\n"; +- foreach (sort(keys %{$run{$my_encoder}{ENCODER}})) { +- print "$_ -> "; +- print "installed" if `which $_ 2>/dev/null`; +- print "not found" if not `which $_ 2>/dev/null`; +- print " (default)" if $_ eq $run{$my_encoder}{DEFAULT_ENCODER}; +- say ''; +- } +- say ''; +-} +- +-# show decoders for input format +-sub show_decoders { +- say "\n$name - $version\n\n$lang{show_decoders}: $my_decoder\n"; +- foreach (sort(keys %{$run{$my_decoder}{DECODER}})) { +- print "$_ -> "; +- print "installed" if `which $_ 2>/dev/null`; +- print " (default)" if $_ eq $run{$my_decoder}{DEFAULT_DECODER}; +- say ''; +- } +- say ''; +-} +- +-################# +-# cd ripping... # +-################# +- +-# get total number of tracks from cdparanoia query +-sub get_total_tracks { +- +- open(CDINFO, "cdparanoia -Q 2>&1 |") or die "can't fork: $!\n"; +- my @cdquery = <CDINFO>; +- close(CDINFO); +- +- my $fmt_tracks = $cdquery-3; +- $fmt_tracks =~ s/\s//g; +- +- my @ttracks = split(/\./, $fmt_tracks); +- +- return "$ttracks0"; +- +-} +- +-my (%cd, %ripconfig, @cdtrack, $track_total); +- +-# setup the cddb config +-sub get_cddb_config { +- +- $config{USE_CDDB} = 0 && return if $nocddb; +- +- $config{CDDB_INPUT} = 0 if $noinput; +- +- $ripconfig{CDDB_HOST} = $config{CDDB_HOST}; +- $ripconfig{CDDB_PORT} = $config{CDDB_PORT}; +- $ripconfig{CDDB_MODE} = $config{CDDB_MODE}; +- $ripconfig{DEVICE} = $device; +- $ripconfig{CDDB_INPUT} = $config{CDDB_INPUT}; +- +- print $ripconfig{CDDB_HOST}; +- +- %cd = get_cddb(\%ripconfig); +- +- if (not $cd{title}) { +- pnotice("no_cddb","",2); +- $config{USE_CDDB} = 0; +- } +- else { +- @cdtrack = @{$cd{track}}; +- $track_total = $cd{tno}; +- } +- +-} +- +-# check to see if a disc is present +-sub query_disc { +- system("cdparanoia -q -d $device -Q > /dev/null 2>&1"); +- perror("no_disc","$device") if $? > 0; +-} +- +-# set tag info from cddb +-sub tag_track { +- +- my $tno = shift; +- +- $tag_name{artist} = $cd{artist} if $cd{artist}; +- $tag_name{title} = $cdtrack$tno-1 if $cdtrack$tno-1; +- $tag_name{genre} = $cd{cat} if $cd{cat}; +- $tag_name{track} = $tno; +- $tag_name{album} = $cd{title} if $cd{title}; +- $tag_name{year} = $cd{year} if $cd{year}; +- $tag_name{comment} = ''; +- +-} +- +-# process and convert ripped track +-sub rip_cd { +- +- my ($on,$tno) = @_; +- +- $outdir = $ENV{HOME}; +- $to =~ tr/A-Z/a-z/; +- +- get_visual_opts($to,$out_dir) if $gui and not defined($first_run); +- $first_run = 1; +- pnotice("ripping_track","$tno",2); +- +- $on =~ s/\//_/g; +- +- say "\ncdparanoia -d $device $tno $on.wav\n" if $dryrun; +- system("cdparanoia -d $device $tno \"$on.wav\" >/dev/null 2>&1") if not $dryrun; +- +- if ($to !~ /wav/i) { +- +- push(@file, "$on.wav"); +- tag_track($tno); +- proc_input(); +- clear_tag_hash(); +- undef(@file); +- unlink("$on.wav") if not $dryrun; +- pnotice("removed_tmp","$on.wav",2) if $verbose; +- +- } +-} +- +-# rip selected tracks or all from disc +-sub proc_cd { +- +- perror("no_app","cdparanoia") if not `which cdparanoia 2>/dev/null`; +- +- query_disc(); +- get_cddb_config(); +- +- my $total_tracks = get_total_tracks(); +- +- if ($rip eq "all") { +- +- if ($config{USE_CDDB} ne 1) { +- +- for(my $i=1;$i<=$total_tracks;$i++) { +- rip_cd($i, $i); +- } +- +- } elsif ($config{USE_CDDB} eq 1) { +- +- my $n = 1; +- +- foreach my $i (@cdtrack) { +- +- my $out_string = $nscheme; +- +- chomp($cdtrack$n-1); +- +- $out_string =~ s/%ar/$cd{artist}/; +- $out_string =~ s/%ti/$cdtrack$n-1/; +- $out_string =~ s/%tr/$n/; +- $out_string =~ s/%ab/$cd{title}/; +- $out_string =~ s/%yr/$cd{year}/; +- +- rip_cd($out_string, $n); +- +- ++$n; +- } +- } +- +- } else { +- +- my @tracks = split(/,/, $rip); +- +- foreach my $i (@tracks) { +- +- next if $i > $total_tracks or $i < 1; +- +- my $out_string = $nscheme; +- +- $out_string =~ s/%ar/$cd{artist}/; +- $out_string =~ s/%ti/$cdtrack$i-1/; +- $out_string =~ s/%tr/$i/; +- $out_string =~ s/%ab/$cd{title}/; +- $out_string =~ s/%yr/$cd{year}/; +- +- rip_cd($out_string, $i) if $config{USE_CDDB} == 1; +- rip_cd($i, $i) if $config{USE_CDDB} == 0; +- } +- } +-} +- +-# get/print cddb information from disc +-sub cdinfo { +- +- query_disc(); +- get_cddb_config(); +- +- say "$name - $version\n"; +- +- say "Artist = $cd{artist}"; +- say "Album = $cd{title}"; +- say "Genre = $cd{genre}"; +- say "Tracks = $cd{tno}"; +- say "Year = $cd{year}\n"; +- +- my $n = 1; +- +- foreach (@cdtrack) { +- say "Track $n: $_"; +- ++$n; +- } +- +- exit(0); +-} +- +-# version / license information +-sub version { +- +-say " +-$name - $version +- +-Copyright (C) 2005-2017 Philip Lyons +- +-This is free software. You may redistribute copies of it under the terms of +-the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. +-There is NO WARRANTY, to the extent permitted by law. +-"; +- +-} +- +-# help & longhelp menu +-sub help_menu { +- +-say "\n$name - $version"; +- +-say " +--t, --to $lang{to} +--r, --recursive $lang{recursive} +--p, --preserve $lang{preserve} +--f, --formats $lang{formats} +--o, --only $lang{only} +--k, --keep $lang{keep} +--j, --jobs $lang{jobs} +--h, --help $lang{help} +--l, --longhelp $lang{longhelp} +--v, --verbose $lang{verbose} +-"; +- +-say "$lang{user_opts} +- +---defopts $lang{defopts} +---eopts $lang{eopts} +---dopts $lang{dopts} +---nopts $lang{nopts} +---outfile $lang{outfile} +---outdir $lang{outdir} +---dryrun $lang{dryrun} +---overwrite $lang{overwrited} +---normalize $lang{normalize} +---delete $lang{delete} +---encoder $lang{encoder} +---decoder $lang{decoder} +---version $lang{version} +- +-$lang{enc_opts} +- +---bitrate $lang{bitrate} +---freq $lang{freq} +---channels $lang{channels} +---effect $lang{effect} +---fcomp $lang{fcomp} +---acomp $lang{acomp} +---oggqual $lang{oggqual} +---spxqual $lang{spxqual} +---aacqual $lang{aacqual} +---mpcqual $lang{mpcqual} +---ofmode $lang{ofmode} +---ofopt $lang{ofopt} +---bratio $lang{bratio} +---bquanl $lang{bquanl} +---bpsize $lang{bpsize} +- +-$lang{tag_opts} +- +---artist $lang{artist} +---title $lang{title} +---track $lang{track} +---year $lang{year} +---album $lang{album} +---genre $lang{genre} +---comment $lang{comment} +---taginfo $lang{taginfo} +- +-$lang{tag_usage} +- +-$lang{rip_opts} +- +---rip $lang{rip} +---nocddb $lang{nocddb} +---noinput $lang{noinput} +---nscheme $lang{nscheme} +---cdinfo $lang{cdinfo} +---device $lang{device} +- +-$lang{rip_usage}" if $longhelp; +- +-say "\n$lang{usage}\n"; +- +-} +- +-sub load_module { +- my ($file) = @_; +- my $return; +- unless($return = do $file) { +- perror("opening_file","$file: $@ $!") if $@ or !defined($return) or not !$return; +- } +-} +- +-sub import_module { +- my ($format_ref) = @_; +- my $format_name=$format_ref->{NAME}; +- $run{$format_name} = $format_ref; +-} +- +-# load all user modules +-sub load_user_modules { +- my @imported_mods; +- opendir(DIR, "$mod_dir") or perror("opening_dir","$mod_dir: $!"); +- foreach (readdir(DIR)) { +- load_module("$mod_dir/$_") if $_ !~ /^\./; +- push(@imported_mods, $_) if $_ !~ /^\./; +- } +- closedir(DIR); +- say "$lang{imported} @imported_mods"; +-} +- +-# place files/directories in their respective arrays +-if (@ARGV) { +- foreach (@ARGV) { +- if (-f $_) { push(@file,$_); print "$lang{debug} adding $_ to \@file\n" if $debug == 1; } +- elsif (-d $_) { push(@dir, $_); print "$lang{debug} adding $_ to \@dir\n" if $debug == 1; } +- else { perror("no_infile","$_"); } +- } +-} +- +-load_user_modules() if $config{IMPORTM} == 1; +- +-if ($to and @ARGV and not $rip) { proc_input(); } +- +-elsif ($to and $rip) { proc_cd(); } +-elsif ($my_encoder and not $to) { show_encoders(); } +-elsif ($my_decoder and not $to) { show_decoders(); } +-elsif ($verinfo) { version(); } +-elsif ($longhelp) { help_menu(); } +-elsif ($formats) { show_formats(); } +-elsif ($cdinfo) { cdinfo(); } +-elsif ($taginfo and not $to) { show_taginfo(); } +-elsif ($title or $track or $artist or $album or $comment or $year or $genre) { write_user_tags(); } +- +-else { help_menu(); } +- +-__END__ +- +-=head1 NAME +- +-pacpl - Perl Audio Converter, a multi purpose converter/ripper/tagger +- +-=head1 SYNOPSIS +- +-pacpl --to <format> <options> file(s)/directory(s) +- +-=head1 DESCRIPTION +- +-Perl Audio Converter +- +-A Linux CLI tool for converting multiple audio types from one format to another. +- +-It supports the following audio formats: +- +-======================================== +- +-3G2, 3GP, 8SVX, AAC, AC3, ADTS, AIFF, AL, AMB, AMR, APE, AU, +-AVR, BONK, CAF, CDR, CVU, DAT, DTS, DVMS, F32, F64, FAP, FLA, +-FLAC, FSSD, GSRT, HCOM, IMA, IRCAM, LA, MAT, MAUD, MAT4, MAT5, +-M4A, MP2, MP3, MP4, MPC, MPP, NIST, OFF, OFR, OFS, OPUS, OGA, +-OGG, PAF, PRC, PVF, RA, RAM, RAW, RF64, SD2, SF, SHN, SMP, SND, +-SOU, SPX, SRN, TAK, TTA, TXW, VOC, VMS, VQF, W64, WAV, WMA, +-and WV. +- +-It can also extract audio from the following video extensions: +- +-============================================================== +- +-RM, RV, ASF, DivX, MPG, MKV, MPEG, AVI, MOV, OGM, OGV, QT, VCD, +-SVCD, M4V, NSV, NUV, PSP, SMK, VOB, FLV, WEBM and WMV. +- +-Parallel Processing, a CD ripping function with CDDB support, batch conversion, +-tag preservation for most supported formats, independent tag reading & writing, +-service menus for KDE Dolphin/Konqueror, GNOME Nautilus script, and action +-scripts for Nemo/Thunar are also provided. +- +-=head1 OPTIONS +- +-B<-t, --to> I<format> +- +-set encode format for the input file(s) or directory(ies). you can see a +-complete list of supported encode formats by using the B<--formats> option. +- +-B<-r, --recursive> +- +-recursively scan and convert input folder(s) to destination format. +- +-B<-p, --preserve> +- +-when recursively converting a directory, preserve the input folders directory +-structure in the specified output directory. such as: +- +-pacpl --to ogg -r -p /home/mp3s --outdir /home/oggs +- +-in the example above, let's assume the directory structure was: +- +-=over 21 +- +-=item /home/mp3s/Alternative +- +-=item /home/mp3s/Alternative/New +- +-=item /home/mp3s/Rap +- +-=item /home/mp3s/Country +- +-=item /home/mp3s/Techno/ +- +-=back +- +-the output directory will now contain: +- +-=over 4 +- +-=item /home/oggs/Alternative +- +-=item /home/oggs/Alternative/New +- +-=item /home/oggs/Rap +- +-=item /home/oggs/Country +- +-=item /home/oggs/Techno +- +-=back +- +-with all files in each sub-folder converted to ogg. +- +-B<-o, --only> I<format> +- +-only convert files matching extension. this option is useful when you have +-a directory or batch of files with mixed audio types and only need to +-convert one specific type. +- +-B<-k, --keep> +- +-do not re-encode files with extensions matching the destination extension. +-instead...copy them to the output folder, or skip to the next file. +- +-B<-j, --jobs> +- +-number of simultanious jobs to run at once. the default limit +-is set to 4 in pacpl.conf. You can modify this value on the fly +-using --jobs=<num> or set it perminately in the configuration file +- +-=over 4 +- +-=item B<-f, --formats> show a list of supported encode/decode formats. +- +-=item B<-h, --help> show the short help menu. +- +-=item B<-l, --longhelp> display the complete list of options. +- +-=item B<--version> show version and licensing information. +- +-=back +- +-=head1 USER OPTIONS +- +-B<--defopts> I<1/0> +- +-to turn off default encoder options use --defopts 0. this option gives you +-more control when using the --eopts command. +- +-defopts is set to 1 by default. you can also toggle this option in +-/etc/pacpl/pacpl.conf. +- +-B<--eopts> I<options> +- +-this option allows you to use encoder options not implemented by pacpl. +-an example would be: +- +-pacpl --to mp4 --eopts="-c 44100 -I 1,2" YourFile.mp3 +- +-B<--dopts> I<options> +- +-this option allows you to use decoder options not implemented by pacpl. +-an example would be: +- +-pacpl --to mpc --dopts="--start 60" YourFile.ogg +- +-B<--outfile> I<name> +- +-set the output file name to I<name>. +- +-B<--outdir> I<directory> +- +-place all encoded files in I<directory>. +- +-B<--dryrun> +- +-show what would be done without actually converting anything. this is a +-good way to trouble shoot, or to see what would be done without actually +-touching your files. +- +-B<--overwrite> +- +-replace the output file if it already exists. +- +-B<--normalize> +- +-adjusts volume levels of audio files. +- +-B<--nopts> I<options> +- +-this allows you to specify normalize options not implemented by pacpl +- +-B<--delete> +- +-remove source/input file after the conversion process has finished. +- +-B<--encoder> I<encoder> +- +-specify an alternate encoder for the selected output file(s) +- +-you can see a list of supported encoders by using the following: +- +-pacpl --encoder I<format> +- +-B<--decoder> I<decoder> +- +-specify an alternate decoder for the selected input file(s) +- +-you can see a list of supported decoders by using the following: +- +-pacpl --decoder I<format> +- +-B<-v, --verbose> +- +-show detailed information about the encoding process and what's actually +-being done. +- +-=head1 ENCODER OPTIONS +- +-B<--bitrate> I<num> +- +-set the bitrate to I<num>. default is 128. this option does not apply +-to all formats. +- +-B<--freq> I<num> +- +-set the frequency to I<num>. default is 44100. this option does not apply +-to all formats. +- +-B<--channels> I<num> +- +-set the number of audio channels in the output file to I<num>. this option +-does not apply to all formats. +- +-B<--effect> I<str> +- +-see B<sox>(1). this option only applies to the following: +- +-AIFF, AU, SND, RAW, VOC, SMP, AVR, and CDR +- +-B<--fcomp> I<num> +- +-set flac compression level to I<num>. fastest -0, highest -8, default -2 +- +-=over 4 +- +-=item 1 = fast +- +-=item 2 = simple +- +-=item 3 = medium (default) +- +-=item 4 = high +- +-=item 5 = extra high, +- +-=back +- +-B<--acomp> I<num> +- +-set ape compression level to I<num>. +- +-=over 4 +- +-=item 1000 = fast +- +-=item 2000 = normal +- +-=item 3000 = high (default) +- +-=item 4000 = extra high +- +-=item 5000 = insane +- +-=back +- +-B<--oggqual> I<num> +- +-set ogg quality level to I<num>. -1, very low and 10 very high, default 3 +- +-B<--spxqual> I<num> +- +-set speex quality level to I<num>. 0-10, default 8 (use --bitrate <num> when using ffmpeg/avconv as encoder) +- +-B<--aacqual> I<num> +- +-set aac, mp4, m4a, or m4b quality level to I<num>. default 300 +- +-B<--mpcqual> I<str> +- +-set mpc/mpp quality level to I<str>. +- +-=over 4 +- +-=item thumb low quality/internet, (typ. 58... 86 kbps) +- +-=item radio medium (MP3) quality, (typ. 112...152 kbps - default) +- +-=item standard high quality (dflt), (typ. 142...184 kbps) +- +-=item xtreme extreme high quality, (typ. 168...212 kbps) +- +-=back +- +-B<--ofmode> I<str> +- +-set off/ofr/ofs compression mode to I<str>. normal, extra, and extranew modes +-are recommended for general use. available options are: +- +-=over 4 +- +-=item fast +- +-=item normal (default) +- +-=item high +- +-=item extra +- +-=item best +- +-=item highnew +- +-=item extranew +- +-=item bestnew +- +-=back +- +-B<--ofopt> I<str> +- +-set off/ofr/ofs optimization level to I<str>. +- +-specify the optimization level in the engine. In order to achieve +-optimal compression at all sample types, sample rates, and audio +-content, the core compression engine has the possibility to find the +-optimal values for its parameters, at the cost of slightly increased +-compression time only. The default recommended value is fast. +-do not use normal (or even high or best) for this parameter unless +-encoding time does not matter and you want to obtain the smallest +-possible file for a given compression mode. The difference between +-the optimize levels fast and best (which is up to three times slower +-than fast) is very small, generally under 0.05%, but may be also +-larger in some rare cases. Note that the none optimize level is +-forced by the encoder to fast optimize level for the extra, best, +-highnew, extranew, and bestnew modes. +- +-available options are: +- +-=over 4 +- +-=item none +- +-=item fast (default) +- +-=item normal +- +-=item high +- +-=item best +- +-=back +- +-B<--bratio> I<num> +- +-set bonk down sampling ratio. default 2 +- +-B<--bquanl> I<num> +- +-set bonk quantanization level. default 1.0 +- +-B<--bpsize> I<num> +- +-set bonk predictor size. default 128 +- +-=head1 TAGGING OPTIONS +- +-B<note:> +- +-tagging outside of the encoding process can only be performed on the +-following audio types: +- +-=over 4 +- +-=item MP3 +- +-=item OGG +- +-=item FLA +- +-=item FLAC +- +-=back +- +-B<--artist> I<str> +- +-set artist information to I<str>. +- +-B<--title> I<str> +- +-set title information to I<str>. +- +-B<--track> I<num> +- +-set track information to I<num>. +- +-B<--year> I<num> +- +-set year/date information to I<num>. +- +-B<--album> I<str> +- +-set album information to I<str>. +- +-B<--genre> I<str> +- +-set genre information to I<str>. +- +-B<--comment> I<str> +- +-set comment information to I<str>. +- +-B<--taginfo> I<file> +- +-show tagging information for I<file>. multiple files can be specified +-at once. +- +-=head1 RIPPING OPTIONS +- +-B<--rip> I<num/all> +- +-rip selected tracks separated by comma or all from current disc. +- +-=over 4 +- +-=item pacpl --rip all --to flac +- +-=item pacpl --rip 1,3,9,15 --to flac +- +-=back +- +-B<--nocddb> +- +-disable cddb. use this option if you do not want tagging based on cddb. +- +-B<--noinput> +- +-disable cddb interactivity. this is enabled by default. +- +-B<--nscheme> I<str> +- +-set naming scheme to I<str>. default is %ar - %ti +- +-available options are: +- +-=over 4 +- +-=item %ar = artist +- +-=item %ti = song title +- +-=item %tr = track +- +-=item %yr = year +- +-=item %ab = album +- +-=back +- +-B<eg:> --nscheme="(%tr)-%ti" +- +-B<--device> I<device> +- +-set device to I<device>. default is /dev/dvd +- +-B<--cdinfo> +- +-show cddb information for current disc. +- +-=head1 SEE ALSO +- +-=over 4 +- +-=item B<sox>(1) B<ffmpeg>(1) B<lame>(1) B<oggenc>(1) B<oggdec>(1) +- +-=item B<flac>(1) B<shorten>(1) B<faac>(1) B<faad>(1) B<mpcenc>(1) +- +-=item B<mpcdec>(1) B<mplayer>(1) B<speexenc>(1) B<speexdec>(1) +- +-=item B<sndfile-convert>(1) B<normalize>(1) B<cdparanoia>(1) +- +-=item B<opusenc>(1) B<opusdec>(1) B<wavpack>(1) B<ffmpeg>(1) +- +-=item B<mplayer>(1) B<avconv>(1) +- +-=back +- +-=head1 BUGS +- +-Report all bugs to Philip Lyons (vorzox@gmail.com) +- +-=head1 LICENSING +- +-This program is free software; you can redistribute it and/or modify +-it under the terms of the GNU General Public License as published by +-the Free Software Foundation; either version 3 of the License, or +-(at your option) any later version. +- +-This program is distributed in the hope that it will be useful, +-but WITHOUT ANY WARRANTY; without even the implied warranty of +-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-GNU General Public License for more details. +- +-You should have received a copy of the GNU General Public License +-along with this program. If not, see <http://www.gnu.org/licenses/>. +- +-=head1 AUTHOR +- +-Copyright (C) 2005-2017 Philip Lyons (vorzox@gmail.com) +diff --git a/pacpl.in b/pacpl.in +new file mode 100755 +index 0000000..3690069 +--- /dev/null ++++ b/pacpl.in +@@ -0,0 +1,4034 @@ ++#!/usr/bin/perl ++# ++# Perl Audio Converter ++# ++# Copyright (C) 2005-2017 Philip Lyons (vorzox@gmail.com) ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++use strict; ++use warnings; ++use Getopt::Long; ++use File::Basename; ++use File::Find; ++use File::Spec::Functions qw(rel2abs); ++use Parallel::ForkManager; ++ ++use feature qw(switch say); ++ ++no if $ >= 5.018, warnings => "experimental::smartmatch"; ++ ++# Tagging modules ++use MP3::Tag; ++use Audio::FLAC::Header; ++use Audio::Scan; ++ ++# CDDB module ++use CDDB_get qw(get_cddb); ++ ++# non-encoder/decoder related options ++my ++( ++ $to, ++ $recursive, ++ $preserve, ++ $rip, ++ $help, ++ $longhelp, ++ $verbose, ++ $verinfo, ++ $dryrun, ++ $delete, ++ $keep, ++ $overwrite, ++ $formats, ++ $topdir, ++ $only, ++ $first_run, ++ ++ @file, ++ @dir, ++ ++ %run, ++ %lang, ++); ++ ++my $silent = "> /dev/null 2>&1"; ++ ++# tagging options ++my ++( ++ $title, ++ $track, ++ $artist, ++ $album, ++ $comment, ++ $year, ++ $genre, ++ $taginfo, ++); ++ ++# name, version & icon information ++my $name = "Perl Audio Converter"; ++my $version = "5.1.0"; ++my $icon_path = "/etc/pacpl/pacpl.png"; ++ ++# If these options are toggled, messages/errors will be displayed ++# via kdialog or zenity/notify-send (depending on environment) ++my ($gui, $kde, $gnome); ++ ++# Debugging (for developer use only) ++my $debug = 0; ++ ++# default configuration. ++my %config = ( ++ ++ IMPORTM => 0, ++ JOBS => 4, ++ ++ DEFOPTS => 1, ++ EOPTS => '', ++ DOPTS => '', ++ NOPTS => '', ++ ++ BITRATE => 128, ++ FREQ => 44100, ++ CHANNELS => 2, ++ EFFECT => '', ++ FCOMP => 2, ++ PCOMP => 3, ++ ACOMP => 3000, ++ OGGQUAL => 3, ++ SPXQUAL => 8, ++ AACQUAL => 100, ++ MPCQUAL => 'radio', ++ OFMODE => 'normal', ++ OFOPT => 'fast', ++ BRATIO => 2, ++ BQUANL => 1.0, ++ BPSIZE => 128, ++ ++ USE_CDDB => 1, ++ CDDB_HOST => 'freedb.freedb.org', ++ CDDB_PORT => 8880, ++ CDDB_MODE => 'cddb', ++ CDDB_INPUT => 1, ++ DEVICE => '/dev/dvd', ++ NSCHEME => '%ar - %ti', ++ ++ ZEN_DIR => 1, ++ ZEN_OPTS => 1, ++ KDE_DIR => 1, ++ KDE_OPTS => 1, ++ ++ ); ++ ++# location of configuration file ++my $conf_path = "@sysconfdir@/pacpl"; ++my $po_dir = "@pkgdatadir@/locale"; ++my $mod_dir = "$conf_path/modules"; ++ ++my $conf_file; ++ ++# load the appropriate locale file ++load_lang(); ++ ++# try to load configuration file in this order... ++my @conf_locations = ( ++ "$ENV{HOME}/.pacplrc", # Local ++ "$conf_path/pacpl.conf", # Global ++ "$ENV{PWD}/pacpl.conf", # Current Directory ++ ); ++ ++# try to load conf file from one of the above locations ++foreach my $i (@conf_locations) { ++ if (not $conf_file and -e $i) { ++ $conf_file = $i; ++ say "$lang{debug} $lang{loaded_config} $conf_file" if $debug == 1; ++ } ++} ++ ++say "$lang{no_config}" if not $conf_file; ++ ++# open config file. ++if ($conf_file and -e $conf_file) { ++ ++ open(CONF, "$conf_file") or die "$lang{opening_file} $conf_file - $!\n"; ++ ++ my @conf_opts = <CONF>; ++ @conf_opts = grep(!/^#|^$/, @conf_opts); ++ ++ close(CONF); ++ ++ # now read config file options and change default values accordingly. ++ foreach (@conf_opts) { ++ chomp; ++ my ($k, $v) = split(/\s*=\s*/); ++ $config{$k} = $v if exists($config{$k}) and $v; ++ say "$lang{debug} $k = $v" if $debug == 1 and exists($config{$k}); ++ } ++} ++ ++my $codecs_conf = "$conf_path/codecs.conf"; ++ ++# set default encoders/decoders ++sub load_codecs { ++ ++ open(CODECS, "$codecs_conf") or die "$lang{opening_file} $codecs_conf - $!\n"; ++ ++ my @codecs = <CODECS>; ++ @codecs = grep(!/^$|^#/, @codecs); ++ @codecs = grep(s/^\s*|\s*$//, @codecs); ++ ++ close(CODECS); ++ ++ foreach (@codecs) { ++ ++ chomp; ++ my ($k, $v) = split(/\s*=\s*/); ++ my ($e, $d) = split(/,/, $v); ++ ++ $k =~ tr/A-Z/a-z/; ++ ++ $run{$k}{DEFAULT_ENCODER} = $e if (exists($run{$k}{DEFAULT_ENCODER})); ++ $run{$k}{DEFAULT_DECODER} = $d if (exists($run{$k}{DEFAULT_DECODER})); ++ } ++} ++ ++# load po file and store in %lang hash ++sub load_lang { ++ ++ my $po = "$po_dir/$ENV{LANG}.po"; ++ $po =~ s/\.UTF-8//i if $po =~ /UTF-8/i; ++ $po =~ s/\.utf8//i if $po =~ /utf8/i; ++ $po =~ s/_\w+// if not -e $po; ++ $po = "$po_dir/en_US.po" if not -e $po; ++ ++ open(LANG, "< $po") or die "error: could not open - $po\n$!\n"; ++ ++ my @data = <LANG>; ++ @data = grep(!/^#|^$/, @data); ++ ++ close(LANG); ++ ++ foreach (@data) { ++ chomp; ++ s/=/__EQ__/; ++ my ($k, $v) = split(/\s*__EQ__\s*/, $_); ++ $lang{$k} = $v; ++ } ++ ++} ++ ++my $banner = 1; ++ ++# print error messages ++sub perror { ++ my ($key, $msg) = @_; ++ say "$name - $version\n"; ++ say "$lang{error}: $lang{$key} $msg" . "\n"; ++ system("kdialog --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $kde; ++ system("zenity --title \"$name\" --error \"$lang{error}: $lang{$key} $msg\" &") if $gui and $gnome; ++ die "$lang{seek_help}\n"; ++} ++ ++# print notices/warnings ++sub pnotice { ++ ++ my ($key, $msg, $nm) = @_; ++ ++ say "$name - $version\n" if $banner == 1; ++ print "$lang{$key} $msg"; ++ say '' if $nm == 1; ++ say "\n" if $nm == 2; ++ ++ $banner = 0; ++} ++ ++# defaults for user variables. ++my $outfile; ++my $outdir; ++my $defopts = $config{DEFOPTS}; ++my $eopts = $config{EOPTS}; ++my $dopts = $config{DOPTS}; ++my $nopts = $config{NOPTS}; ++my $normalize = $config{NOPTS}; ++my $bitrate = $config{BITRATE}; ++my $freq = $config{FREQ}; ++my $channels = $config{CHANNELS}; ++my $effect = $config{EFFECT}; ++my $fcomp = $config{FCOMP}; ++my $acomp = $config{ACOMP}; ++my $oggqual = $config{OGGQUAL}; ++my $spxqual = $config{SPXQUAL}; ++my $aacqual = $config{AACQUAL}; ++my $mpcqual = $config{MPCQUAL}; ++my $ofmode = $config{OFMODE}; ++my $ofopt = $config{OFOPT}; ++my $bratio = $config{BRATIO}; ++my $bquanl = $config{BQUANL}; ++my $bpsize = $config{BPSIZE}; ++ ++my $cdinfo; ++my $nocddb; ++my $noinput; ++my $device = $config{DEVICE}; ++my $nscheme = $config{NSCHEME}; ++my $my_encoder; ++my $my_decoder; ++my $encoder; ++my $decoder; ++ ++my $jobs = $config{JOBS}; ++ ++# command line options ++GetOptions ++( ++ 't|to=s' => \$to, ++ 'r|recursive' => \$recursive, ++ 'p|preserve' => \$preserve, ++ 'h|help' => \$help, ++ 'l|longhelp' => \$longhelp, ++ 'v|verbose' => \$verbose, ++ 'f|formats' => \$formats, ++ 'o|only=s' => \$only, ++ 'k|keep' => \$keep, ++ 'j|jobs=n' => \$jobs, ++ ++ 'taginfo' => \$taginfo, ++ ++ 'version' => \$verinfo, ++ 'dryrun' => \$dryrun, ++ 'delete' => \$delete, ++ 'overwrite' => \$overwrite, ++ 'normalize' => \$normalize, ++ 'encoder=s' => \$my_encoder, ++ 'decoder=s' => \$my_decoder, ++ ++ 'title=s' => \$title, ++ 'track=n' => \$track, ++ 'artist=s' => \$artist, ++ 'album=s' => \$album, ++ 'comment=s' => \$comment, ++ 'year=n' => \$year, ++ 'genre=s' => \$genre, ++ ++ 'gui' => \$gui, ++ 'kde' => \$kde, ++ 'gnome' => \$gnome, ++ ++ 'eopts=s' => \$eopts, ++ 'dopts=s' => \$dopts, ++ 'defopts=n' => \$defopts, ++ 'nopts=s' => \$nopts, ++ 'outfile=s' => \$outfile, ++ 'outdir=s' => \$outdir, ++ ++ 'bitrate=n' => \$bitrate, ++ 'freq=n' => \$freq, ++ 'channels=n' => \$channels, ++ 'effect=s' => \$effect, ++ 'fcomp=n' => \$fcomp, ++ 'acomp=n' => \$acomp, ++ 'oggqual=n' => \$oggqual, ++ 'spxqual=n' => \$spxqual, ++ 'aacqual=n' => \$aacqual, ++ 'mpcqual=s' => \$mpcqual, ++ 'ofmode=s' => \$ofmode, ++ 'ofopt=s' => \$ofopt, ++ 'bratio=n' => \$bratio, ++ 'bquanl=n' => \$bquanl, ++ 'bpsize=n' => \$bpsize, ++ ++ 'rip=s' => \$rip, ++ 'nocddb' => \$nocddb, ++ 'noinput' => \$noinput, ++ 'device=s' => \$device, ++ 'nscheme=s' => \$nscheme, ++ 'cdinfo' => \$cdinfo, ++); ++ ++if (defined($preserve) && !defined($outdir)) { ++ die "You must specify --outdir when you use --preserve option. See man page.\n"; ++} ++ ++$silent = '' if $verbose; ++ ++my $opts; ++my $total_converted = 0; ++my $total_failed = 0; ++ ++# Initialize the fork manager with a count set through pacpl.conf or via the command line ++my $pm = Parallel::ForkManager->new($jobs); ++ ++# conversion options. when adding a new format, ++# wild card %i = input file and %o = output file ++%run = ( ++ ++ '3g2' => { ++ ++ DEFAULT_ENCODER => 'ffmpeg', ++ DEFAULT_DECODER => 'ffmpeg', ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = "-ar 8000 -ac 1" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ar 8000 -ac 1" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ }, ++ ++ DECODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "-y -i %o $dopts %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "-y -i %o %dopts %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ ++ }, ++ ++ '3gp' => { ++ ++ DEFAULT_ENCODER => 'ffmpeg', ++ DEFAULT_DECODER => 'ffmpeg', ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = "-ar 8000 -ac 1" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ar 8000 -ac 1" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ }, ++ ++ DECODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "-y -i %o $dopts %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "-y -i %o %dopts %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ ++ }, ++ ++ aac => { ++ ++ DEFAULT_ENCODER => "faac", ++ DEFAULT_DECODER => "faad", ++ ++ ENCODER => { ++ faac => { ++ NAME => "faac", ++ ESTR => sub { ++ $opts = "-q $aacqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i -o %o" ++ }, ++ PROMPT => { AACQUAL => 1 }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 1, ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ faad => { ++ NAME => "faad", ++ DSTR => sub { "$dopts -o %i %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ ac3 => { ++ ++ DEFAULT_ENCODER => "ffmpeg", ++ DEFAULT_DECODER => "ffmpeg", ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => "avconv", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ aften => { ++ NAME => "aften", ++ ESTR => sub { ++ $opts = "-v 1 -q $bitrate -2" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ }, ++ }, ++ ++ }, ++ ++ DECODER => { ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => "avconv", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ adts => { ++ ++ DEFAULT_ENCODER => 'ffmpeg', ++ DEFAULT_DECODER => 'ffmpeg', ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $opts $eopts -strict -2 %o" ++ }, ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libfaac" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $opts $eopts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => "$dopts -y -i %i %o", ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => "$dopts -y -i %i %o", ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ ape => { ++ ++ DEFAULT_ENCODER => "mac", ++ DEFAULT_DECODER => "mac", ++ ++ ENCODER => { ++ mac => { ++ NAME => "mac", ++ ESTR => sub { ++ $opts = "-c$acomp" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "%i %o $opts $eopts" ++ }, ++ ++ PROMPT => { ACOMP => 1 }, ++ }, ++ }, ++ ++ DECODER => { ++ mac => { ++ NAME => "mac", ++ DSTR => sub { "%i %o -d $dopts" }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "-y -i %i %dopts %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "-y -i %i $dopts %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 0, ++ MODULE => "Audio::Scan", ++ }, ++ }, ++ ++ amr => { ++ ++ DEFAULT_ENCODER => "ffmpeg", ++ DEFAULT_DECODER => "ffmpeg", ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ar 8000 -ac 1" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ avconv => { ++ NAME => "avconv", ++ ESTR => sub { ++ $opts = "-ar 8000 -ac 1" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ }, ++ ++ DECODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "-y -i %i $dopts %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "-y -i %i %dopts %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ ++ }, ++ ++ bonk => { ++ ++ DEFAULT_ENCODER => "bonk", ++ DEFAULT_DECODER => "bonk", ++ ++ ENCODER => { ++ bonk => { ++ NAME => "bonk", ++ ESTR => sub { ++ $opts = "-q $bquanl -b $bratio -s $bpsize" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "encode $eopts $opts %i -o %o" ++ }, ++ ++ PROMPT => { ++ BQUANL => 1, ++ BRATIO => 1, ++ BPSIZE => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ bonk => { ++ NAME => "bonk", ++ DSTR => sub { "decode %i -o %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ dts => { ++ ++ DEFAULT_ENCODER => 'ffmpeg', ++ DEFAULT_DECODER => 'ffmpeg', ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = '' if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $opts $eopts -strict -2 -codec:a libfaac %o" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = '' if $defopts == 1 or $defopts == 0; ++ "-y -i %i $opts $eopts -codec:a libfaac %o", ++ }, ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ dcaenc => { ++ NAME => 'dcaenc', ++ ESTR => sub { ++ $opts = "$bitrate" if $defopts == 0; ++ $opts = '' if $defopts == 1; ++ "%i %o $opts" ++ }, ++ ++ PROMPT => { NONE => 0, }, ++ }, ++ }, ++ ++ DECODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => "$dopts -y -i %i %o", ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => "$dopts -y -i %i %o", ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ flac => { ++ ++ DEFAULT_ENCODER => "flac", ++ DEFAULT_DECODER => "flac", ++ ++ ENCODER => { ++ flac => { ++ NAME => "flac", ++ ESTR => sub { ++ $opts = "-$fcomp" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts -f $opts %i -o %o" ++ }, ++ PROMPT => { FCOMP => 1 }, ++ }, ++ ++ flake => { ++ NAME => "flake", ++ ESTR => sub { ++ $opts = "-$fcomp" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i -o %o" ++ }, ++ PROMPT => { FCOMP => 1 }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 1; ++ "-y -i %i $eopts $opts %o" ++ }, ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ flac => { ++ NAME => "flac", ++ DSTR => sub { "$dopts -f -d %i -o %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::FLAC::Header", ++ }, ++ }, ++ ++ fla => { ++ ++ DEFAULT_ENCODER => "flac", ++ DEFAULT_DECODER => "flac", ++ ++ ENCODER => { ++ flac => { ++ NAME => "flac", ++ ESTR => sub { ++ $opts = "-$fcomp" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts -f $opts %i -o %o" ++ }, ++ PROMPT => { FCOMP => 1 }, ++ }, ++ }, ++ ++ DECODER => { ++ flac => { ++ NAME => "flac", ++ DSTR => sub { "$dopts -f -d %i -o %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::FLAC::Header", ++ }, ++ }, ++ ++ la => { ++ ++ DEFAULT_ENCODER => "la", ++ DEFAULT_DECODER => "la", ++ ++ ENCODER => { ++ la => { ++ NAME => "la", ++ ESTR => sub { "-overwrite $eopts %i %o" }, ++ PROMPT => { NONE => 0, }, ++ }, ++ }, ++ ++ DECODER => { ++ la => { ++ NAME => "la", ++ ESTR => sub { "-console $dopts %i > %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ mp2 => { ++ ++ DEFAULT_ENCODER => "ffmpeg", ++ DEFAULT_DECODER => "ffmpeg", ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ toolame => { ++ NAME => 'toolame', ++ ESTR => sub { ++ $opts = "-b $bitrate" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ }, ++ }, ++ ++ twolame => { ++ NAME => 'twolame', ++ ESTR => sub { ++ $opts = "-b $bitrate -s $freq" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ }, ++ }, ++ ++ sox => { ++ NAME => 'sox', ++ ESTR => sub { ++ $opts = "-c $channels -r $bitrate" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "%i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => "$dopts -y -i %i %o", ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => "%dopts -y -i %i %o", ++ }, ++ ++ mplayer => { ++ NAME => 'mplayer', ++ DSTR => "-vc null -vo null -ao pcm:file=%o %i", ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ mp3 => { ++ ++ DEFAULT_ENCODER => "lame", ++ DEFAULT_DECODER => "lame", ++ ++ ENCODER => { ++ lame => { ++ NAME => "lame", ++ ESTR => sub { ++ $opts = "--resample $freq -b $bitrate -h" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ }, ++ }, ++ ++ bladeenc => { ++ NAME => "bladeenc", ++ ESTR => sub { ++ $opts = "-br $bitrate" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ PROMPT => { BITRATE => 1 }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts -y -i %i $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ sox => { ++ NAME => "sox", ++ ESTR => sub { ++ $opts = "-r $freq -c $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "%i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ lame => { ++ NAME => "lame", ++ DSTR => sub { "$dopts --decode %i %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %O" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ ++ sox => { ++ NAME => "sox", ++ DSTR => sub { "%i $dopts %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "MP3::Tag", ++ }, ++ }, ++ ++ mp3hd => { ++ ++ DEFAULT_ENCODER => "mp3hdEncoder", ++ DEFAULT_DECODER => "mp3hdDecoder", ++ ++ ENCODER => { ++ mp3hdEncoder => { ++ NAME => "mp3hdEncoder", ++ ESTR => sub { ++ $opts = "-br $bitrate" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts -if %i -of %o" ++ }, ++ PROMPT => { BITRATE => 1 }, ++ }, ++ }, ++ ++ DECODER => { ++ mp3hdDecoder => { ++ NAME => "mp3hdDecoder", ++ DSTR => sub { "$dopts -if %i -of %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ WRITE => 1, ++ READ => 1, ++ MODULE => "MP3::Tag", ++ }, ++ }, ++ ++ mp4 => { ++ ++ DEFAULT_ENCODER => "faac", ++ DEFAULT_DECODER => "faad", ++ ++ ENCODER => { ++ ++ faac => { ++ NAME => "faac", ++ ESTR => sub { ++ $opts = "-q $aacqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts -w $opts %i -o %o" ++ }, ++ PROMPT => { AACQUAL => 1 }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PRIMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ ++ faad => { ++ NAME => "faad", ++ DSTR => sub { "$dopts -o %o %i" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::Scan", ++ }, ++ }, ++ ++ m4a => { ++ ++ DEFAULT_ENCODER => "faac", ++ DEFAULT_DECODER => "faad", ++ ++ ENCODER => { ++ ++ faac => { ++ NAME => "faac", ++ ESTR => sub { ++ $opts = "-q $aacqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts -w $opts %i -o %o" ++ }, ++ PROMPT => { AACQUAL => 1 }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts -y -i %i $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ ++ faad => { ++ NAME => "faad", ++ DSTR => sub { "$dopts -o %o %i" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ ++ }, ++ ++ ESTR => sub { "$eopts -w -q $aacqual %i -o %o" }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::Scan", ++ }, ++ }, ++ ++ m4b => { ++ ++ DEFAULT_ENCODER => undef, ++ DEFAULT_DECODER => "faad", ++ ++ DECODER => { ++ faad => { ++ NAME => "faad", ++ DSTR => sub { "$dopts -o %o %i" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 1, ++ MODULE => undef, ++ }, ++ }, ++ ++ mpc => { ++ ++ DEFAULT_ENCODER => "mpcenc", ++ DEFAULT_DECODER => "mpcdec", ++ ++ ENCODER => { ++ ++ mpcenc => { ++ NAME => "mpcenc", ++ ESTR => sub { ++ $opts = "--$mpcqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts --overwrite $opts %i %o" ++ }, ++ PROMPT => { MPCQUAL => 1 }, ++ }, ++ }, ++ ++ DECODER => { ++ ++ mpcdec => { ++ NAME => "mpcdec", ++ DSTR => sub { "$dopts %i %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::Scan", ++ }, ++ ++ PROMPT => { ++ MPCQUAL => 1, ++ }, ++ }, ++ ++ mpp => { ++ ++ DEFAULT_ENCODER => "mpcenc", ++ DEFAULT_DECODER => "mpcdec", ++ ++ ENCODER => { ++ ++ mpcenc => { ++ NAME => "mpcenc", ++ ESTR => sub { ++ $opts = "--$mpcqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts --overwrite $opts %i %o" ++ }, ++ PROMPT => { MPCQUAL => 1 }, ++ }, ++ }, ++ ++ DECODER => { ++ ++ mpcdec => { ++ NAME => "mpcdec", ++ DSTR => sub { "$dopts %i %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::Scan", ++ }, ++ }, ++ ++ off => { ++ DEFAULT_ENCODER => 'off', ++ DEFAULT_DECODER => 'off', ++ ++ ENCODER => { ++ off => { ++ NAME => 'off', ++ ESTR => sub { ++ $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts --overwrite $opts %i --output %o" ++ }, ++ ++ PROMPT => { ++ OFMODE => 1, ++ OFOPT => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ off => { ++ NAME => 'off', ++ DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ ofr => { ++ ++ DEFAULT_ENCODER => "ofr", ++ DEFAULT_DECODER => "ofr", ++ ++ ENCODER => { ++ ofr => { ++ NAME => "ofr", ++ ESTR => sub { ++ $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts --overwrite $opts %i --output %o" ++ }, ++ ++ PROMPT => { ++ OFMODE => 1, ++ OFOPT => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ ofr => { ++ NAME => "ofr", ++ DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ ofs => { ++ ++ DEFAULT_ENCODER => "ofs", ++ DEFAULT_DECODER => "ofs", ++ ++ ENCODER => { ++ ofs => { ++ NAME => "ofs", ++ ESTR => sub { ++ $opts = "--mode $ofmode --optimize $ofopt" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts --overwrite $opts %i --output %o" ++ }, ++ ++ PROMPT => { ++ OFMODE => 1, ++ OFOPT => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ ofs => { ++ NAME => "ofs", ++ DSTR => sub { "$dopts --overwrite --decode %i --output %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ ++ oga => { ++ DEFAULT_ENCODER => 'oggenc', ++ DEFAULT_DECODER => 'oggdec', ++ ++ ENCODER => { ++ oggenc => { ++ NAME => 'oggenc', ++ ESTR => sub { ++ $opts = "--resample $freq -q $oggqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ PROMPT => { ++ FREQ => 1, ++ OGGQUAL => 1, ++ }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ sox => { ++ NAME => "sox", ++ ESTR => sub { ++ $opts = "-r $freq -c $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "%i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ oggdec => { ++ NAME => "oggdec", ++ DSTR => sub { "$dopts %i --output %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ ++ sox => { ++ NAME => "sox", ++ DSTR => sub { "%i $dopts %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "vorbiscomment", ++ }, ++ }, ++ ++ ogg => { ++ ++ DEFAULT_ENCODER => "oggenc", ++ DEFAULT_DECODER => "oggdec", ++ ++ ENCODER => { ++ oggenc => { ++ NAME => "oggenc", ++ ESTR => sub { ++ $opts = "--resample $freq -q $oggqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i -o %o" ++ }, ++ ++ PROMPT => { ++ FREQ => 1, ++ OGGQUAL => 1, ++ }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ab $bitrate.k -ar $freq -ac $channels -codec:a libvorbis" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ sox => { ++ NAME => "sox", ++ ESTR => sub { ++ $opts = "-r $freq -c $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "%i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ oggdec => { ++ NAME => "oggdec", ++ DSTR => sub { "$dopts %i --output %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ ++ sox => { ++ NAME => "sox", ++ DSTR => sub { "%i $dopts %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "vorbiscomment", ++ }, ++ }, ++ ++ opus => { ++ ++ DEFAULT_ENCODER => "opusenc", ++ DEFAULT_DECODER => "opusdec", ++ ++ ENCODER => { ++ opusenc => { ++ NAME => 'opusenc', ++ ESTR => sub { ++ $opts = "--bitrate $bitrate" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ PROMTP => { ++ BITRATE => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ opusdec => { ++ NAME => 'opusdec', ++ DSTR => sub { "--force-wav %i %o" }, ++ PROMPT => { NONE => 0 }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ raw => { ++ ++ DEFAULT_ENCODER => "sox", ++ DEFAULT_DECODER => "sox", ++ ++ ENCODER => { ++ sox => { ++ NAME => 'sox', ++ ESTR => sub { ++ $opts = "-r $freq -c $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "%i $opts $eopts %o $effect" ++ }, ++ ++ PROMPT => { ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ sox => { ++ NAME => 'sox', ++ DSTR => sub { "-w -s -r $freq -c $channels $dopts %i %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ rm => { ++ ++ DEFAULT_ENCODER => 'ffmpeg', ++ DEFAULT_DECODER => 'ffmpeg', ++ ++ ENCODER => { ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = "-ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "-ar $freq -ac $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ FREQ => 1, ++ CHANNELS => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ mplayer => { ++ NAME => 'mplayer', ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ shn => { ++ ++ DEFAULT_ENCODER => "shorten", ++ DEFAULT_DECODER => "shorten", ++ ++ ENCODER => { ++ shorten => { ++ NAME => "shorten", ++ ESTR => sub { ++ $opts = "-c $channels" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ PROMPT => { CHANNELS => 1 }, ++ }, ++ }, ++ ++ DECODER => { ++ shorten => { ++ NAME => "shorten", ++ DSTR => sub { "-x %i %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ spx => { ++ ++ DEFAULT_ENCODER => "speexenc", ++ DEFAULT_DECODER => "speexdec", ++ ++ ENCODER => { ++ speexenc => { ++ NAME => "speexenc", ++ ESTR => sub { ++ $opts = "--quality $spxqual" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "$eopts $opts %i %o" ++ }, ++ PROMPT => { SPXQUAL => 1 }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { ++ $opts = "--bitrate $bitrate.k" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i %i $eopts $opts %o" ++ }, ++ ++ PROMPT => { ++ BITRATE => 1, ++ }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { ++ $opts = "--bitrate $bitrate.k" if $defopts == 1; ++ $opts = '' if $defopts == 0; ++ "-y -i $eopts $opts %o" ++ }, ++ PROMPT => { ++ BITRATE => 1, ++ }, ++ }, ++ }, ++ ++ DECODER => { ++ speexdec => { ++ NAME => "speexdec", ++ DSTR => sub { "$dopts %i %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => undef, ++ }, ++ }, ++ ++ tta => { ++ ++ DEFAULT_ENCODER => "ttaenc", ++ DEFAULT_DECODER => "ttaenc", ++ ++ ENCODER => { ++ ttaenc => { ++ NAME => "ttaenc", ++ ESTR => sub { "$eopts -e %i -o %o" }, ++ PROMPT => { NONE => 0, }, ++ }, ++ }, ++ ++ DECODER => { ++ ttaenc => { ++ NAME => "ttaenc", ++ DSTR => sub { "$dopts -d %i -o %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ wav => { ++ ++ DEFAULT_ENCODER => "mv", ++ DEFAULT_DECODER => "cp", ++ ++ ENCODER => { ++ mv => { ++ NAME => "mv", ++ ESTR => sub { "%i %o" }, ++ PROMPT => { NONE => 0, }, ++ }, ++ }, ++ ++ DECODER => { ++ cp => { ++ NAME => "cp", ++ DSTR => sub { "%i %o" }, ++ } ++ }, ++ ++ TAGS => { ++ READ => 0, ++ WRITE => 0, ++ MODULE => undef, ++ }, ++ }, ++ ++ wv => { ++ ++ DEFAULT_ENCODER => "wavpack", ++ DEFAULT_DECODER => "wvunpack", ++ ++ ENCODER => { ++ wavpack => { ++ NAME => "wavpack", ++ ESTR => sub { "$eopts -h -y %i -o %o" }, ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ ffmpeg => { ++ NAME => 'ffmpeg', ++ ESTR => sub { "-y -i %i $eopts %o" }, ++ PROMPT => { NONE => 0, }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ ESTR => sub { "-y -i %i $eopts %o" }, ++ PROMPT => { NONE => 0, }, ++ }, ++ }, ++ ++ DECODER => { ++ wvunpack => { ++ NAME => "wvunpack", ++ DSTR => sub { "$dopts -y %i -o %o" }, ++ }, ++ ++ ffmpeg => { ++ NAME => "ffmpeg", ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ avconv => { ++ NAME => 'avconv', ++ DSTR => sub { "$dopts -y -i %i %o" }, ++ }, ++ ++ mplayer => { ++ NAME => "mplayer", ++ DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, ++ }, ++ }, ++ ++ TAGS => { ++ READ => 1, ++ WRITE => 1, ++ MODULE => "Audio::Scan", ++ }, ++ }, ++); ++ ++# supported ffmpeg/avconv formats (decode only) ++my @ffmpeg_codecs = ( "mmf", "ra", "wma" ); ++my @ffmpeg_forks = ( "avconv", "ffmpeg" ); ++ ++foreach my $fork (@ffmpeg_forks) { ++ ++ foreach my $codec (@ffmpeg_codecs) { ++ ++ $run{$codec}{DEFAULT_ENCODER} = $fork; ++ $run{$codec}{DEFAULT_DECODER} = $fork; ++ $run{$codec}{ENCODER}{$fork}{NAME} = $fork; ++ $run{$codec}{DECODER}{$fork}{NAME} = $fork; ++ $run{$codec}{DECODER}{$fork}{DSTR} = sub {"-y %i $dopts %o"}; ++ $run{$codec}{ENCODER}{$fork}{ESTR} = sub {"-y -i %i $eopts -ab $bitrate.k -ar $freq -ac $channels %o"}; ++ $run{$codec}{TAGS}{READ} = 0; ++ $run{$codec}{TAGS}{WRITE} = 0; ++ $run{$codec}{TAGS}{MODULE} = undef; ++ } ++ ++} ++ ++# support reading of WMA tags via Audio::Scan ++$run{wma}{TAGS}{READ} = 1; ++$run{wma}{TAGS}{MODULE} = "Audio::Scan"; ++ ++# supported video to audio types ++my @movie_codecs = ( ++ "rv", "asf", "avi", "divx", ++ "mkv", "mpg", "mpeg", "mov", ++ "ogm", "qt", "vcd", "vob", ++ "wmv", "flv", "svcd", "m4v", ++ "nsv", "nuv", "psp", "smk", ++ "ogv", "webm", ++ ++ # decode only audio formats ++ "vqf", "tak", ++ ); ++ ++foreach (@movie_codecs) { ++ $run{$_}{DEFAULT_ENCODER} = undef; ++ $run{$_}{DEFAULT_DECODER} = "ffmpeg"; ++ $run{$_}{DECODER}{mplayer}{NAME} = "mplayer"; ++ $run{$_}{DECODER}{ffmpeg}{NAME} = "ffmpeg"; ++ $run{$_}{DECODER}{mplayer}{DSTR} = sub { "$dopts -vc null -vo null -ao pcm:file=%o %i" }; ++ $run{$_}{DECODER}{ffmpeg}{DSTR} = sub { "$dopts -i %i %o"; }; ++ $run{$_}{TAGS}{READ} = 0; ++ $run{$_}{TAGS}{WRITE} = 0; ++ $run{$_}{TAGS}{MODULE} = undef; ++} ++ ++# supported sndfile-convert formats ++my @sndfile = ( ++ "pvf", "caf", "sf", "paf", "fap", "sd2", ++ "mat4", "mat5", "mat", "ircam", "w64", "nist", ++ "rf64", ++ ); ++ ++foreach (@sndfile) { ++ ++ $run{$_}{DEFAULT_ENCODER} = "sndfile-convert"; ++ $run{$_}{DEFAULT_DECODER} = "sndfile-convert"; ++ $run{$_}{ENCODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; ++ $run{$_}{DECODER}{"sndfile-convert"}{NAME} = "sndfile-convert"; ++ $run{$_}{ENCODER}{"sndfile-convert"}{ESTR} = sub { "$eopts %i %o" }; ++ $run{$_}{DECODER}{"sndfile-convert"}{DSTR} = sub { "$dopts %i %o" }; ++ $run{$_}{TAGS}{READ} = 0; ++ $run{$_}{TAGS}{WRITE} = 0; ++ $run{$_}{TAGS}{MODULE} = undef; ++} ++ ++# supported sox formats ++my @sox_codecs = ( ++ "aiff", "aif", "au", "snd", "voc", ++ "smp", "avr", "cdr", "8svx", "amb", ++ "dat", "dvms", "f32", "f64", "fssd", ++ "gsrt", "hcom", "txw", "vms", "al", ++ "sou", "ima", "prc", "cvu", ++ "maud", ++ ); ++ ++foreach (@sox_codecs) { ++ ++ $run{$_}{DEFAULT_ENCODER} = "sox"; ++ $run{$_}{DEFAULT_DECODER} = "sox"; ++ $run{$_}{ENCODER}{sox}{NAME} = "sox"; ++ $run{$_}{DECODER}{sox}{NAME} = "sox"; ++ $run{$_}{ENCODER}{sox}{ESTR} = sub { "%i -r $freq -c $channels $eopts %o $effect" }; ++ $run{$_}{DECODER}{sox}{DSTR} = sub { "%i $dopts %o" }; ++ $run{$_}{TAGS}{READ} = 0; ++ $run{$_}{TAGS}{WRITE} = 0; ++ $run{$_}{TAGS}{MODULE} = undef; ++ ++ $run{$_}{ENCODER}{sox}{PROMPT}{FREQ} = 1; ++ $run{$_}{ENCODER}{sox}{PROMPT}{CHANNELS} = 1; ++ ++} ++ ++# load codecs.conf file ++load_codecs() if -e $codecs_conf; ++ ++my $out_name = $outfile; ++my $out_dir = $outdir; ++my $first_message = 1; ++my %files; ++my $number = 0; ++ ++# process all files and directories ++sub proc_input { ++ ++ $to =~ tr/A-Z/a-z/; ++ ++ perror("bad_input","") unless(exists($run{$to})); ++ ++ proc_preserve_dir($dir0) if @dir and $preserve; # process recursive directory preservation (sends to proc_files ++ proc_dirs() if @dir and not $preserve; # process directories including recursively (sends to proc_files) ++ proc_files() if @file; # process all files ++ fork_files(); # start the conversion process. ++} ++ ++# process all files (all roads lead to rome) ++sub proc_files { ++ ++ if (@file) { ++ ++ foreach my $i (sort(@file)) { ++ ++ my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); ++ ++ $ext =~ s/^\.//; ++ $dir = rel2abs($dir); ++ $outdir = $dir if not defined($out_dir) and not $preserve; ++ $outdir = $out_dir if $preserve; ++ ++ my $if = $ext; ++ $if =~ tr/A-Z/a-z/; ++ ++ $only =~ tr/A-Z/a-z/ if $only; ++ ++ next if $only and $if ne $only; ++ ++ $encoder = $my_encoder if defined($my_encoder); ++ $decoder = $my_decoder if defined($my_decoder); ++ ++ $encoder = $run{$to}{DEFAULT_ENCODER} if not $my_encoder; ++ $decoder = $run{$if}{DEFAULT_DECODER} if not $my_decoder; ++ ++ if (-e "$file.$to" and not $overwrite) { ++ pnotice("overwrite","$file.$to",1); ++ $total_failed++; ++ next; ++ } ++ ++ if (check_input($file,$dir,$if) == 0) { ++ ++ pnotice("unk_encoder","$file.$ext",1), next unless(exists($run{$to}{ENCODER}{$encoder})); ++ pnotice("unk_decoder","$file.$ext",1), next unless(exists($run{$if}{DECODER}{$decoder})); ++ ++ get_visual_opts($to,$outdir) if $gui and not defined($first_run); ++ ++ $first_run = 1; ++ ++ perror("multi_out","") if (defined($out_name) and $#file gt 0 or defined($out_name) and @dir); ++ perror("no_outdir","") if (not -e $outdir and not -d $outdir); ++ ++ $outfile = "$file" if not $out_name; ++ ++ if ($keep and $if eq $to) { ++ system("cp -v \"$dir/$file.$ext\" \"$outdir/$outfile.$ext\"") if $outdir ne $dir and not -e "$outdir/$outfile.$ext"; ++ next if $outdir eq $dir; ++ } ++ ++ else { ++ $files{"FILE$number"}{FILE} = "$dir/$file"; ++ $files{"FILE$number"}{OUTF} = "$outdir/$outfile"; ++ $files{"FILE$number"}{EXT} = "$ext"; ++ $files{"FILE$number"}{NAME} = "$file"; ++ $files{"FILE$number"}{OUTD} = "$outfile"; ++ $files{"FILE$number"}{DECODER} = "$decoder"; ++ ++ $number++; ++ } ++ ++ } ++ } ++ } ++ undef(@file); ++} ++ ++# process directories and push all to @file arrary ++sub proc_dirs { ++ ++ if (@dir) { ++ ++ my @tmp_dir = @dir; ++ undef(@dir); ++ $topdir = $tmp_dir0; ++ ++ if (not $recursive) { ++ ++ undef(@file); ++ ++ foreach my $d (@tmp_dir) { ++ ++ opendir(DIR, "$d") or perror("opening_dir","$d: $!"); ++ my @dir_files = readdir(DIR); ++ closedir(DIR); ++ perror("empty_dir","$d") if $#dir_files <= 1; ++ ++ foreach my $f (@dir_files) { ++ ++ if (not -d $f and not -d "$d/$f") { ++ push(@file, "$d/$f"); ++ undef($out_name); ++ } ++ } ++ } ++ ++ proc_files(); ++ return 0; ++ ++ } ++ ++ elsif ($recursive) { ++ ++ if (not $preserve) { ++ ++ undef(@file); ++ ++ foreach my $r (@tmp_dir) { ++ ++ $r = rel2abs($r); ++ ++ find ( sub { ++ my $rfile = $File::Find::name; ++ push(@file, $rfile) if not -d $rfile; ++ }, $r ++ ); ++ } ++ ++ proc_files(); ++ return 0; ++ ++ } ++ } ++ ++ } ++} ++ ++# preserve directory structuer (revised 10-7-2013) ++my $out_dir_original = rel2abs($outdir) if $outdir and -d $outdir; ++ ++sub proc_preserve_dir { ++ ++$topdir = rel2abs($dir0); ++ ++perror("no_outdir","") if not defined($out_dir_original); ++perror("no_outdir","") if not -d $out_dir_original; ++ ++undef(@file); # clear the array before we begin. ++ ++find ( sub { ++ my $val = $File::Find::name; ++ $val =~ s/(\$)/\\\$/g; ++ ++ if ($val ne $topdir) { ++ ++ $val =~ s/$topdir\///; ++ ++ # create mirrored directories in output directory ++ if (not -f fileparse("$topdir/$val") and not -d "$out_dir_original/$val") { ++ say "creating directory $out_dir_original/$val" if not -f "$topdir/$val" and $verbose; ++ mkdir("$out_dir_original/$val", 0755) if not -f "$topdir/$val"; ++ } ++ ++ # this will list all files in their original directories ++ if (-f "$topdir/$val") { ++ say "$lang{debug} pushing to \@file: $topdir/$val" if $debug == 1; ++ push(@file, "$topdir/$val"); ++ } ++ ++ # set $out_dir to the ++ $out_dir = "$out_dir_original/" . dirname($val) if -f "$topdir/$val"; ++ ++ # send file, and output dir to proc_files(); ++ proc_files(); ++ } ++ ++ }, $topdir ++ ); ++} ++ ++# convert input to destination format ++sub convert { ++ ++ my ($inf, $outf, $infmt, $iname, $oname, $dec) = @_; ++ ++ my $if = $infmt; ++ $if =~ tr/A-Z/a-z/; ++ ++ clear_tag_hash() if not $rip; ++ ++ # catch ^C. will have to be pressed repeatedly to exit the process. ++ $SIG{INT} = sub { ++ unlink("$outf.$$.wav"); ++ kill 9, $$; ++ }; ++ ++ # check to see if encoder/decoder exists. if not, see if we have one ++ # that supports the desired input/output formats. ++ $decoder = $dec; ++ check_encoder(); ++ check_decoder($infmt); ++ ++ my $decode_string = $run{$if}{DECODER}{$decoder}{DSTR}->(); ++ $decode_string =~ s/%i/\"$inf.$infmt\"/; ++ $decode_string =~ s/%o/\"$outf.$$.wav\"/; ++ $decode_string =~ s/(\$|\\)/\\$1/g; ++ ++ pnotice("debug","\n$run{$if}{DECODER}{$decoder}{NAME} $decode_string", 2) if $dryrun; ++ ++ # decode input file to temporary wav ++ system("$run{$if}{DECODER}{$decoder}{NAME} $decode_string $silent") if not $dryrun; ++ ++ # remove temporary wav file and die if decode fails ++ if ($? > 0) { ++ unlink("$outf.$$.wav") if -e "$outf.$$.wav"; ++ say ""; ++ $banner = 0; ++ pnotice("decode_failed","$inf.$infmt: try with --verbose",1); ++ return 1; ++ } ++ ++ # normalize wav file before encoding to output format ++ perror("no_app","normalize") if $normalize and not `which normalize 2>/dev/null`; ++ system("normalize $nopts \"$outf.$$.wav\"") if $normalize; ++ ++ # copy meta-data from input file to %tag_name ++ read_tags("$inf.$infmt", "$if") if $run{$if}{TAGS}{READ} == 1 and not $dryrun; ++ ++ my $tag_opts = format_tags($to); # tag options for mp4/m4a/m4b/mpc/mpp/bonk/spx/wv ++ ++ my $encode_string = $run{$to}{ENCODER}{$encoder}{ESTR}->(); ++ $encode_string =~ s/%i/$tag_opts \"$outf.$$.wav\"/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "faac" or $encoder eq "mpcenc"; ++ $encode_string =~ s/%i/\"$outf.$$.wav\" $tag_opts/ if $to =~ /mpc|mpp|mp4|m4a/ and $encoder eq "ffmpeg" or $encoder eq "avconv"; ++ $encode_string =~ s/%i/\"$outf.$$.wav\"/ if $to !~ /mpc|mpp|mp4|m4a/; ++ $encode_string =~ s/%o/$tag_opts \"$outf.$to\"/ if $tag_opts ne " " and $to !~ /mpc|mpp|mp4|m4a/; ++ $encode_string =~ s/%o/\"$outf.$to\"/ if $tag_opts eq " " or $to =~ /mpc|mpp|mp4|m4a/; ++ $encode_string =~ s/(\$|\\)/\\$1/g; ++ ++ # read tag options from command line if present ++ get_user_tags(); ++ ++ pnotice("debug","\n$run{$to}{ENCODER}{$encoder}{NAME} $encode_string", 2) if $dryrun; ++ ++ # encode temporary WAV to desired output format. ++ system("$run{$to}{ENCODER}{$encoder}{NAME} $encode_string $silent") if not $dryrun; ++ ++ # remove partially encoded output file and temporary wav if encoding fails ++ if ($? > 0) { ++ unlink("$outf.$to") if -e "$outf.$to"; ++ unlink("$outf.$$.wav") if -e "$outf.$$.wav"; ++ say ""; ++ $banner = 0; ++ pnotice("encode_failed","$outf.$to: $?",1); ++ return 1; ++ } ++ ++ # write meta-data to output file from %tag_name hash ++ write_tags("$outf.$to", "$to") if $run{$to}{TAGS}{WRITE} == 1 and $tag_opts eq " " and not $dryrun; ++ ++ unlink("$outf.$$.wav") if not $dryrun; ++ unlink("$inf.$infmt") if $delete and not $dryrun; ++ ++ pnotice("removed_tmp","$outf.$$.wav","2") if $verbose; ++ pnotice("removed_src","$inf.$infmt", "2") if $delete and $verbose; ++} ++ ++$pm->run_on_finish ++( sub { ++ my $pid = shift; ++ my $exit_code = shift; ++ my $ident = shift; ++ ++ if (-e "$ident.$to") { ++ $total_converted++; ++ } ++ say "$lang{debug} PID: $pid EXIT_CODE: $exit_code IDENTITY: \"$ident.$to\"" if $debug == 1; ++ } ++); ++ ++# convert all files that have been placed in the %files hash through various procs* ++sub fork_files { ++ ++ say "\n$name - $version\n" if not $gui and $banner == 1; ++ ++ foreach (sort(keys(%files))) ++ { ++ $pm->start($files{$_}{OUTF}) and next; ++ my $msg = "$lang{converting}" . " " . basename($files{$_}{FILE}) . ".$files{$_}{EXT} -> $to"; ++ say "$msg" if not $gui; ++ system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$msg\" 10 &") if $gui and $kde; ++ system("notify-send \"$name\" \"$msg\" -t 35 -i $icon_path &") if $gui and $gnome; ++ convert("$files{$_}{FILE}","$files{$_}{OUTF}","$files{$_}{EXT}","$files{$_}{NAME}","$files{$_}{OUTD}","$files{$_}{DECODER}"); ++ $pm->finish; ++ } ++ ++ $pm->wait_all_children; ++ $total_failed = $number - $total_converted if $total_converted < $number; ++ ++ my $finished_msg = "\n$lang{total_converted} $total_converted, $lang{failed} $total_failed\n"; ++ ++ say "$finished_msg" if not $gui; ++ system("kdialog --icon $icon_path --title \"$name\" --passivepopup \"$finished_msg\" 10 &") if $gui and $kde; ++ system("notify-send \"$name\" \"$finished_msg\" -t 35 -i $icon_path &") if $gui and $gnome; ++ ++} ++ ++# if the default encoder does not exist, cycle through the supported ++# encoders until we find one that does. ++sub check_encoder { ++ ++ if (not `which $encoder 2>/dev/null`) { ++ my $first_encoder = $encoder; ++ foreach (keys %{$run{$to}{ENCODER}}) { $encoder = $_ and return if `which $_ 2>/dev/null`; } ++ perror("no_encode_app","$to") if $encoder eq $first_encoder; ++ } ++ ++ else { return 0; } ++} ++ ++# if the default decoder does not exist, cycle through the supported ++# decoders until we find one that does. ++sub check_decoder { ++ ++ my $from = shift; ++ ++ if (not `which $decoder 2>/dev/null`) { ++ my $first_decoder = $decoder; ++ foreach (keys %{$run{$from}{DECODER}}) { $decoder = $_ and return if `which $_ 2>/dev/null`; } ++ perror("no_decode_app","$from") if $decoder eq $first_decoder; ++ } ++ ++ else { return 0; } ++} ++ ++# make sure encoding/decoding is supported. ++sub check_input { ++ ++ my $file = shift; ++ my $dir = shift; ++ my $ext = shift; ++ ++ perror("no_encoder","$to") unless(defined($run{$to}{ENCODER})); ++ ++ unless(defined($run{$ext}{DECODER})) { ++ pnotice("no_decoder","$ext",2) if $verbose or not $only; ++ $total_failed++; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++######################################## ++# GUI options for KDE & Gnome Plugins # ++######################################## ++ ++my $kdialog = "kdialog --title \"$name\""; ++my $zenity = "zenity --title \"$name\" --list --radiolist --width 100 --height 300 --column '' --column "; ++ ++sub get_visual_opts { ++ ++ my ($to_fmt,$od) = @_; ++ ++ # escape illegal characters in output directory name ++ $od =~ s/('|\(|\)|"|\\)/\\$1/g; ++ ++ $outdir = `kdialog --getexistingdirectory $od` if $config{KDE_DIR} == 1 and $kde; ++ $outdir = `zenity --title \"$lang{gui_outdir}\" --file-selection --directory --filename=\`pwd\`` if $config{ZEN_DIR} == 1 and $gnome; ++ ++ chomp($outdir); ++ $out_dir = $outdir; ++ exit(1) if not $outdir; ++ ++ if ($config{KDE_OPTS} == 1 or $config{ZEN_OPTS} == 1) { ++ foreach (keys %{$run{$to_fmt}{ENCODER}{$encoder}{PROMPT}}) { ++ prompt_user($_); ++ } ++ } ++} ++ ++sub prompt_user { ++ ++ my $opt = shift; ++ ++ given ($opt) { ++ ++ when (/^BITRATE/) { ++ $bitrate = `$kdialog --default $bitrate --combobox \"$lang{gui_bitrate}\" 56 112 128 160 192 256 320` if $kde; ++ $bitrate = `$zenity \"$lang{gui_bitrate}\" FALSE 56 FALSE 112 FALSE 128 FALSE 160 TRUE 192 FALSE 256 FALSE 320` if $gnome; ++ chomp($bitrate); ++ exit(1) if not $bitrate; ++ } ++ ++ when (/^FREQ/) { ++ $freq = `$kdialog --default $freq --combobox \"$lang{gui_freq}\" 32000 44100 48000` if $kde; ++ $freq = `$zenity \"$lang{gui_freq}\" FALSE 32000 TRUE 44100 FALSE 48000` if $gnome; ++ chomp($freq); ++ exit(1) if not $freq; ++ } ++ ++ when (/^CHANNELS/) { ++ $channels = `$kdialog --default $channels --combobox \"$lang{gui_chans}\" 1 2` if $kde; ++ $channels = `$zenity \"$lang{gui_chans}\" FALSE 1 TRUE 2` if $gnome; ++ chomp($channels); ++ exit(1) if not $channels; ++ } ++ ++ when (/^FCOMP/) { ++ $fcomp = `$kdialog --default $fcomp --combobox \"$lang{gui_fcomp}\" 0 1 2 3 4 5 6 7 8` if $kde; ++ $fcomp = `$zenity \"$lang{gui_fcomp}\" FALSE 0 FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8` if $gnome; ++ chomp($fcomp); ++ exit(1) if not $fcomp; ++ } ++ ++ when (/^ACOMP/) { ++ $acomp = `$kdialog --default $acomp --combobox \"$lang{gui_acomp}\" 1000 2000 3000 4000 5000` if $kde; ++ $acomp = `$zenity \"$lang{gui_acomp}\" FALSE 1000 FALSE 2000 TRUE 3000 FALSE 4000 FALSE 5000` if $gnome; ++ chomp($acomp); ++ exit(1) if not $acomp; ++ } ++ ++ when (/^OGGQUAL/) { ++ $oggqual = `$kdialog --default $oggqual --combobox \"$lang{gui_oggqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; ++ $oggqual = `$zenity \"$lang{gui_oggqual}\" FALSE 0 FALSE 1 FALSE 2 TRUE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 FALSE 8 FALSE 9 FALSE 10` if $gnome; ++ chomp($oggqual); ++ exit(1) if not $oggqual; ++ } ++ ++ when (/^SPXQUAL/) { ++ $spxqual = `$kdialog --default $spxqual --combobox \"$lang{gui_spxqual}\" 0 1 2 3 4 5 6 7 8 9 10` if $kde; ++ $spxqual = `$zenity \"$lang{gui_spxqual}\" FALSE 0 FALSE 1 FALSE 2 FALSE 3 FALSE 4 FALSE 5 FALSE 6 FALSE 7 TRUE 8 FALSE 9 FALSE 10` if $gnome; ++ chomp($spxqual); ++ exit(1) if not $spxqual; ++ } ++ ++ when (/^AACQUAL/) { ++ $aacqual = `$kdialog --default $aacqual --combobox \"$lang{gui_aacqual}\" 100 200 300 400 500` if $kde; ++ $aacqual = `$zenity \"$lang{gui_aacqual}\" TRUE 100 FALSE 200 FALSE 300 FALSE 400 FALSE 500` if $gnome; ++ chomp($aacqual); ++ exit(1) if not $aacqual; ++ } ++ ++ when (/^MPCQUAL/) { ++ $mpcqual = `$kdialog --default $mpcqual --combobox \"$lang{gui_mpcqual}\" thumb radio standard xtreme insane braindead` if $kde; ++ $mpcqual = `$zenity \"$lang{gui_mpcqual}\" FALSE thumb TRUE radio FALSE standard FALSE xtreme FALSE insane FALSE braindead` if $gnome; ++ chomp($mpcqual); ++ exit(1) if not $mpcqual; ++ } ++ ++ when (/^OFMODE/ ) { ++ $ofmode = `$kdialog --default $ofmode --combobox \"$lang{gui_ofmode}\" fast normal high extra best highnew extranew bestnew` if $kde; ++ $ofmode = `$zenity \"$lang{gui_ofmode}\" FALSE fast TRUE normal FALSE high FALSE extra FALSE best FALSE highnew FALSE extranew FALSE bestnew` if $gnome; ++ chomp($ofmode); ++ exit(1) if not $ofmode; ++ } ++ ++ when (/^OFOPT/) { ++ $ofopt = `$kdialog --default $ofopt --combobox \"$lang{gui_ofopt}\" none fast normal high best` if $kde; ++ $ofopt = `$zenity \"$lang{gui_ofopt}\" FALSE none TRUE fast FALSE normal FALSE high FALSE best` if $gnome; ++ chomp($ofopt); ++ exit(1) if not $ofopt; ++ } ++ ++ when (/^BRATIO/) { ++ $bratio = `$kdialog --default $bratio --combobox \"$lang{gui_bratio}\" 1 2 3 4 5` if $kde; ++ $bratio = `$zenity \"$lang{gui_bratio}\" FALSE 1 TRUE 2 FALSE 3 FALSE 4 FALSE 5` if $gnome; ++ chomp($bratio); ++ exit(1) if not $bratio; ++ } ++ ++ when (/^BQUANL/) { ++ $bquanl = `$kdialog --default $bquanl --combobox \"$lang{gui_bquanl}\" 1.00 1.25 1.50 1.75 2.00` if $kde; ++ $bquanl = `$zenity \"$lang{gui_bquanl}\" TRUE 1.00 FALSE 1.25 FALSE 1.50 FALSE 1.75 FALSE 2.00` if $gnome; ++ chomp($bquanl); ++ exit(1) if not $bquanl; ++ } ++ ++ when (/^BPSIZE/) { ++ $bpsize = `$kdialog --default $bpsize --combobox \"$lang{gui_bpsize}\" 10 128` if $kde; ++ $bpsize = `$zenity \"$lang{gui_bpsize}\" FALSE 10 TRUE 128` if $gnome; ++ chomp($bpsize); ++ exit(1) if not $bpsize; ++ } ++ ++ default { return 0; } ++ } ++ ++} ++ ++# all copied tags will be stored here for furture use ++my %tag_name = ++( ++ title => undef, ++ track => undef, ++ artist => undef, ++ album => undef, ++ comment => undef, ++ year => undef, ++ genre => undef, ++); ++ ++# override tags read from input file if any of the tagging ++# options are specified by the user during conversion. ++sub get_user_tags ++{ ++ $tag_name{title} = $title if $title; ++ $tag_name{track} = $track if $track; ++ $tag_name{artist} = $artist if $artist; ++ $tag_name{album} = $album if $album; ++ $tag_name{comment} = $comment if $comment; ++ $tag_name{year} = $year if $year; ++ $tag_name{genre} = $genre if $genre; ++} ++ ++# the formats MP4/M4A/M4B/MPC/MPP/WV/BONK have no tag writing module. ++# tags therefore have to be written during encode via various ++# command line args. ++sub format_tags { ++ ++ my $type = shift; ++ ++ given ($type) { ++ ++ when (/^mp4$|^m4a$|^m4b$/) { ++ ++ if ($run{$to}{ENCODER}{$encoder}{NAME} eq "ffmpeg" or $run{$to}{ENCODER}{$encoder}{NAME} eq "avconv") { ++ ++ $tag_name{track} = 0 if not $tag_name{track}; ++ $tag_name{year} = 0 if not $tag_name{year}; ++ ++ return "-metadata TITLE=\"$tag_name{title}\" -metadata TRACK=\"$tag_name{track}\" -metadata ARTIST=\"$tag_name{artist}\" -metadata ALBUM=\"$tag_name{album}\" -metadata COMMENT=\"$tag_name{comment}\" -metadata YEAR=\"$tag_name{year}\" -metadata GENRE=\"$tag_name{genre}\""; ++ ++ } else { ++ ++ return "--title \"$tag_name{title}\" --track \"$tag_name{track}\" --artist \"$tag_name{artist}\" --album \"$tag_name{album}\" --comment \"$tag_name{comment}\" --year \"$tag_name{year}\" --genre \"$tag_name{genre}\""; ++ ++ } ++ } ++ ++ when (/^mpc$|^mpp$/) { return "--artist \"$tag_name{artist}\" --title \"$tag_name{title}\" --album \"$tag_name{album}\" --track \"$tag_name{track}\" --genre \"$tag_name{genre}\" --year \"$tag_name{year}\" --comment \"$tag_name{comment}\""; } ++ when (/^wv$/) { return "-w \"Title=$tag_name{title}\" -w \"Track=$tag_name{track}\" -w \"Artist=$tag_name{artist}\" -w \"Album=$tag_name{album}\" -w \"Comment=$tag_name{comment}\" -w \"Year=$tag_name{year}\" -w \"Genre=$tag_name{genre}\""; } ++ when (/^bonk$/) { return "-t \"$tag_name{title}\" -a \"$tag_name{artist}\" -c \"$tag_name{comment}\""; } ++ when (/^spx$/) { return "--author \"$tag_name{artist}\" --title \"$tag_name{title}\" --comment \"year=$tag_name{year}\" --comment \"tracknumber=$tag_name{track}\" --comment \"album=$tag_name{album}\" --comment \"genre=$tag_name{genre}\" --comment \"comment=$tag_name{comment}\""; } ++ ++ default { return " "; } ++ } ++} ++ ++# meta-data is read based on input file extension. ++# all tags which are present will be copied to ++# the %tag_name hash. ++sub read_tags { ++ ++ my $in_file = shift; ++ my $in_format = shift; ++ ++ my $tag_module = $run{$in_format}{TAGS}{MODULE}; ++ ++ given ($in_format) { ++ ++ when (/^mp3$|^mp3hd$/) { ++ my $mp3tag = $tag_module->new($in_file); ++ my @tags = $mp3tag->autoinfo(); ++ ++ $tag_name{title} = "$tags0" if $tags0; ++ $tag_name{track} = "$tags1" if $tags1; ++ $tag_name{artist} = "$tags2" if $tags2; ++ $tag_name{album} = "$tags3" if $tags3; ++ $tag_name{comment} = "$tags4" if $tags4; ++ $tag_name{year} = "$tags5" if $tags5; ++ $tag_name{genre} = "$tags6" if $tags6; ++ ++ return 0; ++ } ++ ++ when (/^ogg$|^oga$/) { ++ my $ogg_tag = Audio::Scan->scan_tags($in_file)->{tags}; ++ ++ $tag_name{title} = $ogg_tag->{TITLE} if $ogg_tag->{TITLE}; ++ $tag_name{track} = $ogg_tag->{TRACKNUMBER} if $ogg_tag->{TRACKNUMBER}; ++ $tag_name{artist} = $ogg_tag->{ARTIST} if $ogg_tag->{ARTIST}; ++ $tag_name{album} = $ogg_tag->{ALBUM} if $ogg_tag->{ALBUM}; ++ $tag_name{comment} = $ogg_tag->{COMMENT} if $ogg_tag->{COMMENT}; ++ $tag_name{year} = $ogg_tag->{YEAR} if $ogg_tag->{YEAR}; ++ $tag_name{genre} = $ogg_tag->{GENRE} if $ogg_tag->{GENRE}; ++ ++ return 0; ++ } ++ ++ when (/^spx$/) { ++ my $pid = open(SPX, "speexdec \"$in_file\" tmp1-$$.wav 2>&1 |") or perror("opening_file","$in_file"); ++ my @data = <SPX>; ++ @data = grep(!/^$|^#/, @data); ++ ++ close(SPX); ++ ++ foreach (@data) { ++ ++ next unless /=/; ++ chomp; ++ ++ my ($k, $v) = split /=/; ++ $k =~ tr/A-Z/a-z/; ++ $tag_name{$k} = $v if exists($tag_name{$k}); ++ $tag_name{artist} = $v if $k =~ /^author/i; ++ $tag_name{track} = $v if $k =~ /^tracknumber/i; ++ } ++ ++ unlink("tmp-$$.wav"); ++ return 0; ++ } ++ ++ when (/^flac$|^fla$/) { ++ my $flac_tag = Audio::Scan->scan_tags($in_file)->{tags}; ++ ++ $tag_name{title} = $flac_tag->{TITLE} if $flac_tag->{TITLE}; ++ $tag_name{track} = $flac_tag->{TRACKNUMBER} if $flac_tag->{TRACKNUMBER}; ++ $tag_name{artist} = $flac_tag->{ARTIST} if $flac_tag->{ARTIST}; ++ $tag_name{album} = $flac_tag->{ALBUM} if $flac_tag->{ALBUM}; ++ $tag_name{comment} = $flac_tag->{COMMENT} if $flac_tag->{COMMENT}; ++ $tag_name{year} = $flac_tag->{DATE} if $flac_tag->{DATE}; ++ $tag_name{genre} = $flac_tag->{GENRE} if $flac_tag->{GENRE}; ++ ++ return 0; ++ } ++ ++ when (/^mp4$|^m4a$|^m4b$/) { ++ my $mp4_tag = $tag_module->scan_tags($in_file)->{tags}; ++ ++ $tag_name{title} = $mp4_tag->{NAM} if $mp4_tag->{NAM}; ++ $tag_name{track} = $mp4_tag->{TRKN} if $mp4_tag->{TRKN}; ++ $tag_name{artist} = $mp4_tag->{ART} if $mp4_tag->{ART}; ++ $tag_name{album} = $mp4_tag->{ALB} if $mp4_tag->{ALB}; ++ $tag_name{comment} = $mp4_tag->{CMT} if $mp4_tag->{CMT}; ++ $tag_name{year} = $mp4_tag->{DAY} if $mp4_tag->{DAY}; ++ $tag_name{genre} = $mp4_tag->{GNRE} if $mp4_tag->{GNRE}; ++ ++ return 0; ++ } ++ ++when (/^ape$|^mpc$|^mpp$|^wv$/) { ++ my $audio_tag = $tag_module->scan_tags($in_file)->{tags}; ++ ++ $tag_name{title} = $audio_tag->{TITLE} if $audio_tag->{TITLE}; ++ $tag_name{track} = $audio_tag->{TRACK} if $audio_tag->{TRACK}; ++ $tag_name{artist} = $audio_tag->{ARTIST} if $audio_tag->{ARTIST}; ++ $tag_name{album} = $audio_tag->{ALBUM} if $audio_tag->{ALBUM}; ++ $tag_name{comment} = $audio_tag->{COMMENT} if $audio_tag->{COMMENT}; ++ $tag_name{year} = $audio_tag->{YEAR} if $audio_tag->{YEAR}; ++ $tag_name{genre} = $audio_tag->{GENRE} if $audio_tag->{GENRE}; ++ ++ return 0; ++ } ++ ++ when (/^wma$/) { ++ my $wma_tag = $tag_module->scan_tags($in_file)->{tags}; ++ ++ $tag_name{title} = $wma_tag->{TITLE} if $wma_tag->{TITLE}; ++ $tag_name{track} = $wma_tag->{TRACKNUMBER} if $wma_tag->{TRACKNUMBER}; ++ $tag_name{artist} = $wma_tag->{AUTHOR} if $wma_tag->{AUTHOR}; ++ $tag_name{album} = $wma_tag->{ALBUMTITLE} if $wma_tag->{ALBUMTITLE}; ++ $tag_name{comment} = $wma_tag->{DESCRIPTION} if $wma_tag->{DESCRIPTION}; ++ $tag_name{year} = $wma_tag->{YEAR} if $wma_tag->{YEAR}; ++ $tag_name{genre} = $wma_tag->{GENRE} if $wma_tag->{GENRE}; ++ ++ return 0; ++ } ++ ++ default { return 1; } ++ } ++} ++ ++# write meta-data stored in %tag_name to output file. ++sub write_tags { ++ ++ my $out_file = shift; ++ my $out_format = shift; ++ ++ my $tag_m; ++ ++ given ($out_format) { ++ ++ when (/^mp3$|^mp3hd$/) { ++ $tag_m = MP3::Tag->config(write_v24 => 'YES'); ++ $tag_m = MP3::Tag->new("$out_file"); ++ ++ # ID3v2 Tags ++ unless(exists($tag_m->{ID3v2})) { $tag_m->new_tag("ID3v2"); } ++ ++ $tag_m->{ID3v2}->add_frame("TIT2", "$tag_name{title}") if defined($tag_name{title}); ++ $tag_m->{ID3v2}->add_frame("TRCK", "$tag_name{track}") if defined($tag_name{track}); ++ $tag_m->{ID3v2}->add_frame("TPE1", "$tag_name{artist}") if defined($tag_name{artist}); ++ $tag_m->{ID3v2}->add_frame("TALB", "$tag_name{album}") if defined($tag_name{album}); ++ $tag_m->{ID3v2}->comment("$tag_name{comment}") if defined($tag_name{comment}); ++ $tag_m->{ID3v2}->add_frame("TYER", "$tag_name{year}") if defined($tag_name{year}); ++ $tag_m->{ID3v2}->add_frame("TCON", "$tag_name{genre}") if defined($tag_name{genre}); ++ ++ $tag_m->{ID3v2}->write_tag; ++ ++ # ID3v1 Tags ++ unless(exists($tag_m->{ID3v1})) { $tag_m->new_tag("ID3v1"); } ++ ++ $tag_m->{ID3v1}->title("$tag_name{title}") if defined($tag_name{title}); ++ $tag_m->{ID3v1}->track("$tag_name{track}") if defined($tag_name{track}); ++ $tag_m->{ID3v1}->artist("$tag_name{artist}") if defined($tag_name{artist}); ++ $tag_m->{ID3v1}->album("$tag_name{album}") if defined($tag_name{album}); ++ $tag_m->{ID3v1}->comment("$tag_name{comment}") if defined($tag_name{comment}); ++ $tag_m->{ID3v1}->year("$tag_name{year}") if defined($tag_name{year}); ++ $tag_m->{ID3v1}->genre("$tag_name{genre}") if defined($tag_name{genre}); ++ ++ $tag_m->{ID3v1}->write_tag; ++ ++ return 0; ++ ++ } ++ ++ when (/^ogg$|^oga$/) { ++ $tag_m = ''; ++ ++ $tag_m = "$tag_m -t \"TITLE=$tag_name{title}\"" if $tag_name{title}; ++ $tag_m = "$tag_m -t \"TRACKNUMBER=$tag_name{track}\"" if $tag_name{track}; ++ $tag_m = "$tag_m -t \"ARTIST=$tag_name{artist}\"" if $tag_name{artist}; ++ $tag_m = "$tag_m -t \"ALBUM=$tag_name{album}\"" if $tag_name{album}; ++ $tag_m = "$tag_m -t \"COMMENT=$tag_name{comment}\"" if $tag_name{comment}; ++ $tag_m = "$tag_m -t \"YEAR=$tag_name{year}\"" if $tag_name{year}; ++ $tag_m = "$tag_m -t \"GENRE=$tag_name{genre}\"" if $tag_name{genre}; ++ ++ system("vorbiscomment -w $tag_m \"$out_file\"") if $tag_m ne ''; ++ ++ return 0; ++ } ++ ++ when (/^fla$|^flac$/) { ++ $tag_m = Audio::FLAC::Header->new("$out_file"); ++ my $tag_i = $tag_m->tags(); ++ ++ $tag_i->{TITLE} = "$tag_name{title}" if $tag_name{title}; ++ $tag_i->{TRACKNUMBER} = "$tag_name{track}" if $tag_name{track}; ++ $tag_i->{ARTIST} = "$tag_name{artist}" if $tag_name{artist}; ++ $tag_i->{ALBUM} = "$tag_name{album}" if $tag_name{album}; ++ $tag_i->{COMMENT} = "$tag_name{comment}" if $tag_name{comment}; ++ $tag_i->{DATE} = "$tag_name{year}" if $tag_name{year}; ++ $tag_i->{GENRE} = "$tag_name{genre}" if $tag_name{genre}; ++ ++ $tag_m->write(); ++ ++ return 0; ++ } ++ ++ default { perror("no_write_tag","$out_file"); } ++ } ++ ++} ++ ++# this is necessary when converting multiple files. ++# it prevents old tags from the previous file being ++# copied over to the next file in line. ++sub clear_tag_hash { ++ foreach (keys(%tag_name)) { ++ $tag_name{$_} = ''; ++ } ++} ++ ++# display meta-data for selected file(s) ++sub show_taginfo { ++ ++ perror("no_input","") if $#file < 0; ++ ++ foreach my $i (@file) { ++ ++ my ($file, $dir, $ext) = fileparse("$i", qr/\.^.*/); ++ ++ $ext =~ s/^\.//; ++ ++ my $from = $ext; ++ $from =~ tr/A-Z/a-z/; ++ ++ if ($run{$from}{TAGS}{READ} == 1) { ++ ++ clear_tag_hash(); ++ read_tags("$dir/$file.$ext","$from"); ++ ++ say ''; ++ ++ pnotice("tag_info","$file.$ext",2); ++ ++ say " Artist: $tag_name{artist}"; ++ say " Title: $tag_name{title}"; ++ say " Album: $tag_name{album}"; ++ say " Track: $tag_name{track}"; ++ say "Comment: $tag_name{comment}"; ++ say " Year: $tag_name{year}"; ++ say " Genre: $tag_name{genre}"; ++ ++ say ''; ++ ++ } else { pnotice("no_read_tag","$file.$ext",2); } ++ } ++} ++ ++# write tags to file supplied by the user ++sub write_user_tags { ++ ++ perror("no_input","") if $#file < 0; ++ ++ say ''; ++ say "$name - $version\n"; ++ ++ foreach (@file) { ++ ++ my ($file, $dir, $ext) = fileparse("$_", qr/\.^.*/); ++ ++ $ext =~ s/^\.//; ++ my $from = $ext; ++ $from =~ tr/A-Z/a-z/; ++ ++ if ($run{$from}{TAGS}{WRITE} == 1) { ++ ++ clear_tag_hash(); ++ read_tags("$dir/$file.$ext","$from"); ++ ++ $tag_name{title} = $title if $title; ++ $tag_name{track} = $track if $track; ++ $tag_name{artist} = $artist if $artist; ++ $tag_name{album} = $album if $album; ++ $tag_name{comment} = $comment if $comment; ++ $tag_name{year} = $year if $year; ++ $tag_name{genre} = $genre if $genre; ++ ++ write_tags("$dir/$file.$ext","$from"); ++ say "$lang{write_tag_i} $file.$ext"; ++ ++ } else { perror("no_write_tag","$file.$ext"); } ++ } ++ say ''; ++} ++ ++# print out list of supported encode & decode formats ++sub show_formats { ++ ++say "\n$name - $version\n"; ++say "EXT E D ENCODER DECODER TAG-READ TAG-WRITE"; ++say "----------------------------------------------------------------------"; ++ ++my $enc_count = 0; ++my $dec_count = 0; ++ ++ foreach (sort(keys(%run))) { ++ ++ my $e = "N"; $e = "Y" if defined($run{$_}{DEFAULT_ENCODER}); ++ my $d = "N"; $d = "Y" if defined($run{$_}{DEFAULT_DECODER}); ++ my $r = "N"; $r = "Y" if $run{$_}{TAGS}{READ} == 1; ++ my $w = "N"; $w = "Y" if $run{$_}{TAGS}{WRITE} == 1; ++ ++ my $enc = ''; $enc = $run{$_}{DEFAULT_ENCODER} if defined($run{$_}{DEFAULT_ENCODER}); ++ my $dec = ''; $dec = $run{$_}{DEFAULT_DECODER} if defined($run{$_}{DEFAULT_DECODER}); ++ ++ printf("%-9s %-3s %-3s %-15s %-18s %-10s %s\n", $_, $e, $d, $enc, $dec, $r, $w); ++ ++ ++$enc_count if $enc ne ''; ++ ++$dec_count if $dec ne ''; ++ ++ } ++ ++ say "\n$lang{enc_fmts} $enc_count --- $lang{dec_fmts} $dec_count\n"; ++ ++} ++ ++# show encoders for output format ++sub show_encoders { ++ say "\n$name - $version\n\n$lang{show_encoders}: $my_encoder\n"; ++ foreach (sort(keys %{$run{$my_encoder}{ENCODER}})) { ++ print "$_ -> "; ++ print "installed" if `which $_ 2>/dev/null`; ++ print "not found" if not `which $_ 2>/dev/null`; ++ print " (default)" if $_ eq $run{$my_encoder}{DEFAULT_ENCODER}; ++ say ''; ++ } ++ say ''; ++} ++ ++# show decoders for input format ++sub show_decoders { ++ say "\n$name - $version\n\n$lang{show_decoders}: $my_decoder\n"; ++ foreach (sort(keys %{$run{$my_decoder}{DECODER}})) { ++ print "$_ -> "; ++ print "installed" if `which $_ 2>/dev/null`; ++ print " (default)" if $_ eq $run{$my_decoder}{DEFAULT_DECODER}; ++ say ''; ++ } ++ say ''; ++} ++ ++################# ++# cd ripping... # ++################# ++ ++# get total number of tracks from cdparanoia query ++sub get_total_tracks { ++ ++ open(CDINFO, "cdparanoia -Q 2>&1 |") or die "can't fork: $!\n"; ++ my @cdquery = <CDINFO>; ++ close(CDINFO); ++ ++ my $fmt_tracks = $cdquery-3; ++ $fmt_tracks =~ s/\s//g; ++ ++ my @ttracks = split(/\./, $fmt_tracks); ++ ++ return "$ttracks0"; ++ ++} ++ ++my (%cd, %ripconfig, @cdtrack, $track_total); ++ ++# setup the cddb config ++sub get_cddb_config { ++ ++ $config{USE_CDDB} = 0 && return if $nocddb; ++ ++ $config{CDDB_INPUT} = 0 if $noinput; ++ ++ $ripconfig{CDDB_HOST} = $config{CDDB_HOST}; ++ $ripconfig{CDDB_PORT} = $config{CDDB_PORT}; ++ $ripconfig{CDDB_MODE} = $config{CDDB_MODE}; ++ $ripconfig{DEVICE} = $device; ++ $ripconfig{CDDB_INPUT} = $config{CDDB_INPUT}; ++ ++ print $ripconfig{CDDB_HOST}; ++ ++ %cd = get_cddb(\%ripconfig); ++ ++ if (not $cd{title}) { ++ pnotice("no_cddb","",2); ++ $config{USE_CDDB} = 0; ++ } ++ else { ++ @cdtrack = @{$cd{track}}; ++ $track_total = $cd{tno}; ++ } ++ ++} ++ ++# check to see if a disc is present ++sub query_disc { ++ system("cdparanoia -q -d $device -Q > /dev/null 2>&1"); ++ perror("no_disc","$device") if $? > 0; ++} ++ ++# set tag info from cddb ++sub tag_track { ++ ++ my $tno = shift; ++ ++ $tag_name{artist} = $cd{artist} if $cd{artist}; ++ $tag_name{title} = $cdtrack$tno-1 if $cdtrack$tno-1; ++ $tag_name{genre} = $cd{cat} if $cd{cat}; ++ $tag_name{track} = $tno; ++ $tag_name{album} = $cd{title} if $cd{title}; ++ $tag_name{year} = $cd{year} if $cd{year}; ++ $tag_name{comment} = ''; ++ ++} ++ ++# process and convert ripped track ++sub rip_cd { ++ ++ my ($on,$tno) = @_; ++ ++ $outdir = $ENV{HOME}; ++ $to =~ tr/A-Z/a-z/; ++ ++ get_visual_opts($to,$out_dir) if $gui and not defined($first_run); ++ $first_run = 1; ++ pnotice("ripping_track","$tno",2); ++ ++ $on =~ s/\//_/g; ++ ++ say "\ncdparanoia -d $device $tno $on.wav\n" if $dryrun; ++ system("cdparanoia -d $device $tno \"$on.wav\" >/dev/null 2>&1") if not $dryrun; ++ ++ if ($to !~ /wav/i) { ++ ++ push(@file, "$on.wav"); ++ tag_track($tno); ++ proc_input(); ++ clear_tag_hash(); ++ undef(@file); ++ unlink("$on.wav") if not $dryrun; ++ pnotice("removed_tmp","$on.wav",2) if $verbose; ++ ++ } ++} ++ ++# rip selected tracks or all from disc ++sub proc_cd { ++ ++ perror("no_app","cdparanoia") if not `which cdparanoia 2>/dev/null`; ++ ++ query_disc(); ++ get_cddb_config(); ++ ++ my $total_tracks = get_total_tracks(); ++ ++ if ($rip eq "all") { ++ ++ if ($config{USE_CDDB} ne 1) { ++ ++ for(my $i=1;$i<=$total_tracks;$i++) { ++ rip_cd($i, $i); ++ } ++ ++ } elsif ($config{USE_CDDB} eq 1) { ++ ++ my $n = 1; ++ ++ foreach my $i (@cdtrack) { ++ ++ my $out_string = $nscheme; ++ ++ chomp($cdtrack$n-1); ++ ++ $out_string =~ s/%ar/$cd{artist}/; ++ $out_string =~ s/%ti/$cdtrack$n-1/; ++ $out_string =~ s/%tr/$n/; ++ $out_string =~ s/%ab/$cd{title}/; ++ $out_string =~ s/%yr/$cd{year}/; ++ ++ rip_cd($out_string, $n); ++ ++ ++$n; ++ } ++ } ++ ++ } else { ++ ++ my @tracks = split(/,/, $rip); ++ ++ foreach my $i (@tracks) { ++ ++ next if $i > $total_tracks or $i < 1; ++ ++ my $out_string = $nscheme; ++ ++ $out_string =~ s/%ar/$cd{artist}/; ++ $out_string =~ s/%ti/$cdtrack$i-1/; ++ $out_string =~ s/%tr/$i/; ++ $out_string =~ s/%ab/$cd{title}/; ++ $out_string =~ s/%yr/$cd{year}/; ++ ++ rip_cd($out_string, $i) if $config{USE_CDDB} == 1; ++ rip_cd($i, $i) if $config{USE_CDDB} == 0; ++ } ++ } ++} ++ ++# get/print cddb information from disc ++sub cdinfo { ++ ++ query_disc(); ++ get_cddb_config(); ++ ++ say "$name - $version\n"; ++ ++ say "Artist = $cd{artist}"; ++ say "Album = $cd{title}"; ++ say "Genre = $cd{genre}"; ++ say "Tracks = $cd{tno}"; ++ say "Year = $cd{year}\n"; ++ ++ my $n = 1; ++ ++ foreach (@cdtrack) { ++ say "Track $n: $_"; ++ ++$n; ++ } ++ ++ exit(0); ++} ++ ++# version / license information ++sub version { ++ ++say " ++$name - $version ++ ++Copyright (C) 2005-2017 Philip Lyons ++ ++This is free software. You may redistribute copies of it under the terms of ++the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. ++There is NO WARRANTY, to the extent permitted by law. ++"; ++ ++} ++ ++# help & longhelp menu ++sub help_menu { ++ ++say "\n$name - $version"; ++ ++say " ++-t, --to $lang{to} ++-r, --recursive $lang{recursive} ++-p, --preserve $lang{preserve} ++-f, --formats $lang{formats} ++-o, --only $lang{only} ++-k, --keep $lang{keep} ++-j, --jobs $lang{jobs} ++-h, --help $lang{help} ++-l, --longhelp $lang{longhelp} ++-v, --verbose $lang{verbose} ++"; ++ ++say "$lang{user_opts} ++ ++--defopts $lang{defopts} ++--eopts $lang{eopts} ++--dopts $lang{dopts} ++--nopts $lang{nopts} ++--outfile $lang{outfile} ++--outdir $lang{outdir} ++--dryrun $lang{dryrun} ++--overwrite $lang{overwrited} ++--normalize $lang{normalize} ++--delete $lang{delete} ++--encoder $lang{encoder} ++--decoder $lang{decoder} ++--version $lang{version} ++ ++$lang{enc_opts} ++ ++--bitrate $lang{bitrate} ++--freq $lang{freq} ++--channels $lang{channels} ++--effect $lang{effect} ++--fcomp $lang{fcomp} ++--acomp $lang{acomp} ++--oggqual $lang{oggqual} ++--spxqual $lang{spxqual} ++--aacqual $lang{aacqual} ++--mpcqual $lang{mpcqual} ++--ofmode $lang{ofmode} ++--ofopt $lang{ofopt} ++--bratio $lang{bratio} ++--bquanl $lang{bquanl} ++--bpsize $lang{bpsize} ++ ++$lang{tag_opts} ++ ++--artist $lang{artist} ++--title $lang{title} ++--track $lang{track} ++--year $lang{year} ++--album $lang{album} ++--genre $lang{genre} ++--comment $lang{comment} ++--taginfo $lang{taginfo} ++ ++$lang{tag_usage} ++ ++$lang{rip_opts} ++ ++--rip $lang{rip} ++--nocddb $lang{nocddb} ++--noinput $lang{noinput} ++--nscheme $lang{nscheme} ++--cdinfo $lang{cdinfo} ++--device $lang{device} ++ ++$lang{rip_usage}" if $longhelp; ++ ++say "\n$lang{usage}\n"; ++ ++} ++ ++sub load_module { ++ my ($file) = @_; ++ my $return; ++ unless($return = do $file) { ++ perror("opening_file","$file: $@ $!") if $@ or !defined($return) or not !$return; ++ } ++} ++ ++sub import_module { ++ my ($format_ref) = @_; ++ my $format_name=$format_ref->{NAME}; ++ $run{$format_name} = $format_ref; ++} ++ ++# load all user modules ++sub load_user_modules { ++ my @imported_mods; ++ opendir(DIR, "$mod_dir") or perror("opening_dir","$mod_dir: $!"); ++ foreach (readdir(DIR)) { ++ load_module("$mod_dir/$_") if $_ !~ /^\./; ++ push(@imported_mods, $_) if $_ !~ /^\./; ++ } ++ closedir(DIR); ++ say "$lang{imported} @imported_mods"; ++} ++ ++# place files/directories in their respective arrays ++if (@ARGV) { ++ foreach (@ARGV) { ++ if (-f $_) { push(@file,$_); print "$lang{debug} adding $_ to \@file\n" if $debug == 1; } ++ elsif (-d $_) { push(@dir, $_); print "$lang{debug} adding $_ to \@dir\n" if $debug == 1; } ++ else { perror("no_infile","$_"); } ++ } ++} ++ ++load_user_modules() if $config{IMPORTM} == 1; ++ ++if ($to and @ARGV and not $rip) { proc_input(); } ++ ++elsif ($to and $rip) { proc_cd(); } ++elsif ($my_encoder and not $to) { show_encoders(); } ++elsif ($my_decoder and not $to) { show_decoders(); } ++elsif ($verinfo) { version(); } ++elsif ($longhelp) { help_menu(); } ++elsif ($formats) { show_formats(); } ++elsif ($cdinfo) { cdinfo(); } ++elsif ($taginfo and not $to) { show_taginfo(); } ++elsif ($title or $track or $artist or $album or $comment or $year or $genre) { write_user_tags(); } ++ ++else { help_menu(); } ++ ++__END__ ++ ++=head1 NAME ++ ++pacpl - Perl Audio Converter, a multi purpose converter/ripper/tagger ++ ++=head1 SYNOPSIS ++ ++pacpl --to <format> <options> file(s)/directory(s) ++ ++=head1 DESCRIPTION ++ ++Perl Audio Converter ++ ++A Linux CLI tool for converting multiple audio types from one format to another. ++ ++It supports the following audio formats: ++ ++======================================== ++ ++3G2, 3GP, 8SVX, AAC, AC3, ADTS, AIFF, AL, AMB, AMR, APE, AU, ++AVR, BONK, CAF, CDR, CVU, DAT, DTS, DVMS, F32, F64, FAP, FLA, ++FLAC, FSSD, GSRT, HCOM, IMA, IRCAM, LA, MAT, MAUD, MAT4, MAT5, ++M4A, MP2, MP3, MP4, MPC, MPP, NIST, OFF, OFR, OFS, OPUS, OGA, ++OGG, PAF, PRC, PVF, RA, RAM, RAW, RF64, SD2, SF, SHN, SMP, SND, ++SOU, SPX, SRN, TAK, TTA, TXW, VOC, VMS, VQF, W64, WAV, WMA, ++and WV. ++ ++It can also extract audio from the following video extensions: ++ ++============================================================== ++ ++RM, RV, ASF, DivX, MPG, MKV, MPEG, AVI, MOV, OGM, OGV, QT, VCD, ++SVCD, M4V, NSV, NUV, PSP, SMK, VOB, FLV, WEBM and WMV. ++ ++Parallel Processing, a CD ripping function with CDDB support, batch conversion, ++tag preservation for most supported formats, independent tag reading & writing, ++service menus for KDE Dolphin/Konqueror, GNOME Nautilus script, and action ++scripts for Nemo/Thunar are also provided. ++ ++=head1 OPTIONS ++ ++B<-t, --to> I<format> ++ ++set encode format for the input file(s) or directory(ies). you can see a ++complete list of supported encode formats by using the B<--formats> option. ++ ++B<-r, --recursive> ++ ++recursively scan and convert input folder(s) to destination format. ++ ++B<-p, --preserve> ++ ++when recursively converting a directory, preserve the input folders directory ++structure in the specified output directory. such as: ++ ++pacpl --to ogg -r -p /home/mp3s --outdir /home/oggs ++ ++in the example above, let's assume the directory structure was: ++ ++=over 21 ++ ++=item /home/mp3s/Alternative ++ ++=item /home/mp3s/Alternative/New ++ ++=item /home/mp3s/Rap ++ ++=item /home/mp3s/Country ++ ++=item /home/mp3s/Techno/ ++ ++=back ++ ++the output directory will now contain: ++ ++=over 4 ++ ++=item /home/oggs/Alternative ++ ++=item /home/oggs/Alternative/New ++ ++=item /home/oggs/Rap ++ ++=item /home/oggs/Country ++ ++=item /home/oggs/Techno ++ ++=back ++ ++with all files in each sub-folder converted to ogg. ++ ++B<-o, --only> I<format> ++ ++only convert files matching extension. this option is useful when you have ++a directory or batch of files with mixed audio types and only need to ++convert one specific type. ++ ++B<-k, --keep> ++ ++do not re-encode files with extensions matching the destination extension. ++instead...copy them to the output folder, or skip to the next file. ++ ++B<-j, --jobs> ++ ++number of simultanious jobs to run at once. the default limit ++is set to 4 in pacpl.conf. You can modify this value on the fly ++using --jobs=<num> or set it perminately in the configuration file ++ ++=over 4 ++ ++=item B<-f, --formats> show a list of supported encode/decode formats. ++ ++=item B<-h, --help> show the short help menu. ++ ++=item B<-l, --longhelp> display the complete list of options. ++ ++=item B<--version> show version and licensing information. ++ ++=back ++ ++=head1 USER OPTIONS ++ ++B<--defopts> I<1/0> ++ ++to turn off default encoder options use --defopts 0. this option gives you ++more control when using the --eopts command. ++ ++defopts is set to 1 by default. you can also toggle this option in ++/etc/pacpl/pacpl.conf. ++ ++B<--eopts> I<options> ++ ++this option allows you to use encoder options not implemented by pacpl. ++an example would be: ++ ++pacpl --to mp4 --eopts="-c 44100 -I 1,2" YourFile.mp3 ++ ++B<--dopts> I<options> ++ ++this option allows you to use decoder options not implemented by pacpl. ++an example would be: ++ ++pacpl --to mpc --dopts="--start 60" YourFile.ogg ++ ++B<--outfile> I<name> ++ ++set the output file name to I<name>. ++ ++B<--outdir> I<directory> ++ ++place all encoded files in I<directory>. ++ ++B<--dryrun> ++ ++show what would be done without actually converting anything. this is a ++good way to trouble shoot, or to see what would be done without actually ++touching your files. ++ ++B<--overwrite> ++ ++replace the output file if it already exists. ++ ++B<--normalize> ++ ++adjusts volume levels of audio files. ++ ++B<--nopts> I<options> ++ ++this allows you to specify normalize options not implemented by pacpl ++ ++B<--delete> ++ ++remove source/input file after the conversion process has finished. ++ ++B<--encoder> I<encoder> ++ ++specify an alternate encoder for the selected output file(s) ++ ++you can see a list of supported encoders by using the following: ++ ++pacpl --encoder I<format> ++ ++B<--decoder> I<decoder> ++ ++specify an alternate decoder for the selected input file(s) ++ ++you can see a list of supported decoders by using the following: ++ ++pacpl --decoder I<format> ++ ++B<-v, --verbose> ++ ++show detailed information about the encoding process and what's actually ++being done. ++ ++=head1 ENCODER OPTIONS ++ ++B<--bitrate> I<num> ++ ++set the bitrate to I<num>. default is 128. this option does not apply ++to all formats. ++ ++B<--freq> I<num> ++ ++set the frequency to I<num>. default is 44100. this option does not apply ++to all formats. ++ ++B<--channels> I<num> ++ ++set the number of audio channels in the output file to I<num>. this option ++does not apply to all formats. ++ ++B<--effect> I<str> ++ ++see B<sox>(1). this option only applies to the following: ++ ++AIFF, AU, SND, RAW, VOC, SMP, AVR, and CDR ++ ++B<--fcomp> I<num> ++ ++set flac compression level to I<num>. fastest -0, highest -8, default -2 ++ ++=over 4 ++ ++=item 1 = fast ++ ++=item 2 = simple ++ ++=item 3 = medium (default) ++ ++=item 4 = high ++ ++=item 5 = extra high, ++ ++=back ++ ++B<--acomp> I<num> ++ ++set ape compression level to I<num>. ++ ++=over 4 ++ ++=item 1000 = fast ++ ++=item 2000 = normal ++ ++=item 3000 = high (default) ++ ++=item 4000 = extra high ++ ++=item 5000 = insane ++ ++=back ++ ++B<--oggqual> I<num> ++ ++set ogg quality level to I<num>. -1, very low and 10 very high, default 3 ++ ++B<--spxqual> I<num> ++ ++set speex quality level to I<num>. 0-10, default 8 (use --bitrate <num> when using ffmpeg/avconv as encoder) ++ ++B<--aacqual> I<num> ++ ++set aac, mp4, m4a, or m4b quality level to I<num>. default 300 ++ ++B<--mpcqual> I<str> ++ ++set mpc/mpp quality level to I<str>. ++ ++=over 4 ++ ++=item thumb low quality/internet, (typ. 58... 86 kbps) ++ ++=item radio medium (MP3) quality, (typ. 112...152 kbps - default) ++ ++=item standard high quality (dflt), (typ. 142...184 kbps) ++ ++=item xtreme extreme high quality, (typ. 168...212 kbps) ++ ++=back ++ ++B<--ofmode> I<str> ++ ++set off/ofr/ofs compression mode to I<str>. normal, extra, and extranew modes ++are recommended for general use. available options are: ++ ++=over 4 ++ ++=item fast ++ ++=item normal (default) ++ ++=item high ++ ++=item extra ++ ++=item best ++ ++=item highnew ++ ++=item extranew ++ ++=item bestnew ++ ++=back ++ ++B<--ofopt> I<str> ++ ++set off/ofr/ofs optimization level to I<str>. ++ ++specify the optimization level in the engine. In order to achieve ++optimal compression at all sample types, sample rates, and audio ++content, the core compression engine has the possibility to find the ++optimal values for its parameters, at the cost of slightly increased ++compression time only. The default recommended value is fast. ++do not use normal (or even high or best) for this parameter unless ++encoding time does not matter and you want to obtain the smallest ++possible file for a given compression mode. The difference between ++the optimize levels fast and best (which is up to three times slower ++than fast) is very small, generally under 0.05%, but may be also ++larger in some rare cases. Note that the none optimize level is ++forced by the encoder to fast optimize level for the extra, best, ++highnew, extranew, and bestnew modes. ++ ++available options are: ++ ++=over 4 ++ ++=item none ++ ++=item fast (default) ++ ++=item normal ++ ++=item high ++ ++=item best ++ ++=back ++ ++B<--bratio> I<num> ++ ++set bonk down sampling ratio. default 2 ++ ++B<--bquanl> I<num> ++ ++set bonk quantanization level. default 1.0 ++ ++B<--bpsize> I<num> ++ ++set bonk predictor size. default 128 ++ ++=head1 TAGGING OPTIONS ++ ++B<note:> ++ ++tagging outside of the encoding process can only be performed on the ++following audio types: ++ ++=over 4 ++ ++=item MP3 ++ ++=item OGG ++ ++=item FLA ++ ++=item FLAC ++ ++=back ++ ++B<--artist> I<str> ++ ++set artist information to I<str>. ++ ++B<--title> I<str> ++ ++set title information to I<str>. ++ ++B<--track> I<num> ++ ++set track information to I<num>. ++ ++B<--year> I<num> ++ ++set year/date information to I<num>. ++ ++B<--album> I<str> ++ ++set album information to I<str>. ++ ++B<--genre> I<str> ++ ++set genre information to I<str>. ++ ++B<--comment> I<str> ++ ++set comment information to I<str>. ++ ++B<--taginfo> I<file> ++ ++show tagging information for I<file>. multiple files can be specified ++at once. ++ ++=head1 RIPPING OPTIONS ++ ++B<--rip> I<num/all> ++ ++rip selected tracks separated by comma or all from current disc. ++ ++=over 4 ++ ++=item pacpl --rip all --to flac ++ ++=item pacpl --rip 1,3,9,15 --to flac ++ ++=back ++ ++B<--nocddb> ++ ++disable cddb. use this option if you do not want tagging based on cddb. ++ ++B<--noinput> ++ ++disable cddb interactivity. this is enabled by default. ++ ++B<--nscheme> I<str> ++ ++set naming scheme to I<str>. default is %ar - %ti ++ ++available options are: ++ ++=over 4 ++ ++=item %ar = artist ++ ++=item %ti = song title ++ ++=item %tr = track ++ ++=item %yr = year ++ ++=item %ab = album ++ ++=back ++ ++B<eg:> --nscheme="(%tr)-%ti" ++ ++B<--device> I<device> ++ ++set device to I<device>. default is /dev/dvd ++ ++B<--cdinfo> ++ ++show cddb information for current disc. ++ ++=head1 SEE ALSO ++ ++=over 4 ++ ++=item B<sox>(1) B<ffmpeg>(1) B<lame>(1) B<oggenc>(1) B<oggdec>(1) ++ ++=item B<flac>(1) B<shorten>(1) B<faac>(1) B<faad>(1) B<mpcenc>(1) ++ ++=item B<mpcdec>(1) B<mplayer>(1) B<speexenc>(1) B<speexdec>(1) ++ ++=item B<sndfile-convert>(1) B<normalize>(1) B<cdparanoia>(1) ++ ++=item B<opusenc>(1) B<opusdec>(1) B<wavpack>(1) B<ffmpeg>(1) ++ ++=item B<mplayer>(1) B<avconv>(1) ++ ++=back ++ ++=head1 BUGS ++ ++Report all bugs to Philip Lyons (vorzox@gmail.com) ++ ++=head1 LICENSING ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 3 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++=head1 AUTHOR ++ ++Copyright (C) 2005-2017 Philip Lyons (vorzox@gmail.com) +-- +2.7.4 +
View file
pacpl-6.1.0.tar.gz/patches/add_alac_decoder_m4a.patch
Added
@@ -0,0 +1,16 @@ +diff --git a/pacpl.in b/pacpl.in +index 0f862f9..611bb2d 100644 +--- a/pacpl.in ++++ b/pacpl.in +@@ -1403,6 +1403,11 @@ my $pm = Parallel::ForkManager->new($jobs); + DSTR => sub { "-vc null -vo null -ao pcm:file=%o %i" }, + }, + ++ 'alac-decoder' => { ++ NAME => "alac-decoder", ++ DSTR => sub { "$dopts -f %o %i" }, ++ }, ++ + }, + + ESTR => sub { "$eopts -w -q $aacqual %i -o %o" },
View file
pacpl-6.1.0.tar.gz/patches/fix_config_value_0.patch
Added
@@ -0,0 +1,13 @@ +diff --git a/pacpl.in b/pacpl.in +index 5c28750..436e140 100644 +--- a/pacpl.in ++++ b/pacpl.in +@@ -175,7 +175,7 @@ if ($conf_file and -e $conf_file) { + foreach (@conf_opts) { + chomp; + my ($k, $v) = split(/\s*=\s*/); +- $config{$k} = $v if exists($config{$k}) and $v; ++ $config{$k} = $v if exists($config{$k}) and length($v); + say "$lang{debug} $k = $v" if $debug == 1 and exists($config{$k}); + } + }
View file
pacpl-6.1.0.tar.gz/patches/fix_decoding_string_ffmpeg.patch
Added
@@ -0,0 +1,13 @@ +diff --git a/pacpl.in b/pacpl.in +index 436e140..68619f9 100644 +--- a/pacpl.in ++++ b/pacpl.in +@@ -2209,7 +2209,7 @@ foreach my $fork (@ffmpeg_forks) { + $run{$codec}{DEFAULT_DECODER} = $fork; + $run{$codec}{ENCODER}{$fork}{NAME} = $fork; + $run{$codec}{DECODER}{$fork}{NAME} = $fork; +- $run{$codec}{DECODER}{$fork}{DSTR} = sub {"-y %i $dopts %o"}; ++ $run{$codec}{DECODER}{$fork}{DSTR} = sub {"-y -i %i $dopts %o"}; + $run{$codec}{ENCODER}{$fork}{ESTR} = sub {"-y -i %i $eopts -ab $bitrate.k -ar $freq -ac $channels %o"}; + $run{$codec}{TAGS}{READ} = 0; + $run{$codec}{TAGS}{WRITE} = 0;
View file
pacpl-6.1.0.tar.gz/patches/fix_destination_always_overwritten.patch
Added
@@ -0,0 +1,13 @@ +diff --git a/pacpl.in b/pacpl.in +index 341e680..3c16141 100644 +--- a/pacpl.in ++++ b/pacpl.in +@@ -2343,7 +2343,7 @@ sub proc_files { + $encoder = $run{$to}{DEFAULT_ENCODER} if not $my_encoder; + $decoder = $run{$if}{DEFAULT_DECODER} if not $my_decoder; + +- if (-e "$file.$to" and not $overwrite) { ++ if (-e "$dir/$file.$to" and not $overwrite) { + pnotice("overwrite","$file.$to",1); + $total_failed++; + next;
View file
pacpl-6.1.0.tar.gz/patches/fix_wma_tag_names.patch
Added
@@ -0,0 +1,25 @@ +diff --git a/pacpl.in b/pacpl.in +index 5b9f7c2..341e680 100644 +--- a/pacpl.in ++++ b/pacpl.in +@@ -2965,13 +2965,13 @@ when (/^ape$|^mpc$|^mpp$|^wv$/) { + when (/^wma$/) { + my $wma_tag = $tag_module->scan_tags($in_file)->{tags}; + +- $tag_name{title} = $wma_tag->{TITLE} if $wma_tag->{TITLE}; +- $tag_name{track} = $wma_tag->{TRACKNUMBER} if $wma_tag->{TRACKNUMBER}; +- $tag_name{artist} = $wma_tag->{AUTHOR} if $wma_tag->{AUTHOR}; +- $tag_name{album} = $wma_tag->{ALBUMTITLE} if $wma_tag->{ALBUMTITLE}; +- $tag_name{comment} = $wma_tag->{DESCRIPTION} if $wma_tag->{DESCRIPTION}; +- $tag_name{year} = $wma_tag->{YEAR} if $wma_tag->{YEAR}; +- $tag_name{genre} = $wma_tag->{GENRE} if $wma_tag->{GENRE}; ++ $tag_name{title} = $wma_tag->{Title} if $wma_tag->{Title}; ++ $tag_name{track} = $wma_tag->{'WM/TrackNumber'} if $wma_tag->{'WM/TrackNumber'}; ++ $tag_name{artist} = $wma_tag->{'WM/AlbumArtist'} if $wma_tag->{'WM/AlbumArtist'}; ++ $tag_name{album} = $wma_tag->{'WM/AlbumTitle'} if $wma_tag->{'WM/AlbumTitle'}; ++ $tag_name{comment} = $wma_tag->{'WM/Description'} if $wma_tag->{'WM/Description'}; ++ $tag_name{year} = $wma_tag->{'WM/Year'} if $wma_tag->{'WM/Year'}; ++ $tag_name{genre} = $wma_tag->{'WM/Genre'} if $wma_tag->{'WM/Genre'}; + + return 0; + }
View file
pacpl-5.1.0.tar.gz/plugins/gnome/nautilus/PACPL-Convert -> pacpl-6.1.0.tar.gz/plugins/gnome/nautilus/PACPL-Convert
Changed
@@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copywrite (C) Philip Lyons 2013-2017 (vorzox@gmail.com) +# Copywrite (C) Philip Lyons 2013-2018 (vorzox@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by
View file
pacpl-5.1.0.tar.gz/plugins/gnome/nemo/PACPL-Convert -> pacpl-6.1.0.tar.gz/plugins/gnome/nemo/PACPL-Convert
Changed
@@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copywrite (C) Philip Lyons 2013-2017 (vorzox@gmail.com) +# Copywrite (C) Philip Lyons 2013-2018 (vorzox@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by
View file
pacpl-5.1.0.tar.gz/plugins/gnome/thunar/PACPL-Convert -> pacpl-6.1.0.tar.gz/plugins/gnome/thunar/PACPL-Convert
Changed
@@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copywrite (C) Philip Lyons 2013-2017 (vorzox@gmail.com) +# Copywrite (C) Philip Lyons 2013-2018 (vorzox@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by
View file
pacpl-5.1.0.tar.gz/plugins/gnome/thunar/PACPL-Konvert -> pacpl-6.1.0.tar.gz/plugins/gnome/thunar/PACPL-Konvert
Changed
@@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copywrite (C) Philip Lyons 2013-2017 (vorzox@gmail.com) +# Copywrite (C) Philip Lyons 2013-2018 (vorzox@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by
View file
pacpl-5.1.0.tar.gz/plugins/kde/PACPL-Konvert -> pacpl-6.1.0.tar.gz/plugins/kde/PACPL-Konvert
Changed
@@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copywrite (C) Philip Lyons 2013-2017 (vorzox@gmail.com) +# Copywrite (C) Philip Lyons 2013-2018 (vorzox@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.