| Server IP : 216.92.14.13 / Your IP : 216.73.216.171 Web Server : Apache System : Linux vps4089.pairvps.com 5.15.0-190-generic #200-Ubuntu SMP Fri Aug 7 15:06:04 UTC 2026 x86_64 User : rmlac2fmr ( 1040637) PHP Version : 8.2.32 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/local/bin/ |
Upload File : |
#!/usr/local/bin/perl -w
my $RCS_Id = '$Id: ls2nocddb.pl,v 1.12 2004/08/13 13:42:27 jv Exp $ ';
# Author : Johan Vromans
# Created On : Tue Sep 15 15:59:04 1992
# Last Modified By: Johan Vromans
# Last Modified On: Fri Aug 13 15:41:52 2004
# Update Count : 115
# Status : Unknown, Use with caution!
################ Common stuff ################
use strict;
# Package or program libraries, if appropriate.
# $LIBDIR = $ENV{'LIBDIR'} || '/usr/local/lib/sample';
# use lib qw($LIBDIR);
# require 'common.pl';
# Package name.
my $my_package = 'Sciurix';
# Program name and version.
my ($my_name, $my_version) = $RCS_Id =~ /: (.+).pl,v ([\d.]+)/;
# Tack '*' if it is not checked in into RCS.
$my_version .= '*' if length('$Locker: $ ') > 12;
use FindBin;
use lib $FindBin::Bin;
################ Command line parameters ################
use Getopt::Long 2.13;
# Command line options.
my $length = -1; # calculate length of tracks
my $verbose = 0; # verbose processing
my $print = 0; # send to stdout
# Development options (not shown with -help).
my $debug = 0; # debugging
my $trace = 0; # trace (show process)
my $test = 0; # test mode.
# Process command line options.
app_options();
# Post-processing.
$trace |= ($debug || $test);
################ Presets ################
my $TMPDIR = $ENV{TMPDIR} || $ENV{TEMP} || '/usr/tmp';
################ The Process ################
use Cwd qw(abs_path);
foreach my $dir ( @ARGV ) {
unless ( -d $dir ) {
warn("$dir: not a directory -- skipped\n");
next;
}
if ( -s "$dir/.nocddb" && !$print ) {
warn("$dir/.nocddb: exists -- directory skipped\n");
next;
}
$dir =~ s;/+$;;;
my @a = split('/', abs_path($dir));
my ($artist, $album) = ("","");
if ( @a >= 2 ) {
$artist = neat($a[-2]);
$album = neat($a[-1]);
}
my @files = sort map { $1 if /([^\/]+)\.mp3$/ } glob("$dir/[0-9]*.mp3");
my $fh = *STDOUT;
unless ( $print ) {
open($fh, ">$dir/.nocddb") or die("$dir/.nocddb: $!\n");
}
print $fh ("$artist / $album\n\n");
my $prev = 0;
my @res;
my $maxlen = 40;
foreach my $file ( @files ) {
my $mmss = 0;
$mmss = getlength("$dir/$file.mp3") if $length;
$file =~ s/^(\d+)_(-_)?//;
$prev++;
if ( $1 - $prev > 5 ) {
warn("Too many 'Unknown's, suppressing\n");
$prev = $1;
}
my $t;
while ( $prev < $1 ) {
$t = sprintf (" %2d. %s", $prev, "Unknown");
$maxlen = length($t) if $maxlen < length($t);
push(@res, [ $t, 0 ]);
$prev++;
}
$t = sprintf (" %2d. %s", $1, neat($file));
$maxlen = length($t) if $maxlen < length($t);
push(@res, [ $t, $mmss ]);
}
foreach ( @res ) {
my ($t, $mmss) = @$_;
my $l = length($t);
unless ( $mmss ) {
print $fh ($t, "\n");
next;
}
$t .= "\t";
$l = ($l & 0xf8) + 7;
while ( $l <= $maxlen ) {
$t .= "\t";
$l += 8;
}
print $fh ($t, $mmss, "\n");
}
print $fh ("\nGenerated by $my_name $my_version on ".
localtime(time)."\n");
close($fh);
}
exit 0;
################ Subroutines ################
sub neat {
local($_) = shift;
s/__/:_/g;
s/;_/_\/_/g;
s/_s_/'s_/gi;
s/_m_/'m_/gi;
s/(you|we|they)_re_/$1're_/gi;
s/_/ /g;
s/\s+/ /g;
s/(^|-|\s|\(|\[)(.)/$1.ucfirst($2)/eg;
$_;
}
sub getlength {
my ($file) = @_;
my $mmss;
if ( $length < 0 ) {
$mmss = getlength_mi($file);
return $mmss if defined $mmss;
}
$mmss = getlength_af($file);
return $mmss if defined $mmss;
$length = 0;
return " -:--";
}
sub getlength_mi {
my ($file) = @_;
unless ( eval { require MP3::Info; } ) {
warn("Cannot load MP3::Info\n");
return undef;
}
import MP3::Info;
return " -:--" unless -f $file;
my $f = get_mp3info($file);
return " -:--" unless $f;
sprintf("%2d:%02d", $f->{MM}, $f->{SS});
}
sub getlength_af {
my ($file) = @_;
unless ( eval { require MPEG::Audio::Frame; } ) {
warn("Cannot load MPEG::Audio::Frame\n");
return undef;
}
return " -:--" unless -f $file;
my $f;
unless ( open($f, '<', $file) ) {
warn("$file: $!\n");
return " -:--";
}
my $length;
my $frames = 0;
while ( my $frame = MPEG::Audio::Frame->read($f)) {
$length += $frame->seconds;
}
return dptime_formatted($length);
}
sub dptime_formatted {
my ($t) = (@_);
$t += 0.5;
$t = int($t);
my $s = $t % 60;
my $m = int($t / 60);
sprintf("%2d:%02d", $m, $s);
}
################ Subroutines ################
sub app_options {
my $help = 0; # handled locally
my $ident = 0; # handled locally
# Process options, if any.
# Make sure defaults are set before returning!
return unless @ARGV > 0;
if ( !GetOptions(
'length!' => \$length,
'ident' => \$ident,
'print' => \$print,
'verbose' => \$verbose,
'trace' => \$trace,
'help|?' => \$help,
'debug' => \$debug,
) or $help )
{
app_usage(2);
}
app_ident() if $ident;
}
sub app_ident {
print STDERR ("This is $my_package [$my_name $my_version]\n");
}
sub app_usage {
my ($exit) = @_;
app_ident();
print STDERR <<EndOfUsage;
Usage: $0 [options] [file ...]
-[no]length [do not] calculate playing time
-help this message
-ident show identification
-verbose verbose information
EndOfUsage
exit $exit if defined $exit && $exit != 0;
}
=head1 NAME
ls2nocddb - produce CDDB::Fake info from a directory
=head1 SYNOPSIS
ls2nocddb [ options ] directory ...
Options:
--[no]length [do not] include length information
--print write to standard output
--verbose more verbose information
--help help message
=head1 DESCRIPTION
This program can generate CDDB::Fake information data from a directory
containing MP3 files.
It requires the directory to be named Artist_Name/Album_Title.
The MP3 files in the directory must be named NN_Track_Title.mp3, where
I<NN> is the track number.
When the package MP3::Info or MPEG::Audio::Frame is available, the
program can add the lengths of the tracks to the generated
information.
For example: Given the directory Jazz/Dick_Onstenk/Dick's_Jazz_Stuff
with the following files:
01_Body_And_Soul.mp3
02_Fly_Me_To_The_Moon.mp3
03_Lover_Man.mp3
04_Freddie_Freeloader.mp3
05_Billie's_Bounce.mp3
06_Softly_As_In_A_Morning_Sunrise.mp3
Then running B<ls2nocddb> with option C<--length> and argument
C<Jazz/Dick_Onstenk/Dick's_Jazz_Stuff>, will create a file named
C<.nocddb> in that directory, with the following contents:
Dick Onstenk / Dick's Jazz Stuff
1. Body And Soul 3:17
2. Fly Me To The Moon 4:20
3. Lover Man 6:16
4. Freddie Freeloader 5:32
5. Billie's Bounce 4:22
6. Softly As In A Morning Sunrise 3:55
Generated by ls2nocddb 1.4 on Fri Jul 25 14:31:41 2003
Note that calculating the length using MPEG::Audio::Frame make tay
some time but it is accurate. Using MP3::Info is fast but depends on
the accuracy of the MP3 header info. For this reason, MP3::Info is
preferred and MPEG::Audio::Frame is only used as a fall back.
Specifying B<--length> forces length calculation with
MPEG::Audio::Frame. B<--nolength> suppresses length calculation.
=head1 SEE ALSO
L<CDDB::File>.
=head1 DEPENDENCIES
C<MP3::Info> or C<MP3::Audio::Frame> (both optional). If installed, the
program can add the lengths of the tracks to the generated
information.
=head1 AUTHOR
Johan Vromans <jvromans@squirrel.nl>
=head1 COPYRIGHT
This programs is Copyright 2003,2004 Squirrel Consultancy.
This program is free software; you can redistribute it and/or modify
it under the terms of the Perl Artistic License or the GNU General
Public License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
=cut