/usr/bin/alfilldb is in audiolink 0.05-1.1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 | #!/usr/bin/perl
# AudioLink
#
# $Id: alfilldb,v 1.33 2003/12/05 12:31:42 amitshah Exp $
#
# alfilldb: Implements the 1st module of the AudioLink software. This
# script crawls through a local collection of music files and
# populates the database based on the tag information found in the
# files.
#
# Copyright (C) 2003, Amit Shah <amitshah@gmx.net>
#
# This file is part of AudioLink.
#
# AudioLink 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; version 2 of the License, or
# (at your option) any later version.
#
# AudioLink 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 AudioLink; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
use DBI;
use MP3::Info;
use File::Find;
use Getopt::Long;
use Ogg::Vorbis::Header;
use Pod::Usage;
# Options
$help = 0; # Display usage information and quit.
$verbose = 0; # Some extra information to be displayed
$no_act = 0; # Do not put the stuff in the database
$prompt = 0; # Prompt for user input if there isn't enf info in ID3 or Vorbis
$dontbug = 0; # Don't prompt if title is NULL. Skips song addition in
# the database in this case.
$addmode = 0; # If the script was invoked as add-only (or w/o add-only
# and upd-only) (new song entries in the datbase
# allowed).
$updmode = 0; # If the script was invoked as upd-only (or w/o add-only
# and upd-only) (update existing entries in the
# database).
$updsong = 0; # Update the song info (ID3 tags for MP3, Vorbis comments).
$mp3_ogg = 0; # 1 = MP3, 2 = Ogg Vorbis
@files; # Multiple pathnames given on the command prompt
$file = ""; # Pathname given on the command prompt to be operated on.
@guessed_parts; # parts of the guessed names: artist, album, etc.
$guessed = 0; # have we shown the 'guesses' list already?
@guessed_nr; # [0]: number of guessed values; [1]: 0+tags
$update_db = 0; # If there exists an entry in the database for any
# song, we need to update it.
# Options for the database
$user = undef;
$password = undef;
$host = "localhost"; # use local mysql server by default
# show the tags read from the file and the db.
sub show_file_tags {
my $counter = $guessed_nr[0];
while ($counter <= $guessed_nr[1]) {
print "\t\t[" . $counter . "] " . $guessed_parts[$counter++] . "\n";
}
}
# guess the values of artist, album, etc. from the filenames
# parameter: the filename
sub guess_guessed {
# just look between '-' for possible values.
@guessed_parts = split(/-/, $_[0]);
my $part;
my $counter = 0;
foreach $part (@guessed_parts) {
# strip leading and trailing whitespaces
$guessed_parts[$counter++] =~ s/(^\s*)(((\w+)(\s*))*(\w+))(\s*$)/$2/;
# 2 stupid bugs above:
# emacs: emacs interprets the ending $) as a variable and
# doesn't have a closing bracket to get the indentation right
# perl: if a space is put between $ and ), the regexp doesn't work
}
}
# print the guessed values of artist, album, etc.
sub show_guessed {
$guessed = 1; # we've shown this list...
my $counter = 0;
unless ($dontbug) {
my $part;
print "NOTE: Use gg<nr> to select a particular entry. Replace <nr> by the corresponding number.\n";
print "\tChoices for fields in the song guessed from the filename are: \n";
foreach $part (@guessed_parts) {
print "\t\t[$counter] $guessed_parts[$counter]\n";
$counter++;
}
$guessed_nr[0] = $counter;
$guessed_parts[$counter++] = $album if $album;
$guessed_parts[$counter++] = $artist if $artist;
$guessed_parts[$counter++] = $title if $title;
$guessed_parts[$counter++] = $comment if $comment;
$guessed_parts[$counter++] = $genre if $genre;
$guessed_parts[$counter++] = $year if $year;
$guessed_parts[$counter++] = $track if $track;
$guessed_nr[1] = $counter - 1;
# show the entries from the db/file tags
print "\tFields from the tags/db:\n";
show_file_tags($guessed_nr[0]);
}
}
# see if the field is empty. If it is, ask for a value.
# parameters: 0: the field to be compared
# 1: the name of the field.
# 2: the pathname of the song.
sub get_input_fields {
my $input;
my $done = 0;
if ($_[0]) {
return $_[0];
}
unless ($guessed) { show_guessed(); }
while (not $done) {
print "Enter " . $_[1] . " for song ". $_[2] . ": ";
chomp($input = <STDIN>);
if ($input =~ /^gg(\d{1,2})$/) {
if ($1 > $guessed_nr[1]) {
print "Invalid input; try again\n";
next;
}
$input = $1;
$done = 1; # valid guessed_field was given
} else {
$done = 2; # valid input was given
}
}
if ($done == 1) {
if ($input <= $guessed_nr[1]) { # if we guessed from file name / tag
$input = $guessed_parts[$input];
}
}
return $input;
}
# the 'find' command executes this subroutine for each file found.
sub wanted {
my $updating = 0; # are we updating an entry?
my $pathname; # stores the absolute file name,
# ie. /path/to/file.ogg
my $dirname; # stores the dirname, ie., /path/to/
my $filename; # stores the filename, ie, file.ogg
my @fileparts; # stores all the parts of a file; ie, /path,
# /to, file.ogg.
my $filname; # filename w/o extension
if ($file) { # filename given on the command-line
$pathname = $file;
} else { # directory name given on the command-line
$pathname = $File::Find::name;
$dirname = $File::Find::dir;
}
@fileparts = split(/\//, $pathname);
$filename = $fileparts[-1]; # get the filename from the last item
# in the array.
if ($filename =~ /\.mp3/i) { # case-insensitive search
$mp3_ogg = 1;
$filname = $`;
}
elsif ($filename =~ /\.ogg/i) {
$mp3_ogg = 2;
$filname = $`;
}
else {
# supporting MP3 and Ogg Vorbis only
return;
}
# the order below is important, as the fields are used in an array
# (indexed by numbers) below. If new fields are added, put them
# after the last field below.
my $statement = qq(SELECT song_nr, song, album,
year, ma1, ma2, fa1, fa2,
composer, lyricist, band, genre,
track, comment
FROM aldb WHERE path = "$pathname");
my $sth = $dbh->prepare($statement);
$sth->execute or die "\n$0: Error: Can't execute search query\n";
if ($sth->rows) {
if($updmode) { # update the entry here
$updating = 1;
} else {
print "Duplicate entry found; not updating\n";
$update_db++;
return;
}
}
if ($mp3_ogg == 1) { # we have an MP3 file to work on
my $tag = get_mp3tag($pathname) or
print "Couldn't get mp3 tag for file $pathname\n";
$artist = $tag->{"ARTIST"};
$title = $tag->{"TITLE"};
$comment = $tag->{"COMMENT"};
$genre = $tag->{"GENRE"};
$year = $tag->{"YEAR"};
$album = $tag->{"ALBUM"};
$track = $tag->{"TRACK"};
}
elsif ($mp3_ogg == 2) { # we have an Ogg file to work on
eval {
$ogg = Ogg::Vorbis::Header->new($pathname);
};
if ($@) {
warn "Couldn't open Vorbis file $pathname; skipping...\n";
return;
}
eval {
foreach my $tag ($ogg->comment_tags) {
foreach my $field ($ogg->comment($tag)) {
if ($tag =~ /title/i) {
$title = $field;
}
elsif ($tag =~ /album/i) {
$album = $field;
}
elsif ($tag =~ /tracknumber/i) {
$track = $field;
}
elsif ($tag =~ /genre/i) {
$genre = $field;
}
elsif ($tag =~ /performer/i) {
$composer = $field;
}
elsif ($tag =~ /lyricist/i) {
$lyricist = $field;
}
elsif ($tag =~ /date/i) {
$year = $field;
}
elsif ($tag =~ /description/i) {
$comment = $field;
}
elsif ($tag =~ /artist/i) {
if (not $artist) {
$artist = $field;
} elsif (not $band) {
$band = $field;
} elsif (not $ma1) {
$ma1 = $field;
} elsif (not $ma2) {
$ma2 = $field;
} elsif (not $fa1) {
$fa1 = $field;
} elsif (not $fa1) {
$fa2 = $field;
}
}
}
}
};
if ($@) {
warn "WARNING: Possibly bad Vorbis file, $pathname; skipping...\n";
return;
}
}
# Now, guess the album, artist, etc. from the filename.
# $filname is filled in when we detected whether we had
# an MP3 or an Ogg Vorbis file.
guess_guessed($filname);
if ($updating) {
my @row = $sth->fetchrow_array;
$title = $row[1]; $album = $row[2]; $year = $row[3];
$ma1 = $row[4]; $ma2 = $row[5]; $fa1 = $row[6]; $fa2 = $row[7];
$composer = $row[8]; $lyricist = $row[9]; $band = $row[10];
$genre = $row[11]; $track = $row[12]; $comment = $row[13];
}
if ($verbose) {
print "About to add/update info from $pathname:\n";
show_guessed();
}
# Inserting title is mandatory 'cos we create links based on song name
unless ($title) {
if ($dontbug) {
print "No-prompt mode and no title found in audio file: skipping entry $pathname\n";
return;
}
$title = get_input_fields($title, "title", $pathname);
}
if ($prompt_mode > 0) { # either of 'basic', 'limited', 'most', 'paranoid' modes
$album = get_input_fields($album, "album", $pathname);
#FIXME: for the artist, accept also if the artist is
# a band, ma1, ma2, fa1, fa2, etc.
$artist = get_input_fields($artist, "artist/band", $pathname);
}
if ($prompt_mode > 1) { # either of 'limited', 'most', 'paranoid' modes
$genre = get_input_fields($genre, "genre", $pathname);
$year = get_input_fields($year, "year", $pathname);
}
if ($prompt_mode > 2) { # either of 'most', 'paranoid' modes
$composer = get_input_fields($composer, "composer", $pathname);
$lyricist = get_input_fields($lyricist, "lyricist", $pathname);
$comment = get_input_fields($comment, "comment", $pathname);
}
if ($prompt_mode > 3) { # 'paranoid' mode
$ma1 = get_input_fields($ma1, "Male Artist-1", $pathname);
$ma2 = get_input_fields($ma2, "Male Artist-2", $pathname);
$fa1 = get_input_fields($fa1, "Female Artist-1", $pathname);
$fa2 = get_input_fields($fa2, "Female Artist-2", $pathname);
$track = get_input_fields($track, "Track", $pathname);
}
unless ($no_act) {
if ($updating) {
$statement = qq(UPDATE aldb SET song = "$title", album = "$album", band = "$artist", genre = "$genre", year = "$year", comment = "$comment", ma1 = "$ma1", ma2 = "$ma2", fa1 = "$fa1", fa2 = "$fa2", composer = "$composer", lyricist = "$lyricist", track = "$track"
WHERE path = "$pathname");
} else {
$statement = qq(INSERT INTO aldb (song, album, band, path, genre, track, year, comment, ma1, ma2, fa1, fa2, composer, lyricist)
VALUES ("$title", "$album", "$artist", "$pathname", "$genre", "$track", "$year", "$comment", "$ma1", "$ma2", "$fa1", "$fa2", "$composer", "$lyricist"));
}
my $sth = $dbh->prepare($statement);
$sth->execute or
print "$0: Couldn't insert data for $pathname\n";
if ($updsong) { # update ID3 in MP3 or comment in Ogg Vorbis
if ($mp3_ogg == 1 ) {
eval {
set_mp3tag($pathname, $title, $artist, $album, $year, $comment, $genre, $track);
};
if ($@) {
warn "WARNING: Couldn't write info back to MP3 ID3 for $pathname.\n\tDo you have write permissions?\n";
}
}
elsif ($mp3_ogg == 2) {
eval {
$ogg->add_comments("ARTIST", $artist) if $artist;
$ogg->add_comments("ARTIST", $ma1) if $ma1;
$ogg->add_comments("ARTIST", $ma2) if $ma2;
$ogg->add_comments("ARTIST", $fa1) if $fa1;
$ogg->add_comments("ARTIST", $fa2) if $fa2;
$ogg->add_comments("ARTIST", $band) if $band;
$ogg->add_comments("TITLE", $title) if $title;
$ogg->add_comments("ALBUM", $album) if $album;
$ogg->add_comments("PERFORMER", $composer) if $composer;
$ogg->add_comments("LYRICIST", $lyricist) if $lyricist;
$ogg->add_comments("DESCRIPTION", $comment) if $comment;
$ogg->add_comments("DATE", $year) if $year;
$ogg->add_comments("GENRE", $genre) if $genre;
$ogg->add_comments("TRACKNUMBER", $track) if $band;
$ogg->write_vorbis;
};
if ($@) {
warn "WARNING: Couldn't write info back to Ogg Vorbis for $pathname.\n\tDo you have write permissions?\n";
}
}
}
}
}
# execution starts here
# check for command-line arguments
if (not @ARGV) {
pod2usage();
}
GetOptions(
'help' => \$help,
'verbose' => \$verbose,
'na|s' => \$no_act,
'prompt=s' => \$prompt,
'no-prompt' => \$dontbug,
'user=s' => \$user,
'pass=s' => \$password,
'host=s' => \$host,
'add-only' => \$addmode,
'upd-only' => \$updmode,
'upd-song' => \$updsong,
'file=s' => \@files
) or pod2usage();
if ($help) {
pod2usage();
}
if (not @ARGV and not $files[0]) {
print "No directory or files specified\n";
pod2usage();
}
if ($prompt =~ /basic/i) {
$prompt_mode = 1;
} elsif ($prompt =~ /limited/i) {
$prompt_mode = 2;
} elsif ($prompt =~ /most/i) {
$prompt_mode = 3;
} elsif ($prompt =~ /paranoid/i) {
$prompt_mode = 4;
} elsif (not $prompt) {
$prompt_mode = 0;
} else {
die "\n$0: Error: Invalid argument \'$prompt\' passed to \'prompt\'.
See the alfilldb(1) man page for more information.\n";
}
if ($addmode and $updmode) {
die "\n$0: Error: Conflicting modes specified, please choose one of "
. " --add-only or --upd-only\n";
}
if ($addmode) {
$updmode = 0;
} elsif ($updmode) {
$addmode = 0;
} else { # no option specified, default to add and update
$addmode = $updmode = 1;
}
$config_file = "$ENV{HOME}/.audiolink/config";
if (-e $config_file) {
open(CONFFILE, $config_file);
# go through the config file
while (<CONFFILE>) {
if (/^\s*user\s*\=+\s*(\w+)/) {
chomp($user = $1) unless $user;
} elsif ( /^\s*pass(word)?\s*=\s*(\w+)/) {
chomp($password = $2) unless $password;
} elsif ( /^\s*host\s*=\s*(\w+)/) {
chomp($host = $1) unless $host;
}
}
} else {
warn "WARNING: config file not found. Use the audiolink script to create one.\n";
}
# connect to the database.
$dbi_string = "DBI:mysql:aldb:$host"; # using MySQL
$dbh = DBI->connect($dbi_string,$user,$password)
or die "\n$0: Error: Could not connect to the database!\
Check the user, password and host fields for the MySQL connection.";
if (not $files[0]) {
foreach $path (@ARGV) {
# Check if the user has given a path format other than an absolute
# path or a path that starts with ~. If yes, bail out.
unless ($path =~ /^~/ or $path =~ /^\//) {
print "WARNING: pathname doesn't consist of an absolute pathname.\n";
print "Skipping entry $path\n";
next;
}
find (\&wanted, $path);
}
} else { # File name specified on the command prompt
foreach $file (@files) {
# perl magic from perl cookbook (1st ed.), recipe 7.3
# expand tilde in filename
$file =~ s{ ^ ~ ( [^/]* ) }
{ $1 ? (getpwnam($1))[7]
: ($ENV{HOME} || $ENV{LOGDIR} || (getpwduid($>))[7])
}ex;
# Check if the user has given a path format other than an absolute
# path or a path that starts with ~. If yes, bail out.
# Since we've already expanded the ~ case, just check against /.
unless ($file =~ /^\//) {
print "WARNING: pathname doesn't consist of an absolute pathname.\n";
print "Skipping entry $file\n";
next;
}
wanted();
}
}
if ($update_db > 0) {
print "$update_db entries in the database were not updated. Use
the --upd-only option to update them.\n";
}
=pod
=head1 NAME
alfilldb - Add/update information of music files in the AudioLink database
=head1 SYNOPSIS
B<alfilldb> [I<OPTION>]... I</path/to/songs/>...
B<alfilldb> [I<OPTION>]... I<--file=/path/to/song>...
=head1 DESCRIPTION
You can use this script to add or update information about your music
files (MP3 or Ogg Vorbis) in the AudioLink database. This information
will be used when you use the L<alsearch(1)> program to search for
particular music. This program is part of the L<audiolink(1)> package.
The path given for the location of individual files or directories
must be an absolute path (paths with ~ are allowed). Relative paths
are not allowed. See the L<"examples"> section for more information.
The user and password options have to be specified to gain access to
the database. See the "I<more information>" section in the
L<audiolink(1)> man page for the various ways in which you can specify
them.
Options that are used repetitively during different invocations of the
program (like the user, password options) may be put in the config
file. See the L<audiolink(1)> man page for details on the config file.
=head1 OPTIONS
=over
=item B<--add-only>
Only the information about new songs will be added to the database;
information about existing songs will not be updated.
=item B<--file>=I<xxx>
Works on just a single file instead of a directory. If this argument
is given, the /path/to/dirs is not considered. (You can have more
than one of these).
=item B<--help>
Brief usage information
=item B<--host>=I<xxx>
Connects to the MySQL server on the given host. Default is localhost.
=item B<--no-prompt>
Don't prompt for anything. Songs which do not have information for
mandatory fields (eg., song title) will not be added to the database.
=item B<--pass>=I<xxx>
Password for accessing the database
=item B<--prompt>=I<xxx>
Prompt for input if there isn't enough information in the song (ID3 or
Ogg Vorbis comments).
The parameters that prompt accepts are:
=over
=item I<basic>
Prompts just for the album name and the artist/band name
=item I<limited>
Prompts for album, artist/band, genre and year fields
=item I<most>
Prompt for all the fields except the Male, Female Artists and the
Track number
=item I<paranoid>
Prompt for all the fields, including Male Artist (1/2), Female Artist
(1/2), Track Number.
=back
=item B<-s>, B<--na>
Simulate or no-act mode: doesn't update the database.
=item B<--upd-only>
Only entries in the database will be updated from the input the user
gives. Make sure you don't use the --no-prompt option along with this
one... else you won't get anything done!
=item B<--upd-song>
Update the tags in the file, ie, ID3 for MP3, comments for Ogg Vorbis.
=item B<--user>=I<xxx>
Username for accessing the database
=item B<--verbose>
Displays some extra information while processing files
=back
=head1 EXAMPLES
=over
=item C<alfilldb --add-only /home/user/tmp/songs/>
This invocation will scan the /home/user/tmp/songs directory
recursively for new songs only. Songs already existing in the database
will not be considered.
=item C<alfilldb --upd-only --prompt=most ~/tmp/songs/>
This invocation will scan the $(HOME)/tmp/songs directory recursively
for the current user for incomplete information in the database.
=item C<alfilldb ~user/tmp/songs/>
This invocation will scan the /home/user/tmp/songs folder for music
files; will add new entries to the database as well as update the
existing ones.
=item C<alfilldb --file=~/tmp/songs/somefile.ogg --file=~/tmp/songs/otherfile.mp3>
This invocation will just add (or update) information about the files
$(HOME)/tmp/songs/somefile.ogg and $(HOME)/tmp/songs/otherfile.mp3.
=back
=head1 CAVEATS
If the B<--prompt> option is not specified, B<alfilldb> will just prompt for
the title of the song being processed. The title information is asked
only if the ID3 tag or the Vorbis comment doesn't contain the
title. This behavior can be overriden by the --no-prompt option, and
in this case, the entry for the file will not be made, since the song
title is a mandatory field for storing song information in the datbase.
If neither of B<--add-only> or B<--upd-only> are specified, the
default action is to add new entries as well as update existing ones.
If the ID3 tags or Vorbis comments for a file were updated after
entries were made in the AudioLink database, they will not be
reflected in the database. If you want to maintain consistency, it is
advised that you keep the database updated (by using the B<--upd-only>
option) and then update the ID3 tag in the MP3 or the comment in the
Ogg Vorbis file (by running B<alfilldb> with the B<--upd-only> option).
=head1 SEE ALSO
=begin man
L<audiolink(1)>, L<alsearch(1)>
=end man
=begin html
<em><a href="audiolink_doc.html">audiolink(1)</a></em>,
<em><a href="alsearch_doc.html">alsearch(1)</a></em>
=end html
The current version of this man page is available on the AudioLink
website at E<lt>http://audiolink.sourceforge.net/E<gt>.
=head1 BUGS
Report bugs related to the AudioLink software or the man pages to the
audiolink-devel mailing list E<lt>audiolink-devel@lists.sourceforge.netE<gt>.
=head1 AUTHOR
This manual page is written and maintained by Amit Shah E<lt>amitshah@gmx.netE<gt>
=head1 COPYRIGHT
The AudioLink package is Copyright (C) 2003, Amit Shah
E<lt>amitshah@gmx.netE<gt>. All the programs and the documentation that come
as part of AudioLink are licensed by the GNU General Public License v2
(GPLv2).
=cut
|